## Automatically generated incremental diff ## From: linux-2.0.37-pre2 ## To: linux-2.0.37-pre3 ## Robot: $Id: make-incremental-diff,v 1.11 2002/02/20 02:59:33 hpa Exp $ diff -urN linux-2.0.37-pre2/arch/i386/kernel/head.S linux-2.0.37-pre3/arch/i386/kernel/head.S --- linux-2.0.37-pre2/arch/i386/kernel/head.S 2003-08-15 15:04:26.000000000 -0700 +++ linux-2.0.37-pre3/arch/i386/kernel/head.S 2003-08-15 15:04:26.000000000 -0700 @@ -484,7 +484,7 @@ #define upper_seg(type,dpl,base,limit) \ ((base) & 0xff000000) | \ (((base) & 0x00ff0000)>>16) | \ - ((limit) & 0xf0000) | \ + (((limit)>>12) & 0xf0000) | \ ((dpl)<<13) | \ (0x00c09000) | \ ((type)<<8) diff -urN linux-2.0.37-pre2/arch/i386/kernel/hexify.c linux-2.0.37-pre3/arch/i386/kernel/hexify.c --- linux-2.0.37-pre2/arch/i386/kernel/hexify.c 1995-10-02 05:25:10.000000000 -0700 +++ linux-2.0.37-pre3/arch/i386/kernel/hexify.c 2003-08-15 15:04:26.000000000 -0700 @@ -1,7 +1,7 @@ #include -void main() +int main() { int c; int comma=0; @@ -25,7 +25,5 @@ } if(count) printf("\n"); - exit(0); + return 0; } - - diff -urN linux-2.0.37-pre2/CREDITS linux-2.0.37-pre3/CREDITS --- linux-2.0.37-pre2/CREDITS 2003-08-15 15:04:26.000000000 -0700 +++ linux-2.0.37-pre3/CREDITS 2003-08-15 15:04:26.000000000 -0700 @@ -796,11 +796,11 @@ D: for Menuconfig's lxdialog. N: Volker Lendecke -E: lendecke@namu01.Num.Math.Uni-Goettingen.de +E: vl@kki.org D: Kernel smbfs (to mount WfW, NT and OS/2 network drives.) D: NCP filesystem support (to mount NetWare volumes) -S: Innersteweg 11 -S: 37081 Goettingen +S: Von Ossietzky Str. 12 +S: 37085 Goettingen S: Germany N: Kevin Lentin diff -urN linux-2.0.37-pre2/Documentation/Configure.help linux-2.0.37-pre3/Documentation/Configure.help --- linux-2.0.37-pre2/Documentation/Configure.help 2003-08-15 15:04:26.000000000 -0700 +++ linux-2.0.37-pre3/Documentation/Configure.help 2003-08-15 15:04:26.000000000 -0700 @@ -1841,43 +1841,50 @@ CONFIG_SCSI_NCR53C8XX This is the BSD ncr driver adapted to Linux for the NCR53C8XX family of PCI-SCSI controllers. This driver supports parity checking, - tagged command queuing, fast SCSI II transfer up to 10 MB/s with - narrow SCSI devices and 20 MB/s with wide SCSI devices. - Support of Ultra SCSI data transfers with NCR53C860 and NCR53C875 - controllers has been recently added to the driver. + tagged command queuing and fast synchronous data transfers up to 80 + MB/s with wide FAST-40 LVD devices and controllers. + The NCR53C860 and NCR53C875 support FAST-20 transfers. The NCR53C895 + supports FAST-40 transfers with Ultra2 LVD devices. + If you have a SYM53C896 PCI-SCSI controller, you may want to use the new + improved driver available at ftp://ftp.tux.org/pub/roudier/896/. Please read drivers/scsi/README.ncr53c8xx for more information. - Linux/i386 and Linux/Alpha are supported by this driver. - + Synchronous data transfers frequency CONFIG_SCSI_NCR53C8XX_SYNC - SCSI-2 specifications allow SCSI devices to negotiate a synchronous - transfer period of 25 nano-seconds or more. - The transfer period value is 4 times the agreed transfer period. - So, data can be transferred at a 10 MHz frequency, allowing 10 - MB/second throughput with 8 bits SCSI-2 devices and 20 MB/second - with wide16 devices. This frequency can be used safely with - differential devices but may cause problems with singled-ended - devices. - Specify 0 if you want to only use asynchronous data transfers. - Otherwise, specify a value between 5 and 10. Commercial O/Ses - generally use 5 Mhz frequency for synchronous transfers. It is a - reasonable default value. - However, a flawless singled-ended SCSI bus supports 10 MHz data - transfers. Regardless the value chosen in the Linux configuration, - the synchronous period can be changed after boot-up through the - /proc/scsi file system. The generic command is: - echo "setsync #target period" >/proc/scsi/ncr53c8xx/0 - Use a 25 ns period for 10 Mhz synchronous data transfers. - If you don't know what to do now, go with the default. + The SCSI Parallel Interface-2 Standard defines 4 classes of transfer + rates: FAST-5, FAST-10, FAST-20 and FAST-40. The numbers are + respectively the maximum data transfer rates in mega-transfers per + second for each class. For example, a FAST-20 Wide 16 device is able + to transfer data at 20 million 16 bit packets per second for a total + rate of 40 MB/s. + You may specify 0 if you want to only use asynchronous data + transfers. This is the safest and slowest option. Otherwise, specify + a value between 5 and 40, depending on the capability of your SCSI + controller. The higher the number, the faster the data transfer. + Note that 40 should normally be ok since the driver decreases the + value automatically according to the controller's capabilities. + Your answer to this question is ignored for controllers with NVRAM, + since the driver will get this information from the user set-up. It + also can be overridden using a boot setup option, as follows + (example): 'ncr53c8xx=sync:12' will allow the driver to negotiate + for FAST-20 synchronous data transfer (20 mega-transfers per + second). + The normal answer therefore is not to go with the default but to + select the maximum value 40 allowing the driver to use the maximum + value supported by each controller. If this causes problems with + your SCSI devices, you should come back and decrease the value. + There is no safe option other than using good cabling, right + terminations and SCSI conformant devices. Use normal IO CONFIG_SCSI_NCR53C8XX_IOMAPPED - This option allows you to force the driver to use normal IO. - Memory mapped IO has less latency than normal IO and works for most - Intel-based hardware. - Under Linux/Alpha only normal IO is currently supported by the - driver and so, this option has no effect. - The normal answer therefore is N. + If you say Y here, the driver will use normal IO, as opposed to + memory mapped IO. Memory mapped IO has less latency than normal IO + and works for most Intel-based hardware. Under Linux/Alpha only + normal IO is currently supported by the driver and so, this option + has no effect on those systems. + The normal answer therefore is N; try Y only if you encounter SCSI + related problems. Not allow targets to disconnect CONFIG_SCSI_NCR53C8XX_NO_DISCONNECT @@ -1885,70 +1892,61 @@ device of yours to not support properly the target-disconnect feature. In that case, you would say Y here. In general however, to not allow targets to disconnect is not reasonable if there is more - than 1 device on a SCSI bus. The normal answer therefore is N. + than 1 device on a SCSI bus. The normal answer therefore is N. -Enable tagged command queuing -CONFIG_SCSI_NCR53C8XX_TAGGED_QUEUE - This option allows you to enable tagged command queuing support at - Linux start-up. Some SCSI devices do not properly support this - feature. The suggested method is to say N here and to use the - "settags" control command after boot-up to enable this feature: - echo "settags 2 4" >/proc/scsi/ncr53c8xx/0 - asks the driver to use up to 4 concurrent tagged commands for target - 2 of controller 0. - See the file drivers/scsi/README.ncr53c8xx for more information. - WARNING! If you say Y here, then you have to say N to "not allow - targets to disconnect", above. - The safe answer therefore is N. - The normal answer therefore is Y. +Default tagged command queue depth +CONFIG_SCSI_NCR53C8XX_DEFAULT_TAGS + "Tagged command queuing" is a feature of SCSI-2 which improves + performance: the host 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; if you want to disable + this feature, enter 0 or 1 here (it doesn't matter which). + The default value is 8 and should be supported by most hard disks. + This value can be overridden from the boot command line using the + 'tags' option as follows (example): + 'ncr53c8xx=tags:4/t2t3q16/t0u2q10' will set default queue depth to + 4, set queue depth to 16 for target 2 and target 3 on controller 0 + and set queue depth to 10 for target 0 / lun 2 on controller 1. + The normal answer therefore is to go with the default 8 and to use + a boot command line option for devices that need to use a different + command queue depth. + There is no safe option other than using good SCSI devices. Maximum number of queued commands CONFIG_SCSI_NCR53C8XX_MAX_TAGS This option allows you to specify the maximum number of commands - that can be queued to a device, when tagged command queuing is - possible. The default value is 4. Minimum is 2, maximum is 12. The - normal answer therefore is the default one. - -Detect and read serial NVRAM -CONFIG_SCSI_NCR53C8XX_NVRAM_DETECT - Enable support for reading the serial NVRAM data on Symbios and - some Symbios compatible cards, and Tekram DC390W/U/F cards. Useful - for systems with more than one Symbios compatible controller where - at least one has a serial NVRAM, or for a system with a mixture of - Symbios and Tekram cards. Enables setting the boot order of host - adaptors to something other than the default order or "reverse - probe" order. Also enables Symbios and Tekram cards to be - distinguished so CONFIG_SCSI_NCR53C8XX_SYMBIOS_COMPAT may be set in - a system with a mixture of Symbios and Tekram cards so the Symbios - cards can make use of the full range of Symbios features, - differential, led pin, without causing problems for the Tekram - card(s). - (added by Richard Waltham: dormouse@farsrobt.demon.co.uk) - Also enables setting host and targets SCSI features as defined in - the user setup for each host using a serial NVRAM (added by the - maintainer). - The default answer is N, the normal answer should be Y. - Read drivers/scsi/README.ncr53c8xx for more information. + that can be queued to any device, when tagged command queuing is + possible. The default value is 32. Minimum is 2, maximum is 64. + Modern hard disks are able to support 64 tags and even more, but + donnot seem to be faster when more than 32 tags are being used. + So, the normal answer here is to go with the default value 32 unless + you are using very large hard disks with large cache (>= 1 MB) that + are able to take advantage of more than 32 tagged commands. + There is no safe option and the default answer is recommended. Assume boards are SYMBIOS compatible CONFIG_SCSI_NCR53C8XX_SYMBIOS_COMPAT This option allows you to enable some features depending on GPIO - wiring. These General Purpose Input/Output pins can be used for + wiring. These General Purpose Input/Output pins can be used for vendor specific features or implementation of the standard SYMBIOS - features. Genuine SYMBIOS boards use GPIO0 in output for controller - LED and GPIO3 bit as a flag indicating singled-ended/differential - interface. - If all the boards of your system are genuine SYMBIOS boards or use - BIOS and drivers from SYMBIOS, you would want to enable this option. - The driver behaves correctly on my system with this option enabled. - (SDMS 4.0 + Promise SCSI ULTRA 875 rev 0x3 + ASUS SC200 810A rev - 0x12). This option must be set to N if your system has at least one - 53C8XX based SCSI board with a vendor-specific BIOS (example: Tekram - DC-390/U/W/F). If unsure, say N. - However, if all your non Symbios compatible boards have NVRAM, - setting option CONFIG_SCSI_NCR53C8XX_NVRAM_DETECT allows the driver - to distinguish Symbios compatible boards from other ones. So, - you can answer Y if all non Symbios compatible boards have NVRAM. + features. Genuine SYMBIOS controllers use GPIO0 in output for + controller LED and GPIO3 bit as a flag indicating + singled-ended/differential interface. The Tekram DC-390U/F boards + uses a different GPIO wiring. + Your answer to this question is ignored if all your controllers have + NVRAM, since the driver is able to detect the board type from the + NVRAM format. + If all the controllers in your system are genuine SYMBIOS boards or + use BIOS and drivers from SYMBIOS, you would want to say Y here, + otherwise N. N is the safe answer. + +Enable profiling statistics gathering +CONFIG_SCSI_NCR53C8XX_PROFILE + This option allows you to enable profiling information gathering. + These statistics are not very accurate due to the low frequency + of the kernel clock (100 Hz on i386) and have performance impact + on systems that use very fast devices. + The normal answer therefore is N. Always IN2000 SCSI support CONFIG_SCSI_IN2000 diff -urN linux-2.0.37-pre2/drivers/cdrom/sbpcd.c linux-2.0.37-pre3/drivers/cdrom/sbpcd.c --- linux-2.0.37-pre2/drivers/cdrom/sbpcd.c 1996-09-02 05:18:26.000000000 -0700 +++ linux-2.0.37-pre3/drivers/cdrom/sbpcd.c 2003-08-15 15:04:26.000000000 -0700 @@ -4911,14 +4911,16 @@ msg(DBG_000, "sbp_data: beginning to read.\n"); p = D_S[d].sbp_buf + frame * CD_FRAMESIZE; if (sbpro_type==1) OUT(CDo_sel_i_d,1); - if (cmd_type==READ_M2) + if (cmd_type==READ_M2) { if (do_16bit) insw(CDi_data, xa_head_buf, CD_XA_HEAD>>1); else insb(CDi_data, xa_head_buf, CD_XA_HEAD); + } if (do_16bit) insw(CDi_data, p, CD_FRAMESIZE>>1); else insb(CDi_data, p, CD_FRAMESIZE); - if (cmd_type==READ_M2) + if (cmd_type==READ_M2) { if (do_16bit) insw(CDi_data, xa_tail_buf, CD_XA_TAIL>>1); else insb(CDi_data, xa_tail_buf, CD_XA_TAIL); + } D_S[d].sbp_current++; if (sbpro_type==1) OUT(CDo_sel_i_d,0); if (cmd_type==READ_M2) @@ -5502,9 +5504,10 @@ cc_ReadStatus(); i=ResponseStatus(); /* returns orig. status or p_busy_new */ if (famT_drive) i=ResponseStatus(); /* returns orig. status or p_busy_new */ - if (i<0) + if (i<0) { if (i!=-402) msg(DBG_INF,"init: ResponseStatus returns %d.\n",i); + } else { if (st_check) diff -urN linux-2.0.37-pre2/drivers/net/at1700.c linux-2.0.37-pre3/drivers/net/at1700.c --- linux-2.0.37-pre2/drivers/net/at1700.c 1998-06-03 15:17:47.000000000 -0700 +++ linux-2.0.37-pre3/drivers/net/at1700.c 2003-08-15 15:04:26.000000000 -0700 @@ -595,7 +595,6 @@ /* The inverse routine to net_open(). */ static int net_close(struct device *dev) { - struct net_local *lp = (struct net_local *)dev->priv; int ioaddr = dev->base_addr; dev->tbusy = 1; @@ -606,14 +605,6 @@ /* No statistic counters on the chip to update. */ -#if 0 - /* Disable the IRQ on boards where it is feasible. */ - if (lp->jumpered) { - outb(0x00, ioaddr + IOCONFIG1); - free_irq(dev->irq, dev); - } -#endif - /* Power-down the chip. Green, green, green! */ outb(0x00, ioaddr + CONFIG_1); diff -urN linux-2.0.37-pre2/drivers/net/dgrs.c linux-2.0.37-pre3/drivers/net/dgrs.c --- linux-2.0.37-pre2/drivers/net/dgrs.c 1998-07-13 13:47:31.000000000 -0700 +++ linux-2.0.37-pre3/drivers/net/dgrs.c 2003-08-15 15:04:26.000000000 -0700 @@ -1254,10 +1254,11 @@ ) { DGRS_PRIV *priv; - int i; #ifdef MODULE { + int i; + /* Allocate and fill new device structure. */ int dev_size = sizeof(struct device) + sizeof(DGRS_PRIV); diff -urN linux-2.0.37-pre2/drivers/net/eth16i.c linux-2.0.37-pre3/drivers/net/eth16i.c --- linux-2.0.37-pre2/drivers/net/eth16i.c 1998-11-15 10:33:03.000000000 -0800 +++ linux-2.0.37-pre3/drivers/net/eth16i.c 2003-08-15 15:04:26.000000000 -0700 @@ -886,7 +886,7 @@ creg[0] &= 0x0F; /* Mask collision cnr */ creg[2] &= 0x7F; /* Mask DCLEN bit */ -#ifdef 0 +#if 0 /* This was removed because the card was sometimes left to state from which it couldn't be find anymore. If there is need diff -urN linux-2.0.37-pre2/drivers/net/lance.c linux-2.0.37-pre3/drivers/net/lance.c --- linux-2.0.37-pre2/drivers/net/lance.c 1998-11-15 10:33:03.000000000 -0800 +++ linux-2.0.37-pre3/drivers/net/lance.c 2003-08-15 15:04:26.000000000 -0700 @@ -334,14 +334,17 @@ dev->base_addr = io[this_dev]; dev->dma = dma[this_dev]; dev->init = lance_probe; +#if NO_AUTOPROBE_MODULE if (io[this_dev] == 0) { if (this_dev != 0) break; /* only complain once */ printk(KERN_NOTICE "lance.c: Module autoprobing not allowed. Append \"io=0xNNN\" value(s).\n"); return -EPERM; } +#endif if (register_netdev(dev) != 0) { - printk(KERN_WARNING "lance.c: No PCnet/LANCE card found (i/o = 0x%x).\n", io[this_dev]); - if (found != 0) return 0; /* Got at least one. */ + if (found != 0) + return 0; /* Got at least one. */ + printk(KERN_WARNING "lance.c: No PCnet/LANCE card found\n"); return -ENXIO; } found++; @@ -350,8 +353,7 @@ return 0; } -void -cleanup_module(void) +void cleanup_module(void) { int this_dev; @@ -390,15 +392,21 @@ unsigned short pci_command; if (pcibios_find_device (PCI_VENDOR_ID_AMD, - PCI_DEVICE_ID_AMD_LANCE, pci_index, - &pci_bus, &pci_device_fn) != 0) + PCI_DEVICE_ID_AMD_LANCE, pci_index, + &pci_bus, &pci_device_fn) != 0) break; pcibios_read_config_byte(pci_bus, pci_device_fn, - PCI_INTERRUPT_LINE, &pci_irq_line); + PCI_INTERRUPT_LINE, &pci_irq_line); pcibios_read_config_dword(pci_bus, pci_device_fn, - PCI_BASE_ADDRESS_0, &pci_ioaddr); + PCI_BASE_ADDRESS_0, &pci_ioaddr); /* Remove I/O space marker in bit 0. */ pci_ioaddr &= ~3; + + /* Avoid already found cards from previous calls + */ + if (check_region(pci_ioaddr, LANCE_TOTAL_SIZE)) + continue; + /* PCI Spec 2.1 states that it is either the driver or PCI card's * responsibility to set the PCI Master Enable Bit if needed. * (From Mark Stockton ) diff -urN linux-2.0.37-pre2/drivers/net/ni52.c linux-2.0.37-pre3/drivers/net/ni52.c --- linux-2.0.37-pre2/drivers/net/ni52.c 1998-07-13 13:47:31.000000000 -0700 +++ linux-2.0.37-pre3/drivers/net/ni52.c 2003-08-15 15:04:26.000000000 -0700 @@ -363,10 +363,11 @@ #endif int base_addr = dev->base_addr; - if (base_addr > 0x1ff) /* Check a single specified location. */ + if (base_addr > 0x1ff) { /* Check a single specified location. */ if( (inb(base_addr+NI52_MAGIC1) == NI52_MAGICVAL1) && (inb(base_addr+NI52_MAGIC2) == NI52_MAGICVAL2)) return ni52_probe1(dev, base_addr); + } else if (base_addr > 0) /* Don't probe at all. */ return ENXIO; diff -urN linux-2.0.37-pre2/drivers/net/pi2.c linux-2.0.37-pre3/drivers/net/pi2.c --- linux-2.0.37-pre2/drivers/net/pi2.c 1998-07-13 13:47:31.000000000 -0700 +++ linux-2.0.37-pre3/drivers/net/pi2.c 2003-08-15 15:04:26.000000000 -0700 @@ -1452,7 +1452,7 @@ static int pi_open(struct device *dev) { unsigned long flags; - static first_time = 1; + static int first_time = 1; struct pi_local *lp = (struct pi_local *) dev->priv; diff -urN linux-2.0.37-pre2/drivers/net/ppp.c linux-2.0.37-pre3/drivers/net/ppp.c --- linux-2.0.37-pre2/drivers/net/ppp.c 1998-06-03 15:17:47.000000000 -0700 +++ linux-2.0.37-pre3/drivers/net/ppp.c 2003-08-15 15:04:26.000000000 -0700 @@ -3155,7 +3155,7 @@ ppp_stats.tx_heartbeat_errors = 0; if (ppp->flags & SC_DEBUG) - printk (KERN_INFO "ppp_dev_stats called"); + printk (KERN_INFO "ppp_dev_stats called\n"); return &ppp_stats; } diff -urN linux-2.0.37-pre2/drivers/net/pt.c linux-2.0.37-pre3/drivers/net/pt.c --- linux-2.0.37-pre2/drivers/net/pt.c 1998-07-13 13:47:31.000000000 -0700 +++ linux-2.0.37-pre3/drivers/net/pt.c 2003-08-15 15:04:26.000000000 -0700 @@ -909,7 +909,7 @@ { unsigned long flags; struct pt_local *lp = dev->priv; - static first_time = 1; + static int first_time = 1; if (dev->base_addr & CHANA) { diff -urN linux-2.0.37-pre2/drivers/net/rcpci45.c linux-2.0.37-pre3/drivers/net/rcpci45.c --- linux-2.0.37-pre2/drivers/net/rcpci45.c 1998-11-15 10:33:03.000000000 -0800 +++ linux-2.0.37-pre3/drivers/net/rcpci45.c 2003-08-15 15:04:26.000000000 -0700 @@ -46,9 +46,6 @@ #include #include #include - -static char kernel_version [] = UTS_RELEASE; - #include #include #include @@ -170,7 +167,7 @@ #ifdef MODULE int init_module(void) #else -int rcpci_probe(struct netdevice *dev) +int rcpci_probe(struct device *dev) #endif { int cards_found; diff -urN linux-2.0.37-pre2/drivers/net/sdla.c linux-2.0.37-pre3/drivers/net/sdla.c --- linux-2.0.37-pre2/drivers/net/sdla.c 1998-06-03 15:17:47.000000000 -0700 +++ linux-2.0.37-pre3/drivers/net/sdla.c 2003-08-15 15:04:26.000000000 -0700 @@ -452,7 +452,7 @@ save_flags(pflags); cli(); SDLA_WINDOW(dev, window); - waiting = ((volatile)(cmd_buf->opp_flag)); + waiting = ((volatile int)(cmd_buf->opp_flag)); restore_flags(pflags); } } @@ -566,11 +566,12 @@ flp->dlci[i] = -*(short *)(master->dev_addr); master->mtu = slave->mtu; - if (slave->start) + if (slave->start) { if (flp->config.station == FRAD_STATION_CPE) sdla_reconfig(slave); else sdla_cmd(slave, SDLA_ADD_DLCI, 0, 0, master->dev_addr, sizeof(short), NULL, NULL); + } return(0); } @@ -594,11 +595,12 @@ MOD_DEC_USE_COUNT; - if (slave->start) + if (slave->start) { if (flp->config.station == FRAD_STATION_CPE) sdla_reconfig(slave); else sdla_cmd(slave, SDLA_DELETE_DLCI, 0, 0, master->dev_addr, sizeof(short), NULL, NULL); + } return(0); } @@ -623,13 +625,14 @@ ret = SDLA_RET_OK; len = sizeof(struct dlci_conf); - if (slave->start) + if (slave->start) { if (get) ret = sdla_cmd(slave, SDLA_READ_DLCI_CONFIGURATION, abs(flp->dlci[i]), 0, NULL, 0, &dlp->config, &len); else ret = sdla_cmd(slave, SDLA_SET_DLCI_CONFIGURATION, abs(flp->dlci[i]), 0, &dlp->config, sizeof(struct dlci_conf) - 4 * sizeof(short), NULL, NULL); + } return(ret == SDLA_RET_OK ? 0 : -EIO); } diff -urN linux-2.0.37-pre2/drivers/net/Space.c linux-2.0.37-pre3/drivers/net/Space.c --- linux-2.0.37-pre2/drivers/net/Space.c 1998-11-15 10:33:02.000000000 -0800 +++ linux-2.0.37-pre3/drivers/net/Space.c 2003-08-15 15:04:26.000000000 -0700 @@ -52,6 +52,7 @@ extern int express_probe(struct device *); extern int eepro_probe(struct device *); extern int el3_probe(struct device *); +extern int tc515_probe(struct device *); extern int at1500_probe(struct device *); extern int at1700_probe(struct device *); extern int fmv18x_probe(struct device *); diff -urN linux-2.0.37-pre2/drivers/pci/pci.c linux-2.0.37-pre3/drivers/pci/pci.c --- linux-2.0.37-pre2/drivers/pci/pci.c 2003-08-15 15:04:26.000000000 -0700 +++ linux-2.0.37-pre3/drivers/pci/pci.c 2003-08-15 15:04:26.000000000 -0700 @@ -146,7 +146,11 @@ DEVICE( MATROX, MATROX_MYS, "Mystique"), DEVICE( MATROX, MATROX_MIL_2, "Millennium II"), DEVICE( MATROX, MATROX_MIL_2_AGP,"Millennium II AGP"), + DEVICE( MATROX, MATROX_G200_PCI,"Matrox G200 PCI"), + DEVICE( MATROX, MATROX_G200_AGP,"Matrox G200 AGP"), DEVICE( MATROX, MATROX_MGA_IMP, "MGA Impression"), + DEVICE( MATROX, MATROX_G100_MM, "Matrox G100 multi monitor"), + DEVICE( MATROX, MATROX_G100_AGP,"Matrox G100 AGP"), DEVICE( CT, CT_65545, "65545"), DEVICE( CT, CT_65548, "65548"), DEVICE( CT, CT_65550, "65550"), @@ -332,6 +336,7 @@ DEVICE( VIA, VIA_82C586_0, "VT 82C586 Apollo ISA"), DEVICE( VIA, VIA_82C595, "VT 82C595 Apollo VP2"), DEVICE( VIA, VIA_82C597_0, "VT 82C597 Apollo VP3"), + DEVICE( VIA, VIA_82C598_0, "VT 82C598 Apollo MVP3"), DEVICE( VIA, VIA_82C926, "VT 82C926 Amazon"), DEVICE( VIA, VIA_82C416, "VT 82C416MV"), DEVICE( VIA, VIA_82C595_97, "VT 82C595 Apollo VP2/97"), @@ -339,6 +344,7 @@ DEVICE( VIA, VIA_82C586_3, "VT 82C586B Apollo ACPI"), DEVICE( VIA, VIA_86C100A, "VT 86C100A"), DEVICE( VIA, VIA_82C597_1, "VT 82C597 Apollo VP3 AGP"), + DEVICE( VIA, VIA_82C598_1, "VT 82C598 Apollo MVP3 AGP"), DEVICE( SMC2, SMC2_1211TX, "1211 TX"), DEVICE( VORTEX, VORTEX_GDT60x0, "GDT 60x0"), DEVICE( VORTEX, VORTEX_GDT6000B,"GDT 6000b"), diff -urN linux-2.0.37-pre2/drivers/scsi/aha1542.c linux-2.0.37-pre3/drivers/scsi/aha1542.c --- linux-2.0.37-pre2/drivers/scsi/aha1542.c 1998-11-15 10:33:07.000000000 -0800 +++ linux-2.0.37-pre3/drivers/scsi/aha1542.c 2003-08-15 15:04:26.000000000 -0700 @@ -120,8 +120,8 @@ #define aha1542_intr_reset(base) outb(IRST, CONTROL(base)) #define WAIT(port, mask, allof, noneof) \ - { register WAITbits; \ - register WAITtimeout = WAITnexttimeout; \ + { register int WAITbits; \ + register int WAITtimeout = WAITnexttimeout; \ while (1) { \ WAITbits = inb(port) & (mask); \ if ((WAITbits & (allof)) == (allof) && ((WAITbits & (noneof)) == 0)) \ @@ -133,8 +133,8 @@ /* Similar to WAIT, except we use the udelay call to regulate the amount of time we wait. */ #define WAITd(port, mask, allof, noneof, timeout) \ - { register WAITbits; \ - register WAITtimeout = timeout; \ + { register int WAITbits; \ + register int WAITtimeout = timeout; \ while (1) { \ WAITbits = inb(port) & (mask); \ if ((WAITbits & (allof)) == (allof) && ((WAITbits & (noneof)) == 0)) \ diff -urN linux-2.0.37-pre2/drivers/scsi/aic7xxx.c linux-2.0.37-pre3/drivers/scsi/aic7xxx.c --- linux-2.0.37-pre2/drivers/scsi/aic7xxx.c 2003-08-15 15:04:26.000000000 -0700 +++ linux-2.0.37-pre3/drivers/scsi/aic7xxx.c 2003-08-15 15:04:26.000000000 -0700 @@ -354,7 +354,7 @@ 0, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; -#define AIC7XXX_C_VERSION "5.1.5" +#define AIC7XXX_C_VERSION "5.1.6" #define NUMBER(arr) (sizeof(arr) / sizeof(arr[0])) #define MIN(a,b) (((a) < (b)) ? (a) : (b)) @@ -1065,8 +1065,7 @@ #define DEVICE_RESET_DELAY 0x04 #define DEVICE_PRINT_SDTR 0x08 #define DEVICE_PRINT_WDTR 0x10 -#define DEVICE_SUCCESS 0x20 -#define DEVICE_TAGGED_SUCCESS 0x40 +#define DEVICE_WAS_BUSY 0x20 #define DEVICE_SCANNED 0x80 volatile unsigned char dev_flags[MAX_TARGETS]; volatile unsigned char dev_active_cmds[MAX_TARGETS]; @@ -2877,6 +2876,7 @@ { char *buffer; + p->dev_flags[tindex] |= DEVICE_PRESENT; if(cmd->use_sg) { struct scatterlist *sg; @@ -2918,23 +2918,34 @@ p->needsdtr_copy |= (1<flags & AHC_SEEPROM_FOUND) + { p->transinfo[tindex].goal_period = p->transinfo[tindex].user_period; - else if (p->features & AHC_ULTRA2) - p->transinfo[tindex].goal_period = - aic7xxx_syncrates[AHC_SYNCRATE_ULTRA2].period; - else if (p->features & AHC_ULTRA) - p->transinfo[tindex].goal_period = - aic7xxx_syncrates[AHC_SYNCRATE_ULTRA].period; - else - p->transinfo[tindex].goal_period = - aic7xxx_syncrates[AHC_SYNCRATE_FAST].period; - - if (p->features & AHC_ULTRA2) - p->transinfo[tindex].goal_offset = MAX_OFFSET_ULTRA2; - else if (p->transinfo[tindex].goal_width == MSG_EXT_WDTR_BUS_16_BIT) - p->transinfo[tindex].goal_offset = MAX_OFFSET_16BIT; + p->transinfo[tindex].goal_offset = p->transinfo[tindex].user_offset; + } else - p->transinfo[tindex].goal_offset = MAX_OFFSET_8BIT; + { + if (p->features & AHC_ULTRA2) + { + p->transinfo[tindex].goal_period = + aic7xxx_syncrates[AHC_SYNCRATE_ULTRA2].period; + } + else if (p->features & AHC_ULTRA) + { + p->transinfo[tindex].goal_period = + aic7xxx_syncrates[AHC_SYNCRATE_ULTRA].period; + } + else + { + p->transinfo[tindex].goal_period = + aic7xxx_syncrates[AHC_SYNCRATE_FAST].period; + } + if (p->features & AHC_ULTRA2) + p->transinfo[tindex].goal_offset = MAX_OFFSET_ULTRA2; + else if (p->transinfo[tindex].goal_width == MSG_EXT_WDTR_BUS_16_BIT) + p->transinfo[tindex].goal_offset = MAX_OFFSET_16BIT; + else + p->transinfo[tindex].goal_offset = MAX_OFFSET_8BIT; + } } else { @@ -3417,19 +3428,6 @@ if (aic7xxx_verbose & (VERBOSE_ABORT_PROCESS | VERBOSE_RESET_PROCESS)) printk(INFO_LEAD "Cleaning up status information " "and delayed_scbs.\n", p->host_no, channel, i, lun); - if ( !(p->dev_flags[i] & DEVICE_TAGGED_SUCCESS) && - (p->dev_active_cmds[i]) && - (p->tagenable & (0x01 << i)) ) - { - printk(INFO_LEAD "Device appears to be choking on tagged commands.\n", - p->host_no, channel, i, lun); - printk(INFO_LEAD "Will use untagged I/O instead.\n", p->host_no, - channel, i, lun); - p->dev_max_queue_depth[i] = 1; - p->dev_temp_queue_depth[i] = 1; - p->tagenable &= ~(0x01 << i); - p->orderedtag &= ~(0x01 << i); - } p->dev_flags[i] &= ~BUS_DEVICE_RESET_PENDING; if ( tag == SCB_LIST_NULL ) { @@ -4010,7 +4008,7 @@ } if ( (p->dev_active_cmds[tindex] >= p->dev_temp_queue_depth[tindex]) || - (p->dev_flags[tindex] & DEVICE_RESET_DELAY) ) + (p->dev_flags[tindex] & (DEVICE_RESET_DELAY|DEVICE_WAS_BUSY)) ) { scbq_insert_tail(&p->delayed_scbs[tindex], scb); } @@ -4140,7 +4138,7 @@ time_after_eq(jiffies, p->dev_expires[i]) ) { p->dev_timer_active &= ~(0x01 << i); - p->dev_flags[i] &= ~DEVICE_RESET_DELAY; + p->dev_flags[i] &= ~(DEVICE_RESET_DELAY|DEVICE_WAS_BUSY); p->dev_temp_queue_depth[i] = p->dev_max_queue_depth[i]; j = 0; while ( ((scb = scbq_remove_head(&p->delayed_scbs[i])) != NULL) && @@ -4455,8 +4453,7 @@ (scb->tag_action) && !(scb->flags & SCB_MSGOUT_BITS) ) { - if ((scb->tag_action == MSG_ORDERED_Q_TAG) && - (p->dev_flags[tindex] & DEVICE_TAGGED_SUCCESS)) + if (scb->tag_action == MSG_ORDERED_Q_TAG) { /* * OK...the device seems able to accept tagged commands, but @@ -4477,8 +4474,7 @@ aic_outb(p, MSG_IDENTIFYFLAG, MSG_OUT); aic_outb(p, aic_inb(p, SCSISIGI) | ATNO, SCSISIGO); } - else if ( (scb->tag_action == MSG_SIMPLE_Q_TAG) && - !(p->dev_flags[tindex] & DEVICE_TAGGED_SUCCESS) ) + else if (scb->tag_action == MSG_SIMPLE_Q_TAG) { unsigned char i, reset = 0; struct aic7xxx_scb *scbp; @@ -4898,11 +4894,11 @@ p->dev_timer_active |= (0x01 << tindex); if ( p->dev_active_cmds[tindex] ) { - p->dev_expires[tindex] = jiffies + (HZ * 2); + p->dev_expires[tindex] = jiffies + HZ; } else { - p->dev_expires[tindex] = jiffies + (HZ / 2); + p->dev_expires[tindex] = jiffies + (HZ / 10); } if ( !(p->dev_timer_active & (0x01 << p->scsi_id)) ) { @@ -4957,6 +4953,10 @@ p->dev_last_queue_full[tindex] = 0; p->dev_last_queue_full_count[tindex] = 0; } + else + { + p->dev_flags[tindex] |= DEVICE_WAS_BUSY; + } } break; } @@ -5281,7 +5281,8 @@ * have a device ask for a higher speed then we want to give it * in that case */ - if (!(p->sdtr_pending & target_mask)) + if ( (scb->flags & (SCB_MSGOUT_SENT|SCB_MSGOUT_SDTR)) != + (SCB_MSGOUT_SENT|SCB_MSGOUT_SDTR) ) { if (!(p->dev_flags[tindex] & DEVICE_SCANNED)) { @@ -5299,54 +5300,36 @@ p->transinfo[tindex].user_offset; p->needsdtr_copy |= target_mask; } + if ( !p->transinfo[tindex].goal_offset ) + period = 255; if ( p->transinfo[tindex].goal_period > period ) period = p->transinfo[tindex].goal_period; - if ( p->transinfo[tindex].goal_offset < offset ) - saved_offset = offset = p->transinfo[tindex].goal_offset; } -#ifdef AIC7XXX_VERBOSE_DEBUGGING - if (aic7xxx_verbose > 0xffff) - { - printk(INFO_LEAD "Finished receipt of SDTR, parsing %d/%d\n", - p->host_no, CTL_OF_SCB(scb), period, offset); - syncrate = aic7xxx_find_syncrate(p, &period, maxsync); - printk(INFO_LEAD "After find_syncrate() %d/%d\n", - p->host_no, CTL_OF_SCB(scb), period, offset); - aic7xxx_validate_offset(p, syncrate, &offset, - target_scsirate & WIDEXFER); - printk(INFO_LEAD "After validate_offset() %d/%d\n", - p->host_no, CTL_OF_SCB(scb), period, offset); - aic7xxx_set_syncrate(p, syncrate, target, channel, period, - offset, AHC_TRANS_ACTIVE|AHC_TRANS_CUR); - printk(INFO_LEAD "Final values of Period/Offset as set: %d/%d\n", - p->host_no, CTL_OF_SCB(scb), period, offset); - } - else - { - syncrate = aic7xxx_find_syncrate(p, &period, maxsync); - aic7xxx_validate_offset(p, syncrate, &offset, - target_scsirate & WIDEXFER); - aic7xxx_set_syncrate(p, syncrate, target, channel, period, - offset, AHC_TRANS_ACTIVE|AHC_TRANS_CUR); - } -#else syncrate = aic7xxx_find_syncrate(p, &period, maxsync); aic7xxx_validate_offset(p, syncrate, &offset, target_scsirate & WIDEXFER); aic7xxx_set_syncrate(p, syncrate, target, channel, period, offset, AHC_TRANS_ACTIVE|AHC_TRANS_CUR); -#endif - if (offset == 0) + /* + * Did we drop to async? If so, are we sending a reply? If we are, + * then we have to make sure that the reply value reflects the proper + * settings so we need to set the goal values according to what + * we need to send. + */ + if ( (offset == 0) || (offset != saved_offset) || + ((scb->flags & (SCB_MSGOUT_SENT|SCB_MSGOUT_SDTR)) != + (SCB_MSGOUT_SENT|SCB_MSGOUT_SDTR) ) ) { - /* - * Uhh ohh, things fell through to async....update the goal - * items and the needsdtr_copy to reflect this... - */ aic7xxx_set_syncrate(p, syncrate, target, channel, period, - offset, AHC_TRANS_GOAL|AHC_TRANS_QUITE); + offset, AHC_TRANS_GOAL|AHC_TRANS_QUITE); + if ( offset == 0 ) + { + p->needsdtr_copy &= ~target_mask; + } } + /* * Did we start this, if not, or if we went to low and had to * go async, then send an SDTR back to the target @@ -5437,7 +5420,6 @@ p->transinfo[tindex].user_width; p->needwdtr_copy |= target_mask; p->needsdtr_copy |= target_mask; - p->dev_flags[tindex] |= DEVICE_SCANNED; } switch(bus_width) { @@ -6266,12 +6248,6 @@ aic7xxx_calculate_residual(p, scb); } cmd->result |= (aic7xxx_error(cmd) << 16); - if (scb->tag_action) - p->dev_flags[TARGET_INDEX(cmd)] |= - DEVICE_TAGGED_SUCCESS | DEVICE_SUCCESS | DEVICE_PRESENT; - else - p->dev_flags[TARGET_INDEX(cmd)] |= - DEVICE_SUCCESS | DEVICE_PRESENT; aic7xxx_done(p, scb); break; } @@ -10131,8 +10107,6 @@ "message buffer\n", p->host_no, CTL_OF_SCB(scb)); scb->flags |= SCB_RESET | SCB_DEVICE_RESET; aic7xxx_error(scb->cmd) = DID_RESET; - p->dev_flags[TARGET_INDEX(scb->cmd)] &= - ~DEVICE_SUCCESS; p->dev_flags[TARGET_INDEX(scb->cmd)] |= BUS_DEVICE_RESET_PENDING; /* Send the abort message to the active SCB. */ @@ -10153,8 +10127,6 @@ "in use\n", p->host_no, CTL_OF_SCB(scb)); scb->flags |= SCB_RESET | SCB_DEVICE_RESET; aic7xxx_error(scb->cmd) = DID_RESET; - p->dev_flags[TARGET_INDEX(scb->cmd)] &= - ~DEVICE_SUCCESS; p->dev_flags[TARGET_INDEX(scb->cmd)] |= BUS_DEVICE_RESET_PENDING; return(SCSI_RESET_ERROR); @@ -10182,7 +10154,6 @@ */ scb->hscb->control |= MK_MESSAGE; scb->flags |= SCB_RESET | SCB_DEVICE_RESET; - p->dev_flags[TARGET_INDEX(scb->cmd)] &= ~DEVICE_SUCCESS; p->dev_flags[TARGET_INDEX(scb->cmd)] |= BUS_DEVICE_RESET_PENDING; if (hscb_index != SCB_LIST_NULL) diff -urN linux-2.0.37-pre2/drivers/scsi/ChangeLog.ncr53c8xx linux-2.0.37-pre3/drivers/scsi/ChangeLog.ncr53c8xx --- linux-2.0.37-pre2/drivers/scsi/ChangeLog.ncr53c8xx 1998-07-13 13:47:32.000000000 -0700 +++ linux-2.0.37-pre3/drivers/scsi/ChangeLog.ncr53c8xx 2003-08-15 15:04:26.000000000 -0700 @@ -1,5 +1,265 @@ -Fri Jan 2 18:00 1998 Gerard Roudier (groudier@club-internet.fr) - * Revision 2.5f +Sun Dec 13 18:00 1998 Gerard Roudier (groudier@club-internet.fr) + * revision 3.1e + - Same work-around as for the 53c876 rev <= 0x15 for 53c896 rev 1: + Disable overlapped arbitration. This will not make difference + since the chip has on-chip RAM. + +Thu Nov 26 22:00 1998 Gerard Roudier (groudier@club-internet.fr) + * revision 3.1d + - The SISL RAID change requires now remap_pci_mem() stuff to be + compiled for __i386__ when normal IOs are used. + - Minor spelling fixes in doc files. + +Sat Nov 21 18:00 1998 Gerard Roudier (groudier@club-internet.fr) + * revision 3.1c + - Ignore chips that are driven by SISL RAID (DAC 960). + Change sent by Leonard Zubkoff and slightly reworked. + - Still a buglet in the tags initial settings that needed to be fixed. + It was not possible to disable TGQ at system startup for devices + that claim TGQ support. The driver used at least 2 for the queue + depth but did'nt keep track of user settings for tags depth lower + than 2. + +Wed Nov 11 10:00 1998 Gerard Roudier (groudier@club-internet.fr) + * revision 3.1b + - The driver was unhappy when configured with default_tags > MAX_TAGS + Hopefully doubly-fixed. + - Update the Configure.help driver section that speaks of TAGS. + +Wed Oct 21 21:00 1998 Gerard Roudier (groudier@club-internet.fr) + * revision 3.1a + - Changes from Eddie Dost for Sparc and Alpha: + ioremap/iounmap support for Sparc. + pcivtophys changed to bus_dvma_to_phys. + - Add the 53c876 description to the chip table. This is only usefull + for printing the right name of the controller. + - DEL-441 Item 2 work-around for the 53c876 rev <= 5 (0x15). + - Add additionnal checking of INQUIRY data: + Check INQUIRY data received length is at least 7. Byte 7 of + inquiry data contains device features bits and the driver might + be confused by garbage. Also check peripheral qualifier. + - Cleanup of the SCSI tasks management: + Remove the special case for 32 tags. Now the driver only uses the + scheme that allows up to 64 tags per LUN. + Merge some code from the 896 driver. + Use a 1,3,5,...MAXTAGS*2+1 tag numbering. Previous driver could + use any tag number from 1 to 253 and some non conformant devices + might have problems with large tag numbers. + - 'no_sync' changed to 'no_disc' in the README file. This is an old + and trivial mistake that seems to demonstrate the README file is + not often read. :) + +Sun Oct 4 14:00 1998 Gerard Roudier (groudier@club-internet.fr) + * revision 3.0i + - Cosmetic changes for sparc (but not for the driver) that needs + __irq_itoa() to be used for printed IRQ value to be understandable. + - Some problems with the driver that didn't occur using driver 2.5f + were due to a SCSI selection problem triggered by a clearly + documented feature that in fact seems not to work: (53C8XX chips + are claimed by the manuals to be able to execute SCSI scripts just + after abitration while the SCSI core is performing SCSI selection). + This optimization is broken and has been removed. + - Some broken scsi devices are confused when a negotiation is started + on a LUN that does not correspond to a real device. According to + SCSI specs, this is a device firmware bug. This has been worked + around by only starting negotiation if the LUN has previously be + used for at least 1 successful SCSI command. + - The 'last message sent' printed out on M_REJECT message reception + was read from the SFBR i/o register after the previous message had + been sent. + This was not correct and affects all previous driver versions and + the original FreeBSD one as well. The SCSI scripts has been fixed + so that it now provides the right information to the C code. + +Sat Jul 18 13:00 1998 Gerard Roudier (groudier@club-internet.fr) + * revision 3.0g + - Preliminary fixes for Big Endian (sent by Eddie C. Dost). + Big Endian architectures should work again with the driver. + Eddie's patch has been partially applied since current 2.1.109 + does not have all the Sparc changes of the vger tree. + - Use of BITS_PER_LONG instead of (~0UL == 0xffffffffUL) has fixed + the problem observed when the driver was compiled using EGCS or + PGCC. + +Mon Jul 13 20:00 1998 Gerard Roudier (groudier@club-internet.fr) + * revision 3.0f + - Some spelling fixes. + - linux/config.h misplaced in ncr53c8xx.h + - MODULE_PARM stuff added for linux 2.1. + - check INQUIRY response data format is exactly 2. + - use BITS_PER_LONG if defined. + +Sun Jun 28 12:00 1998 Gerard Roudier (groudier@club-internet.fr) + * revision 3.0e + - Some cleanup, spelling fixes, version checks, documentations + changes, etc ... + +Sat Jun 20 20:00 1998 Gerard Roudier (groudier@club-internet.fr) + * revision 3.0c + - Add a boot setup option that allows to set up device queue depths + at boot-up. This option is very usefull since Linux does not + allow to change scsi device queue depth once the system has been + booted up. + +Sun Jun 15 23:00 1998 Gerard Roudier (groudier@club-internet.fr) + * revision 3.0a + - Support for up to 64 TAGS per LUN. + - Rewrite the TARGET vs LUN capabilities management. + CmdQueue is now handled as a LUN capability as it shall be. + This also fixes a bug triggered when disabling tagged command + queuing for a device that had this feature enabled. + - Remove the ncr_opennings() stuff that was useless under Linux + and hard to understand to me. + - Add "setverbose" procfs driver command. It allows to tune + verbose level after boot-up. Setting this level to zero, for + example avoid flooding the syslog file. + - Add KERN_XXX to some printk's. + +Tue Jun 10 23:00 1998 Gerard Roudier (groudier@club-internet.fr) + * revision 3.0 + - Linux config changes for 2.0.34: + Remove NVRAM detection config option. This option is now enabled + by default but can be disabled by editing the driver header file. + Add a PROFILE config option. + - Update Configure.help + - Add calls to new function mdelay() for milli-seconds delay if + kernel version >= 2.1.105. + - Replace all printf(s) by printk(s). After all, the ncr53c8xx is + a driver for Linux. + - Perform auto-sense on COMMAND TERMINATED. Not sure it is usefull. + - Some other minor changes. + +Tue Jun 4 23:00 1998 Gerard Roudier (groudier@club-internet.fr) + * revision 2.6n + - Code cleanup and simplification: + Remove kernel 1.2.X and 1.3.X support. + Remove the _old_ target capabilities table. + Remove the error recovery code that have'nt been really usefull. + Use a single alignment boundary (CACHE_LINE_SIZE) for data + structures. + - Several aggressive SCRIPTS optimizations and changes: + Reselect SCRIPTS code rewritten. + Support for selection/reselection without ATN. + And some others. + - Miscallaneous changes in the C code: + Count actual number of CCB queued to the controller (future use). + Lots of other minor changes. + +Wed May 13 20:00 1998 Gerard Roudier (groudier@club-internet.fr) + * revision 2.6m + - Problem of missed SCSI bus reset with the 53C895 fixed by + Richard Waltham. The 53C895 needs about 650 us for the bus + mode to settle. Delays used while resetting the controller + and the bus have been adjusted. Thanks Richard! + - Some simplification for 64 bit arch done ccb address testing. + - Add a check of the MSG_OUT phase after Selection with ATN. + - The new tagged queue stuff seems ok, so some informationnal + message have been conditionned by verbose >= 3. + - Donnot reset if a SBMC interrupt reports the same bus mode. + - Print out the whole driver set-up. Some options were missing and + the print statement was misplaced for modules. + - Ignore a SCSI parity interrupt if the chip is not connected to + the SCSI bus. + +Sat May 1 16:00 1998 Gerard Roudier (groudier@club-internet.fr) + * revision 2.6l + - Add CCB done queue support for Alpha and perhaps some other + architectures. + - Add some barriers to enforce memory ordering for x86 and + Alpha architectures. + - Fix something that looks like an old bug in the nego SIR + interrupt code in case of negotiation failure. + +Sat Apr 25 21:00 1998 Gerard Roudier (groudier@club-internet.fr) + * revision 2.6k + - Remove all accesses to the on-chip RAM from the C code: + Use SCRIPTS to load the on-chip RAM. + Use SCRIPTS to repair the start queue on selection timeout. + Use the copy of script in main memory to calculate the chip + context on phase mismatch. + - The above allows now to use the on-chip RAM without requiring + to get access to the on-chip RAM from the C code. This makes + on-chip RAM useable for linux-1.2.13 and for Linux-Alpha for + instance. + - Some simplifications and cleanups in the SCRIPTS and C code. + - Buglet fixed in parity error recovery SCRIPTS (never tested). + - Minor updates in README.ncr53c8xx. + +Wed Apr 15 21:00 1998 Gerard Roudier (groudier@club-internet.fr) + * revision 2.6j + - Incorporate changes from linux-2.1.95 ncr53c8xx driver version. + - Add SMP support for linux-2.1.95 and above. + - Fix a bug when QUEUE FULL is returned and no commands are + disconnected. This happens with Atlas I / L912 and may happen + with Atlas II / LXY4. + - Nail another one on CHECK condition when requeuing the command + for auto-sense. + - Call scsi_done() for all completed commands after interrupt + handling. + - Increase the done queue to 24 entries. + +Sat Apr 4 20:00 1998 Gerard Roudier (groudier@club-internet.fr) + * revision 2.6i + - CTEST0 is used by the 53C885 for Power Management and + priority setting between the 2 functions. + Use SDID instead as actual target number. Just have had to + overwrite it with SSID on reselection. + - Split DATA_IN and DATA_OUT scripts into 2 sub-scripts. + 64 segments are moved from on-chip RAM scripts. + If more segments, a script in main memory is used for the + additionnal segments. + - Since the SCRIPTS processor continues SCRIPTS execution after + having won arbitration, do some stuff prior to testing any SCSI + phase on reselection. This should have the vertue to process + scripts in parallel with the SCSI core performing selection. + - Increase the done queue to 12 entries. + +Sun Mar 29 12:00 1998 Gerard Roudier (groudier@club-internet.fr) + * revision 2.6h + - Some fixes. + +Tue Mar 26 23:00 1998 Gerard Roudier (groudier@club-internet.fr) + * revision 2.6g + - New done queue. 8 entries by default (6 always useable). + Can be increased if needed. + - Resources management using doubly linked queues. + - New auto-sense and QUEUE FULL handling that does not need to + stall the NCR queue any more. + - New CCB starvation avoiding algorithm. + - Prepare CCBs for SCSI commands that cannot be queued, instead of + inserting these commands into the waiting list. The waiting list + is now only used while resetting and when memory for CCBs is not + yet available? + +Sun Feb 8 22:00 1998 Gerard Roudier (groudier@club-internet.fr) + * revision 2.6f + - Some fixes in order to really support the 53C895, at least with + FAST-20 devices. + - Heavy changes in the target/lun resources management to allow + the scripts to jump directly to the CCB on reselection instead + of walking on the lun CCBs list. Up to 32 tags per lun are now + supported without script processor and PCI traffic overhead. + +Sun Jan 11 22:00 1998 Gerard Roudier (groudier@club-internet.fr) + * revision 2.6d + - new (different ?) implementation of the start queue: + Use a simple CALL to a launch script in the CCB. + - implement a minimal done queue (1 entry :-) ). + this avoid scanning all CCBs on INT FLY (Only scan all CCBs, on + overflow). Hit ratio is better than 99.9 % on my system, so no + need to have a larger done queue. + - generalization of the restart of CCB on special condition as + Abort, QUEUE FULL, CHECK CONDITION. + This has been called 'silly scheduler'. + - make all the profiling code conditionned by a config option. + This spare some PCI traffic and C code when this feature is not + needed. + - handle more cleanly the situation where direction is unknown. + The pointers patching is now performed by the SCRIPTS processor. + - remove some useless scripts instructions. + + Ported from driver 2.5 series: + ------------------------------ - Use FAST-5 instead of SLOW for slow scsi devices according to new SPI-2 draft. - Make some changes in order to accomodate with 875 rev <= 3 @@ -10,1142 +270,13 @@ . Memory Read Line is not enabled for 875 and 875-like chips. . Programmed burst length set to 64 DWORDS (instead of 128). (Note: SYMBIOS uses 32 DWORDS for the SDMS BIOS) - -Sun Oct 26 12:00 1997 Gerard Roudier (groudier@club-internet.fr) - * revision 2.5e - Add 'buschk' boot option. This option enables checking of SCSI BUS data lines after SCSI RESET (set by default). (Submitted by Richard Waltham). - Update the README file. - -Sat Oct 4 18:00 1997 Gerard Roudier (groudier@club-internet.fr) - * revision 2.5d - Dispatch CONDITION MET and RESERVATION CONFLICT scsi status as OK driver status. - Update the README file and the Symbios NVRAM format definition with removable media flags values (available with SDMS 4.09). - -Sat Sep 20 21:00 1997 Gerard Roudier (groudier@club-internet.fr) - * revision 2.5c - Several PCI configuration registers fix-ups for powerpc. (Patch sent by Cort). - -Thu Aug 28 10:00 1997 Gerard Roudier (groudier@club-internet.fr) - * revision 2.5b - - Add 'ncr53c8xx' char pointer variable. This variable allows to - pass a boot command to the driver when it is loaded as a module. - Option separator is ' ' instead of ','. Example: - insmod /ncr53c8xx.o ncr53c8xx='verb:2 sync:0 specf:n' - - Always use 'driver_setup.settle_delay' for internal resets. - 2 seconds hardcoded is sometimes too short. Suggested by Richard W. - This delay may be shortenned in order to avoid spurious timeouts. - - Fix release module stuff that failed for more than 1 controller. - - For linux versions > 1.3.70, trust the 'dev_id' parameter passed - to the interrupt handler (dev_id = struct ncb *). - - Fix up in 'ncr_log_hard_error()' when the DSP points outside scripts. - Suggested by Stefan Esser. - -Tue Aug 23 23:43 1997 Gerard Roudier (groudier@club-internet.fr) - * revision 2.5a - - Update Configure.help for inclusion in linux-2.1.51/2/3 - - Use BASE_2 address from PCI config space instead of some - IO register for getting the on-board SRAM bus address. - - Remove error testing of pcibios_read/write functions. - These functions are intended to be used for successfully - detected PCI devices. Expecting error condition from them - is nothing but paranoia. - -Thu Aug 21 23:00 1997 Gerard Roudier (groudier@club-internet.fr) - * revision 2.5 - - 53C860 chip support fix. - - Move the 'host_status' to the last DWORD of the CCB header. - This header is copied back by the script processor. This - guarantees that the header is entirely copied back over - the PCI when the CPU completes a CCB. - - (re)read ISTAT prior to scanning CCBs for completion. This - ensure that any posted buffer are flushed prior CCBs scan. - - Support for BIG ENDIAN cpu. Added by Cort . - Initial patch did'nt support disconnections and tagged commands. - I've completed the patch and it seems that all is ok now. - Only some powerpc under 2.1.X is supported for the moment. - - Misc. trivial fixes and cleanups. - -Sat July 26 18:00 1997 Gerard Roudier (groudier@club-internet.fr) - * revision 2.4 - Several clean-ups: - - Asynchronous pre-scaler calculation. - Synchronous divisor calculation. - - Use FE_ as feature identifier prefix instead of _F_. - - Change 'ns_sync' identifier to "minsync". - - Some others. - Apply some SPI2-R12 recommendations. - - Use Slow, Fast-10, Fast-20, Fast-40 SCSI instead of SCSI-2, - FAST SCSI-2, ULTRA, ULTRA-2. - - Reset the SCSI on bus mode change. - -Wed July 02 22:58 1997 Gerard Roudier (groudier@club-internet.fr) - * revision 2.3c - - Add define SCSI_NCR_PCI_FIX_UP_SUPPORT for conditionnal compilation - of the corresponding pci fix-up code when a small driver is needed. - - Use "ncr53c8xx" as driver name for both request_irq() and - request_region(). Using different names confused 'lsdev'. - (Suggestion sent by Henrik Storner). - -Wed June 24 22:08 1997 Gerard Roudier (groudier@club-internet.fr) - * revision 2.3b - - Print an error message on unexpected boot command line option. - - Switch to asynchronous data transfer mode after SCSI wide - negotiation. - -Wed June 24 22:08 1997 Gerard Roudier (groudier@club-internet.fr) - * revision 2.3b - - Print an error message on unexpected boot command line option. - - Switch to asynchronous data transfer mode after SCSI wide - negotiation. - -Wed June 14 22:00 1997 Gerard Roudier (groudier@club-internet.fr) - * revision 2.3a - - Add PCI LATENCY TIMER fixup code. - Increase it if necessary according to burst size. - Boot option bit : 'pcifix:4' - - On phase mismatch, calculate residual data size for all OUTPUT - phases. That's only required for interrupted DATA OUT phase, but - this information is usefull for problem solving. - - Add KERN_INFO to some messages printed to the log. - (Patch sent by Wolfram Kleff). - -Tue June 02 22:30 1997 Gerard Roudier (groudier@club-internet.fr) - * revision 2.3 - - NvRAM support code slightly improved (I think): - Use IO or MMIO according to driver setup for reading the NvRAM. - Use structures for NvRAM data instead of raw data. - - Prevent from queuing more than 1 command to the scsi SCRIPT with - negotiation attached when tagged command queueing is enabled. - - Fix-up for old 53C8XX chips that support PCI READ LINE but not - CACHE LINE SIZE. If the cache line size is unknown, set burst - to 8 dwords and disable READ LINE, otherwise set burst max to - the cache line size value. - -Sat May 24 12:30 1997 Gerard Roudier (groudier@club-internet.fr) - * revision 2.2c (for linux-2.1.40) - - Remove reference to 'x86' symbol when MODULE is defined, since this - symbol is not exported for module loading. - The value of 'x86' is used for fixing up the PCI CACHE LINE SIZE - configuration register. - - Bytes/words read one bit at a time from the serial NVRAM were'nt - initialized with zero. - - Some comments added. Minor cosmetic changes. - -Mon May 19 20:30 1997 Gerard Roudier (groudier@club-internet.fr) - * revision 2.2b - - Patch for NVRAM support by Richard Waltham applied. - The code detects Symbios NVRAM format and Tekram NVRAM format. - This enhancement allows to get hosts and devices user set up - from the NVRAM. - - Use the NVRAM contents when present to initialize user definable - target parameters. - - Update the README file. - -Sun May 11 22:30 1997 Gerard Roudier (groudier@club-internet.fr) - * revision 2.1b - - Cosmetic changes. - - Some heavy testings under pre-linux-2.1.37-6 - -Sun May 4 22:30 1997 Gerard Roudier (groudier@club-internet.fr) - * revision 2.1a - - PFEN wrongly used for PREFETCH feature bit testing. - Changed to _F_PFEN. - - 2 SCR_COPY that need NO FLUSH bit to be removed had been missed - in tp->getscr[] script (loads SXFER and SCNTL3 on reselection). - -Sat May 3 22:30 1997 Gerard Roudier (groudier@club-internet.fr) - * revision 2.1 - - Use the NO FLUSH option for MOVE MEMORY (COPY) each time it is - possible. More than 100 COPY with NO FLUSH and 6 with FLUSH for - my configuration (max queued command / device = 8). - This option bit is removed from the script instance for chips - that donnot support prefetching. - - Rewrite the ncr_exception() routine more simple (I think) and - remove useless code. - - Change the data_in and data_out script management. - Use the bottom part of these scripts instead of the beginning. - That avoids to zero the scatter/gather array when a command is - queued (1k) and to deal with some weird IID on MOVE 0 bytes when - a target wants to transfer more bytes than expected. - - Misc. improvements in the init code. - - Remove IOMAPPED/MMIO automatic switching option. - Was useless and reported not reliable. - - Fix a double read of DSTAT and remove DFE testing in the - Phase mismatch service routine. - - Etc... - -Fri Apr 26 20:00 1997 Gerard Roudier (groudier@club-internet.fr) - * revision 2.0a - - Add support if the Diamond FirePort 40 (SYM53C875J chip) - -Mon Apr 22 22:00 1997 Gerard Roudier (groudier@club-internet.fr) - * revision 2.0 - - incorporate __initdata and __initfunc directives in order to - allow 'init' to free unused memory after driver initialisations. - Patch sent by Roberto Fichera. - - rewrite the init code of the driver. Now a feature descriptor - is used for each real chip types. The code is a lot more clean, - since the driver uses device and revision ids only in the - detection procedure. - - add 'pcifix' boot command line. This command allows to fix up PCI - config space for new chips which support features based on the - cache line size and 'write and invalidate'. - - incorporate in the driver, the code used for error recovery - testing. This code is normally not compiled; have to define - SCSI_NCR_DEBUG_ERROR_RECOVERY in order to compile it. - - take into account actual SCSI bus mode for 53C895 LVD/SE controller. - In single ended mode only fast20 is supported. - (Just to not be late since such controllers are not yet available) - - -Sat Apr 20 21:00 1997 Gerard Roudier (groudier@club-internet.fr) - * revision 1.18f - - fix an old bug included in the initial port (version 0.0). - The driver allocated 10 bytes of static data and uses 12 bytes. - No danger, since data are generally aligned on 4 bytes boundary - and so byte 10 and 11 are free (I hope ...) - -Wed Apr 16 12:00 1997 Gerard Roudier (groudier@club-internet.fr) - * revision 1.18e - - reset all when an unexpected data cycle is detected while - disconnecting. - - make changes to abort() ans reset() functions according to - Leonard's documentation. - - small fix in some message for hard errors. - -Sat Apr 5 13:00 1997 Gerard Roudier (groudier@club-internet.fr) - * revision 1.18d - - Probe NCR pci device ids in reverse order if asked by user from - the boot command line. Suggested by Richard Waltham. - - Make a separate function that prints out verbose information on - severe error (assumed from hardware). - - Add the transfer period factor and the max commands per lun value - to the proc info data. If debug flags are set or verbosity is - greater than 1, debug flags and verbosity are returned in proc - info data. - - Update the documentation. - -Thu Mar 20 23:00 1997 Gerard Roudier (groudier@club-internet.fr) - * revision 1.18c - - Add special features support for NCR53C885 and NCR53C896 chip. - Quite obvious, but untested, and based on the fact that: - The 885 supports same features as the 875. - The 896 is a 64 bits PCI version of the 895. - - Improve recovery from SCSI GROSS ERRORS. - I can get such errors by making the driver negotiate offset 8 with - a disk and setting the ncr chip to a lower offset value. - I got bunches of errors that have been gracefully recovered by - the driver. - The driver now uses its timer handler in order to wait 2 sec. for - devices to settle after SCSI reset and so does not uselessly freeze - the system with interrupt masked for seconds. - - Enable 'burst op code fetch' and 'read line' for 815 chips. - - Use a 2 commands queue depth instead of 1 for devices that does - not support tagged command queuing. - - The ULTRA timing flag setting was based on the output resulting - period factor of the ncr and not on the negotiated one. - This flag setting was wrong only for 24 ns negotiated period factor. - - Some other minor changes and cleanups. - -Thu Feb 27 23:00 1997 Gerard Roudier (groudier@club-internet.fr) - * ncr53c8xx.c ncr53c8xx.h revision 1.18b - - 'On paper' support of the NCR53C895 Ultra-2 chip. - (Clock quadrupler + 7 clock divisors) - - Load the main part of the script into the on-board RAM. - - 810A rev. 0x11 PCI problem fixed. - This chip is now supported with all PCI features enabled and - 16 dwords burst transfers. - - Align on 32 boundary some internal structures. - That fixes the 810A problem and allows cache line bursting when - moving the global header (64 bytes) from/to CCBs to/from NCB. - - Synchronous parameters calculation rewritten. The driver - now uses all available clock divisors and will be able to support - clock frequencies that are not multiple of 40 Mhz if necessary. - -Sat Feb 8 22:00 1997 Gerard Roudier (groudier@club-internet.fr) - * ncr53c8xx.c - revision 1.17a - - IRQ mode set up from boot setup command. - irqm:0 open drain (default) - irqm:1 preserve initial setting (assumed from BIOS) - irqm:2 totem pole - - DIFF mode set up from boot setup command. - Suggested by Richard Waltham. - diff:0 never set up diff mode (default) - diff:1 set up diff mode according to initial setting (BIOS?) - diff:2 always set up diff mode - diff:3 set up diff mode if GPIO3 is zero (SYMBIOS boards) - - Change CONFIG option for LED support. - CONFIG_SCSI_NCR53C8XX_SYMBIOS_COMPAT allows LED support and - DIFF support for SYMBIOS boards and compatibles (clones?). - - Set 16 DWORD bursts for 810A rev. >= 0x12 since my SC200 with - such a chip have no problem with it (MB with Triton 2 HX). - 810A rev. 0x11 are set to 8 DWORD bursts since they may give - problems with PCI read multiple and Triton 2 HX. - Thanks to Stefan for this information. - -Sat Jan 25 22:00 1997 Gerard Roudier (groudier@club-internet.fr) - * ncr53c8xx.c - revision 1.17 - - Controller LED support. - Only works with LED pin wired to GPIO_FETCHN, so probably with - all boards using SMDS BIOS. - This option can be enabled only if CONFIG_EXPERIMENTAL is set. - - Assume clock doubler for 875 chip when clock frequency measurement - result is 40 MHz. May help when some old stuff as SDMS BIOS 3.0 - or some old driver has broken the normal BIOS settings. - - Add wide negotiation control from boot setup command. - May be usefull with systems using a 875 based board connected to - a wide device through a 50 pins to 68 pins converter. - - Add a "boot fail safe option" to the boot setup command line. - - Rewrite the "reset_command" routine. - Low-level driver are responsible to keep the involved command - alive. The new code seems to behave correctly. - - Change some variables used by the script from u_long to u_int32. - - Remove some useless code. - -Sun Jan 12 12:00 1997 Gerard Roudier (groudier@club-internet.fr) - * ncr53c8xx.c - revision 1.16e - - Add support of PCI burst length control from boot setup command. - burst:0 disable burst - burst:255 get burst from initial settings (BIOS settings?) - burst:#x set burst transfers to 1<<#x - - Only check xfer direction for common op-codes. - For all device specific / vendor specific opcodes the driver - now uses the xfer direction decided by the target. - -Sun Jan 05 12:00 1997 Gerard Roudier (groudier@club-internet.fr) - * ncr53c8xx.c - revision 1.16d - - The driver is now able to process scsi commands without - knowledge of xfer data direction. - Stefan agreed with this change for Linux. This change is - not needed under FreeBSD since low-level drivers receive - the expected data direction for each scsi request. - - Save ctest5 features bits at start-up and restore them at - module release step. - Avoid side effects when a ncr driver which trusts bios - settings is reloaded (could be the ncr53c8xx itself). - - -Wed Jan 01 23:30 1997 Gerard Roudier (groudier@club-internet.fr) - * ncr53c8xx.c - revision 1.16c - - Bad decision about 20MHz for 13 ns period factor. - Was wrong, so I restore the previous algorithm. - - Burst length 128 not correctly set in dmode. - -Thu Dec 26 22:00 1996 Gerard Roudier (groudier@club-internet.fr) - * ncr53c8xx.c ncr53c8xx.h README.ncr53c8xx - revision 1.16b - - Remove useless code. - - Try to improve error recovery in case of abort and reset. - - Remove DEBUG_NEGO by default. - - Add boot setup command support. - Now, all experimental config options can be removed. - - Update README file. - - -Mon Dec 23 23:00 1996 Gerard Roudier (groudier@club-internet.fr) - * ncr53c8xx.c ncr53c8xx.h - revision 1.16a - New display for speed ##.# MB/s (From Stefan) - - I add "WIDE" qualifier after ULTRA and FAST - - I get "FAST WIDE SCSI-2 20 MB/s" with my Atlas. That's nice. - - Richard Waltham reports SYMBIOS set the 875 to 20 MB/s for 13 ns - period factor. I decide to trust SYMBIOS. 20 MB/s output speed - instead of 19.2 MB/s should not cause problem. The ncr is only able - to use 16.67 MB/s when 20 MB/s is not possible. - - Fix from Markus Kossman: "Ultra SCSI enabled" wrongly printed - when not enabled. - - Set DEBUG_NEGO by default in order to get reports about sync nego. - Will remove it in the next patch. - -Thu Dec 19 21:00 1996 Gerard Roudier (groudier@club-internet.fr) - * ncr53c8xx.c ncr53c8xx.h README.ncr53c8xx - revision 1.16 - Incorporate new definitions in ncr53c8xx.h (From Stefan). - Check changes against Stefan's current version of the driver. - All seems ok. - -Sat Nov 30 21:00 1996 Gerard Roudier (groudier@club-internet.fr) - * ncr53c8xx.c ncr53c8xx.h - Make changes in order to support: - - Clock doubler and so 80 Mhz scsi clock for 875 chips. - - Sync transfers below 7.5 MB/sec. - Use Clock/2 between 5 and 10 Mega-transfers/s and Clock/4 below 5. - - Ultra SCSI data transfers. - - Offset 16. - - Works with my configuration. However I cannot test Ultra transfers, - since my disks are only fast scsi-2. - -Tue Nov 28 21:00 1996 Gerard Roudier (groudier@club-internet.fr) - * ncr53c8xx.c - I received yesterday my Promise SCSI Ultra board. - NCR53C875 rev. 3 with clock doubler. - Add the code to support some bus features, the large 536 dma fifo and - burst 128. Works. - -Mon Nov 4 21:00 1996 Gerard Roudier (groudier@club-internet.fr) - * ncr53c8xx.c ncr53c8xx.h - revision 1.14c - Severall control command improvements: - - - Allow to specify "all" to commands that apply to #target. - For example: "setsync all 255" sets asynchronous data - transfers for all targets on a bus. - - - Allow to control disconnection privilege per device, as follow: - "setflag #target no_sync" disables disconnection for #target. - "setflag #target" with no flag specified reenables it. - - Obviously #target may be specified as "all" in order to control - disconnection for all targets with a single control command. - - - README file updated and some hints about SCSI problems solving added. - -Sun Oct 27 22:00 1996 Gerard Roudier (groudier@club-internet.fr) - * ncr53c8xx.c ncr53c8xx.h - revision 1.14b - Add the following config parameters: - - - CONFIG_SCSI_NCR53C8XX_MAX_TAGS - Max number of queued tagged commands. - Allow from 2 to 12, default 4. - - - CONFIG_SCSI_NCR53C8XX_SYNC - Synchronous transfers frequency in MHz. - Allow from 5 to 10, default 5, 0 means asynchronous. - (And so remove CONFIG_SCSI_NCR53C8XX_FORCE_ASYNCHRONOUS) - -Sun Oct 20 16:00 1996 Gerard Roudier (groudier@club-internet.fr) - * ncr53c8xx.c - ncr_scatter() rewritten. - remove "ncr dead" detection. - -Sun Oct 13 19:00 1996 Gerard Roudier (groudier@club-internet.fr) - * ncr53c8xx.c ncr53c8xx.h - revision 1.14a - Enabling some special features makes problems with some hardware. - So, disable them by default. - Add SCSI_NCR_SPECIAL_FEATURES define to play with. - -Sun Oct 13 14:00 1996 Gerard Roudier (groudier@club-internet.fr) - * ncr53c8xx.c ncr53c8xx.h - Incorporate Stefan's patch for clock frequency detection. - (Committed in FreeBSD/ncr.c rev. 1.81). - The driver then does about the following: - Assume 40 MHz clock for all ncr chips except: - - NCR53C860 chips: - Assume 80 Mhz clock. - - NCR53C875 chips: - If clock doubler enabled, disable it and assume 40 Mhz clock. - Else if (scntl3&7)=0 measure scsi clock frequency. - Else trust bios setting of scntl3&7 (3=40 Mhz, 5=80Mhz). - -Wed Oct 9 22:00 1996 Gerard Roudier (groudier@club-internet.fr) - * ncr53c8xx.c - release 1.14 - For now, just change the clock detection as follow: - - If clock doubler selected by BIOS, assume 40 MHz clock since - clock doubler will be disabled by chip reset. - - Else if NCR53C860 assume 80 MHz clock. - - Else trust BIOS setting if (scntl3&7 >= 3) - - Else assume 40 MHz clock. - -Sat Oct 05 17:00 1996 Gerard Roudier (groudier@club-internet.fr) - * ncr53c8xx.c - Stefan sent me a patch that improves the clock frequency detection - of the driver. Stefan uses the general timer register stime1 in - order to measure as accurately as possible the scsi clock. - Works ok with my 825, but needs still testing. So will be - released later. - -Sun Sep 29 17:00 1996 Gerard Roudier (groudier@club-internet.fr) - * ncr53c8xx.c - Preserve dcntl/dmode/ctest3/ctest4 features bits at start-up. - Add the define option SCSI_NCR_TRUST_BIOS_SETTING. - - If this option is defined, the driver will preserve the - corresponding bits of io registers. - - Else, the driver will set features bits according to chip - and revision ids. - -Sun Sep 22 17:00 1996 Gerard Roudier (groudier@club-internet.fr) - * ncr53c8xx.c - Remove useless fields and code and so spare cpu: - - profile data are accumulated in jiffies ticks and converted - to milli-seconds when read through proc fs. - - when IOMAPPED is not defined, try only MMIO. - (avoid testing a value in order to choose between IO and MMIO) - -Sun Sep 01 20:00 1996 Gerard Roudier (groudier@club-internet.fr) - * ncr53c8xx.h, ncr53c8xx.c - Version 1.13 - Adaptation of the tagged command queuing depth control of the - FreeBSD driver to Linux. Now, tagged command queueing can be - disabled at run time by a "settags N 0" control command. - Add the following heuristic in order to manage intelligently (perhaps) - QUEUE_FULL status: - - Each time a QUEUE FULL status is returned by a device, disable tagged - command queuing for that device. - - Every 100 successfully complete commands, increment the maximum - queuable commands (up to the allowed limit). - -Fri Aug 30 10:00 1996 Gerard Roudier (groudier@club-internet.fr) - * ncr53c8xx.c - Version 1.12c - Incorporate the changes of FreeBSD/ncr.c revision 1.76. - The changes add support for the 53c860 and 53c875, - but without taking advantage of the new features. - Those chips are used exactly as the old 53c810. - -Sun Jul 21 00:00 1996 Gerard Roudier (groudier@club-internet.fr) - * ncr53c8xx.c, README.ncr53c8xx - Add the ncr53c8xx_select_queue_depths() function. - Set queue_depth to SCSI_NCR_MAX_TAGS (4 by default) for devices that - support tagged command queueing. - For other devices, set queue_depth to 1. No need to queue a command - to the driver if this command cannot be sent to the device. - Each time the driver hide io requests from the kernel and/or from the - driver, it may break a little (or a lot) optimization algorithms that - try to increase throughput by reordering io requests. - It is better to enable the disk write caching to reduce latencies for - write operations, and to trust asynchronous read ahead from the device - and from the kernel that can reduce latencies for read operations, - even when tagged command queuing is not supported or enabled. - -Sat Jul 20 20:00 1996 Gerard Roudier (groudier@club-internet.fr) - * ncr53c8xx.c - Minor changes: - - Problem of "CCB address mismatch" that happens with the 3 versions - of the driver. The CCB is correct and Stefan Esser suggests a little - patch that seems to be a bypass. - Stefan says he will change that in a future version of the BSD driver. - - Set burst transfers to 8 for 815 chips. - -Sun Jul 14 15:00 1996 Gerard Roudier (groudier@club-internet.fr) - * ncr53c8xx.c, Configure.help - Memory mapped io donnot work under linux/Alpha for the driver. - For the moment it is better to not support this feature for this - architecture. - -Tue Jul 09 20:00 1996 Gerard Roudier (groudier@club-internet.fr) - * ncr53c8xx.c - Garbage printed out with the following command (fixed): - - cat /proc/scsi/ncr53c8xx/0 - -Sun Jul 07 20:00 1996 Gerard Roudier (groudier@club-internet.fr) - * ncr53c8xx.c - Tagged command queueing cannot be disabled at run time. - I probably never try that because I felt the risk. - Shortest patch sent to Linus. I have to plan something better. - -Wed Jul 03 23:00 1996 Gerard Roudier (groudier@club-internet.fr) - Release 1.12a - Tested linux releases: 1.2.13, 2.0.0, 2.0.1 - -Mon Jul 01 21:00 1996 Gerard Roudier (groudier@club-internet.fr) - ncr53c8xx.h, ncr53c8xx.c - Add "clearprof" user command that clear the profile counters. - Automatically clear profile counters when num_kbytes=1000000000 - in order to avoid ugly overflow. - Donnot compile user command code and profile data with 1.2.13. - -Wed Jun 29 20:38 1996 Gerard Roudier (groudier@club-internet.fr) - Matthew Geier reported to me a weird problem of unexpected - disconnection while asynchronous negotiation. - The message sent by the driver is 1-3-1-ff-00. I sent a patch to - Matthew that change the message to 1-3-1-00-00. - The sync msgout was correct however some devices might be to happy - with ff. - -Wed Jun 26 22:57 1996 Gerard Roudier (groudier@club-internet.fr) - Patch no 4 sent to Harald. - The drived used "wtime" for timeouts adn time measurements. - I change for jiffies. - Work with my P133. - -Mon Jun 24 23:05 1996 Gerard Roudier (groudier@club-internet.fr) - Patch no 3 sent to Harald. - -Sun Jun 23 22:29 1996 Gerard Roudier (groudier@club-internet.fr) - Patch no 2 sent to Harald. - I think that the driver have some chance to work. - -Sun Jun 23 15:00 1996 Gerard Roudier (groudier@club-internet.fr) - Harald Koenig is interested in the adaptation of the driver to - Linux/Alpha. - I have prepared a patch and sent it to Harald. - -Sun Jun 16 19:00 1996 Gerard Roudier (groudier@club-internet.fr) - Release 1.11 - Tested linux releases: 1.2.13, 2.0.0 - -Sat Jun 15 23:00 1996 Gerard Roudier (groudier@club-internet.fr) - * ncr53c8xx.h, Configure.help, scsi/Config.in - Add CONFIG_SCSI_NCR53C8XX_IOMAPPED config option. - Prepare the 2.0.0 with the new version of the driver. - -Wed Jun 12 23:00 1996 Gerard Roudier (groudier@club-internet.fr) - Rewrite the README file. - Add some documentations of the proc file system support. - -Sun Jun 9 18:00 1996 Gerard Roudier (groudier@club-internet.fr) - * ncr53c8xx.c - Add proc filesystem support of the driver. - Read operations returns profile information. - Write operations send control commands to the host adapter driver. - -Wed Jun 5 22:00 1996 Gerard Roudier (groudier@club-internet.fr) - Change xfer direction for SCAN command to write. - Was bogus. - -Tue May 30 18:00 1996 Gerard Roudier (groudier@club-internet.fr) - * ncr53c8xx.c - Set the DMA FIFO to 88 for 825A and 875 boards. - The previous value of 536 is bogus since the script only read 7 - bits for the fifo size (thanks to Stefan). - -Mon May 27 18:00 1996 Gerard Roudier (groudier@club-internet.fr) - * ncr53c8xx.c - Correct the xfer direction guessing for scanner SCAN command (write). - -Mon May 27 18:00 1996 Gerard Roudier (groudier@club-internet.fr) - * ncr53c8xx.c - Add the following config options: - SCSI_NCR_DISABLE_MPARITY_CHECK : disable master parity checking. - SCSI_NCR_DISABLE_PARITY_CHECK : disable scsi parity checking. - SCSI_NCR_FORCE_SYNC_NEGO : force sync nego for all scsi 2 devices. - -Sat May 25 22:00 1996 Gerard Roudier (groudier@club-internet.fr) - Release 1.10 - Tested linux releases: 1.2.13, 1.3.45, 1.3.71, 1.3.90, 1.3.100 - 1.99.6, 1.99.7 - Switch between Drew's driver and Bsd driver tested for 1.99.7. - Both driver was made as modules. - -Sat May 25 16:00 1996 Gerard Roudier (groudier@club-internet.fr) - * ncr53c8xx.c - Some weird problems happen with multi-lun configurations and HDs. - SDTR seems to be sent with TEST UNIT READY of lun 1. - Tagged Queue cannot be enabled. It seems that inqdata are - filled with garbage probably due to some INQUIRY command to - lun 1. - I have fixed the problem as follow: - - negotiation are initiated only with a command to lun 0. - - inquiry data are store only for lun 0. - -Wed May 22 22:00 1996 Gerard Roudier (groudier@club-internet.fr) - * ncr53c8xx.c, ncr53c8xx.h - Have prepared the patch that allow to install the driver in the - kernel tree, without moving Drew's one. - Seems to work. However, I have to check that nothing has been - broken for 1.2.13 and 1.3.45 to 1.3.100. - -Sun May 4 22:00 1996 Gerard Roudier (groudier@club-internet.fr) - * ncr53c8xx.h - Adapt the source to some modifications of the linux tree of 1.3.98. - (include/linux/scsicam.h moved to include/scsi/scsicam.h) - -Thu Apr 25 21:00 1996 Gerard Roudier (groudier@club-internet.fr) - * ncr53c8xx.h, ncr53c8xx.c - Release 1.9 - Prepare conditionnal compilations for the future Linux version(s). - Assume that these versions will be nicely compatible with current - one. - 1.3.255, 1.4.0 or 2.0.0 ? - I suggest 3.0.0 for some obvious reason. - -Wed Apr 24 23:15 1996 Gerard Roudier (groudier@club-internet.fr) - * Install.ncr53c8xx - Add Patch-Current.ncr53c8xx to the distribution. - This patch is applied to the scsi Makefile at installation time for - Linux release V.P.S (V*1000000000+P*100000000+S > 1300000094). - Each time it'll be necessary I will send the patch corresponding to - the current Linux release to the linux-scsi@vger.rutgers.edu. - -Sun Apr 21 19:00 1996 Gerard Roudier (groudier@club-internet.fr) - * README.ncr53c8xx - Update Bonnie results of linux-1.3.92 + prepatch read-ahead 1.3.93. - Results are so good that I must remove FreeBSD-2.0.5 results from the - README file, otherwise I should cause trouble for myself. - -Sun Apr 07 21:00 1996 Gerard Roudier (groudier@club-internet.fr) - * ncr53c8xx.h - Define SCSI_NCR_MAX_LUN (8) inconditionaly. - Previous releases did not work for multi-lun devices. - This definition was wrongly conditionned: - (SCSI_CONFIG_MULTI_LUN instead of CONFIG_SCSI_MULTI_LUN). - No luck, since I donnot have multi-lun devices and could'nt - test it. - Some tests under linux-1.3.84 with an experimental patch that - try to do asynchronous read-ahead. - -Wed Apr 03 23:15 1996 Gerard Roudier (groudier@club-internet.fr) - * ncr53c8xx.h, ncr53c8xx.c - Change some wrong "assert (target == cmd->target & 7)" to - "assert (target == (cmd->target & 0xf)". - Remove NCR_TIMEOUT_ALERT from ncr53c8xx.c - Add SCSI_NCR_TIMEOUT_ALERT to ncr53c8xx.h - -Sun Mar 24 21:15 1996 Gerard Roudier (groudier@club-internet.fr) - * ncr53c8xx.h - During "make dep" of linux-1.2.13, LINUX_VERSION_CODE is undefined. - Have to assume 1.2.13 in such situation. - Release 1.8 - -Sun Mar 24 21:00 1996 Gerard Roudier (groudier@club-internet.fr) - * README.ncr53c8xx - Make changes according to the new uninstallation procedure. - -Sun Mar 24 20:00 1996 Gerard Roudier (groudier@club-internet.fr) - * Uninstall.ncr53c8xx - Add an uninstallation script to the distribution. - This shell script restore the standard driver. - Very usefull for people who prefers to use a driver that - does not support: - - Master parity check - - Tagged command queuing - - Fast Wide Scsi-2 features (up to 20 MB/sec) - and that would be capable to reject a Wide Negotiation that it had - previously initiated. - -Sat Mar 23 22:00 1996 Gerard Roudier (groudier@club-internet.fr) - * README.ncr53c8xx - Make changes according to the new installation procedure. - -Fri Mar 22 23:00 1996 Gerard Roudier (groudier@club-internet.fr) - * Install.ncr53c8xx - Add an installation script to the distribution. - 3 differents patches are necessary: - - linux-1.2.13 - - linux-1.3.45 to linux-1.3.49 - - linux-1.3.50 to linux-1.3.77 - -Wed Mar 13 22:00 1996 Gerard Roudier (groudier@club-internet.fr) - * ncr53c8xx.c, ncr53c8xx.h - Add share irq support. - This facility appears with linux-1.3.70. It seems that the - corresponding code of the kernel was questionnable before 1.3.72. - I decide to support this options from linux-1.3.72 and above. - (Add define option SCSI_NCR_SHARE_IRQ) - Release 1.7 - -Tue Mar 12 22:00 1996 Gerard Roudier (groudier@club-internet.fr) - * ncr53c8xx.c - Download BSD ncr.c 1.67 and apply the correction of negotiations order. - Now the Wide and Sync negotiation are done in the proper order. - (Problem reported by Johannes Plass). - Round up correctly the announced speed in MB/sec. - -Tue Mar 05 22:00 1996 Gerard Roudier (groudier@club-internet.fr) - * README.ncr53c8xx - Have to upload release 1.6 for users of linux-1.3.70-71 - -Mon Mar 04 16:00 1996 Gerard Roudier (groudier@club-internet.fr) - * README.ncr53c8xx - Add some Bonnie results to the README file. - -Sun Mar 03 20:00 1996 Gerard Roudier (groudier@club-internet.fr) - * ncr53c8xx.c - Make changes for linux-1.3.70 according to the new specification of - irq services interface (request_irq(), free_irq()). - With 26 letters, "_", and 10 digits we can build about: - 53x62**9 C names of 10 characters. - Why to use SAME function names with DIFFERENT parameters ? - -Sat Mar 02 22:30 1996 Gerard Roudier (groudier@club-internet.fr) - * ncr53c8xx.c - Using SIMPLE QUEUE TAG for all operations is good for performances, - but may be bad for assumed timeout values. - Under heavy disk load (Bonnie), the drive may start IO process of a - command, then disconnect, then execute lots of other commands - before completing the interrupted command. - The standard value of SD_TIMEOUT (6 sec or 7 sec) seems (is) too short. - I fix the problem by forcing an ORDERED QUEUE TAG for the next - command when I found some "old" pending command. - "Old" means that they might be timeouted in a few seconds. - Add NCR_TIMEOUT_ALERT and set it to 3 seconds. - -Fri Mar 01 22:30 1996 Gerard Roudier (groudier@club-internet.fr) - * ncr53c8xx.h, ncr53c8xx.c - Add define SCSI_NCR_SEGMENT_SIZE and set it by default to 512. - If undefined, the driver use the scatter list given by the upper - scsi driver, else it tries to split segments into shorter one - according to the value of SCSI_NCR_SEGMENT_SIZE. - -Tue Feb 27 21:30 1996 Gerard Roudier (groudier@club-internet.fr) - * ncr53c8xx.h - Set sg_tablesize to 127 = SCSI_NCR_MAX_SCATTER-1. - (was 64 = SCSI_NCR_MAX_SCATTER/2). - May increase the speed (about 20%) for linear read/write operations. - Bonnie results may be better, but I prefered the previous - value. - -Tue Feb 27 21:00 1996 Gerard Roudier (groudier@club-internet.fr) - * ncr54c8xx.c, ncr53c8xx.h - Tagged command queueing seems to affect linux-1.3.XY kernels. - I decide to disable tagged queue by default and to provide a command - tool to enable it per device after boot-up. - Add scsitag.c to the distribution. - Usage: scsitag device - Examples: scsitag /dev/sda - scsitag /dev/sdb - -Sun Feb 25 14:00 1996 Gerard Roudier (groudier@club-internet.fr) - * ncr53c8xx.c, ncr53c8xx.h - Add INQ7_Default definition and set the target capabilities to this - value by default. - Add some code to reject a synchronous negotiation request from a target - that is defined as not capable of Sync in the table of capabilities. - -Sat Feb 24 23:00 1996 Gerard Roudier (groudier@club-internet.fr) - * ncr53c8xx.c - Add some code to fill some write-only host instance fields: - - base - - io_port - - n_io_port - - dma_channel - This fields may be used with some "standard" drivers that do not - process correctly the release function. - -Fri Feb 23 23:00 1996 Gerard Roudier (groudier@club-internet.fr) - I receive a mail from Jason Duerstock. - A new bug in ncrBsd2Linux which is probably outside the driver code - and inside Linux kernel code. - The kernel memory is quite corrupted and we cannot get any information - by looking into the messages about the crash. However Linus see a bug in - ncrBsd2Linux because it is a "non standard" driver. - I think too that ncrBsd2Linux is not a standard driver of Linux kernel, - because it has no bugs enough to become standard for Linux. - Drew's driver is quite standard. - -Wed Feb 21 23:00 1996 Gerard Roudier (groudier@club-internet.fr) - * ncr53c8xx.c, ncr53c8xx.h - I incorporate the differences between FreeBSD ncr.c revision 1.62 and - revision 1.64. - - Some cosmetic changes. - - Use M_SIMPLE_TAG by default (even for write operations). - I seems to me that SIMPLE TAG is safe only if the flag "queue - algorithm modifier" is set to zero. - I will ask some questions to Stefan Esser about this. - Add option SCSI_NCR_ALWAYS_SIMPLE_TAG in ncr53c8xx.h. - -Fri Feb 16 23:00 1996 Gerard Roudier (groudier@club-internet.fr) - I have found the bug. It is a recursion in __get_free_pages(). - I will send a mail to Linus about this. - -Sat Feb 10 20:00 1996 Gerard Roudier (groudier@club-internet.fr) - I am sure that the kernel stack overflow is due to a severe bug in - the Linux kernel. - I decide to try to find the bug by myself. - -Fri Feb 09 20:00 1996 Gerard Roudier (groudier@club-internet.fr) - * ncr53c8xx.c, ncr53c8xx.h - Limit commands per lun to 2 for linux-1.3.XY. - The patch-1.3.60 does not correct the kernel stack overflow problem. - I decide to make some tests with Drew's driver and Bsd2Linux with same - working conditions (3 commands per lun, FAST SCSI, no command queueing). - I get the stack overflow problem with the 2 drivers at the same - frequency. - With only 2 commands per LUN, I don't have the problem with any driver. - It seems that the madness of recursion and the recent introduction of - the silly generic read function have broken performance and reliability - of scsi drivers. - -Thu Feb 08 23:00 1996 Gerard Roudier (groudier@club-internet.fr) - * ncr53c8xx.c, ncr_attach() - Release memory mapped region and io port if initialisation - does not succeed. - -Thu Feb 08 22:00 1996 Gerard Roudier (groudier@club-internet.fr) - * ncr53c8xx.c, ncr53c8xx.c - Try to spare some CPU time in queue_command() function and interrupt - handler: - Add SCSI_NCR_PARANOIA define option in ncr53c8xx.h. - Add SCSI_NCR_PROFILE define option in ncr53c8xx.h. - Avoid useless code and function calls. - -Tue Feb 06 21:00 1996 Gerard Roudier (groudier@club-internet.fr) - * ncr53c8xx.c, ncr53c8xx.h, ncr_timeout() - Add SCSI_NCR_BROKEN_INTR define option in ncr53c8xx.h. - If this option is set, the timeout handler polls the interrupt status - register every tick (10 ms). So, boards with broken interrupt can work. - -Mon Feb 05 21:30 1996 Gerard Roudier (groudier@club-internet.fr) - * ncr53c8xx.c - Print the correct speed, for devices with successfull wide negotiation. - For same period, such devices are two times faster then narrow ones. - -Mon Feb 05 21:00 1996 Gerard Roudier (groudier@club-internet.fr) - * ncr53c8xx.h, ncr53c8xx.c, ncr_attach() - Add define SCSI_NCR_SETTLE_TIME in header file and set it by default - to 2 seconds. - -Sat Jan 27 14:00 1996 Gerard Roudier (groudier@club-internet.fr) - Upload release 1.3 - -Wed Jan 24 24:00 1996 Gerard Roudier (groudier@club-internet.fr) - * ncr53c8xx.c - Update from ncr Bsd 1.60 (Stefan Esser): - The handshake timeout is disabled, since - a few devices will delay ACK for more than a - second: Scanner, CDROM writer and a few old hard - disk drives. - -Wed Jan 24 22:30 1996 Gerard Roudier (groudier@club-internet.fr) - * ncr53c8xx.c - Set the selection timeout to 0.4 sec, since 0.25 sec - is recommended for scsi-1 devices. - Note that the Bsd ncr driver sets this timeout to 0.1 sec - and the linux standard ncr driver sets it to 0.8 sec. - -Wed Jan 24 22:00 1996 Gerard Roudier (groudier@club-internet.fr) - * ncr53c8xx.c - Add a 5 seconds delay after chip initialization, - waiting for scsi devices to settle their stomach, - as FreeBSD generic scsi driver does. - -Tue Jan 23 23:00 1996 Gerard Roudier (groudier@club-internet.fr) - * ncr53c8xx.c - Set burst length value according to chip type. - The original Bsd ncr driver sets burst length to 16 for - all chip types. - -Tue Jan 16 23:00 1996 Gerard Roudier (groudier@club-internet.fr) - * ncr53c8xx.c, ncr53c8xx.h - Add comments to linux specific glue code. - -Mon Jan 15 22:00 1996 Gerard Roudier (groudier@club-internet.fr) - io mapped versus memory mapped. - * ncr53c8xx.c - Add some code to dynamicaly switch to io mapped if memory mapped - does not work. - No more need to reconfigure, compile and link the kernel if - memory mapped is not possible. - -Sun Jan 14 18:00 1996 Gerard Roudier (groudier@club-internet.fr) - Patch sent to ncr mailing list by Jason Duerstock - - I have omitted to provide the proc_dir_entry to the middle - scsi driver. - * ncr53c8xxx.c - Add the declaration of the ncr53c8xx proc_dir_entry and return - the pointer to middle scsi driver. - -Sat Jan 13 01:00 1996 Gerard Roudier (groudier@club-internet.fr) - ncrBsd2Linux 1.1 is ready. - Upload to sunsite immediatly. - -Fri Jan 12 23:45 1996 Gerard Roudier (groudier@club-internet.fr) - It seems that scsi-2 devices too may cause problems because they - have flawes in the firmware. - * ncr53c8xx.h - I add a table of capabilities per target. - This table contains one byte per target. The value of this byte - is anded with byte 7 of INQUIRY data. - Edit ncr53c8xx.h and read the corresponding comments for more - details. - -Wed Jan 10 22:35 1996 Gerard Roudier (groudier@club-internet.fr) - I have some time to read the scsi-1 specifications. - Some very old scsi devices may cause problems with the ncr Bsd driver - for the following raisons: - The Synchronous Negotiation protocol was optional. - The standardized INQUIRY data does not include the byte 7 of - the scsi-2 specifications which contains the capabilities of - the device. - I think that negotiation with such devices are very questionnable. - * ncr53c8xx.c - ncrBsd2Linux 1.1 does not negotiate with scsi-1 devices. - -Sat Jan 06 21:00 1996 Gerard Roudier (groudier@club-internet.fr) - * ncr53c8xx.c function ncr_attach() - Disable chip interrupt before soft reset in attach procedure. - When loadlin is used to boot the system, the state of the NCR chip - is unpredicable. This modification avoid unexpected interrupts. - -Thu Jan 04 23:45 1996 Gerard Roudier (groudier@club-internet.fr) - ncrBsd2Linux 1.0 is ready. - Upload to sunsite immediatly. - -Tue Jan 02 23:00 1996 Gerard Roudier (groudier@club-internet.fr) - * ncr53c8xx.c - Add a waiting list for Scsi Commands than can be inserted - into the start queue immediatly. - When a command complete, the waiting commands are requeued by calling - the queuecommand() function. - -Sun Dec 31 23:59 1995 Gerard Roudier (groudier@club-internet.fr) - * ncr53c8xx.c - Use kmalloc()/kfree() for internal data structures allocation to - avoid scsi memory pool shortage. - -Sat Dec 30 23:00 1995 Gerard Roudier (groudier@club-internet.fr) - ncrBsd2Linux can now use memory mapped IO. - Works fine. - * ncr53c8xx.c - Call vremap() from ncr_attach() to map the physical page which - contains the memory IO window. - Call vfree() from ncr_detach() (release module). - -Fri Dec 29 23:45 1995 Gerard Roudier (groudier@club-internet.fr) - ncrBsd2Linux can now be configured as a module. - Works fine. - * ncr53c8xx.c: add new functions ncr53c8xx_release() and ncr_detach() - Add the code to (per host): - Stop the timer. - Stop the chip. - Free allocated memory. - -Fri Dec 29 23:00 1995 Gerard Roudier (groudier@club-internet.fr) - Problem: detection routine returns 0 and can detect only one host. - * ncr53c8xx.c function ncr_attach() - ncr_attach() now returns 0 on success and -1 on error. - ncr53c8xx_detect() returns the number of detected hosts. - -Thu Dec 28 22:00 1995 Gerard Roudier (groudier@club-internet.fr) - I must upload the new version which corrects the severe problem with - WRITE_10 command. - Release 0.5 - Known or probable problems with this ncr driver release: - -------------------------------------------------------- - Same as the previous release. - -Wed Dec 27 23:00 1995 Gerard Roudier (groudier@club-internet.fr) - Problem: - System CRASH or scsi ERROR "extra data disgarded" on WRITE(10) - command. - * ncr53c8xx.c function guess_xfer_direction() - I add the WRITE(10) (0x2A) into the list of Data Out scsi commands. - It was a big mistake. - This BUG was introduced in the release 0.3 and is obvious present in - the release 0.4. - -Wed Dec 27 22:00 1995 Gerard Roudier (groudier@club-internet.fr) - Problem: - When I was testing tagged command queueing and disconnections - with one hard disk at a time (IBM S12), the script process hung - every 5 minutes with a non empty stall queue. - * ncr53c8xx.c function ncr_exception() - I replace "OUTB (nc_istat, INTF)" by - "OUTB (nc_istat, (istat & SIGP) | INTF)". - This statement cleared the INTF condition, but cleared the SIGP flag too. - (This bug is in the original FreeBSD ncr driver). - -Mon Dec 25 22:00 1995 Gerard Roudier (groudier@club-internet.fr) - Release 0.4 - Known or probable problems with this ncr driver release: - -------------------------------------------------------- - Hardware (or software) conflicts with some ethernet cards. - See release 0.2 above. - Crash with Intel saturn chipset with write-back cache enabled. - The SCSI SCRIPT access the internal registers of - the NCR chip by memory addressing. - Ensure that the memory area of the NCR chip is not cacheable. - Use scanpci to get the base memory address of the ncr chip. - The 128 bytes following this address must not be cached. - -Sat Dec 23 22:00 1995 Gerard Roudier (groudier@club-internet.fr) - Problem: - FreeBSD driver important comments - --------------------------------- - We try to reduce the number of interrupts caused - by unexpected phase changes due to disconnects. - A typical harddisk may disconnect before ANY block. - If we wanted to avoid unexpected phase changes at all - we had to use a break point every 512 bytes. - Of course the number of scatter/gather blocks is - limited. - * ncr53c8xx.c function ncr_scatter() - This function has been rewritten according to the above comments. - The Linux scatter list is scanned, and blocks are broken as possible - into 512 bytes chunks. - -Wed Dec 22 22:00 1995 Gerard Roudier (groudier@club-internet.fr) - Problem: ensure that there are enough allocated Command Control Blocks - for each unit to enqueue commands according to cmd_per_lun. - * ncr53c8xx.c function ncr_allocate_ccb() - Allocate all required ccb(s) instead of one at a time. - -Mon Dec 18 23:00 1995 Gerard Roudier (groudier@club-internet.fr) - Problem: A copy of the system time is used to compute timeouts. - When the system time is changed , we can get spurious timeouts - if scsi commands are pending. - * ncr53c8xx.c function ncr_timeout() - In FreeBSD the kernel time (volatile struct timeval time) is not - affected by settimeofday() or other change time functions. - For Linux, I replace "time" by "xtime". But "xtime" is the system time, - and is affected by change time functions. - If we detect a change <=-1s or >1s we assume system time has been changed. - For all active ccb(s), we recompute tlimit. - We set heartbeat to thistime to prevent spurious chip reset. - -Sun Dec 17 23:00 1995 Gerard Roudier (groudier@club-internet.fr) - Release 0.3. - -Sun Dec 17 11:00 1995 Gerard Roudier (groudier@club-internet.fr) - - Problem: Linux middle-level scsi driver does not provide the - direction of transfert in scsi command parameters. - FreeBSD ncr driver need this information to patch the SCSI script - for SAVE DATA POINTER and to check actual data transfer direction. - * ncr53c8xx.c - I add the function guess_xfer_direction(int opcode) which try to - guess the transfer direction. - Unfortunately my documentation about SCSI-II standard is very old. - It does not contain PHOTO-CD command specifications. - I assume input transfer direction, for unknown command. (not perfect) - -Wed Dec 15 23:00 1995 Gerard Roudier (groudier@club-internet.fr) - - It's time to schedule the release 0.2 - Known or probable problems with this ncr driver release: - -------------------------------------------------------- - Scsi tapes do not work. - scsi-config-1.5 does not work too. - Hardware (or software) conflicts with some ethernet cards. - The linux native ncr53c810 scsi driver does'not use memory - mapped IO at all. - The BSD driver can use memory mapped IO. - Under Linux, i seems to be difficult (or impossible) to map - a PCI memory area. So I decide to use normal IO in the code of - the ported driver. - However, the SCSI SCRIPT access the internal registers of - the NCR chip by memory addressing. - EThernet cards use a memory area to communicate with the system. - I think that this memory area conflicts with the memory area - used by the NCR chip. - The configuration diskette of your ethernet card can help you - to fix the problem (try sofware configurations). - -Wed Dec 15 22:00 1995 Gerard Roudier (groudier@club-internet.fr) - - Problem: detection of CD change did not work. - * ncr53c8xx.c - Signal a CHECK_CONDITION (S_CHECK_COND) to the middle-level - scsi drivers when the scsi completion status = S_SENSE|S_GOOD. - - Problem: System hang with status <4/82> after mounting the root - partition. System disk is a QUANTUM EMPIRE 1080 S. - Submitted by rwilhelm@Physik.TU-Muenchen.DE (Robert Wilhelm) - Thu, 14 Dec 1995 10:18:43 +0100 (MET) - * ncr53c8xx.c - Signal a CHECK_CONDITION (S_CHECK_COND) to the middle-level - scsi drivers when the scsi completion status = S_SENSE|S_CHECK_COND. - (HS_COMPLETE=4, S_SENSE|S_CHECK_COND=x82). - I can't test this fix. I think that it should work. - -Thu Dec 14 22:00 1995 Gerard Roudier (groudier@club-internet.fr) - - Problem submitted by Bill Dyess Tue 12 Dec 1995 - Only one lun detected on a Pioneer DRM-602X 6-disk CD-ROM changer. - * ncr53c8xx.h, ncr53c8xx.c - Define NCR_SCSI_MAX_LUN to 8 if the Linux configuration flag - SCSI_CONFIG_MULTI_LUN is set. - My CD device has only one lun. I can't test multi-lun device, - but I think that it should work. - - * ncr53c8xx.c - Write the ncr_abort_command() and ncr_reset_command() functions. - I intend to test these functions next week. - -Sun Dec 10 22:00 1995 Gerard Roudier (groudier@club-internet.fr) - * Release 0.1 - Works fine with hard disks under Linux 1.2.13 and Linux 1.3.45. diff -urN linux-2.0.37-pre2/drivers/scsi/Config.in linux-2.0.37-pre3/drivers/scsi/Config.in --- linux-2.0.37-pre2/drivers/scsi/Config.in 2003-08-15 15:04:26.000000000 -0700 +++ linux-2.0.37-pre3/drivers/scsi/Config.in 2003-08-15 15:04:26.000000000 -0700 @@ -66,12 +66,12 @@ if [ "$CONFIG_PCI" = "y" -a "$CONFIG_SCSI_NCR53C7xx" != "y" ]; then dep_tristate 'NCR53C8XX SCSI support' CONFIG_SCSI_NCR53C8XX $CONFIG_SCSI if [ "$CONFIG_SCSI_NCR53C8XX" != "n" ]; then - bool ' detect and read serial NVRAMs' CONFIG_SCSI_NCR53C8XX_NVRAM_DETECT - bool ' enable tagged command queueing' CONFIG_SCSI_NCR53C8XX_TAGGED_QUEUE + int ' default tagged command queue depth' CONFIG_SCSI_NCR53C8XX_DEFAULT_TAGS 8 + int ' maximum number of queued commands' CONFIG_SCSI_NCR53C8XX_MAX_TAGS 32 + int ' synchronous transfers frequency in MHz' CONFIG_SCSI_NCR53C8XX_SYNC 20 + bool ' enable profiling' CONFIG_SCSI_NCR53C8XX_PROFILE bool ' use normal IO' CONFIG_SCSI_NCR53C8XX_IOMAPPED - int ' maximum number of queued commands' CONFIG_SCSI_NCR53C8XX_MAX_TAGS 4 - int ' synchronous transfers frequency in MHz' CONFIG_SCSI_NCR53C8XX_SYNC 5 - if [ "$CONFIG_SCSI_NCR53C8XX_TAGGED_QUEUE" != "y" ]; then + if [ "$CONFIG_SCSI_NCR53C8XX_DEFAULT_TAGS" = "0" ]; then bool ' not allow targets to disconnect' CONFIG_SCSI_NCR53C8XX_NO_DISCONNECT fi if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then diff -urN linux-2.0.37-pre2/drivers/scsi/i91uscsi.c linux-2.0.37-pre3/drivers/scsi/i91uscsi.c --- linux-2.0.37-pre2/drivers/scsi/i91uscsi.c 2003-08-15 15:04:26.000000000 -0700 +++ linux-2.0.37-pre3/drivers/scsi/i91uscsi.c 2003-08-15 15:04:26.000000000 -0700 @@ -2,6 +2,7 @@ * Initio 9100 device driver for Linux. * * Copyright (c) 1994-1998 Initio Corporation + * Copyright (c) 1998 Bas Vermeulen * All rights reserved. * * This program is free software; you can redistribute it and/or modify @@ -64,6 +65,12 @@ 07/08/98 hc, Support 0002134A 07/23/98 wh, Change the abort_srb routine. 09/16/98 hl, Support ALPHA, Rewrite the returnNumberAdapters <01> + 12/09/98 bv, Removed unused code, changed tul_se2_wait to + use udelay(30) and tul_do_pause to enable + interrupts for >= 2.1.95 + 12/13/98 bv, Use spinlocks instead of cli() for serialized + access to HCS_Semaph, HCS_FirstAvail and HCS_LastAvail + members of the HCS structure. **********************************************************************/ #define DEBUG_INTERRUPT 0 @@ -75,119 +82,102 @@ #ifndef CVT_LINUX_VERSION #define CVT_LINUX_VERSION(V,P,S) (V * 65536 + P * 256 + S) #endif -#if 0 -#include "../block/blk.h" -#include -#include "scsi.h" -#include "hosts.h" -#include "constants.h" -#include "i91uscsi.h" +#ifndef LINUX_VERSION_CODE +#include #endif -#if 1 + #include -/*#include */ +#include #include -/*#include "hosts.h"*/ -/*#include "scsi.h"*/ #include "i91uscsi.h" -#endif /*--- external functions --*/ -static void tul_se2_wait(void); -/*extern void tul_do_pause(unsigned int);*/ +static void tul_se2_wait(void); /*--- forward refrence ---*/ -static SCB *tul_find_busy_scb(HCS *pCurHcb, WORD tarlun); -static SCB *tul_find_done_scb(HCS *pCurHcb); +static SCB *tul_find_busy_scb(HCS * pCurHcb, WORD tarlun); +static SCB *tul_find_done_scb(HCS * pCurHcb); -static int tulip_main(HCS *pCurHcb); -/* static int init_tulip(HCS *pCurHcb, SCB *pCurScb, int ch_idx);*/ +static int tulip_main(HCS * pCurHcb); -static int tul_next_state(HCS *pCurHcb); -static int tul_state_1(HCS *pCurHcb); -static int tul_state_2(HCS *pCurHcb); -static int tul_state_3(HCS *pCurHcb); -static int tul_state_4(HCS *pCurHcb); -static int tul_state_5(HCS *pCurHcb); -static int tul_state_6(HCS *pCurHcb); -static int tul_state_7(HCS *pCurHcb); -static int tul_xfer_data_in(HCS *pCurHcb); -static int tul_xfer_data_out(HCS *pCurHcb); -static int tul_xpad_in(HCS *pCurHcb); -static int tul_xpad_out(HCS *pCurHcb); -static int tul_status_msg(HCS *pCurHcb); -/*static int tul_bad_seq(HCS *pCurHcb); 10/13/97 */ - -static int tul_msgin(HCS *pCurHcb); -static int tul_msgin_sync(HCS *pCurHcb); -static int tul_msgin_accept(HCS *pCurHcb); -static int tul_msgout_reject(HCS *pCurHcb); -static int tul_msgin_extend(HCS *pCurHcb); - -static int tul_msgout_ide(HCS *pCurHcb); -static int tul_msgout_abort_targ(HCS *pCurHcb); -static int tul_msgout_abort_tag(HCS *pCurHcb); - -static int tul_bus_device_reset(HCS *pCurHcb); -static void tul_select_atn(HCS *pCurHcb, SCB *pCurScb); -static void tul_select_atn3(HCS *pCurHcb, SCB *pCurScb); -static void tul_select_atn_stop(HCS *pCurHcb, SCB *pCurScb); -//static int tul_reset_scsi(HCS *pCurHcb, int seconds); -static int int_tul_busfree(HCS *pCurHcb); -#if 0 -static int int_tul_scsi_rst(HCS *pCurHcb); -#else -int int_tul_scsi_rst(HCS *pCurHcb); -#endif -static int int_tul_bad_seq(HCS *pCurHcb); -static int int_tul_resel(HCS *pCurHcb); -static int tul_sync_done(HCS *pCurHcb); -static int wdtr_done(HCS *pCurHcb); -static int wait_tulip(HCS *pCurHcb); -static int tul_wait_done_disc(HCS *pCurHcb); -static int tul_wait_disc(HCS *pCurHcb); -/*static int tul_msgin_par_err(HCS *pCurHcb);*/ -static void tulip_scsi(HCS *pCurHcb); -static int tul_post_scsi_rst(HCS *pCurHcb); - -static void tul_se2_ew_en(WORD CurBase); -static void tul_se2_ew_ds(WORD CurBase); -static int tul_se2_rd_all(WORD CurBase); -static void tul_se2_update_all(WORD CurBase); /* setup default pattern */ -static void tul_read_eeprom(WORD CurBase); +static int tul_next_state(HCS * pCurHcb); +static int tul_state_1(HCS * pCurHcb); +static int tul_state_2(HCS * pCurHcb); +static int tul_state_3(HCS * pCurHcb); +static int tul_state_4(HCS * pCurHcb); +static int tul_state_5(HCS * pCurHcb); +static int tul_state_6(HCS * pCurHcb); +static int tul_state_7(HCS * pCurHcb); +static int tul_xfer_data_in(HCS * pCurHcb); +static int tul_xfer_data_out(HCS * pCurHcb); +static int tul_xpad_in(HCS * pCurHcb); +static int tul_xpad_out(HCS * pCurHcb); +static int tul_status_msg(HCS * pCurHcb); + +static int tul_msgin(HCS * pCurHcb); +static int tul_msgin_sync(HCS * pCurHcb); +static int tul_msgin_accept(HCS * pCurHcb); +static int tul_msgout_reject(HCS * pCurHcb); +static int tul_msgin_extend(HCS * pCurHcb); + +static int tul_msgout_ide(HCS * pCurHcb); +static int tul_msgout_abort_targ(HCS * pCurHcb); +static int tul_msgout_abort_tag(HCS * pCurHcb); + +static int tul_bus_device_reset(HCS * pCurHcb); +static void tul_select_atn(HCS * pCurHcb, SCB * pCurScb); +static void tul_select_atn3(HCS * pCurHcb, SCB * pCurScb); +static void tul_select_atn_stop(HCS * pCurHcb, SCB * pCurScb); +static int int_tul_busfree(HCS * pCurHcb); +int int_tul_scsi_rst(HCS * pCurHcb); +static int int_tul_bad_seq(HCS * pCurHcb); +static int int_tul_resel(HCS * pCurHcb); +static int tul_sync_done(HCS * pCurHcb); +static int wdtr_done(HCS * pCurHcb); +static int wait_tulip(HCS * pCurHcb); +static int tul_wait_done_disc(HCS * pCurHcb); +static int tul_wait_disc(HCS * pCurHcb); +static void tulip_scsi(HCS * pCurHcb); +static int tul_post_scsi_rst(HCS * pCurHcb); + +static void tul_se2_ew_en(WORD CurBase); +static void tul_se2_ew_ds(WORD CurBase); +static int tul_se2_rd_all(WORD CurBase); +static void tul_se2_update_all(WORD CurBase); /* setup default pattern */ +static void tul_read_eeprom(WORD CurBase); /* ---- EXTERNAL VARIABLES ---- */ -HCS tul_hcs[MAX_SUPPORTED_ADAPTERS]; +HCS tul_hcs[MAX_SUPPORTED_ADAPTERS]; /* ---- INTERNAL VARIABLES ---- */ -static INI_ADPT_STRUCT i91u_adpt[MAX_SUPPORTED_ADAPTERS]; +static INI_ADPT_STRUCT i91u_adpt[MAX_SUPPORTED_ADAPTERS]; -/*NVRAM nvram, *nvramp = &nvram;*/ +/*NVRAM nvram, *nvramp = &nvram; */ static NVRAM i91unvram; static NVRAM *i91unvramp; -/* HCSINFO HcsInfo[ MAX_PCI_DEVICES * MAX_PCI_CHANL ]; ??? */ -/*HCSINFO HcsInfo[ MAX_PCI_CHANL ];*/ -static UCHAR i91udftNvRam[64] = { /*----------- header -----------*/ - 0x25, 0xc9, /* Signature */ - 0x40, /* Size */ - 0x01, /* Revision */ +static UCHAR i91udftNvRam[64] = +{ +/*----------- header -----------*/ + 0x25, 0xc9, /* Signature */ + 0x40, /* Size */ + 0x01, /* Revision */ /* -- Host Adapter Structure -- */ - 0x95, /* ModelByte0 */ - 0x00, /* ModelByte1 */ - 0x00, /* ModelInfo */ - 0x01, /* NumOfCh */ - NBC1_DEFAULT, /* BIOSConfig1 */ - 0, /* BIOSConfig2 */ - 0, /* HAConfig1 */ - 0, /* HAConfig2 */ + 0x95, /* ModelByte0 */ + 0x00, /* ModelByte1 */ + 0x00, /* ModelInfo */ + 0x01, /* NumOfCh */ + NBC1_DEFAULT, /* BIOSConfig1 */ + 0, /* BIOSConfig2 */ + 0, /* HAConfig1 */ + 0, /* HAConfig2 */ /* SCSI channel 0 and target Structure */ - 7, /* SCSIid */ - NCC1_DEFAULT, /* SCSIconfig1 */ - 0, /* SCSIconfig2 */ - 0x10, /* NumSCSItarget*/ + 7, /* SCSIid */ + NCC1_DEFAULT, /* SCSIconfig1 */ + 0, /* SCSIconfig2 */ + 0x10, /* NumSCSItarget */ NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT, @@ -195,112 +185,93 @@ NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT, /* SCSI channel 1 and target Structure */ - 7, /* SCSIid */ - NCC1_DEFAULT, /* SCSIconfig1 */ - 0, /* SCSIconfig2 */ - 0x10, /* NumSCSItarget*/ + 7, /* SCSIid */ + NCC1_DEFAULT, /* SCSIconfig1 */ + 0, /* SCSIconfig2 */ + 0x10, /* NumSCSItarget */ NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0 }; /* - CheckSum - */ + 0, 0}; /* - CheckSum - */ -static UCHAR tul_rate_tbl[8] = /* fast 20 */ - { +static UCHAR tul_rate_tbl[8] = /* fast 20 */ +{ /* nanosecond devide by 4 */ - 12, /* 50ns, 20M */ - 18, /* 75ns, 13.3M */ - 25, /* 100ns, 10M */ - 31, /* 125ns, 8M */ - 37, /* 150ns, 6.6M */ - 43, /* 175ns, 5.7M */ - 50, /* 200ns, 5M */ - 62 /* 250ns, 4M */ - }; - -#if 0 /* <01> */ -static UCHAR bi91uPCI_mechanism = 0; /* The mechanism used by read PCI */ + 12, /* 50ns, 20M */ + 18, /* 75ns, 13.3M */ + 25, /* 100ns, 10M */ + 31, /* 125ns, 8M */ + 37, /* 150ns, 6.6M */ + 43, /* 175ns, 5.7M */ + 50, /* 200ns, 5M */ + 62 /* 250ns, 4M */ +}; + +extern int tul_num_ch; + + +static void tul_do_pause(unsigned amount) +{ /* Pause for amount*10 milliseconds */ + unsigned long the_time = jiffies + amount; /* 0.01 seconds per jiffy */ + +#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95) + /* + * We need to release the io_request_lock + * to make sure that the jiffies are updated + */ + spin_unlock_irq(&io_request_lock); + + while (time_before_eq(jiffies, the_time)); + + /* + * Acquire the io_request_lock again + */ + spin_lock_irq(&io_request_lock); +#else + while (jiffies < the_time); #endif -extern int tul_num_ch; - - -#if 1 -static void tul_do_pause( unsigned amount ) /* Pause for amount*10 milliseconds */ -{ - unsigned long the_time = jiffies + amount; /* 0.01 seconds per jiffy */ - - while (jiffies < the_time) - ; } -#endif /*-- forward reference --*/ -#if 0 -static void tul_snapdump(ULONG *ptr, int length) -{ - int col, row; - int i, idx; - - row = length / 16 + ((length % 16) ? 1 : 0); - idx = 0; - printk("\n\r"); - for (i = 0; i < row; i++) - { - printk("Offset %04x at %08lx : ", idx, (ULONG) ptr); - for (col = 0; (col < 2) & (idx < length); col++, idx+=4) - { - printk(" %08lx", *ptr++); - } - printk(" -"); - for (col = 0; (col < 2) & (idx < length); col++, idx+=4) - { - printk(" %08lx", *ptr++); - } - printk("\n\r"); - } -} -#endif -/*--- forward reference ---*/ /******************************************************************* Use memeory refresh time ~ 15us * 2 ********************************************************************/ void tul_se2_wait() { -#if 0 - ULONG i; - i = jiffies + (30 * HZ / 100000); - while (jiffies , i++); -#else - UCHAR readByte; - - readByte = TUL_RD( 0, 0x61 ); - if ( (readByte & 0x10) == 0x10) { - for (; ;) { - readByte = TUL_RD( 0, 0x61 ); - if ( (readByte & 0x10) == 0x10) - break; - } - for (;;) { - readByte = TUL_RD( 0, 0x61 ); - if ( (readByte & 0x10) != 0x10) - break; - } - } else { - for (; ; ) { - readByte = TUL_RD( 0, 0x61 ); - if ( (readByte & 0x10) == 0x10) - break; - } - for (; ; ) { - readByte = TUL_RD( 0, 0x61 ); - if ( (readByte & 0x10) != 0x10) - break; +#if 1 + udelay(30); +#else + UCHAR readByte; + + readByte = TUL_RD(0, 0x61); + if ((readByte & 0x10) == 0x10) { + for (;;) { + readByte = TUL_RD(0, 0x61); + if ((readByte & 0x10) == 0x10) + break; + } + for (;;) { + readByte = TUL_RD(0, 0x61); + if ((readByte & 0x10) != 0x10) + break; + } + } else { + for (;;) { + readByte = TUL_RD(0, 0x61); + if ((readByte & 0x10) == 0x10) + break; + } + for (;;) { + readByte = TUL_RD(0, 0x61); + if ((readByte & 0x10) != 0x10) + break; + } } - } #endif } @@ -337,28 +308,28 @@ ******************************************************************/ void tul_se2_instr(WORD CurBase, UCHAR instr) { - int i; - UCHAR b; + int i; + UCHAR b; - TUL_WR(CurBase + TUL_NVRAM, SE2CS | SE2DO); /* cs+start bit */ - tul_se2_wait(); - TUL_WR(CurBase + TUL_NVRAM, SE2CS | SE2CLK | SE2DO); /* +CLK */ - tul_se2_wait(); - - for ( i = 0; i < 8; i++) { - if (instr & 0x80) - b = SE2CS | SE2DO; /* -CLK+dataBit */ - else - b = SE2CS ; /* -CLK */ - TUL_WR(CurBase + TUL_NVRAM, b); + TUL_WR(CurBase + TUL_NVRAM, SE2CS | SE2DO); /* cs+start bit */ + tul_se2_wait(); + TUL_WR(CurBase + TUL_NVRAM, SE2CS | SE2CLK | SE2DO); /* +CLK */ tul_se2_wait(); - TUL_WR(CurBase + TUL_NVRAM, b | SE2CLK); /* +CLK */ + + for (i = 0; i < 8; i++) { + if (instr & 0x80) + b = SE2CS | SE2DO; /* -CLK+dataBit */ + else + b = SE2CS; /* -CLK */ + TUL_WR(CurBase + TUL_NVRAM, b); + tul_se2_wait(); + TUL_WR(CurBase + TUL_NVRAM, b | SE2CLK); /* +CLK */ + tul_se2_wait(); + instr <<= 1; + } + TUL_WR(CurBase + TUL_NVRAM, SE2CS); /* -CLK */ tul_se2_wait(); - instr <<= 1; - } - TUL_WR(CurBase + TUL_NVRAM, SE2CS ); /* -CLK */ - tul_se2_wait(); - return; + return; } @@ -368,10 +339,10 @@ ******************************************************************/ void tul_se2_ew_en(WORD CurBase) { - tul_se2_instr(CurBase, 0x30); /* EWEN */ - TUL_WR(CurBase + TUL_NVRAM, 0); /* -CS */ - tul_se2_wait(); - return; + tul_se2_instr(CurBase, 0x30); /* EWEN */ + TUL_WR(CurBase + TUL_NVRAM, 0); /* -CS */ + tul_se2_wait(); + return; } @@ -380,10 +351,10 @@ *************************************************************************/ void tul_se2_ew_ds(WORD CurBase) { - tul_se2_instr(CurBase, 0); /* EWDS */ - TUL_WR(CurBase + TUL_NVRAM, 0); /* -CS */ - tul_se2_wait(); - return; + tul_se2_instr(CurBase, 0); /* EWDS */ + TUL_WR(CurBase + TUL_NVRAM, 0); /* -CS */ + tul_se2_wait(); + return; } @@ -393,29 +364,29 @@ *******************************************************************/ USHORT tul_se2_rd(WORD CurBase, ULONG adr) { - UCHAR instr, readByte; - USHORT readWord; - int i; - - instr = (UCHAR)( adr | 0x80 ); - tul_se2_instr(CurBase, instr); /* READ INSTR */ - readWord = 0; - - for ( i = 15; i >= 0; i--) { - TUL_WR(CurBase + TUL_NVRAM, SE2CS | SE2CLK ); /* +CLK */ - tul_se2_wait(); - TUL_WR(CurBase + TUL_NVRAM, SE2CS ); /* -CLK */ + UCHAR instr, readByte; + USHORT readWord; + int i; + + instr = (UCHAR) (adr | 0x80); + tul_se2_instr(CurBase, instr); /* READ INSTR */ + readWord = 0; + + for (i = 15; i >= 0; i--) { + TUL_WR(CurBase + TUL_NVRAM, SE2CS | SE2CLK); /* +CLK */ + tul_se2_wait(); + TUL_WR(CurBase + TUL_NVRAM, SE2CS); /* -CLK */ /* sample data after the following edge of clock */ - readByte = TUL_RD(CurBase, TUL_NVRAM); - readByte &= SE2DI; - readWord += (readByte << i); - tul_se2_wait(); /* 6/20/95 */ - } - - TUL_WR(CurBase + TUL_NVRAM, 0 ); /* no chip select */ - tul_se2_wait(); - return readWord; + readByte = TUL_RD(CurBase, TUL_NVRAM); + readByte &= SE2DI; + readWord += (readByte << i); + tul_se2_wait(); /* 6/20/95 */ + } + + TUL_WR(CurBase + TUL_NVRAM, 0); /* no chip select */ + tul_se2_wait(); + return readWord; } @@ -424,40 +395,40 @@ *******************************************************************/ void tul_se2_wr(WORD CurBase, UCHAR adr, USHORT writeWord) { - UCHAR readByte; - UCHAR instr; - int i; - - instr = (UCHAR)( adr | 0x40 ); - tul_se2_instr(CurBase, instr); /* WRITE INSTR */ - for ( i = 15; i >= 0; i--) { - if (writeWord & 0x8000) - TUL_WR(CurBase + TUL_NVRAM, SE2CS | SE2DO); /* -CLK+dataBit 1 */ - else - TUL_WR(CurBase + TUL_NVRAM, SE2CS ); /* -CLK+dataBit 0 */ + UCHAR readByte; + UCHAR instr; + int i; + + instr = (UCHAR) (adr | 0x40); + tul_se2_instr(CurBase, instr); /* WRITE INSTR */ + for (i = 15; i >= 0; i--) { + if (writeWord & 0x8000) + TUL_WR(CurBase + TUL_NVRAM, SE2CS | SE2DO); /* -CLK+dataBit 1 */ + else + TUL_WR(CurBase + TUL_NVRAM, SE2CS); /* -CLK+dataBit 0 */ + tul_se2_wait(); + TUL_WR(CurBase + TUL_NVRAM, SE2CS | SE2CLK); /* +CLK */ + tul_se2_wait(); + writeWord <<= 1; + } + TUL_WR(CurBase + TUL_NVRAM, SE2CS); /* -CLK */ tul_se2_wait(); - TUL_WR(CurBase + TUL_NVRAM, SE2CS | SE2CLK ); /* +CLK */ + TUL_WR(CurBase + TUL_NVRAM, 0); /* -CS */ tul_se2_wait(); - writeWord <<= 1; - } - TUL_WR(CurBase + TUL_NVRAM, SE2CS); /* -CLK */ - tul_se2_wait(); - TUL_WR(CurBase + TUL_NVRAM, 0); /* -CS */ - tul_se2_wait(); - TUL_WR(CurBase + TUL_NVRAM, SE2CS); /* +CS */ - tul_se2_wait(); - - for (; ; ) { - TUL_WR(CurBase + TUL_NVRAM, SE2CS | SE2CLK); /* +CLK */ - tul_se2_wait(); - TUL_WR(CurBase + TUL_NVRAM, SE2CS ); /* -CLK */ + TUL_WR(CurBase + TUL_NVRAM, SE2CS); /* +CS */ tul_se2_wait(); - if ((readByte = TUL_RD(CurBase, TUL_NVRAM )) & SE2DI ) - break; /* write complete */ - } - TUL_WR(CurBase + TUL_NVRAM, 0); /* -CS */ - return; + + for (;;) { + TUL_WR(CurBase + TUL_NVRAM, SE2CS | SE2CLK); /* +CLK */ + tul_se2_wait(); + TUL_WR(CurBase + TUL_NVRAM, SE2CS); /* -CLK */ + tul_se2_wait(); + if ((readByte = TUL_RD(CurBase, TUL_NVRAM)) & SE2DI) + break; /* write complete */ + } + TUL_WR(CurBase + TUL_NVRAM, 0); /* -CS */ + return; } @@ -466,61 +437,56 @@ ************************************************************************/ int tul_se2_rd_all(WORD CurBase) { - int i; - ULONG chksum = 0; - USHORT *np; - - i91unvramp = &i91unvram; - np = (USHORT * )i91unvramp; - for ( i = 0; i < 32; i++) { - *np++ = tul_se2_rd(CurBase, i); - } - - /*--------------------Is signature "ini" ok ? ----------------*/ - if ( i91unvramp->NVM_Signature != INI_SIGNATURE ) - return - 1; -#if 0 - /*--------------------Is Model# byte 1 "91" ok ? ----------------*/ -// if ( i91unvramp->ModelByte0 != 0x91) /* 4: Model number (byte 0) */ -// return - 1; -#endif - /*---------------------- Is ckecksum ok ? ----------------------*/ - np = (USHORT * )i91unvramp; - for ( i = 0; i < 31; i++) - chksum += *np++; - if ( i91unvramp->NVM_CheckSum != (USHORT)chksum ) - return - 1; - return 1; + int i; + ULONG chksum = 0; + USHORT *np; + + i91unvramp = &i91unvram; + np = (USHORT *) i91unvramp; + for (i = 0; i < 32; i++) { + *np++ = tul_se2_rd(CurBase, i); + } + +/*--------------------Is signature "ini" ok ? ----------------*/ + if (i91unvramp->NVM_Signature != INI_SIGNATURE) + return -1; +/*---------------------- Is ckecksum ok ? ----------------------*/ + np = (USHORT *) i91unvramp; + for (i = 0; i < 31; i++) + chksum += *np++; + if (i91unvramp->NVM_CheckSum != (USHORT) chksum) + return -1; + return 1; } /*********************************************************************** Update SCSI H/A configuration parameters from serial EEPROM ************************************************************************/ -void tul_se2_update_all(WORD CurBase) /* setup default pattern */ -{ - int i; - ULONG chksum = 0; - USHORT * np, *np1; +void tul_se2_update_all(WORD CurBase) +{ /* setup default pattern */ + int i; + ULONG chksum = 0; + USHORT *np, *np1; - i91unvramp = &i91unvram; + i91unvramp = &i91unvram; /* Calculate checksum first */ - np = (USHORT * )i91udftNvRam; - for ( i = 0; i < 31; i++) - chksum += *np++; - *np = (USHORT)chksum; - tul_se2_ew_en(CurBase); /* Enable write */ - - np = (USHORT * )i91udftNvRam; - np1 = (USHORT * )i91unvramp; - for ( i = 0; i < 32; i++, np++, np1++) { - if (*np != *np1) { - tul_se2_wr(CurBase, i, *np); + np = (USHORT *) i91udftNvRam; + for (i = 0; i < 31; i++) + chksum += *np++; + *np = (USHORT) chksum; + tul_se2_ew_en(CurBase); /* Enable write */ + + np = (USHORT *) i91udftNvRam; + np1 = (USHORT *) i91unvramp; + for (i = 0; i < 32; i++, np++, np1++) { + if (*np != *np1) { + tul_se2_wr(CurBase, i, *np); + } } - } - tul_se2_ew_ds(CurBase); /* Disable write */ - return; + tul_se2_ew_ds(CurBase); /* Disable write */ + return; } /************************************************************************* @@ -528,2297 +494,1855 @@ **************************************************************************/ void tul_read_eeprom(WORD CurBase) { - UCHAR gctrl; - - i91unvramp = &i91unvram; - /*------Enable EEProm programming ---*/ - gctrl = TUL_RD(CurBase, TUL_GCTRL); - TUL_WR(CurBase + TUL_GCTRL, gctrl | TUL_GCTRL_EEPROM_BIT ); - if ( tul_se2_rd_all(CurBase) != 1 ) { - tul_se2_update_all(CurBase); /* setup default pattern */ - tul_se2_rd_all(CurBase); /* load again */ - } - /*------ Disable EEProm programming ---*/ - gctrl = TUL_RD(CurBase, TUL_GCTRL); - TUL_WR(CurBase + TUL_GCTRL, gctrl & ~TUL_GCTRL_EEPROM_BIT ); -} /* read_eeprom */ - - -#if 0 /* <01> */ -static UBYTE i91uGetPCIMechanism(void) -{ - int bus, device; - unsigned long lConfigAddress, lConfigData; - - lConfigAddress = 0x80000000; - for (bus = 0; bus < 255; bus++) - { - lConfigAddress &= 0xFFFF0000; - for (device = 0; device < 21; device++) - { - outl(lConfigAddress, 0xCF8); /*Write config_address,enable*/ - lConfigData = inl(0xCFC); /* Read config_data */ - if ((lConfigData & 0xFFFF) == 0x1101) - return (1); /* Mechanism 1 */ - if ((lConfigData & 0xFFFF) == 0x134A) - return (1); /* Mechanism 1 */ - lConfigAddress += 0x800; - } - lConfigAddress += 0x10000; - } - return (2); /* Mechanism 2 */ -} - -#if 1 - -/*****************************************************************************/ -static unsigned long i91uReadPCIConfig( unsigned char BusNum, - unsigned char DeviceNum, - unsigned char RegNum) -{ - HOST_ADR HostAdr; - CONFIG_ADR ConfigAdr; - unsigned long ConfigData; - -#if BIOS32 - REGS Regs; - - if (CallBIOS32) - { /* PCI BIOS32 exists, use it */ - Regs.eax.byte.ah = PCI_FUNCTION_ID; - Regs.eax.byte.al = READ_CONFIG_DWORD; - Regs.ebx.byte.bh = BusNum; - Regs.ebx.byte.bl = DeviceNum & 0xFC; - Regs.edi.word.di = RegNum; - if (PCIBIOS32Call(CallBIOS32, &Regs)) - { - return(-1); /* Read configuration error */ - } - if (Regs.eax.byte.ah != SUCCESSFUL) - { /* Check return code */ - return(-1); /* Read configuration error */ - } - return(Regs.ecx.ecx); - } -#endif - if (bi91uPCI_mechanism == 0) - bi91uPCI_mechanism = i91uGetPCIMechanism(); - if (bi91uPCI_mechanism == 1) - { /* Mechanism #1 */ - ConfigAdr.lConfigAdr = 0; - ConfigAdr.sConfigAdr.RegNum = RegNum & 0xFC; /* Get rid of bit 0&1 */ - ConfigAdr.sConfigAdr.DeviceNum = DeviceNum; - ConfigAdr.sConfigAdr.BusNum = BusNum; - ConfigAdr.sConfigAdr.Enable = 1; - outl(ConfigAdr.lConfigAdr, 0xCF8); /*Write config_address,enable*/ - ConfigData = inl(0xCFC); /* Read config_data */ - ConfigAdr.lConfigAdr = 0; - outl(ConfigAdr.lConfigAdr, 0xCF8); /*Write config_address,disable*/ - /*if (ConfigData != -1) Read success */ - return(ConfigData); - } - else - { /* Mechanism #2 */ - if (DeviceNum >= 16) /* Mechanism #2 only support 16 */ - return(-1); /* devices C000- CF00 */ - HostAdr.sHostAdr.RegNum = RegNum & 0xFC; /* Get rid of bit 0&1 */ - HostAdr.sHostAdr.DeviceNum = 0xC0 | (DeviceNum & 0xF); - HostAdr.sHostAdr.Reserved = 0x0000; - outb(BusNum, 0xCFA);/* Setup forward address */ - outb(0xC0, 0xCF8); /* Configuration mapping enable */ -/* outb(0xC0, 0xCFA); Configuration mapping enable */ - ConfigData = inl(HostAdr.lHostAdr);/* Read configuration data */ - outb(0, 0xCFA); /* Setup forward address */ - outb(0, 0xCF8); /* Configuration mapping disable*/ - return(ConfigData); - } -} - -#else + UCHAR gctrl; -/************************************************************************* - Function name : ReadPCIConfig - Description : This function return configuration space's register value. - Input : - BusNum - Bus number - DeviceNum - Device number - RegNum - Register number - Output : None. - Return : Register value -**************************************************************************/ -unsigned long ReadPCIConfig( unsigned char BusNum, - unsigned char DeviceNum, - unsigned char RegNum) -{ - HOST_ADR HostAdr; - CONFIG_ADR ConfigAdr; - unsigned long ConfigData; - - if (bPCI_mechanism == 1) { - /*------------------ Mechanism #1 ------------------------- */ - ConfigAdr.lConfigAdr = 0; - ConfigAdr.sConfigAdr.RegNum = RegNum & 0xFC; /* Get rid of bit 0&1 */ - ConfigAdr.sConfigAdr.DeviceNum = DeviceNum; - ConfigAdr.sConfigAdr.BusNum = BusNum; - ConfigAdr.sConfigAdr.Enable = 1; - outpl( 0xCF8, ConfigAdr.lConfigAdr); /* Write config_address, enable */ - - ConfigData = inpl( 0xCFC ); /* Read config_data */ - ConfigAdr.lConfigAdr = 0; - outpl( 0xCF8, ConfigAdr.lConfigAdr); /* Write config_address, disable*/ - return(ConfigData); - } else { - /*------------------ Mechanism #2 ------------------------- */ - if (DeviceNum >= 16) /* Mechanism #2 only support 16 */ - return(0); /* devices C000- CF00 */ - HostAdr.lHostAdr = 0; - HostAdr.sHostAdr.RegNum = RegNum & 0xFC; /* Get rid of bit 0&1 */ - HostAdr.sHostAdr.DeviceNum = 0xC0 | (DeviceNum & 0xF); - outp(0xCFA, BusNum); /* Setup forward address */ - outp(0xCF8, 0xC0); /* Configuration mapping enable */ - ConfigData = inpl(HostAdr.lHostAdr); /* Read configuration data */ - outp(0xCFA, 0); /* Setup forward address */ - outp(0xCF8, 0); /* Configuration mapping disable*/ - return(ConfigData); - } -} -#endif -#endif - -int Addi91u_into_Adapter_table(WORD wBIOS, WORD wBASE, BYTE bInterrupt, - BYTE bBus, BYTE bDevice) -{ - int i, j; - - for (i = 0; i < MAX_SUPPORTED_ADAPTERS; i++) - { - if (i91u_adpt[i].ADPT_BIOS < wBIOS) - continue; - if (i91u_adpt[i].ADPT_BIOS == wBIOS) - { - if (i91u_adpt[i].ADPT_BASE == wBASE) - if (i91u_adpt[i].ADPT_Bus != 0xFF) - return(FAILURE); - else - if (i91u_adpt[i].ADPT_BASE < wBASE) - continue; - } - for (j = MAX_SUPPORTED_ADAPTERS - 1; j > i; j--) - { - i91u_adpt[j].ADPT_BASE = i91u_adpt[j-1].ADPT_BASE; - i91u_adpt[j].ADPT_INTR = i91u_adpt[j-1].ADPT_INTR; - i91u_adpt[j].ADPT_BIOS = i91u_adpt[j-1].ADPT_BIOS; - i91u_adpt[j].ADPT_Bus = i91u_adpt[j-1].ADPT_Bus; - i91u_adpt[j].ADPT_Device = i91u_adpt[j-1].ADPT_Device; - } - i91u_adpt[i].ADPT_BASE = wBASE; - i91u_adpt[i].ADPT_INTR = bInterrupt; - i91u_adpt[i].ADPT_BIOS = wBIOS; - i91u_adpt[i].ADPT_Bus = bBus; - i91u_adpt[i].ADPT_Device = bDevice; - return(SUCCESSFUL); + i91unvramp = &i91unvram; +/*------Enable EEProm programming ---*/ + gctrl = TUL_RD(CurBase, TUL_GCTRL); + TUL_WR(CurBase + TUL_GCTRL, gctrl | TUL_GCTRL_EEPROM_BIT); + if (tul_se2_rd_all(CurBase) != 1) { + tul_se2_update_all(CurBase); /* setup default pattern */ + tul_se2_rd_all(CurBase); /* load again */ + } +/*------ Disable EEProm programming ---*/ + gctrl = TUL_RD(CurBase, TUL_GCTRL); + TUL_WR(CurBase + TUL_GCTRL, gctrl & ~TUL_GCTRL_EEPROM_BIT); +} /* read_eeprom */ + +int Addi91u_into_Adapter_table(WORD wBIOS, WORD wBASE, BYTE bInterrupt, + BYTE bBus, BYTE bDevice) +{ + int i, j; + + for (i = 0; i < MAX_SUPPORTED_ADAPTERS; i++) { + if (i91u_adpt[i].ADPT_BIOS < wBIOS) + continue; + if (i91u_adpt[i].ADPT_BIOS == wBIOS) { + if (i91u_adpt[i].ADPT_BASE == wBASE) + if (i91u_adpt[i].ADPT_Bus != 0xFF) + return (FAILURE); + else if (i91u_adpt[i].ADPT_BASE < wBASE) + continue; + } + for (j = MAX_SUPPORTED_ADAPTERS - 1; j > i; j--) { + i91u_adpt[j].ADPT_BASE = i91u_adpt[j - 1].ADPT_BASE; + i91u_adpt[j].ADPT_INTR = i91u_adpt[j - 1].ADPT_INTR; + i91u_adpt[j].ADPT_BIOS = i91u_adpt[j - 1].ADPT_BIOS; + i91u_adpt[j].ADPT_Bus = i91u_adpt[j - 1].ADPT_Bus; + i91u_adpt[j].ADPT_Device = i91u_adpt[j - 1].ADPT_Device; + } + i91u_adpt[i].ADPT_BASE = wBASE; + i91u_adpt[i].ADPT_INTR = bInterrupt; + i91u_adpt[i].ADPT_BIOS = wBIOS; + i91u_adpt[i].ADPT_Bus = bBus; + i91u_adpt[i].ADPT_Device = bDevice; + return (SUCCESSFUL); } - return(FAILURE); + return (FAILURE); } void init_i91uAdapter_table(void) { - int i; - - for (i = 0; i < MAX_SUPPORTED_ADAPTERS; i++) - { /* Initialize adapter structure */ - i91u_adpt[i].ADPT_BIOS = 0xffff; - i91u_adpt[i].ADPT_BASE = 0xffff; - i91u_adpt[i].ADPT_INTR = 0xff; - i91u_adpt[i].ADPT_Bus = 0xff; - i91u_adpt[i].ADPT_Device = 0xff; - } - return; -} - -#if 0 /* <01> */ -int tul_ReturnNumberOfAdapters(void) -{ - long dRegValue; - int i, iAdapters; - BYTE bPCIBusNum, bTotalBusNum, bInterrupt, bPCIDeviceNum; - WORD wBIOS, wBASE; - - for (i = 0; i < MAX_SUPPORTED_ADAPTERS; i++) - { /* Initialize adapter structure */ - i91u_adpt[i].ADPT_BIOS = 0xffff; - i91u_adpt[i].ADPT_BASE = 0xffff; - i91u_adpt[i].ADPT_INTR = 0xff; - i91u_adpt[i].ADPT_Bus = 0xff; - i91u_adpt[i].ADPT_Device = 0xff; - } - - bTotalBusNum = 0xFF; /* Search 255 buses */ - -/* bi91uPCI_mechanism = 1; 02/05/95 */ - - for (bPCIBusNum = 0, iAdapters = 0; bPCIBusNum < bTotalBusNum; bPCIBusNum++) - { /* Scan all the buses */ - for (bPCIDeviceNum=0; bPCIDeviceNum < MAX_PCI_DEVICES; bPCIDeviceNum++) - { /* Find all jasmine devices */ - if (iAdapters >= MAX_SUPPORTED_ADAPTERS) - break; /* Never greater than maximum */ - dRegValue = i91uReadPCIConfig(bPCIBusNum, bPCIDeviceNum, TUL_PVID); - if ((dRegValue & 0xFFFF) != INI_VENDOR_ID) - { -#if 1 - if ((dRegValue & 0xFFFF) != 0x134A) /* 07/08/98 */ - continue; -#else - if (bPCI_MechanismDone) - continue; - bi91uPCI_mechanism = 2; /* 02/05/95 */ - dRegValue =i91uReadPCIConfig(bPCIBusNum,bPCIDeviceNum,TUL_PVID); - if ((dRegValue & 0xFFFF) != INI_VENDOR_ID) - { - bi91uPCI_mechanism = 1; /* 02/05/95 */ - continue; /* Wrong vendor ID */ - } -#endif - } -/* bPCI_MechanismDone = 1;*/ - if ((((dRegValue >> 16) & 0xFF00) != I950_DEVICE_ID) && - (((dRegValue >> 16) & 0xFF00) != I940_DEVICE_ID) && - (((dRegValue >> 16) & 0xFF00) != 0x0002) && /* 07/08/98 */ - (((dRegValue >> 16) & 0xFF00) != I935_DEVICE_ID)) - continue; /* Wrong device ID */ - /* Read base address */ - dRegValue = i91uReadPCIConfig(bPCIBusNum, bPCIDeviceNum, TUL_PBAD); - if (dRegValue == -1) - { /* Check return code */ - printk("\n\ri91u: Jasmine read configuration error.\n"); - return(0); /* Read configuration space error */ - } - if ((dRegValue & 0x01) == 0) - { /* Base address for memory */ - printk("\n\ri91u: Wrong base address setting at -> Bus: %d; Device: %d", bPCIBusNum, bPCIDeviceNum); - continue; /* PCI configuration setup error*/ - } + int i; - wBASE = (WORD) (dRegValue & 0xFFFE); - /* Now read the BIOS address */ - dRegValue = i91uReadPCIConfig(bPCIBusNum, bPCIDeviceNum, TUL_SDCFG0); - wBIOS = (UWORD) (dRegValue & 0xFF); - if (((dRegValue & 0xFF00) >> 8) == 0xFF) - dRegValue = 0; - wBIOS = (wBIOS << 8) + ((UWORD) ((dRegValue & 0xFF00) >> 8)); - /* Now read the interrupt line */ - dRegValue = i91uReadPCIConfig(bPCIBusNum, bPCIDeviceNum, TUL_PINTL); - bInterrupt = dRegValue & 0xFF;/* Assign interrupt line */ - - if (Addi91u_into_Adapter_table(wBIOS, wBASE, bInterrupt, bPCIBusNum, - bPCIDeviceNum) == SUCCESSFUL) - iAdapters++; - } + for (i = 0; i < MAX_SUPPORTED_ADAPTERS; i++) { /* Initialize adapter structure */ + i91u_adpt[i].ADPT_BIOS = 0xffff; + i91u_adpt[i].ADPT_BASE = 0xffff; + i91u_adpt[i].ADPT_INTR = 0xff; + i91u_adpt[i].ADPT_Bus = 0xff; + i91u_adpt[i].ADPT_Device = 0xff; } - return (iAdapters); + return; } -#endif -void tul_stop_bm(HCS *pCurHcb) +void tul_stop_bm(HCS * pCurHcb) { - if (TUL_RD(pCurHcb->HCS_Base, TUL_XStatus) & XPEND) - { /* if DMA xfer is pending, abort DMA xfer */ - TUL_WR(pCurHcb->HCS_Base+ TUL_XCmd, TAX_X_ABT | TAX_X_CLR_FIFO); - /* wait Abort DMA xfer done */ - while ((TUL_RD(pCurHcb->HCS_Base, TUL_Int) & XABT) == 0); + if (TUL_RD(pCurHcb->HCS_Base, TUL_XStatus) & XPEND) { /* if DMA xfer is pending, abort DMA xfer */ + TUL_WR(pCurHcb->HCS_Base + TUL_XCmd, TAX_X_ABT | TAX_X_CLR_FIFO); + /* wait Abort DMA xfer done */ + while ((TUL_RD(pCurHcb->HCS_Base, TUL_Int) & XABT) == 0); } - TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO); + TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO); } /***************************************************************************/ -void get_tulipPCIConfig(HCS *pCurHcb, int ch_idx) +void get_tulipPCIConfig(HCS * pCurHcb, int ch_idx) { - pCurHcb->HCS_Base = i91u_adpt[ch_idx].ADPT_BASE; /* Supply base address */ - pCurHcb->HCS_BIOS = i91u_adpt[ch_idx].ADPT_BIOS; /* Supply BIOS address */ - pCurHcb->HCS_Intr = i91u_adpt[ch_idx].ADPT_INTR; /* Supply interrupt line*/ - return; + pCurHcb->HCS_Base = i91u_adpt[ch_idx].ADPT_BASE; /* Supply base address */ + pCurHcb->HCS_BIOS = i91u_adpt[ch_idx].ADPT_BIOS; /* Supply BIOS address */ + pCurHcb->HCS_Intr = i91u_adpt[ch_idx].ADPT_INTR; /* Supply interrupt line */ + return; } /***************************************************************************/ -int tul_reset_scsi(HCS *pCurHcb, int seconds) +int tul_reset_scsi(HCS * pCurHcb, int seconds) { -#if 0 - printk("i91u: enter tul_reset_scsi.\n"); -#endif + TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_RST_BUS); - TUL_WR( pCurHcb->HCS_Base + TUL_SCtrl0, TSC_RST_BUS); + while (!((pCurHcb->HCS_JSInt = TUL_RD(pCurHcb->HCS_Base, TUL_SInt)) & TSS_SCSIRST_INT)); + /* reset tulip chip */ - while(!((pCurHcb->HCS_JSInt = TUL_RD(pCurHcb->HCS_Base,TUL_SInt)) & TSS_SCSIRST_INT)); - /* reset tulip chip */ + TUL_WR(pCurHcb->HCS_Base + TUL_SSignal, 0); - TUL_WR(pCurHcb->HCS_Base + TUL_SSignal, 0); + /* Stall for a while, wait for target's firmware ready,make it 2 sec ! */ + /* SONY 5200 tape drive won't work if only stall for 1 sec */ + tul_do_pause(seconds * 100); - /* Stall for a while, wait for target's firmware ready,make it 2 sec ! */ - /* SONY 5200 tape drive won't work if only stall for 1 sec */ -#if 1 - tul_do_pause(seconds*100); -#else - for (i = 0; i < 66666; i++) /* wait 2 sec */ - tul_se2_wait(); /* wait 30 us */ -#endif + TUL_RD(pCurHcb->HCS_Base, TUL_SInt); - TUL_RD(pCurHcb->HCS_Base,TUL_SInt); + return (SCSI_RESET_SUCCESS); +} -#if 0 - TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0,TSC_RST_CHIP); - /* program HBA's SCSI ID */ - TUL_WR( hcsp->Base+TUL_SScsiId,hcsp->HaId << 4); - - /* Enable Initiator Mode ,phase latch,alternate sync period mode, - disable SCSI reset */ - if (hcsp->Config & HCC_EN_PAR) - TUL_WR(hcsp->Base+TUL_SConfig, TSC_INITDEFAULT | TSC_EN_SCSI_PAR); - else - TUL_WR(hcsp->Base+TUL_SConfig, TSC_INITDEFAULT ); - - /*Synchronous data transfer rate - Sync. period 0 -> 100 ns for 10 MHz - Sync. offset 0 -> Async. operation */ - /* Initialize the sync. xfer register values to an narrow, async. xfer */ - TUL_WR(hcsp->Base+TUL_SPeriodOffset, 0x70); +/***************************************************************************/ +int init_tulip(HCS * pCurHcb, SCB * scbp, int tul_num_scb, BYTE * pbBiosAdr, int seconds) +{ + int i; + WORD *pwFlags; + BYTE *pbHeads; + SCB *pTmpScb, *pPrevScb = NULL; - /* selection time out = 250 ms */ - TUL_WR(hcsp->Base+TUL_STimeOut, 153); + pCurHcb->HCS_NumScbs = tul_num_scb; + pCurHcb->HCS_Semaph = 1; +#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95) + pCurHcb->HCS_SemaphLock = SPIN_LOCK_UNLOCKED; +#endif + pCurHcb->HCS_JSStatus0 = 0; + pCurHcb->HCS_Scb = scbp; + pCurHcb->HCS_NxtPend = scbp; + pCurHcb->HCS_NxtAvail = scbp; + for (i = 0, pTmpScb = scbp; i < tul_num_scb; i++, pTmpScb++) { + pTmpScb->SCB_TagId = i; + if (i != 0) + pPrevScb->SCB_NxtScb = pTmpScb; + pPrevScb = pTmpScb; + } + pPrevScb->SCB_NxtScb = NULL; + pCurHcb->HCS_ScbEnd = pTmpScb; + pCurHcb->HCS_FirstAvail = scbp; + pCurHcb->HCS_LastAvail = pPrevScb; +#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95) + pCurHcb->HCS_AvailLock = SPIN_LOCK_UNLOCKED; +#endif + pCurHcb->HCS_FirstPend = NULL; + pCurHcb->HCS_LastPend = NULL; + pCurHcb->HCS_FirstBusy = NULL; + pCurHcb->HCS_LastBusy = NULL; + pCurHcb->HCS_FirstDone = NULL; + pCurHcb->HCS_LastDone = NULL; + pCurHcb->HCS_ActScb = NULL; + pCurHcb->HCS_ActTcs = NULL; -#if 1 - /* Initialize the sync. xfer register values to an async. xfer */ - tcsp = &hcsp->HCS_Tcs[0]; - for (i = 0; i < pCurHcb->HCS_MaxTar; tcsp++, i++) { - tcsp->Flags &= ~(TCF_SYNC_DONE|TCF_WDTR_DONE); - } /* for */ -#endif - - if (hwInitialized) { - /* Post_scsi_rst: clean up active SCB */ - /* clear sync done flag */ - dbgPrint0(0,"tul_reset_scsi:call tul_post_scsi_rst\n"); - tul_post_scsi_rst(hcsp); - } - -#if NEWCHIP_BUG0 - TUL_WR(hcsp->Base+TUL_STest1, 0x22); -#endif - - return; - - /* Post_scsi_rst: clean up active SCB */ - pCurHcb->HCS_ActScb = 0; - pCurHcb->HCS_ActTcs = 0; - - while ((pCurScb = tul_pop_busy_scb(pCurHcb)) != NULL) - { -// pCurScb->SCB_Status = SCB_DONE; - pCurScb->SCB_HaStat = HOST_BAD_PHAS; - tul_append_done_scb(pCurHcb, pCurScb); - } - /* clear sync done flag */ - pCurTcb = &pCurHcb->HCS_Tcs[0]; - for (i = 0; i < 8; pCurTcb++, i++) { - pCurTcb->TCS_Flags &= (BYTE)~(TCF_SYNC_DONE|TCF_WDTR_DONE); - /* Initialize the sync. xfer register values to an asyn xfer */ - pCurTcb->TCS_JS_Period = 5; /* Async xfer before nego. */ - pCurTcb->TCS_JS_Offset = 0x0; /* Async xfer before nego. */ - pCurTcb->TCS_JS_Config3 = 0x8; /* Fast clock */ - } /* for */ - -#endif - return (SCSI_RESET_SUCCESS); -} - -/***************************************************************************/ -int init_tulip(HCS *pCurHcb, SCB *scbp, int tul_num_scb, BYTE *pbBiosAdr, int seconds) -{ - int i; - WORD *pwFlags; - BYTE *pbHeads; - SCB *pTmpScb, *pPrevScb = NULL; - - pCurHcb->HCS_NumScbs = tul_num_scb; - pCurHcb->HCS_Semaph = 1; - pCurHcb->HCS_JSStatus0 = 0; - pCurHcb->HCS_Scb = scbp; - pCurHcb->HCS_NxtPend = scbp; - pCurHcb->HCS_NxtAvail = scbp; - for (i = 0, pTmpScb = scbp; i < tul_num_scb; i++, pTmpScb++) - { - pTmpScb->SCB_TagId = i; - if (i != 0) - pPrevScb->SCB_NxtScb = pTmpScb; - pPrevScb = pTmpScb; - } - pPrevScb->SCB_NxtScb = NULL; - pCurHcb->HCS_ScbEnd = pTmpScb; - pCurHcb->HCS_FirstAvail = scbp; - pCurHcb->HCS_LastAvail = pPrevScb; - pCurHcb->HCS_FirstPend = NULL; - pCurHcb->HCS_LastPend = NULL; - pCurHcb->HCS_FirstBusy = NULL; - pCurHcb->HCS_LastBusy = NULL; - pCurHcb->HCS_FirstDone = NULL; - pCurHcb->HCS_LastDone = NULL; - pCurHcb->HCS_ActScb = NULL; - pCurHcb->HCS_ActTcs = NULL; - - tul_read_eeprom( pCurHcb->HCS_Base ); - /*---------- get H/A configuration -------------*/ - if (i91unvramp->NVM_SCSIInfo[0].NVM_NumOfTarg == 8) - pCurHcb->HCS_MaxTar = 8; - else - pCurHcb->HCS_MaxTar = 16; + tul_read_eeprom(pCurHcb->HCS_Base); +/*---------- get H/A configuration -------------*/ + if (i91unvramp->NVM_SCSIInfo[0].NVM_NumOfTarg == 8) + pCurHcb->HCS_MaxTar = 8; + else + pCurHcb->HCS_MaxTar = 16; - pCurHcb->HCS_Config = i91unvramp->NVM_SCSIInfo[0].NVM_ChConfig1; + pCurHcb->HCS_Config = i91unvramp->NVM_SCSIInfo[0].NVM_ChConfig1; - pCurHcb->HCS_SCSI_ID = i91unvramp->NVM_SCSIInfo[0].NVM_ChSCSIID; - pCurHcb->HCS_IdMask = ~(1 << pCurHcb->HCS_SCSI_ID); + pCurHcb->HCS_SCSI_ID = i91unvramp->NVM_SCSIInfo[0].NVM_ChSCSIID; + pCurHcb->HCS_IdMask = ~(1 << pCurHcb->HCS_SCSI_ID); #if CHK_PARITY - /* Enable parity error response */ - TUL_WR(pCurHcb->HCS_Base + TUL_PCMD, TUL_RD(pCurHcb->HCS_Base, TUL_PCMD) | 0x40); + /* Enable parity error response */ + TUL_WR(pCurHcb->HCS_Base + TUL_PCMD, TUL_RD(pCurHcb->HCS_Base, TUL_PCMD) | 0x40); #endif - /* Mask all the interrupt */ - TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x1F); + /* Mask all the interrupt */ + TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x1F); - tul_stop_bm(pCurHcb); - /* --- Initialize the tulip --- */ - TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_RST_CHIP); - - /* program HBA's SCSI ID */ - TUL_WR(pCurHcb->HCS_Base + TUL_SScsiId, pCurHcb->HCS_SCSI_ID << 4); + tul_stop_bm(pCurHcb); + /* --- Initialize the tulip --- */ + TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_RST_CHIP); + + /* program HBA's SCSI ID */ + TUL_WR(pCurHcb->HCS_Base + TUL_SScsiId, pCurHcb->HCS_SCSI_ID << 4); /* Enable Initiator Mode ,phase latch,alternate sync period mode, - disable SCSI reset */ - if (pCurHcb->HCS_Config & HCC_EN_PAR) - pCurHcb->HCS_SConf1 = (TSC_INITDEFAULT | TSC_EN_SCSI_PAR); - else - pCurHcb->HCS_SConf1 = (TSC_INITDEFAULT); - TUL_WR(pCurHcb->HCS_Base + TUL_SConfig, pCurHcb->HCS_SConf1); + disable SCSI reset */ + if (pCurHcb->HCS_Config & HCC_EN_PAR) + pCurHcb->HCS_SConf1 = (TSC_INITDEFAULT | TSC_EN_SCSI_PAR); + else + pCurHcb->HCS_SConf1 = (TSC_INITDEFAULT); + TUL_WR(pCurHcb->HCS_Base + TUL_SConfig, pCurHcb->HCS_SConf1); - /* Enable HW reselect */ - TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl1, TSC_HW_RESELECT ); + /* Enable HW reselect */ + TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl1, TSC_HW_RESELECT); - TUL_WR(pCurHcb->HCS_Base + TUL_SPeriod, 0); + TUL_WR(pCurHcb->HCS_Base + TUL_SPeriod, 0); /* selection time out = 250 ms */ - TUL_WR(pCurHcb->HCS_Base + TUL_STimeOut, 153); + TUL_WR(pCurHcb->HCS_Base + TUL_STimeOut, 153); - /*--------- Enable SCSI terminator -----*/ - TUL_WR(pCurHcb->HCS_Base + TUL_XCtrl, (pCurHcb->HCS_Config & (HCC_ACT_TERM1 | HCC_ACT_TERM2))); - TUL_WR(pCurHcb->HCS_Base + TUL_GCTRL1, - ((pCurHcb->HCS_Config & HCC_AUTO_TERM) >> 4) | (TUL_RD(pCurHcb->HCS_Base, TUL_GCTRL1) & 0xFE)); - -// dBiosAdr += 0x180; - for (i = 0, - pwFlags = (WORD *) &(i91unvramp->NVM_SCSIInfo[0].NVM_Targ0Config), -// pbHeads = (BYTE *)(dBiosAdr); - pbHeads = pbBiosAdr+0x180; - i < pCurHcb->HCS_MaxTar; - i++, pwFlags++) - { - pCurHcb->HCS_Tcs[i].TCS_Flags = *pwFlags & ~(TCF_SYNC_DONE | TCF_WDTR_DONE); - if (pCurHcb->HCS_Tcs[i].TCS_Flags & TCF_EN_255) - pCurHcb->HCS_Tcs[i].TCS_DrvFlags = TCF_DRV_255_63; - else - pCurHcb->HCS_Tcs[i].TCS_DrvFlags = 0; - pCurHcb->HCS_Tcs[i].TCS_JS_Period = 0; - pCurHcb->HCS_Tcs[i].TCS_SConfig0 = pCurHcb->HCS_SConf1; - pCurHcb->HCS_Tcs[i].TCS_DrvHead = *pbHeads++; - if (pCurHcb->HCS_Tcs[i].TCS_DrvHead == 255) - pCurHcb->HCS_Tcs[i].TCS_DrvFlags = TCF_DRV_255_63; - else - pCurHcb->HCS_Tcs[i].TCS_DrvFlags = 0; - pCurHcb->HCS_Tcs[i].TCS_DrvSector = *pbHeads++; - pCurHcb->HCS_Tcs[i].TCS_Flags &= ~TCF_BUSY; - pCurHcb->HCS_ActTags[i] = 0; - pCurHcb->HCS_MaxTags[i] = 0xFF; - } /* for */ -#if 1 - printk("i91u: PCI Base=0x%04X, IRQ=%d, BIOS=0x%04X0, SCSI ID=%d\n", - pCurHcb->HCS_Base, pCurHcb->HCS_Intr, - pCurHcb->HCS_BIOS, pCurHcb->HCS_SCSI_ID); -#endif - /*------------------- reset SCSI Bus ---------------------------*/ - if (pCurHcb->HCS_Config & HCC_SCSI_RESET) - { -#if 1 - printk("i91u: Reset SCSI Bus ... \n"); -#endif - tul_reset_scsi(pCurHcb, seconds); - } - TUL_WR(pCurHcb->HCS_Base + TUL_SCFG1, 0x17); - TUL_WR(pCurHcb->HCS_Base + TUL_SIntEnable, 0xE9); - return(0); +/*--------- Enable SCSI terminator -----*/ + TUL_WR(pCurHcb->HCS_Base + TUL_XCtrl, (pCurHcb->HCS_Config & (HCC_ACT_TERM1 | HCC_ACT_TERM2))); + TUL_WR(pCurHcb->HCS_Base + TUL_GCTRL1, + ((pCurHcb->HCS_Config & HCC_AUTO_TERM) >> 4) | (TUL_RD(pCurHcb->HCS_Base, TUL_GCTRL1) & 0xFE)); + + for (i = 0, + pwFlags = (WORD *) & (i91unvramp->NVM_SCSIInfo[0].NVM_Targ0Config), + pbHeads = pbBiosAdr + 0x180; + i < pCurHcb->HCS_MaxTar; + i++, pwFlags++) { + pCurHcb->HCS_Tcs[i].TCS_Flags = *pwFlags & ~(TCF_SYNC_DONE | TCF_WDTR_DONE); + if (pCurHcb->HCS_Tcs[i].TCS_Flags & TCF_EN_255) + pCurHcb->HCS_Tcs[i].TCS_DrvFlags = TCF_DRV_255_63; + else + pCurHcb->HCS_Tcs[i].TCS_DrvFlags = 0; + pCurHcb->HCS_Tcs[i].TCS_JS_Period = 0; + pCurHcb->HCS_Tcs[i].TCS_SConfig0 = pCurHcb->HCS_SConf1; + pCurHcb->HCS_Tcs[i].TCS_DrvHead = *pbHeads++; + if (pCurHcb->HCS_Tcs[i].TCS_DrvHead == 255) + pCurHcb->HCS_Tcs[i].TCS_DrvFlags = TCF_DRV_255_63; + else + pCurHcb->HCS_Tcs[i].TCS_DrvFlags = 0; + pCurHcb->HCS_Tcs[i].TCS_DrvSector = *pbHeads++; + pCurHcb->HCS_Tcs[i].TCS_Flags &= ~TCF_BUSY; + pCurHcb->HCS_ActTags[i] = 0; + pCurHcb->HCS_MaxTags[i] = 0xFF; + } /* for */ + printk("i91u: PCI Base=0x%04X, IRQ=%d, BIOS=0x%04X0, SCSI ID=%d\n", + pCurHcb->HCS_Base, pCurHcb->HCS_Intr, + pCurHcb->HCS_BIOS, pCurHcb->HCS_SCSI_ID); +/*------------------- reset SCSI Bus ---------------------------*/ + if (pCurHcb->HCS_Config & HCC_SCSI_RESET) { + printk("i91u: Reset SCSI Bus ... \n"); + tul_reset_scsi(pCurHcb, seconds); + } + TUL_WR(pCurHcb->HCS_Base + TUL_SCFG1, 0x17); + TUL_WR(pCurHcb->HCS_Base + TUL_SIntEnable, 0xE9); + return (0); } /***************************************************************************/ -SCB *tul_alloc_scb(HCS *hcsp) -{ - SCB *pTmpScb; - ULONG flags; - - save_flags(flags); - cli(); - if ((pTmpScb = hcsp->HCS_FirstAvail) != NULL) - { +SCB *tul_alloc_scb(HCS * hcsp) +{ + SCB *pTmpScb; + ULONG flags; +#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95) + spin_lock_irqsave(&(hcsp->HCS_AvailLock), flags); +#else + save_flags(flags); + cli(); +#endif + if ((pTmpScb = hcsp->HCS_FirstAvail) != NULL) { #if DEBUG_QUEUE - printk("find scb at %08lx\n", (ULONG) pTmpScb); + printk("find scb at %08lx\n", (ULONG) pTmpScb); #endif - if ((hcsp->HCS_FirstAvail = pTmpScb->SCB_NxtScb) == NULL) - hcsp->HCS_LastAvail = NULL; - pTmpScb->SCB_NxtScb = NULL; - pTmpScb->SCB_Status = SCB_RENT; + if ((hcsp->HCS_FirstAvail = pTmpScb->SCB_NxtScb) == NULL) + hcsp->HCS_LastAvail = NULL; + pTmpScb->SCB_NxtScb = NULL; + pTmpScb->SCB_Status = SCB_RENT; } - restore_flags(flags); - return (pTmpScb); +#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95) + spin_unlock_irqrestore(&(hcsp->HCS_AvailLock), flags); +#else + restore_flags(flags); +#endif + return (pTmpScb); } /***************************************************************************/ -void tul_release_scb(HCS *hcsp, SCB *scbp) +void tul_release_scb(HCS * hcsp, SCB * scbp) { - ULONG flags; + ULONG flags; #if DEBUG_QUEUE -printk("Release SCB %lx; ", (ULONG) scbp); + printk("Release SCB %lx; ", (ULONG) scbp); #endif - save_flags(flags); - cli(); - scbp->SCB_Srb = 0; - scbp->SCB_Status = 0; - scbp->SCB_NxtScb = NULL; - if (hcsp->HCS_LastAvail != NULL) - { - hcsp->HCS_LastAvail->SCB_NxtScb = scbp; - hcsp->HCS_LastAvail = scbp; - } - else - { - hcsp->HCS_FirstAvail = scbp; - hcsp->HCS_LastAvail = scbp; +#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95) + spin_lock_irqsave(&(hcsp->HCS_AvailLock), flags); +#else + save_flags(flags); + cli(); +#endif + scbp->SCB_Srb = 0; + scbp->SCB_Status = 0; + scbp->SCB_NxtScb = NULL; + if (hcsp->HCS_LastAvail != NULL) { + hcsp->HCS_LastAvail->SCB_NxtScb = scbp; + hcsp->HCS_LastAvail = scbp; + } else { + hcsp->HCS_FirstAvail = scbp; + hcsp->HCS_LastAvail = scbp; } - restore_flags(flags); +#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95) + spin_unlock_irqrestore(&(hcsp->HCS_AvailLock), flags); +#else + restore_flags(flags); +#endif } /***************************************************************************/ -void tul_append_pend_scb(HCS *pCurHcb, SCB *scbp) +void tul_append_pend_scb(HCS * pCurHcb, SCB * scbp) { #if DEBUG_QUEUE -printk("Append pend SCB %lx; ", (ULONG) scbp); + printk("Append pend SCB %lx; ", (ULONG) scbp); #endif - scbp->SCB_Status = SCB_PEND; - scbp->SCB_NxtScb = NULL; - if (pCurHcb->HCS_LastPend != NULL) - { - pCurHcb->HCS_LastPend->SCB_NxtScb = scbp; - pCurHcb->HCS_LastPend = scbp; - } - else - { - pCurHcb->HCS_FirstPend = scbp; - pCurHcb->HCS_LastPend = scbp; + scbp->SCB_Status = SCB_PEND; + scbp->SCB_NxtScb = NULL; + if (pCurHcb->HCS_LastPend != NULL) { + pCurHcb->HCS_LastPend->SCB_NxtScb = scbp; + pCurHcb->HCS_LastPend = scbp; + } else { + pCurHcb->HCS_FirstPend = scbp; + pCurHcb->HCS_LastPend = scbp; } } /***************************************************************************/ -void tul_push_pend_scb(HCS *pCurHcb, SCB *scbp) +void tul_push_pend_scb(HCS * pCurHcb, SCB * scbp) { #if DEBUG_QUEUE -printk("Push pend SCB %lx; ", (ULONG) scbp); + printk("Push pend SCB %lx; ", (ULONG) scbp); #endif - scbp->SCB_Status = SCB_PEND; - if ((scbp->SCB_NxtScb = pCurHcb->HCS_FirstPend) != NULL) - { - pCurHcb->HCS_FirstPend = scbp; - } - else - { - pCurHcb->HCS_FirstPend = scbp; - pCurHcb->HCS_LastPend = scbp; + scbp->SCB_Status = SCB_PEND; + if ((scbp->SCB_NxtScb = pCurHcb->HCS_FirstPend) != NULL) { + pCurHcb->HCS_FirstPend = scbp; + } else { + pCurHcb->HCS_FirstPend = scbp; + pCurHcb->HCS_LastPend = scbp; } } /***************************************************************************/ -SCB *tul_find_first_pend_scb(HCS *pCurHcb) +SCB *tul_find_first_pend_scb(HCS * pCurHcb) { - SCB *pFirstPend; - + SCB *pFirstPend; - pFirstPend = pCurHcb->HCS_FirstPend; - while (pFirstPend != NULL) { - if (pFirstPend->SCB_Opcode != ExecSCSI) { - return (pFirstPend); - } - if (pFirstPend->SCB_TagMsg == 0) - { - if ((pCurHcb->HCS_ActTags[pFirstPend->SCB_Target] == 0) && - !(pCurHcb->HCS_Tcs[pFirstPend->SCB_Target].TCS_Flags & TCF_BUSY)) - { - return (pFirstPend); + pFirstPend = pCurHcb->HCS_FirstPend; + while (pFirstPend != NULL) { + if (pFirstPend->SCB_Opcode != ExecSCSI) { + return (pFirstPend); } - } - else - { - if ((pCurHcb->HCS_ActTags[pFirstPend->SCB_Target] >= - pCurHcb->HCS_MaxTags[pFirstPend->SCB_Target]) | - (pCurHcb->HCS_Tcs[pFirstPend->SCB_Target].TCS_Flags & TCF_BUSY)) - { - pFirstPend = pFirstPend->SCB_NxtScb; - continue; + if (pFirstPend->SCB_TagMsg == 0) { + if ((pCurHcb->HCS_ActTags[pFirstPend->SCB_Target] == 0) && + !(pCurHcb->HCS_Tcs[pFirstPend->SCB_Target].TCS_Flags & TCF_BUSY)) { + return (pFirstPend); + } + } else { + if ((pCurHcb->HCS_ActTags[pFirstPend->SCB_Target] >= + pCurHcb->HCS_MaxTags[pFirstPend->SCB_Target]) | + (pCurHcb->HCS_Tcs[pFirstPend->SCB_Target].TCS_Flags & TCF_BUSY)) { + pFirstPend = pFirstPend->SCB_NxtScb; + continue; + } + return (pFirstPend); } - return (pFirstPend); - } - pFirstPend = pFirstPend->SCB_NxtScb; + pFirstPend = pFirstPend->SCB_NxtScb; } - return (pFirstPend); + return (pFirstPend); } /***************************************************************************/ -SCB *tul_pop_pend_scb(HCS *pCurHcb) +SCB *tul_pop_pend_scb(HCS * pCurHcb) { - SCB *pTmpScb; + SCB *pTmpScb; - if ((pTmpScb = pCurHcb->HCS_FirstPend) != NULL) - { - if ((pCurHcb->HCS_FirstPend = pTmpScb->SCB_NxtScb) == NULL) - pCurHcb->HCS_LastPend = NULL; - pTmpScb->SCB_NxtScb = NULL; + if ((pTmpScb = pCurHcb->HCS_FirstPend) != NULL) { + if ((pCurHcb->HCS_FirstPend = pTmpScb->SCB_NxtScb) == NULL) + pCurHcb->HCS_LastPend = NULL; + pTmpScb->SCB_NxtScb = NULL; } #if DEBUG_QUEUE -printk("Pop pend SCB %lx; ", (ULONG) pTmpScb); + printk("Pop pend SCB %lx; ", (ULONG) pTmpScb); #endif - return (pTmpScb); + return (pTmpScb); } /***************************************************************************/ -void tul_unlink_pend_scb(HCS *pCurHcb, SCB *pCurScb) +void tul_unlink_pend_scb(HCS * pCurHcb, SCB * pCurScb) { - SCB *pTmpScb, *pPrevScb; + SCB *pTmpScb, *pPrevScb; #if DEBUG_QUEUE -printk("unlink pend SCB %lx; ", (ULONG) pCurScb); + printk("unlink pend SCB %lx; ", (ULONG) pCurScb); #endif - pPrevScb = pTmpScb = pCurHcb->HCS_FirstPend; - while (pTmpScb != NULL) - { - if (pCurScb == pTmpScb) - { /* Unlink this SCB */ - if (pTmpScb == pCurHcb->HCS_FirstPend) - { - if ((pCurHcb->HCS_FirstPend = pTmpScb->SCB_NxtScb) == NULL) - pCurHcb->HCS_LastPend = NULL; - } - else - { - pPrevScb->SCB_NxtScb = pTmpScb->SCB_NxtScb; - if (pTmpScb == pCurHcb->HCS_LastPend) - pCurHcb->HCS_LastPend = pPrevScb; + pPrevScb = pTmpScb = pCurHcb->HCS_FirstPend; + while (pTmpScb != NULL) { + if (pCurScb == pTmpScb) { /* Unlink this SCB */ + if (pTmpScb == pCurHcb->HCS_FirstPend) { + if ((pCurHcb->HCS_FirstPend = pTmpScb->SCB_NxtScb) == NULL) + pCurHcb->HCS_LastPend = NULL; + } else { + pPrevScb->SCB_NxtScb = pTmpScb->SCB_NxtScb; + if (pTmpScb == pCurHcb->HCS_LastPend) + pCurHcb->HCS_LastPend = pPrevScb; + } + pTmpScb->SCB_NxtScb = NULL; + break; } - pTmpScb->SCB_NxtScb = NULL; - break; - } - pPrevScb = pTmpScb; - pTmpScb = pTmpScb->SCB_NxtScb; + pPrevScb = pTmpScb; + pTmpScb = pTmpScb->SCB_NxtScb; } - return; + return; } /***************************************************************************/ -void tul_append_busy_scb(HCS *pCurHcb, SCB *scbp) +void tul_append_busy_scb(HCS * pCurHcb, SCB * scbp) { #if DEBUG_QUEUE -printk("append busy SCB %lx; ", (ULONG) scbp); + printk("append busy SCB %lx; ", (ULONG) scbp); #endif - if (scbp->SCB_TagMsg) - pCurHcb->HCS_ActTags[scbp->SCB_Target]++; - else - pCurHcb->HCS_Tcs[scbp->SCB_Target].TCS_Flags |= TCF_BUSY; - scbp->SCB_Status = SCB_BUSY; - scbp->SCB_NxtScb = NULL; - if (pCurHcb->HCS_LastBusy != NULL) - { - pCurHcb->HCS_LastBusy->SCB_NxtScb = scbp; - pCurHcb->HCS_LastBusy = scbp; - } - else - { - pCurHcb->HCS_FirstBusy = scbp; - pCurHcb->HCS_LastBusy = scbp; + if (scbp->SCB_TagMsg) + pCurHcb->HCS_ActTags[scbp->SCB_Target]++; + else + pCurHcb->HCS_Tcs[scbp->SCB_Target].TCS_Flags |= TCF_BUSY; + scbp->SCB_Status = SCB_BUSY; + scbp->SCB_NxtScb = NULL; + if (pCurHcb->HCS_LastBusy != NULL) { + pCurHcb->HCS_LastBusy->SCB_NxtScb = scbp; + pCurHcb->HCS_LastBusy = scbp; + } else { + pCurHcb->HCS_FirstBusy = scbp; + pCurHcb->HCS_LastBusy = scbp; } } /***************************************************************************/ -SCB *tul_pop_busy_scb(HCS *pCurHcb) +SCB *tul_pop_busy_scb(HCS * pCurHcb) { - SCB *pTmpScb; + SCB *pTmpScb; - if ((pTmpScb = pCurHcb->HCS_FirstBusy) != NULL) - { - if ((pCurHcb->HCS_FirstBusy = pTmpScb->SCB_NxtScb) == NULL) - pCurHcb->HCS_LastBusy = NULL; - pTmpScb->SCB_NxtScb = NULL; - if (pTmpScb->SCB_TagMsg) - pCurHcb->HCS_ActTags[pTmpScb->SCB_Target]--; - else - pCurHcb->HCS_Tcs[pTmpScb->SCB_Target].TCS_Flags &= ~TCF_BUSY; + if ((pTmpScb = pCurHcb->HCS_FirstBusy) != NULL) { + if ((pCurHcb->HCS_FirstBusy = pTmpScb->SCB_NxtScb) == NULL) + pCurHcb->HCS_LastBusy = NULL; + pTmpScb->SCB_NxtScb = NULL; + if (pTmpScb->SCB_TagMsg) + pCurHcb->HCS_ActTags[pTmpScb->SCB_Target]--; + else + pCurHcb->HCS_Tcs[pTmpScb->SCB_Target].TCS_Flags &= ~TCF_BUSY; } #if DEBUG_QUEUE -printk("Pop busy SCB %lx; ", (ULONG) pTmpScb); + printk("Pop busy SCB %lx; ", (ULONG) pTmpScb); #endif - return (pTmpScb); + return (pTmpScb); } /***************************************************************************/ -void tul_unlink_busy_scb(HCS *pCurHcb, SCB *pCurScb) +void tul_unlink_busy_scb(HCS * pCurHcb, SCB * pCurScb) { - SCB *pTmpScb, *pPrevScb; + SCB *pTmpScb, *pPrevScb; #if DEBUG_QUEUE -printk("unlink busy SCB %lx; ", (ULONG) pCurScb); + printk("unlink busy SCB %lx; ", (ULONG) pCurScb); #endif - pPrevScb = pTmpScb = pCurHcb->HCS_FirstBusy; - while (pTmpScb != NULL) - { - if (pCurScb == pTmpScb) - { /* Unlink this SCB */ - if (pTmpScb == pCurHcb->HCS_FirstBusy) - { - if ((pCurHcb->HCS_FirstBusy = pTmpScb->SCB_NxtScb) == NULL) - pCurHcb->HCS_LastBusy = NULL; + pPrevScb = pTmpScb = pCurHcb->HCS_FirstBusy; + while (pTmpScb != NULL) { + if (pCurScb == pTmpScb) { /* Unlink this SCB */ + if (pTmpScb == pCurHcb->HCS_FirstBusy) { + if ((pCurHcb->HCS_FirstBusy = pTmpScb->SCB_NxtScb) == NULL) + pCurHcb->HCS_LastBusy = NULL; + } else { + pPrevScb->SCB_NxtScb = pTmpScb->SCB_NxtScb; + if (pTmpScb == pCurHcb->HCS_LastBusy) + pCurHcb->HCS_LastBusy = pPrevScb; + } + pTmpScb->SCB_NxtScb = NULL; + if (pTmpScb->SCB_TagMsg) + pCurHcb->HCS_ActTags[pTmpScb->SCB_Target]--; + else + pCurHcb->HCS_Tcs[pTmpScb->SCB_Target].TCS_Flags &= ~TCF_BUSY; + break; } - else - { - pPrevScb->SCB_NxtScb = pTmpScb->SCB_NxtScb; - if (pTmpScb == pCurHcb->HCS_LastBusy) - pCurHcb->HCS_LastBusy = pPrevScb; - } - pTmpScb->SCB_NxtScb = NULL; - if (pTmpScb->SCB_TagMsg) - pCurHcb->HCS_ActTags[pTmpScb->SCB_Target]--; - else - pCurHcb->HCS_Tcs[pTmpScb->SCB_Target].TCS_Flags &= ~TCF_BUSY; - break; - } - pPrevScb = pTmpScb; - pTmpScb = pTmpScb->SCB_NxtScb; - } - return; + pPrevScb = pTmpScb; + pTmpScb = pTmpScb->SCB_NxtScb; + } + return; } /***************************************************************************/ -SCB *tul_find_busy_scb(HCS *pCurHcb, WORD tarlun) -{ - SCB *pTmpScb, *pPrevScb; - WORD scbp_tarlun; - - - pPrevScb = pTmpScb = pCurHcb->HCS_FirstBusy; - while (pTmpScb != NULL) - { - scbp_tarlun = (pTmpScb->SCB_Lun << 8) | (pTmpScb->SCB_Target); - if (scbp_tarlun == tarlun) - { /* Unlink this SCB */ -#if 0 - if (pTmpScb == pCurHcb->HCS_FirstBusy) - { - if ((pCurHcb->HCS_FirstBusy = pTmpScb->SCB_NxtScb) == NULL) - pCurHcb->HCS_LastBusy = NULL; +SCB *tul_find_busy_scb(HCS * pCurHcb, WORD tarlun) +{ + SCB *pTmpScb, *pPrevScb; + WORD scbp_tarlun; + + + pPrevScb = pTmpScb = pCurHcb->HCS_FirstBusy; + while (pTmpScb != NULL) { + scbp_tarlun = (pTmpScb->SCB_Lun << 8) | (pTmpScb->SCB_Target); + if (scbp_tarlun == tarlun) { /* Unlink this SCB */ + break; } - else - { - pPrevScb->SCB_NxtScb = pTmpScb->SCB_NxtScb; - if (pTmpScb == pCurHcb->HCS_LastBusy) - pCurHcb->HCS_LastBusy = pPrevScb; - } - pTmpScb->SCB_NxtScb = NULL; -#endif - break; - } - pPrevScb = pTmpScb; - pTmpScb = pTmpScb->SCB_NxtScb; + pPrevScb = pTmpScb; + pTmpScb = pTmpScb->SCB_NxtScb; } #if DEBUG_QUEUE -printk("find busy SCB %lx; ", (ULONG) pTmpScb); + printk("find busy SCB %lx; ", (ULONG) pTmpScb); #endif - return (pTmpScb); + return (pTmpScb); } /***************************************************************************/ -void tul_append_done_scb(HCS *pCurHcb, SCB *scbp) +void tul_append_done_scb(HCS * pCurHcb, SCB * scbp) { #if DEBUG_QUEUE -printk("append done SCB %lx; ", (ULONG) scbp); + printk("append done SCB %lx; ", (ULONG) scbp); #endif -/* tul_unlink_busy_scb(pCurHcb, scbp);*/ - scbp->SCB_Status = SCB_DONE; - scbp->SCB_NxtScb = NULL; - if (pCurHcb->HCS_LastDone != NULL) - { - pCurHcb->HCS_LastDone->SCB_NxtScb = scbp; - pCurHcb->HCS_LastDone = scbp; - } - else - { - pCurHcb->HCS_FirstDone = scbp; - pCurHcb->HCS_LastDone = scbp; + scbp->SCB_Status = SCB_DONE; + scbp->SCB_NxtScb = NULL; + if (pCurHcb->HCS_LastDone != NULL) { + pCurHcb->HCS_LastDone->SCB_NxtScb = scbp; + pCurHcb->HCS_LastDone = scbp; + } else { + pCurHcb->HCS_FirstDone = scbp; + pCurHcb->HCS_LastDone = scbp; } } /***************************************************************************/ -SCB *tul_find_done_scb(HCS *pCurHcb) +SCB *tul_find_done_scb(HCS * pCurHcb) { - SCB *pTmpScb; + SCB *pTmpScb; - if ((pTmpScb = pCurHcb->HCS_FirstDone) != NULL) - { - if ((pCurHcb->HCS_FirstDone = pTmpScb->SCB_NxtScb) == NULL) - pCurHcb->HCS_LastDone = NULL; - pTmpScb->SCB_NxtScb = NULL; + if ((pTmpScb = pCurHcb->HCS_FirstDone) != NULL) { + if ((pCurHcb->HCS_FirstDone = pTmpScb->SCB_NxtScb) == NULL) + pCurHcb->HCS_LastDone = NULL; + pTmpScb->SCB_NxtScb = NULL; } #if DEBUG_QUEUE -printk("find done SCB %lx; ", (ULONG) pTmpScb); + printk("find done SCB %lx; ", (ULONG) pTmpScb); #endif - return (pTmpScb); + return (pTmpScb); } /***************************************************************************/ -int tul_abort_srb(HCS *pCurHcb, ULONG srbp) +int tul_abort_srb(HCS * pCurHcb, ULONG srbp) { - ULONG flags; - SCB *pTmpScb, *pPrevScb; + ULONG flags; + SCB *pTmpScb, *pPrevScb; - save_flags(flags); - cli(); +#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95) + spin_lock_irqsave(&(pCurHcb->HCS_SemaphLock), flags); +#else + save_flags(flags); + cli(); +#endif - if ((pCurHcb->HCS_Semaph == 0) && (pCurHcb->HCS_ActScb == NULL)) { - TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x1F); - /* disable Jasmin SCSI Int */ - tulip_main(pCurHcb); + if ((pCurHcb->HCS_Semaph == 0) && (pCurHcb->HCS_ActScb == NULL)) { + TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x1F); + /* disable Jasmin SCSI Int */ + tulip_main(pCurHcb); - pCurHcb->HCS_Semaph = 1; - TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x0F); + pCurHcb->HCS_Semaph = 1; + TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x0F); - restore_flags(flags); +#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95) + spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags); +#else + restore_flags(flags); +#endif - return SCSI_ABORT_SNOOZE; - } + return SCSI_ABORT_SNOOZE; + } + pPrevScb = pTmpScb = pCurHcb->HCS_FirstPend; /* Check Pend queue */ + while (pTmpScb != NULL) { + /* 07/27/98 */ + if (pTmpScb->SCB_Srb == (unsigned char *) srbp) { + if (pTmpScb == pCurHcb->HCS_ActScb) { +#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95) + spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags); +#else + restore_flags(flags); +#endif + return SCSI_ABORT_BUSY; + } else if (pTmpScb == pCurHcb->HCS_FirstPend) { + if ((pCurHcb->HCS_FirstPend = pTmpScb->SCB_NxtScb) == NULL) + pCurHcb->HCS_LastPend = NULL; + } else { + pPrevScb->SCB_NxtScb = pTmpScb->SCB_NxtScb; + if (pTmpScb == pCurHcb->HCS_LastPend) + pCurHcb->HCS_LastPend = pPrevScb; + } + pTmpScb->SCB_HaStat = HOST_ABORTED; + pTmpScb->SCB_Flags |= SCF_DONE; + if (pTmpScb->SCB_Flags & SCF_POST) + (*pTmpScb->SCB_Post) ((BYTE *) pCurHcb, (BYTE *) pTmpScb); +#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95) + spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags); +#else + restore_flags(flags); +#endif + return SCSI_ABORT_SUCCESS; + } + pPrevScb = pTmpScb; + pTmpScb = pTmpScb->SCB_NxtScb; + } - pPrevScb = pTmpScb = pCurHcb->HCS_FirstPend; /* Check Pend queue */ - while (pTmpScb != NULL) - { - /* 07/27/98 */ - if (pTmpScb->SCB_Srb == (unsigned char *)srbp) { - if (pTmpScb == pCurHcb->HCS_ActScb) { - restore_flags(flags); - return SCSI_ABORT_BUSY; - } - else if (pTmpScb == pCurHcb->HCS_FirstPend) { - if ((pCurHcb->HCS_FirstPend = pTmpScb->SCB_NxtScb) == NULL) - pCurHcb->HCS_LastPend = NULL; - } - else { - pPrevScb->SCB_NxtScb = pTmpScb->SCB_NxtScb; - if (pTmpScb == pCurHcb->HCS_LastPend) - pCurHcb->HCS_LastPend = pPrevScb; - } - pTmpScb->SCB_HaStat = HOST_ABORTED; - pTmpScb->SCB_Flags |= SCF_DONE; - if (pTmpScb->SCB_Flags & SCF_POST) - (*pTmpScb->SCB_Post)((BYTE *) pCurHcb, (BYTE *) pTmpScb); - restore_flags(flags); - return SCSI_ABORT_SUCCESS ; - } - pPrevScb = pTmpScb; - pTmpScb = pTmpScb->SCB_NxtScb; - } - - pPrevScb = pTmpScb = pCurHcb->HCS_FirstBusy; /* Check Busy queue */ - while (pTmpScb != NULL) { - - if (pTmpScb->SCB_Srb == (unsigned char *)srbp) { - - if (pTmpScb == pCurHcb->HCS_ActScb) { - restore_flags(flags); - return SCSI_ABORT_BUSY; - } - else if (pTmpScb->SCB_TagMsg == 0) { - restore_flags(flags); - return SCSI_ABORT_BUSY; - } - else { - pCurHcb->HCS_ActTags[pTmpScb->SCB_Target]--; - if (pTmpScb == pCurHcb->HCS_FirstBusy) { - if ((pCurHcb->HCS_FirstBusy = pTmpScb->SCB_NxtScb) == NULL) - pCurHcb->HCS_LastBusy = NULL; - } - else { - pPrevScb->SCB_NxtScb = pTmpScb->SCB_NxtScb; - if (pTmpScb == pCurHcb->HCS_LastBusy) - pCurHcb->HCS_LastBusy = pPrevScb; - } - pTmpScb->SCB_NxtScb = NULL; - - - pTmpScb->SCB_HaStat = HOST_ABORTED; - pTmpScb->SCB_Flags |= SCF_DONE; - if (pTmpScb->SCB_Flags & SCF_POST) - (*pTmpScb->SCB_Post)((BYTE *) pCurHcb, (BYTE *) pTmpScb); - restore_flags(flags); - return SCSI_ABORT_SUCCESS ; - } - } - pPrevScb = pTmpScb; - pTmpScb = pTmpScb->SCB_NxtScb; - } - restore_flags(flags); - return (SCSI_ABORT_NOT_RUNNING); + pPrevScb = pTmpScb = pCurHcb->HCS_FirstBusy; /* Check Busy queue */ + while (pTmpScb != NULL) { + + if (pTmpScb->SCB_Srb == (unsigned char *) srbp) { + + if (pTmpScb == pCurHcb->HCS_ActScb) { +#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95) + spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags); +#else + restore_flags(flags); +#endif + return SCSI_ABORT_BUSY; + } else if (pTmpScb->SCB_TagMsg == 0) { +#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95) + spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags); +#else + restore_flags(flags); +#endif + return SCSI_ABORT_BUSY; + } else { + pCurHcb->HCS_ActTags[pTmpScb->SCB_Target]--; + if (pTmpScb == pCurHcb->HCS_FirstBusy) { + if ((pCurHcb->HCS_FirstBusy = pTmpScb->SCB_NxtScb) == NULL) + pCurHcb->HCS_LastBusy = NULL; + } else { + pPrevScb->SCB_NxtScb = pTmpScb->SCB_NxtScb; + if (pTmpScb == pCurHcb->HCS_LastBusy) + pCurHcb->HCS_LastBusy = pPrevScb; + } + pTmpScb->SCB_NxtScb = NULL; + + + pTmpScb->SCB_HaStat = HOST_ABORTED; + pTmpScb->SCB_Flags |= SCF_DONE; + if (pTmpScb->SCB_Flags & SCF_POST) + (*pTmpScb->SCB_Post) ((BYTE *) pCurHcb, (BYTE *) pTmpScb); +#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95) + spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags); +#else + restore_flags(flags); +#endif + return SCSI_ABORT_SUCCESS; + } + } + pPrevScb = pTmpScb; + pTmpScb = pTmpScb->SCB_NxtScb; + } +#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95) + spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags); +#else + restore_flags(flags); +#endif + return (SCSI_ABORT_NOT_RUNNING); } /***************************************************************************/ -int tul_bad_seq(HCS *pCurHcb) +int tul_bad_seq(HCS * pCurHcb) { - SCB *pCurScb; + SCB *pCurScb; -#if 1 -printk("tul_bad_seg c=%d\n", pCurHcb->HCS_Index); -#endif - if ((pCurScb = pCurHcb->HCS_ActScb) != NULL) - { - tul_unlink_busy_scb(pCurHcb, pCurScb); - pCurScb->SCB_HaStat = HOST_BAD_PHAS; - pCurScb->SCB_TaStat = 0; -// pCurScb->SCB_Status = SCB_DONE; /* Done */ - tul_append_done_scb(pCurHcb, pCurScb); - } + printk("tul_bad_seg c=%d\n", pCurHcb->HCS_Index); - tul_stop_bm(pCurHcb); + if ((pCurScb = pCurHcb->HCS_ActScb) != NULL) { + tul_unlink_busy_scb(pCurHcb, pCurScb); + pCurScb->SCB_HaStat = HOST_BAD_PHAS; + pCurScb->SCB_TaStat = 0; + tul_append_done_scb(pCurHcb, pCurScb); + } + tul_stop_bm(pCurHcb); - tul_reset_scsi(pCurHcb, 8); /* 7/29/98 */ + tul_reset_scsi(pCurHcb, 8); /* 7/29/98 */ - return (tul_post_scsi_rst(pCurHcb)); + return (tul_post_scsi_rst(pCurHcb)); } /************************************************************************/ -int tul_device_reset(HCS *pCurHcb, ULONG pSrb, unsigned int target, unsigned int ResetFlags) +int tul_device_reset(HCS * pCurHcb, ULONG pSrb, unsigned int target, unsigned int ResetFlags) { - ULONG flags; - SCB *pScb; - -#if 0 -printk("tul_device_reset c=%d %d \n", pCurHcb->HCS_Index, pCurHcb->HCS_Semaph); + ULONG flags; + SCB *pScb; +#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95) + spin_lock_irqsave(&(pCurHcb->HCS_SemaphLock), flags); +#else + save_flags(flags); + cli(); #endif - save_flags(flags); - cli(); + if (ResetFlags & SCSI_RESET_ASYNCHRONOUS) { + if ((pCurHcb->HCS_Semaph == 0) && (pCurHcb->HCS_ActScb == NULL)) { + TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x1F); + /* disable Jasmin SCSI Int */ + tulip_main(pCurHcb); - if (ResetFlags & SCSI_RESET_ASYNCHRONOUS) { + pCurHcb->HCS_Semaph = 1; + TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x0F); - if ((pCurHcb->HCS_Semaph == 0) && (pCurHcb->HCS_ActScb == NULL)) { - TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x1F); - /* disable Jasmin SCSI Int */ - tulip_main(pCurHcb); - - pCurHcb->HCS_Semaph = 1; - TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x0F); - - restore_flags(flags); +#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95) + spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags); +#else + restore_flags(flags); +#endif - return SCSI_RESET_SNOOZE ; - } + return SCSI_RESET_SNOOZE; + } + pScb = pCurHcb->HCS_FirstBusy; /* Check Busy queue */ + while (pScb != NULL) { + if (pScb->SCB_Srb == (unsigned char *) pSrb) + break; + pScb = pScb->SCB_NxtScb; + } + if (pScb == NULL) { + printk("Unable to Reset - No SCB Found\n"); - pScb = pCurHcb->HCS_FirstBusy; /* Check Busy queue */ - while (pScb != NULL) { - if (pScb->SCB_Srb == (unsigned char *)pSrb) - break; - pScb = pScb->SCB_NxtScb; +#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95) + spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags); +#else + restore_flags(flags); +#endif + return SCSI_RESET_NOT_RUNNING; + } } - if (pScb == NULL) { - printk("Unable to Reset - No SCB Found\n"); - - restore_flags(flags); - return SCSI_RESET_NOT_RUNNING; + if ((pScb = tul_alloc_scb(pCurHcb)) == NULL) { +#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95) + spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags); +#else + restore_flags(flags); +#endif + return SCSI_RESET_NOT_RUNNING; } - } - if ((pScb = tul_alloc_scb(pCurHcb)) == NULL) { - restore_flags(flags); - return SCSI_RESET_NOT_RUNNING; - } - pScb->SCB_Opcode = BusDevRst; - pScb->SCB_Flags = SCF_POST; - pScb->SCB_Target = target; - pScb->SCB_Mode = 0; + pScb->SCB_Opcode = BusDevRst; + pScb->SCB_Flags = SCF_POST; + pScb->SCB_Target = target; + pScb->SCB_Mode = 0; - pScb->SCB_Srb = 0; - if (ResetFlags & SCSI_RESET_SYNCHRONOUS) - { - pScb->SCB_Srb = (unsigned char *)pSrb; - } - tul_push_pend_scb(pCurHcb,pScb); /* push this SCB to Pending queue */ + pScb->SCB_Srb = 0; + if (ResetFlags & SCSI_RESET_SYNCHRONOUS) { + pScb->SCB_Srb = (unsigned char *) pSrb; + } + tul_push_pend_scb(pCurHcb, pScb); /* push this SCB to Pending queue */ - if (pCurHcb->HCS_Semaph == 1) { - TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x1F); - /* disable Jasmin SCSI Int */ - pCurHcb->HCS_Semaph = 0; + if (pCurHcb->HCS_Semaph == 1) { + TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x1F); + /* disable Jasmin SCSI Int */ + pCurHcb->HCS_Semaph = 0; - tulip_main(pCurHcb); + tulip_main(pCurHcb); - pCurHcb->HCS_Semaph = 1; - TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x0F); + pCurHcb->HCS_Semaph = 1; + TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x0F); } - restore_flags(flags); - return SCSI_RESET_PENDING; - - +#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95) + spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags); +#else + restore_flags(flags); +#endif + return SCSI_RESET_PENDING; } -int tul_reset_scsi_bus(HCS *pCurHcb) +int tul_reset_scsi_bus(HCS * pCurHcb) { - ULONG flags; + ULONG flags; -#if 0 -printk("tul_reset_scsi_bus c=%d %d \n", pCurHcb->HCS_Index, pCurHcb->HCS_Semaph); +#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95) + spin_lock_irqsave(&(pCurHcb->HCS_SemaphLock), flags); +#else + save_flags(flags); + cli(); #endif + TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x1F); + pCurHcb->HCS_Semaph = 0; - save_flags(flags); - cli(); - TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x1F); - pCurHcb->HCS_Semaph = 0; - - restore_flags(flags); - - tul_stop_bm(pCurHcb); +#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95) + spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags); +#else + restore_flags(flags); +#endif - tul_reset_scsi(pCurHcb, 2); /* 7/29/98 */ + tul_stop_bm(pCurHcb); - save_flags(flags); - cli(); - tul_post_scsi_rst(pCurHcb); + tul_reset_scsi(pCurHcb, 2); /* 7/29/98 */ -// tul_do_pause(7*100); +#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95) + spin_lock_irqsave(&(pCurHcb->HCS_SemaphLock), flags); +#else + save_flags(flags); + cli(); +#endif + tul_post_scsi_rst(pCurHcb); - tulip_main(pCurHcb); + tulip_main(pCurHcb); - pCurHcb->HCS_Semaph = 1; - TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x0F); - restore_flags(flags); - return (SCSI_RESET_SUCCESS | SCSI_RESET_HOST_RESET); + pCurHcb->HCS_Semaph = 1; + TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x0F); +#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95) + spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags); +#else + restore_flags(flags); +#endif + return (SCSI_RESET_SUCCESS | SCSI_RESET_HOST_RESET); } /************************************************************************/ -void tul_exec_scb(HCS *pCurHcb, SCB *pCurScb) +void tul_exec_scb(HCS * pCurHcb, SCB * pCurScb) { - ULONG flags; - -/* printk("Enter tul_exec_scb");*/ - + ULONG flags; - -/* pCurScb->SCB_Status = SCB_PEND; 7/22/98 */ pCurScb->SCB_Mode = 0; pCurScb->SCB_SGIdx = 0; pCurScb->SCB_SGMax = pCurScb->SCB_SGLen; - save_flags(flags); - cli(); +#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95) + spin_lock_irqsave(&(pCurScb->HCS_SemaphLock), flags); +#else + save_flags(flags); + cli(); +#endif - tul_append_pend_scb(pCurHcb,pCurScb); /* Append this SCB to Pending queue */ + tul_append_pend_scb(pCurHcb, pCurScb); /* Append this SCB to Pending queue */ /* VVVVV 07/21/98 */ - if (pCurHcb->HCS_Semaph == 1) { - TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x1F); - /* disable Jasmin SCSI Int */ - pCurHcb->HCS_Semaph = 0; + if (pCurHcb->HCS_Semaph == 1) { + TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x1F); + /* disable Jasmin SCSI Int */ + pCurHcb->HCS_Semaph = 0; - tulip_main(pCurHcb); + tulip_main(pCurHcb); - pCurHcb->HCS_Semaph = 1; - TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x0F); + pCurHcb->HCS_Semaph = 1; + TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x0F); } - restore_flags(flags); - return; +#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95) + spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags); +#else + restore_flags(flags); +#endif + return; } /***************************************************************************/ -int tul_isr(HCS *pCurHcb) +int tul_isr(HCS * pCurHcb) { -/* printk("Enter i91u_isr\n");*/ - /* Enter critical section */ + /* Enter critical section */ - if (TUL_RD(pCurHcb->HCS_Base, TUL_Int) & TSS_INT_PENDING) - { - if (pCurHcb->HCS_Semaph == 1) - { - TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x1F); - /* Disable Tulip SCSI Int */ - pCurHcb->HCS_Semaph = 0; + if (TUL_RD(pCurHcb->HCS_Base, TUL_Int) & TSS_INT_PENDING) { + if (pCurHcb->HCS_Semaph == 1) { + TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x1F); + /* Disable Tulip SCSI Int */ + pCurHcb->HCS_Semaph = 0; - tulip_main(pCurHcb); + tulip_main(pCurHcb); - pCurHcb->HCS_Semaph = 1; - TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x0F); - return (1); - } + pCurHcb->HCS_Semaph = 1; + TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x0F); + return (1); + } } - return (0); + return (0); } /***************************************************************************/ -int tulip_main(HCS *pCurHcb) +int tulip_main(HCS * pCurHcb) { - SCB *pCurScb; -// ULONG flags; - -/*printk("Enter tulip_main\n");*/ + SCB *pCurScb; - for (;;) - { + for (;;) { -// save_flags(flags); /* wh 07/21/98 */ -// sti(); + tulip_scsi(pCurHcb); /* Call tulip_scsi */ - tulip_scsi(pCurHcb); /* Call tulip_scsi */ + while ((pCurScb = tul_find_done_scb(pCurHcb)) != NULL) { /* find done entry */ + if (pCurScb->SCB_TaStat == QUEUE_FULL) { + pCurHcb->HCS_MaxTags[pCurScb->SCB_Target] = + pCurHcb->HCS_ActTags[pCurScb->SCB_Target] - 1; + pCurScb->SCB_TaStat = 0; + tul_append_pend_scb(pCurHcb, pCurScb); + continue; + } + if (!(pCurScb->SCB_Mode & SCM_RSENS)) { /* not in auto req. sense mode */ + if (pCurScb->SCB_TaStat == 2) { -// restore_flags(flags); /* Addedby hc 07/21/98 */ + /* clr sync. nego flag */ - while ((pCurScb = tul_find_done_scb(pCurHcb)) != NULL) - {/* find done entry */ - if (pCurScb->SCB_TaStat == QUEUE_FULL) - { - pCurHcb->HCS_MaxTags[pCurScb->SCB_Target] = - pCurHcb->HCS_ActTags[pCurScb->SCB_Target] - 1; - pCurScb->SCB_TaStat = 0; -// pCurScb->SCB_Status = SCB_PEND; - tul_append_pend_scb(pCurHcb, pCurScb); - continue; - } + if (pCurScb->SCB_Flags & SCF_SENSE) { + BYTE len; + len = pCurScb->SCB_SenseLen; + if (len == 0) + len = 1; + pCurScb->SCB_BufLen = pCurScb->SCB_SenseLen; + pCurScb->SCB_BufPtr = pCurScb->SCB_SensePtr; + pCurScb->SCB_Flags &= ~(SCF_SG | SCF_DIR); /* for xfer_data_in */ +/* pCurScb->SCB_Flags |= SCF_NO_DCHK; */ + /* so, we won't report worng direction in xfer_data_in, + and won't report HOST_DO_DU in state_6 */ + pCurScb->SCB_Mode = SCM_RSENS; + pCurScb->SCB_Ident &= 0xBF; /* Disable Disconnect */ + pCurScb->SCB_TagMsg = 0; + pCurScb->SCB_TaStat = 0; + pCurScb->SCB_CDBLen = 6; + pCurScb->SCB_CDB[0] = SCSICMD_RequestSense; + pCurScb->SCB_CDB[1] = 0; + pCurScb->SCB_CDB[2] = 0; + pCurScb->SCB_CDB[3] = 0; + pCurScb->SCB_CDB[4] = len; + pCurScb->SCB_CDB[5] = 0; + tul_push_pend_scb(pCurHcb, pCurScb); + break; + } + } + } else { /* in request sense mode */ + + if (pCurScb->SCB_TaStat == 2) { /* check contition status again after sending + requset sense cmd 0x3 */ + pCurScb->SCB_HaStat = HOST_BAD_PHAS; + } + pCurScb->SCB_TaStat = 2; + } + pCurScb->SCB_Flags |= SCF_DONE; + if (pCurScb->SCB_Flags & SCF_POST) { + (*pCurScb->SCB_Post) ((BYTE *) pCurHcb, (BYTE *) pCurScb); + } + } /* while */ - if (!(pCurScb->SCB_Mode & SCM_RSENS)) - { /* not in auto req. sense mode*/ - if (pCurScb->SCB_TaStat == 2) - { - -// pCurHcb->HCS_Tcs[pCurScb->SCB_Target].TCS_Flags -// &= ~(TCF_SYNC_DONE | TCF_WDTR_DONE); - /* clr sync. nego flag */ + /* find_active: */ + if (TUL_RD(pCurHcb->HCS_Base, TUL_SStatus0) & TSS_INT_PENDING) + continue; - if (pCurScb->SCB_Flags & SCF_SENSE) - { - BYTE len; - len = pCurScb->SCB_SenseLen; - if (len == 0) - len = 1; - pCurScb->SCB_BufLen = pCurScb->SCB_SenseLen; - pCurScb->SCB_BufPtr = pCurScb->SCB_SensePtr; - pCurScb->SCB_Flags &= ~(SCF_SG|SCF_DIR); /* for xfer_data_in */ -/* pCurScb->SCB_Flags |= SCF_NO_DCHK; */ - /* so, we won't report worng direction in xfer_data_in, - and won't report HOST_DO_DU in state_6 */ - pCurScb->SCB_Mode = SCM_RSENS; - pCurScb->SCB_Ident &= 0xBF; /* Disable Disconnect */ - pCurScb->SCB_TagMsg = 0; - pCurScb->SCB_TaStat = 0; - pCurScb->SCB_CDBLen = 6; - pCurScb->SCB_CDB[0] = SCSICMD_RequestSense; - pCurScb->SCB_CDB[1] = 0; - pCurScb->SCB_CDB[2] = 0; - pCurScb->SCB_CDB[3] = 0; - pCurScb->SCB_CDB[4] = len; - pCurScb->SCB_CDB[5] = 0; - tul_push_pend_scb(pCurHcb, pCurScb); - break; - } - } - } - else { /* in request sense mode */ - - if (pCurScb->SCB_TaStat == 2) - {/* check contition status again after sending - requset sense cmd 0x3*/ - pCurScb->SCB_HaStat = HOST_BAD_PHAS; - } - pCurScb->SCB_TaStat = 2; - } - pCurScb->SCB_Flags |= SCF_DONE; - if (pCurScb->SCB_Flags & SCF_POST) - { -// restore_flags(flags); /* Addedby hc 07/08/98 */ -// sti(); - (*pCurScb->SCB_Post)((BYTE *) pCurHcb, (BYTE *) pCurScb); -// save_flags(flags); /* Addedby hc 07/08/98 */ - } - } /* while */ - - /* find_active: */ - if (TUL_RD(pCurHcb->HCS_Base, TUL_SStatus0) & TSS_INT_PENDING) - continue; - - if (pCurHcb->HCS_ActScb) /* return to OS and wait for xfer_done_ISR/Selected_ISR */ - { - return 1; /* return to OS, enable interrupt */ - } - /* Check pending SCB */ - if (tul_find_first_pend_scb(pCurHcb) == NULL) - { - return 1; /* return to OS, enable interrupt */ - } - } /* End of for loop */ + if (pCurHcb->HCS_ActScb) { /* return to OS and wait for xfer_done_ISR/Selected_ISR */ + return 1; /* return to OS, enable interrupt */ + } + /* Check pending SCB */ + if (tul_find_first_pend_scb(pCurHcb) == NULL) { + return 1; /* return to OS, enable interrupt */ + } + } /* End of for loop */ /* statement won't reach here */ } -/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */ /***************************************************************************/ /***************************************************************************/ /***************************************************************************/ /***************************************************************************/ /***************************************************************************/ -void tulip_scsi(HCS *pCurHcb) +void tulip_scsi(HCS * pCurHcb) { - SCB *pCurScb; - TCS *pCurTcb; + SCB *pCurScb; + TCS *pCurTcb; -/* printk("Enter tulip_scsi()\n");*/ /* make sure to service interrupt asap */ - if ((pCurHcb->HCS_JSStatus0 = TUL_RD(pCurHcb->HCS_Base, TUL_SStatus0)) & TSS_INT_PENDING) - { - - pCurHcb->HCS_Phase = pCurHcb->HCS_JSStatus0 & TSS_PH_MASK; - pCurHcb->HCS_JSStatus1 = TUL_RD(pCurHcb->HCS_Base, TUL_SStatus1); - pCurHcb->HCS_JSInt = TUL_RD(pCurHcb->HCS_Base, TUL_SInt); -/* printk("SCSI status = %x\n", pCurHcb->HCS_JSStatus0 ); - printk("SCSI status 1 = %x\n", pCurHcb->HCS_JSStatus1); - printk("SCSI interrupt = %x\n", pCurHcb->HCS_JSInt);*/ - if (pCurHcb->HCS_JSInt & TSS_SCSIRST_INT) - { /* SCSI bus reset detected */ - int_tul_scsi_rst(pCurHcb); - return; - } - if (pCurHcb->HCS_JSInt & TSS_RESEL_INT) - { /* if selected/reselected interrupt */ - if (int_tul_resel(pCurHcb) == 0) - tul_next_state(pCurHcb); - return; - } - if (pCurHcb->HCS_JSInt & TSS_SEL_TIMEOUT) - { - int_tul_busfree(pCurHcb) ; - return; - } - if (pCurHcb->HCS_JSInt & TSS_DISC_INT) - { /* BUS disconnection */ - int_tul_busfree(pCurHcb); /* unexpected bus free or sel timeout */ - return; - } - if (pCurHcb->HCS_JSInt & (TSS_FUNC_COMP | TSS_BUS_SERV)) - { /* func complete or Bus service */ - if ((pCurScb = pCurHcb->HCS_ActScb) != NULL) - tul_next_state(pCurHcb); - return; - } - } - - if (pCurHcb->HCS_ActScb != NULL) - return; - -/* if ((pCurScb = pCurHcb->HCS_FirstPend) == NULL)*/ - if ((pCurScb = tul_find_first_pend_scb(pCurHcb)) == NULL) - return; - - /* program HBA's SCSI ID & target SCSI ID */ - TUL_WR( pCurHcb->HCS_Base + TUL_SScsiId, - (pCurHcb->HCS_SCSI_ID << 4) | (pCurScb->SCB_Target & 0x0F) ); - if (pCurScb->SCB_Opcode == ExecSCSI) { - pCurTcb = &pCurHcb->HCS_Tcs[pCurScb->SCB_Target]; + if ((pCurHcb->HCS_JSStatus0 = TUL_RD(pCurHcb->HCS_Base, TUL_SStatus0)) & TSS_INT_PENDING) { - if (pCurScb->SCB_TagMsg) - pCurTcb->TCS_DrvFlags |= TCF_DRV_EN_TAG; - else - pCurTcb->TCS_DrvFlags &= ~TCF_DRV_EN_TAG; + pCurHcb->HCS_Phase = pCurHcb->HCS_JSStatus0 & TSS_PH_MASK; + pCurHcb->HCS_JSStatus1 = TUL_RD(pCurHcb->HCS_Base, TUL_SStatus1); + pCurHcb->HCS_JSInt = TUL_RD(pCurHcb->HCS_Base, TUL_SInt); + if (pCurHcb->HCS_JSInt & TSS_SCSIRST_INT) { /* SCSI bus reset detected */ + int_tul_scsi_rst(pCurHcb); + return; + } + if (pCurHcb->HCS_JSInt & TSS_RESEL_INT) { /* if selected/reselected interrupt */ + if (int_tul_resel(pCurHcb) == 0) + tul_next_state(pCurHcb); + return; + } + if (pCurHcb->HCS_JSInt & TSS_SEL_TIMEOUT) { + int_tul_busfree(pCurHcb); + return; + } + if (pCurHcb->HCS_JSInt & TSS_DISC_INT) { /* BUS disconnection */ + int_tul_busfree(pCurHcb); /* unexpected bus free or sel timeout */ + return; + } + if (pCurHcb->HCS_JSInt & (TSS_FUNC_COMP | TSS_BUS_SERV)) { /* func complete or Bus service */ + if ((pCurScb = pCurHcb->HCS_ActScb) != NULL) + tul_next_state(pCurHcb); + return; + } + } + if (pCurHcb->HCS_ActScb != NULL) + return; + + if ((pCurScb = tul_find_first_pend_scb(pCurHcb)) == NULL) + return; + + /* program HBA's SCSI ID & target SCSI ID */ + TUL_WR(pCurHcb->HCS_Base + TUL_SScsiId, + (pCurHcb->HCS_SCSI_ID << 4) | (pCurScb->SCB_Target & 0x0F)); + if (pCurScb->SCB_Opcode == ExecSCSI) { + pCurTcb = &pCurHcb->HCS_Tcs[pCurScb->SCB_Target]; - TUL_WR(pCurHcb->HCS_Base + TUL_SPeriod, pCurTcb->TCS_JS_Period); -/*printk("TCS_Flags = %x\n", pCurTcb->TCS_Flags); -do_pause(15000);*/ - if ((pCurTcb->TCS_Flags & (TCF_WDTR_DONE | TCF_NO_WDTR)) == 0) - { /* do wdtr negotiation */ - tul_select_atn_stop(pCurHcb, pCurScb); - } - else - { - if ((pCurTcb->TCS_Flags & (TCF_SYNC_DONE | TCF_NO_SYNC_NEGO)) == 0) - { /* do sync negotiation */ - tul_select_atn_stop(pCurHcb, pCurScb); - } - else - { if (pCurScb->SCB_TagMsg) - tul_select_atn3(pCurHcb, pCurScb); + pCurTcb->TCS_DrvFlags |= TCF_DRV_EN_TAG; else - tul_select_atn(pCurHcb, pCurScb); - } - } - if (pCurScb->SCB_Flags & SCF_POLL) - { - while (wait_tulip(pCurHcb) != -1) - { - if (tul_next_state(pCurHcb) == -1) - break; - } - } - } - else if (pCurScb->SCB_Opcode == BusDevRst) { - tul_select_atn_stop(pCurHcb, pCurScb); - pCurScb->SCB_NxtStat = 8; - if (pCurScb->SCB_Flags & SCF_POLL) - { - while (wait_tulip(pCurHcb) != -1) - { - if (tul_next_state(pCurHcb) == -1) - break; - } - } - } - else if (pCurScb->SCB_Opcode == AbortCmd ) { - ULONG srbp; + pCurTcb->TCS_DrvFlags &= ~TCF_DRV_EN_TAG; - srbp = (ULONG)pCurScb->SCB_Srb; -/* 08/03/98 */ - if (tul_abort_srb(pCurHcb, srbp) != 0) { - - - tul_unlink_pend_scb(pCurHcb, pCurScb); - - tul_release_scb(pCurHcb, pCurScb); + TUL_WR(pCurHcb->HCS_Base + TUL_SPeriod, pCurTcb->TCS_JS_Period); + if ((pCurTcb->TCS_Flags & (TCF_WDTR_DONE | TCF_NO_WDTR)) == 0) { /* do wdtr negotiation */ + tul_select_atn_stop(pCurHcb, pCurScb); + } else { + if ((pCurTcb->TCS_Flags & (TCF_SYNC_DONE | TCF_NO_SYNC_NEGO)) == 0) { /* do sync negotiation */ + tul_select_atn_stop(pCurHcb, pCurScb); + } else { + if (pCurScb->SCB_TagMsg) + tul_select_atn3(pCurHcb, pCurScb); + else + tul_select_atn(pCurHcb, pCurScb); + } + } + if (pCurScb->SCB_Flags & SCF_POLL) { + while (wait_tulip(pCurHcb) != -1) { + if (tul_next_state(pCurHcb) == -1) + break; + } } - else { - pCurScb->SCB_Opcode = BusDevRst; + } else if (pCurScb->SCB_Opcode == BusDevRst) { tul_select_atn_stop(pCurHcb, pCurScb); pCurScb->SCB_NxtStat = 8; + if (pCurScb->SCB_Flags & SCF_POLL) { + while (wait_tulip(pCurHcb) != -1) { + if (tul_next_state(pCurHcb) == -1) + break; + } } - + } else if (pCurScb->SCB_Opcode == AbortCmd) { + ULONG srbp; + + srbp = (ULONG) pCurScb->SCB_Srb; /* 08/03/98 */ - } - else { - tul_unlink_pend_scb(pCurHcb, pCurScb); -// pCurScb->SCB_Status = SCB_DONE; /* done */ - pCurScb->SCB_HaStat = 0x16; /* bad command */ - tul_append_done_scb(pCurHcb, pCurScb); - } - return; -} + if (tul_abort_srb(pCurHcb, srbp) != 0) { -/***************************************************************************/ -int tul_next_state(HCS *pCurHcb) -{ - int next; - - next = pCurHcb->HCS_ActScb->SCB_NxtStat; - for (;;) { - switch (next) { - case 1: - next = tul_state_1(pCurHcb); - break; - case 2: - next = tul_state_2(pCurHcb); - break; - case 3: - next = tul_state_3(pCurHcb); - break; - case 4: - next = tul_state_4(pCurHcb); - break; - case 5: - next = tul_state_5(pCurHcb); - break; - case 6: - next = tul_state_6(pCurHcb); - break; - case 7: - next = tul_state_7(pCurHcb); - break; - case 8: - return (tul_bus_device_reset(pCurHcb)); - default: - return (tul_bad_seq(pCurHcb)); - } - if (next <= 0) - return next; - } -} + tul_unlink_pend_scb(pCurHcb, pCurScb); + + tul_release_scb(pCurHcb, pCurScb); + } else { + pCurScb->SCB_Opcode = BusDevRst; + tul_select_atn_stop(pCurHcb, pCurScb); + pCurScb->SCB_NxtStat = 8; + } + +/* 08/03/98 */ + } else { + tul_unlink_pend_scb(pCurHcb, pCurScb); + pCurScb->SCB_HaStat = 0x16; /* bad command */ + tul_append_done_scb(pCurHcb, pCurScb); + } + return; +} + + +/***************************************************************************/ +int tul_next_state(HCS * pCurHcb) +{ + int next; + + next = pCurHcb->HCS_ActScb->SCB_NxtStat; + for (;;) { + switch (next) { + case 1: + next = tul_state_1(pCurHcb); + break; + case 2: + next = tul_state_2(pCurHcb); + break; + case 3: + next = tul_state_3(pCurHcb); + break; + case 4: + next = tul_state_4(pCurHcb); + break; + case 5: + next = tul_state_5(pCurHcb); + break; + case 6: + next = tul_state_6(pCurHcb); + break; + case 7: + next = tul_state_7(pCurHcb); + break; + case 8: + return (tul_bus_device_reset(pCurHcb)); + default: + return (tul_bad_seq(pCurHcb)); + } + if (next <= 0) + return next; + } +} /***************************************************************************/ /* sTate after selection with attention & stop */ -int tul_state_1(HCS *pCurHcb) +int tul_state_1(HCS * pCurHcb) { - SCB *pCurScb = pCurHcb->HCS_ActScb; - TCS *pCurTcb = pCurHcb->HCS_ActTcs; + SCB *pCurScb = pCurHcb->HCS_ActScb; + TCS *pCurTcb = pCurHcb->HCS_ActTcs; #if DEBUG_STATE -printk("-s1-"); + printk("-s1-"); #endif - tul_unlink_pend_scb(pCurHcb, pCurScb); - tul_append_busy_scb(pCurHcb, pCurScb); - - TUL_WR(pCurHcb->HCS_Base+ TUL_SConfig, pCurTcb->TCS_SConfig0); - /* ATN on */ - if (pCurHcb->HCS_Phase == MSG_OUT) { - -/*printk("MSG OUT\n");*/ - TUL_WR(pCurHcb->HCS_Base+ TUL_SCtrl1, (TSC_EN_BUS_IN | TSC_HW_RESELECT)); + tul_unlink_pend_scb(pCurHcb, pCurScb); + tul_append_busy_scb(pCurHcb, pCurScb); - TUL_WR(pCurHcb->HCS_Base+ TUL_SFifo, pCurScb->SCB_Ident); + TUL_WR(pCurHcb->HCS_Base + TUL_SConfig, pCurTcb->TCS_SConfig0); + /* ATN on */ + if (pCurHcb->HCS_Phase == MSG_OUT) { - if (pCurScb->SCB_TagMsg) - { - TUL_WR(pCurHcb->HCS_Base+ TUL_SFifo, pCurScb->SCB_TagMsg); - TUL_WR(pCurHcb->HCS_Base+ TUL_SFifo, pCurScb->SCB_TagId); - } + TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl1, (TSC_EN_BUS_IN | TSC_HW_RESELECT)); - if ((pCurTcb->TCS_Flags & (TCF_WDTR_DONE | TCF_NO_WDTR)) == 0) { + TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, pCurScb->SCB_Ident); - pCurTcb->TCS_Flags |= TCF_WDTR_DONE; + if (pCurScb->SCB_TagMsg) { + TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, pCurScb->SCB_TagMsg); + TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, pCurScb->SCB_TagId); + } + if ((pCurTcb->TCS_Flags & (TCF_WDTR_DONE | TCF_NO_WDTR)) == 0) { - TUL_WR(pCurHcb->HCS_Base+ TUL_SFifo, MSG_EXTEND); - TUL_WR(pCurHcb->HCS_Base+ TUL_SFifo, 2); /* Extended msg length*/ - TUL_WR(pCurHcb->HCS_Base+ TUL_SFifo, 3); /* Sync request*/ - TUL_WR(pCurHcb->HCS_Base+ TUL_SFifo, 1); /* Start from 16 bits */ - } - else if ((pCurTcb->TCS_Flags & (TCF_SYNC_DONE|TCF_NO_SYNC_NEGO)) == 0) { + pCurTcb->TCS_Flags |= TCF_WDTR_DONE; - pCurTcb->TCS_Flags |= TCF_SYNC_DONE; + TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_EXTEND); + TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, 2); /* Extended msg length */ + TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, 3); /* Sync request */ + TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, 1); /* Start from 16 bits */ + } else if ((pCurTcb->TCS_Flags & (TCF_SYNC_DONE | TCF_NO_SYNC_NEGO)) == 0) { - TUL_WR(pCurHcb->HCS_Base+TUL_SFifo, MSG_EXTEND); - TUL_WR(pCurHcb->HCS_Base+TUL_SFifo, 3); /* extended msg length */ - TUL_WR(pCurHcb->HCS_Base+TUL_SFifo, 1); /* sync request */ - TUL_WR(pCurHcb->HCS_Base+TUL_SFifo, tul_rate_tbl[pCurTcb->TCS_Flags & TCF_SCSI_RATE]); - TUL_WR(pCurHcb->HCS_Base+TUL_SFifo, MAX_OFFSET); /* REQ/ACK offset */ - } + pCurTcb->TCS_Flags |= TCF_SYNC_DONE; - TUL_WR(pCurHcb->HCS_Base+ TUL_SCmd, TSC_XF_FIFO_OUT); - if (wait_tulip(pCurHcb) == -1) - return(-1); + TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_EXTEND); + TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, 3); /* extended msg length */ + TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, 1); /* sync request */ + TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, tul_rate_tbl[pCurTcb->TCS_Flags & TCF_SCSI_RATE]); + TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MAX_OFFSET); /* REQ/ACK offset */ + } + TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT); + if (wait_tulip(pCurHcb) == -1) + return (-1); } - - TUL_WR(pCurHcb->HCS_Base+ TUL_SCtrl0, TSC_FLUSH_FIFO); + TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO); TUL_WR(pCurHcb->HCS_Base + TUL_SSignal, (TUL_RD(pCurHcb->HCS_Base, TUL_SSignal) & (TSC_SET_ACK | 7))); - return(3); + return (3); } /***************************************************************************/ /* state after selection with attention */ /* state after selection with attention3 */ -int tul_state_2(HCS *pCurHcb) +int tul_state_2(HCS * pCurHcb) { - SCB *pCurScb = pCurHcb->HCS_ActScb; - TCS *pCurTcb = pCurHcb->HCS_ActTcs; + SCB *pCurScb = pCurHcb->HCS_ActScb; + TCS *pCurTcb = pCurHcb->HCS_ActTcs; #if DEBUG_STATE -printk("-s2-"); + printk("-s2-"); #endif - tul_unlink_pend_scb(pCurHcb, pCurScb); - tul_append_busy_scb(pCurHcb, pCurScb); + tul_unlink_pend_scb(pCurHcb, pCurScb); + tul_append_busy_scb(pCurHcb, pCurScb); - TUL_WR(pCurHcb->HCS_Base + TUL_SConfig, pCurTcb->TCS_SConfig0); + TUL_WR(pCurHcb->HCS_Base + TUL_SConfig, pCurTcb->TCS_SConfig0); - if ( pCurHcb->HCS_JSStatus1 & TSS_CMD_PH_CMP) { - return (4); - } - TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO); - TUL_WR(pCurHcb->HCS_Base + TUL_SSignal, (TUL_RD(pCurHcb->HCS_Base, TUL_SSignal) & (TSC_SET_ACK | 7))); - return (3); + if (pCurHcb->HCS_JSStatus1 & TSS_CMD_PH_CMP) { + return (4); + } + TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO); + TUL_WR(pCurHcb->HCS_Base + TUL_SSignal, (TUL_RD(pCurHcb->HCS_Base, TUL_SSignal) & (TSC_SET_ACK | 7))); + return (3); } /***************************************************************************/ /* state before CDB xfer is done */ -int tul_state_3(HCS *pCurHcb) +int tul_state_3(HCS * pCurHcb) { - SCB *pCurScb = pCurHcb->HCS_ActScb; - TCS *pCurTcb = pCurHcb->HCS_ActTcs; - int i; + SCB *pCurScb = pCurHcb->HCS_ActScb; + TCS *pCurTcb = pCurHcb->HCS_ActTcs; + int i; #if DEBUG_STATE -printk("-s3-"); + printk("-s3-"); #endif - for (;;) { - switch (pCurHcb->HCS_Phase) - { - case CMD_OUT: /* Command out phase */ -/*printk("Command Out Phase\n");*/ - for ( i = 0; i < (int) pCurScb->SCB_CDBLen; i++) - TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, pCurScb->SCB_CDB[i]); - TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT); - if (wait_tulip(pCurHcb) == -1) - return (-1); - if (pCurHcb->HCS_Phase == CMD_OUT) { - return (tul_bad_seq(pCurHcb)); - } - return(4); - - case MSG_IN: /* Message in phase */ -/*printk("Message In Phase\n");*/ - pCurScb->SCB_NxtStat = 3; - if (tul_msgin(pCurHcb) == -1) - return (-1); - break; - - case STATUS_IN: /* Status phase */ -/*printk("Status Phase\n");*/ - if (tul_status_msg(pCurHcb) == -1) - return (-1); - break; - - case MSG_OUT: /* Message out phase */ -/*printk("Message Out Phase\n");*/ - if (pCurTcb->TCS_Flags & (TCF_SYNC_DONE | TCF_NO_SYNC_NEGO)) { - - TUL_WR(pCurHcb->HCS_Base+TUL_SFifo, MSG_NOP); /* msg nop */ - TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT); - if (wait_tulip(pCurHcb) == -1) - return(-1); + for (;;) { + switch (pCurHcb->HCS_Phase) { + case CMD_OUT: /* Command out phase */ + for (i = 0; i < (int) pCurScb->SCB_CDBLen; i++) + TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, pCurScb->SCB_CDB[i]); + TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT); + if (wait_tulip(pCurHcb) == -1) + return (-1); + if (pCurHcb->HCS_Phase == CMD_OUT) { + return (tul_bad_seq(pCurHcb)); + } + return (4); - } else { - pCurTcb->TCS_Flags |= TCF_SYNC_DONE; + case MSG_IN: /* Message in phase */ + pCurScb->SCB_NxtStat = 3; + if (tul_msgin(pCurHcb) == -1) + return (-1); + break; - TUL_WR(pCurHcb->HCS_Base+TUL_SFifo, MSG_EXTEND); - TUL_WR(pCurHcb->HCS_Base+TUL_SFifo, 3); /* ext. msg len */ - TUL_WR(pCurHcb->HCS_Base+TUL_SFifo, 1); /* sync request */ - TUL_WR(pCurHcb->HCS_Base+TUL_SFifo, tul_rate_tbl[pCurTcb->TCS_Flags & TCF_SCSI_RATE]); - TUL_WR(pCurHcb->HCS_Base+TUL_SFifo, MAX_OFFSET); /* REQ/ACK offset */ - TUL_WR(pCurHcb->HCS_Base+TUL_SCmd, TSC_XF_FIFO_OUT); - if (wait_tulip(pCurHcb) == -1) - return(-1); - TUL_WR(pCurHcb->HCS_Base+TUL_SCtrl0, TSC_FLUSH_FIFO); - TUL_WR(pCurHcb->HCS_Base+TUL_SSignal, TUL_RD(pCurHcb->HCS_Base, TUL_SSignal) & (TSC_SET_ACK | 7)); + case STATUS_IN: /* Status phase */ + if (tul_status_msg(pCurHcb) == -1) + return (-1); + break; - } - break; + case MSG_OUT: /* Message out phase */ + if (pCurTcb->TCS_Flags & (TCF_SYNC_DONE | TCF_NO_SYNC_NEGO)) { - default: - return (tul_bad_seq(pCurHcb)); - } + TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_NOP); /* msg nop */ + TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT); + if (wait_tulip(pCurHcb) == -1) + return (-1); + + } else { + pCurTcb->TCS_Flags |= TCF_SYNC_DONE; + + TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_EXTEND); + TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, 3); /* ext. msg len */ + TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, 1); /* sync request */ + TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, tul_rate_tbl[pCurTcb->TCS_Flags & TCF_SCSI_RATE]); + TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MAX_OFFSET); /* REQ/ACK offset */ + TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT); + if (wait_tulip(pCurHcb) == -1) + return (-1); + TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO); + TUL_WR(pCurHcb->HCS_Base + TUL_SSignal, TUL_RD(pCurHcb->HCS_Base, TUL_SSignal) & (TSC_SET_ACK | 7)); + + } + break; + + default: + return (tul_bad_seq(pCurHcb)); + } } } /***************************************************************************/ -int tul_state_4(HCS *pCurHcb) +int tul_state_4(HCS * pCurHcb) { - SCB *pCurScb = pCurHcb->HCS_ActScb; + SCB *pCurScb = pCurHcb->HCS_ActScb; #if DEBUG_STATE -printk("-s4-"); + printk("-s4-"); #endif - if ((pCurScb->SCB_Flags & SCF_DIR) == SCF_NO_XF) { - return (6); /* Go to state 6 */ - } - - for (;;) { - if (pCurScb->SCB_BufLen == 0) - return (6); /* Go to state 6 */ + if ((pCurScb->SCB_Flags & SCF_DIR) == SCF_NO_XF) { + return (6); /* Go to state 6 */ + } + for (;;) { + if (pCurScb->SCB_BufLen == 0) + return (6); /* Go to state 6 */ - switch (pCurHcb->HCS_Phase) { + switch (pCurHcb->HCS_Phase) { - case STATUS_IN: /* Status phase */ - if ((pCurScb->SCB_Flags & SCF_DIR) != 0) - { /* if direction bit set then report data underrun */ - pCurScb->SCB_HaStat = HOST_DO_DU; - } - if ((tul_status_msg(pCurHcb)) == -1) - return (-1); - break; - - case MSG_IN: /* Message in phase */ - pCurScb->SCB_NxtStat = 0x4; - if (tul_msgin(pCurHcb) == -1) - return (-1); - break; + case STATUS_IN: /* Status phase */ + if ((pCurScb->SCB_Flags & SCF_DIR) != 0) { /* if direction bit set then report data underrun */ + pCurScb->SCB_HaStat = HOST_DO_DU; + } + if ((tul_status_msg(pCurHcb)) == -1) + return (-1); + break; - case MSG_OUT: /* Message out phase */ - if (pCurHcb->HCS_JSStatus0 & TSS_PAR_ERROR) { - pCurScb->SCB_BufLen = 0; - pCurScb->SCB_HaStat = HOST_DO_DU; - if (tul_msgout_ide(pCurHcb) == -1) - return (-1); - return (6); /* Go to state 6 */ - } else { - TUL_WR(pCurHcb->HCS_Base+TUL_SFifo, MSG_NOP); /* msg nop */ - TUL_WR(pCurHcb->HCS_Base+TUL_SCmd, TSC_XF_FIFO_OUT); - if (wait_tulip(pCurHcb) == -1) - return (-1); - } - break; + case MSG_IN: /* Message in phase */ + pCurScb->SCB_NxtStat = 0x4; + if (tul_msgin(pCurHcb) == -1) + return (-1); + break; - case DATA_IN: /* Data in phase */ - return (tul_xfer_data_in(pCurHcb)); + case MSG_OUT: /* Message out phase */ + if (pCurHcb->HCS_JSStatus0 & TSS_PAR_ERROR) { + pCurScb->SCB_BufLen = 0; + pCurScb->SCB_HaStat = HOST_DO_DU; + if (tul_msgout_ide(pCurHcb) == -1) + return (-1); + return (6); /* Go to state 6 */ + } else { + TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_NOP); /* msg nop */ + TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT); + if (wait_tulip(pCurHcb) == -1) + return (-1); + } + break; - case DATA_OUT: /* Data out phase */ - return (tul_xfer_data_out(pCurHcb)); + case DATA_IN: /* Data in phase */ + return (tul_xfer_data_in(pCurHcb)); - default: - return (tul_bad_seq(pCurHcb)); + case DATA_OUT: /* Data out phase */ + return (tul_xfer_data_out(pCurHcb)); + + default: + return (tul_bad_seq(pCurHcb)); + } } - } } /***************************************************************************/ /* state after dma xfer done or phase change before xfer done */ -int tul_state_5(HCS *pCurHcb) +int tul_state_5(HCS * pCurHcb) { - SCB *pCurScb = pCurHcb->HCS_ActScb; - long cnt, xcnt; /* cannot use unsigned !! code: if (xcnt < 0) */ + SCB *pCurScb = pCurHcb->HCS_ActScb; + long cnt, xcnt; /* cannot use unsigned !! code: if (xcnt < 0) */ #if DEBUG_STATE -printk("-s5-"); + printk("-s5-"); #endif - /*------ get remaining count -------*/ +/*------ get remaining count -------*/ - cnt = TUL_RDLONG(pCurHcb->HCS_Base, TUL_SCnt0) & 0x0FFFFFF; + cnt = TUL_RDLONG(pCurHcb->HCS_Base, TUL_SCnt0) & 0x0FFFFFF; -/*printk("Remaining SCSI Count = %lx\n", cnt);*/ - if (TUL_RD(pCurHcb->HCS_Base, TUL_XCmd) & 0x20) - { - /* ----------------------- DATA_IN -----------------------------*/ + if (TUL_RD(pCurHcb->HCS_Base, TUL_XCmd) & 0x20) { + /* ----------------------- DATA_IN ----------------------------- */ /* check scsi parity error */ - if (pCurHcb->HCS_JSStatus0 & TSS_PAR_ERROR) - { - pCurScb->SCB_HaStat = HOST_DO_DU; - } - - if (TUL_RD(pCurHcb->HCS_Base, TUL_XStatus) & XPEND) - { /* DMA xfer pending, Send STOP */ + if (pCurHcb->HCS_JSStatus0 & TSS_PAR_ERROR) { + pCurScb->SCB_HaStat = HOST_DO_DU; + } + if (TUL_RD(pCurHcb->HCS_Base, TUL_XStatus) & XPEND) { /* DMA xfer pending, Send STOP */ /* tell Hardware scsi xfer has been terminated */ - TUL_WR(pCurHcb->HCS_Base + TUL_XCtrl, TUL_RD(pCurHcb->HCS_Base, TUL_XCtrl) | 0x80); + TUL_WR(pCurHcb->HCS_Base + TUL_XCtrl, TUL_RD(pCurHcb->HCS_Base, TUL_XCtrl) | 0x80); /* wait until DMA xfer not pending */ - while (TUL_RD(pCurHcb->HCS_Base, TUL_XStatus) & XPEND ); - } - } - else - { /*-------- DATA OUT -----------*/ - if ((TUL_RD(pCurHcb->HCS_Base, TUL_SStatus1) & TSS_XFER_CMP) == 0) - { - if (pCurHcb->HCS_ActTcs->TCS_JS_Period & TSC_WIDE_SCSI) - cnt += (TUL_RD(pCurHcb->HCS_Base, TUL_SFifoCnt) & 0x1F) << 1; - else - cnt += (TUL_RD(pCurHcb->HCS_Base, TUL_SFifoCnt) & 0x1F); - } - if (TUL_RD(pCurHcb->HCS_Base, TUL_XStatus) & XPEND) - { /* if DMA xfer is pending, abort DMA xfer */ - TUL_WR(pCurHcb->HCS_Base + TUL_XCmd, TAX_X_ABT); - /* wait Abort DMA xfer done */ - while ((TUL_RD(pCurHcb->HCS_Base, TUL_Int) & XABT) == 0); - } - if ((cnt == 1) && (pCurHcb->HCS_Phase == DATA_OUT)) - { - TUL_WR(pCurHcb->HCS_Base+ TUL_SCmd, TSC_XF_FIFO_OUT); - if (wait_tulip(pCurHcb) == -1) - { - return (-1); + while (TUL_RD(pCurHcb->HCS_Base, TUL_XStatus) & XPEND); } - cnt = 0; - } - else - { - if ((TUL_RD(pCurHcb->HCS_Base, TUL_SStatus1) & TSS_XFER_CMP) == 0) - TUL_WR(pCurHcb->HCS_Base+ TUL_SCtrl0, TSC_FLUSH_FIFO); - } - } - - if (cnt == 0) - { - pCurScb->SCB_BufLen = 0; - return (6); /* Go to state 6 */ - } - /* Update active data pointer */ - xcnt = (long)pCurScb->SCB_BufLen - cnt; /* xcnt== bytes already xferred */ - pCurScb->SCB_BufLen = (U32)cnt; /* cnt == bytes left to be xferred */ - if (pCurScb->SCB_Flags & SCF_SG) - { - register SG *sgp; - ULONG i; - - sgp = &pCurScb->SCB_SGList[pCurScb->SCB_SGIdx]; - for (i = pCurScb->SCB_SGIdx; i < pCurScb->SCB_SGMax; sgp++, i++) - { - xcnt -= (long)sgp->SG_Len; - if (xcnt < 0) - { /* this sgp xfer half done */ - xcnt += (long)sgp->SG_Len; /* xcnt == bytes xferred in this sgp */ - sgp->SG_Ptr += (U32)xcnt; /* new ptr to be xfer */ - sgp->SG_Len -= (U32)xcnt; /* new len to be xfer */ - pCurScb->SCB_BufPtr += ((U32)(i - pCurScb->SCB_SGIdx) << 3); - /* new SG table ptr */ - pCurScb->SCB_SGLen = (BYTE)(pCurScb->SCB_SGMax - i); - /* new SG table len */ - pCurScb->SCB_SGIdx = (WORD)i; - /* for next disc and come in this loop*/ - return (4); /* Go to state 4 */ + } else { +/*-------- DATA OUT -----------*/ + if ((TUL_RD(pCurHcb->HCS_Base, TUL_SStatus1) & TSS_XFER_CMP) == 0) { + if (pCurHcb->HCS_ActTcs->TCS_JS_Period & TSC_WIDE_SCSI) + cnt += (TUL_RD(pCurHcb->HCS_Base, TUL_SFifoCnt) & 0x1F) << 1; + else + cnt += (TUL_RD(pCurHcb->HCS_Base, TUL_SFifoCnt) & 0x1F); + } + if (TUL_RD(pCurHcb->HCS_Base, TUL_XStatus) & XPEND) { /* if DMA xfer is pending, abort DMA xfer */ + TUL_WR(pCurHcb->HCS_Base + TUL_XCmd, TAX_X_ABT); + /* wait Abort DMA xfer done */ + while ((TUL_RD(pCurHcb->HCS_Base, TUL_Int) & XABT) == 0); + } + if ((cnt == 1) && (pCurHcb->HCS_Phase == DATA_OUT)) { + TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT); + if (wait_tulip(pCurHcb) == -1) { + return (-1); + } + cnt = 0; + } else { + if ((TUL_RD(pCurHcb->HCS_Base, TUL_SStatus1) & TSS_XFER_CMP) == 0) + TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO); } - /* else (xcnt >= 0 , i.e. this sgp already xferred */ - } /* for */ - return (6); /* Go to state 6 */ } - else - { - pCurScb->SCB_BufPtr += (U32)xcnt; + + if (cnt == 0) { + pCurScb->SCB_BufLen = 0; + return (6); /* Go to state 6 */ + } + /* Update active data pointer */ + xcnt = (long) pCurScb->SCB_BufLen - cnt; /* xcnt== bytes already xferred */ + pCurScb->SCB_BufLen = (U32) cnt; /* cnt == bytes left to be xferred */ + if (pCurScb->SCB_Flags & SCF_SG) { + register SG *sgp; + ULONG i; + + sgp = &pCurScb->SCB_SGList[pCurScb->SCB_SGIdx]; + for (i = pCurScb->SCB_SGIdx; i < pCurScb->SCB_SGMax; sgp++, i++) { + xcnt -= (long) sgp->SG_Len; + if (xcnt < 0) { /* this sgp xfer half done */ + xcnt += (long) sgp->SG_Len; /* xcnt == bytes xferred in this sgp */ + sgp->SG_Ptr += (U32) xcnt; /* new ptr to be xfer */ + sgp->SG_Len -= (U32) xcnt; /* new len to be xfer */ + pCurScb->SCB_BufPtr += ((U32) (i - pCurScb->SCB_SGIdx) << 3); + /* new SG table ptr */ + pCurScb->SCB_SGLen = (BYTE) (pCurScb->SCB_SGMax - i); + /* new SG table len */ + pCurScb->SCB_SGIdx = (WORD) i; + /* for next disc and come in this loop */ + return (4); /* Go to state 4 */ + } + /* else (xcnt >= 0 , i.e. this sgp already xferred */ + } /* for */ + return (6); /* Go to state 6 */ + } else { + pCurScb->SCB_BufPtr += (U32) xcnt; } - return (4); /* Go to state 4 */ + return (4); /* Go to state 4 */ } /***************************************************************************/ /* state after Data phase */ -int tul_state_6(HCS *pCurHcb) +int tul_state_6(HCS * pCurHcb) { - SCB *pCurScb = pCurHcb->HCS_ActScb; + SCB *pCurScb = pCurHcb->HCS_ActScb; #if DEBUG_STATE -printk("-s6-"); + printk("-s6-"); #endif - for (;;) { - switch (pCurHcb->HCS_Phase) { - case STATUS_IN: /* Status phase */ - if ((tul_status_msg(pCurHcb)) == -1) - return (-1); - break; - - case MSG_IN: /* Message in phase */ - pCurScb->SCB_NxtStat = 6; - if ((tul_msgin(pCurHcb)) == -1) - return (-1); - break; + for (;;) { + switch (pCurHcb->HCS_Phase) { + case STATUS_IN: /* Status phase */ + if ((tul_status_msg(pCurHcb)) == -1) + return (-1); + break; - case MSG_OUT: /* Message out phase */ - TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_NOP); /* msg nop */ - TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT); - if (wait_tulip(pCurHcb) == -1) - return (-1); - break; + case MSG_IN: /* Message in phase */ + pCurScb->SCB_NxtStat = 6; + if ((tul_msgin(pCurHcb)) == -1) + return (-1); + break; - case DATA_IN: /* Data in phase */ - return (tul_xpad_in(pCurHcb)); + case MSG_OUT: /* Message out phase */ + TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_NOP); /* msg nop */ + TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT); + if (wait_tulip(pCurHcb) == -1) + return (-1); + break; - case DATA_OUT: /* Data out phase */ - return (tul_xpad_out(pCurHcb)); + case DATA_IN: /* Data in phase */ + return (tul_xpad_in(pCurHcb)); - default: - return (tul_bad_seq(pCurHcb)); + case DATA_OUT: /* Data out phase */ + return (tul_xpad_out(pCurHcb)); + + default: + return (tul_bad_seq(pCurHcb)); + } } - } } /***************************************************************************/ -int tul_state_7(HCS *pCurHcb) +int tul_state_7(HCS * pCurHcb) { - int cnt, i; + int cnt, i; #if DEBUG_STATE -printk("-s7-"); + printk("-s7-"); #endif /* flush SCSI FIFO */ - cnt = TUL_RD(pCurHcb->HCS_Base, TUL_SFifoCnt) & 0x1F; - if (cnt) { - for (i = 0; i < cnt; i++) - TUL_RD(pCurHcb->HCS_Base, TUL_SFifo); - } - - switch (pCurHcb->HCS_Phase) { - case DATA_IN: /* Data in phase */ - case DATA_OUT: /* Data out phase */ - return (tul_bad_seq(pCurHcb)); + cnt = TUL_RD(pCurHcb->HCS_Base, TUL_SFifoCnt) & 0x1F; + if (cnt) { + for (i = 0; i < cnt; i++) + TUL_RD(pCurHcb->HCS_Base, TUL_SFifo); + } + switch (pCurHcb->HCS_Phase) { + case DATA_IN: /* Data in phase */ + case DATA_OUT: /* Data out phase */ + return (tul_bad_seq(pCurHcb)); default: - return (6); /* Go to state 6 */ - } + return (6); /* Go to state 6 */ + } } /***************************************************************************/ -int tul_xfer_data_in(HCS *pCurHcb) +int tul_xfer_data_in(HCS * pCurHcb) { - SCB *pCurScb = pCurHcb->HCS_ActScb; + SCB *pCurScb = pCurHcb->HCS_ActScb; -/*printk("\nEnter xfer data in; ptr = %lx; cnt = %lx\n", pCurScb->SCB_BufPtr, - pCurScb->SCB_BufLen);*/ - if ((pCurScb->SCB_Flags & SCF_DIR) == SCF_DOUT) { - return (6); /* wrong direction */ - } - TUL_WRLONG(pCurHcb->HCS_Base+ TUL_SCnt0, pCurScb->SCB_BufLen); + if ((pCurScb->SCB_Flags & SCF_DIR) == SCF_DOUT) { + return (6); /* wrong direction */ + } + TUL_WRLONG(pCurHcb->HCS_Base + TUL_SCnt0, pCurScb->SCB_BufLen); - TUL_WR(pCurHcb->HCS_Base+ TUL_SCmd, TSC_XF_DMA_IN); /* 7/25/95 */ + TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_DMA_IN); /* 7/25/95 */ - if (pCurScb->SCB_Flags & SCF_SG) { /* S/G xfer */ - TUL_WRLONG(pCurHcb->HCS_Base+ TUL_XCntH, ((ULONG)pCurScb->SCB_SGLen) << 3); - TUL_WRLONG(pCurHcb->HCS_Base+ TUL_XAddH, pCurScb->SCB_BufPtr); - TUL_WR(pCurHcb->HCS_Base+ TUL_XCmd, TAX_SG_IN); - } else { - TUL_WRLONG(pCurHcb->HCS_Base+ TUL_XCntH, pCurScb->SCB_BufLen); - TUL_WRLONG(pCurHcb->HCS_Base+ TUL_XAddH, pCurScb->SCB_BufPtr); - TUL_WR(pCurHcb->HCS_Base+ TUL_XCmd, TAX_X_IN); - } - pCurScb->SCB_NxtStat = 0x5; - return (0); /* return to OS, wait xfer done , let jas_isr come in */ + if (pCurScb->SCB_Flags & SCF_SG) { /* S/G xfer */ + TUL_WRLONG(pCurHcb->HCS_Base + TUL_XCntH, ((ULONG) pCurScb->SCB_SGLen) << 3); + TUL_WRLONG(pCurHcb->HCS_Base + TUL_XAddH, pCurScb->SCB_BufPtr); + TUL_WR(pCurHcb->HCS_Base + TUL_XCmd, TAX_SG_IN); + } else { + TUL_WRLONG(pCurHcb->HCS_Base + TUL_XCntH, pCurScb->SCB_BufLen); + TUL_WRLONG(pCurHcb->HCS_Base + TUL_XAddH, pCurScb->SCB_BufPtr); + TUL_WR(pCurHcb->HCS_Base + TUL_XCmd, TAX_X_IN); + } + pCurScb->SCB_NxtStat = 0x5; + return (0); /* return to OS, wait xfer done , let jas_isr come in */ } /***************************************************************************/ -int tul_xfer_data_out(HCS *pCurHcb) +int tul_xfer_data_out(HCS * pCurHcb) { - SCB *pCurScb = pCurHcb->HCS_ActScb; - -/*printk("Enter xfer data out\n");*/ - if ((pCurScb->SCB_Flags & SCF_DIR) == SCF_DIN) { - return (6); /* wrong direction */ - } + SCB *pCurScb = pCurHcb->HCS_ActScb; - TUL_WRLONG(pCurHcb->HCS_Base+ TUL_SCnt0, pCurScb->SCB_BufLen); - TUL_WR(pCurHcb->HCS_Base+ TUL_SCmd, TSC_XF_DMA_OUT); + if ((pCurScb->SCB_Flags & SCF_DIR) == SCF_DIN) { + return (6); /* wrong direction */ + } + TUL_WRLONG(pCurHcb->HCS_Base + TUL_SCnt0, pCurScb->SCB_BufLen); + TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_DMA_OUT); - if (pCurScb->SCB_Flags & SCF_SG) { /* S/G xfer */ - TUL_WRLONG(pCurHcb->HCS_Base+ TUL_XCntH, ((ULONG)pCurScb->SCB_SGLen) << 3); - TUL_WRLONG(pCurHcb->HCS_Base+ TUL_XAddH, pCurScb->SCB_BufPtr); - TUL_WR(pCurHcb->HCS_Base+ TUL_XCmd, TAX_SG_OUT); - } else { - TUL_WRLONG(pCurHcb->HCS_Base+ TUL_XCntH, pCurScb->SCB_BufLen); - TUL_WRLONG(pCurHcb->HCS_Base+ TUL_XAddH, pCurScb->SCB_BufPtr); - TUL_WR(pCurHcb->HCS_Base+ TUL_XCmd, TAX_X_OUT); - } + if (pCurScb->SCB_Flags & SCF_SG) { /* S/G xfer */ + TUL_WRLONG(pCurHcb->HCS_Base + TUL_XCntH, ((ULONG) pCurScb->SCB_SGLen) << 3); + TUL_WRLONG(pCurHcb->HCS_Base + TUL_XAddH, pCurScb->SCB_BufPtr); + TUL_WR(pCurHcb->HCS_Base + TUL_XCmd, TAX_SG_OUT); + } else { + TUL_WRLONG(pCurHcb->HCS_Base + TUL_XCntH, pCurScb->SCB_BufLen); + TUL_WRLONG(pCurHcb->HCS_Base + TUL_XAddH, pCurScb->SCB_BufPtr); + TUL_WR(pCurHcb->HCS_Base + TUL_XCmd, TAX_X_OUT); + } - pCurScb->SCB_NxtStat = 0x5; - return (0); /* return to OS, wait xfer done , let jas_isr come in */ + pCurScb->SCB_NxtStat = 0x5; + return (0); /* return to OS, wait xfer done , let jas_isr come in */ } /***************************************************************************/ -int tul_xpad_in(HCS *pCurHcb) +int tul_xpad_in(HCS * pCurHcb) { - SCB *pCurScb = pCurHcb->HCS_ActScb; - TCS *pCurTcb = pCurHcb->HCS_ActTcs; + SCB *pCurScb = pCurHcb->HCS_ActScb; + TCS *pCurTcb = pCurHcb->HCS_ActTcs; - if ((pCurScb->SCB_Flags & SCF_DIR) != SCF_NO_DCHK) { - pCurScb->SCB_HaStat = HOST_DO_DU; /* over run */ - } - for (;;) { - if (pCurTcb->TCS_JS_Period & TSC_WIDE_SCSI) - TUL_WRLONG(pCurHcb->HCS_Base+ TUL_SCnt0, 2); - else - TUL_WRLONG(pCurHcb->HCS_Base+ TUL_SCnt0, 1); + if ((pCurScb->SCB_Flags & SCF_DIR) != SCF_NO_DCHK) { + pCurScb->SCB_HaStat = HOST_DO_DU; /* over run */ + } + for (;;) { + if (pCurTcb->TCS_JS_Period & TSC_WIDE_SCSI) + TUL_WRLONG(pCurHcb->HCS_Base + TUL_SCnt0, 2); + else + TUL_WRLONG(pCurHcb->HCS_Base + TUL_SCnt0, 1); - TUL_WR(pCurHcb->HCS_Base+ TUL_SCmd, TSC_XF_FIFO_IN); - if ((wait_tulip(pCurHcb)) == -1) - { - return (-1); - } - if (pCurHcb->HCS_Phase != DATA_IN) - { - TUL_WR(pCurHcb->HCS_Base+ TUL_SCtrl0, TSC_FLUSH_FIFO); - return (6); - } - TUL_RD(pCurHcb->HCS_Base, TUL_SFifo); - } -} - -int tul_xpad_out(HCS *pCurHcb) -{ - SCB *pCurScb = pCurHcb->HCS_ActScb; - TCS *pCurTcb = pCurHcb->HCS_ActTcs; - - if ((pCurScb->SCB_Flags & SCF_DIR) != SCF_NO_DCHK) { - pCurScb->SCB_HaStat = HOST_DO_DU; /* over run */ - } - for (;;) { - if (pCurTcb->TCS_JS_Period & TSC_WIDE_SCSI) - TUL_WRLONG(pCurHcb->HCS_Base+ TUL_SCnt0, 2); - else - TUL_WRLONG(pCurHcb->HCS_Base + TUL_SCnt0, 1); + TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_IN); + if ((wait_tulip(pCurHcb)) == -1) { + return (-1); + } + if (pCurHcb->HCS_Phase != DATA_IN) { + TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO); + return (6); + } + TUL_RD(pCurHcb->HCS_Base, TUL_SFifo); + } +} + +int tul_xpad_out(HCS * pCurHcb) +{ + SCB *pCurScb = pCurHcb->HCS_ActScb; + TCS *pCurTcb = pCurHcb->HCS_ActTcs; - TUL_WR(pCurHcb->HCS_Base+ TUL_SFifo, 0); - TUL_WR(pCurHcb->HCS_Base+ TUL_SCmd, TSC_XF_FIFO_OUT); - if ((wait_tulip(pCurHcb)) == -1) - { - return (-1); - } - if (pCurHcb->HCS_Phase != DATA_OUT) - { /* Disable wide CPU to allow read 16 bits */ - TUL_WR(pCurHcb->HCS_Base+ TUL_SCtrl1, TSC_HW_RESELECT); - TUL_WR(pCurHcb->HCS_Base+ TUL_SCtrl0, TSC_FLUSH_FIFO); - return (6); - } - } + if ((pCurScb->SCB_Flags & SCF_DIR) != SCF_NO_DCHK) { + pCurScb->SCB_HaStat = HOST_DO_DU; /* over run */ + } + for (;;) { + if (pCurTcb->TCS_JS_Period & TSC_WIDE_SCSI) + TUL_WRLONG(pCurHcb->HCS_Base + TUL_SCnt0, 2); + else + TUL_WRLONG(pCurHcb->HCS_Base + TUL_SCnt0, 1); + + TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, 0); + TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT); + if ((wait_tulip(pCurHcb)) == -1) { + return (-1); + } + if (pCurHcb->HCS_Phase != DATA_OUT) { /* Disable wide CPU to allow read 16 bits */ + TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl1, TSC_HW_RESELECT); + TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO); + return (6); + } + } } /***************************************************************************/ -int tul_status_msg(HCS *pCurHcb) /* status & MSG_IN */ -{ - SCB *pCurScb = pCurHcb->HCS_ActScb; - BYTE msg; +int tul_status_msg(HCS * pCurHcb) +{ /* status & MSG_IN */ + SCB *pCurScb = pCurHcb->HCS_ActScb; + BYTE msg; - TUL_WR(pCurHcb->HCS_Base+ TUL_SCmd, TSC_CMD_COMP); - if ((wait_tulip(pCurHcb)) == -1) { - return (-1); - } + TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_CMD_COMP); + if ((wait_tulip(pCurHcb)) == -1) { + return (-1); + } /* get status */ - pCurScb->SCB_TaStat = TUL_RD(pCurHcb->HCS_Base, TUL_SFifo); + pCurScb->SCB_TaStat = TUL_RD(pCurHcb->HCS_Base, TUL_SFifo); - if (pCurHcb->HCS_Phase == MSG_OUT) - { - if (pCurHcb->HCS_JSStatus0 & TSS_PAR_ERROR) - { - TUL_WR(pCurHcb->HCS_Base+ TUL_SFifo, MSG_PARITY); - } - else - { - TUL_WR(pCurHcb->HCS_Base+ TUL_SFifo, MSG_NOP); - } - TUL_WR(pCurHcb->HCS_Base+ TUL_SCmd, TSC_XF_FIFO_OUT); - return (wait_tulip(pCurHcb)); + if (pCurHcb->HCS_Phase == MSG_OUT) { + if (pCurHcb->HCS_JSStatus0 & TSS_PAR_ERROR) { + TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_PARITY); + } else { + TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_NOP); + } + TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT); + return (wait_tulip(pCurHcb)); } - if (pCurHcb->HCS_Phase == MSG_IN) - { - msg = TUL_RD(pCurHcb->HCS_Base, TUL_SFifo); - if (pCurHcb->HCS_JSStatus0 & TSS_PAR_ERROR) - { /* Parity error */ - if ((tul_msgin_accept(pCurHcb)) == -1) - return (-1); - if (pCurHcb->HCS_Phase != MSG_OUT) - return (tul_bad_seq(pCurHcb)); - TUL_WR(pCurHcb->HCS_Base+ TUL_SFifo, MSG_PARITY); - TUL_WR(pCurHcb->HCS_Base+ TUL_SCmd, TSC_XF_FIFO_OUT); - return (wait_tulip(pCurHcb)); - } - if (msg == 0) { /* Command complete */ - - if ((pCurScb->SCB_TaStat & 0x18) == 0x10) - { /* No link support */ - return (tul_bad_seq(pCurHcb)); + if (pCurHcb->HCS_Phase == MSG_IN) { + msg = TUL_RD(pCurHcb->HCS_Base, TUL_SFifo); + if (pCurHcb->HCS_JSStatus0 & TSS_PAR_ERROR) { /* Parity error */ + if ((tul_msgin_accept(pCurHcb)) == -1) + return (-1); + if (pCurHcb->HCS_Phase != MSG_OUT) + return (tul_bad_seq(pCurHcb)); + TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_PARITY); + TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT); + return (wait_tulip(pCurHcb)); } + if (msg == 0) { /* Command complete */ + if ((pCurScb->SCB_TaStat & 0x18) == 0x10) { /* No link support */ + return (tul_bad_seq(pCurHcb)); + } + TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO); + TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_MSG_ACCEPT); + return tul_wait_done_disc(pCurHcb); - TUL_WR(pCurHcb->HCS_Base+ TUL_SCtrl0, TSC_FLUSH_FIFO); - TUL_WR(pCurHcb->HCS_Base+ TUL_SCmd, TSC_MSG_ACCEPT); - return tul_wait_done_disc(pCurHcb); - - } - if ((msg == MSG_LINK_COMP) || (msg == MSG_LINK_FLAG)) - { - if ((pCurScb->SCB_TaStat & 0x18) == 0x10) - return (tul_msgin_accept(pCurHcb)); - } + } + if ((msg == MSG_LINK_COMP) || (msg == MSG_LINK_FLAG)) { + if ((pCurScb->SCB_TaStat & 0x18) == 0x10) + return (tul_msgin_accept(pCurHcb)); + } } - return (tul_bad_seq(pCurHcb)); + return (tul_bad_seq(pCurHcb)); } /***************************************************************************/ /* scsi bus free */ -int int_tul_busfree(HCS *pCurHcb) +int int_tul_busfree(HCS * pCurHcb) { - SCB *pCurScb = pCurHcb->HCS_ActScb; + SCB *pCurScb = pCurHcb->HCS_ActScb; - if (pCurScb != NULL) - { - if (pCurScb->SCB_Status & SCB_SELECT) - { /* selection timeout */ -#if 0 -// if (pCurScb != tul_pop_pend_scb(pCurHcb)) -// { -// printk("Differnet SCB\n"); -// } -#endif - tul_unlink_pend_scb(pCurHcb, pCurScb); -// pCurScb->SCB_Status = SCB_DONE; - pCurScb->SCB_HaStat = HOST_SEL_TOUT; - tul_append_done_scb(pCurHcb, pCurScb); - } - else - { /* Unexpected bus free */ - tul_unlink_busy_scb(pCurHcb, pCurScb); -// pCurScb->SCB_Status = SCB_DONE; - pCurScb->SCB_HaStat = HOST_BUS_FREE; - tul_append_done_scb(pCurHcb, pCurScb); - } - pCurHcb->HCS_ActScb = NULL; - pCurHcb->HCS_ActTcs = NULL; - } - TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO); /* Flush SCSI FIFO */ - TUL_WR(pCurHcb->HCS_Base + TUL_SConfig, TSC_INITDEFAULT); - TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl1, TSC_HW_RESELECT);/* Enable HW reselect */ - return (-1); -/* return (1);*/ + if (pCurScb != NULL) { + if (pCurScb->SCB_Status & SCB_SELECT) { /* selection timeout */ + tul_unlink_pend_scb(pCurHcb, pCurScb); + pCurScb->SCB_HaStat = HOST_SEL_TOUT; + tul_append_done_scb(pCurHcb, pCurScb); + } else { /* Unexpected bus free */ + tul_unlink_busy_scb(pCurHcb, pCurScb); + pCurScb->SCB_HaStat = HOST_BUS_FREE; + tul_append_done_scb(pCurHcb, pCurScb); + } + pCurHcb->HCS_ActScb = NULL; + pCurHcb->HCS_ActTcs = NULL; + } + TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO); /* Flush SCSI FIFO */ + TUL_WR(pCurHcb->HCS_Base + TUL_SConfig, TSC_INITDEFAULT); + TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl1, TSC_HW_RESELECT); /* Enable HW reselect */ + return (-1); } /***************************************************************************/ /* scsi bus reset */ -int int_tul_scsi_rst(HCS *pCurHcb) +int int_tul_scsi_rst(HCS * pCurHcb) { - SCB *pCurScb; - int i; + SCB *pCurScb; + int i; /* if DMA xfer is pending, abort DMA xfer */ - if (TUL_RD(pCurHcb->HCS_Base, TUL_XStatus) & 0x01) - { - TUL_WR(pCurHcb->HCS_Base + TUL_XCmd, TAX_X_ABT | TAX_X_CLR_FIFO); + if (TUL_RD(pCurHcb->HCS_Base, TUL_XStatus) & 0x01) { + TUL_WR(pCurHcb->HCS_Base + TUL_XCmd, TAX_X_ABT | TAX_X_CLR_FIFO); /* wait Abort DMA xfer done */ - while ((TUL_RD(pCurHcb->HCS_Base, TUL_Int) & 0x04) == 0) - ; - TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO); + while ((TUL_RD(pCurHcb->HCS_Base, TUL_Int) & 0x04) == 0); + TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO); } - /* Abort all active & disconnected scb */ - while ((pCurScb = tul_pop_busy_scb(pCurHcb)) != NULL) - { -// pCurScb->SCB_Status = SCB_DONE; - pCurScb->SCB_HaStat = HOST_BAD_PHAS; - tul_append_done_scb(pCurHcb, pCurScb); + /* Abort all active & disconnected scb */ + while ((pCurScb = tul_pop_busy_scb(pCurHcb)) != NULL) { + pCurScb->SCB_HaStat = HOST_BAD_PHAS; + tul_append_done_scb(pCurHcb, pCurScb); } - pCurHcb->HCS_ActScb = NULL; - pCurHcb->HCS_ActTcs = NULL; + pCurHcb->HCS_ActScb = NULL; + pCurHcb->HCS_ActTcs = NULL; /* clr sync nego. done flag */ - for (i = 0; i < pCurHcb->HCS_MaxTar; i++) - { - pCurHcb->HCS_Tcs[i].TCS_Flags &= ~(TCF_SYNC_DONE | TCF_WDTR_DONE); + for (i = 0; i < pCurHcb->HCS_MaxTar; i++) { + pCurHcb->HCS_Tcs[i].TCS_Flags &= ~(TCF_SYNC_DONE | TCF_WDTR_DONE); } - return(-1); + return (-1); } /***************************************************************************/ /* scsi reselection */ -int int_tul_resel(HCS *pCurHcb) +int int_tul_resel(HCS * pCurHcb) { - SCB *pCurScb; - TCS *pCurTcb; - BYTE tag, msg = 0; - BYTE tar, lun; - - if ((pCurScb = pCurHcb->HCS_ActScb) != NULL) - { - if (pCurScb->SCB_Status & SCB_SELECT) - { /* if waiting for selection complete*/ - pCurScb->SCB_Status &= ~SCB_SELECT; - } - pCurHcb->HCS_ActScb = NULL; + SCB *pCurScb; + TCS *pCurTcb; + BYTE tag, msg = 0; + BYTE tar, lun; + + if ((pCurScb = pCurHcb->HCS_ActScb) != NULL) { + if (pCurScb->SCB_Status & SCB_SELECT) { /* if waiting for selection complete */ + pCurScb->SCB_Status &= ~SCB_SELECT; + } + pCurHcb->HCS_ActScb = NULL; } - /* --------- get target id---------------------- */ - tar = TUL_RD(pCurHcb->HCS_Base, TUL_SBusId); + tar = TUL_RD(pCurHcb->HCS_Base, TUL_SBusId); /* ------ get LUN from Identify message----------- */ - lun = TUL_RD(pCurHcb->HCS_Base, TUL_SIdent) & 0x0F; - /* 07/22/98 from 0x1F -> 0x0F */ - pCurTcb = &pCurHcb->HCS_Tcs[tar]; - pCurHcb->HCS_ActTcs = pCurTcb; - TUL_WR(pCurHcb->HCS_Base + TUL_SConfig, pCurTcb->TCS_SConfig0); - TUL_WR(pCurHcb->HCS_Base+ TUL_SPeriod, pCurTcb->TCS_JS_Period); + lun = TUL_RD(pCurHcb->HCS_Base, TUL_SIdent) & 0x0F; + /* 07/22/98 from 0x1F -> 0x0F */ + pCurTcb = &pCurHcb->HCS_Tcs[tar]; + pCurHcb->HCS_ActTcs = pCurTcb; + TUL_WR(pCurHcb->HCS_Base + TUL_SConfig, pCurTcb->TCS_SConfig0); + TUL_WR(pCurHcb->HCS_Base + TUL_SPeriod, pCurTcb->TCS_JS_Period); /* ------------- tag queueing ? ------------------- */ - if (pCurTcb->TCS_DrvFlags & TCF_DRV_EN_TAG) - { -/*printk("Tag enabled\n");*/ - if ((tul_msgin_accept(pCurHcb)) == -1) - return (-1); - if (pCurHcb->HCS_Phase != MSG_IN) - goto no_tag; - TUL_WRLONG(pCurHcb->HCS_Base + TUL_SCnt0, 1); - TUL_WR(pCurHcb->HCS_Base+ TUL_SCmd, TSC_XF_FIFO_IN); - if ((wait_tulip(pCurHcb)) == -1) - return (-1); - msg = TUL_RD(pCurHcb->HCS_Base, TUL_SFifo); /* Read Tag Message */ + if (pCurTcb->TCS_DrvFlags & TCF_DRV_EN_TAG) { + if ((tul_msgin_accept(pCurHcb)) == -1) + return (-1); + if (pCurHcb->HCS_Phase != MSG_IN) + goto no_tag; + TUL_WRLONG(pCurHcb->HCS_Base + TUL_SCnt0, 1); + TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_IN); + if ((wait_tulip(pCurHcb)) == -1) + return (-1); + msg = TUL_RD(pCurHcb->HCS_Base, TUL_SFifo); /* Read Tag Message */ - if ((msg < MSG_STAG) || (msg > MSG_OTAG)) /* Is simple Tag */ - goto no_tag; + if ((msg < MSG_STAG) || (msg > MSG_OTAG)) /* Is simple Tag */ + goto no_tag; - if ((tul_msgin_accept(pCurHcb)) == -1) - return (-1); + if ((tul_msgin_accept(pCurHcb)) == -1) + return (-1); - if (pCurHcb->HCS_Phase != MSG_IN) - goto no_tag; + if (pCurHcb->HCS_Phase != MSG_IN) + goto no_tag; - TUL_WRLONG(pCurHcb->HCS_Base + TUL_SCnt0, 1); - TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_IN); - if ((wait_tulip(pCurHcb)) == -1) - return (-1); - tag = TUL_RD(pCurHcb->HCS_Base, TUL_SFifo); /* Read Tag ID */ - pCurScb = pCurHcb->HCS_Scb + tag; - if ((pCurScb->SCB_Target != tar) || (pCurScb->SCB_Lun != lun)) - { - return tul_msgout_abort_tag(pCurHcb); - } - if (pCurScb->SCB_Status != SCB_BUSY) - { /* 03/24/95 */ - return tul_msgout_abort_tag(pCurHcb); - } - pCurHcb->HCS_ActScb = pCurScb; - if ((tul_msgin_accept(pCurHcb)) == -1) - return (-1); - } - else /* No tag */ - { -no_tag: - if ((pCurScb = tul_find_busy_scb(pCurHcb, tar | (lun << 8))) == NULL) - { -/*printk("SCB pointer = NULL\n");*/ - return tul_msgout_abort_targ(pCurHcb); - } - pCurHcb->HCS_ActScb = pCurScb; - if (!(pCurTcb->TCS_DrvFlags & TCF_DRV_EN_TAG)) - { - if ((tul_msgin_accept(pCurHcb)) == -1) - return (-1); - } + TUL_WRLONG(pCurHcb->HCS_Base + TUL_SCnt0, 1); + TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_IN); + if ((wait_tulip(pCurHcb)) == -1) + return (-1); + tag = TUL_RD(pCurHcb->HCS_Base, TUL_SFifo); /* Read Tag ID */ + pCurScb = pCurHcb->HCS_Scb + tag; + if ((pCurScb->SCB_Target != tar) || (pCurScb->SCB_Lun != lun)) { + return tul_msgout_abort_tag(pCurHcb); + } + if (pCurScb->SCB_Status != SCB_BUSY) { /* 03/24/95 */ + return tul_msgout_abort_tag(pCurHcb); + } + pCurHcb->HCS_ActScb = pCurScb; + if ((tul_msgin_accept(pCurHcb)) == -1) + return (-1); + } else { /* No tag */ + no_tag: + if ((pCurScb = tul_find_busy_scb(pCurHcb, tar | (lun << 8))) == NULL) { + return tul_msgout_abort_targ(pCurHcb); + } + pCurHcb->HCS_ActScb = pCurScb; + if (!(pCurTcb->TCS_DrvFlags & TCF_DRV_EN_TAG)) { + if ((tul_msgin_accept(pCurHcb)) == -1) + return (-1); + } } - return 0; + return 0; } /***************************************************************************/ -int int_tul_bad_seq(HCS *pCurHcb) /* target wrong phase */ -{ - SCB *pCurScb; - int i; - - tul_reset_scsi(pCurHcb, 10); - - while ((pCurScb = tul_pop_busy_scb(pCurHcb)) != NULL) - { -// pCurScb->SCB_Status = SCB_DONE; - pCurScb->SCB_HaStat = HOST_BAD_PHAS; - tul_append_done_scb(pCurHcb, pCurScb); +int int_tul_bad_seq(HCS * pCurHcb) +{ /* target wrong phase */ + SCB *pCurScb; + int i; + + tul_reset_scsi(pCurHcb, 10); + + while ((pCurScb = tul_pop_busy_scb(pCurHcb)) != NULL) { + pCurScb->SCB_HaStat = HOST_BAD_PHAS; + tul_append_done_scb(pCurHcb, pCurScb); } - for (i = 0; i < pCurHcb->HCS_MaxTar; i++) - { - pCurHcb->HCS_Tcs[i].TCS_Flags &= ~(TCF_SYNC_DONE | TCF_WDTR_DONE);; + for (i = 0; i < pCurHcb->HCS_MaxTar; i++) { + pCurHcb->HCS_Tcs[i].TCS_Flags &= ~(TCF_SYNC_DONE | TCF_WDTR_DONE);; } - return (-1); + return (-1); } /***************************************************************************/ -int tul_msgout_abort_targ(HCS *pCurHcb) +int tul_msgout_abort_targ(HCS * pCurHcb) { - TUL_WR(pCurHcb->HCS_Base + TUL_SSignal, ((TUL_RD(pCurHcb->HCS_Base, TUL_SSignal) & (TSC_SET_ACK | 7)) | TSC_SET_ATN)); - if (tul_msgin_accept(pCurHcb) == -1) - return(-1); - if (pCurHcb->HCS_Phase != MSG_OUT) - return(tul_bad_seq(pCurHcb)); + TUL_WR(pCurHcb->HCS_Base + TUL_SSignal, ((TUL_RD(pCurHcb->HCS_Base, TUL_SSignal) & (TSC_SET_ACK | 7)) | TSC_SET_ATN)); + if (tul_msgin_accept(pCurHcb) == -1) + return (-1); + if (pCurHcb->HCS_Phase != MSG_OUT) + return (tul_bad_seq(pCurHcb)); - TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_ABORT); - TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT); + TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_ABORT); + TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT); - return tul_wait_disc(pCurHcb); + return tul_wait_disc(pCurHcb); } /***************************************************************************/ -int tul_msgout_abort_tag(HCS *pCurHcb) +int tul_msgout_abort_tag(HCS * pCurHcb) { - TUL_WR(pCurHcb->HCS_Base + TUL_SSignal, ((TUL_RD(pCurHcb->HCS_Base, TUL_SSignal) & (TSC_SET_ACK | 7)) | TSC_SET_ATN)); - if (tul_msgin_accept(pCurHcb) == -1) - return(-1); - if (pCurHcb->HCS_Phase != MSG_OUT) - return(tul_bad_seq(pCurHcb)); + TUL_WR(pCurHcb->HCS_Base + TUL_SSignal, ((TUL_RD(pCurHcb->HCS_Base, TUL_SSignal) & (TSC_SET_ACK | 7)) | TSC_SET_ATN)); + if (tul_msgin_accept(pCurHcb) == -1) + return (-1); + if (pCurHcb->HCS_Phase != MSG_OUT) + return (tul_bad_seq(pCurHcb)); - TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_ABORT_TAG); - TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT); + TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_ABORT_TAG); + TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT); - return tul_wait_disc(pCurHcb); + return tul_wait_disc(pCurHcb); } /***************************************************************************/ -int tul_msgin(HCS *pCurHcb) +int tul_msgin(HCS * pCurHcb) { - TCS *pCurTcb; + TCS *pCurTcb; - for (;;) { + for (;;) { - TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO); + TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO); - TUL_WRLONG(pCurHcb->HCS_Base + TUL_SCnt0, 1); - TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_IN); - if ((wait_tulip(pCurHcb)) == -1) - return (-1); + TUL_WRLONG(pCurHcb->HCS_Base + TUL_SCnt0, 1); + TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_IN); + if ((wait_tulip(pCurHcb)) == -1) + return (-1); - switch (TUL_RD(pCurHcb->HCS_Base, TUL_SFifo)) { - case MSG_DISC: /* Disconnect msg */ - TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_MSG_ACCEPT); - - return tul_wait_disc(pCurHcb); - - case MSG_SDP: - case MSG_RESTORE: - case MSG_NOP: - tul_msgin_accept(pCurHcb); - break; - - case MSG_REJ: /* Clear ATN first */ - TUL_WR(pCurHcb->HCS_Base + TUL_SSignal, - (TUL_RD(pCurHcb->HCS_Base, TUL_SSignal) & (TSC_SET_ACK | 7))); - pCurTcb = pCurHcb->HCS_ActTcs; - if ((pCurTcb->TCS_Flags & (TCF_SYNC_DONE | TCF_NO_SYNC_NEGO)) == 0) - { /* do sync nego */ - TUL_WR(pCurHcb->HCS_Base + TUL_SSignal, ((TUL_RD(pCurHcb->HCS_Base, TUL_SSignal) & (TSC_SET_ACK | 7)) | TSC_SET_ATN)); - } - tul_msgin_accept(pCurHcb); - break; - - case MSG_EXTEND: /* extended msg */ - tul_msgin_extend(pCurHcb); - break; - - case MSG_IGNOREWIDE: - tul_msgin_accept(pCurHcb); - break; + switch (TUL_RD(pCurHcb->HCS_Base, TUL_SFifo)) { + case MSG_DISC: /* Disconnect msg */ + TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_MSG_ACCEPT); + + return tul_wait_disc(pCurHcb); + + case MSG_SDP: + case MSG_RESTORE: + case MSG_NOP: + tul_msgin_accept(pCurHcb); + break; - /* get */ - TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_IN); - if (wait_tulip(pCurHcb) == -1) - return -1; + case MSG_REJ: /* Clear ATN first */ + TUL_WR(pCurHcb->HCS_Base + TUL_SSignal, + (TUL_RD(pCurHcb->HCS_Base, TUL_SSignal) & (TSC_SET_ACK | 7))); + pCurTcb = pCurHcb->HCS_ActTcs; + if ((pCurTcb->TCS_Flags & (TCF_SYNC_DONE | TCF_NO_SYNC_NEGO)) == 0) { /* do sync nego */ + TUL_WR(pCurHcb->HCS_Base + TUL_SSignal, ((TUL_RD(pCurHcb->HCS_Base, TUL_SSignal) & (TSC_SET_ACK | 7)) | TSC_SET_ATN)); + } + tul_msgin_accept(pCurHcb); + break; + + case MSG_EXTEND: /* extended msg */ + tul_msgin_extend(pCurHcb); + break; + + case MSG_IGNOREWIDE: + tul_msgin_accept(pCurHcb); + break; + + /* get */ + TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_IN); + if (wait_tulip(pCurHcb) == -1) + return -1; + + TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, 0); /* put pad */ + TUL_RD(pCurHcb->HCS_Base, TUL_SFifo); /* get IGNORE field */ + TUL_RD(pCurHcb->HCS_Base, TUL_SFifo); /* get pad */ - TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, 0); /* put pad */ - TUL_RD(pCurHcb->HCS_Base, TUL_SFifo); /* get IGNORE field */ - TUL_RD(pCurHcb->HCS_Base, TUL_SFifo); /* get pad */ - - tul_msgin_accept(pCurHcb); - break; - - case MSG_COMP: - { - TUL_WR(pCurHcb->HCS_Base+ TUL_SCtrl0, TSC_FLUSH_FIFO); - TUL_WR(pCurHcb->HCS_Base+ TUL_SCmd, TSC_MSG_ACCEPT); - return tul_wait_done_disc(pCurHcb); - } - default: - tul_msgout_reject(pCurHcb); - break; - } - if (pCurHcb->HCS_Phase != MSG_IN) - return (pCurHcb->HCS_Phase); - } + tul_msgin_accept(pCurHcb); + break; + + case MSG_COMP: + { + TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO); + TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_MSG_ACCEPT); + return tul_wait_done_disc(pCurHcb); + } + default: + tul_msgout_reject(pCurHcb); + break; + } + if (pCurHcb->HCS_Phase != MSG_IN) + return (pCurHcb->HCS_Phase); + } /* statement won't reach here */ } @@ -2826,507 +2350,425 @@ /***************************************************************************/ -int tul_msgout_reject(HCS *pCurHcb) +int tul_msgout_reject(HCS * pCurHcb) { - TUL_WR(pCurHcb->HCS_Base + TUL_SSignal, ((TUL_RD(pCurHcb->HCS_Base, TUL_SSignal) & (TSC_SET_ACK | 7)) | TSC_SET_ATN)); + TUL_WR(pCurHcb->HCS_Base + TUL_SSignal, ((TUL_RD(pCurHcb->HCS_Base, TUL_SSignal) & (TSC_SET_ACK | 7)) | TSC_SET_ATN)); - if ((tul_msgin_accept(pCurHcb)) == -1) - return(-1); + if ((tul_msgin_accept(pCurHcb)) == -1) + return (-1); - if (pCurHcb->HCS_Phase == MSG_OUT) - { - TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_REJ); /* Msg reject */ - TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT); - return (wait_tulip(pCurHcb)); + if (pCurHcb->HCS_Phase == MSG_OUT) { + TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_REJ); /* Msg reject */ + TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT); + return (wait_tulip(pCurHcb)); } - return (pCurHcb->HCS_Phase); + return (pCurHcb->HCS_Phase); } /***************************************************************************/ -int tul_msgout_ide(HCS *pCurHcb) +int tul_msgout_ide(HCS * pCurHcb) { - TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_IDE); /* Initiator Detected Error */ - TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT); - return (wait_tulip(pCurHcb)); + TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_IDE); /* Initiator Detected Error */ + TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT); + return (wait_tulip(pCurHcb)); } /***************************************************************************/ -int tul_msgin_extend(HCS *pCurHcb) +int tul_msgin_extend(HCS * pCurHcb) { - BYTE len, idx; - - if (tul_msgin_accept(pCurHcb) != MSG_IN) - return (pCurHcb->HCS_Phase); + BYTE len, idx; - /* Get extended msg length */ - TUL_WRLONG(pCurHcb->HCS_Base+ TUL_SCnt0, 1); - TUL_WR(pCurHcb->HCS_Base+ TUL_SCmd, TSC_XF_FIFO_IN); - if (wait_tulip(pCurHcb) == -1) - return (-1); + if (tul_msgin_accept(pCurHcb) != MSG_IN) + return (pCurHcb->HCS_Phase); - len = TUL_RD(pCurHcb->HCS_Base, TUL_SFifo); - pCurHcb->HCS_Msg[0] = len; - for (idx = 1 ; len != 0; len--) { - - if ((tul_msgin_accept(pCurHcb)) != MSG_IN) - return (pCurHcb->HCS_Phase); - TUL_WRLONG(pCurHcb->HCS_Base+ TUL_SCnt0, 1); - TUL_WR(pCurHcb->HCS_Base+ TUL_SCmd, TSC_XF_FIFO_IN); + /* Get extended msg length */ + TUL_WRLONG(pCurHcb->HCS_Base + TUL_SCnt0, 1); + TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_IN); if (wait_tulip(pCurHcb) == -1) - return (-1); - pCurHcb->HCS_Msg[idx++] = TUL_RD(pCurHcb->HCS_Base, TUL_SFifo); + return (-1); + + len = TUL_RD(pCurHcb->HCS_Base, TUL_SFifo); + pCurHcb->HCS_Msg[0] = len; + for (idx = 1; len != 0; len--) { + + if ((tul_msgin_accept(pCurHcb)) != MSG_IN) + return (pCurHcb->HCS_Phase); + TUL_WRLONG(pCurHcb->HCS_Base + TUL_SCnt0, 1); + TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_IN); + if (wait_tulip(pCurHcb) == -1) + return (-1); + pCurHcb->HCS_Msg[idx++] = TUL_RD(pCurHcb->HCS_Base, TUL_SFifo); } - if (pCurHcb->HCS_Msg[1] == 1) - { /* if it's synchronous data transfer request */ - if (pCurHcb->HCS_Msg[0] != 3) /* if length is not right */ - return (tul_msgout_reject(pCurHcb)); - if (pCurHcb->HCS_ActTcs->TCS_Flags & TCF_NO_SYNC_NEGO) - { /* Set OFFSET=0 to do async, nego back */ - pCurHcb->HCS_Msg[3] = 0; - } - else - { - if ((tul_msgin_sync(pCurHcb) == 0) && - (pCurHcb->HCS_ActTcs->TCS_Flags & TCF_SYNC_DONE)) - { - tul_sync_done(pCurHcb); - return (tul_msgin_accept(pCurHcb)); + if (pCurHcb->HCS_Msg[1] == 1) { /* if it's synchronous data transfer request */ + if (pCurHcb->HCS_Msg[0] != 3) /* if length is not right */ + return (tul_msgout_reject(pCurHcb)); + if (pCurHcb->HCS_ActTcs->TCS_Flags & TCF_NO_SYNC_NEGO) { /* Set OFFSET=0 to do async, nego back */ + pCurHcb->HCS_Msg[3] = 0; + } else { + if ((tul_msgin_sync(pCurHcb) == 0) && + (pCurHcb->HCS_ActTcs->TCS_Flags & TCF_SYNC_DONE)) { + tul_sync_done(pCurHcb); + return (tul_msgin_accept(pCurHcb)); + } } - } - TUL_WR(pCurHcb->HCS_Base+ TUL_SSignal, ((TUL_RD(pCurHcb->HCS_Base, TUL_SSignal) & (TSC_SET_ACK | 7)) | TSC_SET_ATN)); - if ((tul_msgin_accept(pCurHcb)) != MSG_OUT) - return (pCurHcb->HCS_Phase); - /* sync msg out */ - TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO); -/* TUL_WR(pCurHcb->HCS_Base+ TUL_SFifo, TSC_FLUSH_FIFO); */ + TUL_WR(pCurHcb->HCS_Base + TUL_SSignal, ((TUL_RD(pCurHcb->HCS_Base, TUL_SSignal) & (TSC_SET_ACK | 7)) | TSC_SET_ATN)); + if ((tul_msgin_accept(pCurHcb)) != MSG_OUT) + return (pCurHcb->HCS_Phase); + /* sync msg out */ + TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO); - tul_sync_done(pCurHcb); + tul_sync_done(pCurHcb); - TUL_WR(pCurHcb->HCS_Base+ TUL_SFifo, MSG_EXTEND); - TUL_WR(pCurHcb->HCS_Base+ TUL_SFifo, 3); - TUL_WR(pCurHcb->HCS_Base+ TUL_SFifo, 1); - TUL_WR(pCurHcb->HCS_Base+ TUL_SFifo, pCurHcb->HCS_Msg[2]); - TUL_WR(pCurHcb->HCS_Base+ TUL_SFifo, pCurHcb->HCS_Msg[3]); + TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_EXTEND); + TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, 3); + TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, 1); + TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, pCurHcb->HCS_Msg[2]); + TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, pCurHcb->HCS_Msg[3]); - TUL_WR(pCurHcb->HCS_Base+ TUL_SCmd, TSC_XF_FIFO_OUT); - return (wait_tulip(pCurHcb)); + TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT); + return (wait_tulip(pCurHcb)); } - - if ((pCurHcb->HCS_Msg[0] != 2) || (pCurHcb->HCS_Msg[1] != 3)) - return (tul_msgout_reject(pCurHcb)); - /* if it's WIDE DATA XFER REQ */ - if (pCurHcb->HCS_ActTcs->TCS_Flags & TCF_NO_WDTR) - { - pCurHcb->HCS_Msg[2] = 0; - } - else - { - if (pCurHcb->HCS_Msg[2] > 2) /* > 32 bits */ - return (tul_msgout_reject(pCurHcb)); - if (pCurHcb->HCS_Msg[2] == 2) /* == 32 */ - { - pCurHcb->HCS_Msg[2] = 1; - } - else - { - if ((pCurHcb->HCS_ActTcs->TCS_Flags & TCF_NO_WDTR) == 0) - { - wdtr_done(pCurHcb); - if ((pCurHcb->HCS_ActTcs->TCS_Flags & (TCF_SYNC_DONE | TCF_NO_SYNC_NEGO)) == 0) - TUL_WR(pCurHcb->HCS_Base+ TUL_SSignal, ((TUL_RD(pCurHcb->HCS_Base, TUL_SSignal) & (TSC_SET_ACK | 7)) | TSC_SET_ATN)); - return (tul_msgin_accept(pCurHcb)); + if ((pCurHcb->HCS_Msg[0] != 2) || (pCurHcb->HCS_Msg[1] != 3)) + return (tul_msgout_reject(pCurHcb)); + /* if it's WIDE DATA XFER REQ */ + if (pCurHcb->HCS_ActTcs->TCS_Flags & TCF_NO_WDTR) { + pCurHcb->HCS_Msg[2] = 0; + } else { + if (pCurHcb->HCS_Msg[2] > 2) /* > 32 bits */ + return (tul_msgout_reject(pCurHcb)); + if (pCurHcb->HCS_Msg[2] == 2) { /* == 32 */ + pCurHcb->HCS_Msg[2] = 1; + } else { + if ((pCurHcb->HCS_ActTcs->TCS_Flags & TCF_NO_WDTR) == 0) { + wdtr_done(pCurHcb); + if ((pCurHcb->HCS_ActTcs->TCS_Flags & (TCF_SYNC_DONE | TCF_NO_SYNC_NEGO)) == 0) + TUL_WR(pCurHcb->HCS_Base + TUL_SSignal, ((TUL_RD(pCurHcb->HCS_Base, TUL_SSignal) & (TSC_SET_ACK | 7)) | TSC_SET_ATN)); + return (tul_msgin_accept(pCurHcb)); + } } - } } - TUL_WR(pCurHcb->HCS_Base+ TUL_SSignal, ((TUL_RD(pCurHcb->HCS_Base, TUL_SSignal) & (TSC_SET_ACK | 7)) | TSC_SET_ATN)); + TUL_WR(pCurHcb->HCS_Base + TUL_SSignal, ((TUL_RD(pCurHcb->HCS_Base, TUL_SSignal) & (TSC_SET_ACK | 7)) | TSC_SET_ATN)); - if (tul_msgin_accept(pCurHcb) != MSG_OUT) - return (pCurHcb->HCS_Phase); - /* WDTR msg out */ - TUL_WR(pCurHcb->HCS_Base+ TUL_SFifo, MSG_EXTEND); - TUL_WR(pCurHcb->HCS_Base+ TUL_SFifo, 2); - TUL_WR(pCurHcb->HCS_Base+ TUL_SFifo, 3); - TUL_WR(pCurHcb->HCS_Base+ TUL_SFifo, pCurHcb->HCS_Msg[2]); - TUL_WR(pCurHcb->HCS_Base+ TUL_SCmd, TSC_XF_FIFO_OUT); - return (wait_tulip(pCurHcb)); + if (tul_msgin_accept(pCurHcb) != MSG_OUT) + return (pCurHcb->HCS_Phase); + /* WDTR msg out */ + TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_EXTEND); + TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, 2); + TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, 3); + TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, pCurHcb->HCS_Msg[2]); + TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT); + return (wait_tulip(pCurHcb)); } /***************************************************************************/ -int tul_msgin_sync(HCS *pCurHcb) -{ - char default_period; - - default_period = tul_rate_tbl[pCurHcb->HCS_ActTcs->TCS_Flags & TCF_SCSI_RATE]; - if (pCurHcb->HCS_Msg[3] > MAX_OFFSET) - { - pCurHcb->HCS_Msg[3] = MAX_OFFSET; - if (pCurHcb->HCS_Msg[2] < default_period) - { - pCurHcb->HCS_Msg[2] = default_period; - return 1; - } - if (pCurHcb->HCS_Msg[2] >= 59) - { /* Change to async */ - pCurHcb->HCS_Msg[3] = 0; - } - return 1; - } +int tul_msgin_sync(HCS * pCurHcb) +{ + char default_period; - /* offset requests asynchronous transfers ? */ - if (pCurHcb->HCS_Msg[3] == 0) - { - return 0; + default_period = tul_rate_tbl[pCurHcb->HCS_ActTcs->TCS_Flags & TCF_SCSI_RATE]; + if (pCurHcb->HCS_Msg[3] > MAX_OFFSET) { + pCurHcb->HCS_Msg[3] = MAX_OFFSET; + if (pCurHcb->HCS_Msg[2] < default_period) { + pCurHcb->HCS_Msg[2] = default_period; + return 1; + } + if (pCurHcb->HCS_Msg[2] >= 59) { /* Change to async */ + pCurHcb->HCS_Msg[3] = 0; + } + return 1; } - if (pCurHcb->HCS_Msg[2] < default_period) - { - pCurHcb->HCS_Msg[2] = default_period; - return 1; + /* offset requests asynchronous transfers ? */ + if (pCurHcb->HCS_Msg[3] == 0) { + return 0; } - - if (pCurHcb->HCS_Msg[2] >= 59) - { - pCurHcb->HCS_Msg[3] = 0; - return 1; + if (pCurHcb->HCS_Msg[2] < default_period) { + pCurHcb->HCS_Msg[2] = default_period; + return 1; } - return 0; + if (pCurHcb->HCS_Msg[2] >= 59) { + pCurHcb->HCS_Msg[3] = 0; + return 1; + } + return 0; } /***************************************************************************/ -int wdtr_done(HCS *pCurHcb) +int wdtr_done(HCS * pCurHcb) { - pCurHcb->HCS_ActTcs->TCS_Flags &= ~TCF_SYNC_DONE; - pCurHcb->HCS_ActTcs->TCS_Flags |= TCF_WDTR_DONE; + pCurHcb->HCS_ActTcs->TCS_Flags &= ~TCF_SYNC_DONE; + pCurHcb->HCS_ActTcs->TCS_Flags |= TCF_WDTR_DONE; - pCurHcb->HCS_ActTcs->TCS_JS_Period = 0; - if (pCurHcb->HCS_Msg[2]) - { /* if 16 bit */ - pCurHcb->HCS_ActTcs->TCS_JS_Period |= TSC_WIDE_SCSI; - } - pCurHcb->HCS_ActTcs->TCS_SConfig0 &= ~TSC_ALT_PERIOD; - TUL_WR(pCurHcb->HCS_Base+TUL_SConfig, pCurHcb->HCS_ActTcs->TCS_SConfig0); - TUL_WR(pCurHcb->HCS_Base+TUL_SPeriod, pCurHcb->HCS_ActTcs->TCS_JS_Period); + pCurHcb->HCS_ActTcs->TCS_JS_Period = 0; + if (pCurHcb->HCS_Msg[2]) { /* if 16 bit */ + pCurHcb->HCS_ActTcs->TCS_JS_Period |= TSC_WIDE_SCSI; + } + pCurHcb->HCS_ActTcs->TCS_SConfig0 &= ~TSC_ALT_PERIOD; + TUL_WR(pCurHcb->HCS_Base + TUL_SConfig, pCurHcb->HCS_ActTcs->TCS_SConfig0); + TUL_WR(pCurHcb->HCS_Base + TUL_SPeriod, pCurHcb->HCS_ActTcs->TCS_JS_Period); - return 1; + return 1; } /***************************************************************************/ -int tul_sync_done(HCS *pCurHcb) +int tul_sync_done(HCS * pCurHcb) { - int i; + int i; - pCurHcb->HCS_ActTcs->TCS_Flags |= TCF_SYNC_DONE; + pCurHcb->HCS_ActTcs->TCS_Flags |= TCF_SYNC_DONE; - if (pCurHcb->HCS_Msg[3]) - { - pCurHcb->HCS_ActTcs->TCS_JS_Period |= pCurHcb->HCS_Msg[3]; - for (i = 0; i < 8; i++) - { - if (tul_rate_tbl[i] >= pCurHcb->HCS_Msg[2]) /* pick the big one */ - break; - } - pCurHcb->HCS_ActTcs->TCS_JS_Period |= (i << 4); - pCurHcb->HCS_ActTcs->TCS_SConfig0 |= TSC_ALT_PERIOD; + if (pCurHcb->HCS_Msg[3]) { + pCurHcb->HCS_ActTcs->TCS_JS_Period |= pCurHcb->HCS_Msg[3]; + for (i = 0; i < 8; i++) { + if (tul_rate_tbl[i] >= pCurHcb->HCS_Msg[2]) /* pick the big one */ + break; + } + pCurHcb->HCS_ActTcs->TCS_JS_Period |= (i << 4); + pCurHcb->HCS_ActTcs->TCS_SConfig0 |= TSC_ALT_PERIOD; } - TUL_WR(pCurHcb->HCS_Base+TUL_SConfig, pCurHcb->HCS_ActTcs->TCS_SConfig0); - TUL_WR(pCurHcb->HCS_Base+TUL_SPeriod, pCurHcb->HCS_ActTcs->TCS_JS_Period); + TUL_WR(pCurHcb->HCS_Base + TUL_SConfig, pCurHcb->HCS_ActTcs->TCS_SConfig0); + TUL_WR(pCurHcb->HCS_Base + TUL_SPeriod, pCurHcb->HCS_ActTcs->TCS_JS_Period); - return (-1); + return (-1); } -int tul_post_scsi_rst(HCS *pCurHcb) +int tul_post_scsi_rst(HCS * pCurHcb) { - SCB *pCurScb; - TCS *pCurTcb; - int i; - - pCurHcb->HCS_ActScb = 0; - pCurHcb->HCS_ActTcs = 0; - pCurHcb->HCS_Flags = 0; - - while ((pCurScb = tul_pop_busy_scb(pCurHcb)) != NULL) - { -// pCurScb->SCB_Status = SCB_DONE; - pCurScb->SCB_HaStat = HOST_BAD_PHAS; - tul_append_done_scb(pCurHcb, pCurScb); - } - /* clear sync done flag */ - pCurTcb = &pCurHcb->HCS_Tcs[0]; - for (i = 0; i < pCurHcb->HCS_MaxTar; pCurTcb++, i++) - { - pCurTcb->TCS_Flags &= ~(TCF_SYNC_DONE | TCF_WDTR_DONE); + SCB *pCurScb; + TCS *pCurTcb; + int i; + + pCurHcb->HCS_ActScb = 0; + pCurHcb->HCS_ActTcs = 0; + pCurHcb->HCS_Flags = 0; + + while ((pCurScb = tul_pop_busy_scb(pCurHcb)) != NULL) { + pCurScb->SCB_HaStat = HOST_BAD_PHAS; + tul_append_done_scb(pCurHcb, pCurScb); + } + /* clear sync done flag */ + pCurTcb = &pCurHcb->HCS_Tcs[0]; + for (i = 0; i < pCurHcb->HCS_MaxTar; pCurTcb++, i++) { + pCurTcb->TCS_Flags &= ~(TCF_SYNC_DONE | TCF_WDTR_DONE); /* Initialize the sync. xfer register values to an asyn xfer */ - pCurTcb->TCS_JS_Period = 0; - pCurTcb->TCS_SConfig0 = pCurHcb->HCS_SConf1; - pCurHcb->HCS_ActTags[0] = 0; /* 07/22/98 */ - pCurHcb->HCS_Tcs[i].TCS_Flags &= ~TCF_BUSY; /* 07/22/98 */ - } /* for */ + pCurTcb->TCS_JS_Period = 0; + pCurTcb->TCS_SConfig0 = pCurHcb->HCS_SConf1; + pCurHcb->HCS_ActTags[0] = 0; /* 07/22/98 */ + pCurHcb->HCS_Tcs[i].TCS_Flags &= ~TCF_BUSY; /* 07/22/98 */ + } /* for */ -// pCurHcb->HCS_Semaph = 1; /* 07/29/98 */ - return (-1); + return (-1); } /***************************************************************************/ -void tul_select_atn_stop(HCS *pCurHcb, SCB *pCurScb) +void tul_select_atn_stop(HCS * pCurHcb, SCB * pCurScb) { - pCurScb->SCB_Status |= SCB_SELECT; - pCurScb->SCB_NxtStat = 0x1; - pCurHcb->HCS_ActScb = pCurScb; - pCurHcb->HCS_ActTcs = &pCurHcb->HCS_Tcs[pCurScb->SCB_Target]; - TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_SELATNSTOP); - return; + pCurScb->SCB_Status |= SCB_SELECT; + pCurScb->SCB_NxtStat = 0x1; + pCurHcb->HCS_ActScb = pCurScb; + pCurHcb->HCS_ActTcs = &pCurHcb->HCS_Tcs[pCurScb->SCB_Target]; + TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_SELATNSTOP); + return; } /***************************************************************************/ -void tul_select_atn(HCS *pCurHcb, SCB *pCurScb) +void tul_select_atn(HCS * pCurHcb, SCB * pCurScb) { - int i; + int i; - pCurScb->SCB_Status |= SCB_SELECT; - pCurScb->SCB_NxtStat = 0x2; + pCurScb->SCB_Status |= SCB_SELECT; + pCurScb->SCB_NxtStat = 0x2; - TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, pCurScb->SCB_Ident); - for (i = 0; i < (int)pCurScb->SCB_CDBLen; i++) - TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, pCurScb->SCB_CDB[i]); - pCurHcb->HCS_ActTcs = &pCurHcb->HCS_Tcs[pCurScb->SCB_Target]; - pCurHcb->HCS_ActScb = pCurScb; - TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_SEL_ATN); - return; + TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, pCurScb->SCB_Ident); + for (i = 0; i < (int) pCurScb->SCB_CDBLen; i++) + TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, pCurScb->SCB_CDB[i]); + pCurHcb->HCS_ActTcs = &pCurHcb->HCS_Tcs[pCurScb->SCB_Target]; + pCurHcb->HCS_ActScb = pCurScb; + TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_SEL_ATN); + return; } /***************************************************************************/ -void tul_select_atn3(HCS *pCurHcb, SCB *pCurScb) +void tul_select_atn3(HCS * pCurHcb, SCB * pCurScb) { - int i; + int i; - pCurScb->SCB_Status |= SCB_SELECT; - pCurScb->SCB_NxtStat = 0x2; + pCurScb->SCB_Status |= SCB_SELECT; + pCurScb->SCB_NxtStat = 0x2; - TUL_WR(pCurHcb->HCS_Base+ TUL_SFifo, pCurScb->SCB_Ident); - TUL_WR(pCurHcb->HCS_Base+ TUL_SFifo, pCurScb->SCB_TagMsg); - TUL_WR(pCurHcb->HCS_Base+ TUL_SFifo, pCurScb->SCB_TagId); - for (i = 0; i < (int) pCurScb->SCB_CDBLen; i++) - TUL_WR(pCurHcb->HCS_Base+ TUL_SFifo, pCurScb->SCB_CDB[i]); - pCurHcb->HCS_ActTcs = &pCurHcb->HCS_Tcs[pCurScb->SCB_Target]; - pCurHcb->HCS_ActScb = pCurScb; - TUL_WR(pCurHcb->HCS_Base+ TUL_SCmd, TSC_SEL_ATN3); - return; + TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, pCurScb->SCB_Ident); + TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, pCurScb->SCB_TagMsg); + TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, pCurScb->SCB_TagId); + for (i = 0; i < (int) pCurScb->SCB_CDBLen; i++) + TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, pCurScb->SCB_CDB[i]); + pCurHcb->HCS_ActTcs = &pCurHcb->HCS_Tcs[pCurScb->SCB_Target]; + pCurHcb->HCS_ActScb = pCurScb; + TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_SEL_ATN3); + return; } /***************************************************************************/ /* SCSI Bus Device Reset */ -int tul_bus_device_reset(HCS *pCurHcb) +int tul_bus_device_reset(HCS * pCurHcb) { - SCB *pCurScb = pCurHcb->HCS_ActScb; - TCS *pCurTcb = pCurHcb->HCS_ActTcs; - SCB *pTmpScb, *pPrevScb; - BYTE tar; + SCB *pCurScb = pCurHcb->HCS_ActScb; + TCS *pCurTcb = pCurHcb->HCS_ActTcs; + SCB *pTmpScb, *pPrevScb; + BYTE tar; - if (pCurHcb->HCS_Phase != MSG_OUT) - { - return (int_tul_bad_seq(pCurHcb)); /* Unexpected phase */ + if (pCurHcb->HCS_Phase != MSG_OUT) { + return (int_tul_bad_seq(pCurHcb)); /* Unexpected phase */ } - - tul_unlink_pend_scb(pCurHcb, pCurScb); -#if 0 - pCurScb->SCB_HaStat = 0; - pCurScb->SCB_Status = SCB_DONE; /* command done */ - tul_append_done_scb(pCurHcb, pCurScb); -#else - tul_release_scb(pCurHcb, pCurScb); -#endif + tul_unlink_pend_scb(pCurHcb, pCurScb); + tul_release_scb(pCurHcb, pCurScb); - tar = pCurScb->SCB_Target; /* target */ - pCurTcb->TCS_Flags &= ~(TCF_SYNC_DONE|TCF_WDTR_DONE|TCF_BUSY); - /* clr sync. nego & WDTR flags 07/22/98 */ + tar = pCurScb->SCB_Target; /* target */ + pCurTcb->TCS_Flags &= ~(TCF_SYNC_DONE | TCF_WDTR_DONE | TCF_BUSY); + /* clr sync. nego & WDTR flags 07/22/98 */ /* abort all SCB with same target */ - pPrevScb = pTmpScb = pCurHcb->HCS_FirstBusy; /* Check Busy queue */ - while (pTmpScb != NULL) { + pPrevScb = pTmpScb = pCurHcb->HCS_FirstBusy; /* Check Busy queue */ + while (pTmpScb != NULL) { - if (pTmpScb->SCB_Target == tar) - { - /* unlink it */ - if (pTmpScb == pCurHcb->HCS_FirstBusy) - { - if ((pCurHcb->HCS_FirstBusy = pTmpScb->SCB_NxtScb) == NULL) - pCurHcb->HCS_LastBusy = NULL; + if (pTmpScb->SCB_Target == tar) { + /* unlink it */ + if (pTmpScb == pCurHcb->HCS_FirstBusy) { + if ((pCurHcb->HCS_FirstBusy = pTmpScb->SCB_NxtScb) == NULL) + pCurHcb->HCS_LastBusy = NULL; + } else { + pPrevScb->SCB_NxtScb = pTmpScb->SCB_NxtScb; + if (pTmpScb == pCurHcb->HCS_LastBusy) + pCurHcb->HCS_LastBusy = pPrevScb; + } + pTmpScb->SCB_HaStat = HOST_ABORTED; + tul_append_done_scb(pCurHcb, pTmpScb); } - else - { - pPrevScb->SCB_NxtScb = pTmpScb->SCB_NxtScb; - if (pTmpScb == pCurHcb->HCS_LastBusy) - pCurHcb->HCS_LastBusy = pPrevScb; - } - pTmpScb->SCB_HaStat = HOST_ABORTED; - tul_append_done_scb(pCurHcb, pTmpScb); - } /* Previous haven't change */ - else - { - pPrevScb = pTmpScb; - } - pTmpScb = pTmpScb->SCB_NxtScb; + /* Previous haven't change */ + else { + pPrevScb = pTmpScb; + } + pTmpScb = pTmpScb->SCB_NxtScb; } - TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_DEVRST); - TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT); + TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_DEVRST); + TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT); - return tul_wait_disc(pCurHcb); + return tul_wait_disc(pCurHcb); } /***************************************************************************/ -int tul_msgin_accept(HCS *pCurHcb) +int tul_msgin_accept(HCS * pCurHcb) { - TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_MSG_ACCEPT); - return (wait_tulip(pCurHcb)); + TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_MSG_ACCEPT); + return (wait_tulip(pCurHcb)); } /***************************************************************************/ -int wait_tulip(HCS *pCurHcb) +int wait_tulip(HCS * pCurHcb) { -/* register BYTE s; - int phase;*/ -// ULONG flags; -// pCurHcb->HCS_Flags &= ~HCF_RESET; + while (!((pCurHcb->HCS_JSStatus0 = TUL_RD(pCurHcb->HCS_Base, TUL_SStatus0)) + & TSS_INT_PENDING)); - while (!((pCurHcb->HCS_JSStatus0 = TUL_RD(pCurHcb->HCS_Base,TUL_SStatus0)) - & TSS_INT_PENDING)) { -// save_flags(flags); /* wh 07/21/98 */ -// sti(); -// restore_flags(flags); /* Addedby hc 07/21/98 */ - -// if (pCurHcb->HCS_Flags & HCF_RESET) { -// return -1; -// } - } - - pCurHcb->HCS_JSInt = TUL_RD(pCurHcb->HCS_Base, TUL_SInt); - pCurHcb->HCS_Phase = pCurHcb->HCS_JSStatus0 & TSS_PH_MASK; - pCurHcb->HCS_JSStatus1 = TUL_RD(pCurHcb->HCS_Base, TUL_SStatus1); - -/* stat2 = TUL_RD(pCurHcb->HCS_Base,TUL_SStatus2); - printk("SCSI int status = %x", pCurHcb->HCS_JSInt);*/ + pCurHcb->HCS_JSInt = TUL_RD(pCurHcb->HCS_Base, TUL_SInt); + pCurHcb->HCS_Phase = pCurHcb->HCS_JSStatus0 & TSS_PH_MASK; + pCurHcb->HCS_JSStatus1 = TUL_RD(pCurHcb->HCS_Base, TUL_SStatus1); - if (pCurHcb->HCS_JSInt & TSS_RESEL_INT) - { /* if SCSI bus reset detected */ - return (int_tul_resel(pCurHcb)); + if (pCurHcb->HCS_JSInt & TSS_RESEL_INT) { /* if SCSI bus reset detected */ + return (int_tul_resel(pCurHcb)); } - - if (pCurHcb->HCS_JSInt & TSS_SEL_TIMEOUT) - { /* if selected/reselected timeout interrupt */ - return (int_tul_busfree(pCurHcb)); + if (pCurHcb->HCS_JSInt & TSS_SEL_TIMEOUT) { /* if selected/reselected timeout interrupt */ + return (int_tul_busfree(pCurHcb)); } - - if (pCurHcb->HCS_JSInt & TSS_SCSIRST_INT) - { /* if SCSI bus reset detected */ - return (int_tul_scsi_rst(pCurHcb)); + if (pCurHcb->HCS_JSInt & TSS_SCSIRST_INT) { /* if SCSI bus reset detected */ + return (int_tul_scsi_rst(pCurHcb)); } - - if (pCurHcb->HCS_JSInt & TSS_DISC_INT) - { /* BUS disconnection */ - if (pCurHcb->HCS_Flags & HCF_EXPECT_DONE_DISC) - { - TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO); /* Flush SCSI FIFO */ - tul_unlink_busy_scb(pCurHcb, pCurHcb->HCS_ActScb); -// pCurHcb->HCS_ActScb->SCB_Status = SCB_DONE; - pCurHcb->HCS_ActScb->SCB_HaStat = 0; - tul_append_done_scb(pCurHcb, pCurHcb->HCS_ActScb); - pCurHcb->HCS_ActScb = NULL; - pCurHcb->HCS_ActTcs = NULL; - pCurHcb->HCS_Flags &= ~HCF_EXPECT_DONE_DISC; - TUL_WR(pCurHcb->HCS_Base + TUL_SConfig, TSC_INITDEFAULT); - TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl1, TSC_HW_RESELECT);/* Enable HW reselect */ - return (-1); - } - if (pCurHcb->HCS_Flags & HCF_EXPECT_DISC) - { - TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO); /* Flush SCSI FIFO */ - pCurHcb->HCS_ActScb = NULL; - pCurHcb->HCS_ActTcs = NULL; - pCurHcb->HCS_Flags &= ~HCF_EXPECT_DISC; - TUL_WR(pCurHcb->HCS_Base + TUL_SConfig, TSC_INITDEFAULT); - TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl1, TSC_HW_RESELECT);/* Enable HW reselect */ - return (-1); - } - return (int_tul_busfree(pCurHcb)); + if (pCurHcb->HCS_JSInt & TSS_DISC_INT) { /* BUS disconnection */ + if (pCurHcb->HCS_Flags & HCF_EXPECT_DONE_DISC) { + TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO); /* Flush SCSI FIFO */ + tul_unlink_busy_scb(pCurHcb, pCurHcb->HCS_ActScb); + pCurHcb->HCS_ActScb->SCB_HaStat = 0; + tul_append_done_scb(pCurHcb, pCurHcb->HCS_ActScb); + pCurHcb->HCS_ActScb = NULL; + pCurHcb->HCS_ActTcs = NULL; + pCurHcb->HCS_Flags &= ~HCF_EXPECT_DONE_DISC; + TUL_WR(pCurHcb->HCS_Base + TUL_SConfig, TSC_INITDEFAULT); + TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl1, TSC_HW_RESELECT); /* Enable HW reselect */ + return (-1); + } + if (pCurHcb->HCS_Flags & HCF_EXPECT_DISC) { + TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO); /* Flush SCSI FIFO */ + pCurHcb->HCS_ActScb = NULL; + pCurHcb->HCS_ActTcs = NULL; + pCurHcb->HCS_Flags &= ~HCF_EXPECT_DISC; + TUL_WR(pCurHcb->HCS_Base + TUL_SConfig, TSC_INITDEFAULT); + TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl1, TSC_HW_RESELECT); /* Enable HW reselect */ + return (-1); + } + return (int_tul_busfree(pCurHcb)); } - - if (pCurHcb->HCS_JSInt & (TSS_FUNC_COMP | TSS_BUS_SERV)) - { - return (pCurHcb->HCS_Phase); + if (pCurHcb->HCS_JSInt & (TSS_FUNC_COMP | TSS_BUS_SERV)) { + return (pCurHcb->HCS_Phase); } - - return (pCurHcb->HCS_Phase); + return (pCurHcb->HCS_Phase); } /***************************************************************************/ -int tul_wait_disc(HCS *pCurHcb) +int tul_wait_disc(HCS * pCurHcb) { - while (!((pCurHcb->HCS_JSStatus0 = TUL_RD(pCurHcb->HCS_Base,TUL_SStatus0)) - & TSS_INT_PENDING)) - ; - + while (!((pCurHcb->HCS_JSStatus0 = TUL_RD(pCurHcb->HCS_Base, TUL_SStatus0)) + & TSS_INT_PENDING)); - pCurHcb->HCS_JSInt = TUL_RD(pCurHcb->HCS_Base, TUL_SInt); - if (pCurHcb->HCS_JSInt & TSS_SCSIRST_INT) - { /* if SCSI bus reset detected */ - return (int_tul_scsi_rst(pCurHcb)); - } + pCurHcb->HCS_JSInt = TUL_RD(pCurHcb->HCS_Base, TUL_SInt); - if (pCurHcb->HCS_JSInt & TSS_DISC_INT) - { /* BUS disconnection */ - TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO); /* Flush SCSI FIFO */ - TUL_WR(pCurHcb->HCS_Base + TUL_SConfig, TSC_INITDEFAULT); - TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl1, TSC_HW_RESELECT);/* Enable HW reselect */ - pCurHcb->HCS_ActScb = NULL; - return (-1); + if (pCurHcb->HCS_JSInt & TSS_SCSIRST_INT) { /* if SCSI bus reset detected */ + return (int_tul_scsi_rst(pCurHcb)); } - - return (tul_bad_seq(pCurHcb)); + if (pCurHcb->HCS_JSInt & TSS_DISC_INT) { /* BUS disconnection */ + TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO); /* Flush SCSI FIFO */ + TUL_WR(pCurHcb->HCS_Base + TUL_SConfig, TSC_INITDEFAULT); + TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl1, TSC_HW_RESELECT); /* Enable HW reselect */ + pCurHcb->HCS_ActScb = NULL; + return (-1); + } + return (tul_bad_seq(pCurHcb)); } /***************************************************************************/ -int tul_wait_done_disc(HCS *pCurHcb) +int tul_wait_done_disc(HCS * pCurHcb) { - while (!((pCurHcb->HCS_JSStatus0 = TUL_RD(pCurHcb->HCS_Base,TUL_SStatus0)) - & TSS_INT_PENDING)) - ; + while (!((pCurHcb->HCS_JSStatus0 = TUL_RD(pCurHcb->HCS_Base, TUL_SStatus0)) + & TSS_INT_PENDING)); - pCurHcb->HCS_JSInt = TUL_RD(pCurHcb->HCS_Base, TUL_SInt); - - - if (pCurHcb->HCS_JSInt & TSS_SCSIRST_INT) - { /* if SCSI bus reset detected */ - return (int_tul_scsi_rst(pCurHcb)); - } + pCurHcb->HCS_JSInt = TUL_RD(pCurHcb->HCS_Base, TUL_SInt); - if (pCurHcb->HCS_JSInt & TSS_DISC_INT) - { /* BUS disconnection */ - TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO); /* Flush SCSI FIFO */ - TUL_WR(pCurHcb->HCS_Base + TUL_SConfig, TSC_INITDEFAULT); - TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl1, TSC_HW_RESELECT);/* Enable HW reselect */ - tul_unlink_busy_scb(pCurHcb, pCurHcb->HCS_ActScb); - tul_append_done_scb(pCurHcb, pCurHcb->HCS_ActScb); - pCurHcb->HCS_ActScb = NULL; - return (-1); + if (pCurHcb->HCS_JSInt & TSS_SCSIRST_INT) { /* if SCSI bus reset detected */ + return (int_tul_scsi_rst(pCurHcb)); } + if (pCurHcb->HCS_JSInt & TSS_DISC_INT) { /* BUS disconnection */ + TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO); /* Flush SCSI FIFO */ + TUL_WR(pCurHcb->HCS_Base + TUL_SConfig, TSC_INITDEFAULT); + TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl1, TSC_HW_RESELECT); /* Enable HW reselect */ + tul_unlink_busy_scb(pCurHcb, pCurHcb->HCS_ActScb); - - return (tul_bad_seq(pCurHcb)); + tul_append_done_scb(pCurHcb, pCurHcb->HCS_ActScb); + pCurHcb->HCS_ActScb = NULL; + return (-1); + } + return (tul_bad_seq(pCurHcb)); } /**************************** EOF *********************************/ diff -urN linux-2.0.37-pre2/drivers/scsi/i91uscsi.h linux-2.0.37-pre3/drivers/scsi/i91uscsi.h --- linux-2.0.37-pre2/drivers/scsi/i91uscsi.h 2003-08-15 15:04:26.000000000 -0700 +++ linux-2.0.37-pre3/drivers/scsi/i91uscsi.h 2003-08-15 15:04:26.000000000 -0700 @@ -1,4 +1,3 @@ - /************************************************************************** * Initio 9100 device driver for Linux. * @@ -70,277 +69,271 @@ #endif #ifndef NULL -#define NULL 0 /* zero */ +#define NULL 0 /* zero */ #endif #ifndef TRUE -#define TRUE (1) /* boolean true */ +#define TRUE (1) /* boolean true */ #endif #ifndef FALSE -#define FALSE (0) /* boolean false */ +#define FALSE (0) /* boolean false */ #endif #ifndef FAILURE #define FAILURE (-1) #endif -/*#endif*/ #define TOTAL_SG_ENTRY 32 #define MAX_SUPPORTED_ADAPTERS 8 #define MAX_OFFSET 15 #define MAX_TARGETS 16 -#define INI_VENDOR_ID 0x1101 /* Initio's PCI vendor ID */ -#define I950_DEVICE_ID 0x9500 /* Initio's inic-950 product ID */ -#define I940_DEVICE_ID 0x9400 /* Initio's inic-940 product ID */ -#define I935_DEVICE_ID 0x9401 /* Initio's inic-935 product ID */ - -//#if defined(__KERNEL__) +#define INI_VENDOR_ID 0x1101 /* Initio's PCI vendor ID */ +#define I950_DEVICE_ID 0x9500 /* Initio's inic-950 product ID */ +#define I940_DEVICE_ID 0x9400 /* Initio's inic-940 product ID */ +#define I935_DEVICE_ID 0x9401 /* Initio's inic-935 product ID */ #define _I91USCSI_H -#if 0 -#include "ini9100u.h" -#endif typedef struct { - unsigned short base; - unsigned short vec; -} i91u_config ; + unsigned short base; + unsigned short vec; +} i91u_config; /***************************************/ /* Tulip Configuration Register Set */ /***************************************/ -#define TUL_PVID 0x00 /* Vendor ID */ -#define TUL_PDID 0x02 /* Device ID */ -#define TUL_PCMD 0x04 /* Command */ -#define TUL_PSTUS 0x06 /* Status */ -#define TUL_PRID 0x08 /* Revision number */ -#define TUL_PPI 0x09 /* Programming interface */ -#define TUL_PSC 0x0A /* Sub Class */ -#define TUL_PBC 0x0B /* Base Class */ -#define TUL_PCLS 0x0C /* Cache line size */ -#define TUL_PLTR 0x0D /* Latency timer */ -#define TUL_PHDT 0x0E /* Header type */ -#define TUL_PBIST 0x0F /* BIST */ -#define TUL_PBAD 0x10 /* Base address */ -#define TUL_PBAD1 0x14 /* Base address */ -#define TUL_PBAD2 0x18 /* Base address */ -#define TUL_PBAD3 0x1C /* Base address */ -#define TUL_PBAD4 0x20 /* Base address */ -#define TUL_PBAD5 0x24 /* Base address */ -#define TUL_PRSVD 0x28 /* Reserved */ -#define TUL_PRSVD1 0x2C /* Reserved */ -#define TUL_PRAD 0x30 /* Expansion ROM base address */ -#define TUL_PRSVD2 0x34 /* Reserved */ -#define TUL_PRSVD3 0x38 /* Reserved */ -#define TUL_PINTL 0x3C /* Interrupt line */ -#define TUL_PINTP 0x3D /* Interrupt pin */ -#define TUL_PIGNT 0x3E /* MIN_GNT */ -#define TUL_PMGNT 0x3F /* MAX_GNT */ +#define TUL_PVID 0x00 /* Vendor ID */ +#define TUL_PDID 0x02 /* Device ID */ +#define TUL_PCMD 0x04 /* Command */ +#define TUL_PSTUS 0x06 /* Status */ +#define TUL_PRID 0x08 /* Revision number */ +#define TUL_PPI 0x09 /* Programming interface */ +#define TUL_PSC 0x0A /* Sub Class */ +#define TUL_PBC 0x0B /* Base Class */ +#define TUL_PCLS 0x0C /* Cache line size */ +#define TUL_PLTR 0x0D /* Latency timer */ +#define TUL_PHDT 0x0E /* Header type */ +#define TUL_PBIST 0x0F /* BIST */ +#define TUL_PBAD 0x10 /* Base address */ +#define TUL_PBAD1 0x14 /* Base address */ +#define TUL_PBAD2 0x18 /* Base address */ +#define TUL_PBAD3 0x1C /* Base address */ +#define TUL_PBAD4 0x20 /* Base address */ +#define TUL_PBAD5 0x24 /* Base address */ +#define TUL_PRSVD 0x28 /* Reserved */ +#define TUL_PRSVD1 0x2C /* Reserved */ +#define TUL_PRAD 0x30 /* Expansion ROM base address */ +#define TUL_PRSVD2 0x34 /* Reserved */ +#define TUL_PRSVD3 0x38 /* Reserved */ +#define TUL_PINTL 0x3C /* Interrupt line */ +#define TUL_PINTP 0x3D /* Interrupt pin */ +#define TUL_PIGNT 0x3E /* MIN_GNT */ +#define TUL_PMGNT 0x3F /* MAX_GNT */ /************************/ /* Jasmin Register Set */ /************************/ -#define TUL_HACFG0 0x40 /* H/A Configuration Register 0 */ -#define TUL_HACFG1 0x41 /* H/A Configuration Register 1 */ -#define TUL_HACFG2 0x42 /* H/A Configuration Register 2 */ - -#define TUL_SDCFG0 0x44 /* SCSI Device Configuration 0 */ -#define TUL_SDCFG1 0x45 /* SCSI Device Configuration 1 */ -#define TUL_SDCFG2 0x46 /* SCSI Device Configuration 2 */ -#define TUL_SDCFG3 0x47 /* SCSI Device Configuration 3 */ - -#define TUL_GINTS 0x50 /* Global Interrupt Status Register */ -#define TUL_GIMSK 0x52 /* Global Interrupt MASK Register */ -#define TUL_GCTRL 0x54 /* Global Control Register */ - #define TUL_GCTRL_EEPROM_BIT 0x04 -#define TUL_GCTRL1 0x55 /* Global Control Register */ -#define TUL_DMACFG 0x5B /* DMA configuration */ -#define TUL_NVRAM 0x5D /* Non-volatile RAM port */ - -#define TUL_SCnt0 0x80 /* 00 R/W Transfer Counter Low */ -#define TUL_SCnt1 0x81 /* 01 R/W Transfer Counter Mid */ -#define TUL_SCnt2 0x82 /* 02 R/W Transfer Count High */ -#define TUL_SFifoCnt 0x83 /* 03 R FIFO counter */ -#define TUL_SIntEnable 0x84 /* 03 W Interrupt enble */ -#define TUL_SInt 0x84 /* 04 R Interrupt Register */ -#define TUL_SCtrl0 0x85 /* 05 W Control 0 */ -#define TUL_SStatus0 0x85 /* 05 R Status 0 */ -#define TUL_SCtrl1 0x86 /* 06 W Control 1 */ -#define TUL_SStatus1 0x86 /* 06 R Status 1 */ -#define TUL_SConfig 0x87 /* 07 W Configuration */ -#define TUL_SStatus2 0x87 /* 07 R Status 2 */ -#define TUL_SPeriod 0x88 /* 08 W Sync. Transfer Period & Offset*/ -#define TUL_SOffset 0x88 /* 08 R Offset */ -#define TUL_SScsiId 0x89 /* 09 W SCSI ID */ -#define TUL_SBusId 0x89 /* 09 R SCSI BUS ID */ -#define TUL_STimeOut 0x8A /* 0A W Sel/Resel Time Out Register */ -#define TUL_SIdent 0x8A /* 0A R Identify Message Register */ -#define TUL_SAvail 0x8A /* 0A R Availiable Counter Register */ -#define TUL_SData 0x8B /* 0B R/W SCSI data in/out */ -#define TUL_SFifo 0x8C /* 0C R/W FIFO */ -#define TUL_SSignal 0x90 /* 10 R/W SCSI signal in/out */ -#define TUL_SCmd 0x91 /* 11 R/W Command */ -#define TUL_STest0 0x92 /* 12 R/W Test0 */ -#define TUL_STest1 0x93 /* 13 R/W Test1 */ -#define TUL_SCFG1 0x94 /* 14 R/W Configuration */ - -#define TUL_XAddH 0xC0 /*DMA Transfer Physical Address */ -#define TUL_XAddW 0xC8 /*DMA Current Transfer Physical Address */ -#define TUL_XCntH 0xD0 /*DMA Transfer Counter */ -#define TUL_XCntW 0xD4 /*DMA Current Transfer Counter */ -#define TUL_XCmd 0xD8 /*DMA Command Register */ -#define TUL_Int 0xDC /*Interrupt Register */ -#define TUL_XStatus 0xDD /*DMA status Register */ -#define TUL_Mask 0xE0 /*Interrupt Mask Register */ -#define TUL_XCtrl 0xE4 /*DMA Control Register */ -#define TUL_XCtrl1 0xE5 /*DMA Control Register 1 */ -#define TUL_XFifo 0xE8 /*DMA FIFO */ +#define TUL_HACFG0 0x40 /* H/A Configuration Register 0 */ +#define TUL_HACFG1 0x41 /* H/A Configuration Register 1 */ +#define TUL_HACFG2 0x42 /* H/A Configuration Register 2 */ + +#define TUL_SDCFG0 0x44 /* SCSI Device Configuration 0 */ +#define TUL_SDCFG1 0x45 /* SCSI Device Configuration 1 */ +#define TUL_SDCFG2 0x46 /* SCSI Device Configuration 2 */ +#define TUL_SDCFG3 0x47 /* SCSI Device Configuration 3 */ + +#define TUL_GINTS 0x50 /* Global Interrupt Status Register */ +#define TUL_GIMSK 0x52 /* Global Interrupt MASK Register */ +#define TUL_GCTRL 0x54 /* Global Control Register */ +#define TUL_GCTRL_EEPROM_BIT 0x04 +#define TUL_GCTRL1 0x55 /* Global Control Register */ +#define TUL_DMACFG 0x5B /* DMA configuration */ +#define TUL_NVRAM 0x5D /* Non-volatile RAM port */ + +#define TUL_SCnt0 0x80 /* 00 R/W Transfer Counter Low */ +#define TUL_SCnt1 0x81 /* 01 R/W Transfer Counter Mid */ +#define TUL_SCnt2 0x82 /* 02 R/W Transfer Count High */ +#define TUL_SFifoCnt 0x83 /* 03 R FIFO counter */ +#define TUL_SIntEnable 0x84 /* 03 W Interrupt enble */ +#define TUL_SInt 0x84 /* 04 R Interrupt Register */ +#define TUL_SCtrl0 0x85 /* 05 W Control 0 */ +#define TUL_SStatus0 0x85 /* 05 R Status 0 */ +#define TUL_SCtrl1 0x86 /* 06 W Control 1 */ +#define TUL_SStatus1 0x86 /* 06 R Status 1 */ +#define TUL_SConfig 0x87 /* 07 W Configuration */ +#define TUL_SStatus2 0x87 /* 07 R Status 2 */ +#define TUL_SPeriod 0x88 /* 08 W Sync. Transfer Period & Offset */ +#define TUL_SOffset 0x88 /* 08 R Offset */ +#define TUL_SScsiId 0x89 /* 09 W SCSI ID */ +#define TUL_SBusId 0x89 /* 09 R SCSI BUS ID */ +#define TUL_STimeOut 0x8A /* 0A W Sel/Resel Time Out Register */ +#define TUL_SIdent 0x8A /* 0A R Identify Message Register */ +#define TUL_SAvail 0x8A /* 0A R Availiable Counter Register */ +#define TUL_SData 0x8B /* 0B R/W SCSI data in/out */ +#define TUL_SFifo 0x8C /* 0C R/W FIFO */ +#define TUL_SSignal 0x90 /* 10 R/W SCSI signal in/out */ +#define TUL_SCmd 0x91 /* 11 R/W Command */ +#define TUL_STest0 0x92 /* 12 R/W Test0 */ +#define TUL_STest1 0x93 /* 13 R/W Test1 */ +#define TUL_SCFG1 0x94 /* 14 R/W Configuration */ + +#define TUL_XAddH 0xC0 /*DMA Transfer Physical Address */ +#define TUL_XAddW 0xC8 /*DMA Current Transfer Physical Address */ +#define TUL_XCntH 0xD0 /*DMA Transfer Counter */ +#define TUL_XCntW 0xD4 /*DMA Current Transfer Counter */ +#define TUL_XCmd 0xD8 /*DMA Command Register */ +#define TUL_Int 0xDC /*Interrupt Register */ +#define TUL_XStatus 0xDD /*DMA status Register */ +#define TUL_Mask 0xE0 /*Interrupt Mask Register */ +#define TUL_XCtrl 0xE4 /*DMA Control Register */ +#define TUL_XCtrl1 0xE5 /*DMA Control Register 1 */ +#define TUL_XFifo 0xE8 /*DMA FIFO */ -#define TUL_WCtrl 0xF7 /*Bus master wait state control */ -#define TUL_DCtrl 0xFB /*DMA delay control */ +#define TUL_WCtrl 0xF7 /*Bus master wait state control */ +#define TUL_DCtrl 0xFB /*DMA delay control */ /*----------------------------------------------------------------------*/ /* bit definition for Command register of Configuration Space Header */ /*----------------------------------------------------------------------*/ -#define BUSMS 0x04 /* BUS MASTER Enable */ -#define IOSPA 0x01 /* IO Space Enable */ +#define BUSMS 0x04 /* BUS MASTER Enable */ +#define IOSPA 0x01 /* IO Space Enable */ /*----------------------------------------------------------------------*/ /* Command Codes of Tulip SCSI Command register */ /*----------------------------------------------------------------------*/ -#define TSC_EN_RESEL 0x80 /* Enable Reselection */ -#define TSC_CMD_COMP 0x84 /* Command Complete Sequence */ -#define TSC_SEL 0x01 /* Select Without ATN Sequence */ -#define TSC_SEL_ATN 0x11 /* Select With ATN Sequence */ -#define TSC_SEL_ATN_DMA 0x51 /* Select With ATN Sequence with DMA */ -#define TSC_SEL_ATN3 0x31 /* Select With ATN3 Sequence */ -#define TSC_SEL_ATNSTOP 0x12 /* Select With ATN and Stop Sequence */ -#define TSC_SELATNSTOP 0x1E /* Select With ATN and Stop Sequence */ - -#define TSC_SEL_ATN_DIRECT_IN 0x95 /* Select With ATN Sequence */ -#define TSC_SEL_ATN_DIRECT_OUT 0x15 /* Select With ATN Sequence */ -#define TSC_SEL_ATN3_DIRECT_IN 0xB5 /* Select With ATN3 Sequence */ -#define TSC_SEL_ATN3_DIRECT_OUT 0x35 /* Select With ATN3 Sequence */ -#define TSC_XF_DMA_OUT_DIRECT 0x06 /* DMA Xfer Infomation out */ -#define TSC_XF_DMA_IN_DIRECT 0x86 /* DMA Xfer Infomation in */ - -#define TSC_XF_DMA_OUT 0x43 /* DMA Xfer Infomation out */ -#define TSC_XF_DMA_IN 0xC3 /* DMA Xfer Infomation in */ -#define TSC_XF_FIFO_OUT 0x03 /* FIFO Xfer Infomation out */ -#define TSC_XF_FIFO_IN 0x83 /* FIFO Xfer Infomation in */ +#define TSC_EN_RESEL 0x80 /* Enable Reselection */ +#define TSC_CMD_COMP 0x84 /* Command Complete Sequence */ +#define TSC_SEL 0x01 /* Select Without ATN Sequence */ +#define TSC_SEL_ATN 0x11 /* Select With ATN Sequence */ +#define TSC_SEL_ATN_DMA 0x51 /* Select With ATN Sequence with DMA */ +#define TSC_SEL_ATN3 0x31 /* Select With ATN3 Sequence */ +#define TSC_SEL_ATNSTOP 0x12 /* Select With ATN and Stop Sequence */ +#define TSC_SELATNSTOP 0x1E /* Select With ATN and Stop Sequence */ + +#define TSC_SEL_ATN_DIRECT_IN 0x95 /* Select With ATN Sequence */ +#define TSC_SEL_ATN_DIRECT_OUT 0x15 /* Select With ATN Sequence */ +#define TSC_SEL_ATN3_DIRECT_IN 0xB5 /* Select With ATN3 Sequence */ +#define TSC_SEL_ATN3_DIRECT_OUT 0x35 /* Select With ATN3 Sequence */ +#define TSC_XF_DMA_OUT_DIRECT 0x06 /* DMA Xfer Infomation out */ +#define TSC_XF_DMA_IN_DIRECT 0x86 /* DMA Xfer Infomation in */ + +#define TSC_XF_DMA_OUT 0x43 /* DMA Xfer Infomation out */ +#define TSC_XF_DMA_IN 0xC3 /* DMA Xfer Infomation in */ +#define TSC_XF_FIFO_OUT 0x03 /* FIFO Xfer Infomation out */ +#define TSC_XF_FIFO_IN 0x83 /* FIFO Xfer Infomation in */ -#define TSC_MSG_ACCEPT 0x0F /* Message Accept */ +#define TSC_MSG_ACCEPT 0x0F /* Message Accept */ /*----------------------------------------------------------------------*/ /* bit definition for Tulip SCSI Control 0 Register */ /*----------------------------------------------------------------------*/ -#define TSC_RST_SEQ 0x20 /* Reset sequence counter */ -#define TSC_FLUSH_FIFO 0x10 /* Flush FIFO */ -#define TSC_ABT_CMD 0x04 /* Abort command (sequence) */ -#define TSC_RST_CHIP 0x02 /* Reset SCSI Chip */ -#define TSC_RST_BUS 0x01 /* Reset SCSI Bus */ +#define TSC_RST_SEQ 0x20 /* Reset sequence counter */ +#define TSC_FLUSH_FIFO 0x10 /* Flush FIFO */ +#define TSC_ABT_CMD 0x04 /* Abort command (sequence) */ +#define TSC_RST_CHIP 0x02 /* Reset SCSI Chip */ +#define TSC_RST_BUS 0x01 /* Reset SCSI Bus */ /*----------------------------------------------------------------------*/ /* bit definition for Tulip SCSI Control 1 Register */ /*----------------------------------------------------------------------*/ -#define TSC_EN_SCAM 0x80 /* Enable SCAM */ -#define TSC_TIMER 0x40 /* Select timeout unit */ -#define TSC_EN_SCSI2 0x20 /* SCSI-2 mode */ -#define TSC_PWDN 0x10 /* Power down mode */ -#define TSC_WIDE_CPU 0x08 /* Wide CPU */ -#define TSC_HW_RESELECT 0x04 /* Enable HW reselect */ -#define TSC_EN_BUS_OUT 0x02 /* Enable SCSI data bus out latch */ -#define TSC_EN_BUS_IN 0x01 /* Enable SCSI data bus in latch */ +#define TSC_EN_SCAM 0x80 /* Enable SCAM */ +#define TSC_TIMER 0x40 /* Select timeout unit */ +#define TSC_EN_SCSI2 0x20 /* SCSI-2 mode */ +#define TSC_PWDN 0x10 /* Power down mode */ +#define TSC_WIDE_CPU 0x08 /* Wide CPU */ +#define TSC_HW_RESELECT 0x04 /* Enable HW reselect */ +#define TSC_EN_BUS_OUT 0x02 /* Enable SCSI data bus out latch */ +#define TSC_EN_BUS_IN 0x01 /* Enable SCSI data bus in latch */ /*----------------------------------------------------------------------*/ /* bit definition for Tulip SCSI Configuration Register */ /*----------------------------------------------------------------------*/ -#define TSC_EN_LATCH 0x80 /* Enable phase latch */ -#define TSC_INITIATOR 0x40 /* Initiator mode */ -#define TSC_EN_SCSI_PAR 0x20 /* Enable SCSI parity */ -#define TSC_DMA_8BIT 0x10 /* Alternate dma 8-bits mode */ -#define TSC_DMA_16BIT 0x08 /* Alternate dma 16-bits mode */ -#define TSC_EN_WDACK 0x04 /* Enable DACK while wide SCSI xfer */ -#define TSC_ALT_PERIOD 0x02 /* Alternate sync period mode */ -#define TSC_DIS_SCSIRST 0x01 /* Disable SCSI bus reset us */ +#define TSC_EN_LATCH 0x80 /* Enable phase latch */ +#define TSC_INITIATOR 0x40 /* Initiator mode */ +#define TSC_EN_SCSI_PAR 0x20 /* Enable SCSI parity */ +#define TSC_DMA_8BIT 0x10 /* Alternate dma 8-bits mode */ +#define TSC_DMA_16BIT 0x08 /* Alternate dma 16-bits mode */ +#define TSC_EN_WDACK 0x04 /* Enable DACK while wide SCSI xfer */ +#define TSC_ALT_PERIOD 0x02 /* Alternate sync period mode */ +#define TSC_DIS_SCSIRST 0x01 /* Disable SCSI bus reset us */ #define TSC_INITDEFAULT (TSC_INITIATOR | TSC_EN_LATCH | TSC_ALT_PERIOD | TSC_DIS_SCSIRST) -#define TSC_WIDE_SCSI 0x80 /* Enable Wide SCSI */ +#define TSC_WIDE_SCSI 0x80 /* Enable Wide SCSI */ /*----------------------------------------------------------------------*/ /* bit definition for Tulip SCSI signal Register */ /*----------------------------------------------------------------------*/ -#define TSC_RST_ACK 0x00 /* Release ACK signal */ -#define TSC_RST_ATN 0x00 /* Release ATN signal */ -#define TSC_RST_BSY 0x00 /* Release BSY signal */ - -#define TSC_SET_ACK 0x40 /* ACK signal */ -#define TSC_SET_ATN 0x08 /* ATN signal */ - -#define TSC_REQI 0x80 /* REQ signal */ -#define TSC_ACKI 0x40 /* ACK signal */ -#define TSC_BSYI 0x20 /* BSY signal */ -#define TSC_SELI 0x10 /* SEL signal */ -#define TSC_ATNI 0x08 /* ATN signal */ -#define TSC_MSGI 0x04 /* MSG signal */ -#define TSC_CDI 0x02 /* C/D signal */ -#define TSC_IOI 0x01 /* I/O signal */ +#define TSC_RST_ACK 0x00 /* Release ACK signal */ +#define TSC_RST_ATN 0x00 /* Release ATN signal */ +#define TSC_RST_BSY 0x00 /* Release BSY signal */ + +#define TSC_SET_ACK 0x40 /* ACK signal */ +#define TSC_SET_ATN 0x08 /* ATN signal */ + +#define TSC_REQI 0x80 /* REQ signal */ +#define TSC_ACKI 0x40 /* ACK signal */ +#define TSC_BSYI 0x20 /* BSY signal */ +#define TSC_SELI 0x10 /* SEL signal */ +#define TSC_ATNI 0x08 /* ATN signal */ +#define TSC_MSGI 0x04 /* MSG signal */ +#define TSC_CDI 0x02 /* C/D signal */ +#define TSC_IOI 0x01 /* I/O signal */ /*----------------------------------------------------------------------*/ /* bit definition for Tulip SCSI Status 0 Register */ /*----------------------------------------------------------------------*/ -#define TSS_INT_PENDING 0x80 /* Interrupt pending */ -#define TSS_SEQ_ACTIVE 0x40 /* Sequencer active */ -#define TSS_XFER_CNT 0x20 /* Transfer counter zero */ -#define TSS_FIFO_EMPTY 0x10 /* FIFO empty */ -#define TSS_PAR_ERROR 0x08 /* SCSI parity error */ -#define TSS_PH_MASK 0x07 /* SCSI phase mask */ +#define TSS_INT_PENDING 0x80 /* Interrupt pending */ +#define TSS_SEQ_ACTIVE 0x40 /* Sequencer active */ +#define TSS_XFER_CNT 0x20 /* Transfer counter zero */ +#define TSS_FIFO_EMPTY 0x10 /* FIFO empty */ +#define TSS_PAR_ERROR 0x08 /* SCSI parity error */ +#define TSS_PH_MASK 0x07 /* SCSI phase mask */ /*----------------------------------------------------------------------*/ /* bit definition for Tulip SCSI Status 1 Register */ /*----------------------------------------------------------------------*/ -#define TSS_STATUS_RCV 0x08 /* Status received */ -#define TSS_MSG_SEND 0x40 /* Message sent */ -#define TSS_CMD_PH_CMP 0x20 /* command phase done */ -#define TSS_DATA_PH_CMP 0x10 /* Data phase done */ -#define TSS_STATUS_SEND 0x08 /* Status sent */ -#define TSS_XFER_CMP 0x04 /* Transfer completed */ -#define TSS_SEL_CMP 0x02 /* Selection completed */ -#define TSS_ARB_CMP 0x01 /* Arbitration completed */ +#define TSS_STATUS_RCV 0x08 /* Status received */ +#define TSS_MSG_SEND 0x40 /* Message sent */ +#define TSS_CMD_PH_CMP 0x20 /* command phase done */ +#define TSS_DATA_PH_CMP 0x10 /* Data phase done */ +#define TSS_STATUS_SEND 0x08 /* Status sent */ +#define TSS_XFER_CMP 0x04 /* Transfer completed */ +#define TSS_SEL_CMP 0x02 /* Selection completed */ +#define TSS_ARB_CMP 0x01 /* Arbitration completed */ /*----------------------------------------------------------------------*/ /* bit definition for Tulip SCSI Status 2 Register */ /*----------------------------------------------------------------------*/ -#define TSS_CMD_ABTED 0x80 /* Command aborted */ -#define TSS_OFFSET_0 0x40 /* Offset counter zero */ -#define TSS_FIFO_FULL 0x20 /* FIFO full */ -#define TSS_TIMEOUT_0 0x10 /* Timeout counter zero */ -#define TSS_BUSY_RLS 0x08 /* Busy release */ -#define TSS_PH_MISMATCH 0x04 /* Phase mismatch */ -#define TSS_SCSI_BUS_EN 0x02 /* SCSI data bus enable */ -#define TSS_SCSIRST 0x01 /* SCSI bus reset in progress */ +#define TSS_CMD_ABTED 0x80 /* Command aborted */ +#define TSS_OFFSET_0 0x40 /* Offset counter zero */ +#define TSS_FIFO_FULL 0x20 /* FIFO full */ +#define TSS_TIMEOUT_0 0x10 /* Timeout counter zero */ +#define TSS_BUSY_RLS 0x08 /* Busy release */ +#define TSS_PH_MISMATCH 0x04 /* Phase mismatch */ +#define TSS_SCSI_BUS_EN 0x02 /* SCSI data bus enable */ +#define TSS_SCSIRST 0x01 /* SCSI bus reset in progress */ /*----------------------------------------------------------------------*/ /* bit definition for Tulip SCSI Interrupt Register */ /*----------------------------------------------------------------------*/ -#define TSS_RESEL_INT 0x80 /* Reselected interrupt */ -#define TSS_SEL_TIMEOUT 0x40 /* Selected/reselected timeout */ +#define TSS_RESEL_INT 0x80 /* Reselected interrupt */ +#define TSS_SEL_TIMEOUT 0x40 /* Selected/reselected timeout */ #define TSS_BUS_SERV 0x20 -#define TSS_SCSIRST_INT 0x10 /* SCSI bus reset detected */ -#define TSS_DISC_INT 0x08 /* Disconnected interrupt */ -#define TSS_SEL_INT 0x04 /* Select interrupt */ -#define TSS_SCAM_SEL 0x02 /* SCAM selected */ +#define TSS_SCSIRST_INT 0x10 /* SCSI bus reset detected */ +#define TSS_DISC_INT 0x08 /* Disconnected interrupt */ +#define TSS_SEL_INT 0x04 /* Select interrupt */ +#define TSS_SCAM_SEL 0x02 /* SCAM selected */ #define TSS_FUNC_COMP 0x01 /*----------------------------------------------------------------------*/ /* SCSI Phase Codes. */ /*----------------------------------------------------------------------*/ #define DATA_OUT 0 -#define DATA_IN 1 /* 4 */ +#define DATA_IN 1 /* 4 */ #define CMD_OUT 2 -#define STATUS_IN 3 /* 6 */ -#define MSG_OUT 6 /* 3 */ +#define STATUS_IN 3 /* 6 */ +#define MSG_OUT 6 /* 3 */ #define MSG_IN 7 @@ -370,8 +363,8 @@ /*----------------------------------------------------------------------*/ /* Tulip DMA Status Register */ /*----------------------------------------------------------------------*/ -#define XPEND 0x01 /* Transfer pending */ -#define FEMPTY 0x02 /* FIFO empty */ +#define XPEND 0x01 /* Transfer pending */ +#define FEMPTY 0x02 /* FIFO empty */ @@ -396,59 +389,58 @@ /************************************************************************/ /* Scatter-Gather Element Structure */ /************************************************************************/ -typedef struct SG_Struc { - U32 SG_Ptr; /* Data Pointer */ - U32 SG_Len; /* Data Length */ +typedef struct SG_Struc { + U32 SG_Ptr; /* Data Pointer */ + U32 SG_Len; /* Data Length */ } SG; /*********************************************************************** SCSI Control Block ************************************************************************/ -typedef struct Scsi_Ctrl_Blk { - struct Scsi_Ctrl_Blk *SCB_NxtScb; - UBYTE SCB_Status; /*4 */ - UBYTE SCB_NxtStat; /*5 */ - UBYTE SCB_Mode; /*6 */ - UBYTE SCB_Msgin; /*7 SCB_Res0 */ - UWORD SCB_SGIdx; /*8 */ - UWORD SCB_SGMax; /*A */ +typedef struct Scsi_Ctrl_Blk { + struct Scsi_Ctrl_Blk *SCB_NxtScb; + UBYTE SCB_Status; /*4 */ + UBYTE SCB_NxtStat; /*5 */ + UBYTE SCB_Mode; /*6 */ + UBYTE SCB_Msgin; /*7 SCB_Res0 */ + UWORD SCB_SGIdx; /*8 */ + UWORD SCB_SGMax; /*A */ #ifdef ALPHA - U32 SCB_Reserved[2];/*C */ + U32 SCB_Reserved[2]; /*C */ #else - U32 SCB_Reserved[3];/*C */ + U32 SCB_Reserved[3]; /*C */ #endif - U32 SCB_XferLen; /*18 Current xfer len */ - U32 SCB_TotXLen; /*1C Total xfer len */ - U32 SCB_PAddr; /*20 SCB phy. Addr. */ - - UBYTE SCB_Opcode; /*24 SCB command code */ - UBYTE SCB_Flags; /*25 SCB Flags */ - UBYTE SCB_Target; /*26 Target Id */ - UBYTE SCB_Lun; /*27 Lun */ - U32 SCB_BufPtr; /*28 Data Buffer Pointer */ - U32 SCB_BufLen; /*2C Data Allocation Length */ - UBYTE SCB_SGLen; /*30 SG list # */ - UBYTE SCB_SenseLen; /*31 Sense Allocation Length */ - UBYTE SCB_HaStat; /*32 */ - UBYTE SCB_TaStat; /*33 */ - UBYTE SCB_CDBLen; /*34 CDB Length */ - UBYTE SCB_Ident; /*35 Identify */ - UBYTE SCB_TagMsg; /*36 Tag Message */ - UBYTE SCB_TagId; /*37 Queue Tag */ - UBYTE SCB_CDB[12]; /*38 */ - U32 SCB_SGPAddr; /*44 SG List/Sense Buf phy. Addr. */ - U32 SCB_SensePtr; /*48 Sense data pointer */ - void (* SCB_Post)(BYTE *, BYTE *); /*4C POST routine */ - unsigned char *SCB_Srb; /*50 SRB Pointer */ -// Scsi_Cmnd *SCB_Srb; /*2C SRB Pointer */ - SG SCB_SGList[TOTAL_SG_ENTRY]; /*54 Start of SG list */ + U32 SCB_XferLen; /*18 Current xfer len */ + U32 SCB_TotXLen; /*1C Total xfer len */ + U32 SCB_PAddr; /*20 SCB phy. Addr. */ + + UBYTE SCB_Opcode; /*24 SCB command code */ + UBYTE SCB_Flags; /*25 SCB Flags */ + UBYTE SCB_Target; /*26 Target Id */ + UBYTE SCB_Lun; /*27 Lun */ + U32 SCB_BufPtr; /*28 Data Buffer Pointer */ + U32 SCB_BufLen; /*2C Data Allocation Length */ + UBYTE SCB_SGLen; /*30 SG list # */ + UBYTE SCB_SenseLen; /*31 Sense Allocation Length */ + UBYTE SCB_HaStat; /*32 */ + UBYTE SCB_TaStat; /*33 */ + UBYTE SCB_CDBLen; /*34 CDB Length */ + UBYTE SCB_Ident; /*35 Identify */ + UBYTE SCB_TagMsg; /*36 Tag Message */ + UBYTE SCB_TagId; /*37 Queue Tag */ + UBYTE SCB_CDB[12]; /*38 */ + U32 SCB_SGPAddr; /*44 SG List/Sense Buf phy. Addr. */ + U32 SCB_SensePtr; /*48 Sense data pointer */ + void (*SCB_Post) (BYTE *, BYTE *); /*4C POST routine */ + unsigned char *SCB_Srb; /*50 SRB Pointer */ + SG SCB_SGList[TOTAL_SG_ENTRY]; /*54 Start of SG list */ } SCB; /* Bit Definition for SCB_Status */ #define SCB_RENT 0x01 #define SCB_PEND 0x02 -#define SCB_CONTIG 0x04 /* Contigent Allegiance */ +#define SCB_CONTIG 0x04 /* Contigent Allegiance */ #define SCB_SELECT 0x08 #define SCB_BUSY 0x10 #define SCB_DONE 0x20 @@ -461,7 +453,7 @@ /* Bit Definition for SCB_Mode */ -#define SCM_RSENS 0x01 /* request sense mode */ +#define SCM_RSENS 0x01 /* request sense mode */ /* Bit Definition for SCB_Flags */ @@ -473,7 +465,7 @@ #define SCF_DIN 0x08 #define SCF_DOUT 0x10 #define SCF_NO_XF 0x18 -#define SCF_WR_VF 0x20 /* Write verify turn on */ +#define SCF_WR_VF 0x20 /* Write verify turn on */ #define SCF_POLL 0x40 #define SCF_SG 0x80 @@ -483,7 +475,7 @@ #define HOST_BUS_FREE 0x13 #define HOST_BAD_PHAS 0x14 #define HOST_INV_CMD 0x16 -#define HOST_ABORTED 0x1A /* 07/21/98 */ +#define HOST_ABORTED 0x1A /* 07/21/98 */ #define HOST_SCSI_RST 0x1B #define HOST_DEV_RST 0x1C @@ -522,13 +514,13 @@ **********************************************************************/ typedef struct Tar_Ctrl_Struc { - UWORD TCS_Flags; /* 0 */ - UBYTE TCS_JS_Period; /* 2 */ - UBYTE TCS_SConfig0; /* 3 */ - - UWORD TCS_DrvFlags; /* 4 */ - UBYTE TCS_DrvHead; /* 6 */ - UBYTE TCS_DrvSector; /* 7 */ + UWORD TCS_Flags; /* 0 */ + UBYTE TCS_JS_Period; /* 2 */ + UBYTE TCS_SConfig0; /* 3 */ + + UWORD TCS_DrvFlags; /* 4 */ + UBYTE TCS_DrvHead; /* 6 */ + UBYTE TCS_DrvSector; /* 7 */ } TCS; /*********************************************************************** @@ -548,16 +540,16 @@ /* Bit Definition for TCF_DrvFlags */ -#define TCF_DRV_BUSY 0x01 /* Indicate target busy(driver) */ +#define TCF_DRV_BUSY 0x01 /* Indicate target busy(driver) */ #define TCF_DRV_EN_TAG 0x0800 #define TCF_DRV_255_63 0x0400 typedef struct I91u_Adpt_Struc { - UWORD ADPT_BIOS; /* 0 */ - UWORD ADPT_BASE; /* 1 */ - UBYTE ADPT_Bus; /* 2 */ - UBYTE ADPT_Device; /* 3 */ - UBYTE ADPT_INTR; /* 4 */ + UWORD ADPT_BIOS; /* 0 */ + UWORD ADPT_BASE; /* 1 */ + UBYTE ADPT_Bus; /* 2 */ + UBYTE ADPT_Device; /* 3 */ + UBYTE ADPT_INTR; /* 4 */ } INI_ADPT_STRUCT; @@ -565,57 +557,52 @@ Host Adapter Control Structure ************************************************************************/ typedef struct Ha_Ctrl_Struc { - UWORD HCS_Base; /* 00 */ - UWORD HCS_BIOS; /* 02 */ - UBYTE HCS_Intr; /* 04 */ - UBYTE HCS_SCSI_ID; /* 05 */ - UBYTE HCS_MaxTar; /* 06 */ - UBYTE HCS_NumScbs; /* 07 */ - - UBYTE HCS_Flags; /* 08 */ - UBYTE HCS_Index; /* 09 */ - UBYTE HCS_HaId; /* 0A */ - UBYTE HCS_Config; /* 0B */ - UWORD HCS_IdMask; /* 0C */ - UBYTE HCS_Semaph; /* 0E */ - UBYTE HCS_Phase; /* 0F */ - UBYTE HCS_JSStatus0; /* 10 */ - UBYTE HCS_JSInt; /* 11 */ - UBYTE HCS_JSStatus1; /* 12 */ - UBYTE HCS_SConf1; /* 13 */ - - UBYTE HCS_Msg[8]; /* 14 */ - SCB *HCS_NxtAvail; /* 1C */ - SCB *HCS_Scb; /* 20 */ - SCB *HCS_ScbEnd; /* 24 */ - SCB *HCS_NxtPend; /* 28 */ - SCB *HCS_NxtContig; /* 2C */ - SCB *HCS_ActScb; /* 30 */ - TCS *HCS_ActTcs; /* 34 */ - - SCB *HCS_FirstAvail;/* 38 */ - SCB *HCS_LastAvail; /* 3C */ - SCB *HCS_FirstPend; /* 40 */ - SCB *HCS_LastPend; /* 44 */ - SCB *HCS_FirstBusy; /* 48 */ - SCB *HCS_LastBusy; /* 4C */ - SCB *HCS_FirstDone; /* 50 */ - SCB *HCS_LastDone; /* 54 */ -#if 1 /* HILAM */ - UBYTE HCS_MaxTags[16];/* 58 */ - UBYTE HCS_ActTags[16];/* 68 */ - TCS HCS_Tcs[MAX_TARGETS]; /* 78 */ - ULONG pSRB_head; /* SRB save queue header */ - ULONG pSRB_tail; /* SRB save queue tail */ -#else - ULONG pSRB_head; /* 58 SRB save queue header */ - ULONG pSRB_tail; /* 5C SRB save queue tail */ - UBYTE HCS_MaxTags[16];/* 60 */ - UBYTE HCS_ActTags[16];/* 70 */ - TCS HCS_Tcs[MAX_TARGETS]; /* 78 */ + UWORD HCS_Base; /* 00 */ + UWORD HCS_BIOS; /* 02 */ + UBYTE HCS_Intr; /* 04 */ + UBYTE HCS_SCSI_ID; /* 05 */ + UBYTE HCS_MaxTar; /* 06 */ + UBYTE HCS_NumScbs; /* 07 */ + + UBYTE HCS_Flags; /* 08 */ + UBYTE HCS_Index; /* 09 */ + UBYTE HCS_HaId; /* 0A */ + UBYTE HCS_Config; /* 0B */ + UWORD HCS_IdMask; /* 0C */ + UBYTE HCS_Semaph; /* 0E */ + UBYTE HCS_Phase; /* 0F */ + UBYTE HCS_JSStatus0; /* 10 */ + UBYTE HCS_JSInt; /* 11 */ + UBYTE HCS_JSStatus1; /* 12 */ + UBYTE HCS_SConf1; /* 13 */ + + UBYTE HCS_Msg[8]; /* 14 */ + SCB *HCS_NxtAvail; /* 1C */ + SCB *HCS_Scb; /* 20 */ + SCB *HCS_ScbEnd; /* 24 */ + SCB *HCS_NxtPend; /* 28 */ + SCB *HCS_NxtContig; /* 2C */ + SCB *HCS_ActScb; /* 30 */ + TCS *HCS_ActTcs; /* 34 */ + + SCB *HCS_FirstAvail; /* 38 */ + SCB *HCS_LastAvail; /* 3C */ + SCB *HCS_FirstPend; /* 40 */ + SCB *HCS_LastPend; /* 44 */ + SCB *HCS_FirstBusy; /* 48 */ + SCB *HCS_LastBusy; /* 4C */ + SCB *HCS_FirstDone; /* 50 */ + SCB *HCS_LastDone; /* 54 */ + UBYTE HCS_MaxTags[16]; /* 58 */ + UBYTE HCS_ActTags[16]; /* 68 */ + TCS HCS_Tcs[MAX_TARGETS]; /* 78 */ + ULONG pSRB_head; /* SRB save queue header */ + ULONG pSRB_tail; /* SRB save queue tail */ +#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95) + spinlock_t HCS_AvailLock; + spinlock_t HCS_SemaphLock; + spinlock_t pSRB_lock; /* SRB queue lock */ #endif -// Scsi_Cmnd *pSRB_head; /* B4 SRB save queue header */ -// Scsi_Cmnd *pSRB_tail; /* B8 SRB save queue tail */ } HCS; /* Bit Definition for HCB_Config */ @@ -636,77 +623,77 @@ Serial EEProm *******************************************************************/ -typedef struct _NVRAM_SCSI { /* SCSI channel configuration */ - UCHAR NVM_ChSCSIID; /* 0Ch -> Channel SCSI ID */ - UCHAR NVM_ChConfig1; /* 0Dh -> Channel config 1 */ - UCHAR NVM_ChConfig2; /* 0Eh -> Channel config 2 */ - UCHAR NVM_NumOfTarg; /* 0Fh -> Number of SCSI target */ - /* SCSI target configuration */ - UCHAR NVM_Targ0Config; /* 10h -> Target 0 configuration*/ - UCHAR NVM_Targ1Config; /* 11h -> Target 1 configuration*/ - UCHAR NVM_Targ2Config; /* 12h -> Target 2 configuration*/ - UCHAR NVM_Targ3Config; /* 13h -> Target 3 configuration*/ - UCHAR NVM_Targ4Config; /* 14h -> Target 4 configuration*/ - UCHAR NVM_Targ5Config; /* 15h -> Target 5 configuration*/ - UCHAR NVM_Targ6Config; /* 16h -> Target 6 configuration*/ - UCHAR NVM_Targ7Config; /* 17h -> Target 7 configuration*/ - UCHAR NVM_Targ8Config; /* 18h -> Target 8 configuration*/ - UCHAR NVM_Targ9Config; /* 19h -> Target 9 configuration*/ - UCHAR NVM_TargAConfig; /* 1Ah -> Target A configuration*/ - UCHAR NVM_TargBConfig; /* 1Bh -> Target B configuration*/ - UCHAR NVM_TargCConfig; /* 1Ch -> Target C configuration*/ - UCHAR NVM_TargDConfig; /* 1Dh -> Target D configuration*/ - UCHAR NVM_TargEConfig; /* 1Eh -> Target E configuration*/ - UCHAR NVM_TargFConfig; /* 1Fh -> Target F configuration*/ +typedef struct _NVRAM_SCSI { /* SCSI channel configuration */ + UCHAR NVM_ChSCSIID; /* 0Ch -> Channel SCSI ID */ + UCHAR NVM_ChConfig1; /* 0Dh -> Channel config 1 */ + UCHAR NVM_ChConfig2; /* 0Eh -> Channel config 2 */ + UCHAR NVM_NumOfTarg; /* 0Fh -> Number of SCSI target */ + /* SCSI target configuration */ + UCHAR NVM_Targ0Config; /* 10h -> Target 0 configuration */ + UCHAR NVM_Targ1Config; /* 11h -> Target 1 configuration */ + UCHAR NVM_Targ2Config; /* 12h -> Target 2 configuration */ + UCHAR NVM_Targ3Config; /* 13h -> Target 3 configuration */ + UCHAR NVM_Targ4Config; /* 14h -> Target 4 configuration */ + UCHAR NVM_Targ5Config; /* 15h -> Target 5 configuration */ + UCHAR NVM_Targ6Config; /* 16h -> Target 6 configuration */ + UCHAR NVM_Targ7Config; /* 17h -> Target 7 configuration */ + UCHAR NVM_Targ8Config; /* 18h -> Target 8 configuration */ + UCHAR NVM_Targ9Config; /* 19h -> Target 9 configuration */ + UCHAR NVM_TargAConfig; /* 1Ah -> Target A configuration */ + UCHAR NVM_TargBConfig; /* 1Bh -> Target B configuration */ + UCHAR NVM_TargCConfig; /* 1Ch -> Target C configuration */ + UCHAR NVM_TargDConfig; /* 1Dh -> Target D configuration */ + UCHAR NVM_TargEConfig; /* 1Eh -> Target E configuration */ + UCHAR NVM_TargFConfig; /* 1Fh -> Target F configuration */ } NVRAM_SCSI; typedef struct _NVRAM { - /*----------header ---------------*/ - USHORT NVM_Signature; /* 0,1: Signature */ - UCHAR NVM_Size; /* 2: Size of data structure */ - UCHAR NVM_Revision; /* 3: Revision of data structure */ - /* ----Host Adapter Structure ----*/ - UCHAR NVM_ModelByte0; /* 4: Model number (byte 0) */ - UCHAR NVM_ModelByte1; /* 5: Model number (byte 1) */ - UCHAR NVM_ModelInfo; /* 6: Model information */ - UCHAR NVM_NumOfCh; /* 7: Number of SCSI channel*/ - UCHAR NVM_BIOSConfig1; /* 8: BIOS configuration 1 */ - UCHAR NVM_BIOSConfig2; /* 9: BIOS configuration 2 */ - UCHAR NVM_HAConfig1; /* A: Hoat adapter configuration 1 */ - UCHAR NVM_HAConfig2; /* B: Hoat adapter configuration 2 */ +/*----------header ---------------*/ + USHORT NVM_Signature; /* 0,1: Signature */ + UCHAR NVM_Size; /* 2: Size of data structure */ + UCHAR NVM_Revision; /* 3: Revision of data structure */ + /* ----Host Adapter Structure ---- */ + UCHAR NVM_ModelByte0; /* 4: Model number (byte 0) */ + UCHAR NVM_ModelByte1; /* 5: Model number (byte 1) */ + UCHAR NVM_ModelInfo; /* 6: Model information */ + UCHAR NVM_NumOfCh; /* 7: Number of SCSI channel */ + UCHAR NVM_BIOSConfig1; /* 8: BIOS configuration 1 */ + UCHAR NVM_BIOSConfig2; /* 9: BIOS configuration 2 */ + UCHAR NVM_HAConfig1; /* A: Hoat adapter configuration 1 */ + UCHAR NVM_HAConfig2; /* B: Hoat adapter configuration 2 */ NVRAM_SCSI NVM_SCSIInfo[2]; - UCHAR NVM_reserved[10]; + UCHAR NVM_reserved[10]; /* ---------- CheckSum ---------- */ - USHORT NVM_CheckSum; /* 0x3E, 0x3F: Checksum of NVRam */ - } NVRAM, *PNVRAM; + USHORT NVM_CheckSum; /* 0x3E, 0x3F: Checksum of NVRam */ +} NVRAM, *PNVRAM; /* Bios Configuration for nvram->BIOSConfig1 */ -#define NBC1_ENABLE 0x01 /* BIOS enable */ -#define NBC1_8DRIVE 0x02 /* Support more than 2 drives */ -#define NBC1_REMOVABLE 0x04 /* Support removable drive */ -#define NBC1_INT19 0x08 /* Intercept int 19h */ -#define NBC1_BIOSSCAN 0x10 /* Dynamic BIOS scan */ -#define NBC1_LUNSUPPORT 0x40 /* Support LUN */ +#define NBC1_ENABLE 0x01 /* BIOS enable */ +#define NBC1_8DRIVE 0x02 /* Support more than 2 drives */ +#define NBC1_REMOVABLE 0x04 /* Support removable drive */ +#define NBC1_INT19 0x08 /* Intercept int 19h */ +#define NBC1_BIOSSCAN 0x10 /* Dynamic BIOS scan */ +#define NBC1_LUNSUPPORT 0x40 /* Support LUN */ /* HA Configuration Byte 1 */ -#define NHC1_BOOTIDMASK 0x0F /* Boot ID number */ -#define NHC1_LUNMASK 0x70 /* Boot LUN number */ -#define NHC1_CHANMASK 0x80 /* Boot Channel number */ +#define NHC1_BOOTIDMASK 0x0F /* Boot ID number */ +#define NHC1_LUNMASK 0x70 /* Boot LUN number */ +#define NHC1_CHANMASK 0x80 /* Boot Channel number */ /* Bit definition for nvram->SCSIconfig1 */ -#define NCC1_BUSRESET 0x01 /* Reset SCSI bus at power up */ -#define NCC1_PARITYCHK 0x02 /* SCSI parity enable */ -#define NCC1_ACTTERM1 0x04 /* Enable active terminator 1 */ -#define NCC1_ACTTERM2 0x08 /* Enable active terminator 2 */ -#define NCC1_AUTOTERM 0x10 /* Enable auto terminator */ -#define NCC1_PWRMGR 0x80 /* Enable power management */ +#define NCC1_BUSRESET 0x01 /* Reset SCSI bus at power up */ +#define NCC1_PARITYCHK 0x02 /* SCSI parity enable */ +#define NCC1_ACTTERM1 0x04 /* Enable active terminator 1 */ +#define NCC1_ACTTERM2 0x08 /* Enable active terminator 2 */ +#define NCC1_AUTOTERM 0x10 /* Enable auto terminator */ +#define NCC1_PWRMGR 0x80 /* Enable power management */ /* Bit definition for SCSI Target configuration byte */ -#define NTC_DISCONNECT 0x08 /* Enable SCSI disconnect */ -#define NTC_SYNC 0x10 /* SYNC_NEGO */ -#define NTC_NO_WDTR 0x20 /* SYNC_NEGO */ -#define NTC_1GIGA 0x40 /* 255 head / 63 sectors (64/32)*/ -#define NTC_SPINUP 0x80 /* Start disk drive */ +#define NTC_DISCONNECT 0x08 /* Enable SCSI disconnect */ +#define NTC_SYNC 0x10 /* SYNC_NEGO */ +#define NTC_NO_WDTR 0x20 /* SYNC_NEGO */ +#define NTC_1GIGA 0x40 /* 255 head / 63 sectors (64/32) */ +#define NTC_SPINUP 0x80 /* Start disk drive */ /* Default NVRam values */ #define INI_SIGNATURE 0xC925 @@ -715,8 +702,8 @@ #define NTC_DEFAULT (NTC_NO_WDTR | NTC_1GIGA | NTC_DISCONNECT) /* SCSI related definition */ -#define DISC_NOT_ALLOW 0x80 /* Disconnect is not allowed */ -#define DISC_ALLOW 0xC0 /* Disconnect is allowed */ +#define DISC_NOT_ALLOW 0x80 /* Disconnect is not allowed */ +#define DISC_ALLOW 0xC0 /* Disconnect is allowed */ #define SCSICMD_RequestSense 0x03 @@ -737,126 +724,105 @@ #define SUCCESSFUL 0x00 #define FUNC_NOT_SUPPORTED 0x81 -#define BAD_VENDOR_ID 0x83 /* Bad vendor ID */ -#define DEVICE_NOT_FOUND 0x86 /* PCI device not found */ +#define BAD_VENDOR_ID 0x83 /* Bad vendor ID */ +#define DEVICE_NOT_FOUND 0x86 /* PCI device not found */ #define BAD_REGISTER_NUMBER 0x87 -#define MAX_PCI_DEVICES 21 /* Maximum devices supportted */ +#define MAX_PCI_DEVICES 21 /* Maximum devices supportted */ #define MAX_PCI_CHANL 4 typedef struct _BIOS32_ENTRY_STRUCTURE { - DWORD Signatures; /* Should be "_32_" */ - DWORD BIOS32Entry; /* 32-bit physical address */ - BYTE Revision; /* Revision level, should be 0 */ - BYTE Length; /* Multiply of 16, should be 1 */ - BYTE CheckSum; /* Checksum of whole structure */ - BYTE Reserved[5]; /* Reserved */ + DWORD Signatures; /* Should be "_32_" */ + DWORD BIOS32Entry; /* 32-bit physical address */ + BYTE Revision; /* Revision level, should be 0 */ + BYTE Length; /* Multiply of 16, should be 1 */ + BYTE CheckSum; /* Checksum of whole structure */ + BYTE Reserved[5]; /* Reserved */ } BIOS32_ENTRY_STRUCTURE, *PBIOS32_ENTRY_STRUCTURE; -typedef struct - { - union - { - unsigned int eax; - struct - { - unsigned short ax; - } word; - struct - { - unsigned char al; - unsigned char ah; - } byte; - } eax; - union - { - unsigned int ebx; - struct - { - unsigned short bx; - } word; - struct - { - unsigned char bl; - unsigned char bh; - } byte; - } ebx; - union - { - unsigned int ecx; - struct - { - unsigned short cx; - } word; - struct - { - unsigned char cl; - unsigned char ch; - } byte; - } ecx; - union - { - unsigned int edx; - struct - { - unsigned short dx; - } word; - struct - { - unsigned char dl; - unsigned char dh; - } byte; - } edx; - union - { - unsigned int edi; - struct - { - unsigned short di; - } word; - } edi; - union - { - unsigned int esi; - struct - { - unsigned short si; - } word; - } esi; - } REGS; - -typedef union /* Union define for mechanism 1 */ - { - struct - { - unsigned char RegNum; - unsigned char FcnNum:3; - unsigned char DeviceNum:5; - unsigned char BusNum; - unsigned char Reserved:7; - unsigned char Enable:1; - } sConfigAdr; - unsigned long lConfigAdr; - } CONFIG_ADR; - -typedef union /* Union define for mechanism 2 */ - { - struct - { - unsigned char RegNum; - unsigned char DeviceNum; - unsigned short Reserved; - } sHostAdr; - unsigned long lHostAdr; - } HOST_ADR; +typedef struct { + union { + unsigned int eax; + struct { + unsigned short ax; + } word; + struct { + unsigned char al; + unsigned char ah; + } byte; + } eax; + union { + unsigned int ebx; + struct { + unsigned short bx; + } word; + struct { + unsigned char bl; + unsigned char bh; + } byte; + } ebx; + union { + unsigned int ecx; + struct { + unsigned short cx; + } word; + struct { + unsigned char cl; + unsigned char ch; + } byte; + } ecx; + union { + unsigned int edx; + struct { + unsigned short dx; + } word; + struct { + unsigned char dl; + unsigned char dh; + } byte; + } edx; + union { + unsigned int edi; + struct { + unsigned short di; + } word; + } edi; + union { + unsigned int esi; + struct { + unsigned short si; + } word; + } esi; +} REGS; + +typedef union { /* Union define for mechanism 1 */ + struct { + unsigned char RegNum; + unsigned char FcnNum:3; + unsigned char DeviceNum:5; + unsigned char BusNum; + unsigned char Reserved:7; + unsigned char Enable:1; + } sConfigAdr; + unsigned long lConfigAdr; +} CONFIG_ADR; + +typedef union { /* Union define for mechanism 2 */ + struct { + unsigned char RegNum; + unsigned char DeviceNum; + unsigned short Reserved; + } sHostAdr; + unsigned long lHostAdr; +} HOST_ADR; typedef struct _HCSinfo { - ULONG base; - UCHAR vec; - UCHAR bios; /* High byte of BIOS address */ - USHORT BaseAndBios; /* high byte: pHcsInfo->bios,low byte:pHcsInfo->base */ - } HCSINFO ; + ULONG base; + UCHAR vec; + UCHAR bios; /* High byte of BIOS address */ + USHORT BaseAndBios; /* high byte: pHcsInfo->bios,low byte:pHcsInfo->base */ +} HCSINFO; #define TUL_RD(x,y) (UCHAR)(inb( (int)((ULONG)(x+y)) )) #define TUL_RDLONG(x,y) (ULONG)(inl((int)((ULONG)(x+y)) )) @@ -887,4 +853,3 @@ #define SCSI_RESET_BUS_RESET 0x100 #define SCSI_RESET_HOST_RESET 0x200 #define SCSI_RESET_ACTION 0xff - diff -urN linux-2.0.37-pre2/drivers/scsi/ini9100u.c linux-2.0.37-pre3/drivers/scsi/ini9100u.c --- linux-2.0.37-pre2/drivers/scsi/ini9100u.c 2003-08-15 15:04:26.000000000 -0700 +++ linux-2.0.37-pre3/drivers/scsi/ini9100u.c 2003-08-15 15:04:26.000000000 -0700 @@ -1,8 +1,8 @@ - /************************************************************************** * Initio 9100 device driver for Linux. * * Copyright (c) 1994-1998 Initio Corporation + * Copyright (c) 1998 Bas Vermeulen * All rights reserved. * * This program is free software; you can redistribute it and/or modify @@ -87,6 +87,12 @@ * - Handle reset routine. * 09/21/98 hl - v1.03 * - remove comments. + * 12/09/98 bv - v1.03a + * - Removed unused code + * 12/13/98 bv - v1.03b + * - Remove cli() locking for kernels >= 2.1.95. This uses + * spinlocks to serialize access to the pSRB_head and + * pSRB_tail members of the HCS structure. **************************************************************************/ #define CVT_LINUX_VERSION(V,P,S) (V * 65536 + P * 256 + S) @@ -156,7 +162,7 @@ #endif #ifdef DEBUG_i91u -unsigned int i91u_debug = DEBUG_DEFAULT; +unsigned int i91u_debug = DEBUG_DEFAULT; #endif #ifdef MODULE @@ -164,82 +170,80 @@ #include "scsi_module.c" #endif -char *i91uCopyright = "Copyright (C) 1996-98"; -char *i91uInitioName = "by Initio Corporation"; -char *i91uProductName= "INI-9X00U/UW"; -char *i91uVersion = "v1.03"; +char *i91uCopyright = "Copyright (C) 1996-98"; +char *i91uInitioName = "by Initio Corporation"; +char *i91uProductName = "INI-9X00U/UW"; +char *i91uVersion = "v1.03b"; #if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0) struct proc_dir_entry proc_scsi_ini9100u = - { - PROC_SCSI_INI9100U , 7, "INI9100U", +{ + PROC_SCSI_INI9100U, 7, "INI9100U", S_IFDIR | S_IRUGO | S_IXUGO, 2, 0, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL - }; +}; #endif -#if 1 /* <01> */ #define TULSZ(sz) (sizeof(sz) / sizeof(sz[0])) #define TUL_RDWORD(x,y) (short)(inl((int)((ULONG)((ULONG)x+(UCHAR)y)) )) -#endif /* set by i91_setup according to the command line */ -static int setup_called = 0; +static int setup_called = 0; -static int tul_num_ch = 4; /* Maximum 4 adapters */ -static int tul_num_scb; -static int tul_tag_enable = 1; -static SCB *tul_scb; +static int tul_num_ch = 4; /* Maximum 4 adapters */ +static int tul_num_scb; +static int tul_tag_enable = 1; +static SCB *tul_scb; #ifdef DEBUG_i91u -static int setup_debug = 0; +static int setup_debug = 0; #endif -static char *setup_str = (char *)NULL; +static char *setup_str = (char *) NULL; #if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0) -static void i91u_intr0( int irq, void *dev_id, struct pt_regs * ); -static void i91u_intr1( int irq, void *dev_id, struct pt_regs * ); -static void i91u_intr2( int irq, void *dev_id, struct pt_regs * ); -static void i91u_intr3( int irq, void *dev_id, struct pt_regs * ); -static void i91u_intr4( int irq, void *dev_id, struct pt_regs * ); -static void i91u_intr5( int irq, void *dev_id, struct pt_regs * ); -static void i91u_intr6( int irq, void *dev_id, struct pt_regs * ); -static void i91u_intr7( int irq, void *dev_id, struct pt_regs * ); +static void i91u_intr0(int irq, void *dev_id, struct pt_regs *); +static void i91u_intr1(int irq, void *dev_id, struct pt_regs *); +static void i91u_intr2(int irq, void *dev_id, struct pt_regs *); +static void i91u_intr3(int irq, void *dev_id, struct pt_regs *); +static void i91u_intr4(int irq, void *dev_id, struct pt_regs *); +static void i91u_intr5(int irq, void *dev_id, struct pt_regs *); +static void i91u_intr6(int irq, void *dev_id, struct pt_regs *); +static void i91u_intr7(int irq, void *dev_id, struct pt_regs *); #else -static void i91u_intr0( int irq, struct pt_regs * ); -static void i91u_intr1( int irq, struct pt_regs * ); -static void i91u_intr2( int irq, struct pt_regs * ); -static void i91u_intr3( int irq, struct pt_regs * ); -static void i91u_intr4( int irq, struct pt_regs * ); -static void i91u_intr5( int irq, struct pt_regs * ); -static void i91u_intr6( int irq, struct pt_regs * ); -static void i91u_intr7( int irq, struct pt_regs * ); +static void i91u_intr0(int irq, struct pt_regs *); +static void i91u_intr1(int irq, struct pt_regs *); +static void i91u_intr2(int irq, struct pt_regs *); +static void i91u_intr3(int irq, struct pt_regs *); +static void i91u_intr4(int irq, struct pt_regs *); +static void i91u_intr5(int irq, struct pt_regs *); +static void i91u_intr6(int irq, struct pt_regs *); +static void i91u_intr7(int irq, struct pt_regs *); #endif -static void i91u_panic(char *msg); +static void i91u_panic(char *msg); -static void i91uSCBPost(BYTE *pHcb, BYTE *pScb); +static void i91uSCBPost(BYTE * pHcb, BYTE * pScb); /* ---- EXTERNAL FUNCTIONS ---- */ - /* Get total number of adapters*/ -extern void init_i91uAdapter_table(void); -extern int Addi91u_into_Adapter_table(WORD, WORD, BYTE, BYTE, BYTE); -extern int tul_ReturnNumberOfAdapters(void); -extern void get_tulipPCIConfig(HCS *pHCB, int iChannel_index); -extern int init_tulip(HCS *pHCB, SCB *pSCB, int tul_num_scb, BYTE *pbBiosAdr, int reset_time); -extern SCB *tul_alloc_scb(HCS *pHCB); -extern int tul_abort_srb(HCS *pHCB, Scsi_Cmnd *pSRB); -extern void tul_exec_scb(HCS *pHCB, SCB *pSCB); -extern void tul_release_scb(HCS *pHCB, SCB *pSCB); -extern void tul_stop_bm(HCS *pHCB); -extern int tul_reset_scsi(HCS *pCurHcb, int seconds); -extern int tul_isr(HCS *pHCB); -extern int tul_reset(HCS *pHCB, Scsi_Cmnd *pSRB, unsigned char target); -extern int tul_reset_scsi_bus(HCS *pCurHcb); -extern int tul_device_reset(HCS *pCurHcb, ULONG pSrb, unsigned int target, unsigned int ResetFlags); + /* Get total number of adapters */ +extern void init_i91uAdapter_table(void); +extern int Addi91u_into_Adapter_table(WORD, WORD, BYTE, BYTE, BYTE); +extern int tul_ReturnNumberOfAdapters(void); +extern void get_tulipPCIConfig(HCS * pHCB, int iChannel_index); +extern int init_tulip(HCS * pHCB, SCB * pSCB, int tul_num_scb, BYTE * pbBiosAdr, int reset_time); +extern SCB *tul_alloc_scb(HCS * pHCB); +extern int tul_abort_srb(HCS * pHCB, Scsi_Cmnd * pSRB); +extern void tul_exec_scb(HCS * pHCB, SCB * pSCB); +extern void tul_release_scb(HCS * pHCB, SCB * pSCB); +extern void tul_stop_bm(HCS * pHCB); +extern int tul_reset_scsi(HCS * pCurHcb, int seconds); +extern int tul_isr(HCS * pHCB); +extern int tul_reset(HCS * pHCB, Scsi_Cmnd * pSRB, unsigned char target); +extern int tul_reset_scsi_bus(HCS * pCurHcb); +extern int tul_device_reset(HCS * pCurHcb, ULONG pSrb, unsigned int target, unsigned int ResetFlags); /* ---- EXTERNAL VARIABLES ---- */ -extern HCS tul_hcs[]; +extern HCS tul_hcs[]; /* * queue services: @@ -252,24 +256,30 @@ Output : None. Return : None. *****************************************************************************/ -static void i91uAppendSRBToQueue(HCS *pHCB, Scsi_Cmnd *pSRB) +static void i91uAppendSRBToQueue(HCS * pHCB, Scsi_Cmnd * pSRB) { - ULONG flags; - - save_flags(flags); - cli(); - - pSRB->next = NULL; /* Pointer to next */ + ULONG flags; +#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95) + spin_lock_irqsave(&(pHCB->pSRB_lock), flags); +#else + save_flags(flags); + cli(); +#endif - if (pHCB->pSRB_head == NULL) - pHCB->pSRB_head = pSRB; - else - pHCB->pSRB_tail->next = pSRB; /* Pointer to next */ - pHCB->pSRB_tail = pSRB; + pSRB->next = NULL; /* Pointer to next */ - restore_flags(flags); + if (pHCB->pSRB_head == NULL) + pHCB->pSRB_head = pSRB; + else + pHCB->pSRB_tail->next = pSRB; /* Pointer to next */ + pHCB->pSRB_tail = pSRB; - return; +#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95) + spin_unlock_irqrestore(&(pHCB->pSRB_lock), flags); +#else + restore_flags(flags); +#endif + return; } /***************************************************************************** @@ -279,115 +289,117 @@ Output : None. Return : pSRB - Pointer to SCSI request block. *****************************************************************************/ -static Scsi_Cmnd *i91uPopSRBFromQueue(HCS *pHCB) +static Scsi_Cmnd *i91uPopSRBFromQueue(HCS * pHCB) { - Scsi_Cmnd *pSRB; - ULONG flags; + Scsi_Cmnd *pSRB; + ULONG flags; - save_flags(flags); - cli(); +#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95) + spin_lock_irqsave(&(pHCB->pSRB_lock), flags); +#else + save_flags(flags); + cli(); +#endif - if ((pSRB = pHCB->pSRB_head) != NULL) - { - pHCB->pSRB_head = pHCB->pSRB_head->next; - pSRB->next = NULL; + if ((pSRB = pHCB->pSRB_head) != NULL) { + pHCB->pSRB_head = pHCB->pSRB_head->next; + pSRB->next = NULL; } +#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95) + spin_unlock_irqrestore(&(pHCB->pSRB_lock), flags); +#else + restore_flags(flags); +#endif - restore_flags(flags); - - return (pSRB); + return (pSRB); } /* called from init/main.c */ -void i91u_setup( char *str, int *ints) +void i91u_setup(char *str, int *ints) { - if (setup_called) - i91u_panic("i91u: i91u_setup called twice.\n"); + if (setup_called) + i91u_panic("i91u: i91u_setup called twice.\n"); - setup_called = ints[0]; - setup_str = str; + setup_called = ints[0]; + setup_str = str; #ifdef DEBUG_i91u - setup_debug = ints[0] >= 1 ? ints[1] : DEBUG_DEFAULT; + setup_debug = ints[0] >= 1 ? ints[1] : DEBUG_DEFAULT; #endif } #if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,93) int tul_NewReturnNumberOfAdapters(void) { - struct pci_dev *pDev = NULL; /* Start from none */ - int iAdapters = 0; - long dRegValue; - WORD wBIOS; - - init_i91uAdapter_table(); - - while ((pDev = pci_find_device(INI_VENDOR_ID,I950_DEVICE_ID,pDev)) != NULL) - { - pci_read_config_dword(pDev, 0x44, (u32 *) &dRegValue); - wBIOS = (UWORD) (dRegValue & 0xFF); - if (((dRegValue & 0xFF00) >> 8) == 0xFF) - dRegValue = 0; - wBIOS = (wBIOS << 8) + ((UWORD) ((dRegValue & 0xFF00) >> 8)); - if (Addi91u_into_Adapter_table( wBIOS, + struct pci_dev *pDev = NULL; /* Start from none */ + int iAdapters = 0; + long dRegValue; + WORD wBIOS; + + init_i91uAdapter_table(); + + while ((pDev = pci_find_device(INI_VENDOR_ID, I950_DEVICE_ID, pDev)) != NULL) { + pci_read_config_dword(pDev, 0x44, (u32 *) & dRegValue); + wBIOS = (UWORD) (dRegValue & 0xFF); + if (((dRegValue & 0xFF00) >> 8) == 0xFF) + dRegValue = 0; + wBIOS = (wBIOS << 8) + ((UWORD) ((dRegValue & 0xFF00) >> 8)); + if (Addi91u_into_Adapter_table(wBIOS, (pDev->base_address[0] & 0xFFFE), - pDev->irq, - pDev->bus->number, - (pDev->devfn >> 3) - ) == 0) - iAdapters++; - } - while ((pDev = pci_find_device(INI_VENDOR_ID,I940_DEVICE_ID,pDev)) != NULL) - { - pci_read_config_dword(pDev, 0x44, (u32 *) &dRegValue); - wBIOS = (UWORD) (dRegValue & 0xFF); - if (((dRegValue & 0xFF00) >> 8) == 0xFF) - dRegValue = 0; - wBIOS = (wBIOS << 8) + ((UWORD) ((dRegValue & 0xFF00) >> 8)); - if (Addi91u_into_Adapter_table( wBIOS, + pDev->irq, + pDev->bus->number, + (pDev->devfn >> 3) + ) == 0) + iAdapters++; + } + while ((pDev = pci_find_device(INI_VENDOR_ID, I940_DEVICE_ID, pDev)) != NULL) { + pci_read_config_dword(pDev, 0x44, (u32 *) & dRegValue); + wBIOS = (UWORD) (dRegValue & 0xFF); + if (((dRegValue & 0xFF00) >> 8) == 0xFF) + dRegValue = 0; + wBIOS = (wBIOS << 8) + ((UWORD) ((dRegValue & 0xFF00) >> 8)); + if (Addi91u_into_Adapter_table(wBIOS, (pDev->base_address[0] & 0xFFFE), - pDev->irq, - pDev->bus->number, - (pDev->devfn >> 3) - ) == 0) - iAdapters++; - } - while ((pDev = pci_find_device(INI_VENDOR_ID,I935_DEVICE_ID,pDev)) != NULL) - { - pci_read_config_dword(pDev, 0x44, (u32 *) &dRegValue); - wBIOS = (UWORD) (dRegValue & 0xFF); - if (((dRegValue & 0xFF00) >> 8) == 0xFF) - dRegValue = 0; - wBIOS = (wBIOS << 8) + ((UWORD) ((dRegValue & 0xFF00) >> 8)); - if (Addi91u_into_Adapter_table( wBIOS, + pDev->irq, + pDev->bus->number, + (pDev->devfn >> 3) + ) == 0) + iAdapters++; + } + while ((pDev = pci_find_device(INI_VENDOR_ID, I935_DEVICE_ID, pDev)) != NULL) { + pci_read_config_dword(pDev, 0x44, (u32 *) & dRegValue); + wBIOS = (UWORD) (dRegValue & 0xFF); + if (((dRegValue & 0xFF00) >> 8) == 0xFF) + dRegValue = 0; + wBIOS = (wBIOS << 8) + ((UWORD) ((dRegValue & 0xFF00) >> 8)); + if (Addi91u_into_Adapter_table(wBIOS, (pDev->base_address[0] & 0xFFFE), - pDev->irq, - pDev->bus->number, - (pDev->devfn >> 3) - ) == 0) - iAdapters++; - } - while ((pDev = pci_find_device(INI_VENDOR_ID,0x0002,pDev)) != NULL) - { - pci_read_config_dword(pDev, 0x44, (u32 *) &dRegValue); - wBIOS = (UWORD) (dRegValue & 0xFF); - if (((dRegValue & 0xFF00) >> 8) == 0xFF) - dRegValue = 0; - wBIOS = (wBIOS << 8) + ((UWORD) ((dRegValue & 0xFF00) >> 8)); - if (Addi91u_into_Adapter_table( wBIOS, + pDev->irq, + pDev->bus->number, + (pDev->devfn >> 3) + ) == 0) + iAdapters++; + } + while ((pDev = pci_find_device(INI_VENDOR_ID, 0x0002, pDev)) != NULL) { + pci_read_config_dword(pDev, 0x44, (u32 *) & dRegValue); + wBIOS = (UWORD) (dRegValue & 0xFF); + if (((dRegValue & 0xFF00) >> 8) == 0xFF) + dRegValue = 0; + wBIOS = (wBIOS << 8) + ((UWORD) ((dRegValue & 0xFF00) >> 8)); + if (Addi91u_into_Adapter_table(wBIOS, (pDev->base_address[0] & 0xFFFE), - pDev->irq, - pDev->bus->number, - (pDev->devfn >> 3) - ) == 0) - iAdapters++; + pDev->irq, + pDev->bus->number, + (pDev->devfn >> 3) + ) == 0) + iAdapters++; } - return (iAdapters); + return (iAdapters); } -#else /* <01> */ +#else /* <01> */ /***************************************************************************** Function name : tul_ReturnNumberOfAdapters @@ -399,480 +411,422 @@ *****************************************************************************/ int tul_ReturnNumberOfAdapters(void) { - unsigned int i, iAdapters; - unsigned int dRegValue; - unsigned short command; - WORD wBIOS, wBASE; - BYTE bPCIBusNum, bInterrupt, bPCIDeviceNum; - struct - { - unsigned short vendor_id; - unsigned short device_id; - } const i91u_pci_devices[] = { - {INI_VENDOR_ID, I935_DEVICE_ID}, - {INI_VENDOR_ID, I940_DEVICE_ID}, - {INI_VENDOR_ID, I950_DEVICE_ID}, - {INI_VENDOR_ID, I920_DEVICE_ID} - }; - - - iAdapters = 0; - /* - * PCI-bus probe. - */ - if (pcibios_present()) - { + unsigned int i, iAdapters; + unsigned int dRegValue; + unsigned short command; + WORD wBIOS, wBASE; + BYTE bPCIBusNum, bInterrupt, bPCIDeviceNum; + struct { + unsigned short vendor_id; + unsigned short device_id; + } const i91u_pci_devices[] = + { + {INI_VENDOR_ID, I935_DEVICE_ID}, + {INI_VENDOR_ID, I940_DEVICE_ID}, + {INI_VENDOR_ID, I950_DEVICE_ID}, + {INI_VENDOR_ID, I920_DEVICE_ID} + }; + + + iAdapters = 0; + /* + * PCI-bus probe. + */ + if (pcibios_present()) { #ifdef MMAPIO - unsigned long page_offset, base; + unsigned long page_offset, base; #endif #if LINUX_VERSION_CODE > CVT_LINUX_VERSION(2,1,92) - struct pci_dev *pdev = NULL; + struct pci_dev *pdev = NULL; #else - int index; - unsigned char pci_bus, pci_devfn; + int index; + unsigned char pci_bus, pci_devfn; #endif - bPCIBusNum = 0; - bPCIDeviceNum = 0; - init_i91uAdapter_table(); - for (i = 0; i < TULSZ(i91u_pci_devices); i++) - { + bPCIBusNum = 0; + bPCIDeviceNum = 0; + init_i91uAdapter_table(); + for (i = 0; i < TULSZ(i91u_pci_devices); i++) { #if LINUX_VERSION_CODE > CVT_LINUX_VERSION(2,1,92) - pdev = NULL; - while ((pdev = pci_find_device(i91u_pci_devices[i].vendor_id, - i91u_pci_devices[i].device_id, - pdev))) -#else - index = 0; - while (!(pcibios_find_device(i91u_pci_devices[i].vendor_id, - i91u_pci_devices[i].device_id, - index++, &pci_bus, &pci_devfn)) ) -#endif - { - if ( i == 0 ) - { - /* - printk("i91u: The RAID controller is not supported by\n"); - printk("i91u: this driver, we are ignoring it.\n"); - */ - } - else - { - /* - * Read sundry information from PCI BIOS. - */ + pdev = NULL; + while ((pdev = pci_find_device(i91u_pci_devices[i].vendor_id, + i91u_pci_devices[i].device_id, + pdev))) +#else + index = 0; + while (!(pcibios_find_device(i91u_pci_devices[i].vendor_id, + i91u_pci_devices[i].device_id, + index++, &pci_bus, &pci_devfn))) +#endif + { + if (i == 0) { + /* + printk("i91u: The RAID controller is not supported by\n"); + printk("i91u: this driver, we are ignoring it.\n"); + */ + } else { + /* + * Read sundry information from PCI BIOS. + */ #if LINUX_VERSION_CODE > CVT_LINUX_VERSION(2,1,92) - bPCIBusNum = pdev->bus->number; - bPCIDeviceNum = pdev->devfn; - dRegValue = pdev->base_address[0]; - if (dRegValue == -1) - { /* Check return code */ - printk("\n\ri91u: tulip read configuration error.\n"); - return(0); /* Read configuration space error */ - } - /* <02> read from base address + 0x50 offset to get the wBIOS balue. */ - wBASE = (WORD) dRegValue; - - /* Now read the interrupt line */ - dRegValue = pdev->irq; - bInterrupt = dRegValue & 0xFF;/* Assign interrupt line */ - pci_read_config_word(pdev, PCI_COMMAND, &command); - pci_write_config_word(pdev, PCI_COMMAND, - command | PCI_COMMAND_MASTER | PCI_COMMAND_IO); - -#else - bPCIBusNum = pci_bus; - bPCIDeviceNum = pci_devfn; - pcibios_read_config_dword(pci_bus, pci_devfn, PCI_BASE_ADDRESS_0, - &dRegValue); - if (dRegValue == -1) - { /* Check return code */ - printk("\n\ri91u: tulip read configuration error.\n"); - return(0); /* Read configuration space error */ - } - /* <02> read from base address + 0x50 offset to get the wBIOS balue. */ - wBASE = (WORD) dRegValue; - - /* Now read the interrupt line */ - pcibios_read_config_dword(pci_bus, pci_devfn, PCI_INTERRUPT_LINE, - &dRegValue); - bInterrupt = dRegValue & 0xFF;/* Assign interrupt line */ - pcibios_read_config_word(pci_bus, pci_devfn, PCI_COMMAND, &command); - pcibios_write_config_word(pci_bus, pci_devfn, PCI_COMMAND, - command | PCI_COMMAND_MASTER | PCI_COMMAND_IO); + bPCIBusNum = pdev->bus->number; + bPCIDeviceNum = pdev->devfn; + dRegValue = pdev->base_address[0]; + if (dRegValue == -1) { /* Check return code */ + printk("\n\ri91u: tulip read configuration error.\n"); + return (0); /* Read configuration space error */ + } + /* <02> read from base address + 0x50 offset to get the wBIOS balue. */ + wBASE = (WORD) dRegValue; + + /* Now read the interrupt line */ + dRegValue = pdev->irq; + bInterrupt = dRegValue & 0xFF; /* Assign interrupt line */ + pci_read_config_word(pdev, PCI_COMMAND, &command); + pci_write_config_word(pdev, PCI_COMMAND, + command | PCI_COMMAND_MASTER | PCI_COMMAND_IO); + +#else + bPCIBusNum = pci_bus; + bPCIDeviceNum = pci_devfn; + pcibios_read_config_dword(pci_bus, pci_devfn, PCI_BASE_ADDRESS_0, + &dRegValue); + if (dRegValue == -1) { /* Check return code */ + printk("\n\ri91u: tulip read configuration error.\n"); + return (0); /* Read configuration space error */ + } + /* <02> read from base address + 0x50 offset to get the wBIOS balue. */ + wBASE = (WORD) dRegValue; + + /* Now read the interrupt line */ + pcibios_read_config_dword(pci_bus, pci_devfn, PCI_INTERRUPT_LINE, + &dRegValue); + bInterrupt = dRegValue & 0xFF; /* Assign interrupt line */ + pcibios_read_config_word(pci_bus, pci_devfn, PCI_COMMAND, &command); + pcibios_write_config_word(pci_bus, pci_devfn, PCI_COMMAND, + command | PCI_COMMAND_MASTER | PCI_COMMAND_IO); #endif - wBASE &= PCI_BASE_ADDRESS_IO_MASK; - wBIOS = TUL_RDWORD(wBASE, 0x50); + wBASE &= PCI_BASE_ADDRESS_IO_MASK; + wBIOS = TUL_RDWORD(wBASE, 0x50); #ifdef MMAPIO - base = wBASE & PAGE_MASK; - page_offset = wBASE - base; + base = wBASE & PAGE_MASK; + page_offset = wBASE - base; - /* - * replace the next line with this one if you are using 2.1.x: - * temp_p->maddr = ioremap(base, page_offset + 256); - */ + /* + * replace the next line with this one if you are using 2.1.x: + * temp_p->maddr = ioremap(base, page_offset + 256); + */ #if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,0) - wBASE = ioremap(base, page_offset + 256); + wBASE = ioremap(base, page_offset + 256); #else - wBASE = (WORD)vremap(base, page_offset + 256); + wBASE = (WORD) vremap(base, page_offset + 256); #endif - if(wBASE) - { - wBASE += page_offset; - } -#endif - - if (Addi91u_into_Adapter_table(wBIOS, wBASE, bInterrupt, bPCIBusNum, - bPCIDeviceNum) == 0x0) - iAdapters++; - } - } /* while(pdev=....) */ - } /* for PCI_DEVICES */ - } /* PCI BIOS present */ - return (iAdapters); + if (wBASE) { + wBASE += page_offset; + } +#endif + + if (Addi91u_into_Adapter_table(wBIOS, wBASE, bInterrupt, bPCIBusNum, + bPCIDeviceNum) == 0x0) + iAdapters++; + } + } /* while(pdev=....) */ + } /* for PCI_DEVICES */ + } /* PCI BIOS present */ + return (iAdapters); } #endif int i91u_detect(Scsi_Host_Template * tpnt) { - SCB *pSCB; - HCS *pHCB; - struct Scsi_Host *hreg; - unsigned long i; /* 01/14/98 */ - int ok = 0, iAdapters; - ULONG dBiosAdr; - BYTE *pbBiosAdr; - -#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0) - tpnt->proc_dir = &proc_scsi_ini9100u; -#endif - - if (setup_called) - { /* Setup by i91u_setup */ - printk("i91u: processing commandline: "); - -#ifdef DEBUG_i91u - if (setup_called > 1) - { - printk("\ni91u: %s\n", setup_str ); - printk("i91u: usage: i91u[=]\n"); - i91u_panic("i91u panics in line %d", __LINE__); - } - i91u_debug = setup_debug; -#endif - } + SCB *pSCB; + HCS *pHCB; + struct Scsi_Host *hreg; + unsigned long i; /* 01/14/98 */ + int ok = 0, iAdapters; + ULONG dBiosAdr; + BYTE *pbBiosAdr; - /* Get total number of adapters in the motherboard */ -#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,93) - #ifdef CONFIG_PCI - iAdapters = tul_NewReturnNumberOfAdapters(); - #else - iAdapters = tul_ReturnNumberOfAdapters(); - #endif -#else - iAdapters = tul_ReturnNumberOfAdapters(); +#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0) + tpnt->proc_dir = &proc_scsi_ini9100u; #endif - if (iAdapters == 0) /* If no tulip founded, return*/ - return (0); + if (setup_called) { /* Setup by i91u_setup */ + printk("i91u: processing commandline: "); - tul_num_ch = (iAdapters > tul_num_ch)? tul_num_ch : iAdapters; - /* Update actually channel number */ - if (tul_tag_enable) /* 1.01i */ - { - tul_num_scb = MAX_TARGETS * i91u_MAXQUEUE; - } - else - { - tul_num_scb = MAX_TARGETS + 3; /* 1-tape, 1-CD_ROM, 1- extra */ - } /* Update actually SCBs per adapter */ - - /* Get total memory needed for HCS */ - i = tul_num_ch * sizeof(HCS); - memset((unsigned char *) &tul_hcs[0], 0, i);/* Initialize tul_hcs 0 */ - /* Get total memory needed for SCB */ - -#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0) - for (;tul_num_scb >= MAX_TARGETS+3; tul_num_scb--) - { - i = tul_num_ch * tul_num_scb * sizeof(SCB); - if ((tul_scb = (SCB *) kmalloc(i, GFP_ATOMIC|GFP_DMA)) != NULL) - break; +#ifdef DEBUG_i91u + if (setup_called > 1) { + printk("\ni91u: %s\n", setup_str); + printk("i91u: usage: i91u[=]\n"); + i91u_panic("i91u panics in line %d", __LINE__); + } + i91u_debug = setup_debug; +#endif } + /* Get total number of adapters in the motherboard */ +#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,93) +#ifdef CONFIG_PCI + iAdapters = tul_NewReturnNumberOfAdapters(); #else - i = tul_num_ch * tul_num_scb * sizeof(SCB); - tul_scb = (SCB *) scsi_init_malloc(i, GFP_ATOMIC|GFP_DMA); + iAdapters = tul_ReturnNumberOfAdapters(); #endif - if (tul_scb == NULL) - { - printk("i91u: SCB memory allocation error\n"); - return (0); - } - - memset((unsigned char *) tul_scb, 0, i); - - pSCB = tul_scb; - for ( i = 0; i < tul_num_ch * tul_num_scb; i++, pSCB++) - { -#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0) - pSCB->SCB_SGPAddr = (U32) VIRT_TO_BUS (&pSCB->SCB_SGList[0]); #else - pSCB->SCB_SGPAddr = (U32) (&pSCB->SCB_SGList[0]); + iAdapters = tul_ReturnNumberOfAdapters(); #endif - } - - for (i = 0, pHCB = &tul_hcs[0]; /* Get pointer for control block*/ - i < tul_num_ch; - i++, pHCB++) - { - pHCB->pSRB_head = NULL; /* Initial SRB save queue */ - pHCB->pSRB_tail = NULL; /* Initial SRB save queue */ - request_region(pHCB->HCS_Base, 0x100, "i91u"); /* Register */ + if (iAdapters == 0) /* If no tulip founded, return */ + return (0); - get_tulipPCIConfig(pHCB, i); + tul_num_ch = (iAdapters > tul_num_ch) ? tul_num_ch : iAdapters; + /* Update actually channel number */ + if (tul_tag_enable) { /* 1.01i */ + tul_num_scb = MAX_TARGETS * i91u_MAXQUEUE; + } else { + tul_num_scb = MAX_TARGETS + 3; /* 1-tape, 1-CD_ROM, 1- extra */ + } /* Update actually SCBs per adapter */ - dBiosAdr = pHCB->HCS_BIOS; - dBiosAdr = (dBiosAdr << 4); + /* Get total memory needed for HCS */ + i = tul_num_ch * sizeof(HCS); + memset((unsigned char *) &tul_hcs[0], 0, i); /* Initialize tul_hcs 0 */ + /* Get total memory needed for SCB */ #if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0) - pbBiosAdr = phys_to_virt (dBiosAdr); -#endif - - init_tulip(pHCB, tul_scb + (i * tul_num_scb), tul_num_scb, pbBiosAdr, 10); - pHCB->HCS_Index = i; /* 7/29/98 */ - hreg = scsi_register(tpnt, sizeof(HCS)); - hreg->io_port = pHCB->HCS_Base; - hreg->n_io_port = 0xff; - hreg->can_queue = tul_num_scb; /* 03/05/98 */ -#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0) - hreg->unique_id = pHCB->HCS_Base; - hreg->max_id = pHCB->HCS_MaxTar; -#endif - hreg->max_lun = 32; /* 10/21/97 */ -/* hreg->max_lun = 8; - hreg->max_channel = 1;*/ - hreg->irq = pHCB->HCS_Intr; - hreg->this_id = pHCB->HCS_SCSI_ID;/* Assign HCS index */ - hreg->base = (UCHAR *) pHCB; -#if 1 - hreg->sg_tablesize = TOTAL_SG_ENTRY; /* Maximun support is 32*/ + for (; tul_num_scb >= MAX_TARGETS + 3; tul_num_scb--) { + i = tul_num_ch * tul_num_scb * sizeof(SCB); + if ((tul_scb = (SCB *) kmalloc(i, GFP_ATOMIC | GFP_DMA)) != NULL) + break; + } #else - hreg->sg_tablesize = SG_NONE; /* No SG */ + i = tul_num_ch * tul_num_scb * sizeof(SCB); + tul_scb = (SCB *) scsi_init_malloc(i, GFP_ATOMIC | GFP_DMA); #endif -/* hreg->this_id = i; Assign HCS index */ - - /* Initial tulip chip */ - switch (i) { -#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0) - case 0: - ok = request_irq(pHCB->HCS_Intr, i91u_intr0,SA_INTERRUPT | SA_SHIRQ,"i91u",NULL); - break; - case 1: - ok = request_irq(pHCB->HCS_Intr, i91u_intr1,SA_INTERRUPT | SA_SHIRQ,"i91u",NULL); - break; - case 2: - ok = request_irq(pHCB->HCS_Intr, i91u_intr2,SA_INTERRUPT | SA_SHIRQ,"i91u",NULL); - break; - case 3: - ok = request_irq(pHCB->HCS_Intr, i91u_intr3,SA_INTERRUPT | SA_SHIRQ,"i91u",NULL); - break; - case 4: - ok = request_irq(pHCB->HCS_Intr, i91u_intr4,SA_INTERRUPT | SA_SHIRQ,"i91u",NULL); - break; - case 5: - ok = request_irq(pHCB->HCS_Intr, i91u_intr5,SA_INTERRUPT | SA_SHIRQ,"i91u",NULL); - break; - case 6: - ok = request_irq(pHCB->HCS_Intr, i91u_intr6,SA_INTERRUPT | SA_SHIRQ,"i91u",NULL); - break; - case 7: - ok = request_irq(pHCB->HCS_Intr, i91u_intr7,SA_INTERRUPT | SA_SHIRQ,"i91u",NULL); - break; - default: - i91u_panic("i91u: Too many host adapters\n"); - break; - } - if (ok < 0) - { - if (ok == -EINVAL) - { - printk("i91u: bad IRQ %d.\n", pHCB->HCS_Intr); - printk(" Contact author.\n"); + if (tul_scb == NULL) { + printk("i91u: SCB memory allocation error\n"); + return (0); + } + memset((unsigned char *) tul_scb, 0, i); + + pSCB = tul_scb; + for (i = 0; i < tul_num_ch * tul_num_scb; i++, pSCB++) { +#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0) + pSCB->SCB_SGPAddr = (U32) VIRT_TO_BUS(&pSCB->SCB_SGList[0]); +#else + pSCB->SCB_SGPAddr = (U32) (&pSCB->SCB_SGList[0]); +#endif + } + + for (i = 0, pHCB = &tul_hcs[0]; /* Get pointer for control block */ + i < tul_num_ch; + i++, pHCB++) { + pHCB->pSRB_head = NULL; /* Initial SRB save queue */ + pHCB->pSRB_tail = NULL; /* Initial SRB save queue */ +#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95) + pHCB->pSRB_lock = SPIN_LOCK_UNLOCKED; /* SRB save queue lock */ +#endif + request_region(pHCB->HCS_Base, 0x100, "i91u"); /* Register */ + + get_tulipPCIConfig(pHCB, i); + + dBiosAdr = pHCB->HCS_BIOS; + dBiosAdr = (dBiosAdr << 4); + +#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0) + pbBiosAdr = phys_to_virt(dBiosAdr); +#endif + + init_tulip(pHCB, tul_scb + (i * tul_num_scb), tul_num_scb, pbBiosAdr, 10); + pHCB->HCS_Index = i; /* 7/29/98 */ + hreg = scsi_register(tpnt, sizeof(HCS)); + hreg->io_port = pHCB->HCS_Base; + hreg->n_io_port = 0xff; + hreg->can_queue = tul_num_scb; /* 03/05/98 */ +#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0) + hreg->unique_id = pHCB->HCS_Base; + hreg->max_id = pHCB->HCS_MaxTar; +#endif + hreg->max_lun = 32; /* 10/21/97 */ + hreg->irq = pHCB->HCS_Intr; + hreg->this_id = pHCB->HCS_SCSI_ID; /* Assign HCS index */ + hreg->base = (UCHAR *) pHCB; + hreg->sg_tablesize = TOTAL_SG_ENTRY; /* Maximun support is 32 */ + + /* Initial tulip chip */ + switch (i) { +#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0) + case 0: + ok = request_irq(pHCB->HCS_Intr, i91u_intr0, SA_INTERRUPT | SA_SHIRQ, "i91u", NULL); + break; + case 1: + ok = request_irq(pHCB->HCS_Intr, i91u_intr1, SA_INTERRUPT | SA_SHIRQ, "i91u", NULL); + break; + case 2: + ok = request_irq(pHCB->HCS_Intr, i91u_intr2, SA_INTERRUPT | SA_SHIRQ, "i91u", NULL); + break; + case 3: + ok = request_irq(pHCB->HCS_Intr, i91u_intr3, SA_INTERRUPT | SA_SHIRQ, "i91u", NULL); + break; + case 4: + ok = request_irq(pHCB->HCS_Intr, i91u_intr4, SA_INTERRUPT | SA_SHIRQ, "i91u", NULL); + break; + case 5: + ok = request_irq(pHCB->HCS_Intr, i91u_intr5, SA_INTERRUPT | SA_SHIRQ, "i91u", NULL); + break; + case 6: + ok = request_irq(pHCB->HCS_Intr, i91u_intr6, SA_INTERRUPT | SA_SHIRQ, "i91u", NULL); + break; + case 7: + ok = request_irq(pHCB->HCS_Intr, i91u_intr7, SA_INTERRUPT | SA_SHIRQ, "i91u", NULL); + break; + default: + i91u_panic("i91u: Too many host adapters\n"); + break; + } + if (ok < 0) { + if (ok == -EINVAL) { + printk("i91u: bad IRQ %d.\n", pHCB->HCS_Intr); + printk(" Contact author.\n"); + } else if (ok == -EBUSY) + printk("i91u: IRQ %d already in use. Configure another.\n", + pHCB->HCS_Intr); + else { + printk("\ni91u: Unexpected error code on requesting IRQ %d.\n", + pHCB->HCS_Intr); + printk(" Contact author.\n"); + } + i91u_panic("i91u: driver needs an IRQ.\n"); } - else - if( ok == -EBUSY) - printk( "i91u: IRQ %d already in use. Configure another.\n", - pHCB->HCS_Intr); - else - { - printk( "\ni91u: Unexpected error code on requesting IRQ %d.\n", - pHCB->HCS_Intr); - printk(" Contact author.\n"); - } - i91u_panic("i91u: driver needs an IRQ.\n"); - } #endif } - tpnt->this_id = -1; -/* tpnt->can_queue=i91u_MAXQUEUE;*/ - tpnt->can_queue=1; + tpnt->this_id = -1; + tpnt->can_queue = 1; - return 1; + return 1; } -static void i91uBuildSCB(HCS *pHCB, SCB *pSCB, Scsi_Cmnd *SCpnt) -{ /* Create corresponding SCB */ - struct scatterlist *pSrbSG; - SG *pSG; /* Pointer to SG list */ - int i; - long TotalLen; - - pSCB->SCB_Post = i91uSCBPost; /* i91u's callback routine */ - pSCB->SCB_Srb = SCpnt; - pSCB->SCB_Opcode = ExecSCSI; -#if 0 - pSCB->SCB_Flags = SCF_NO_DCHK; /* Clear done bit */ - pSCB->SCB_Flags |= SCF_POST; /* After SCSI done, call post routine*/ -#else - pSCB->SCB_Flags = SCF_POST; /* After SCSI done, call post routine*/ -#endif - pSCB->SCB_Target = SCpnt->target; - pSCB->SCB_Lun = SCpnt->lun; -/* pSCB->SCB_Ident = SCpnt->lun | DISC_NOT_ALLOW;*/ - pSCB->SCB_Ident = SCpnt->lun | DISC_ALLOW; -#if 1 - pSCB->SCB_Flags |= SCF_SENSE; /* Turn on auto request sense */ -/* memset((unsigned char *) &SCpnt->sense_buffer[0], 0, SENSE_SIZE); 7/22/98 */ -#endif - -#if 1 /* 7/22/98 */ +static void i91uBuildSCB(HCS * pHCB, SCB * pSCB, Scsi_Cmnd * SCpnt) +{ /* Create corresponding SCB */ + struct scatterlist *pSrbSG; + SG *pSG; /* Pointer to SG list */ + int i; + long TotalLen; + + pSCB->SCB_Post = i91uSCBPost; /* i91u's callback routine */ + pSCB->SCB_Srb = SCpnt; + pSCB->SCB_Opcode = ExecSCSI; + pSCB->SCB_Flags = SCF_POST; /* After SCSI done, call post routine */ + pSCB->SCB_Target = SCpnt->target; + pSCB->SCB_Lun = SCpnt->lun; + pSCB->SCB_Ident = SCpnt->lun | DISC_ALLOW; + pSCB->SCB_Flags |= SCF_SENSE; /* Turn on auto request sense */ #if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0) - pSCB->SCB_SensePtr = (U32) VIRT_TO_BUS (SCpnt->sense_buffer); + pSCB->SCB_SensePtr = (U32) VIRT_TO_BUS(SCpnt->sense_buffer); #else pSCB->SCB_SensePtr = (U32) (SCpnt->sense_buffer); #endif -#else - pSCB->SCB_SensePtr = pSCB->SCB_SGPAddr; -#endif - - pSCB->SCB_SenseLen = SENSE_SIZE; + pSCB->SCB_SenseLen = SENSE_SIZE; - pSCB->SCB_CDBLen = SCpnt->cmd_len; - pSCB->SCB_HaStat = 0; - pSCB->SCB_TaStat = 0; - memcpy(&pSCB->SCB_CDB[0], &SCpnt->cmnd, SCpnt->cmd_len); + pSCB->SCB_CDBLen = SCpnt->cmd_len; + pSCB->SCB_HaStat = 0; + pSCB->SCB_TaStat = 0; + memcpy(&pSCB->SCB_CDB[0], &SCpnt->cmnd, SCpnt->cmd_len); - if (SCpnt->device->tagged_supported) - { /* Tag Support */ - pSCB->SCB_TagMsg = SIMPLE_QUEUE_TAG; /* Do simple tag only */ - } - else - { - pSCB->SCB_TagMsg = 0; /* No tag support */ + if (SCpnt->device->tagged_supported) { /* Tag Support */ + pSCB->SCB_TagMsg = SIMPLE_QUEUE_TAG; /* Do simple tag only */ + } else { + pSCB->SCB_TagMsg = 0; /* No tag support */ } - if (SCpnt->use_sg) - { - pSrbSG = (struct scatterlist *) SCpnt->request_buffer; - if (SCpnt->use_sg == 1) /* If only one entry in the list*/ - { /* treat it as regular I/O */ + if (SCpnt->use_sg) { + pSrbSG = (struct scatterlist *) SCpnt->request_buffer; + if (SCpnt->use_sg == 1) { /* If only one entry in the list *//* treat it as regular I/O */ #if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0) - pSCB->SCB_BufPtr = (U32) VIRT_TO_BUS (pSrbSG->address); + pSCB->SCB_BufPtr = (U32) VIRT_TO_BUS(pSrbSG->address); #else - pSCB->SCB_BufPtr = (U32) (pSrbSG->address); + pSCB->SCB_BufPtr = (U32) (pSrbSG->address); #endif - TotalLen = pSrbSG->length; - pSCB->SCB_SGLen = 0; - } - else - { /* Assign SG physical address */ - pSCB->SCB_BufPtr = pSCB->SCB_SGPAddr; - pSCB->SCB_Flags |= SCF_SG;/* Turn on SG list flag */ - for (i = 0, TotalLen = 0, pSG = &pSCB->SCB_SGList[0];/* 1.01g*/ - i < SCpnt->use_sg; - i++, pSG++, pSrbSG++) - { + TotalLen = pSrbSG->length; + pSCB->SCB_SGLen = 0; + } else { /* Assign SG physical address */ + pSCB->SCB_BufPtr = pSCB->SCB_SGPAddr; + pSCB->SCB_Flags |= SCF_SG; /* Turn on SG list flag */ + for (i = 0, TotalLen = 0, pSG = &pSCB->SCB_SGList[0]; /* 1.01g */ + i < SCpnt->use_sg; + i++, pSG++, pSrbSG++) { #if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0) - pSG->SG_Ptr = (U32) VIRT_TO_BUS (pSrbSG->address); + pSG->SG_Ptr = (U32) VIRT_TO_BUS(pSrbSG->address); #else - pSG->SG_Ptr = (U32) (pSrbSG->address); + pSG->SG_Ptr = (U32) (pSrbSG->address); #endif - TotalLen += pSG->SG_Len = pSrbSG->length; + TotalLen += pSG->SG_Len = pSrbSG->length; + } + pSCB->SCB_SGLen = i; } - pSCB->SCB_SGLen = i; - } - pSCB->SCB_BufLen = (SCpnt->request_bufflen > TotalLen) ? - TotalLen : SCpnt->request_bufflen; - } - else /* Non SG */ - { + pSCB->SCB_BufLen = (SCpnt->request_bufflen > TotalLen) ? + TotalLen : SCpnt->request_bufflen; + } else { /* Non SG */ #if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0) - pSCB->SCB_BufPtr = (U32) VIRT_TO_BUS(SCpnt->request_buffer); + pSCB->SCB_BufPtr = (U32) VIRT_TO_BUS(SCpnt->request_buffer); #else - pSCB->SCB_BufPtr = (U32) (SCpnt->request_buffer); + pSCB->SCB_BufPtr = (U32) (SCpnt->request_buffer); #endif - pSCB->SCB_BufLen = SCpnt->request_bufflen; - pSCB->SCB_SGLen = 0; + pSCB->SCB_BufLen = SCpnt->request_bufflen; + pSCB->SCB_SGLen = 0; } - return; + return; } /* * Queue a command and setup interrupts for a free bus. */ -int i91u_queue( Scsi_Cmnd * SCpnt, void (*done)(Scsi_Cmnd *)) +int i91u_queue(Scsi_Cmnd * SCpnt, void (*done) (Scsi_Cmnd *)) { - register SCB *pSCB; - HCS *pHCB; /* Point to Host adapter control block*/ - - if (SCpnt->lun > 16) { /* 07/22/98 */ + register SCB *pSCB; + HCS *pHCB; /* Point to Host adapter control block */ - SCpnt->result = (DID_TIME_OUT << 16); - done(SCpnt); /* Notify system DONE */ - return (0); - } + if (SCpnt->lun > 16) { /* 07/22/98 */ - pHCB = (HCS *) SCpnt->host->base; + SCpnt->result = (DID_TIME_OUT << 16); + done(SCpnt); /* Notify system DONE */ + return (0); + } + pHCB = (HCS *) SCpnt->host->base; - SCpnt->scsi_done = done; - /* Get free SCSI control block */ - if ((pSCB = tul_alloc_scb(pHCB)) == NULL) - { - i91uAppendSRBToQueue(pHCB, SCpnt); /* Buffer this request */ -/* printk("i91u_entry: can't allocate SCB\n");*/ - return (0); + SCpnt->scsi_done = done; + /* Get free SCSI control block */ + if ((pSCB = tul_alloc_scb(pHCB)) == NULL) { + i91uAppendSRBToQueue(pHCB, SCpnt); /* Buffer this request */ + return (0); } - i91uBuildSCB(pHCB, pSCB, SCpnt); - tul_exec_scb(pHCB, pSCB); /* Start execute SCB */ - return (0); + i91uBuildSCB(pHCB, pSCB, SCpnt); + tul_exec_scb(pHCB, pSCB); /* Start execute SCB */ + return (0); } /* * We only support command in interrupt-driven fashion */ -int i91u_command( Scsi_Cmnd *SCpnt ) +int i91u_command(Scsi_Cmnd * SCpnt) { - printk( "i91u: interrupt driven driver; use i91u_queue()\n" ); - return -1; + printk("i91u: interrupt driven driver; use i91u_queue()\n"); + return -1; } /* * Abort a queued command * (commands that are on the bus can't be aborted easily) */ -int i91u_abort( Scsi_Cmnd *SCpnt) +int i91u_abort(Scsi_Cmnd * SCpnt) { - HCS *pHCB; + HCS *pHCB; - pHCB = (HCS *) SCpnt->host->base; - return tul_abort_srb(pHCB, SCpnt); + pHCB = (HCS *) SCpnt->host->base; + return tul_abort_srb(pHCB, SCpnt); } /* @@ -880,65 +834,57 @@ * kill active and disconnected commands for target w/o soft reset */ int i91u_reset(Scsi_Cmnd * SCpnt, unsigned int reset_flags) -{ /* I need Host Control Block Information */ - HCS *pHCB; - - pHCB = (HCS *) SCpnt->host->base; +{ /* I need Host Control Block Information */ + HCS *pHCB; - if (reset_flags & (SCSI_RESET_SUGGEST_BUS_RESET|SCSI_RESET_SUGGEST_HOST_RESET)) + pHCB = (HCS *) SCpnt->host->base; - return tul_reset_scsi_bus(pHCB); - else - return tul_device_reset(pHCB, (ULONG)SCpnt, SCpnt->target, reset_flags); + if (reset_flags & (SCSI_RESET_SUGGEST_BUS_RESET | SCSI_RESET_SUGGEST_HOST_RESET)) + return tul_reset_scsi_bus(pHCB); + else + return tul_device_reset(pHCB, (ULONG) SCpnt, SCpnt->target, reset_flags); } /* * Return the "logical geometry" */ #if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0) -int i91u_biosparam(Scsi_Disk *disk, kdev_t dev, int *info_array ) +int i91u_biosparam(Scsi_Disk * disk, kdev_t dev, int *info_array) #else -int i91u_biosparam(Scsi_Disk *disk, int dev, int *info_array ) +int i91u_biosparam(Scsi_Disk * disk, int dev, int *info_array) #endif { - HCS *pHcb; /* Point to Host adapter control block*/ - TCS *pTcb; + HCS *pHcb; /* Point to Host adapter control block */ + TCS *pTcb; - pHcb = (HCS *) disk->device->host->base; - pTcb = &pHcb->HCS_Tcs[disk->device->id]; + pHcb = (HCS *) disk->device->host->base; + pTcb = &pHcb->HCS_Tcs[disk->device->id]; - if (pTcb->TCS_DrvHead) - { - info_array[0] = pTcb->TCS_DrvHead; - info_array[1] = pTcb->TCS_DrvSector; - info_array[2] = disk->capacity / pTcb->TCS_DrvHead / pTcb->TCS_DrvSector; - } - else - { - if (pTcb->TCS_DrvFlags & TCF_DRV_255_63) - { - info_array[0] = 255; - info_array[1] = 63; - info_array[2] = disk->capacity / 255 / 63; - } - else - { - info_array[0] = 64; - info_array[1] = 32; - info_array[2] = disk->capacity >> 11; - } + if (pTcb->TCS_DrvHead) { + info_array[0] = pTcb->TCS_DrvHead; + info_array[1] = pTcb->TCS_DrvSector; + info_array[2] = disk->capacity / pTcb->TCS_DrvHead / pTcb->TCS_DrvSector; + } else { + if (pTcb->TCS_DrvFlags & TCF_DRV_255_63) { + info_array[0] = 255; + info_array[1] = 63; + info_array[2] = disk->capacity / 255 / 63; + } else { + info_array[0] = 64; + info_array[1] = 32; + info_array[2] = disk->capacity >> 11; + } } #if defined(DEBUG_BIOSPARAM) - if (i91u_debug & debug_biosparam) - { - printk("bios geometry: head=%d, sec=%d, cyl=%d\n", - info_array[0], info_array[1], info_array[2]); - printk("WARNING: check, if the bios geometry is correct.\n"); + if (i91u_debug & debug_biosparam) { + printk("bios geometry: head=%d, sec=%d, cyl=%d\n", + info_array[0], info_array[1], info_array[2]); + printk("WARNING: check, if the bios geometry is correct.\n"); } #endif - return 0; + return 0; } /***************************************************************************** @@ -950,276 +896,266 @@ Output : None. Return : None. *****************************************************************************/ -static void i91uSCBPost(BYTE *pHcb, BYTE *pScb) +static void i91uSCBPost(BYTE * pHcb, BYTE * pScb) { - Scsi_Cmnd *pSRB; /* Pointer to SCSI request block */ - HCS *pHCB; - SCB *pSCB; - - pHCB = (HCS *)pHcb; - pSCB = (SCB *)pScb; - if ((pSRB = pSCB->SCB_Srb) == 0) - { - printk("i91uSCBPost: SRB pointer is empty\n"); + Scsi_Cmnd *pSRB; /* Pointer to SCSI request block */ + HCS *pHCB; + SCB *pSCB; + + pHCB = (HCS *) pHcb; + pSCB = (SCB *) pScb; + if ((pSRB = pSCB->SCB_Srb) == 0) { + printk("i91uSCBPost: SRB pointer is empty\n"); - tul_release_scb(pHCB, pSCB); /* Release SCB for current channel */ - return; + tul_release_scb(pHCB, pSCB); /* Release SCB for current channel */ + return; } - switch (pSCB->SCB_HaStat) { + switch (pSCB->SCB_HaStat) { case 0x0: - case 0xa: /* Linked command complete without error and linked normally*/ - case 0xb: /* Linked command complete without error interrupt generated*/ - pSCB->SCB_HaStat = 0; - break; - - case 0x11: /* Selection time out-The initiator selection or target - reselection was not complete within the SCSI Time out period */ - pSCB->SCB_HaStat = DID_TIME_OUT; - break; - - case 0x14: /* Target bus phase sequence failure-An invalid bus phase or bus - phase sequence was requested by the target. The host adapter - will generate a SCSI Reset Condition, notifying the host with - a SCRD interrupt */ - pSCB->SCB_HaStat = DID_RESET; - break; - - case 0x1a: /* SCB Aborted. 07/21/98 */ - pSCB->SCB_HaStat = DID_ABORT; - break; - - case 0x12: /* Data overrun/underrun-The target attempted to transfer more data - than was allocated by the Data Length field or the sum of the - Scatter / Gather Data Length fields. */ - case 0x13: /* Unexpected bus free-The target dropped the SCSI BSY at an unexpected time. */ - case 0x16: /* Invalid SCB Operation Code. */ + case 0xa: /* Linked command complete without error and linked normally */ + case 0xb: /* Linked command complete without error interrupt generated */ + pSCB->SCB_HaStat = 0; + break; + + case 0x11: /* Selection time out-The initiator selection or target + reselection was not complete within the SCSI Time out period */ + pSCB->SCB_HaStat = DID_TIME_OUT; + break; + + case 0x14: /* Target bus phase sequence failure-An invalid bus phase or bus + phase sequence was requested by the target. The host adapter + will generate a SCSI Reset Condition, notifying the host with + a SCRD interrupt */ + pSCB->SCB_HaStat = DID_RESET; + break; + + case 0x1a: /* SCB Aborted. 07/21/98 */ + pSCB->SCB_HaStat = DID_ABORT; + break; + + case 0x12: /* Data overrun/underrun-The target attempted to transfer more data + than was allocated by the Data Length field or the sum of the + Scatter / Gather Data Length fields. */ + case 0x13: /* Unexpected bus free-The target dropped the SCSI BSY at an unexpected time. */ + case 0x16: /* Invalid SCB Operation Code. */ default: - printk("ini9100u: %x %x\n", pSCB->SCB_HaStat, pSCB->SCB_TaStat); - pSCB->SCB_HaStat = DID_ERROR; /* Couldn't find any better */ - break; - } - -#if 0 - if ((pSCB->SCB_TaStat == 2) && /* Check condition */ - (pSCB->SCB_Flags & SCF_SENSE)) /* Turn on auto request sense */ - { - memcpy((unsigned char *) &pSRB->sense_buffer[0], (unsigned char *) &pSCB->SCB_SGList[0], SENSE_SIZE); + printk("ini9100u: %x %x\n", pSCB->SCB_HaStat, pSCB->SCB_TaStat); + pSCB->SCB_HaStat = DID_ERROR; /* Couldn't find any better */ + break; } -#endif - pSRB->result = pSCB->SCB_TaStat | (pSCB->SCB_HaStat << 16); - if (pSRB == NULL) - { - printk("pSRB is NULL\n"); - } - pSRB->scsi_done(pSRB); /* Notify system DONE */ - if ((pSRB = i91uPopSRBFromQueue(pHCB)) != NULL) - /* Find the next pending SRB */ - { /* Assume resend will success */ - /* Reuse old SCB */ - i91uBuildSCB(pHCB, pSCB, pSRB); /* Create corresponding SCB */ + pSRB->result = pSCB->SCB_TaStat | (pSCB->SCB_HaStat << 16); - tul_exec_scb(pHCB, pSCB); /* Start execute SCB */ + if (pSRB == NULL) { + printk("pSRB is NULL\n"); } - else - { /* No Pending SRB */ - tul_release_scb(pHCB, pSCB); /* Release SCB for current channel */ + pSRB->scsi_done(pSRB); /* Notify system DONE */ + if ((pSRB = i91uPopSRBFromQueue(pHCB)) != NULL) + /* Find the next pending SRB */ + { /* Assume resend will success */ + /* Reuse old SCB */ + i91uBuildSCB(pHCB, pSCB, pSRB); /* Create corresponding SCB */ + + tul_exec_scb(pHCB, pSCB); /* Start execute SCB */ + } else { /* No Pending SRB */ + tul_release_scb(pHCB, pSCB); /* Release SCB for current channel */ } - return; + return; } /* * Interrupts handler (main routine of the driver) */ #if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0) -static void i91u_intr0( int irqno, void *dev_id, struct pt_regs * regs ) +static void i91u_intr0(int irqno, void *dev_id, struct pt_regs *regs) #else -static void i91u_intr0( int irqno, struct pt_regs * regs ) +static void i91u_intr0(int irqno, struct pt_regs *regs) #endif { #if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95) - unsigned long flags; + unsigned long flags; #endif - if (tul_hcs[0].HCS_Intr != irqno) - return; + if (tul_hcs[0].HCS_Intr != irqno) + return; #if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95) - spin_lock_irqsave(&io_request_lock, flags); + spin_lock_irqsave(&io_request_lock, flags); #endif - tul_isr(&tul_hcs[0]); + tul_isr(&tul_hcs[0]); #if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95) - spin_unlock_irqrestore(&io_request_lock, flags); + spin_unlock_irqrestore(&io_request_lock, flags); #endif } #if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0) -static void i91u_intr1( int irqno, void *dev_id, struct pt_regs * regs ) +static void i91u_intr1(int irqno, void *dev_id, struct pt_regs *regs) #else -static void i91u_intr1( int irqno, struct pt_regs * regs ) +static void i91u_intr1(int irqno, struct pt_regs *regs) #endif { #if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95) - unsigned long flags; + unsigned long flags; #endif - if (tul_hcs[1].HCS_Intr != irqno) - return; + if (tul_hcs[1].HCS_Intr != irqno) + return; #if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95) - spin_lock_irqsave(&io_request_lock, flags); + spin_lock_irqsave(&io_request_lock, flags); #endif - tul_isr(&tul_hcs[1]); + tul_isr(&tul_hcs[1]); #if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95) - spin_unlock_irqrestore(&io_request_lock, flags); + spin_unlock_irqrestore(&io_request_lock, flags); #endif } #if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0) -static void i91u_intr2( int irqno, void *dev_id, struct pt_regs * regs ) +static void i91u_intr2(int irqno, void *dev_id, struct pt_regs *regs) #else -static void i91u_intr2( int irqno, struct pt_regs * regs ) +static void i91u_intr2(int irqno, struct pt_regs *regs) #endif { #if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95) - unsigned long flags; + unsigned long flags; #endif - if (tul_hcs[2].HCS_Intr != irqno) - return; + if (tul_hcs[2].HCS_Intr != irqno) + return; #if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95) - spin_lock_irqsave(&io_request_lock, flags); + spin_lock_irqsave(&io_request_lock, flags); #endif - tul_isr(&tul_hcs[2]); + tul_isr(&tul_hcs[2]); #if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95) - spin_unlock_irqrestore(&io_request_lock, flags); + spin_unlock_irqrestore(&io_request_lock, flags); #endif } #if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0) -static void i91u_intr3( int irqno, void *dev_id, struct pt_regs * regs ) +static void i91u_intr3(int irqno, void *dev_id, struct pt_regs *regs) #else -static void i91u_intr3( int irqno, struct pt_regs * regs ) +static void i91u_intr3(int irqno, struct pt_regs *regs) #endif { #if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95) - unsigned long flags; + unsigned long flags; #endif - if (tul_hcs[3].HCS_Intr != irqno) - return; + if (tul_hcs[3].HCS_Intr != irqno) + return; #if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95) - spin_lock_irqsave(&io_request_lock, flags); + spin_lock_irqsave(&io_request_lock, flags); #endif - tul_isr(&tul_hcs[3]); + tul_isr(&tul_hcs[3]); #if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95) - spin_unlock_irqrestore(&io_request_lock, flags); + spin_unlock_irqrestore(&io_request_lock, flags); #endif } #if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0) -static void i91u_intr4( int irqno, void *dev_id, struct pt_regs * regs ) +static void i91u_intr4(int irqno, void *dev_id, struct pt_regs *regs) #else -static void i91u_intr4( int irqno, struct pt_regs * regs ) +static void i91u_intr4(int irqno, struct pt_regs *regs) #endif { #if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95) - unsigned long flags; + unsigned long flags; #endif - if (tul_hcs[4].HCS_Intr != irqno) - return; + if (tul_hcs[4].HCS_Intr != irqno) + return; #if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95) - spin_lock_irqsave(&io_request_lock, flags); + spin_lock_irqsave(&io_request_lock, flags); #endif - tul_isr(&tul_hcs[4]); + tul_isr(&tul_hcs[4]); #if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95) - spin_unlock_irqrestore(&io_request_lock, flags); + spin_unlock_irqrestore(&io_request_lock, flags); #endif } #if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0) -static void i91u_intr5( int irqno, void *dev_id, struct pt_regs * regs ) +static void i91u_intr5(int irqno, void *dev_id, struct pt_regs *regs) #else -static void i91u_intr5( int irqno, struct pt_regs * regs ) +static void i91u_intr5(int irqno, struct pt_regs *regs) #endif { #if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95) - unsigned long flags; + unsigned long flags; #endif - if (tul_hcs[5].HCS_Intr != irqno) - return; + if (tul_hcs[5].HCS_Intr != irqno) + return; #if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95) - spin_lock_irqsave(&io_request_lock, flags); + spin_lock_irqsave(&io_request_lock, flags); #endif - tul_isr(&tul_hcs[5]); + tul_isr(&tul_hcs[5]); #if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95) - spin_unlock_irqrestore(&io_request_lock, flags); + spin_unlock_irqrestore(&io_request_lock, flags); #endif } #if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0) -static void i91u_intr6( int irqno, void *dev_id, struct pt_regs * regs ) +static void i91u_intr6(int irqno, void *dev_id, struct pt_regs *regs) #else -static void i91u_intr6( int irqno, struct pt_regs * regs ) +static void i91u_intr6(int irqno, struct pt_regs *regs) #endif { #if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95) - unsigned long flags; + unsigned long flags; #endif - if (tul_hcs[6].HCS_Intr != irqno) - return; + if (tul_hcs[6].HCS_Intr != irqno) + return; #if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95) - spin_lock_irqsave(&io_request_lock, flags); + spin_lock_irqsave(&io_request_lock, flags); #endif - tul_isr(&tul_hcs[6]); + tul_isr(&tul_hcs[6]); #if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95) - spin_unlock_irqrestore(&io_request_lock, flags); + spin_unlock_irqrestore(&io_request_lock, flags); #endif } + #if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0) -static void i91u_intr7( int irqno, void *dev_id, struct pt_regs * regs ) +static void i91u_intr7(int irqno, void *dev_id, struct pt_regs *regs) #else -static void i91u_intr7( int irqno, struct pt_regs * regs ) +static void i91u_intr7(int irqno, struct pt_regs *regs) #endif { #if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95) - unsigned long flags; + unsigned long flags; #endif - if (tul_hcs[7].HCS_Intr != irqno) - return; + if (tul_hcs[7].HCS_Intr != irqno) + return; #if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95) - spin_lock_irqsave(&io_request_lock, flags); + spin_lock_irqsave(&io_request_lock, flags); #endif - tul_isr(&tul_hcs[7]); + tul_isr(&tul_hcs[7]); #if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95) - spin_unlock_irqrestore(&io_request_lock, flags); + spin_unlock_irqrestore(&io_request_lock, flags); #endif } @@ -1228,7 +1164,6 @@ */ static void i91u_panic(char *msg) { - printk("\ni91u_panic: %s\n", msg); - panic("i91u panic"); + printk("\ni91u_panic: %s\n", msg); + panic("i91u panic"); } -/*#include "i91uscsi.c"*/ diff -urN linux-2.0.37-pre2/drivers/scsi/ini9100u.h linux-2.0.37-pre3/drivers/scsi/ini9100u.h --- linux-2.0.37-pre2/drivers/scsi/ini9100u.h 2003-08-15 15:04:26.000000000 -0700 +++ linux-2.0.37-pre3/drivers/scsi/ini9100u.h 2003-08-15 15:04:26.000000000 -0700 @@ -1,4 +1,3 @@ - /************************************************************************** * Initio 9100 device driver for Linux. * @@ -60,6 +59,10 @@ * 06/18/96 Harry Chen, Initial Version 1.00A (Beta) * 06/23/98 hc - v1.01k * - Get it work for kernel version >= 2.1.75 + * 12/09/98 bv - v1.03a + * - Removed unused code + * 12/13/98 bv - v1.03b + * - Add spinlocks to HCS structure. *******************************************************************************/ #ifndef CVT_LINUX_VERSION @@ -72,20 +75,20 @@ #include "sd.h" -extern int i91u_detect(Scsi_Host_Template *); -extern int i91u_command(Scsi_Cmnd *); -extern int i91u_queue(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); -extern int i91u_abort(Scsi_Cmnd *); -extern int i91u_reset(Scsi_Cmnd *, unsigned int); +extern int i91u_detect(Scsi_Host_Template *); +extern int i91u_command(Scsi_Cmnd *); +extern int i91u_queue(Scsi_Cmnd *, void (*done) (Scsi_Cmnd *)); +extern int i91u_abort(Scsi_Cmnd *); +extern int i91u_reset(Scsi_Cmnd *, unsigned int); #if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1, 3, 0) -extern int i91u_biosparam(Scsi_Disk *, kdev_t, int *); /*for linux v2.0*/ +extern int i91u_biosparam(Scsi_Disk *, kdev_t, int *); /*for linux v2.0 */ extern struct proc_dir_entry proc_scsi_ini9100u; #else -extern int i91u_biosparam(Disk *, int, int *); /*for linux v1.13 */ +extern int i91u_biosparam(Disk *, int, int *); /*for linux v1.13 */ #endif -#define i91u_REVID "Initio INI-9X00U/UW SCSI device driver; Revision: 1.03" +#define i91u_REVID "Initio INI-9X00U/UW SCSI device driver; Revision: 1.03b" #if LINUX_VERSION_CODE < CVT_LINUX_VERSION(1, 3, 0) #define INI9100U { \ @@ -135,7 +138,7 @@ 0, \ ENABLE_CLUSTERING \ } -#else /* Version >= 2.1.75 */ +#else /* Version >= 2.1.75 */ #define INI9100U { \ next: NULL, \ module: NULL, \ @@ -186,63 +189,63 @@ #endif #ifndef NULL -#define NULL 0 /* zero */ +#define NULL 0 /* zero */ #endif #ifndef TRUE -#define TRUE (1) /* boolean true */ +#define TRUE (1) /* boolean true */ #endif #ifndef FALSE -#define FALSE (0) /* boolean false */ +#define FALSE (0) /* boolean false */ #endif #ifndef FAILURE #define FAILURE (-1) #endif -#define i91u_MAXQUEUE 2 +#define i91u_MAXQUEUE 2 #define TOTAL_SG_ENTRY 32 #define MAX_TARGETS 16 #define SENSE_SIZE 14 -#define INI_VENDOR_ID 0x1101 /* Initio's PCI vendor ID */ -#define I950_DEVICE_ID 0x9500 /* Initio's inic-950 product ID */ -#define I940_DEVICE_ID 0x9400 /* Initio's inic-940 product ID */ -#define I935_DEVICE_ID 0x9401 /* Initio's inic-935 product ID */ -#define I920_DEVICE_ID 0x0002 /* Initio's other product ID */ +#define INI_VENDOR_ID 0x1101 /* Initio's PCI vendor ID */ +#define I950_DEVICE_ID 0x9500 /* Initio's inic-950 product ID */ +#define I940_DEVICE_ID 0x9400 /* Initio's inic-940 product ID */ +#define I935_DEVICE_ID 0x9401 /* Initio's inic-935 product ID */ +#define I920_DEVICE_ID 0x0002 /* Initio's other product ID */ /************************************************************************/ /* Scatter-Gather Element Structure */ /************************************************************************/ -typedef struct SG_Struc { - U32 SG_Ptr; /* Data Pointer */ - U32 SG_Len; /* Data Length */ +typedef struct SG_Struc { + U32 SG_Ptr; /* Data Pointer */ + U32 SG_Len; /* Data Length */ } SG; /*********************************************************************** SCSI Control Block ************************************************************************/ -typedef struct Scsi_Ctrl_Blk { - U32 SCB_InitioReserved[9]; /* 0 */ +typedef struct Scsi_Ctrl_Blk { + U32 SCB_InitioReserved[9]; /* 0 */ - UBYTE SCB_Opcode; /*24 SCB command code */ - UBYTE SCB_Flags; /*25 SCB Flags */ - UBYTE SCB_Target; /*26 Target Id */ - UBYTE SCB_Lun; /*27 Lun */ - U32 SCB_BufPtr; /*28 Data Buffer Pointer */ - U32 SCB_BufLen; /*2C Data Allocation Length */ - UBYTE SCB_SGLen; /*30 SG list # */ - UBYTE SCB_SenseLen; /*31 Sense Allocation Length */ - UBYTE SCB_HaStat; /*32 */ - UBYTE SCB_TaStat; /*33 */ - UBYTE SCB_CDBLen; /*34 CDB Length */ - UBYTE SCB_Ident; /*35 Identify */ - UBYTE SCB_TagMsg; /*36 Tag Message */ - UBYTE SCB_TagId; /*37 Queue Tag */ - UBYTE SCB_CDB[12]; /*38 */ - U32 SCB_SGPAddr; /*44 SG List/Sense Buf phy. Addr. */ - U32 SCB_SensePtr; /*48 Sense data pointer */ - void (* SCB_Post)(BYTE *, BYTE *); /*4C POST routine */ - Scsi_Cmnd *SCB_Srb; /*50 SRB Pointer */ - SG SCB_SGList[TOTAL_SG_ENTRY]; /*54 Start of SG list */ + UBYTE SCB_Opcode; /*24 SCB command code */ + UBYTE SCB_Flags; /*25 SCB Flags */ + UBYTE SCB_Target; /*26 Target Id */ + UBYTE SCB_Lun; /*27 Lun */ + U32 SCB_BufPtr; /*28 Data Buffer Pointer */ + U32 SCB_BufLen; /*2C Data Allocation Length */ + UBYTE SCB_SGLen; /*30 SG list # */ + UBYTE SCB_SenseLen; /*31 Sense Allocation Length */ + UBYTE SCB_HaStat; /*32 */ + UBYTE SCB_TaStat; /*33 */ + UBYTE SCB_CDBLen; /*34 CDB Length */ + UBYTE SCB_Ident; /*35 Identify */ + UBYTE SCB_TagMsg; /*36 Tag Message */ + UBYTE SCB_TagId; /*37 Queue Tag */ + UBYTE SCB_CDB[12]; /*38 */ + U32 SCB_SGPAddr; /*44 SG List/Sense Buf phy. Addr. */ + U32 SCB_SensePtr; /*48 Sense data pointer */ + void (*SCB_Post) (BYTE *, BYTE *); /*4C POST routine */ + Scsi_Cmnd *SCB_Srb; /*50 SRB Pointer */ + SG SCB_SGList[TOTAL_SG_ENTRY]; /*54 Start of SG list */ } SCB; /* Opcodes of SCB_Opcode */ @@ -285,11 +288,11 @@ **********************************************************************/ typedef struct Tar_Ctrl_Struc { - ULONG TCS_InitioReserved; /* 0 */ + ULONG TCS_InitioReserved; /* 0 */ - UWORD TCS_DrvFlags; /* 4 */ - UBYTE TCS_DrvHead; /* 6 */ - UBYTE TCS_DrvSector; /* 7 */ + UWORD TCS_DrvFlags; /* 4 */ + UBYTE TCS_DrvHead; /* 6 */ + UBYTE TCS_DrvSector; /* 7 */ } TCS; /*********************************************************************** @@ -302,26 +305,30 @@ Host Adapter Control Structure ************************************************************************/ typedef struct Ha_Ctrl_Struc { - UWORD HCS_Base; /* 00 */ - UWORD HCS_BIOS; /* 02 */ - UBYTE HCS_Intr; /* 04 */ - UBYTE HCS_SCSI_ID; /* 05 */ - UBYTE HCS_MaxTar; /* 06 */ - UBYTE HCS_NumScbs; /* 07 */ - - UBYTE HCS_Flags; /* 08 */ - UBYTE HCS_Index; /* 09 */ - UBYTE HCS_Reserved[2]; /* 0a */ - ULONG HCS_InitioReserved[27]; /* 0C */ - - TCS HCS_Tcs[16]; /* 78 -> 16 Targets */ - Scsi_Cmnd *pSRB_head; /* SRB save queue header */ - Scsi_Cmnd *pSRB_tail; /* SRB save queue tail */ + UWORD HCS_Base; /* 00 */ + UWORD HCS_BIOS; /* 02 */ + UBYTE HCS_Intr; /* 04 */ + UBYTE HCS_SCSI_ID; /* 05 */ + UBYTE HCS_MaxTar; /* 06 */ + UBYTE HCS_NumScbs; /* 07 */ + + UBYTE HCS_Flags; /* 08 */ + UBYTE HCS_Index; /* 09 */ + UBYTE HCS_Reserved[2]; /* 0a */ + ULONG HCS_InitioReserved[27]; /* 0C */ + TCS HCS_Tcs[16]; /* 78 -> 16 Targets */ + Scsi_Cmnd *pSRB_head; /* SRB save queue header */ + Scsi_Cmnd *pSRB_tail; /* SRB save queue tail */ +#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95) + spinlock_t HCS_AvailLock; + spinlock_t HCS_SemaphLock; + spinlock_t pSRB_lock; +#endif } HCS; /* Bit Definition for HCB_Flags */ #define HCF_EXPECT_RESET 0x10 /* SCSI related definition */ -#define DISC_NOT_ALLOW 0x80 /* Disconnect is not allowed */ -#define DISC_ALLOW 0xC0 /* Disconnect is allowed */ +#define DISC_NOT_ALLOW 0x80 /* Disconnect is not allowed */ +#define DISC_ALLOW 0xC0 /* Disconnect is allowed */ diff -urN linux-2.0.37-pre2/drivers/scsi/ncr53c8xx.c linux-2.0.37-pre3/drivers/scsi/ncr53c8xx.c --- linux-2.0.37-pre2/drivers/scsi/ncr53c8xx.c 1998-11-15 10:33:09.000000000 -0800 +++ linux-2.0.37-pre3/drivers/scsi/ncr53c8xx.c 2003-08-15 15:04:26.000000000 -0700 @@ -63,11 +63,17 @@ ** August 18 1997 by Cort : ** Support for Power/PC (Big Endian). ** +** June 20 1998 by Gerard Roudier : +** Support for up to 64 tags per lun. +** O(1) everywhere (C and SCRIPTS) for normal cases. +** Low PCI traffic for command handling when on-chip RAM is present. +** Aggressive SCSI SCRIPTS optimizations. +** ******************************************************************************* */ /* -** 30 January 1998, version 2.5f.1 +** December 14 1998, version 3.1e ** ** Supported SCSI-II features: ** Synchronous negotiation @@ -92,9 +98,7 @@ ** Shared IRQ (since linux-1.3.72) */ -#define SCSI_NCR_DEBUG_FLAGS (0) - -#define NCR_GETCC_WITHMSG +#define SCSI_NCR_DEBUG_FLAGS (0) /*========================================================== ** @@ -112,11 +116,13 @@ #include #include #include +#if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,93) +#include +#endif #include #include #include #include -#include #include #include #include @@ -127,11 +133,7 @@ #include #include -#if LINUX_VERSION_CODE >= LinuxVersionCode(1,3,0) #include -#else -#include "../block/blk.h" -#endif #if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,35) #include @@ -144,6 +146,10 @@ #endif #endif +#if LINUX_VERSION_CODE <= LinuxVersionCode(2,1,92) +#include +#endif + #include "scsi.h" #include "hosts.h" #include "constants.h" @@ -152,14 +158,180 @@ #include /* -** Define the BSD style u_int32 type +** Define BITS_PER_LONG for earlier linux versions. +*/ +#ifndef BITS_PER_LONG +#if (~0UL) == 0xffffffffUL +#define BITS_PER_LONG 32 +#else +#define BITS_PER_LONG 64 +#endif +#endif + +/* +** Define the BSD style u_int32 and u_int64 type. +** Are in fact u_int32_t and u_int64_t :-) */ typedef u32 u_int32; +typedef u64 u_int64; #include "ncr53c8xx.h" /*========================================================== ** +** A la VMS/CAM-3 queue management. +** Implemented from linux list management. +** +**========================================================== +*/ + +typedef struct xpt_quehead { + struct xpt_quehead *flink; /* Forward pointer */ + struct xpt_quehead *blink; /* Backward pointer */ +} XPT_QUEHEAD; + +#define xpt_que_init(ptr) do { \ + (ptr)->flink = (ptr); (ptr)->blink = (ptr); \ +} while (0) + +static inline void __xpt_que_add(struct xpt_quehead * new, + struct xpt_quehead * blink, + struct xpt_quehead * flink) +{ + flink->blink = new; + new->flink = flink; + new->blink = blink; + blink->flink = new; +} + +static inline void __xpt_que_del(struct xpt_quehead * blink, + struct xpt_quehead * flink) +{ + flink->blink = blink; + blink->flink = flink; +} + +static inline int xpt_que_empty(struct xpt_quehead *head) +{ + return head->flink == head; +} + +static inline void xpt_que_splice(struct xpt_quehead *list, + struct xpt_quehead *head) +{ + struct xpt_quehead *first = list->flink; + + if (first != list) { + struct xpt_quehead *last = list->blink; + struct xpt_quehead *at = head->flink; + + first->blink = head; + head->flink = first; + + last->flink = at; + at->blink = last; + } +} + +#define xpt_que_entry(ptr, type, member) \ + ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member))) + + +#define xpt_insque(new, pos) __xpt_que_add(new, pos, (pos)->flink) + +#define xpt_remque(el) __xpt_que_del((el)->blink, (el)->flink) + +#define xpt_insque_head(new, head) __xpt_que_add(new, head, (head)->flink) + +static inline struct xpt_quehead *xpt_remque_head(struct xpt_quehead *head) +{ + struct xpt_quehead *elem = head->flink; + + if (elem != head) + __xpt_que_del(head, elem->flink); + else + elem = 0; + return elem; +} + +#define xpt_insque_tail(new, head) __xpt_que_add(new, (head)->blink, head) + +static inline struct xpt_quehead *xpt_remque_tail(struct xpt_quehead *head) +{ + struct xpt_quehead *elem = head->blink; + + if (elem != head) + __xpt_que_del(elem->blink, head); + else + elem = 0; + return elem; +} + +/*========================================================== +** +** The CCB done queue uses an array of CCB virtual +** addresses. Empty entries are flagged using the bogus +** virtual address 0xffffffff. +** +** Since PCI ensures that only aligned DWORDs are accessed +** atomically, 64 bit little-endian architecture requires +** to test the high order DWORD of the entry to determine +** if it is empty or valid. +** +** BTW, I will make things differently as soon as I will +** have a better idea, but this is simple and should work. +** +**========================================================== +*/ + +#define SCSI_NCR_CCB_DONE_SUPPORT +#ifdef SCSI_NCR_CCB_DONE_SUPPORT + +#define MAX_DONE 24 +#define CCB_DONE_EMPTY 0xffffffffUL + +/* All 32 bit architectures */ +#if BITS_PER_LONG == 32 +#define CCB_DONE_VALID(cp) (((u_long) cp) != CCB_DONE_EMPTY) + +/* All > 32 bit (64 bit) architectures regardless endian-ness */ +#else +#define CCB_DONE_VALID(cp) \ + ((((u_long) cp) & 0xffffffff00000000ul) && \ + (((u_long) cp) & 0xfffffffful) != CCB_DONE_EMPTY) +#endif + +#endif /* SCSI_NCR_CCB_DONE_SUPPORT */ + +/*========================================================== +** +** On x86 architecture, write buffers management does +** not reorder writes to memory. So, using compiler +** optimization barriers is enough to guarantee some +** ordering when the CPU is writing data accessed by +** the NCR. +** On Alpha architecture, explicit memory barriers have +** to be used. +** Other architectures are defaulted to mb() macro if +** defined, otherwise use compiler barrier. +** +**========================================================== +*/ + +#if defined(__i386__) +#define MEMORY_BARRIER() barrier() +#elif defined(__alpha__) +#define MEMORY_BARRIER() mb() +#else +# ifdef mb +# define MEMORY_BARRIER() mb() +# else +# define MEMORY_BARRIER() barrier() +# endif +#endif + +/*========================================================== +** ** Configuration and Debugging ** **========================================================== @@ -181,13 +353,33 @@ */ #ifndef SCSI_NCR_MAX_TAGS -#define SCSI_NCR_MAX_TAGS (4) +#define SCSI_NCR_MAX_TAGS (8) +#endif + +/* +** TAGS are actually limited to 64 tags/lun. +** We need to deal with power of 2, for alignment constraints. +*/ +#if SCSI_NCR_MAX_TAGS > 64 +#undef SCSI_NCR_MAX_TAGS +#define SCSI_NCR_MAX_TAGS (64) +#endif + +#define NO_TAG (255) + +/* +** Choose appropriate type for tag bitmap. +*/ +#if SCSI_NCR_MAX_TAGS > 32 +typedef u_int64 tagmap_t; +#else +typedef u_int32 tagmap_t; #endif /* ** Number of targets supported by the driver. ** n permits target numbers 0..n-1. -** Default is 7, meaning targets #0..#6. +** Default is 16, meaning targets #0..#15. ** #7 .. is myself. */ @@ -233,10 +425,23 @@ /* ** The maximum number of segments a transfer is split into. +** We support up to 127 segments for both read and write. +** The data scripts are broken into 2 sub-scripts. +** 80 (MAX_SCATTERL) segments are moved from a sub-script +** in on-chip RAM. This makes data transfers shorter than +** 80k (assuming 1k fs) as fast as possible. */ #define MAX_SCATTER (SCSI_NCR_MAX_SCATTER) +#if (MAX_SCATTER > 80) +#define MAX_SCATTERL 80 +#define MAX_SCATTERH (MAX_SCATTER - MAX_SCATTERL) +#else +#define MAX_SCATTERL (MAX_SCATTER-1) +#define MAX_SCATTERH 1 +#endif + /* ** Io mapped or memory mapped. */ @@ -266,7 +471,6 @@ ** Obvious definitions */ -#define printf printk #define u_char unsigned char #define u_short unsigned short #define u_int unsigned int @@ -275,27 +479,83 @@ typedef u_long vm_offset_t; typedef int vm_size_t; +#ifndef bcopy #define bcopy(s, d, n) memcpy((d), (s), (n)) +#endif +#ifndef bzero #define bzero(d, n) memset((d), 0, (n)) - +#endif + #ifndef offsetof #define offsetof(t, m) ((size_t) (&((t *)0)->m)) #endif /* +** SMP threading. +** +** Assuming that SMP systems are generally high end systems and may +** use several SCSI adapters, we are using one lock per controller +** instead of some global one. For the moment (linux-2.1.95), driver's +** entry points are called with the 'io_request_lock' lock held, so: +** - We are uselessly loosing a couple of micro-seconds to lock the +** controller data structure. +** - But the driver is not broken by design for SMP and so can be +** more resistant to bugs or bad changes in the IO sub-system code. +** - A small advantage could be that the interrupt code is grained as +** wished (e.g.: threaded by controller). +*/ + +#if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,93) + +#if 0 /* not yet needed */ +static spinlock_t driver_lock; +#define NCR_LOCK_DRIVER(flags) spin_lock_irqsave(&driver_lock, flags) +#define NCR_UNLOCK_DRIVER(flags) spin_unlock_irqrestore(&driver_lock, flags) +#endif + +#define NCR_INIT_LOCK_NCB(np) spin_lock_init(&np->smp_lock); +#define NCR_LOCK_NCB(np, flags) spin_lock_irqsave(&np->smp_lock, flags) +#define NCR_UNLOCK_NCB(np, flags) spin_unlock_irqrestore(&np->smp_lock, flags) + +# if LINUX_VERSION_CODE < LinuxVersionCode(2,3,99) + +# define NCR_LOCK_SCSI_DONE(np, flags) \ + spin_lock_irqsave(&io_request_lock, flags) +# define NCR_UNLOCK_SCSI_DONE(np, flags) \ + spin_unlock_irqrestore(&io_request_lock, flags) + +# else + +# define NCR_LOCK_SCSI_DONE(np, flags) do {;} while (0) +# define NCR_UNLOCK_SCSI_DONE(np, flags) do {;} while (0) + +# endif + +#else + +#if 0 /* not yet needed */ +#define NCR_LOCK_DRIVER(flags) do {;} while (0) +#define NCR_UNLOCK_DRIVER(flags) do {;} while (0) +#endif + +#define NCR_INIT_LOCK_NCB(np) do { } while (0) +#define NCR_LOCK_NCB(np, flags) do { save_flags(flags); cli(); } while (0) +#define NCR_UNLOCK_NCB(np, flags) do { restore_flags(flags); } while (0) + +#define NCR_LOCK_SCSI_DONE(np, flags) do {;} while (0) +#define NCR_UNLOCK_SCSI_DONE(np, flags) do {;} while (0) + +#endif + +/* ** Address translation ** -** On Linux 1.3.X, virt_to_bus() must be used to translate -** virtual memory addresses of the kernel data segment into -** IO bus adresses. -** On i386 architecture, IO bus addresses match the physical -** addresses. But on other architectures they can be different. -** In the original Bsd driver, vtophys() is called to translate -** data addresses to IO bus addresses. In order to minimize -** change, I decide to define vtophys() as virt_to_bus(). +** The driver has to provide physical memory addresses to +** the script processor. Because some architectures use +** different physical addresses from the PCI BUS, we must +** use virt_to_bus instead of virt_to_phys. */ -#if LINUX_VERSION_CODE >= LinuxVersionCode(1,3,0) #define vtophys(p) virt_to_bus(p) /* @@ -309,20 +569,29 @@ ** architecture. */ -#ifndef NCR_IOMAPPED +#if LINUX_VERSION_CODE < LinuxVersionCode(2,1,0) +#define ioremap vremap +#define iounmap vfree +#endif + +#if defined (__sparc__) +#include +#elif defined (__alpha__) +#define bus_dvma_to_mem(p) ((p) & 0xfffffffful) +#else +#define bus_dvma_to_mem(p) (p) +#endif + +#if defined(__i386__) || !defined(NCR_IOMAPPED) __initfunc( static vm_offset_t remap_pci_mem(u_long base, u_long size) ) { u_long page_base = ((u_long) base) & PAGE_MASK; u_long page_offs = ((u_long) base) - page_base; -#if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,0) u_long page_remapped = (u_long) ioremap(page_base, page_offs+size); -#else - u_long page_remapped = (u_long) vremap(page_base, page_offs+size); -#endif - return (vm_offset_t) (page_remapped ? (page_remapped + page_offs) : 0UL); + return (vm_offset_t) (page_remapped? (page_remapped + page_offs) : 0UL); } __initfunc( @@ -330,51 +599,40 @@ ) { if (vaddr) -#if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,0) iounmap((void *) (vaddr & PAGE_MASK)); -#else - vfree((void *) (vaddr & PAGE_MASK)); -#endif } -#endif /* !NCR_IOMAPPED */ - -#else /* linux-1.2.13 */ +#endif /* __i386__ || !NCR_IOMAPPED */ /* -** Linux 1.2.X assumes that addresses (virtual, physical, bus) -** are the same. -** -** I have not found how to do MMIO. It seems that only processes can -** map high physical pages to virtual (Xservers can do MMIO). -*/ - -#define vtophys(p) ((u_long) (p)) +** Insert a delay in micro-seconds and milli-seconds. +** ------------------------------------------------- +** Under Linux, udelay() is restricted to delay < 1 milli-second. +** In fact, it generally works for up to 1 second delay. +** Since 2.1.105, the mdelay() function is provided for delays +** in milli-seconds. +** Under 2.0 kernels, udelay() is an inline function that is very +** inaccurate on Pentium processors. +*/ + +#if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,105) +#define UDELAY udelay +#define MDELAY mdelay +#else +static void UDELAY(long us) { udelay(us); } +static void MDELAY(long ms) { while (ms--) UDELAY(1000); } #endif /* -** Insert a delay in micro-seconds. -*/ - -static void DELAY(long us) -{ - for (;us>1000;us-=1000) udelay(1000); - if (us) udelay(us); -} - -/* ** Internal data structure allocation. ** ** Linux scsi memory poor pool is adjusted for the need of ** middle-level scsi driver. ** We allocate our control blocks in the kernel memory pool ** to avoid scsi pool shortage. -** I notice that kmalloc() returns NULL during host attach under -** Linux 1.2.13. But this ncr driver is reliable enough to -** accomodate with this joke. ** -** kmalloc() only ensure 8 bytes boundary alignment. +** kmalloc() only ensures 8 bytes boundary alignment. ** The NCR need better alignment for cache line bursting. -** The global header is moved betewen the NCB and CCBs and need +** The global header is moved between the NCB and CCBs and needs ** origin and destination addresses to have same lower four bits. ** ** We use 32 boundary alignment for NCB and CCBs and offset multiple @@ -384,17 +642,9 @@ #define ALIGN_SIZE(shift) (1UL << shift) #define ALIGN_MASK(shift) (~(ALIGN_SIZE(shift)-1)) -#define NCB_ALIGN_SHIFT 5 -#define CCB_ALIGN_SHIFT 5 -#define LCB_ALIGN_SHIFT 5 -#define SCR_ALIGN_SHIFT 5 - -#define NCB_ALIGN_SIZE ALIGN_SIZE(NCB_ALIGN_SHIFT) -#define NCB_ALIGN_MASK ALIGN_MASK(NCB_ALIGN_SHIFT) -#define CCB_ALIGN_SIZE ALIGN_SIZE(CCB_ALIGN_SHIFT) -#define CCB_ALIGN_MASK ALIGN_MASK(CCB_ALIGN_SHIFT) -#define SCR_ALIGN_SIZE ALIGN_SIZE(SCR_ALIGN_SHIFT) -#define SCR_ALIGN_MASK ALIGN_MASK(SCR_ALIGN_SHIFT) +#define CACHE_LINE_SHIFT 5 +#define CACHE_LINE_SIZE ALIGN_SIZE(CACHE_LINE_SHIFT) +#define CACHE_LINE_MASK ALIGN_MASK(CACHE_LINE_SHIFT) static void *m_alloc(int size, int a_shift) { @@ -448,11 +698,8 @@ ** be able to transfer data in the direction choosen by the target. */ -#define XferNone 0 -#define XferIn 1 -#define XferOut 2 -#define XferBoth 3 -static int guess_xfer_direction(int opcode); +#define XFER_IN (1) +#define XFER_OUT (2) /* ** Head of list of NCR boards @@ -470,45 +717,30 @@ ** /proc directory entry and proc_info function */ -#if LINUX_VERSION_CODE >= LinuxVersionCode(1,3,0) struct proc_dir_entry proc_scsi_ncr53c8xx = { PROC_SCSI_NCR53C8XX, 9, "ncr53c8xx", S_IFDIR | S_IRUGO | S_IXUGO, 2 }; -# ifdef SCSI_NCR_PROC_INFO_SUPPORT +#ifdef SCSI_NCR_PROC_INFO_SUPPORT int ncr53c8xx_proc_info(char *buffer, char **start, off_t offset, int length, int hostno, int func); -# endif #endif /* -** Table of target capabilities. -** -** This bitmap is anded with the byte 7 of inquiry data on completion of -** INQUIRY command. -** The driver never see zeroed bits and will ignore the corresponding -** capabilities of the target. -*/ - -static struct { - unsigned char and_map[MAX_TARGET]; -} target_capabilities[SCSI_NCR_MAX_HOST] = { NCR53C8XX_TARGET_CAPABILITIES }; - -/* ** Driver setup. ** ** This structure is initialized from linux config options. ** It can be overridden at boot-up by the boot command line. */ struct ncr_driver_setup { - unsigned master_parity : 1; - unsigned scsi_parity : 1; - unsigned disconnection : 1; - unsigned special_features : 2; - unsigned ultra_scsi : 2; - unsigned force_sync_nego: 1; - unsigned reverse_probe: 1; - unsigned pci_fix_up: 4; + u_char master_parity; + u_char scsi_parity; + u_char disconnection; + u_char special_features; + u_char ultra_scsi; + u_char force_sync_nego; + u_char reverse_probe; + u_char pci_fix_up; u_char use_nvram; u_char verbose; u_char default_tags; @@ -521,6 +753,7 @@ u_char diff_support; u_char irqm; u_char bus_check; + char tag_ctrl[100]; }; static struct ncr_driver_setup @@ -529,9 +762,12 @@ #ifdef SCSI_NCR_BOOT_COMMAND_LINE_SUPPORT static struct ncr_driver_setup driver_safe_setup __initdata = SCSI_NCR_DRIVER_SAFE_SETUP; -#ifdef MODULE +# ifdef MODULE char *ncr53c8xx = 0; /* command line passed by insmod */ -#endif +# if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,30) +MODULE_PARM(ncr53c8xx, "s"); +# endif +# endif #endif /* @@ -540,16 +776,9 @@ #define ScsiResult(host_code, scsi_code) (((host_code) << 16) + ((scsi_code) & 0x7f)) -#if LINUX_VERSION_CODE >= LinuxVersionCode(2,0,0) -static void ncr53c8xx_select_queue_depths(struct Scsi_Host *host, struct scsi_device *devlist); -#endif - -#if LINUX_VERSION_CODE >= LinuxVersionCode(1,3,70) +static void ncr53c8xx_select_queue_depths( + struct Scsi_Host *host, struct scsi_device *devlist); static void ncr53c8xx_intr(int irq, void *dev_id, struct pt_regs * regs); -#else -static void ncr53c8xx_intr(int irq, struct pt_regs * regs); -#endif - static void ncr53c8xx_timeout(unsigned long np); #define initverbose (driver_setup.verbose) @@ -576,6 +805,7 @@ #define SYMBIOS_SCAM_ENABLE (1) #define SYMBIOS_PARITY_ENABLE (1<<1) #define SYMBIOS_VERBOSE_MSGS (1<<2) +#define SYMBIOS_CHS_MAPPING (1<<3) u_short flags1; #define SYMBIOS_SCAN_HI_LO (1) u_short word10; /* 0x00 */ @@ -666,13 +896,13 @@ typedef struct { int bus; u_char device_fn; - u_int base; - u_int base_2; - u_int io_port; + u_long base; + u_long base_2; + u_long io_port; int irq; /* port and reg fields to use INB, OUTB macros */ - u_int port; - volatile struct ncr_reg *reg; + u_long port; + volatile struct ncr_reg *reg; } ncr_slot; typedef struct { @@ -745,7 +975,7 @@ #define assert(expression) { \ if (!(expression)) { \ - (void)printf(\ + (void)printk(KERN_ERR \ "assertion \"%s\" failed: file \"%s\", line %d\n", \ #expression, \ __FILE__, __LINE__); \ @@ -808,7 +1038,12 @@ ** ** Access to the controller chip. ** -** If NCR_IOMAPPED is defined, only IO are used by the driver. +** If NCR_IOMAPPED is defined, the driver will use +** normal IOs instead of the MEMORY MAPPED IO method +** recommended by PCI specifications. +** If all PCI bridges, host brigdes and architectures +** would have been correctly designed for PCI, this +** option would be useless. ** **========================================================== */ @@ -928,15 +1163,31 @@ #define HS_NEGOTIATE (2) /* sync/wide data transfer*/ #define HS_DISCONNECT (3) /* Disconnected by target */ -#define HS_COMPLETE (4) -#define HS_SEL_TIMEOUT (5) /* Selection timeout */ -#define HS_RESET (6) /* SCSI reset */ -#define HS_ABORTED (7) /* Transfer aborted */ -#define HS_TIMEOUT (8) /* Software timeout */ -#define HS_FAIL (9) /* SCSI or PCI bus errors */ -#define HS_UNEXPECTED (10) /* Unexpected disconnect */ +#define HS_DONEMASK (0x80) +#define HS_COMPLETE (4|HS_DONEMASK) +#define HS_SEL_TIMEOUT (5|HS_DONEMASK) /* Selection timeout */ +#define HS_RESET (6|HS_DONEMASK) /* SCSI reset */ +#define HS_ABORTED (7|HS_DONEMASK) /* Transfer aborted */ +#define HS_TIMEOUT (8|HS_DONEMASK) /* Software timeout */ +#define HS_FAIL (9|HS_DONEMASK) /* SCSI or PCI bus errors */ +#define HS_UNEXPECTED (10|HS_DONEMASK)/* Unexpected disconnect */ -#define HS_DONEMASK (0xfc) +/* +** Invalid host status values used by the SCRIPTS processor +** when the nexus is not fully identified. +** Shall never appear in a CCB. +*/ + +#define HS_INVALMASK (0x40) +#define HS_SELECTING (0|HS_INVALMASK) +#define HS_IN_RESELECT (1|HS_INVALMASK) +#define HS_STARTING (2|HS_INVALMASK) + +/* +** Flags set by the SCRIPT processor for commands +** that have been skipped. +*/ +#define HS_SKIPMASK (0x20) /*========================================================== ** @@ -945,21 +1196,24 @@ **========================================================== */ -#define SIR_SENSE_RESTART (1) -#define SIR_SENSE_FAILED (2) -#define SIR_STALL_RESTART (3) -#define SIR_STALL_QUEUE (4) -#define SIR_NEGO_SYNC (5) -#define SIR_NEGO_WIDE (6) -#define SIR_NEGO_FAILED (7) -#define SIR_NEGO_PROTO (8) -#define SIR_REJECT_RECEIVED (9) -#define SIR_REJECT_SENT (10) -#define SIR_IGN_RESIDUE (11) -#define SIR_MISSING_SAVE (12) -#define SIR_DATA_IO_IS_OUT (13) -#define SIR_DATA_IO_IS_IN (14) -#define SIR_MAX (14) +#define SIR_BAD_STATUS (1) +#define SIR_XXXXXXXXXX (2) +#define SIR_NEGO_SYNC (3) +#define SIR_NEGO_WIDE (4) +#define SIR_NEGO_FAILED (5) +#define SIR_NEGO_PROTO (6) +#define SIR_REJECT_RECEIVED (7) +#define SIR_REJECT_SENT (8) +#define SIR_IGN_RESIDUE (9) +#define SIR_MISSING_SAVE (10) +#define SIR_RESEL_NO_MSG_IN (11) +#define SIR_RESEL_NO_IDENTIFY (12) +#define SIR_RESEL_BAD_LUN (13) +#define SIR_RESEL_BAD_TARGET (14) +#define SIR_RESEL_BAD_I_T_L (15) +#define SIR_RESEL_BAD_I_T_L_Q (16) +#define SIR_DONE_OVERFLOW (17) +#define SIR_MAX (17) /*========================================================== ** @@ -997,7 +1251,6 @@ #define QUIRK_NOMSG (0x02) #define QUIRK_NOSYNC (0x10) #define QUIRK_NOWIDE16 (0x20) -#define QUIRK_UPDATE (0x80) /*========================================================== ** @@ -1056,10 +1309,7 @@ #define UC_SETWIDE 14 #define UC_SETFLAG 15 #define UC_CLEARPROF 16 - -#ifdef SCSI_NCR_DEBUG_ERROR_RECOVERY_SUPPORT -#define UC_DEBUG_ERROR_RECOVERY 17 -#endif +#define UC_SETVERBOSE 17 #define UF_TRACE (0x01) #define UF_NODISC (0x02) @@ -1072,10 +1322,11 @@ **--------------------------------------- */ +#ifdef SCSI_NCR_PROFILE_SUPPORT + struct tstamp { u_long start; u_long end; - u_long select; u_long command; u_long status; u_long disconnect; @@ -1099,263 +1350,257 @@ u_long ms_disc; u_long ms_post; }; +#endif -/*========================================================== +/*======================================================================== ** ** Declaration of structs: target control block ** -**========================================================== +**======================================================================== */ - struct tcb { - /* - ** during reselection the ncr jumps to this point - ** with SFBR set to the encoded target number - ** with bit 7 set. + /*---------------------------------------------------------------- + ** During reselection the ncr jumps to this point with SFBR + ** set to the encoded target number with bit 7 set. ** if it's not this target, jump to the next. ** - ** JUMP IF (SFBR != #target#) - ** @(next tcb) + ** JUMP IF (SFBR != #target#), @(next tcb) + **---------------------------------------------------------------- */ - struct link jump_tcb; - /* - ** load the actual values for the sxfer and the scntl3 + /*---------------------------------------------------------------- + ** Load the actual values for the sxfer and the scntl3 ** register (sync/wide mode). ** - ** SCR_COPY (1); - ** @(sval field of this tcb) - ** @(sxfer register) - ** SCR_COPY (1); - ** @(wval field of this tcb) - ** @(scntl3 register) + ** SCR_COPY (1), @(sval field of this tcb), @(sxfer register) + ** SCR_COPY (1), @(wval field of this tcb), @(scntl3 register) + **---------------------------------------------------------------- */ - ncrcmd getscr[6]; - /* - ** if next message is "identify" - ** then load the message to SFBR, - ** else load 0 to SFBR. + /*---------------------------------------------------------------- + ** Get the IDENTIFY message and load the LUN to SFBR. ** - ** CALL - ** + ** CALL, + **---------------------------------------------------------------- */ - struct link call_lun; - /* - ** now look for the right lun. + /*---------------------------------------------------------------- + ** Now look for the right lun. ** - ** JUMP - ** @(first ccb of this lun) - */ - - struct link jump_lcb; - - /* - ** pointer to interrupted getcc ccb - */ - - ccb_p hold_cp; - - /* - ** pointer to ccb used for negotiating. - ** Avoid to start a nego for all queued commands + ** For i = 0 to 3 + ** SCR_JUMP ^ IFTRUE(MASK(i, 3)), @(first lcb mod. i) + ** + ** Recent chips will prefetch the 4 JUMPS using only 1 burst. + ** It is kind of hashcoding. + **---------------------------------------------------------------- + */ + struct link jump_lcb[4]; /* JUMPs for reselection */ + lcb_p lp[MAX_LUN]; /* The lcb's of this tcb */ + u_char inq_done; /* Target capabilities received */ + u_char inq_byte7; /* Contains these capabilities */ + + /*---------------------------------------------------------------- + ** Pointer to the ccb used for negotiation. + ** Prevent from starting a negotiation for all queued commands ** when tagged command queuing is enabled. + **---------------------------------------------------------------- */ - ccb_p nego_cp; - /* + /*---------------------------------------------------------------- ** statistical data + **---------------------------------------------------------------- */ - u_long transfers; u_long bytes; - /* - ** user settable limits for sync transfer - ** and tagged commands. - ** These limits are read from the NVRAM if present. - */ - - u_char usrsync; - u_char usrwide; - u_char usrtags; - u_char usrflag; - - u_char numtags; - u_char maxtags; - u_short num_good; - - /* - ** negotiation of wide and synch transfer. - ** device quirks. + /*---------------------------------------------------------------- + ** negotiation of wide and synch transfer and device quirks. + **---------------------------------------------------------------- */ - /*0*/ u_char minsync; /*1*/ u_char sval; /*2*/ u_short period; /*0*/ u_char maxoffs; - /*1*/ u_char quirks; - /*2*/ u_char widedone; /*3*/ u_char wval; - /* - ** inquire data - */ -#define MAX_INQUIRE 36 - u_char inqdata[MAX_INQUIRE]; - /* - ** the lcb's of this tcb + /*---------------------------------------------------------------- + ** User settable limits and options. + ** These limits are read from the NVRAM if present. + **---------------------------------------------------------------- */ - - lcb_p lp[MAX_LUN]; + u_char usrsync; + u_char usrwide; + u_char usrtags; + u_char usrflag; }; -/*========================================================== +/*======================================================================== ** ** Declaration of structs: lun control block ** -**========================================================== +**======================================================================== */ - struct lcb { - /* - ** during reselection the ncr jumps to this point + /*---------------------------------------------------------------- + ** During reselection the ncr jumps to this point ** with SFBR set to the "Identify" message. ** if it's not this lun, jump to the next. ** - ** JUMP IF (SFBR != #lun#) - ** @(next lcb of this target) - */ - - struct link jump_lcb; - - /* - ** if next message is "simple tag", - ** then load the tag to SFBR, - ** else load 0 to SFBR. + ** JUMP IF (SFBR != #lun#), @(next lcb of this target) ** - ** CALL - ** - */ - - struct link call_tag; - - /* - ** now look for the right ccb. + ** It is this lun. Load TEMP with the nexus jumps table + ** address and jump to RESEL_TAG (or RESEL_NOTAG). ** - ** JUMP - ** @(first ccb of this lun) - */ - - struct link jump_ccb; - - /* - ** start of the ccb chain - */ - - ccb_p next_ccb; - - /* - ** Control of tagged queueing - */ - - u_char reqccbs; - u_char actccbs; - u_char reqlink; - u_char actlink; - u_char usetags; - u_char lasttag; - - /* - ** Linux specific fields: - ** Number of active commands and current credit. - ** Should be managed by the generic scsi driver + ** SCR_COPY (4), p_jump_ccb, TEMP, + ** SCR_JUMP, + **---------------------------------------------------------------- */ + struct link jump_lcb; + ncrcmd load_jump_ccb[3]; + struct link jump_tag; + ncrcmd p_jump_ccb; /* Jump table bus address */ + + /*---------------------------------------------------------------- + ** Jump table used by the script processor to directly jump + ** to the CCB corresponding to the reselected nexus. + ** Address is allocated on 256 bytes boundary in order to + ** allow 8 bit calculation of the tag jump entry for up to + ** 64 possible tags. + **---------------------------------------------------------------- + */ + u_int32 jump_ccb_0; /* Default table if no tags */ + u_int32 *jump_ccb; /* Virtual address */ + + /*---------------------------------------------------------------- + ** CCB queue management. + **---------------------------------------------------------------- + */ + XPT_QUEHEAD free_ccbq; /* Queue of available CCBs */ + XPT_QUEHEAD busy_ccbq; /* Queue of busy CCBs */ + XPT_QUEHEAD wait_ccbq; /* Queue of waiting for IO CCBs */ + XPT_QUEHEAD skip_ccbq; /* Queue of skipped CCBs */ + u_char actccbs; /* Number of allocated CCBs */ + u_char busyccbs; /* CCBs busy for this lun */ + u_char queuedccbs; /* CCBs queued to the controller*/ + u_char queuedepth; /* Queue depth for this lun */ + u_char scdev_depth; /* SCSI device queue depth */ + u_char maxnxs; /* Max possible nexuses */ + + /*---------------------------------------------------------------- + ** Control of tagged command queuing. + ** Tags allocation is performed using a circular buffer. + ** This avoids using a loop for tag allocation. + **---------------------------------------------------------------- + */ + u_char ia_tag; /* Allocation index */ + u_char if_tag; /* Freeing index */ + u_char cb_tags[SCSI_NCR_MAX_TAGS]; /* Circular tags buffer */ + u_char usetags; /* Command queuing is active */ + u_char maxtags; /* Max nr of tags asked by user */ + u_char numtags; /* Current number of tags */ + u_char inq_byte7; /* Store unit CmdQ capabitility */ + + /*---------------------------------------------------------------- + ** QUEUE FULL control and ORDERED tag control. + **---------------------------------------------------------------- + */ + /*---------------------------------------------------------------- + ** QUEUE FULL and ORDERED tag control. + **---------------------------------------------------------------- + */ + u_short num_good; /* Nr of GOOD since QUEUE FULL */ + tagmap_t tags_umap; /* Used tags bitmap */ + tagmap_t tags_smap; /* Tags in use at 'tag_stime' */ + u_long tags_stime; /* Last time we set smap=umap */ + ccb_p held_ccb; /* CCB held for QUEUE FULL */ +}; - u_char active; - u_char opennings; - - /*----------------------------------------------- - ** Flag to force M_ORDERED_TAG on next command - ** in order to avoid spurious timeout when - ** M_SIMPLE_TAG is used for all operations. - **----------------------------------------------- +/*======================================================================== +** +** Declaration of structs: the launch script. +** +**======================================================================== +** +** It is part of the CCB and is called by the scripts processor to +** start or restart the data structure (nexus). +** This 6 DWORDs mini script makes use of prefetching. +** +**------------------------------------------------------------------------ +*/ +struct launch { + /*---------------------------------------------------------------- + ** SCR_COPY(4), @(p_phys), @(dsa register) + ** SCR_JUMP, @(scheduler_point) + **---------------------------------------------------------------- */ - u_char force_ordered_tag; -#define NCR_TIMEOUT_INCREASE (5*HZ) + ncrcmd setup_dsa[3]; /* Copy 'phys' address to dsa */ + struct link schedule; /* Jump to scheduler point */ + ncrcmd p_phys; /* 'phys' header bus address */ }; -/*========================================================== +/*======================================================================== ** -** Declaration of structs: COMMAND control block +** Declaration of structs: global HEADER. ** -**========================================================== +**======================================================================== ** -** This substructure is copied from the ccb to a -** global address after selection (or reselection) -** and copied back before disconnect. +** This substructure is copied from the ccb to a global address after +** selection (or reselection) and copied back before disconnect. ** ** These fields are accessible to the script processor. ** -**---------------------------------------------------------- +**------------------------------------------------------------------------ */ struct head { - /* - ** Execution of a ccb starts at this point. - ** It's a jump to the "SELECT" label - ** of the script. - ** - ** After successful selection the script - ** processor overwrites it with a jump to - ** the IDLE label of the script. - */ - - struct link launch; - - /* + /*---------------------------------------------------------------- ** Saved data pointer. - ** Points to the position in the script - ** responsible for the actual transfer - ** of data. - ** It's written after reception of a - ** "SAVE_DATA_POINTER" message. - ** The goalpointer points after - ** the last transfer command. + ** Points to the position in the script responsible for the + ** actual transfer transfer of data. + ** It's written after reception of a SAVE_DATA_POINTER message. + ** The goalpointer points after the last transfer command. + **---------------------------------------------------------------- */ - u_int32 savep; u_int32 lastp; u_int32 goalp; - /* - ** The virtual address of the ccb - ** containing this header. + /*---------------------------------------------------------------- + ** Alternate data pointer. + ** They are copied back to savep/lastp/goalp by the SCRIPTS + ** when the direction is unknown and the device claims data out. + **---------------------------------------------------------------- + */ + u_int32 wlastp; + u_int32 wgoalp; + + /*---------------------------------------------------------------- + ** The virtual address of the ccb containing this header. + **---------------------------------------------------------------- */ - ccb_p cp; - /* - ** space for some timestamps to gather - ** profiling data about devices and this driver. +#ifdef SCSI_NCR_PROFILE_SUPPORT + /*---------------------------------------------------------------- + ** Space for some timestamps to gather profiling data. + **---------------------------------------------------------------- */ - struct tstamp stamp; +#endif - /* - ** status fields. - */ - - u_char scr_st[4]; /* script status */ - u_char status[4]; /* host status. Must be the last */ - /* DWORD of the CCB header */ + /*---------------------------------------------------------------- + ** Status fields. + **---------------------------------------------------------------- + */ + u_char scr_st[4]; /* script status */ + u_char status[4]; /* host status. must be the */ + /* last DWORD of the header. */ }; /* @@ -1388,6 +1633,7 @@ #define HS_REG scr1 #define HS_PRT nc_scr1 #define SS_REG scr2 +#define SS_PRT nc_scr2 #define PS_REG scr3 /* @@ -1410,9 +1656,12 @@ ** First four bytes (host) */ #define xerr_status phys.xerr_st -#define sync_status phys.sync_st #define nego_status phys.nego_st + +#if 0 +#define sync_status phys.sync_st #define wide_status phys.wide_st +#endif /*========================================================== ** @@ -1434,9 +1683,6 @@ /* ** Header. - ** Has to be the first entry, - ** because it's jumped to by the - ** script processor */ struct head header; @@ -1447,403 +1693,276 @@ struct scr_tblsel select; struct scr_tblmove smsg ; - struct scr_tblmove smsg2 ; struct scr_tblmove cmd ; - struct scr_tblmove scmd ; struct scr_tblmove sense ; struct scr_tblmove data [MAX_SCATTER]; }; -/*========================================================== + +/*======================================================================== ** ** Declaration of structs: Command control block. ** -**========================================================== -** -** During execution of a ccb by the script processor, -** the DSA (data structure address) register points -** to this substructure of the ccb. -** This substructure contains the header with -** the script-processor-changable data and then -** data blocks for the indirect move commands. -** -**---------------------------------------------------------- +**======================================================================== */ - - struct ccb { - /* - ** This field forces 32 bytes alignement for phys.header, - ** in order to use cache line bursting when copying it - ** to the ncb. - */ - - struct link filler[2]; - - /* - ** during reselection the ncr jumps to this point. - ** If a "SIMPLE_TAG" message was received, - ** then SFBR is set to the tag. - ** else SFBR is set to 0 - ** If looking for another tag, jump to the next ccb. - ** - ** JUMP IF (SFBR != #TAG#) - ** @(next ccb of this lun) - */ - - struct link jump_ccb; - - /* - ** After execution of this call, the return address - ** (in the TEMP register) points to the following - ** data structure block. - ** So copy it to the DSA register, and start - ** processing of this data structure. - ** - ** CALL - ** - */ - - struct link call_tmp; - - /* - ** This is the data structure which is - ** to be executed by the script processor. + /*---------------------------------------------------------------- + ** This is the data structure which is pointed by the DSA + ** register when it is executed by the script processor. + ** It must be the first entry because it contains the header + ** as first entry that must be cache line aligned. + **---------------------------------------------------------------- + */ + struct dsb phys; + + /*---------------------------------------------------------------- + ** Mini-script used at CCB execution start-up. + ** Load the DSA with the data structure address (phys) and + ** jump to SELECT. Jump to CANCEL if CCB is to be canceled. + **---------------------------------------------------------------- + */ + struct launch start; + + /*---------------------------------------------------------------- + ** Mini-script used at CCB relection to restart the nexus. + ** Load the DSA with the data structure address (phys) and + ** jump to RESEL_DSA. Jump to ABORT if CCB is to be aborted. + **---------------------------------------------------------------- */ + struct launch restart; - struct dsb phys; - - /* + /*---------------------------------------------------------------- ** If a data transfer phase is terminated too early ** (after reception of a message (i.e. DISCONNECT)), ** we have to prepare a mini script to transfer ** the rest of the data. + **---------------------------------------------------------------- */ + ncrcmd patch[8]; - ncrcmd patch[8]; - - /* + /*---------------------------------------------------------------- ** The general SCSI driver provides a ** pointer to a control block. + **---------------------------------------------------------------- */ - - Scsi_Cmnd *cmd; - int data_len; - - /* - ** We prepare a message to be sent after selection, - ** and a second one to be sent after getcc selection. + Scsi_Cmnd *cmd; /* SCSI command */ + u_long tlimit; /* Deadline for this job */ + int data_len; /* Total data length */ + + /*---------------------------------------------------------------- + ** Message areas. + ** We prepare a message to be sent after selection. + ** We may use a second one if the command is rescheduled + ** due to GETCC or QFULL. ** Contents are IDENTIFY and SIMPLE_TAG. ** While negotiating sync or wide transfer, - ** a SDTM or WDTM message is appended. - */ - - u_char scsi_smsg [8]; - u_char scsi_smsg2[8]; - - /* - ** Lock this ccb. - ** Flag is used while looking for a free ccb. - */ - - u_long magic; - - /* - ** Physical address of this instance of ccb - */ - - u_long p_ccb; - - /* - ** Completion time out for this job. - ** It's set to time of start + allowed number of seconds. - */ - - u_long tlimit; - - /* - ** All ccbs of one hostadapter are chained. - */ - - ccb_p link_ccb; - - /* - ** All ccbs of one target/lun are chained. + ** a SDTR or WDTR message is appended. + **---------------------------------------------------------------- */ + u_char scsi_smsg [8]; + u_char scsi_smsg2[8]; - ccb_p next_ccb; - - /* - ** Sense command - */ - - u_char sensecmd[6]; - - /* - ** Tag for this transfer. - ** It's patched into jump_ccb. - ** If it's not zero, a SIMPLE_TAG - ** message is included in smsg. - */ - - u_char tag; - - /* - ** Number of segments of the scatter list. - ** Used for recalculation of savep/goalp/lastp on - ** SIR_DATA_IO_IS_OUT interrupt. - */ - - u_char segments; + /*---------------------------------------------------------------- + ** Other fields. + **---------------------------------------------------------------- + */ + u_long p_ccb; /* BUS address of this CCB */ + u_char sensecmd[6]; /* Sense command */ + u_char tag; /* Tag for this transfer */ + /* 255 means no tag */ + u_char target; + u_char lun; + u_char queued; + u_char auto_sense; + ccb_p link_ccb; /* Host adapter CCB chain */ + XPT_QUEHEAD link_ccbq; /* Link to unit CCB queue */ + u_int32 startp; /* Initial data pointer */ + u_long magic; /* Free / busy CCB flag */ }; #define CCB_PHYS(cp,lbl) (cp->p_ccb + offsetof(struct ccb, lbl)) -/*========================================================== + +/*======================================================================== ** ** Declaration of structs: NCR device descriptor ** -**========================================================== +**======================================================================== */ - struct ncb { - /* + /*---------------------------------------------------------------- ** The global header. - ** Accessible to both the host and the - ** script-processor. - ** Is 32 bytes aligned since ncb is, in order to - ** allow cache line bursting when copying it from or - ** to ccbs. + ** It is accessible to both the host and the script processor. + ** Must be cache line size aligned (32 for x86) in order to + ** allow cache line bursting when it is copied to/from CCB. + **---------------------------------------------------------------- */ struct head header; - /*----------------------------------------------- - ** Specific Linux fields - **----------------------------------------------- - */ - int unit; /* Unit number */ - char chip_name[8]; /* Chip name */ - char inst_name[16]; /* Instance name */ - struct timer_list timer; /* Timer link header */ - int ncr_cache; /* Cache test variable */ - Scsi_Cmnd *waiting_list; /* Waiting list header for commands */ - /* that we can't put into the squeue */ - u_long settle_time; /* Reset in progess */ - u_char release_stage; /* Synchronisation stage on release */ - u_char verbose; /* Boot verbosity for this controller*/ -#ifdef SCSI_NCR_DEBUG_ERROR_RECOVERY_SUPPORT - u_char debug_error_recovery; - u_char stalling; - u_char assert_atn; -#endif - - /*----------------------------------------------- - ** Added field to support differences - ** between ncr chips. - ** sv_xxx are some io register bit value at start-up and - ** so assumed to have been set by the sdms bios. - ** rv_xxx are the bit fields of io register that will keep - ** the features used by the driver. - **----------------------------------------------- - */ - u_short device_id; - u_char revision_id; - - u_char sv_scntl0; - u_char sv_scntl3; - u_char sv_dmode; - u_char sv_dcntl; - u_char sv_ctest3; - u_char sv_ctest4; - u_char sv_ctest5; - u_char sv_gpcntl; - u_char sv_stest2; - u_char sv_stest4; - - u_char rv_scntl0; - u_char rv_scntl3; - u_char rv_dmode; - u_char rv_dcntl; - u_char rv_ctest3; - u_char rv_ctest4; - u_char rv_ctest5; - u_char rv_stest2; - - u_char scsi_mode; - - /*----------------------------------------------- - ** Scripts .. - **----------------------------------------------- - ** - ** During reselection the ncr jumps to this point. + /*---------------------------------------------------------------- + ** CCBs management queues. + **---------------------------------------------------------------- + */ + Scsi_Cmnd *waiting_list; /* Commands waiting for a CCB */ + /* when lcb is not allocated. */ + Scsi_Cmnd *done_list; /* Commands waiting for done() */ + /* callback to be invoked. */ +#if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,93) + spinlock_t smp_lock; /* Lock for SMP threading */ +#endif + + /*---------------------------------------------------------------- + ** Chip and controller indentification. + **---------------------------------------------------------------- + */ + int unit; /* Unit number */ + char chip_name[8]; /* Chip name */ + char inst_name[16]; /* ncb instance name */ + + /*---------------------------------------------------------------- + ** Initial value of some IO register bits. + ** These values are assumed to have been set by BIOS, and may + ** be used for probing adapter implementation differences. + **---------------------------------------------------------------- + */ + u_char sv_scntl0, sv_scntl3, sv_dmode, sv_dcntl, sv_ctest3, sv_ctest4, + sv_ctest5, sv_gpcntl, sv_stest2, sv_stest4; + + /*---------------------------------------------------------------- + ** Actual initial value of IO register bits used by the + ** driver. They are loaded at initialisation according to + ** features that are to be enabled. + **---------------------------------------------------------------- + */ + u_char rv_scntl0, rv_scntl3, rv_dmode, rv_dcntl, rv_ctest3, rv_ctest4, + rv_ctest5, rv_stest2; + + /*---------------------------------------------------------------- + ** Targets management. + ** During reselection the ncr jumps to jump_tcb. ** The SFBR register is loaded with the encoded target id. + ** For i = 0 to 3 + ** SCR_JUMP ^ IFTRUE(MASK(i, 3)), @(next tcb mod. i) ** - ** Jump to the first target. - ** - ** JUMP - ** @(next tcb) - */ - struct link jump_tcb; - - /*----------------------------------------------- - ** Configuration .. - **----------------------------------------------- - ** - ** virtual and physical addresses - ** of the 53c810 chip. - */ - vm_offset_t vaddr; - vm_offset_t paddr; - - vm_offset_t vaddr2; - vm_offset_t paddr2; - - /* - ** pointer to the chip's registers. - */ - volatile - struct ncr_reg* reg; - - /* - ** A copy of the scripts, relocated for this ncb. - */ - struct script *script0; - struct scripth *scripth0; - - /* - ** Scripts instance virtual address. - */ - struct script *script; - struct scripth *scripth; - - /* - ** Scripts instance physical address. - */ - u_long p_script; - u_long p_scripth; - - /* - ** The SCSI address of the host adapter. - */ - u_char myaddr; - - /* - ** Max dwords burst supported by the adapter. - */ + ** Recent chips will prefetch the 4 JUMPS using only 1 burst. + ** It is kind of hashcoding. + **---------------------------------------------------------------- + */ + struct link jump_tcb[4]; /* JUMPs for reselection */ + struct tcb target[MAX_TARGET]; /* Target data */ + + /*---------------------------------------------------------------- + ** Virtual and physical bus addresses of the chip. + **---------------------------------------------------------------- + */ + vm_offset_t vaddr; /* Virtual and bus address of */ + vm_offset_t paddr; /* chip's IO registers. */ + vm_offset_t paddr2; /* On-chip RAM bus address. */ + volatile /* Pointer to volatile for */ + struct ncr_reg *reg; /* memory mapped IO. */ + + /*---------------------------------------------------------------- + ** SCRIPTS virtual and physical bus addresses. + ** 'script' is loaded in the on-chip RAM if present. + ** 'scripth' stays in main memory. + **---------------------------------------------------------------- + */ + struct script *script0; /* Copies of script and scripth */ + struct scripth *scripth0; /* relocated for this ncb. */ + struct scripth *scripth; /* Actual scripth virt. address */ + u_long p_script; /* Actual script and scripth */ + u_long p_scripth; /* bus addresses. */ + + /*---------------------------------------------------------------- + ** General controller parameters and configuration. + **---------------------------------------------------------------- + */ + u_short device_id; /* PCI device id */ + u_char revision_id; /* PCI device revision id */ + u_long port; /* IO space base address */ + u_int irq; /* IRQ level */ + u_int features; /* Chip features map */ + u_char myaddr; /* SCSI id of the adapter */ u_char maxburst; /* log base 2 of dwords burst */ - - /* - ** timing parameters - */ + u_char maxwide; /* Maximum transfer width */ u_char minsync; /* Minimum sync period factor */ u_char maxsync; /* Maximum sync period factor */ u_char maxoffs; /* Max scsi offset */ u_char multiplier; /* Clock multiplier (1,2,4) */ u_char clock_divn; /* Number of clock divisors */ u_long clock_khz; /* SCSI clock frequency in KHz */ - u_int features; /* Chip features map */ - - /*----------------------------------------------- - ** Link to the generic SCSI driver - **----------------------------------------------- + /*---------------------------------------------------------------- + ** Start queue management. + ** It is filled up by the host processor and accessed by the + ** SCRIPTS processor in order to start SCSI commands. + **---------------------------------------------------------------- + */ + u_short squeueput; /* Next free slot of the queue */ + u_short actccbs; /* Number of allocated CCBs */ + u_short queuedccbs; /* Number of CCBs in start queue*/ + u_short queuedepth; /* Start queue depth */ + + /*---------------------------------------------------------------- + ** Timeout handler. + **---------------------------------------------------------------- */ - - /* struct scsi_link sc_link; */ - - /*----------------------------------------------- - ** Job control - **----------------------------------------------- - ** - ** Commands from user - */ - struct usrcmd user; - u_char order; - - /* - ** Target data - */ - struct tcb target[MAX_TARGET]; - - /* - ** Start queue. - */ - u_int32 squeue [MAX_START]; - u_short squeueput; - u_short actccbs; - - /* - ** Timeout handler - */ -#if 0 - u_long heartbeat; - u_short ticks; - u_short latetime; -#endif + struct timer_list timer; /* Timer handler link header */ u_long lasttime; + u_long settle_time; /* Resetting the SCSI BUS */ - /*----------------------------------------------- - ** Debug and profiling - **----------------------------------------------- - ** - ** register dump - */ - struct ncr_reg regdump; - u_long regtime; - - /* - ** Profiling data - */ - struct profile profile; - u_long disc_phys; - u_long disc_ref; - - /* - ** The global control block. - ** It's used only during the configuration phase. - ** A target control block will be created - ** after the first successful transfer. - */ - struct ccb *ccb; - - /* - ** message buffers. - ** Should be longword aligned, - ** because they're written with a - ** COPY script command. - */ - u_char msgout[8]; - u_char msgin [8]; - u_int32 lastmsg; - - /* - ** Buffer for STATUS_IN phase. - */ - u_char scratch; - - /* - ** controller chip dependent maximal transfer width. - */ - u_char maxwide; - - /* - ** option for M_IDENTIFY message: enables disconnecting - */ - u_char disc; - - /* - ** address of the ncr control registers in io space - */ - u_int port; - - /* - ** irq level + /*---------------------------------------------------------------- + ** Debugging and profiling. + **---------------------------------------------------------------- */ - u_short irq; + struct ncr_reg regdump; /* Register dump */ + u_long regtime; /* Time it has been done */ +#ifdef SCSI_NCR_PROFILE_SUPPORT + struct profile profile; /* Profiling data */ + u_int disc_phys; /* Disconnection counters */ + u_int disc_ref; +#endif + + /*---------------------------------------------------------------- + ** Miscellaneous buffers accessed by the scripts-processor. + ** They shall be DWORD aligned, because they may be read or + ** written with a SCR_COPY script command. + **---------------------------------------------------------------- + */ + u_char msgout[8]; /* Buffer for MESSAGE OUT */ + u_char msgin [8]; /* Buffer for MESSAGE IN */ + u_int32 lastmsg; /* Last SCSI message sent */ + u_char scratch; /* Scratch for SCSI receive */ + + /*---------------------------------------------------------------- + ** Miscellaneous configuration and status parameters. + **---------------------------------------------------------------- + */ + u_char disc; /* Diconnection allowed */ + u_char scsi_mode; /* Current SCSI BUS mode */ + u_char order; /* Tag order to use */ + u_char verbose; /* Verbosity for this controller*/ + int ncr_cache; /* Used for cache test at init. */ + + /*---------------------------------------------------------------- + ** Command completion handling. + **---------------------------------------------------------------- + */ +#ifdef SCSI_NCR_CCB_DONE_SUPPORT + struct ccb *(ccb_done[MAX_DONE]); + int ccb_done_ic; +#endif + /*---------------------------------------------------------------- + ** Fields that should be removed or changed. + **---------------------------------------------------------------- + */ + struct ccb *ccb; /* Global CCB */ + struct usrcmd user; /* Command from user */ + u_char release_stage; /* Synchronisation stage on release */ }; #define NCB_SCRIPT_PHYS(np,lbl) (np->p_script + offsetof (struct script, lbl)) -#define NCB_SCRIPTH_PHYS(np,lbl) (np->p_scripth + offsetof (struct scripth, lbl)) +#define NCB_SCRIPTH_PHYS(np,lbl) (np->p_scripth + offsetof (struct scripth,lbl)) /*========================================================== ** @@ -1861,84 +1980,129 @@ ** we reach them (for forward jumps). ** Therefore we declare a struct here. ** If you make changes inside the script, -** DON'T FORGET TO CHANGE THE LENGTHS HERE! +** DONT FORGET TO CHANGE THE LENGTHS HERE! ** **---------------------------------------------------------- */ /* -** Script fragments which are loaded into the on-board RAM +** Script fragments which are loaded into the on-chip RAM ** of 825A, 875 and 895 chips. */ struct script { - ncrcmd start [ 4]; - ncrcmd start0 [ 2]; - ncrcmd start1 [ 3]; + ncrcmd start [ 5]; ncrcmd startpos [ 1]; - ncrcmd trysel [ 8]; - ncrcmd skip [ 8]; - ncrcmd skip2 [ 3]; - ncrcmd idle [ 2]; - ncrcmd select [ 22]; - ncrcmd prepare [ 4]; - ncrcmd loadpos [ 14]; - ncrcmd prepare2 [ 24]; - ncrcmd setmsg [ 5]; - ncrcmd clrack [ 2]; - ncrcmd dispatch [ 38]; + ncrcmd select [ 6]; + ncrcmd select2 [ 9]; + ncrcmd loadpos [ 4]; + ncrcmd send_ident [ 9]; + ncrcmd prepare [ 6]; + ncrcmd prepare2 [ 7]; +#ifdef SCSI_NCR_PROFILE_SUPPORT + ncrcmd command [ 9]; +#else + ncrcmd command [ 6]; +#endif + ncrcmd dispatch [ 32]; + ncrcmd clrack [ 4]; ncrcmd no_data [ 17]; - ncrcmd checkatn [ 10]; - ncrcmd command [ 15]; - ncrcmd status [ 27]; - ncrcmd msg_in [ 26]; - ncrcmd msg_bad [ 6]; - ncrcmd complete [ 13]; - ncrcmd cleanup [ 12]; - ncrcmd cleanup0 [ 11]; - ncrcmd signal [ 10]; - ncrcmd save_dp [ 5]; +#ifdef SCSI_NCR_PROFILE_SUPPORT + ncrcmd status [ 11]; +#else + ncrcmd status [ 8]; +#endif + ncrcmd msg_in [ 2]; + ncrcmd msg_in2 [ 16]; + ncrcmd msg_bad [ 4]; + ncrcmd setmsg [ 7]; + ncrcmd cleanup [ 6]; + ncrcmd complete [ 9]; + ncrcmd cleanup_ok [ 8]; + ncrcmd cleanup0 [ 1]; +#ifndef SCSI_NCR_CCB_DONE_SUPPORT + ncrcmd signal [ 12]; +#else + ncrcmd signal [ 9]; + ncrcmd done_pos [ 1]; + ncrcmd done_plug [ 2]; + ncrcmd done_end [ 7]; +#endif + ncrcmd save_dp [ 7]; ncrcmd restore_dp [ 5]; - ncrcmd disconnect [ 12]; - ncrcmd disconnect0 [ 5]; - ncrcmd disconnect1 [ 23]; +#ifdef SCSI_NCR_PROFILE_SUPPORT + ncrcmd disconnect [ 28]; +#else + ncrcmd disconnect [ 17]; +#endif ncrcmd msg_out [ 9]; ncrcmd msg_out_done [ 7]; - ncrcmd badgetcc [ 6]; + ncrcmd idle [ 2]; ncrcmd reselect [ 8]; - ncrcmd reselect1 [ 8]; - ncrcmd reselect2 [ 8]; - ncrcmd resel_tmp [ 5]; - ncrcmd resel_lun [ 18]; - ncrcmd resel_tag [ 24]; - ncrcmd data_io [ 6]; - ncrcmd data_in [MAX_SCATTER * 4 + 4]; + ncrcmd reselected [ 8]; + ncrcmd resel_dsa [ 6]; +#ifdef SCSI_NCR_PROFILE_SUPPORT + ncrcmd loadpos1 [ 7]; +#else + ncrcmd loadpos1 [ 4]; +#endif + ncrcmd resel_lun [ 6]; + ncrcmd resel_tag [ 6]; + ncrcmd jump_to_nexus [ 4]; + ncrcmd nexus_indirect [ 4]; + ncrcmd resel_notag [ 4]; + ncrcmd data_in [MAX_SCATTERL * 4]; + ncrcmd data_in2 [ 4]; + ncrcmd data_out [MAX_SCATTERL * 4]; + ncrcmd data_out2 [ 4]; }; /* ** Script fragments which stay in main memory for all chips. */ struct scripth { - ncrcmd tryloop [MAX_START*5+2]; - ncrcmd msg_parity [ 6]; + ncrcmd tryloop [MAX_START*2]; + ncrcmd tryloop2 [ 2]; +#ifdef SCSI_NCR_CCB_DONE_SUPPORT + ncrcmd done_queue [MAX_DONE*5]; + ncrcmd done_queue2 [ 2]; +#endif + ncrcmd select_no_atn [ 8]; + ncrcmd cancel [ 4]; + ncrcmd skip [ 9]; + ncrcmd skip2 [ 19]; + ncrcmd par_err_data_in [ 6]; + ncrcmd par_err_other [ 4]; ncrcmd msg_reject [ 8]; - ncrcmd msg_ign_residue [ 32]; - ncrcmd msg_extended [ 18]; - ncrcmd msg_ext_2 [ 18]; - ncrcmd msg_wdtr [ 27]; - ncrcmd msg_ext_3 [ 18]; - ncrcmd msg_sdtr [ 27]; + ncrcmd msg_ign_residue [ 24]; + ncrcmd msg_extended [ 10]; + ncrcmd msg_ext_2 [ 10]; + ncrcmd msg_wdtr [ 14]; + ncrcmd send_wdtr [ 7]; + ncrcmd msg_ext_3 [ 10]; + ncrcmd msg_sdtr [ 14]; + ncrcmd send_sdtr [ 7]; ncrcmd msg_out_abort [ 10]; - ncrcmd getcc [ 4]; - ncrcmd getcc1 [ 5]; -#ifdef NCR_GETCC_WITHMSG - ncrcmd getcc2 [ 33]; -#else - ncrcmd getcc2 [ 14]; -#endif - ncrcmd getcc3 [ 10]; - ncrcmd data_out [MAX_SCATTER * 4 + 4]; + ncrcmd hdata_in [MAX_SCATTERH * 4]; + ncrcmd hdata_in2 [ 2]; + ncrcmd hdata_out [MAX_SCATTERH * 4]; + ncrcmd hdata_out2 [ 2]; + ncrcmd reset [ 4]; ncrcmd aborttag [ 4]; - ncrcmd abort [ 22]; + ncrcmd abort [ 2]; + ncrcmd abort_resel [ 20]; + ncrcmd resend_ident [ 4]; + ncrcmd clratn_go_on [ 3]; + ncrcmd nxtdsp_go_on [ 1]; + ncrcmd sdata_in [ 8]; + ncrcmd data_io [ 18]; + ncrcmd bad_identify [ 12]; + ncrcmd bad_i_t_l [ 4]; + ncrcmd bad_i_t_l_q [ 4]; + ncrcmd bad_target [ 8]; + ncrcmd bad_status [ 8]; + ncrcmd start_ram [ 4]; + ncrcmd start_ram0 [ 4]; + ncrcmd sto_restart [ 5]; ncrcmd snooptest [ 9]; ncrcmd snoopend [ 2]; }; @@ -1952,13 +2116,18 @@ **========================================================== */ -static void ncr_alloc_ccb (ncb_p np, u_long t, u_long l); +static void ncr_alloc_ccb (ncb_p np, u_char tn, u_char ln); static void ncr_complete (ncb_p np, ccb_p cp); static void ncr_exception (ncb_p np); -static void ncr_free_ccb (ncb_p np, ccb_p cp, u_long t, u_long l); +static void ncr_free_ccb (ncb_p np, ccb_p cp); +static void ncr_init_ccb (ncb_p np, ccb_p cp); +static void ncr_init_tcb (ncb_p np, u_char tn); +static lcb_p ncr_alloc_lcb (ncb_p np, u_char tn, u_char ln); +static lcb_p ncr_setup_lcb (ncb_p np, u_char tn, u_char ln, + u_char *inq_data); static void ncr_getclock (ncb_p np, int mult); static void ncr_selectclock (ncb_p np, u_char scntl3); -static ccb_p ncr_get_ccb (ncb_p np, u_long t,u_long l); +static ccb_p ncr_get_ccb (ncb_p np, u_char tn, u_char ln); static void ncr_init (ncb_p np, int reset, char * msg, u_long code); static int ncr_int_sbmc (ncb_p np); static int ncr_int_par (ncb_p np); @@ -1967,7 +2136,6 @@ static void ncr_int_sto (ncb_p np); static u_long ncr_lookup (char* id); static void ncr_negotiate (struct ncb* np, struct tcb* tp); -static void ncr_opennings (ncb_p np, lcb_p lp, Scsi_Cmnd * xp); #ifdef SCSI_NCR_PROFILE_SUPPORT static void ncb_profile (ncb_p np, ccb_p cp); @@ -1977,16 +2145,18 @@ (ncb_p np, ncrcmd *src, ncrcmd *dst, int len); static void ncr_script_fill (struct script * scr, struct scripth * scripth); static int ncr_scatter (ccb_p cp, Scsi_Cmnd *cmd); -static void ncr_setmaxtags (ncb_p np, tcb_p tp, u_long numtags); static void ncr_getsync (ncb_p np, u_char sfac, u_char *fakp, u_char *scntl3p); static void ncr_setsync (ncb_p np, ccb_p cp, u_char scntl3, u_char sxfer); -static void ncr_settags (tcb_p tp, lcb_p lp); +static void ncr_setup_tags (ncb_p np, u_char tn, u_char ln); static void ncr_setwide (ncb_p np, ccb_p cp, u_char wide, u_char ack); static int ncr_show_msg (u_char * msg); static int ncr_snooptest (ncb_p np); static void ncr_timeout (ncb_p np); static void ncr_wakeup (ncb_p np, u_long code); -static void ncr_start_reset (ncb_p np, int settle_delay); +static void ncr_wakeup_done (ncb_p np); +static void ncr_start_next_ccb (ncb_p np, lcb_p lp, int maxn); +static void ncr_put_start_queue(ncb_p np, ccb_p cp); +static void ncr_start_reset (ncb_p np); static int ncr_reset_scsi_bus (ncb_p np, int enab_int, int settle_delay); #ifdef SCSI_NCR_USER_COMMAND_SUPPORT @@ -2075,38 +2245,17 @@ static struct script script0 __initdata = { /*--------------------------< START >-----------------------*/ { -#if 0 /* - ** Claim to be still alive ... + ** This NOP will be patched with LED ON + ** SCR_REG_REG (gpreg, SCR_AND, 0xfe) */ - SCR_COPY (sizeof (((struct ncb *)0)->heartbeat)), - KVAR(SCRIPT_KVAR_JIFFIES), - NADDR (heartbeat), -#endif + SCR_NO_OP, + 0, /* - ** Make data structure address invalid. - ** clear SIGP. + ** Clear SIGP. */ - SCR_LOAD_REG (dsa, 0xff), - 0, SCR_FROM_REG (ctest2), 0, -}/*-------------------------< START0 >----------------------*/,{ - /* - ** Hook for interrupted GetConditionCode. - ** Will be patched to ... IFTRUE by - ** the interrupt handler. - */ - SCR_INT ^ IFFALSE (0), - SIR_SENSE_RESTART, - -}/*-------------------------< START1 >----------------------*/,{ - /* - ** Hook for stalled start queue. - ** Will be patched to IFTRUE by the interrupt handler. - */ - SCR_INT ^ IFFALSE (0), - SIR_STALL_RESTART, /* ** Then jump to a certain point in tryloop. ** Due to the lack of indirect addressing the code @@ -2115,76 +2264,6 @@ SCR_JUMP, }/*-------------------------< STARTPOS >--------------------*/,{ PADDRH(tryloop), -}/*-------------------------< TRYSEL >----------------------*/,{ - /* - ** Now: - ** DSA: Address of a Data Structure - ** or Address of the IDLE-Label. - ** - ** TEMP: Address of a script, which tries to - ** start the NEXT entry. - ** - ** Save the TEMP register into the SCRATCHA register. - ** Then copy the DSA to TEMP and RETURN. - ** This is kind of an indirect jump. - ** (The script processor has NO stack, so the - ** CALL is actually a jump and link, and the - ** RETURN is an indirect jump.) - ** - ** If the slot was empty, DSA contains the address - ** of the IDLE part of this script. The processor - ** jumps to IDLE and waits for a reselect. - ** It will wake up and try the same slot again - ** after the SIGP bit becomes set by the host. - ** - ** If the slot was not empty, DSA contains - ** the address of the phys-part of a ccb. - ** The processor jumps to this address. - ** phys starts with head, - ** head starts with launch, - ** so actually the processor jumps to - ** the lauch part. - ** If the entry is scheduled for execution, - ** then launch contains a jump to SELECT. - ** If it's not scheduled, it contains a jump to IDLE. - */ - SCR_COPY (4), - RADDR (temp), - RADDR (scratcha), - SCR_COPY (4), - RADDR (dsa), - RADDR (temp), - SCR_RETURN, - 0 - -}/*-------------------------< SKIP >------------------------*/,{ - /* - ** This entry has been canceled. - ** Next time use the next slot. - */ - SCR_COPY (4), - RADDR (scratcha), - PADDR (startpos), - /* - ** patch the launch field. - ** should look like an idle process. - */ - SCR_COPY_F (4), - RADDR (dsa), - PADDR (skip2), - SCR_COPY (8), - PADDR (idle), -}/*-------------------------< SKIP2 >-----------------------*/,{ - 0, - SCR_JUMP, - PADDR(start), -}/*-------------------------< IDLE >------------------------*/,{ - /* - ** Nothing to do? - ** Wait for reselect. - */ - SCR_JUMP, - PADDR(reselect), }/*-------------------------< SELECT >----------------------*/,{ /* @@ -2201,7 +2280,7 @@ SCR_CLR (SCR_TRG), 0, - SCR_LOAD_REG (HS_REG, 0xff), + SCR_LOAD_REG (HS_REG, HS_SELECTING), 0, /* @@ -2210,6 +2289,7 @@ SCR_SEL_TBL_ATN ^ offsetof (struct dsb, select), PADDR (reselect), +}/*-------------------------< SELECT2 >----------------------*/,{ /* ** Now there are 4 possibilities: ** @@ -2222,50 +2302,31 @@ ** Then the script processor takes the jump ** to the RESELECT label. ** - ** (3) The ncr completes the selection. - ** Then it will execute the next statement. - ** - ** (4) There is a selection timeout. - ** Then the ncr should interrupt the host and stop. - ** Unfortunately, it seems to continue execution - ** of the script. But it will fail with an - ** IID-interrupt on the next WHEN. - */ - - SCR_JUMPR ^ IFTRUE (WHEN (SCR_MSG_IN)), - 0, - - /* - ** Save target id to ctest0 register + ** (3) The ncr wins arbitration. + ** Then it will execute SCRIPTS instruction until + ** the next instruction that checks SCSI phase. + ** Then will stop and wait for selection to be + ** complete or selection time-out to occur. + ** As a result the SCRIPTS instructions until + ** LOADPOS + 2 should be executed in parallel with + ** the SCSI core performing selection. */ - SCR_FROM_REG (sdid), - 0, - SCR_TO_REG (ctest0), - 0, /* - ** Send the IDENTIFY and SIMPLE_TAG messages - ** (and the M_X_SYNC_REQ message) + ** The M_REJECT problem seems to be due to a selection + ** timing problem. + ** Wait immediately for the selection to complete. + ** (2.5x behaves so) */ - SCR_MOVE_TBL ^ SCR_MSG_OUT, - offsetof (struct dsb, smsg), -#ifdef undef /* XXX better fail than try to deal with this ... */ - SCR_JUMPR ^ IFTRUE (WHEN (SCR_MSG_OUT)), - -16, -#endif - SCR_CLR (SCR_ATN), + SCR_JUMPR ^ IFFALSE (WHEN (SCR_MSG_OUT)), 0, - SCR_COPY (1), - RADDR (sfbr), - NADDR (lastmsg), + /* - ** Selection complete. ** Next time use the next slot. */ SCR_COPY (4), - RADDR (scratcha), + RADDR (temp), PADDR (startpos), -}/*-------------------------< PREPARE >----------------------*/,{ /* ** The ncr doesn't have an indirect load ** or store command. So we have to @@ -2285,22 +2346,32 @@ /* ** continued after the next label ... */ - }/*-------------------------< LOADPOS >---------------------*/,{ 0, NADDR (header), /* - ** Mark this ccb as not scheduled. + ** Wait for the next phase or the selection + ** to complete or time-out. */ - SCR_COPY (8), - PADDR (idle), - NADDR (header.launch), + SCR_JUMP ^ IFFALSE (WHEN (SCR_MSG_OUT)), + PADDR (prepare), + +}/*-------------------------< SEND_IDENT >----------------------*/,{ /* - ** Set a time stamp for this selection + ** Selection complete. + ** Send the IDENTIFY and SIMPLE_TAG messages + ** (and the M_X_SYNC_REQ message) */ - SCR_COPY (sizeof (u_long)), - KVAR(SCRIPT_KVAR_JIFFIES), - NADDR (header.stamp.select), + SCR_MOVE_TBL ^ SCR_MSG_OUT, + offsetof (struct dsb, smsg), + SCR_JUMP ^ IFTRUE (WHEN (SCR_MSG_OUT)), + PADDRH (resend_ident), + SCR_LOAD_REG (scratcha, 0x80), + 0, + SCR_COPY (1), + RADDR (scratcha), + NADDR (lastmsg), +}/*-------------------------< PREPARE >----------------------*/,{ /* ** load the savep (saved pointer) into ** the TEMP register (actual pointer) @@ -2314,74 +2385,61 @@ SCR_COPY (4), NADDR (header.status), RADDR (scr0), - }/*-------------------------< PREPARE2 >---------------------*/,{ /* - ** Load the synchronous mode register - */ - SCR_COPY (1), - NADDR (sync_st), - RADDR (sxfer), - /* - ** Load the wide mode and timing register - */ - SCR_COPY (1), - NADDR (wide_st), - RADDR (scntl3), - /* - ** Initialize the msgout buffer with a NOOP message. + ** Initialize the msgout buffer with a NOOP message. */ SCR_LOAD_REG (scratcha, M_NOOP), 0, SCR_COPY (1), RADDR (scratcha), NADDR (msgout), +#if 0 SCR_COPY (1), RADDR (scratcha), NADDR (msgin), +#endif /* - ** Message in phase ? + ** Anticipate the COMMAND phase. + ** This is the normal case for initial selection. */ - SCR_JUMP ^ IFFALSE (WHEN (SCR_MSG_IN)), + SCR_JUMP ^ IFFALSE (WHEN (SCR_COMMAND)), PADDR (dispatch), + +}/*-------------------------< COMMAND >--------------------*/,{ +#ifdef SCSI_NCR_PROFILE_SUPPORT /* - ** Extended or reject message ? + ** ... set a timestamp ... */ - SCR_FROM_REG (sbdl), - 0, - SCR_JUMP ^ IFTRUE (DATA (M_EXTENDED)), - PADDR (msg_in), - SCR_JUMP ^ IFTRUE (DATA (M_REJECT)), - PADDRH (msg_reject), + SCR_COPY (sizeof (u_long)), + KVAR(SCRIPT_KVAR_JIFFIES), + NADDR (header.stamp.command), +#endif /* - ** normal processing + ** ... and send the command */ - SCR_JUMP, - PADDR (dispatch), -}/*-------------------------< SETMSG >----------------------*/,{ - SCR_COPY (1), - RADDR (scratcha), - NADDR (msgout), - SCR_SET (SCR_ATN), - 0, -}/*-------------------------< CLRACK >----------------------*/,{ + SCR_MOVE_TBL ^ SCR_COMMAND, + offsetof (struct dsb, cmd), /* - ** Terminate possible pending message phase. + ** If status is still HS_NEGOTIATE, negotiation failed. + ** We check this here, since we want to do that + ** only once. */ - SCR_CLR (SCR_ACK), - 0, - -}/*-----------------------< DISPATCH >----------------------*/,{ SCR_FROM_REG (HS_REG), 0, SCR_INT ^ IFTRUE (DATA (HS_NEGOTIATE)), SIR_NEGO_FAILED, + +}/*-----------------------< DISPATCH >----------------------*/,{ /* - ** remove bogus output signals + ** MSG_IN is the only phase that shall be + ** entered at least once for each (re)selection. + ** So we test it first. */ - SCR_REG_REG (socl, SCR_AND, CACK|CATN), - 0, - SCR_RETURN ^ IFTRUE (WHEN (SCR_DATA_OUT)), + SCR_JUMP ^ IFTRUE (WHEN (SCR_MSG_IN)), + PADDR (msg_in), + + SCR_RETURN ^ IFTRUE (IF (SCR_DATA_OUT)), 0, /* ** DEL 397 - 53C875 Rev 3 - Part Number 609-0392410 - ITEM 4. @@ -2396,16 +2454,13 @@ RADDR (scratcha), RADDR (scratcha), SCR_RETURN, - 0, - - SCR_JUMP ^ IFTRUE (IF (SCR_MSG_OUT)), - PADDR (msg_out), - SCR_JUMP ^ IFTRUE (IF (SCR_MSG_IN)), - PADDR (msg_in), - SCR_JUMP ^ IFTRUE (IF (SCR_COMMAND)), - PADDR (command), + 0, SCR_JUMP ^ IFTRUE (IF (SCR_STATUS)), PADDR (status), + SCR_JUMP ^ IFTRUE (IF (SCR_COMMAND)), + PADDR (command), + SCR_JUMP ^ IFTRUE (IF (SCR_MSG_OUT)), + PADDR (msg_out), /* ** Discard one illegal phase byte, if required. */ @@ -2425,6 +2480,15 @@ SCR_JUMP, PADDR (dispatch), +}/*-------------------------< CLRACK >----------------------*/,{ + /* + ** Terminate possible pending message phase. + */ + SCR_CLR (SCR_ACK), + 0, + SCR_JUMP, + PADDR (dispatch), + }/*-------------------------< NO_DATA >--------------------*/,{ /* ** The target wants to tranfer too much data @@ -2454,116 +2518,31 @@ PADDR (dispatch), SCR_JUMP, PADDR (no_data), -}/*-------------------------< CHECKATN >--------------------*/,{ - /* - ** If AAP (bit 1 of scntl0 register) is set - ** and a parity error is detected, - ** the script processor asserts ATN. - ** - ** The target should switch to a MSG_OUT phase - ** to get the message. - */ - SCR_FROM_REG (socl), - 0, - SCR_JUMP ^ IFFALSE (MASK (CATN, CATN)), - PADDR (dispatch), - /* - ** count it - */ - SCR_REG_REG (PS_REG, SCR_ADD, 1), - 0, - /* - ** Prepare a M_ID_ERROR message - ** (initiator detected error). - ** The target should retry the transfer. - */ - SCR_LOAD_REG (scratcha, M_ID_ERROR), - 0, - SCR_JUMP, - PADDR (setmsg), - -}/*-------------------------< COMMAND >--------------------*/,{ - /* - ** If this is not a GETCC transfer ... - */ - SCR_FROM_REG (SS_REG), - 0, -/*<<<*/ SCR_JUMPR ^ IFTRUE (DATA (S_CHECK_COND)), - 28, - /* - ** ... set a timestamp ... - */ - SCR_COPY (sizeof (u_long)), - KVAR(SCRIPT_KVAR_JIFFIES), - NADDR (header.stamp.command), - /* - ** ... and send the command - */ - SCR_MOVE_TBL ^ SCR_COMMAND, - offsetof (struct dsb, cmd), - SCR_JUMP, - PADDR (dispatch), - /* - ** Send the GETCC command - */ -/*>>>*/ SCR_MOVE_TBL ^ SCR_COMMAND, - offsetof (struct dsb, scmd), - SCR_JUMP, - PADDR (dispatch), }/*-------------------------< STATUS >--------------------*/,{ +#ifdef SCSI_NCR_PROFILE_SUPPORT /* ** set the timestamp. */ SCR_COPY (sizeof (u_long)), KVAR(SCRIPT_KVAR_JIFFIES), NADDR (header.stamp.status), - /* - ** If this is a GETCC transfer, - */ - SCR_FROM_REG (SS_REG), - 0, -/*<<<*/ SCR_JUMPR ^ IFFALSE (DATA (S_CHECK_COND)), - 40, +#endif /* ** get the status */ SCR_MOVE_ABS (1) ^ SCR_STATUS, NADDR (scratch), /* - ** Save status to scsi_status. - ** Mark as complete. - ** And wait for disconnect. - */ - SCR_TO_REG (SS_REG), - 0, - SCR_REG_REG (SS_REG, SCR_OR, S_SENSE), - 0, - SCR_LOAD_REG (HS_REG, HS_COMPLETE), - 0, - SCR_JUMP, - PADDR (checkatn), - /* - ** If it was no GETCC transfer, - ** save the status to scsi_status. + ** save status to scsi_status. + ** mark as complete. */ -/*>>>*/ SCR_MOVE_ABS (1) ^ SCR_STATUS, - NADDR (scratch), SCR_TO_REG (SS_REG), 0, - /* - ** if it was no check condition ... - */ - SCR_JUMP ^ IFTRUE (DATA (S_CHECK_COND)), - PADDR (checkatn), - /* - ** ... mark as complete. - */ SCR_LOAD_REG (HS_REG, HS_COMPLETE), 0, SCR_JUMP, - PADDR (checkatn), - + PADDR (dispatch), }/*-------------------------< MSG_IN >--------------------*/,{ /* ** Get the first byte of the message @@ -2574,28 +2553,18 @@ */ SCR_MOVE_ABS (1) ^ SCR_MSG_IN, NADDR (msgin[0]), +}/*-------------------------< MSG_IN2 >--------------------*/,{ /* - ** Check for message parity error. - */ - SCR_TO_REG (scratcha), - 0, - SCR_FROM_REG (socl), - 0, - SCR_JUMP ^ IFTRUE (MASK (CATN, CATN)), - PADDRH (msg_parity), - SCR_FROM_REG (scratcha), - 0, - /* - ** Parity was ok, handle this message. + ** Handle this message. */ SCR_JUMP ^ IFTRUE (DATA (M_COMPLETE)), PADDR (complete), + SCR_JUMP ^ IFTRUE (DATA (M_DISCONNECT)), + PADDR (disconnect), SCR_JUMP ^ IFTRUE (DATA (M_SAVE_DP)), PADDR (save_dp), SCR_JUMP ^ IFTRUE (DATA (M_RESTORE_DP)), PADDR (restore_dp), - SCR_JUMP ^ IFTRUE (DATA (M_DISCONNECT)), - PADDR (disconnect), SCR_JUMP ^ IFTRUE (DATA (M_EXTENDED)), PADDRH (msg_extended), SCR_JUMP ^ IFTRUE (DATA (M_NOOP)), @@ -2619,24 +2588,42 @@ SIR_REJECT_SENT, SCR_LOAD_REG (scratcha, M_REJECT), 0, +}/*-------------------------< SETMSG >----------------------*/,{ + SCR_COPY (1), + RADDR (scratcha), + NADDR (msgout), + SCR_SET (SCR_ATN), + 0, + SCR_JUMP, + PADDR (clrack), +}/*-------------------------< CLEANUP >-------------------*/,{ + /* + ** dsa: Pointer to ccb + ** or xxxxxxFF (no ccb) + ** + ** HS_REG: Host-Status (<>0!) + */ + SCR_FROM_REG (dsa), + 0, + SCR_JUMP ^ IFTRUE (DATA (0xff)), + PADDR (start), + /* + ** dsa is valid. + ** complete the cleanup. + */ SCR_JUMP, - PADDR (setmsg), + PADDR (cleanup_ok), }/*-------------------------< COMPLETE >-----------------*/,{ /* ** Complete message. ** - ** If it's not the get condition code, - ** copy TEMP register to LASTP in header. + ** Copy TEMP register to LASTP in header. */ - SCR_FROM_REG (SS_REG), - 0, -/*<<<*/ SCR_JUMPR ^ IFTRUE (MASK (S_SENSE, S_SENSE)), - 12, SCR_COPY (4), RADDR (temp), NADDR (header.lastp), -/*>>>*/ /* + /* ** When we terminate the cycle by clearing ACK, ** the target may disconnect immediately. ** @@ -2656,20 +2643,9 @@ */ SCR_WAIT_DISC, 0, -}/*-------------------------< CLEANUP >-------------------*/,{ - /* - ** dsa: Pointer to ccb - ** or xxxxxxFF (no ccb) - ** - ** HS_REG: Host-Status (<>0!) - */ - SCR_FROM_REG (dsa), - 0, - SCR_JUMP ^ IFTRUE (DATA (0xff)), - PADDR (signal), +}/*-------------------------< CLEANUP_OK >----------------*/,{ /* - ** dsa is valid. - ** save the status registers + ** Save host status to header. */ SCR_COPY (4), RADDR (scr0), @@ -2684,43 +2660,32 @@ NADDR (header), }/*-------------------------< CLEANUP0 >--------------------*/,{ 0, - +}/*-------------------------< SIGNAL >----------------------*/,{ /* - ** If command resulted in "check condition" - ** status and is not yet completed, - ** try to get the condition code. + ** if job not completed ... */ SCR_FROM_REG (HS_REG), 0, -/*<<<*/ SCR_JUMPR ^ IFFALSE (MASK (0, HS_DONEMASK)), - 16, - SCR_FROM_REG (SS_REG), - 0, - SCR_JUMP ^ IFTRUE (DATA (S_CHECK_COND)), - PADDRH(getcc2), /* - ** And make the DSA register invalid. + ** ... start the next command. */ -/*>>>*/ SCR_LOAD_REG (dsa, 0xff), /* invalid */ - 0, -}/*-------------------------< SIGNAL >----------------------*/,{ + SCR_JUMP ^ IFTRUE (MASK (0, (HS_DONEMASK|HS_SKIPMASK))), + PADDR(start), /* - ** if status = queue full, - ** reinsert in startqueue and stall queue. + ** If command resulted in not GOOD status, + ** call the C code if needed. */ SCR_FROM_REG (SS_REG), 0, - SCR_INT ^ IFTRUE (DATA (S_QUEUE_FULL)), - SIR_STALL_QUEUE, - /* - ** if job completed ... - */ - SCR_FROM_REG (HS_REG), - 0, + SCR_CALL ^ IFFALSE (DATA (S_GOOD)), + PADDRH (bad_status), + +#ifndef SCSI_NCR_CCB_DONE_SUPPORT + /* ** ... signal completion to the host */ - SCR_INT_FLY ^ IFFALSE (MASK (0, HS_DONEMASK)), + SCR_INT_FLY, 0, /* ** Auf zu neuen Schandtaten! @@ -2728,6 +2693,28 @@ SCR_JUMP, PADDR(start), +#else /* defined SCSI_NCR_CCB_DONE_SUPPORT */ + + /* + ** ... signal completion to the host + */ + SCR_JUMP, +}/*------------------------< DONE_POS >---------------------*/,{ + PADDRH (done_queue), +}/*------------------------< DONE_PLUG >--------------------*/,{ + SCR_INT, + SIR_DONE_OVERFLOW, +}/*------------------------< DONE_END >---------------------*/,{ + SCR_INT_FLY, + 0, + SCR_COPY (4), + RADDR (temp), + PADDR (done_pos), + SCR_JUMP, + PADDR (start), + +#endif /* SCSI_NCR_CCB_DONE_SUPPORT */ + }/*-------------------------< SAVE_DP >------------------*/,{ /* ** SAVE_DP message: @@ -2736,8 +2723,10 @@ SCR_COPY (4), RADDR (temp), NADDR (header.savep), + SCR_CLR (SCR_ACK), + 0, SCR_JUMP, - PADDR (clrack), + PADDR (dispatch), }/*-------------------------< RESTORE_DP >---------------*/,{ /* ** RESTORE_DP message: @@ -2751,56 +2740,6 @@ }/*-------------------------< DISCONNECT >---------------*/,{ /* - ** If QUIRK_AUTOSAVE is set, - ** do an "save pointer" operation. - */ - SCR_FROM_REG (QU_REG), - 0, -/*<<<*/ SCR_JUMPR ^ IFFALSE (MASK (QUIRK_AUTOSAVE, QUIRK_AUTOSAVE)), - 12, - /* - ** like SAVE_DP message: - ** Copy TEMP register to SAVEP in header. - */ - SCR_COPY (4), - RADDR (temp), - NADDR (header.savep), -/*>>>*/ /* - ** Check if temp==savep or temp==goalp: - ** if not, log a missing save pointer message. - ** In fact, it's a comparison mod 256. - ** - ** Hmmm, I hadn't thought that I would be urged to - ** write this kind of ugly self modifying code. - ** - ** It's unbelievable, but the ncr53c8xx isn't able - ** to subtract one register from another. - */ - SCR_FROM_REG (temp), - 0, - /* - ** You are not expected to understand this .. - ** - ** CAUTION: only little endian architectures supported! XXX - */ - SCR_COPY_F (1), - NADDR (header.savep), - PADDR (disconnect0), -}/*-------------------------< DISCONNECT0 >--------------*/,{ -/*<<<*/ SCR_JUMPR ^ IFTRUE (DATA (1)), - 20, - /* - ** neither this - */ - SCR_COPY_F (1), - NADDR (header.goalp), - PADDR (disconnect1), -}/*-------------------------< DISCONNECT1 >--------------*/,{ - SCR_INT ^ IFFALSE (DATA (1)), - SIR_MISSING_SAVE, -/*>>>*/ - - /* ** DISCONNECTing ... ** ** disable the "unexpected disconnect" feature, @@ -2815,6 +2754,7 @@ */ SCR_WAIT_DISC, 0, +#ifdef SCSI_NCR_PROFILE_SUPPORT /* ** Profiling: ** Set a time stamp, @@ -2825,19 +2765,35 @@ NADDR (header.stamp.disconnect), SCR_COPY (4), NADDR (disc_phys), - RADDR (temp), - SCR_REG_REG (temp, SCR_ADD, 0x01), + RADDR (scratcha), + SCR_REG_REG (scratcha, SCR_ADD, 0x01), 0, SCR_COPY (4), - RADDR (temp), + RADDR (scratcha), NADDR (disc_phys), +#endif /* ** Status is: DISCONNECTED. */ SCR_LOAD_REG (HS_REG, HS_DISCONNECT), 0, + /* + ** If QUIRK_AUTOSAVE is set, + ** do an "save pointer" operation. + */ + SCR_FROM_REG (QU_REG), + 0, + SCR_JUMP ^ IFFALSE (MASK (QUIRK_AUTOSAVE, QUIRK_AUTOSAVE)), + PADDR (cleanup_ok), + /* + ** like SAVE_DP message: + ** Copy TEMP register to SAVEP in header. + */ + SCR_COPY (4), + RADDR (temp), + NADDR (header.savep), SCR_JUMP, - PADDR (cleanup), + PADDR (cleanup_ok), }/*-------------------------< MSG_OUT >-------------------*/,{ /* @@ -2846,7 +2802,7 @@ SCR_MOVE_ABS (1) ^ SCR_MSG_OUT, NADDR (msgout), SCR_COPY (1), - RADDR (sfbr), + NADDR (msgout), NADDR (lastmsg), /* ** If it was no ABORT message ... @@ -2873,23 +2829,16 @@ */ SCR_JUMP, PADDR (dispatch), -}/*------------------------< BADGETCC >---------------------*/,{ - /* - ** If SIGP was set, clear it and try again. - */ - SCR_FROM_REG (ctest2), - 0, - SCR_JUMP ^ IFTRUE (MASK (CSIGP,CSIGP)), - PADDRH (getcc2), - SCR_INT, - SIR_SENSE_FAILED, -}/*-------------------------< RESELECT >--------------------*/,{ +}/*-------------------------< IDLE >------------------------*/,{ /* + ** Nothing to do? + ** Wait for reselect. ** This NOP will be patched with LED OFF ** SCR_REG_REG (gpreg, SCR_OR, 0x01) */ SCR_NO_OP, 0, +}/*-------------------------< RESELECT >--------------------*/,{ /* ** make the DSA invalid. */ @@ -2897,6 +2846,8 @@ 0, SCR_CLR (SCR_TRG), 0, + SCR_LOAD_REG (HS_REG, HS_IN_RESELECT), + 0, /* ** Sleep waiting for a reselection. ** If SIGP is set, special treatment. @@ -2904,8 +2855,8 @@ ** Zu allem bereit .. */ SCR_WAIT_RESEL, - PADDR(reselect2), -}/*-------------------------< RESELECT1 >--------------------*/,{ + PADDR(start), +}/*-------------------------< RESELECTED >------------------*/,{ /* ** This NOP will be patched with LED ON ** SCR_REG_REG (gpreg, SCR_AND, 0xfe) @@ -2927,38 +2878,51 @@ */ SCR_REG_SFBR (ssid, SCR_AND, 0x8F), 0, - SCR_TO_REG (ctest0), + SCR_TO_REG (sdid), 0, SCR_JUMP, NADDR (jump_tcb), -}/*-------------------------< RESELECT2 >-------------------*/,{ + +}/*-------------------------< RESEL_DSA >-------------------*/,{ /* - ** This NOP will be patched with LED ON - ** SCR_REG_REG (gpreg, SCR_AND, 0xfe) + ** Ack the IDENTIFY or TAG previously received. */ - SCR_NO_OP, + SCR_CLR (SCR_ACK), 0, /* - ** If it's not connected :( - ** -> interrupted by SIGP bit. - ** Jump to start. + ** The ncr doesn't have an indirect load + ** or store command. So we have to + ** copy part of the control block to a + ** fixed place, where we can access it. + ** + ** We patch the address part of a + ** COPY command with the DSA-register. + */ + SCR_COPY_F (4), + RADDR (dsa), + PADDR (loadpos1), + /* + ** then we do the actual copy. + */ + SCR_COPY (sizeof (struct head)), + /* + ** continued after the next label ... */ - SCR_FROM_REG (ctest2), - 0, - SCR_JUMP ^ IFTRUE (MASK (CSIGP,CSIGP)), - PADDR (start), - SCR_JUMP, - PADDR (reselect), -}/*-------------------------< RESEL_TMP >-------------------*/,{ +}/*-------------------------< LOADPOS1 >-------------------*/,{ + 0, + NADDR (header), +#ifdef SCSI_NCR_PROFILE_SUPPORT /* - ** The return address in TEMP - ** is in fact the data structure address, - ** so copy it to the DSA register. + ** Set a time stamp for this reselection + */ + SCR_COPY (sizeof (u_long)), + KVAR(SCRIPT_KVAR_JIFFIES), + NADDR (header.stamp.reselect), +#endif + /* + ** The DSA contains the data structure address. */ - SCR_COPY (4), - RADDR (temp), - RADDR (dsa), SCR_JUMP, PADDR (prepare), @@ -2968,133 +2932,111 @@ ** to get an IDENTIFY message ** Wait for a msg_in phase. */ -/*<<<*/ SCR_JUMPR ^ IFFALSE (WHEN (SCR_MSG_IN)), - 48, + SCR_INT ^ IFFALSE (WHEN (SCR_MSG_IN)), + SIR_RESEL_NO_MSG_IN, /* - ** message phase - ** It's not a sony, it's a trick: - ** read the data without acknowledging it. + ** message phase. + ** Read the data directly from the BUS DATA lines. + ** This helps to support very old SCSI devices that + ** may reselect without sending an IDENTIFY. */ SCR_FROM_REG (sbdl), 0, -/*<<<*/ SCR_JUMPR ^ IFFALSE (MASK (M_IDENTIFY, 0x98)), - 32, - /* - ** It WAS an Identify message. - ** get it and ack it! - */ - SCR_MOVE_ABS (1) ^ SCR_MSG_IN, - NADDR (msgin), - SCR_CLR (SCR_ACK), - 0, /* - ** Mask out the lun. + ** It should be an Identify message. */ - SCR_REG_REG (sfbr, SCR_AND, 0x07), - 0, - SCR_RETURN, - 0, - /* - ** No message phase or no IDENTIFY message: - ** return 0. - */ -/*>>>*/ SCR_LOAD_SFBR (0), - 0, SCR_RETURN, 0, - }/*-------------------------< RESEL_TAG >-------------------*/,{ /* - ** come back to this point - ** to get a SIMPLE_TAG message - ** Wait for a MSG_IN phase. + ** Read IDENTIFY + SIMPLE + TAG using a single MOVE. + ** Agressive optimization, is'nt it? + ** No need to test the SIMPLE TAG message, since the + ** driver only supports conformant devices for tags. ;-) */ -/*<<<*/ SCR_JUMPR ^ IFFALSE (WHEN (SCR_MSG_IN)), - 64, + SCR_MOVE_ABS (3) ^ SCR_MSG_IN, + NADDR (msgin), /* - ** message phase - ** It's a trick - read the data - ** without acknowledging it. + ** Read the TAG from the SIDL. + ** Still an aggressive optimization. ;-) + ** Compute the CCB indirect jump address which + ** is (#TAG*2 & 0xfc) due to tag numbering using + ** 1,3,5..MAXTAGS*2+1 actual values. */ - SCR_FROM_REG (sbdl), + SCR_REG_SFBR (sidl, SCR_SHL, 0), 0, -/*<<<*/ SCR_JUMPR ^ IFFALSE (DATA (M_SIMPLE_TAG)), - 48, - /* - ** It WAS a SIMPLE_TAG message. - ** get it and ack it! - */ - SCR_MOVE_ABS (1) ^ SCR_MSG_IN, - NADDR (msgin), - SCR_CLR (SCR_ACK), + SCR_SFBR_REG (temp, SCR_AND, 0xfc), 0, - /* - ** Wait for the second byte (the tag) - */ -/*<<<*/ SCR_JUMPR ^ IFFALSE (WHEN (SCR_MSG_IN)), - 24, - /* - ** Get it and ack it! - */ - SCR_MOVE_ABS (1) ^ SCR_MSG_IN, - NADDR (msgin), - SCR_CLR (SCR_ACK|SCR_CARRY), +}/*-------------------------< JUMP_TO_NEXUS >-------------------*/,{ + SCR_COPY_F (4), + RADDR (temp), + PADDR (nexus_indirect), + SCR_COPY (4), +}/*-------------------------< NEXUS_INDIRECT >-------------------*/,{ 0, + RADDR (temp), SCR_RETURN, 0, +}/*-------------------------< RESEL_NOTAG >-------------------*/,{ /* - ** No message phase or no SIMPLE_TAG message - ** or no second byte: return 0. + ** No tag expected. + ** Read an throw away the IDENTIFY. */ -/*>>>*/ SCR_LOAD_SFBR (0), - 0, - SCR_SET (SCR_CARRY), - 0, - SCR_RETURN, - 0, - -}/*-------------------------< DATA_IO >--------------------*/,{ -/* -** Because Linux does not provide xfer data direction -** to low-level scsi drivers, we must trust the target -** for actual data direction when we cannot guess it. -** The programmed interrupt patches savep, lastp, goalp, -** etc.., and restarts the scsi script at data_out/in. -*/ - SCR_INT ^ IFTRUE (WHEN (SCR_DATA_OUT)), - SIR_DATA_IO_IS_OUT, - SCR_INT ^ IFTRUE (WHEN (SCR_DATA_IN)), - SIR_DATA_IO_IS_IN, + SCR_MOVE_ABS (1) ^ SCR_MSG_IN, + NADDR (msgin), SCR_JUMP, - PADDR (no_data), - + PADDR (jump_to_nexus), }/*-------------------------< DATA_IN >--------------------*/,{ /* ** Because the size depends on the -** #define MAX_SCATTER parameter, +** #define MAX_SCATTERL parameter, ** it is filled in at runtime. ** -** ##===========< i=0; i========= +** ##===========< i=0; i========= ** || SCR_CALL ^ IFFALSE (WHEN (SCR_DATA_IN)), -** || PADDR (checkatn), +** || PADDR (dispatch), ** || SCR_MOVE_TBL ^ SCR_DATA_IN, ** || offsetof (struct dsb, data[ i]), ** ##========================================== ** -** SCR_CALL, -** PADDR (checkatn), -** SCR_JUMP, -** PADDR (no_data), +**--------------------------------------------------------- */ 0 +}/*-------------------------< DATA_IN2 >-------------------*/,{ + SCR_CALL, + PADDR (dispatch), + SCR_JUMP, + PADDR (no_data), +}/*-------------------------< DATA_OUT >--------------------*/,{ +/* +** Because the size depends on the +** #define MAX_SCATTERL parameter, +** it is filled in at runtime. +** +** ##===========< i=0; i========= +** || SCR_CALL ^ IFFALSE (WHEN (SCR_DATA_OUT)), +** || PADDR (dispatch), +** || SCR_MOVE_TBL ^ SCR_DATA_OUT, +** || offsetof (struct dsb, data[ i]), +** ##========================================== +** +**--------------------------------------------------------- +*/ +0 +}/*-------------------------< DATA_OUT2 >-------------------*/,{ + SCR_CALL, + PADDR (dispatch), + SCR_JUMP, + PADDR (no_data), }/*--------------------------------------------------------*/ }; static struct scripth scripth0 __initdata = { /*-------------------------< TRYLOOP >---------------------*/{ /* -** Load an entry of the start queue into dsa -** and try to start it by jumping to TRYSEL. +** Start the next entry. +** Called addresses point to the launch script in the CCB. +** They are patched by the main processor. ** ** Because the size depends on the ** #define MAX_START parameter, it is filled @@ -3103,32 +3045,142 @@ **----------------------------------------------------------- ** ** ##===========< I=0; i=========== -** || SCR_COPY (4), -** || NADDR (squeue[i]), -** || RADDR (dsa), ** || SCR_CALL, -** || PADDR (trysel), +** || PADDR (idle), ** ##========================================== ** -** SCR_JUMP, -** PADDRH(tryloop), +**----------------------------------------------------------- +*/ +0 +}/*------------------------< TRYLOOP2 >---------------------*/,{ + SCR_JUMP, + PADDRH(tryloop), + +#ifdef SCSI_NCR_CCB_DONE_SUPPORT + +}/*------------------------< DONE_QUEUE >-------------------*/,{ +/* +** Copy the CCB address to the next done entry. +** Because the size depends on the +** #define MAX_DONE parameter, it is filled +** in at runtime. +** +**----------------------------------------------------------- +** +** ##===========< I=0; i=========== +** || SCR_COPY (sizeof(ccb_p)), +** || NADDR (header.cp), +** || NADDR (ccb_done[i]), +** || SCR_CALL, +** || PADDR (done_end), +** ##========================================== ** **----------------------------------------------------------- */ 0 -},/*-------------------------< MSG_PARITY >---------------*/{ +}/*------------------------< DONE_QUEUE2 >------------------*/,{ + SCR_JUMP, + PADDRH (done_queue), + +#endif /* SCSI_NCR_CCB_DONE_SUPPORT */ +}/*------------------------< SELECT_NO_ATN >-----------------*/,{ /* - ** count it + ** Set Initiator mode. + ** And try to select this target without ATN. */ - SCR_REG_REG (PS_REG, SCR_ADD, 0x01), + + SCR_CLR (SCR_TRG), + 0, + SCR_LOAD_REG (HS_REG, HS_SELECTING), + 0, + SCR_SEL_TBL ^ offsetof (struct dsb, select), + PADDR (reselect), + SCR_JUMP, + PADDR (select2), + +}/*-------------------------< CANCEL >------------------------*/,{ + + SCR_LOAD_REG (scratcha, HS_ABORTED), + 0, + SCR_JUMPR, + 8, +}/*-------------------------< SKIP >------------------------*/,{ + SCR_LOAD_REG (scratcha, 0), + 0, + /* + ** This entry has been canceled. + ** Next time use the next slot. + */ + SCR_COPY (4), + RADDR (temp), + PADDR (startpos), + /* + ** The ncr doesn't have an indirect load + ** or store command. So we have to + ** copy part of the control block to a + ** fixed place, where we can access it. + ** + ** We patch the address part of a + ** COPY command with the DSA-register. + */ + SCR_COPY_F (4), + RADDR (dsa), + PADDRH (skip2), + /* + ** then we do the actual copy. + */ + SCR_COPY (sizeof (struct head)), + /* + ** continued after the next label ... + */ +}/*-------------------------< SKIP2 >---------------------*/,{ + 0, + NADDR (header), + /* + ** Initialize the status registers + */ + SCR_COPY (4), + NADDR (header.status), + RADDR (scr0), + /* + ** Force host status. + */ + SCR_FROM_REG (scratcha), + 0, + SCR_JUMPR ^ IFFALSE (MASK (0, HS_DONEMASK)), + 16, + SCR_REG_REG (HS_REG, SCR_OR, HS_SKIPMASK), + 0, + SCR_JUMPR, + 8, + SCR_TO_REG (HS_REG), + 0, + SCR_LOAD_REG (SS_REG, S_GOOD), 0, + SCR_JUMP, + PADDR (cleanup_ok), + +},/*-------------------------< PAR_ERR_DATA_IN >---------------*/{ + /* + ** Ignore all data in byte, until next phase + */ + SCR_JUMP ^ IFFALSE (WHEN (SCR_DATA_IN)), + PADDRH (par_err_other), + SCR_MOVE_ABS (1) ^ SCR_DATA_IN, + NADDR (scratch), + SCR_JUMPR, + -24, +},/*-------------------------< PAR_ERR_OTHER >------------------*/{ /* - ** send a "message parity error" message. + ** count it. */ - SCR_LOAD_REG (scratcha, M_PARITY), + SCR_REG_REG (PS_REG, SCR_ADD, 0x01), 0, + /* + ** jump to dispatcher. + */ SCR_JUMP, - PADDR (setmsg), + PADDR (dispatch), }/*-------------------------< MSG_REJECT >---------------*/,{ /* ** If a negotiation was in progress, @@ -3160,17 +3212,6 @@ SCR_MOVE_ABS (1) ^ SCR_MSG_IN, NADDR (msgin[1]), /* - ** Check for message parity error. - */ - SCR_TO_REG (scratcha), - 0, - SCR_FROM_REG (socl), - 0, - SCR_JUMP ^ IFTRUE (MASK (CATN, CATN)), - PADDRH (msg_parity), - SCR_FROM_REG (scratcha), - 0, - /* ** Size is 0 .. ignore message. */ SCR_JUMP ^ IFTRUE (DATA (0)), @@ -3178,14 +3219,14 @@ /* ** Size is not 1 .. have to interrupt. */ -/*<<<*/ SCR_JUMPR ^ IFFALSE (DATA (1)), + SCR_JUMPR ^ IFFALSE (DATA (1)), 40, /* ** Check for residue byte in swide register */ SCR_FROM_REG (scntl2), 0, -/*<<<*/ SCR_JUMPR ^ IFFALSE (MASK (WSR, WSR)), + SCR_JUMPR ^ IFFALSE (MASK (WSR, WSR)), 16, /* ** There IS data in the swide register. @@ -3198,9 +3239,9 @@ /* ** Load again the size to the sfbr register. */ -/*>>>*/ SCR_FROM_REG (scratcha), + SCR_FROM_REG (scratcha), 0, -/*>>>*/ SCR_INT, + SCR_INT, SIR_IGN_RESIDUE, SCR_JUMP, PADDR (clrack), @@ -3219,17 +3260,6 @@ SCR_MOVE_ABS (1) ^ SCR_MSG_IN, NADDR (msgin[1]), /* - ** Check for message parity error. - */ - SCR_TO_REG (scratcha), - 0, - SCR_FROM_REG (socl), - 0, - SCR_JUMP ^ IFTRUE (MASK (CATN, CATN)), - PADDRH (msg_parity), - SCR_FROM_REG (scratcha), - 0, - /* */ SCR_JUMP ^ IFTRUE (DATA (3)), PADDRH (msg_ext_3), @@ -3245,17 +3275,6 @@ */ SCR_MOVE_ABS (1) ^ SCR_MSG_IN, NADDR (msgin[2]), - /* - ** Check for message parity error. - */ - SCR_TO_REG (scratcha), - 0, - SCR_FROM_REG (socl), - 0, - SCR_JUMP ^ IFTRUE (MASK (CATN, CATN)), - PADDRH (msg_parity), - SCR_FROM_REG (scratcha), - 0, SCR_JUMP ^ IFTRUE (DATA (M_X_WIDE_REQ)), PADDRH (msg_wdtr), /* @@ -3273,10 +3292,6 @@ */ SCR_MOVE_ABS (1) ^ SCR_MSG_IN, NADDR (msgin[3]), - SCR_FROM_REG (socl), - 0, - SCR_JUMP ^ IFTRUE (MASK (CATN, CATN)), - PADDRH (msg_parity), /* ** let the host do the real work. */ @@ -3290,17 +3305,17 @@ SCR_CLR (SCR_ACK), 0, +/* CHECK THE SOURCE FOR 'send_wdtr' IF YOU INTEND TO CHANGE SOMETHING HERE */ SCR_INT ^ IFFALSE (WHEN (SCR_MSG_OUT)), SIR_NEGO_PROTO, +}/*-------------------------< SEND_WDTR >----------------*/,{ /* ** Send the M_X_WIDE_REQ */ SCR_MOVE_ABS (4) ^ SCR_MSG_OUT, NADDR (msgout), - SCR_CLR (SCR_ATN), - 0, SCR_COPY (1), - RADDR (sfbr), + NADDR (msgout), NADDR (lastmsg), SCR_JUMP, PADDR (msg_out_done), @@ -3315,17 +3330,6 @@ */ SCR_MOVE_ABS (1) ^ SCR_MSG_IN, NADDR (msgin[2]), - /* - ** Check for message parity error. - */ - SCR_TO_REG (scratcha), - 0, - SCR_FROM_REG (socl), - 0, - SCR_JUMP ^ IFTRUE (MASK (CATN, CATN)), - PADDRH (msg_parity), - SCR_FROM_REG (scratcha), - 0, SCR_JUMP ^ IFTRUE (DATA (M_X_SYNC_REQ)), PADDRH (msg_sdtr), /* @@ -3344,10 +3348,6 @@ */ SCR_MOVE_ABS (2) ^ SCR_MSG_IN, NADDR (msgin[3]), - SCR_FROM_REG (socl), - 0, - SCR_JUMP ^ IFTRUE (MASK (CATN, CATN)), - PADDRH (msg_parity), /* ** let the host do the real work. */ @@ -3361,17 +3361,17 @@ SCR_CLR (SCR_ACK), 0, +/* CHECK THE SOURCE FOR 'send_sdtr' IF YOU INTEND TO CHANGE SOMETHING HERE */ SCR_INT ^ IFFALSE (WHEN (SCR_MSG_OUT)), SIR_NEGO_PROTO, +}/*-------------------------< SEND_SDTR >-------------*/,{ /* ** Send the M_X_SYNC_REQ */ SCR_MOVE_ABS (5) ^ SCR_MSG_OUT, NADDR (msgout), - SCR_CLR (SCR_ATN), - 0, SCR_COPY (1), - RADDR (sfbr), + NADDR (msgout), NADDR (lastmsg), SCR_JUMP, PADDR (msg_out_done), @@ -3396,203 +3396,259 @@ SCR_JUMP, PADDR (cleanup), -}/*-------------------------< GETCC >-----------------------*/,{ +}/*-------------------------< HDATA_IN >-------------------*/,{ +/* +** Because the size depends on the +** #define MAX_SCATTERH parameter, +** it is filled in at runtime. +** +** ##==< i=MAX_SCATTERL; i== +** || SCR_CALL ^ IFFALSE (WHEN (SCR_DATA_IN)), +** || PADDR (dispatch), +** || SCR_MOVE_TBL ^ SCR_DATA_IN, +** || offsetof (struct dsb, data[ i]), +** ##=================================================== +** +**--------------------------------------------------------- +*/ +0 +}/*-------------------------< HDATA_IN2 >------------------*/,{ + SCR_JUMP, + PADDR (data_in), + +}/*-------------------------< HDATA_OUT >-------------------*/,{ +/* +** Because the size depends on the +** #define MAX_SCATTERH parameter, +** it is filled in at runtime. +** +** ##==< i=MAX_SCATTERL; i== +** || SCR_CALL ^ IFFALSE (WHEN (SCR_DATA_OUT)), +** || PADDR (dispatch), +** || SCR_MOVE_TBL ^ SCR_DATA_OUT, +** || offsetof (struct dsb, data[ i]), +** ##=================================================== +** +**--------------------------------------------------------- +*/ +0 +}/*-------------------------< HDATA_OUT2 >------------------*/,{ + SCR_JUMP, + PADDR (data_out), + +}/*-------------------------< RESET >----------------------*/,{ /* - ** The ncr doesn't have an indirect load - ** or store command. So we have to - ** copy part of the control block to a - ** fixed place, where we can modify it. - ** - ** We patch the address part of a COPY command - ** with the address of the dsa register ... + ** Send a M_RESET message if bad IDENTIFY + ** received on reselection. */ - SCR_COPY_F (4), - RADDR (dsa), - PADDRH (getcc1), + SCR_LOAD_REG (scratcha, M_ABORT_TAG), + 0, + SCR_JUMP, + PADDRH (abort_resel), +}/*-------------------------< ABORTTAG >-------------------*/,{ /* - ** ... then we do the actual copy. + ** Abort a wrong tag received on reselection. */ - SCR_COPY (sizeof (struct head)), -}/*-------------------------< GETCC1 >----------------------*/,{ + SCR_LOAD_REG (scratcha, M_ABORT_TAG), 0, - NADDR (header), + SCR_JUMP, + PADDRH (abort_resel), +}/*-------------------------< ABORT >----------------------*/,{ /* - ** Initialize the status registers + ** Abort a reselection when no active CCB. */ - SCR_COPY (4), - NADDR (header.status), - RADDR (scr0), -}/*-------------------------< GETCC2 >----------------------*/,{ + SCR_LOAD_REG (scratcha, M_ABORT), + 0, +}/*-------------------------< ABORT_RESEL >----------------*/,{ + SCR_COPY (1), + RADDR (scratcha), + NADDR (msgout), + SCR_SET (SCR_ATN), + 0, + SCR_CLR (SCR_ACK), + 0, /* - ** Get the condition code from a target. - ** - ** DSA points to a data structure. - ** Set TEMP to the script location - ** that receives the condition code. - ** - ** Because there is no script command - ** to load a longword into a register, - ** we use a CALL command. + ** and send it. + ** we expect an immediate disconnect */ -/*<<<*/ SCR_CALLR, - 24, + SCR_REG_REG (scntl2, SCR_AND, 0x7f), + 0, + SCR_MOVE_ABS (1) ^ SCR_MSG_OUT, + NADDR (msgout), + SCR_COPY (1), + NADDR (msgout), + NADDR (lastmsg), + SCR_CLR (SCR_ACK|SCR_ATN), + 0, + SCR_WAIT_DISC, + 0, + SCR_JUMP, + PADDR (start), +}/*-------------------------< RESEND_IDENT >-------------------*/,{ /* - ** Get the condition code. + ** The target stays in MSG OUT phase after having acked + ** Identify [+ Tag [+ Extended message ]]. Targets shall + ** behave this way on parity error. + ** We must send it again all the messages. */ + SCR_SET (SCR_ATN), /* Shall be asserted 2 deskew delays before the */ + 0, /* 1rst ACK = 90 ns. Hope the NCR is'nt too fast */ + SCR_JUMP, + PADDR (send_ident), +}/*-------------------------< CLRATN_GO_ON >-------------------*/,{ + SCR_CLR (SCR_ATN), + 0, + SCR_JUMP, +}/*-------------------------< NXTDSP_GO_ON >-------------------*/,{ + 0, +}/*-------------------------< SDATA_IN >-------------------*/,{ + SCR_CALL ^ IFFALSE (WHEN (SCR_DATA_IN)), + PADDR (dispatch), SCR_MOVE_TBL ^ SCR_DATA_IN, offsetof (struct dsb, sense), - /* - ** No data phase may follow! - */ SCR_CALL, - PADDR (checkatn), + PADDR (dispatch), SCR_JUMP, PADDR (no_data), -/*>>>*/ - +}/*-------------------------< DATA_IO >--------------------*/,{ /* - ** The CALL jumps to this point. - ** Prepare for a RESTORE_POINTER message. - ** Save the TEMP register into the saved pointer. + ** We jump here if the data direction was unknown at the + ** time we had to queue the command to the scripts processor. + ** Pointers had been set as follow in this situation: + ** savep --> DATA_IO + ** lastp --> start pointer when DATA_IN + ** goalp --> goal pointer when DATA_IN + ** wlastp --> start pointer when DATA_OUT + ** wgoalp --> goal pointer when DATA_OUT + ** This script sets savep/lastp/goalp according to the + ** direction chosen by the target. */ - SCR_COPY (4), - RADDR (temp), - NADDR (header.savep), + SCR_JUMPR ^ IFTRUE (WHEN (SCR_DATA_OUT)), + 32, /* - ** Load scratcha, because in case of a selection timeout, - ** the host will expect a new value for startpos in - ** the scratcha register. + ** Direction is DATA IN. + ** Warning: we jump here, even when phase is DATA OUT. */ SCR_COPY (4), - PADDR (startpos), - RADDR (scratcha), -#ifdef NCR_GETCC_WITHMSG - /* - ** If QUIRK_NOMSG is set, select without ATN. - ** and don't send a message. - */ - SCR_FROM_REG (QU_REG), - 0, - SCR_JUMP ^ IFTRUE (MASK (QUIRK_NOMSG, QUIRK_NOMSG)), - PADDRH(getcc3), - /* - ** Then try to connect to the target. - ** If we are reselected, special treatment - ** of the current job is required before - ** accepting the reselection. - */ - SCR_SEL_TBL_ATN ^ offsetof (struct dsb, select), - PADDR(badgetcc), + NADDR (header.lastp), + NADDR (header.savep), + /* - ** save target id. + ** Jump to the SCRIPTS according to actual direction. */ - SCR_FROM_REG (sdid), - 0, - SCR_TO_REG (ctest0), + SCR_COPY (4), + NADDR (header.savep), + RADDR (temp), + SCR_RETURN, 0, /* - ** Send the IDENTIFY message. - ** In case of short transfer, remove ATN. + ** Direction is DATA OUT. */ - SCR_MOVE_TBL ^ SCR_MSG_OUT, - offsetof (struct dsb, smsg2), - SCR_CLR (SCR_ATN), - 0, - /* - ** save the first byte of the message. + SCR_COPY (4), + NADDR (header.wlastp), + NADDR (header.lastp), + SCR_COPY (4), + NADDR (header.wgoalp), + NADDR (header.goalp), + SCR_JUMPR, + -64, +}/*-------------------------< BAD_IDENTIFY >---------------*/,{ + /* + ** If message phase but not an IDENTIFY, + ** get some help from the C code. + ** Old SCSI device may behave so. */ - SCR_COPY (1), - RADDR (sfbr), - NADDR (lastmsg), + SCR_JUMPR ^ IFTRUE (MASK (0x80, 0x80)), + 16, + SCR_INT, + SIR_RESEL_NO_IDENTIFY, SCR_JUMP, - PADDR (prepare2), - -#endif -}/*-------------------------< GETCC3 >----------------------*/,{ + PADDRH (reset), /* - ** Try to connect to the target. - ** If we are reselected, special treatment - ** of the current job is required before - ** accepting the reselection. - ** - ** Silly target won't accept a message. - ** Select without ATN. + ** Message is an IDENTIFY, but lun is unknown. + ** Read the message, since we got it directly + ** from the SCSI BUS data lines. + ** Signal problem to C code for logging the event. + ** Send a M_ABORT to clear all pending tasks. */ - SCR_SEL_TBL ^ offsetof (struct dsb, select), - PADDR(badgetcc), + SCR_INT, + SIR_RESEL_BAD_LUN, + SCR_MOVE_ABS (1) ^ SCR_MSG_IN, + NADDR (msgin), + SCR_JUMP, + PADDRH (abort), +}/*-------------------------< BAD_I_T_L >------------------*/,{ /* - ** save target id. + ** We donnot have a task for that I_T_L. + ** Signal problem to C code for logging the event. + ** Send a M_ABORT message. */ - SCR_FROM_REG (sdid), - 0, - SCR_TO_REG (ctest0), - 0, + SCR_INT, + SIR_RESEL_BAD_I_T_L, + SCR_JUMP, + PADDRH (abort), +}/*-------------------------< BAD_I_T_L_Q >----------------*/,{ /* - ** Force error if selection timeout + ** We donnot have a task that matches the tag. + ** Signal problem to C code for logging the event. + ** Send a M_ABORTTAG message. */ - SCR_JUMPR ^ IFTRUE (WHEN (SCR_MSG_IN)), - 0, + SCR_INT, + SIR_RESEL_BAD_I_T_L_Q, + SCR_JUMP, + PADDRH (aborttag), +}/*-------------------------< BAD_TARGET >-----------------*/,{ /* - ** don't negotiate. + ** We donnot know the target that reselected us. + ** Grab the first message if any (IDENTIFY). + ** Signal problem to C code for logging the event. + ** M_RESET message. */ + SCR_INT, + SIR_RESEL_BAD_TARGET, + SCR_JUMPR ^ IFFALSE (WHEN (SCR_MSG_IN)), + 8, + SCR_MOVE_ABS (1) ^ SCR_MSG_IN, + NADDR (msgin), SCR_JUMP, - PADDR (prepare2), - -}/*-------------------------< DATA_OUT >-------------------*/,{ -/* -** Because the size depends on the -** #define MAX_SCATTER parameter, -** it is filled in at runtime. -** -** ##===========< i=0; i========= -** || SCR_CALL ^ IFFALSE (WHEN (SCR_DATA_OUT)), -** || PADDR (dispatch), -** || SCR_MOVE_TBL ^ SCR_DATA_OUT, -** || offsetof (struct dsb, data[ i]), -** ##========================================== -** -** SCR_CALL, -** PADDR (dispatch), -** SCR_JUMP, -** PADDR (no_data), -** -**--------------------------------------------------------- -*/ -0 -}/*-------------------------< ABORTTAG >-------------------*/,{ + PADDRH (reset), +}/*-------------------------< BAD_STATUS >-----------------*/,{ /* - ** Abort a bad reselection. - ** Set the message to ABORT vs. ABORT_TAG + ** If command resulted in either QUEUE FULL, + ** CHECK CONDITION or COMMAND TERMINATED, + ** call the C code. */ - SCR_LOAD_REG (scratcha, M_ABORT_TAG), - 0, - SCR_JUMPR ^ IFFALSE (CARRYSET), - 8, -}/*-------------------------< ABORT >----------------------*/,{ - SCR_LOAD_REG (scratcha, M_ABORT), + SCR_INT ^ IFTRUE (DATA (S_QUEUE_FULL)), + SIR_BAD_STATUS, + SCR_INT ^ IFTRUE (DATA (S_CHECK_COND)), + SIR_BAD_STATUS, + SCR_INT ^ IFTRUE (DATA (S_TERMINATED)), + SIR_BAD_STATUS, + SCR_RETURN, 0, - SCR_COPY (1), +}/*-------------------------< START_RAM >-------------------*/,{ + /* + ** Load the script into on-chip RAM, + ** and jump to start point. + */ + SCR_COPY_F (4), RADDR (scratcha), - NADDR (msgout), - SCR_SET (SCR_ATN), - 0, - SCR_CLR (SCR_ACK), + PADDRH (start_ram0), + SCR_COPY (sizeof (struct script)), +}/*-------------------------< START_RAM0 >--------------------*/,{ 0, + PADDR (start), + SCR_JUMP, + PADDR (start), +}/*-------------------------< STO_RESTART >-------------------*/,{ /* - ** and send it. - ** we expect an immediate disconnect + ** + ** Repair start queue (e.g. next time use the next slot) + ** and jump to start point. */ - SCR_REG_REG (scntl2, SCR_AND, 0x7f), - 0, - SCR_MOVE_ABS (1) ^ SCR_MSG_OUT, - NADDR (msgout), - SCR_COPY (1), - RADDR (sfbr), - NADDR (lastmsg), - SCR_CLR (SCR_ACK|SCR_ATN), - 0, - SCR_WAIT_DISC, - 0, + SCR_COPY (4), + RADDR (temp), + PADDR (startpos), SCR_JUMP, PADDR (start), }/*-------------------------< SNOOPTEST >-------------------*/,{ @@ -3641,48 +3697,63 @@ p = scrh->tryloop; for (i=0; itryloop + sizeof (scrh->tryloop)); - p = scr->data_in; +#ifdef SCSI_NCR_CCB_DONE_SUPPORT - for (i=0; idone_queue; + for (i = 0; idone_queue+sizeof(scrh->done_queue)); + +#endif /* SCSI_NCR_CCB_DONE_SUPPORT */ + + p = scrh->hdata_in; + for (i=0; ihdata_in + sizeof (scrh->hdata_in)); - *p++ =SCR_CALL; - *p++ =PADDR (checkatn); - *p++ =SCR_JUMP; - *p++ =PADDR (no_data); - + p = scr->data_in; + for (i=MAX_SCATTERH; idata_in + sizeof (scr->data_in)); - p = scrh->data_out; - - for (i=0; ihdata_out; + for (i=0; ihdata_out + sizeof (scrh->hdata_out)); - *p++ =SCR_CALL; - *p++ =PADDR (dispatch); - *p++ =SCR_JUMP; - *p++ =PADDR (no_data); + p = scr->data_out; + for (i=MAX_SCATTERH; idata_out + sizeof (scrh->data_out)); + assert ((u_long)p == (u_long)&scr->data_out + sizeof (scr->data_out)); } /*========================================================== @@ -3719,13 +3790,13 @@ */ if (opcode == 0) { - printf ("%s: ERROR0 IN SCRIPT at %d.\n", + printk (KERN_ERR "%s: ERROR0 IN SCRIPT at %d.\n", ncr_name(np), (int) (src-start-1)); - DELAY (1000000); + MDELAY (1000); }; if (DEBUG_FLAGS & DEBUG_SCRIPT) - printf ("%p: <%x>\n", + printk (KERN_DEBUG "%p: <%x>\n", (src-1), (unsigned)opcode); /* @@ -3745,9 +3816,9 @@ if ((tmp2 & RELOC_MASK) == RELOC_KVAR) tmp2 = 0; if ((tmp1 ^ tmp2) & 3) { - printf ("%s: ERROR1 IN SCRIPT at %d.\n", + printk (KERN_ERR"%s: ERROR1 IN SCRIPT at %d.\n", ncr_name(np), (int) (src-start-1)); - DELAY (1000000); + MDELAY (1000); } /* ** If PREFETCH feature not enabled, remove @@ -3769,7 +3840,7 @@ case 0x8: /* ** JUMP / CALL - ** don't relocate if relative :-) + ** dont't relocate if relative :-) */ if (opcode & 0x00800000) relocs = 0; @@ -3795,7 +3866,8 @@ switch (old & RELOC_MASK) { case RELOC_REGISTER: - new = (old & ~RELOC_MASK) + np->paddr; + new = (old & ~RELOC_MASK) + + bus_dvma_to_mem(np->paddr); break; case RELOC_LABEL: new = (old & ~RELOC_MASK) + np->p_script; @@ -3833,9 +3905,6 @@ *dst++ = cpu_to_scr(*src++); }; - if (bootverbose > 1 && opchanged) - printf("%s: NO FLUSH bit removed from %d script instructions\n", - ncr_name(np), opchanged); } /*========================================================== @@ -3858,31 +3927,37 @@ struct host_data { struct ncb *ncb; - char ncb_align[NCB_ALIGN_SIZE-1]; /* Filler for alignment */ + char ncb_align[CACHE_LINE_SIZE-1]; /* Filler for alignment */ struct ncb _ncb_data; - char ccb_align[CCB_ALIGN_SIZE-1]; /* Filler for alignment */ + char ccb_align[CACHE_LINE_SIZE-1]; /* Filler for alignment */ struct ccb _ccb_data; - char scr_align[SCR_ALIGN_SIZE-1]; /* Filler for alignment */ + char scr_align[CACHE_LINE_SIZE-1]; /* Filler for alignment */ struct script script_data; struct scripth scripth_data; }; /* -** Print something which allow to retrieve the controler type, unit, +** Print something which allows to retrieve the controler type, unit, ** target, lun concerned by a kernel message. */ -#define PRINT_LUN(np, target, lun) \ -printf(KERN_INFO "%s-<%d,%d>: ", ncr_name(np), (int) (target), (int) (lun)) +static void PRINT_TARGET(ncb_p np, int target) +{ + printk(KERN_INFO "%s-<%d,*>: ", ncr_name(np), target); +} + +static void PRINT_LUN(ncb_p np, int target, int lun) +{ + printk(KERN_INFO "%s-<%d,%d>: ", ncr_name(np), target, lun); +} static void PRINT_ADDR(Scsi_Cmnd *cmd) { struct host_data *host_data = (struct host_data *) cmd->host->hostdata; - ncb_p np = host_data->ncb; - if (np) PRINT_LUN(np, cmd->target, cmd->lun); + PRINT_LUN(host_data->ncb, cmd->target, cmd->lun); } /*========================================================== @@ -3989,8 +4064,6 @@ if (tn->flags & TEKRAM_TAGGED_COMMANDS) { tp->usrtags = 2 << nvram->max_tags_index; - if (tp->usrtags > SCSI_NCR_MAX_TAGS) - tp->usrtags = SCSI_NCR_MAX_TAGS; } if (!(tn->flags & TEKRAM_DISCONNECT_ENABLE)) @@ -4053,8 +4126,7 @@ * Divisor to be used for async (timer pre-scaler). */ i = np->clock_divn - 1; - while (i >= 0) { - --i; + while (--i >= 0) { if (10ul * SCSI_NCR_MIN_ASYNC * np->clock_khz > div_10M[i]) { ++i; break; @@ -4246,7 +4318,7 @@ #endif tp->usrsync = driver_setup.default_sync; tp->usrwide = driver_setup.max_wide; - tp->usrtags = driver_setup.default_tags; + tp->usrtags = SCSI_NCR_MAX_TAGS; if (!driver_setup.disconnection) np->target[i].usrflag = UF_NODISC; } @@ -4257,7 +4329,7 @@ */ i = nvram ? nvram->type : 0; - printf(KERN_INFO "%s: %sID %d, Fast-%d%s%s\n", ncr_name(np), + printk(KERN_INFO "%s: %sID %d, Fast-%d%s%s\n", ncr_name(np), i == SCSI_NCR_SYMBIOS_NVRAM ? "Symbios format NVRAM, " : (i == SCSI_NCR_TEKRAM_NVRAM ? "Tekram format NVRAM, " : ""), np->myaddr, @@ -4266,19 +4338,19 @@ (np->rv_stest2 & 0x20) ? ", Differential" : ""); if (bootverbose > 1) { - printf ("%s: initial SCNTL3/DMODE/DCNTL/CTEST3/4/5 = " + printk (KERN_INFO "%s: initial SCNTL3/DMODE/DCNTL/CTEST3/4/5 = " "(hex) %02x/%02x/%02x/%02x/%02x/%02x\n", ncr_name(np), np->sv_scntl3, np->sv_dmode, np->sv_dcntl, np->sv_ctest3, np->sv_ctest4, np->sv_ctest5); - printf ("%s: final SCNTL3/DMODE/DCNTL/CTEST3/4/5 = " + printk (KERN_INFO "%s: final SCNTL3/DMODE/DCNTL/CTEST3/4/5 = " "(hex) %02x/%02x/%02x/%02x/%02x/%02x\n", ncr_name(np), np->rv_scntl3, np->rv_dmode, np->rv_dcntl, np->rv_ctest3, np->rv_ctest4, np->rv_ctest5); } if (bootverbose && np->paddr2) - printf (KERN_INFO "%s: on-board RAM at 0x%lx\n", + printk (KERN_INFO "%s: on-chip RAM at 0x%lx\n", ncr_name(np), np->paddr2); return 0; @@ -4294,17 +4366,18 @@ int i; /* display Symbios nvram host data */ - printf("%s: HOST ID=%d%s%s%s%s\n", + printk(KERN_DEBUG "%s: HOST ID=%d%s%s%s%s%s\n", ncr_name(np), nvram->host_id & 0x0f, (nvram->flags & SYMBIOS_SCAM_ENABLE) ? " SCAM" :"", (nvram->flags & SYMBIOS_PARITY_ENABLE) ? " PARITY" :"", - (nvram->flags & SYMBIOS_VERBOSE_MSGS) ? " VERSBOSE" :"", + (nvram->flags & SYMBIOS_VERBOSE_MSGS) ? " VERBOSE" :"", + (nvram->flags & SYMBIOS_CHS_MAPPING) ? " CHS_ALT" :"", (nvram->flags1 & SYMBIOS_SCAN_HI_LO) ? " HI_LO" :""); /* display Symbios nvram drive data */ for (i = 0 ; i < 15 ; i++) { struct Symbios_target *tn = &nvram->target[i]; - printf("%s-%d:%s%s%s%s WIDTH=%d SYNC=%d TMO=%d\n", + printk(KERN_DEBUG "%s-%d:%s%s%s%s WIDTH=%d SYNC=%d TMO=%d\n", ncr_name(np), i, (tn->flags & SYMBIOS_DISCONNECT_ENABLE) ? " DISC" : "", (tn->flags & SYMBIOS_SCAN_AT_BOOT_TIME) ? " SCAN_BOOT" : "", @@ -4337,7 +4410,8 @@ case 2: rem = " REMOVABLE=all"; break; } - printf("%s: HOST ID=%d%s%s%s%s%s%s%s%s%s BOOT DELAY=%d tags=%d\n", + printk(KERN_DEBUG + "%s: HOST ID=%d%s%s%s%s%s%s%s%s%s BOOT DELAY=%d tags=%d\n", ncr_name(np), nvram->host_id & 0x0f, (nvram->flags1 & SYMBIOS_SCAM_ENABLE) ? " SCAM" :"", (nvram->flags & TEKRAM_MORE_THAN_2_DRIVES) ? " >2DRIVES" :"", @@ -4355,7 +4429,7 @@ struct Tekram_target *tn = &nvram->target[i]; j = tn->sync_index & 0xf; sync = j < 12 ? Tekram_sync[j] : 255; - printf("%s-%d:%s%s%s%s%s%s PERIOD=%d\n", + printk(KERN_DEBUG "%s-%d:%s%s%s%s%s%s PERIOD=%d\n", ncr_name(np), i, (tn->flags & TEKRAM_PARITY_CHECK) ? " PARITY" : "", (tn->flags & TEKRAM_SYNC_NEGO) ? " SYNC" : "", @@ -4387,11 +4461,18 @@ struct Scsi_Host *instance = 0; u_long flags = 0; ncr_nvram *nvram = device->nvram; + int i; -printf(KERN_INFO "ncr53c%s-%d: rev=0x%02x, base=0x%x, io_port=0x%x, irq=%d\n", +#ifdef __sparc__ +printk(KERN_INFO "ncr53c%s-%d: rev=0x%02x, base=0x%lx, io_port=0x%lx, irq=%s\n", + device->chip.name, unit, device->chip.revision_id, device->slot.base, + device->slot.io_port, __irq_itoa(device->slot.irq)); +#else +printk(KERN_INFO "ncr53c%s-%d: rev=0x%02x, base=0x%lx, io_port=0x%lx, irq=%d\n", device->chip.name, unit, device->chip.revision_id, device->slot.base, device->slot.io_port, device->slot.irq); - +#endif + /* ** Allocate host_data structure */ @@ -4402,17 +4483,16 @@ ** Initialize structure. */ host_data = (struct host_data *) instance->hostdata; + bzero (host_data, sizeof(*host_data)); /* ** Align np and first ccb to 32 boundary for cache line ** bursting when copying the global header. */ - np = (ncb_p) (((u_long) &host_data->_ncb_data) & NCB_ALIGN_MASK); + np = (ncb_p) (((u_long) &host_data->_ncb_data) & CACHE_LINE_MASK); + NCR_INIT_LOCK_NCB(np); host_data->ncb = np; - bzero (np, sizeof (*np)); - - np->ccb = (ccb_p) (((u_long) &host_data->_ccb_data) & CCB_ALIGN_MASK); - bzero (np->ccb, sizeof (*np->ccb)); + np->ccb = (ccb_p) (((u_long) &host_data->_ccb_data) & CACHE_LINE_MASK); /* ** Store input informations in the host data structure. @@ -4428,8 +4508,8 @@ np->maxoffs = device->chip.offset_max; np->maxburst = device->chip.burst_max; - np->script0 = - (struct script *) (((u_long) &host_data->script_data) & SCR_ALIGN_MASK); + np->script0 = (struct script *) + (((u_long) &host_data->script_data) & CACHE_LINE_MASK); np->scripth0 = &host_data->scripth_data; /* @@ -4451,12 +4531,14 @@ #ifndef NCR_IOMAPPED np->vaddr = remap_pci_mem((u_long) np->paddr, (u_long) 128); if (!np->vaddr) { - printf("%s: can't map memory mapped IO region\n", ncr_name(np)); + printk(KERN_ERR + "%s: can't map memory mapped IO region\n",ncr_name(np)); goto attach_error; } else if (bootverbose > 1) - printf("%s: using memory mapped IO at virtual address 0x%lx\n", ncr_name(np), (u_long) np->vaddr); + printk(KERN_INFO + "%s: using memory mapped IO at virtual address 0x%lx\n", ncr_name(np), (u_long) np->vaddr); /* ** Make the controller's registers available. @@ -4491,7 +4573,7 @@ default: nvram = 0; #ifdef SCSI_NCR_DEBUG_NVRAM - printf("%s: NVRAM: None or invalid data.\n", ncr_name(np)); + printk(KERN_DEBUG "%s: NVRAM: None or invalid data.\n", ncr_name(np)); #endif } } @@ -4502,37 +4584,27 @@ */ (void)ncr_prepare_setting(np, nvram); -#ifndef NCR_IOMAPPED - if (np->paddr2 && sizeof(struct script) <= 4096) { - np->vaddr2 = remap_pci_mem((u_long) np->paddr2, (u_long) 4096); - if (!np->vaddr2) { - printf("%s: can't map memory mapped IO region\n", ncr_name(np)); - goto attach_error; - } - else - if (bootverbose > 1) - printf("%s: on-board ram mapped at virtual address 0x%lx\n", ncr_name(np), (u_long) np->vaddr2); + if (np->paddr2 && sizeof(struct script) > 4096) { + np->paddr2 = 0; + printk(KERN_WARNING "%s: script too large, NOT using on chip RAM.\n", + ncr_name(np)); } -#endif /* !defined NCR_IOMAPPED */ /* ** Fill Linux host instance structure */ -#if LINUX_VERSION_CODE >= LinuxVersionCode(1,3,0) instance->max_channel = 0; instance->max_id = np->maxwide ? 16 : 8; instance->max_lun = SCSI_NCR_MAX_LUN; -#endif #ifndef NCR_IOMAPPED instance->base = (char *) np->reg; #endif instance->irq = device->slot.irq; + instance->unique_id = device->slot.io_port; instance->io_port = device->slot.io_port; instance->n_io_port = 128; instance->dma_channel = 0; -#if LINUX_VERSION_CODE >= LinuxVersionCode(2,0,0) instance->select_queue_depths = ncr53c8xx_select_queue_depths; -#endif /* ** Patch script to physical addresses @@ -4542,8 +4614,7 @@ np->scripth = np->scripth0; np->p_scripth = vtophys(np->scripth); - np->script = (np->vaddr2) ? (struct script *) np->vaddr2 : np->script0; - np->p_script = (np->vaddr2) ? np->paddr2 : vtophys(np->script0); + np->p_script = (np->paddr2) ? bus_dvma_to_mem(np->paddr2) : vtophys(np->script0); ncr_script_copy_and_bind (np, (ncrcmd *) &script0, (ncrcmd *) np->script0, sizeof(struct script)); ncr_script_copy_and_bind (np, (ncrcmd *) &scripth0, (ncrcmd *) np->scripth0, sizeof(struct scripth)); @@ -4554,27 +4625,32 @@ */ if (np->features & FE_LED0) { - np->script0->reselect[0] = + np->script0->idle[0] = cpu_to_scr(SCR_REG_REG(gpreg, SCR_OR, 0x01)); - np->script0->reselect1[0] = + np->script0->reselected[0] = cpu_to_scr(SCR_REG_REG(gpreg, SCR_AND, 0xfe)); - np->script0->reselect2[0] = + np->script0->start[0] = cpu_to_scr(SCR_REG_REG(gpreg, SCR_AND, 0xfe)); } /* - ** init data structure - */ - - np->jump_tcb.l_cmd = cpu_to_scr(SCR_JUMP); - np->jump_tcb.l_paddr = cpu_to_scr(NCB_SCRIPTH_PHYS (np, abort)); + ** Look for the target control block of this nexus. + ** For i = 0 to 3 + ** JUMP ^ IFTRUE (MASK (i, 3)), @(next_lcb) + */ + for (i = 0 ; i < 4 ; i++) { + np->jump_tcb[i].l_cmd = + cpu_to_scr((SCR_JUMP ^ IFTRUE (MASK (i, 3)))); + np->jump_tcb[i].l_paddr = + cpu_to_scr(NCB_SCRIPTH_PHYS (np, bad_target)); + } /* ** Reset chip. */ OUTB (nc_istat, SRST); - DELAY (1000); + UDELAY (100); OUTB (nc_istat, 0 ); /* @@ -4582,34 +4658,45 @@ */ if (ncr_snooptest (np)) { - printf ("CACHE INCORRECTLY CONFIGURED.\n"); + printk (KERN_ERR "CACHE INCORRECTLY CONFIGURED.\n"); goto attach_error; }; /* ** Install the interrupt handler. */ -#if LINUX_VERSION_CODE >= LinuxVersionCode(1,3,70) -#ifdef SCSI_NCR_SHARE_IRQ +#ifdef SCSI_NCR_SHARE_IRQ +#define NCR_SA_INTERRUPT_FLAGS (SA_INTERRUPT | SA_SHIRQ) if (bootverbose > 1) - printf("%s: requesting shared irq %d (dev_id=0x%lx)\n", - ncr_name(np), device->slot.irq, (u_long) np); - if (request_irq(device->slot.irq, ncr53c8xx_intr, - SA_INTERRUPT|SA_SHIRQ, "ncr53c8xx", np)) { +#ifdef __sparc__ + printk(KERN_INFO "%s: requesting shared irq %s (dev_id=0x%lx)\n", + ncr_name(np), __irq_itoa(device->slot.irq), (u_long) np); #else - if (request_irq(device->slot.irq, ncr53c8xx_intr, - SA_INTERRUPT, "ncr53c8xx", np)) { + printk(KERN_INFO "%s: requesting shared irq %d (dev_id=0x%lx)\n", + ncr_name(np), device->slot.irq, (u_long) np); #endif #else +#define NCR_SA_INTERRUPT_FLAGS SA_INTERRUPT +#endif if (request_irq(device->slot.irq, ncr53c8xx_intr, - SA_INTERRUPT, "ncr53c8xx")) { + NCR_SA_INTERRUPT_FLAGS, "ncr53c8xx", np)) { +#ifdef __sparc__ + printk(KERN_ERR "%s: request irq %s failure\n", + ncr_name(np), __irq_itoa(device->slot.irq)); +#else + printk(KERN_ERR "%s: request irq %d failure\n", + ncr_name(np), device->slot.irq); #endif - printf("%s: request irq %d failure\n", ncr_name(np), device->slot.irq); goto attach_error; } np->irq = device->slot.irq; /* + ** Initialize the fixed part of the default ccb. + */ + ncr_init_ccb(np, np->ccb); + + /* ** After SCSI devices have been opened, we cannot ** reset the bus safely, so we do it here. ** Interrupt handler does the real work. @@ -4617,26 +4704,26 @@ ** if interrupts are not enabled yet. ** Then enable disconnects. */ - save_flags(flags); cli(); + NCR_LOCK_NCB(np, flags); if (ncr_reset_scsi_bus(np, 0, driver_setup.settle_delay) != 0) { - printf("%s: FATAL ERROR: CHECK SCSI BUS - CABLES, TERMINATION, DEVICE POWER etc.!\n", ncr_name(np)); - restore_flags(flags); + printk(KERN_ERR "%s: FATAL ERROR: CHECK SCSI BUS - CABLES, TERMINATION, DEVICE POWER etc.!\n", ncr_name(np)); + + NCR_UNLOCK_NCB(np, flags); goto attach_error; } ncr_exception (np); - restore_flags(flags); np->disc = 1; /* ** The middle-level SCSI driver does not - ** wait devices to settle. + ** wait for devices to settle. ** Wait synchronously if more than 2 seconds. */ if (driver_setup.settle_delay > 2) { - printf("%s: waiting %d seconds for scsi devices to settle...\n", + printk(KERN_INFO "%s: waiting %d seconds for scsi devices to settle...\n", ncr_name(np), driver_setup.settle_delay); - DELAY(1000000UL * driver_setup.settle_delay); + MDELAY (1000 * driver_setup.settle_delay); } /* @@ -4665,46 +4752,81 @@ first_host = instance; } + NCR_UNLOCK_NCB(np, flags); + return 0; attach_error: if (!instance) return -1; - printf("%s: detaching...\n", ncr_name(np)); + printk(KERN_INFO "%s: detaching...\n", ncr_name(np)); #ifndef NCR_IOMAPPED if (np->vaddr) { #ifdef DEBUG_NCR53C8XX - printf("%s: releasing memory mapped IO region %lx[%d]\n", ncr_name(np), (u_long) np->vaddr, 128); + printk(KERN_DEBUG "%s: releasing memory mapped IO region %lx[%d]\n", ncr_name(np), (u_long) np->vaddr, 128); #endif unmap_pci_mem((vm_offset_t) np->vaddr, (u_long) 128); } - if (np->vaddr2) { -#ifdef DEBUG_NCR53C8XX - printf("%s: releasing memory mapped IO region %lx[%d]\n", ncr_name(np), (u_long) np->vaddr2, 4096); -#endif - unmap_pci_mem((vm_offset_t) np->vaddr2, (u_long) 4096); - } -#endif +#endif /* !NCR_IOMAPPED */ if (np->port) { #ifdef DEBUG_NCR53C8XX - printf("%s: releasing IO region %x[%d]\n", ncr_name(np), np->port, 128); + printk(KERN_DEBUG "%s: releasing IO region %x[%d]\n", ncr_name(np), np->port, 128); #endif release_region(np->port, 128); } if (np->irq) { #ifdef DEBUG_NCR53C8XX - printf("%s: freeing irq %d\n", ncr_name(np), np->irq); -#endif -#if LINUX_VERSION_CODE >= LinuxVersionCode(1,3,70) - free_irq(np->irq, np); +#ifdef __sparc__ + printk(KERN_INFO "%s: freeing irq %s\n", ncr_name(np), + __irq_itoa(np->irq)); #else - free_irq(np->irq); + printk(KERN_INFO "%s: freeing irq %d\n", ncr_name(np), np->irq); +#endif #endif + free_irq(np->irq, np); } scsi_unregister(instance); return -1; } + +/*========================================================== +** +** +** Done SCSI commands list management. +** +** We donnot enter the scsi_done() callback immediately +** after a command has been seen as completed but we +** insert it into a list which is flushed outside any kind +** of driver critical section. +** This allows to do minimal stuff under interrupt and +** inside critical sections and to also avoid locking up +** on recursive calls to driver entry points under SMP. +** In fact, the only kernel point which is entered by the +** driver with a driver lock set is kmalloc(GFP_ATOMIC) +** that shall not reenter the driver under any circumstances, +** AFAIK. +** +**========================================================== +*/ +static inline void ncr_queue_done_cmd(ncb_p np, Scsi_Cmnd *cmd) +{ + cmd->host_scribble = (char *) np->done_list; + np->done_list = cmd; +} + +static inline void ncr_flush_done_cmds(Scsi_Cmnd *lcmd) +{ + Scsi_Cmnd *cmd; + + while (lcmd) { + cmd = lcmd; + lcmd = (Scsi_Cmnd *) cmd->host_scribble; + cmd->scsi_done(cmd); + } +} + + /*========================================================== ** ** @@ -4714,27 +4836,18 @@ ** **========================================================== */ -int ncr_queue_command (Scsi_Cmnd *cmd, void (* done)(Scsi_Cmnd *)) +int ncr_queue_command (ncb_p np, Scsi_Cmnd *cmd) { - struct Scsi_Host *host = cmd->host; /* Scsi_Device *device = cmd->device; */ - struct host_data *host_data = (struct host_data *) host->hostdata; - ncb_p np = host_data->ncb; tcb_p tp = &np->target[cmd->target]; - + lcb_p lp = tp->lp[cmd->lun]; ccb_p cp; - lcb_p lp; int segments; - u_char qidx, nego, idmsg, *msgptr; - u_int msglen, msglen2; - u_long flags; - int xfer_direction; - - cmd->scsi_done = done; - cmd->host_scribble = NULL; - cmd->SCp.ptr = NULL; - cmd->SCp.buffer = NULL; + u_char nego, idmsg, *msgptr; + u_int msglen; + int direction; + u_int32 lastp, goalp; /*--------------------------------------------- ** @@ -4764,7 +4877,7 @@ if (DEBUG_FLAGS & DEBUG_TINY) { PRINT_ADDR(cmd); - printf ("CMD=%x ", cmd->cmnd[0]); + printk ("CMD=%x ", cmd->cmnd[0]); } /*--------------------------------------------------- @@ -4777,8 +4890,6 @@ ** **---------------------------------------------------- */ - save_flags(flags); cli(); - if (np->settle_time && cmd->timeout_per_command >= HZ && np->settle_time > jiffies + cmd->timeout_per_command - HZ) { np->settle_time = jiffies + cmd->timeout_per_command - HZ; @@ -4786,7 +4897,6 @@ if (np->settle_time || !(cp=ncr_get_ccb (np, cmd->target, cmd->lun))) { insert_into_waiting_list(np, cmd); - restore_flags(flags); return(DID_OK); } cp->cmd = cmd; @@ -4797,10 +4907,12 @@ ** **---------------------------------------------------- */ - if (!tp->usrtags && cmd->device && cmd->device->tagged_queue) { - tp->usrtags = SCSI_NCR_MAX_TAGS; - ncr_setmaxtags (np, tp, SCSI_NCR_MAX_TAGS); +#if 0 /* This stuff was only usefull for linux-1.2.13 */ + if (lp && !lp->numtags && cmd->device && cmd->device->tagged_queue) { + lp->numtags = tp->usrtags; + ncr_setup_tags (np, cmd->target, cmd->lun); } +#endif /*--------------------------------------------------- ** @@ -4813,47 +4925,23 @@ cp->phys.header.stamp.start = jiffies; #endif - /*---------------------------------------------------- - ** - ** Get device quirks from a speciality table. - ** - ** @GENSCSI@ - ** This should be a part of the device table - ** in "scsi_conf.c". - ** - **---------------------------------------------------- - */ - if (tp->quirks & QUIRK_UPDATE) { - tp->quirks = ncr_lookup ((char*) &tp->inqdata[0]); -#ifndef NCR_GETCC_WITHMSG - if (tp->quirks) { - PRINT_ADDR(cmd); - printf ("quirks=%x.\n", tp->quirks); - } -#endif - } - /*--------------------------------------------------- ** ** negotiation required? ** - ** Only SCSI-II devices. - ** To negotiate with SCSI-I devices is dangerous, since - ** Synchronous Negotiation protocol is optional, and - ** INQUIRY data do not contains capabilities in byte 7. - **---------------------------------------------------- + **--------------------------------------------------- */ nego = 0; - if (cmd->lun == 0 && !tp->nego_cp && - (tp->inqdata[2] & 0x7) >= 2 && tp->inqdata[7]) { + if ((!tp->widedone || !tp->period) && !tp->nego_cp && tp->inq_done && lp) { + /* ** negotiate wide transfers ? */ if (!tp->widedone) { - if (tp->inqdata[7] & INQ7_WIDE16) { + if (tp->inq_byte7 & INQ7_WIDE16) { nego = NS_WIDE; } else tp->widedone=1; @@ -4864,17 +4952,13 @@ */ if (!nego && !tp->period) { - if ( 1 -#if defined (CDROM_ASYNC) - && ((tp->inqdata[0] & 0x1f) != 5) -#endif - && (tp->inqdata[7] & INQ7_SYNC)) { + if (tp->inq_byte7 & INQ7_SYNC) { nego = NS_SYNC; } else { tp->period =0xffff; tp->sval = 0xe0; - PRINT_ADDR(cmd); - printf ("asynchronous.\n"); + PRINT_TARGET(np, cmd->target); + printk ("SYNC transfers not supported.\n"); }; }; @@ -4888,33 +4972,6 @@ tp->nego_cp = cp; }; - /*--------------------------------------------------- - ** - ** choose a new tag ... - ** - **---------------------------------------------------- - */ - - if ((lp = tp->lp[cmd->lun]) && (lp->usetags)) { - /* - ** assign a tag to this ccb! - */ - while (!cp->tag) { - ccb_p cp2 = lp->next_ccb; - lp->lasttag = lp->lasttag % 255 + 1; - while (cp2 && cp2->tag != lp->lasttag) - cp2 = cp2->next_ccb; - if (cp2) continue; - cp->tag=lp->lasttag; - if (DEBUG_FLAGS & DEBUG_TAGS) { - PRINT_ADDR(cmd); - printf ("using tag #%d.\n", cp->tag); - } - } - } else { - cp->tag=0; - } - /*---------------------------------------------------- ** ** Build the identify / tag / sdtr message @@ -4924,44 +4981,54 @@ idmsg = M_IDENTIFY | cmd->lun; - if (cp != np->ccb && ((np->disc && !(tp->usrflag & UF_NODISC)) || cp->tag)) + if (cp ->tag != NO_TAG || + (cp != np->ccb && np->disc && !(tp->usrflag & UF_NODISC))) idmsg |= 0x40; msgptr = cp->scsi_smsg; msglen = 0; msgptr[msglen++] = idmsg; - if (cp->tag) { - char tag; + if (cp->tag != NO_TAG) { + char order = np->order; - tag = np->order; - if (tag == 0) { /* - ** Ordered write ops, unordered read ops. + ** Force ordered tag if necessary to avoid timeouts + ** and to preserve interactivity. */ - switch (cmd->cmnd[0]) { - case 0x08: /* READ_SMALL (6) */ - case 0x28: /* READ_BIG (10) */ - case 0xa8: /* READ_HUGE (12) */ - tag = M_SIMPLE_TAG; - break; - default: - tag = M_ORDERED_TAG; + if (lp && lp->tags_stime + (3*HZ) <= jiffies) { + if (lp->tags_smap) { + order = M_ORDERED_TAG; + if ((DEBUG_FLAGS & DEBUG_TAGS)||bootverbose>2){ + PRINT_ADDR(cmd); + printk("ordered tag forced.\n"); + } + } + lp->tags_stime = jiffies; + lp->tags_smap = lp->tags_umap; } - } - /* - ** Have to force ordered tag to avoid timeouts - */ - if ((lp = tp->lp[cmd->lun]) && (lp->force_ordered_tag)) { - tag = M_ORDERED_TAG; - lp->force_ordered_tag = 0; - if (DEBUG_FLAGS & DEBUG_TAGS) { - PRINT_ADDR(cmd); - printf ("Ordered Queue Tag forced\n"); + + if (order == 0) { + /* + ** Ordered write ops, unordered read ops. + */ + switch (cmd->cmnd[0]) { + case 0x08: /* READ_SMALL (6) */ + case 0x28: /* READ_BIG (10) */ + case 0xa8: /* READ_HUGE (12) */ + order = M_SIMPLE_TAG; + break; + default: + order = M_ORDERED_TAG; + } } - } - msgptr[msglen++] = tag; - msgptr[msglen++] = cp -> tag; + msgptr[msglen++] = order; + /* + ** Actual tags are numbered 1,3,5,..2*MAXTAGS+1, + ** since we may have to deal with devices that have + ** problems with #TAG 0 or too great #TAG numbers. + */ + msgptr[msglen++] = (cp->tag << 1) + 1; } switch (nego) { @@ -4973,9 +5040,9 @@ msgptr[msglen++] = tp->maxoffs; if (DEBUG_FLAGS & DEBUG_NEGO) { PRINT_ADDR(cp->cmd); - printf ("sync msgout: "); + printk ("sync msgout: "); ncr_show_msg (&cp->scsi_smsg [msglen-5]); - printf (".\n"); + printk (".\n"); }; break; case NS_WIDE: @@ -4985,25 +5052,15 @@ msgptr[msglen++] = tp->usrwide; if (DEBUG_FLAGS & DEBUG_NEGO) { PRINT_ADDR(cp->cmd); - printf ("wide msgout: "); + printk ("wide msgout: "); ncr_show_msg (&cp->scsi_smsg [msglen-4]); - printf (".\n"); + printk (".\n"); }; break; }; /*---------------------------------------------------- ** - ** Build the identify message for getcc. - ** - **---------------------------------------------------- - */ - - cp -> scsi_smsg2 [0] = idmsg; - msglen2 = 1; - - /*---------------------------------------------------- - ** ** Build the data descriptors ** **---------------------------------------------------- @@ -5012,8 +5069,7 @@ segments = ncr_scatter (cp, cp->cmd); if (segments < 0) { - ncr_free_ccb(np, cp, cmd->target, cmd->lun); - restore_flags(flags); + ncr_free_ccb(np, cp); return(DID_ERROR); } @@ -5024,20 +5080,24 @@ ** **---------------------------------------------------- */ - switch((int) cmd->cmnd[0]) { - case 0x08: /* READ(6) 08 */ - case 0x28: /* READ(10) 28 */ - case 0xA8: /* READ(12) A8 */ - xfer_direction = XferIn; - break; - case 0x0A: /* WRITE(6) 0A */ - case 0x2A: /* WRITE(10) 2A */ - case 0xAA: /* WRITE(12) AA */ - xfer_direction = XferOut; - break; - default: - xfer_direction = guess_xfer_direction((int) cmd->cmnd[0]); - break; + if (!cp->data_len) + direction = 0; + else { + switch((int) cmd->cmnd[0]) { + case 0x08: /* READ(6) 08 */ + case 0x28: /* READ(10) 28 */ + case 0xA8: /* READ(12) A8 */ + direction = XFER_IN; + break; + case 0x0A: /* WRITE(6) 0A */ + case 0x2A: /* WRITE(10) 2A */ + case 0xAA: /* WRITE(12) AA */ + direction = XFER_OUT; + break; + default: + direction = (XFER_IN|XFER_OUT); + break; + } } /*---------------------------------------------------- @@ -5047,36 +5107,64 @@ **---------------------------------------------------- */ - cp->segments = segments; - if (!cp->data_len) - xfer_direction = XferNone; + /* + ** Default to no data transfer. + */ + lastp = goalp = NCB_SCRIPT_PHYS (np, no_data); - switch (xfer_direction) { - u_long endp; - default: - case XferBoth: - cp->phys.header.savep = - cpu_to_scr(NCB_SCRIPT_PHYS (np, data_io)); - cp->phys.header.goalp = cp->phys.header.savep; - break; - case XferIn: - endp = NCB_SCRIPT_PHYS (np, data_in) + MAX_SCATTER*16; - cp->phys.header.goalp = cpu_to_scr(endp + 8); - cp->phys.header.savep = cpu_to_scr(endp - segments*16); - break; - case XferOut: - endp = NCB_SCRIPTH_PHYS (np, data_out) + MAX_SCATTER*16; - cp->phys.header.goalp = cpu_to_scr(endp + 8); - cp->phys.header.savep = cpu_to_scr(endp - segments*16); - break; - case XferNone: - cp->phys.header.savep = - cpu_to_scr(NCB_SCRIPT_PHYS (np, no_data)); - cp->phys.header.goalp = cp->phys.header.savep; - break; + /* + ** Compute data out pointers, if needed. + */ + if (direction & XFER_OUT) { + goalp = NCB_SCRIPT_PHYS (np, data_out2) + 8; + if (segments <= MAX_SCATTERL) + lastp = goalp - 8 - (segments * 16); + else { + lastp = NCB_SCRIPTH_PHYS (np, hdata_out2); + lastp -= (segments - MAX_SCATTERL) * 16; + } + /* + ** If actual data direction is unknown, save pointers + ** in header. The SCRIPTS will swap them to current + ** if target decision will be data out. + */ + if (direction & XFER_IN) { + cp->phys.header.wgoalp = cpu_to_scr(goalp); + cp->phys.header.wlastp = cpu_to_scr(lastp); + } } - cp->phys.header.lastp = cp->phys.header.savep; + /* + ** Compute data in pointers, if needed. + */ + if (direction & XFER_IN) { + goalp = NCB_SCRIPT_PHYS (np, data_in2) + 8; + if (segments <= MAX_SCATTERL) + lastp = goalp - 8 - (segments * 16); + else { + lastp = NCB_SCRIPTH_PHYS (np, hdata_in2); + lastp -= (segments - MAX_SCATTERL) * 16; + } + } + + /* + ** Set all pointers values needed by SCRIPTS. + ** If direction is unknown, start at data_io. + */ + cp->phys.header.lastp = cpu_to_scr(lastp); + cp->phys.header.goalp = cpu_to_scr(goalp); + + if ((direction & (XFER_IN|XFER_OUT)) == (XFER_IN|XFER_OUT)) + cp->phys.header.savep = + cpu_to_scr(NCB_SCRIPTH_PHYS (np, data_io)); + else + cp->phys.header.savep= cpu_to_scr(lastp); + + /* + ** Save the initial data pointer in order to be able + ** to redo the command. + */ + cp->startp = cp->phys.header.savep; /*---------------------------------------------------- ** @@ -5088,13 +5176,12 @@ ** physical -> virtual backlink ** Generic SCSI command */ - cp->phys.header.cp = cp; + /* ** Startqueue */ - cp->phys.header.launch.l_paddr = - cpu_to_scr(NCB_SCRIPT_PHYS (np, select)); - cp->phys.header.launch.l_cmd = cpu_to_scr(SCR_JUMP); + cp->start.schedule.l_paddr = cpu_to_scr(NCB_SCRIPT_PHYS (np, select)); + cp->restart.schedule.l_paddr = cpu_to_scr(NCB_SCRIPT_PHYS (np, resel_dsa)); /* ** select */ @@ -5107,30 +5194,12 @@ cp->phys.smsg.addr = cpu_to_scr(CCB_PHYS (cp, scsi_smsg)); cp->phys.smsg.size = cpu_to_scr(msglen); - cp->phys.smsg2.addr = cpu_to_scr(CCB_PHYS (cp, scsi_smsg2)); - cp->phys.smsg2.size = cpu_to_scr(msglen2); - /* - ** command - */ - cp->phys.cmd.addr = cpu_to_scr(vtophys (&cmd->cmnd[0])); - cp->phys.cmd.size = cpu_to_scr(cmd->cmd_len); - /* - ** sense command - */ - cp->phys.scmd.addr = cpu_to_scr(CCB_PHYS (cp, sensecmd)); - cp->phys.scmd.size = cpu_to_scr(6); - /* - ** patch requested size into sense command - */ - cp->sensecmd[0] = 0x03; - cp->sensecmd[1] = cmd->lun << 5; - cp->sensecmd[4] = sizeof(cmd->sense_buffer); /* - ** sense data + ** command */ - cp->phys.sense.addr = - cpu_to_scr(vtophys (&cmd->sense_buffer[0])); - cp->phys.sense.size = cpu_to_scr(sizeof(cmd->sense_buffer)); + cp->phys.cmd.addr = cpu_to_scr(vtophys (&cmd->cmnd[0])); + cp->phys.cmd.size = cpu_to_scr(cmd->cmd_len); + /* ** status */ @@ -5140,9 +5209,11 @@ cp->parity_status = 0; cp->xerr_status = XE_OK; - cp->sync_status = tp->sval; cp->nego_status = nego; +#if 0 + cp->sync_status = tp->sval; cp->wide_status = tp->wval; +#endif /*---------------------------------------------------- ** @@ -5152,56 +5223,96 @@ */ /* - ** reselect pattern and activate this job. + ** activate this job. */ - cp->jump_ccb.l_cmd = - cpu_to_scr((SCR_JUMP ^ IFFALSE (DATA (cp->tag)))); - /* Compute a time limit greater than the middle-level driver one */ if (cmd->timeout_per_command > 0) - cp->tlimit = jiffies + cmd->timeout_per_command + NCR_TIMEOUT_INCREASE; + cp->tlimit = jiffies + cmd->timeout_per_command + HZ; else - cp->tlimit = jiffies + 3600 * HZ; /* No timeout=one hour */ + cp->tlimit = jiffies + 86400 * HZ;/* No timeout=24 hours */ cp->magic = CCB_MAGIC; /* + ** insert next CCBs into start queue. + ** 2 max at a time is enough to flush the CCB wait queue. + */ + cp->auto_sense = 0; + if (lp) + ncr_start_next_ccb(np, lp, 2); + else + ncr_put_start_queue(np, cp); + + /* + ** Command is successfully queued. + */ + + return(DID_OK); +} + + +/*========================================================== +** +** +** Insert a CCB into the start queue and wake up the +** SCRIPTS processor. +** +** +**========================================================== +*/ + +static void ncr_start_next_ccb(ncb_p np, lcb_p lp, int maxn) +{ + XPT_QUEHEAD *qp; + ccb_p cp; + + if (lp->held_ccb) + return; + + while (maxn-- && lp->queuedccbs < lp->queuedepth) { + qp = xpt_remque_head(&lp->wait_ccbq); + if (!qp) + break; + ++lp->queuedccbs; + cp = xpt_que_entry(qp, struct ccb, link_ccbq); + xpt_insque_tail(qp, &lp->busy_ccbq); + lp->jump_ccb[cp->tag == NO_TAG ? 0 : cp->tag] = + cpu_to_scr(CCB_PHYS (cp, restart)); + ncr_put_start_queue(np, cp); + } +} + +static void ncr_put_start_queue(ncb_p np, ccb_p cp) +{ + u_short qidx; + + /* ** insert into start queue. */ + if (!np->squeueput) np->squeueput = 1; + qidx = np->squeueput + 2; + if (qidx >= MAX_START + MAX_START) qidx = 1; + + np->scripth->tryloop [qidx] = cpu_to_scr(NCB_SCRIPT_PHYS (np, idle)); + MEMORY_BARRIER(); + np->scripth->tryloop [np->squeueput] = cpu_to_scr(CCB_PHYS (cp, start)); - qidx = np->squeueput + 1; - if (qidx >= MAX_START) qidx=0; - np->squeue [qidx ] = cpu_to_scr(NCB_SCRIPT_PHYS (np, idle)); - np->squeue [np->squeueput] = cpu_to_scr(CCB_PHYS (cp, phys)); np->squeueput = qidx; + ++np->queuedccbs; + cp->queued = 1; - if(DEBUG_FLAGS & DEBUG_QUEUE) - printf ("%s: queuepos=%d tryoffset=%d.\n", ncr_name (np), - np->squeueput, - (unsigned)(scr_to_cpu(np->script->startpos[0]) - - (NCB_SCRIPTH_PHYS (np, tryloop)))); + if (DEBUG_FLAGS & DEBUG_QUEUE) + printk ("%s: queuepos=%d.\n", ncr_name (np), np->squeueput); /* ** Script processor may be waiting for reselect. ** Wake it up. */ -#ifdef SCSI_NCR_DEBUG_ERROR_RECOVERY_SUPPORT - if (!np->stalling) -#endif + MEMORY_BARRIER(); OUTB (nc_istat, SIGP); - - /* - ** and reenable interrupts - */ - restore_flags(flags); - - /* - ** Command is successfully queued. - */ - - return(DID_OK); } + /*========================================================== ** ** @@ -5214,18 +5325,13 @@ ** **========================================================== */ -static void ncr_start_reset(ncb_p np, int settle_delay) +static void ncr_start_reset(ncb_p np) { - u_long flags; - - save_flags(flags); cli(); - if (!np->settle_time) { - (void) ncr_reset_scsi_bus(np, 1, settle_delay); - } - restore_flags(flags); -} - + (void) ncr_reset_scsi_bus(np, 1, driver_setup.settle_delay); + } + } + static int ncr_reset_scsi_bus(ncb_p np, int enab_int, int settle_delay) { u_int32 term; @@ -5234,13 +5340,14 @@ np->settle_time = jiffies + settle_delay * HZ; if (bootverbose > 1) - printf("%s: resetting, " + printk("%s: resetting, " "command processing suspended for %d seconds\n", ncr_name(np), settle_delay); OUTB (nc_istat, SRST); - DELAY (1000); + UDELAY (100); OUTB (nc_istat, 0); + UDELAY (2000); /* The 895 needs time for the bus mode to settle */ if (enab_int) OUTW (nc_sien, RST); /* @@ -5250,7 +5357,7 @@ OUTB (nc_stest3, TE); OUTB (nc_dcntl, (np->rv_dcntl & IRQM)); OUTB (nc_scntl1, CRST); - DELAY (100); + UDELAY (200); if (!driver_setup.bus_check) goto out; @@ -5270,9 +5377,9 @@ term &= 0x3ffff; if (term != (2<<7)) { - printf("%s: suspicious SCSI data while resetting the BUS.\n", + printk("%s: suspicious SCSI data while resetting the BUS.\n", ncr_name(np)); - printf("%s: %sdp0,d7-0,rst,req,ack,bsy,sel,atn,msg,c/d,i/o = " + printk("%s: %sdp0,d7-0,rst,req,ack,bsy,sel,atn,msg,c/d,i/o = " "0x%lx, expecting 0x%lx\n", ncr_name(np), (np->features & FE_WIDE) ? "dp1,d15-8," : "", @@ -5294,27 +5401,16 @@ ** **========================================================== */ -int ncr_reset_bus (Scsi_Cmnd *cmd, int sync_reset) +int ncr_reset_bus (ncb_p np, Scsi_Cmnd *cmd, int sync_reset) { - struct Scsi_Host *host = cmd->host; /* Scsi_Device *device = cmd->device; */ - struct host_data *host_data = (struct host_data *) host->hostdata; - ncb_p np = host_data->ncb; ccb_p cp; - u_long flags; int found; -#ifdef SCSI_NCR_DEBUG_ERROR_RECOVERY_SUPPORT - if (np->stalling) - np->stalling = 0; -#endif - - save_flags(flags); cli(); /* * Return immediately if reset is in progress. */ if (np->settle_time) { - restore_flags(flags); return SCSI_RESET_PUNT; } /* @@ -5323,7 +5419,7 @@ * Commands will now be queued in the waiting list until a settle * delay of 2 seconds will be completed. */ - ncr_start_reset(np, driver_setup.settle_delay); + ncr_start_reset(np); /* * First, look in the wakeup list */ @@ -5358,11 +5454,9 @@ */ if (!found && sync_reset && !retrieve_from_waiting_list(0, np, cmd)) { cmd->result = ScsiResult(DID_RESET, 0); - cmd->scsi_done(cmd); + ncr_queue_done_cmd(np, cmd); } - restore_flags(flags); - return SCSI_RESET_SUCCESS; } @@ -5375,30 +5469,19 @@ ** **========================================================== */ -static int ncr_abort_command (Scsi_Cmnd *cmd) +static int ncr_abort_command (ncb_p np, Scsi_Cmnd *cmd) { - struct Scsi_Host *host = cmd->host; /* Scsi_Device *device = cmd->device; */ - struct host_data *host_data = (struct host_data *) host->hostdata; - ncb_p np = host_data->ncb; ccb_p cp; - u_long flags; int found; int retv; -#ifdef SCSI_NCR_DEBUG_ERROR_RECOVERY_SUPPORT - if (np->stalling == 2) - np->stalling = 0; -#endif - - save_flags(flags); cli(); /* * First, look for the scsi command in the waiting list */ if (remove_from_waiting_list(np, cmd)) { cmd->result = ScsiResult(DID_ABORT, 0); - cmd->scsi_done(cmd); - restore_flags(flags); + ncr_queue_done_cmd(np, cmd); return SCSI_ABORT_SUCCESS; } @@ -5417,45 +5500,45 @@ } if (!found) { - restore_flags(flags); return SCSI_ABORT_NOT_RUNNING; } if (np->settle_time) { - restore_flags(flags); return SCSI_ABORT_SNOOZE; } /* - ** Disable reselect. - ** Remove it from startqueue. - ** Set cp->tlimit to 0. The ncr_timeout() handler will use - ** this condition in order to complete the canceled command - ** after the script skipped the ccb, if necessary. - */ - cp->jump_ccb.l_cmd = cpu_to_scr(SCR_JUMP); - if (cp->phys.header.launch.l_paddr == - cpu_to_scr(NCB_SCRIPT_PHYS (np, select))) { - printf ("%s: abort ccb=%p (skip)\n", ncr_name (np), cp); - cp->phys.header.launch.l_paddr = - cpu_to_scr(NCB_SCRIPT_PHYS (np, skip)); - } + ** If the CCB is active, patch schedule jumps for the + ** script to abort the command. + */ cp->tlimit = 0; - retv = SCSI_ABORT_PENDING; + switch(cp->host_status) { + case HS_BUSY: + case HS_NEGOTIATE: + printk ("%s: abort ccb=%p (cancel)\n", ncr_name (np), cp); + cp->start.schedule.l_paddr = + cpu_to_scr(NCB_SCRIPTH_PHYS (np, cancel)); + retv = SCSI_ABORT_PENDING; + break; + case HS_DISCONNECT: + cp->restart.schedule.l_paddr = + cpu_to_scr(NCB_SCRIPTH_PHYS (np, abort)); + retv = SCSI_ABORT_PENDING; + break; + default: + retv = SCSI_ABORT_NOT_RUNNING; + break; + + } /* ** If there are no requests, the script ** processor will sleep on SEL_WAIT_RESEL. ** Let's wake it up, since it may have to work. */ -#ifdef SCSI_NCR_DEBUG_ERROR_RECOVERY_SUPPORT - if (!np->stalling) -#endif OUTB (nc_istat, SIGP); - restore_flags(flags); - return retv; } @@ -5479,7 +5562,7 @@ int target, lun; int i; - printf("%s: releasing host resources\n", ncr_name(np)); + printk("%s: releasing host resources\n", ncr_name(np)); /* ** Stop the ncr_timeout process @@ -5487,12 +5570,12 @@ */ #ifdef DEBUG_NCR53C8XX - printf("%s: stopping the timer\n", ncr_name(np)); + printk("%s: stopping the timer\n", ncr_name(np)); #endif np->release_stage = 1; - for (i = 50 ; i && np->release_stage != 2 ; i--) DELAY(100000); + for (i = 50 ; i && np->release_stage != 2 ; i--) MDELAY (100); if (np->release_stage != 2) - printf("%s: the timer seems to be already stopped\n", ncr_name(np)); + printk("%s: the timer seems to be already stopped\n", ncr_name(np)); else np->release_stage = 2; /* @@ -5500,7 +5583,7 @@ */ #ifdef DEBUG_NCR53C8XX - printf("%s: disabling chip interrupts\n", ncr_name(np)); + printk("%s: disabling chip interrupts\n", ncr_name(np)); #endif OUTW (nc_sien , 0); OUTB (nc_dien , 0); @@ -5510,22 +5593,22 @@ */ #ifdef DEBUG_NCR53C8XX - printf("%s: freeing irq %d\n", ncr_name(np), np->irq); -#endif -#if LINUX_VERSION_CODE >= LinuxVersionCode(1,3,70) - free_irq(np->irq, np); +#ifdef __sparc__ + printk("%s: freeing irq %s\n", ncr_name(np), __irq_itoa(np->irq)); #else - free_irq(np->irq); + printk("%s: freeing irq %d\n", ncr_name(np), np->irq); #endif +#endif + free_irq(np->irq, np); /* ** Reset NCR chip ** Restore bios setting for automatic clock detection. */ - printf("%s: resetting chip\n", ncr_name(np)); + printk("%s: resetting chip\n", ncr_name(np)); OUTB (nc_istat, SRST); - DELAY (1000); + UDELAY (100); OUTB (nc_istat, 0 ); OUTB(nc_dmode, np->sv_dmode); @@ -5544,17 +5627,13 @@ #ifndef NCR_IOMAPPED #ifdef DEBUG_NCR53C8XX - printf("%s: releasing memory mapped IO region %lx[%d]\n", ncr_name(np), (u_long) np->vaddr, 128); + printk("%s: releasing memory mapped IO region %lx[%d]\n", ncr_name(np), (u_long) np->vaddr, 128); #endif unmap_pci_mem((vm_offset_t) np->vaddr, (u_long) 128); -#ifdef DEBUG_NCR53C8XX - printf("%s: releasing memory mapped IO region %lx[%d]\n", ncr_name(np), (u_long) np->vaddr2, 4096); -#endif - unmap_pci_mem((vm_offset_t) np->vaddr2, (u_long) 4096); -#endif +#endif /* !NCR_IOMAPPED */ #ifdef DEBUG_NCR53C8XX - printf("%s: releasing IO region %x[%d]\n", ncr_name(np), np->port, 128); + printk("%s: releasing IO region %x[%d]\n", ncr_name(np), np->port, 128); #endif release_region(np->port, 128); @@ -5565,11 +5644,11 @@ while ((cp=np->ccb->link_ccb) != NULL) { np->ccb->link_ccb = cp->link_ccb; if (cp->host_status) { - printf("%s: shall free an active ccb (host_status=%d)\n", + printk("%s: shall free an active ccb (host_status=%d)\n", ncr_name(np), cp->host_status); } #ifdef DEBUG_NCR53C8XX - printf("%s: freeing ccb (%lx)\n", ncr_name(np), (u_long) cp); + printk("%s: freeing ccb (%lx)\n", ncr_name(np), (u_long) cp); #endif m_free(cp, sizeof(*cp)); } @@ -5584,14 +5663,16 @@ lp = tp->lp[lun]; if (lp) { #ifdef DEBUG_NCR53C8XX - printf("%s: freeing lp (%lx)\n", ncr_name(np), (u_long) lp); + printk("%s: freeing lp (%lx)\n", ncr_name(np), (u_long) lp); #endif + if (lp->jump_ccb != &lp->jump_ccb_0) + m_free(lp->jump_ccb, 256); m_free(lp, sizeof(*lp)); } } } - printf("%s: host resources successfully released\n", ncr_name(np)); + printk("%s: host resources successfully released\n", ncr_name(np)); return 1; } @@ -5617,20 +5698,8 @@ ** Sanity check */ - if (!cp || (cp->magic!=CCB_MAGIC) || !cp->cmd) return; - cp->magic = 1; - cp->tlimit= 0; - cmd = cp->cmd; - - /* - ** No Reselect anymore. - */ - cp->jump_ccb.l_cmd = cpu_to_scr(SCR_JUMP); - - /* - ** No starting. - */ - cp->phys.header.launch.l_paddr = cpu_to_scr(NCB_SCRIPT_PHYS (np, idle)); + if (!cp || cp->magic != CCB_MAGIC || !cp->cmd) + return; /* ** timestamp @@ -5641,9 +5710,13 @@ #endif if (DEBUG_FLAGS & DEBUG_TINY) - printf ("CCB=%lx STAT=%x/%x\n", (unsigned long)cp & 0xfff, + printk ("CCB=%lx STAT=%x/%x\n", (unsigned long)cp & 0xfff, cp->host_status,cp->scsi_status); + /* + ** Get command, target and lun pointers. + */ + cmd = cp->cmd; cp->cmd = NULL; tp = &np->target[cmd->target]; @@ -5659,17 +5732,32 @@ tp->nego_cp = 0; /* + ** If auto-sense performed, change scsi status. + */ + if (cp->auto_sense) { + cp->scsi_status = cp->auto_sense; + } + + /* + ** If we were recovering from queue full or performing + ** auto-sense, requeue skipped CCBs to the wait queue. + */ + + if (lp && lp->held_ccb) { + if (cp == lp->held_ccb) { + xpt_que_splice(&lp->skip_ccbq, &lp->wait_ccbq); + xpt_que_init(&lp->skip_ccbq); + lp->held_ccb = 0; + } + } + + /* ** Check for parity errors. */ - if (cp->parity_status) { + if (cp->parity_status > 1) { PRINT_ADDR(cmd); - printf ("%d parity error(s), fallback.\n", cp->parity_status); - /* - ** fallback to asynch transfer. - */ - tp->usrsync=255; - tp->period = 0; + printk ("%d parity error(s).\n",cp->parity_status); } /* @@ -5680,13 +5768,13 @@ PRINT_ADDR(cmd); switch (cp->xerr_status) { case XE_EXTRA_DATA: - printf ("extraneous data discarded.\n"); + printk ("extraneous data discarded.\n"); break; case XE_BAD_PHASE: - printf ("illegal scsi phase (4/5).\n"); + printk ("illegal scsi phase (4/5).\n"); break; default: - printf ("extended error %d.\n", cp->xerr_status); + printk ("extended error %d.\n", cp->xerr_status); break; } if (cp->host_status==HS_COMPLETE) @@ -5694,95 +5782,70 @@ } /* + ** Print out any error for debugging purpose. + */ + if (DEBUG_FLAGS & (DEBUG_RESULT|DEBUG_TINY)) { + if (cp->host_status!=HS_COMPLETE || cp->scsi_status!=S_GOOD) { + PRINT_ADDR(cmd); + printk ("ERROR: cmd=%x host_status=%x scsi_status=%x\n", + cmd->cmnd[0], cp->host_status, cp->scsi_status); + } + } + + /* ** Check the status. */ if ( (cp->host_status == HS_COMPLETE) && (cp->scsi_status == S_GOOD || cp->scsi_status == S_COND_MET)) { - /* + /* ** All went well (GOOD status). ** CONDITION MET status is returned on - ** `Pre-Fetch' or `Search data' success. - */ + ** `Pre-Fetch' or `Search data' success. + */ cmd->result = ScsiResult(DID_OK, cp->scsi_status); /* - ** if (cp->phys.header.lastp != cp->phys.header.goalp)... - ** ** @RESID@ ** Could dig out the correct value for resid, ** but it would be quite complicated. - ** - ** The ah1542.c driver sets it to 0 too ... */ + /* if (cp->phys.header.lastp != cp->phys.header.goalp) */ /* - ** Try to assign a ccb to this nexus + ** Allocate the lcb if not yet. */ - ncr_alloc_ccb (np, cmd->target, cmd->lun); + if (!lp) + ncr_alloc_lcb (np, cmd->target, cmd->lun); /* - ** On inquire cmd (0x12) save some data. - ** Clear questionnable capacities. + ** On standard INQUIRY response (EVPD and CmDt + ** not set), setup logical unit according to + ** announced capabilities (we need the 1rst 7 bytes). */ - if (cmd->lun == 0 && cmd->cmnd[0] == 0x12) { - if (np->unit < SCSI_NCR_MAX_HOST) { - if (driver_setup.force_sync_nego) - ((char *) cmd->request_buffer)[7] |= INQ7_SYNC; - else - ((char *) cmd->request_buffer)[7] &= - (target_capabilities[np->unit].and_map[cmd->target]); - } - bcopy ( cmd->request_buffer, - &tp->inqdata, - sizeof (tp->inqdata)); - - /* - ** set number of tags - */ - ncr_setmaxtags (np, tp, driver_setup.default_tags); - /* - ** prepare negotiation of synch and wide. - */ - ncr_negotiate (np, tp); - - /* - ** force quirks update before next command start - */ - tp->quirks |= QUIRK_UPDATE; + if (cmd->cmnd[0] == 0x12 && !(cmd->cmnd[1] & 0x3) && + cmd->cmnd[4] >= 7) { + ncr_setup_lcb (np, cmd->target, cmd->lun, + (char *) cmd->request_buffer); } - /* - ** Announce changes to the generic driver. - */ - if (lp) { - ncr_settags (tp, lp); - if (lp->reqlink != lp->actlink) - ncr_opennings (np, lp, cmd); - }; - tp->bytes += cp->data_len; tp->transfers ++; /* ** If tags was reduced due to queue full, - ** increase tags if 100 good status received. + ** increase tags if 1000 good status received. */ - if (tp->numtags < tp->maxtags) { - ++tp->num_good; - if (tp->num_good >= 100) { - tp->num_good = 0; - ++tp->numtags; - if (tp->numtags == 1) { - PRINT_ADDR(cmd); - printf("tagged command queueing resumed\n"); - } + if (lp && lp->usetags && lp->numtags < lp->maxtags) { + ++lp->num_good; + if (lp->num_good >= 1000) { + lp->num_good = 0; + ++lp->numtags; + ncr_setup_tags (np, cmd->target, cmd->lun); } } } else if ((cp->host_status == HS_COMPLETE) - && (cp->scsi_status == (S_SENSE|S_GOOD) || - cp->scsi_status == (S_SENSE|S_CHECK_COND))) { - + && (cp->scsi_status == S_CHECK_COND)) { /* ** Check condition code */ @@ -5791,43 +5854,21 @@ if (DEBUG_FLAGS & (DEBUG_RESULT|DEBUG_TINY)) { u_char * p = (u_char*) & cmd->sense_buffer; int i; - printf ("\n%s: sense data:", ncr_name (np)); - for (i=0; i<14; i++) printf (" %x", *p++); - printf (".\n"); + PRINT_ADDR(cmd); + printk ("sense data:"); + for (i=0; i<14; i++) printk (" %x", *p++); + printk (".\n"); } } else if ((cp->host_status == HS_COMPLETE) && (cp->scsi_status == S_BUSY || - cp->scsi_status == S_CONFLICT)) { + cp->scsi_status == S_QUEUE_FULL)) { /* ** Target is busy. */ cmd->result = ScsiResult(DID_OK, cp->scsi_status); - } else if ((cp->host_status == HS_COMPLETE) - && (cp->scsi_status == S_QUEUE_FULL)) { - - /* - ** Target is stuffed. - */ - cmd->result = ScsiResult(DID_OK, cp->scsi_status); - - /* - ** Suspend tagged queuing and start good status counter. - ** Announce changes to the generic driver. - */ - if (tp->numtags) { - PRINT_ADDR(cmd); - printf("QUEUE FULL! suspending tagged command queueing\n"); - tp->numtags = 0; - tp->num_good = 0; - if (lp) { - ncr_settags (tp, lp); - if (lp->reqlink != lp->actlink) - ncr_opennings (np, lp, cmd); - }; - } } else if ((cp->host_status == HS_SEL_TIMEOUT) || (cp->host_status == HS_TIMEOUT)) { @@ -5856,7 +5897,7 @@ ** Other protocol messes */ PRINT_ADDR(cmd); - printf ("COMMAND FAILED (%x %x) @%p.\n", + printk ("COMMAND FAILED (%x %x) @%p.\n", cp->host_status, cp->scsi_status, cp); cmd->result = ScsiResult(DID_ERROR, cp->scsi_status); @@ -5870,43 +5911,51 @@ u_char * p; int i; PRINT_ADDR(cmd); - printf (" CMD:"); + printk (" CMD:"); p = (u_char*) &cmd->cmnd[0]; - for (i=0; icmd_len; i++) printf (" %x", *p++); + for (i=0; icmd_len; i++) printk (" %x", *p++); if (cp->host_status==HS_COMPLETE) { switch (cp->scsi_status) { case S_GOOD: - printf (" GOOD"); + printk (" GOOD"); break; case S_CHECK_COND: - printf (" SENSE:"); + printk (" SENSE:"); p = (u_char*) &cmd->sense_buffer; for (i=0; i<14; i++) - printf (" %x", *p++); + printk (" %x", *p++); break; default: - printf (" STAT: %x\n", cp->scsi_status); + printk (" STAT: %x\n", cp->scsi_status); break; } - } else printf (" HOSTERROR: %x", cp->host_status); - printf ("\n"); + } else printk (" HOSTERROR: %x", cp->host_status); + printk ("\n"); } /* ** Free this ccb */ - ncr_free_ccb (np, cp, cmd->target, cmd->lun); + ncr_free_ccb (np, cp); + + /* + ** requeue awaiting scsi commands for this lun. + */ + if (lp && lp->queuedccbs < lp->queuedepth && + !xpt_que_empty(&lp->wait_ccbq)) + ncr_start_next_ccb(np, lp, 2); /* - ** requeue awaiting scsi commands + ** requeue awaiting scsi commands for this controller. */ - if (np->waiting_list) requeue_waiting_list(np); + if (np->waiting_list) + requeue_waiting_list(np); /* ** signal completion to generic driver. */ - cmd->scsi_done (cmd); + ncr_queue_done_cmd(np, cmd); } /*========================================================== @@ -5918,41 +5967,92 @@ **========================================================== */ -void ncr_wakeup (ncb_p np, u_long code) +/* +** This CCB has been skipped by the NCR. +** Queue it in the correponding unit queue. +*/ +void ncr_ccb_skipped(ncb_p np, ccb_p cp) { - /* - ** Starting at the default ccb and following - ** the links, complete all jobs with a - ** host_status greater than "disconnect". - ** - ** If the "code" parameter is not zero, - ** complete all jobs that are not IDLE. - */ + tcb_p tp = &np->target[cp->target]; + lcb_p lp = tp->lp[cp->lun]; - ccb_p cp = np->ccb; - while (cp) { - switch (cp->host_status) { + if (lp && cp != np->ccb) { + cp->host_status &= ~HS_SKIPMASK; + cp->start.schedule.l_paddr = + cpu_to_scr(NCB_SCRIPT_PHYS (np, select)); + xpt_remque(&cp->link_ccbq); + xpt_insque_tail(&cp->link_ccbq, &lp->skip_ccbq); + if (cp->queued) { + --lp->queuedccbs; + } + } + if (cp->queued) { + --np->queuedccbs; + cp->queued = 0; + } +} + +/* +** The NCR has completed CCBs. +** Look at the DONE QUEUE if enabled, otherwise scan all CCBs +*/ +void ncr_wakeup_done (ncb_p np) +{ + ccb_p cp; +#ifdef SCSI_NCR_CCB_DONE_SUPPORT + int i, j; - case HS_IDLE: + i = np->ccb_done_ic; + while (1) { + j = i+1; + if (j >= MAX_DONE) + j = 0; + + cp = np->ccb_done[j]; + if (!CCB_DONE_VALID(cp)) break; - case HS_DISCONNECT: - if(DEBUG_FLAGS & DEBUG_TINY) printf ("D"); - /* fall through */ - - case HS_BUSY: - case HS_NEGOTIATE: - if (!code) break; - cp->host_status = code; + np->ccb_done[j] = (ccb_p) CCB_DONE_EMPTY; + np->scripth->done_queue[5*j + 4] = + cpu_to_scr(NCB_SCRIPT_PHYS (np, done_plug)); + MEMORY_BARRIER(); + np->scripth->done_queue[5*i + 4] = + cpu_to_scr(NCB_SCRIPT_PHYS (np, done_end)); - /* fall through */ + if (cp->host_status & HS_DONEMASK) + ncr_complete (np, cp); + else if (cp->host_status & HS_SKIPMASK) + ncr_ccb_skipped (np, cp); - default: + i = j; + } + np->ccb_done_ic = i; +#else + cp = np->ccb; + while (cp) { + if (cp->host_status & HS_DONEMASK) ncr_complete (np, cp); - break; - }; - cp = cp -> link_ccb; - }; + else if (cp->host_status & HS_SKIPMASK) + ncr_ccb_skipped (np, cp); + cp = cp->link_ccb; + } +#endif +} + +/* +** Complete all active CCBs. +*/ +void ncr_wakeup (ncb_p np, u_long code) +{ + ccb_p cp = np->ccb; + + while (cp) { + if (cp->host_status != HS_IDLE) { + cp->host_status = code; + ncr_complete (np, cp); + } + cp = cp->link_ccb; + } } /*========================================================== @@ -5966,38 +6066,57 @@ void ncr_init (ncb_p np, int reset, char * msg, u_long code) { - int i; + int i; - /* + /* ** Reset chip if asked, otherwise just clear fifos. - */ + */ + if (reset) { OUTB (nc_istat, SRST); - DELAY (10000); + UDELAY (100); } else { OUTB (nc_stest3, TE|CSF); OUTONB (nc_ctest3, CLF); } - + /* ** Message. */ - if (msg) printf (KERN_INFO "%s: restart (%s).\n", ncr_name (np), msg); + if (msg) printk (KERN_INFO "%s: restart (%s).\n", ncr_name (np), msg); /* ** Clear Start Queue */ - for (i=0;i squeue [i] = cpu_to_scr(NCB_SCRIPT_PHYS (np, idle)); + np->queuedepth = MAX_START - 1; /* 1 entry needed as end marker */ + for (i = 1; i < MAX_START + MAX_START; i += 2) + np->scripth0->tryloop[i] = + cpu_to_scr(NCB_SCRIPT_PHYS (np, idle)); /* ** Start at first entry. */ np->squeueput = 0; np->script0->startpos[0] = cpu_to_scr(NCB_SCRIPTH_PHYS (np, tryloop)); - np->script0->start0 [0] = cpu_to_scr(SCR_INT ^ IFFALSE (0)); + + /* + ** Clear Done Queue + */ + for (i = 0; i < MAX_DONE; i++) { + np->ccb_done[i] = (ccb_p) CCB_DONE_EMPTY; + np->scripth0->done_queue[5*i + 4] = + cpu_to_scr(NCB_SCRIPT_PHYS (np, done_end)); + } + + /* + ** Start at first entry. + */ + np->script0->done_pos[0] = cpu_to_scr(NCB_SCRIPTH_PHYS (np,done_queue)); + np->ccb_done_ic = MAX_DONE-1; + np->scripth0->done_queue[5*(MAX_DONE-1) + 4] = + cpu_to_scr(NCB_SCRIPT_PHYS (np, done_plug)); /* ** Wakeup all pending jobs. @@ -6009,6 +6128,8 @@ */ OUTB (nc_istat, 0x00 ); /* Remove Reset, abort */ + UDELAY (2000); /* The 895 needs time for the bus mode to settle */ + OUTB (nc_scntl0, np->rv_scntl0 | 0xc0); /* full arb., ena parity, par->ATN */ OUTB (nc_scntl1, 0x00); /* odd parity, and remove CRST!! */ @@ -6027,7 +6148,7 @@ OUTB (nc_stest2, EXT|np->rv_stest2); /* Extended Sreq/Sack filtering */ OUTB (nc_stest3, TE); /* TolerANT enable */ - OUTB (nc_stime0, 0x0d ); /* HTH disabled STO 0.4 sec. */ + OUTB (nc_stime0, 0x0c ); /* HTH disabled STO 0.25 sec */ /* ** Disable disconnects. @@ -6044,23 +6165,10 @@ } /* - ** Upload the script into on-board RAM - */ - if (np->vaddr2) { - if (bootverbose) - printf ("%s: copying script fragments into the on-board RAM ...\n", ncr_name(np)); -#if LINUX_VERSION_CODE >= LinuxVersionCode(2,0,0) - memcpy_toio(np->script, np->script0, sizeof(struct script)); -#else - memcpy(np->script, np->script0, sizeof(struct script)); -#endif - } - - /* ** enable ints */ - OUTW (nc_sien , STO|HTH|MA|SGE|UDC|RST); + OUTW (nc_sien , STO|HTH|MA|SGE|UDC|RST|PAR); OUTB (nc_dien , MDPE|BF|ABRT|SSI|SIR|IID); /* @@ -6072,6 +6180,18 @@ } /* + ** DEL 441 - 53C876 Rev 5 - Part Number 609-0392787/2788 - ITEM 2. + ** Disable overlapped arbitration. + ** The 896 Rev 1 is also affected by this errata. + */ + if (np->device_id == PCI_DEVICE_ID_NCR_53C875 && + np->revision_id >= 0x10 && np->revision_id <= 0x15) + OUTB (nc_ctest0, (1<<5)); + else if (np->device_id == PCI_DEVICE_ID_NCR_53C896 && + np->revision_id <= 0x1) + OUTB (nc_ccntl0, DPR); + + /* ** Fill in target structure. ** Reinitialize usrsync. ** Reinitialize usrwide. @@ -6103,8 +6223,16 @@ /* ** Start script processor. */ - - OUTL (nc_dsp, NCB_SCRIPT_PHYS (np, start)); + MEMORY_BARRIER(); + if (np->paddr2) { + if (bootverbose) + printk ("%s: Downloading SCSI SCRIPTS.\n", + ncr_name(np)); + OUTL (nc_scratcha, vtophys(np->script0)); + OUTL (nc_dsp, NCB_SCRIPTH_PHYS (np, start_ram)); + } + else + OUTL (nc_dsp, NCB_SCRIPT_PHYS (np, start)); } /*========================================================== @@ -6132,14 +6260,6 @@ } /* - ** if not scsi 2 - ** don't believe FAST! - */ - - if ((minsync < 50) && (tp->inqdata[2] & 0x0f) < 2) - minsync=50; - - /* ** our limit .. */ @@ -6215,7 +6335,7 @@ /* ** Why not to try the immediate lower divisor and to choose ** the one that allows the fastest output speed ? - ** We don't want input speed too much greater than output speed. + ** We dont want input speed too much greater than output speed. */ if (div >= 1 && fak < 8) { u_long fak2, per2; @@ -6266,8 +6386,12 @@ for (cp = np->ccb; cp; cp = cp->link_ccb) { if (!cp->cmd) continue; if (cp->cmd->target != target) continue; +#if 0 cp->sync_status = tp->sval; cp->wide_status = tp->wval; +#endif + cp->phys.select.sel_scntl3 = tp->wval; + cp->phys.select.sel_sxfer = tp->sval; }; } @@ -6282,15 +6406,15 @@ { Scsi_Cmnd *cmd; tcb_p tp; - u_char target = INB (nc_ctest0) & 0x0f; + u_char target = INB (nc_sdid) & 0x0f; u_char idiv; - assert (cp); + assert (cp && cp->cmd); if (!cp) return; cmd = cp->cmd; - assert (cmd); if (!cmd) return; + assert (target == (cmd->target & 0xf)); tp = &np->target[target]; @@ -6320,7 +6444,7 @@ /* ** Bells and whistles ;-) */ - PRINT_ADDR(cmd); + PRINT_TARGET(np, target); if (sxfer & 0x01f) { unsigned f10 = 100000 << (tp->widedone ? tp->widedone -1 : 0); unsigned mb10 = (f10 + tp->period/2) / tp->period; @@ -6339,11 +6463,11 @@ else if (tp->period < 2000) scsi = "FAST-10"; else scsi = "FAST-5"; - printf ("%s %sSCSI %d.%d MB/s (%d ns, offset %d)\n", scsi, + printk ("%s %sSCSI %d.%d MB/s (%d ns, offset %d)\n", scsi, tp->widedone > 1 ? "WIDE " : "", mb10 / 10, mb10 % 10, tp->period / 10, sxfer & 0x1f); } else - printf ("%sasynchronous.\n", tp->widedone > 1 ? "wide " : ""); + printk ("%sasynchronous.\n", tp->widedone > 1 ? "wide " : ""); /* ** set actual value and sync_status @@ -6365,17 +6489,17 @@ static void ncr_setwide (ncb_p np, ccb_p cp, u_char wide, u_char ack) { Scsi_Cmnd *cmd; - u_short target = INB (nc_ctest0) & 0x0f; + u_short target = INB (nc_sdid) & 0x0f; tcb_p tp; u_char scntl3; u_char sxfer; - assert (cp); + assert (cp && cp->cmd); if (!cp) return; cmd = cp->cmd; - assert (cmd); if (!cmd) return; + assert (target == (cmd->target & 0xf)); tp = &np->target[target]; @@ -6395,11 +6519,11 @@ ** Bells and whistles ;-) */ if (bootverbose >= 2) { - PRINT_ADDR(cmd); + PRINT_TARGET(np, target); if (scntl3 & EWS) - printf ("WIDE SCSI (16 bit) enabled.\n"); + printk ("WIDE SCSI (16 bit) enabled.\n"); else - printf ("WIDE SCSI disabled.\n"); + printk ("WIDE SCSI disabled.\n"); } /* @@ -6416,73 +6540,91 @@ **========================================================== */ -static void ncr_setmaxtags (ncb_p np, tcb_p tp, u_long numtags) +static void ncr_setup_tags (ncb_p np, u_char tn, u_char ln) { - int l; - if (numtags > tp->usrtags) - numtags = tp->usrtags; - tp->numtags = numtags; - tp->maxtags = numtags; - - for (l=0; ltarget[tn]; + lcb_p lp = tp->lp[ln]; + u_char reqtags, maxdepth; - if (!tp) break; - lp=tp->lp[l]; - if (!lp) continue; - - wastags = lp->usetags; - ncr_settags (tp, lp); - - if (numtags > 1 && lp->reqccbs > 1) { - PRINT_LUN(np, tp - np->target, l); - printf("using tagged command queueing, up to %ld cmds/lun\n", numtags); - } - else if (numtags <= 1 && wastags) { - PRINT_LUN(np, tp - np->target, l); - printf("disabling tagged command queueing\n"); - } - }; -} + /* + ** Just in case ... + */ + if ((!tp) || (!lp)) + return; -static void ncr_settags (tcb_p tp, lcb_p lp) -{ - u_char reqtags, tmp; + /* + ** If SCSI device queue depth is not yet set, leave here. + */ + if (!lp->scdev_depth) + return; - if ((!tp) || (!lp)) return; + /* + ** Donnot allow more tags than the SCSI driver can queue + ** for this device. + ** Donnot allow more tags than we can handle. + */ + maxdepth = lp->scdev_depth; + if (maxdepth > lp->maxnxs) maxdepth = lp->maxnxs; + if (lp->maxtags > maxdepth) lp->maxtags = maxdepth; + if (lp->numtags > maxdepth) lp->numtags = maxdepth; /* ** only devices conformant to ANSI Version >= 2 - ** only devices capable of tagges commands - ** only disk devices + ** only devices capable of tagged commands ** only if enabled by user .. */ - if (( tp->inqdata[2] & 0x7) >= 2 && - ( tp->inqdata[7] & INQ7_QUEUE) && ((tp->inqdata[0] & 0x1f)==0x00) - && tp->numtags > 1) { - reqtags = tp->numtags; - if (lp->actlink <= 1) - lp->usetags=reqtags; - } else { - reqtags = 1; - if (lp->actlink <= 1) - lp->usetags=0; - }; + if ((lp->inq_byte7 & INQ7_QUEUE) && lp->numtags > 1) { + reqtags = lp->numtags; + } else { + reqtags = 1; + }; + + /* + ** Update max number of tags + */ + lp->numtags = reqtags; + if (lp->numtags > lp->maxtags) + lp->maxtags = lp->numtags; + + /* + ** If we want to switch tag mode, we must wait + ** for no CCB to be active. + */ + if (reqtags > 1 && lp->usetags) { /* Stay in tagged mode */ + if (lp->queuedepth == reqtags) /* Already announced */ + return; + lp->queuedepth = reqtags; + } + else if (reqtags <= 1 && !lp->usetags) { /* Stay in untagged mode */ + lp->queuedepth = reqtags; + return; + } + else { /* Want to switch tag mode */ + if (lp->busyccbs) /* If not yet safe, return */ + return; + lp->queuedepth = reqtags; + lp->usetags = reqtags > 1 ? 1 : 0; + } /* - ** don't announce more than available. + ** Patch the lun mini-script, according to tag mode. */ - tmp = lp->actccbs; - if (tmp > reqtags) tmp = reqtags; - lp->reqlink = tmp; + lp->jump_tag.l_paddr = lp->usetags? + cpu_to_scr(NCB_SCRIPT_PHYS(np, resel_tag)) : + cpu_to_scr(NCB_SCRIPT_PHYS(np, resel_notag)); /* - ** don't discard if announced. + ** Announce change to user. */ - tmp = lp->actlink; - if (tmp < reqtags) tmp = reqtags; - lp->reqccbs = tmp; + if (bootverbose) { + PRINT_LUN(np, tn, ln); + if (lp->usetags) { + printk("tagged command queue depth set to %d\n", reqtags); + } + else { + printk("tagged command queueing disabled\n"); + } + } } /*---------------------------------------------------- @@ -6513,13 +6655,18 @@ break; case UC_SETTAGS: - if (np->user.data > SCSI_NCR_MAX_TAGS) - np->user.data = SCSI_NCR_MAX_TAGS; for (t=0; tuser.target>>t)&1)) continue; np->target[t].usrtags = np->user.data; - ncr_setmaxtags (np, &np->target[t], np->user.data); - }; + for (ln = 0; ln < MAX_LUN; ln++) { + lcb_p lp = np->target[t].lp[ln]; + if (!lp) + continue; + lp->maxtags = lp->numtags = np->user.data; + ncr_setup_tags (np, t, ln); + } + }; break; case UC_SETDEBUG: @@ -6532,6 +6679,10 @@ np->order = np->user.data; break; + case UC_SETVERBOSE: + np->verbose = np->user.data; + break; + case UC_SETWIDE: for (t=0; tprofile, sizeof(np->profile)); break; -#ifdef UC_DEBUG_ERROR_RECOVERY - case UC_DEBUG_ERROR_RECOVERY: - np->debug_error_recovery = np->user.data; - break; #endif } np->user.cmd=0; } #endif - -/*===================================================================== -** -** Embedded error recovery debugging code. -** -**===================================================================== -** -** This code is conditionned by SCSI_NCR_DEBUG_ERROR_RECOVERY_SUPPORT. -** It only can be enabled after boot-up with a control command. -** -** Every 30 seconds the timer handler of the driver decides to -** change the behaviour of the driver in order to trigger errors. -** -** If last command was "debug_error_recovery sge", the driver -** sets sync offset of all targets that use sync transfers to 2, -** and so hopes a SCSI gross error at the next read operation. -** -** If last command was "debug_error_recovery abort", the driver -** does not signal new scsi commands to the script processor, until -** it is asked to abort or reset a command by the mid-level driver. -** -** If last command was "debug_error_recovery reset", the driver -** does not signal new scsi commands to the script processor, until -** it is asked to reset a command by the mid-level driver. -** -** If last command was "debug_error_recovery parity", the driver -** will assert ATN on the next DATA IN phase mismatch, and so will -** behave as if a parity error had been detected. -** -** The command "debug_error_recovery none" makes the driver behave -** normaly. -** -**===================================================================== -*/ - -#ifdef SCSI_NCR_DEBUG_ERROR_RECOVERY_SUPPORT -static void ncr_trigger_errors (ncb_p np) -{ - /* - ** If np->debug_error_recovery is not zero, we want to - ** simulate common errors in order to test error recovery. - */ - do { - static u_long last = 0l; - - if (!np->debug_error_recovery) - break; - if (!last) - last = jiffies; - else if (jiffies < last + 30*HZ) - break; - last = jiffies; - /* - * This one triggers SCSI gross errors. - */ - if (np->debug_error_recovery == 1) { - int i; - printf("%s: testing error recovery from SCSI gross error...\n", ncr_name(np)); - for (i = 0 ; i < MAX_TARGET ; i++) { - if (np->target[i].sval & 0x1f) { - np->target[i].sval &= ~0x1f; - np->target[i].sval += 2; - } - } - } - /* - * This one triggers abort from the mid-level driver. - */ - else if (np->debug_error_recovery == 2) { - printf("%s: testing error recovery from mid-level driver abort()...\n", ncr_name(np)); - np->stalling = 2; - } - /* - * This one triggers reset from the mid-level driver. - */ - else if (np->debug_error_recovery == 3) { - printf("%s: testing error recovery from mid-level driver reset()...\n", ncr_name(np)); - np->stalling = 3; - } - /* - * This one set ATN on phase mismatch in DATA IN phase and so - * will behave as on scsi parity error detected. - */ - else if (np->debug_error_recovery == 4) { - printf("%s: testing data in parity error...\n", ncr_name(np)); - np->assert_atn = 1; - } - } while (0); -} -#endif - /*========================================================== ** ** @@ -6673,9 +6730,6 @@ static void ncr_timeout (ncb_p np) { u_long thistime = jiffies; - u_long count = 0; - ccb_p cp; - u_long flags; /* ** If release process in progress, let's go @@ -6688,18 +6742,9 @@ return; } - np->timer.expires = -#if LINUX_VERSION_CODE >= LinuxVersionCode(1,3,0) - jiffies + -#endif - SCSI_NCR_TIMER_INTERVAL; - + np->timer.expires = jiffies + SCSI_NCR_TIMER_INTERVAL; add_timer(&np->timer); -#ifdef SCSI_NCR_DEBUG_ERROR_RECOVERY_SUPPORT - ncr_trigger_errors (np); -#endif - /* ** If we are resetting the ncr, wait for settle_time before ** clearing it. Then command processing will be resumed. @@ -6707,12 +6752,10 @@ if (np->settle_time) { if (np->settle_time <= thistime) { if (bootverbose > 1) - printf("%s: command processing resumed\n", ncr_name(np)); - save_flags(flags); cli(); + printk("%s: command processing resumed\n", ncr_name(np)); np->settle_time = 0; np->disc = 1; requeue_waiting_list(np); - restore_flags(flags); } return; } @@ -6722,99 +6765,20 @@ ** to perform abort of a command, we must look at ccbs about ** every 0.25 second. */ - if (np->lasttime + (HZ>>2) <= thistime) { + if (np->lasttime + 4*HZ < thistime) { /* ** block ncr interrupts */ - save_flags(flags); cli(); - np->lasttime = thistime; +#ifdef SCSI_NCR_PROFILE_SUPPORT /* ** Reset profile data to avoid ugly overflow ** (Limited to 1024 GB for 32 bit architecture) */ if (np->profile.num_kbytes > (~0UL >> 2)) bzero(&np->profile, sizeof(np->profile)); - - /*---------------------------------------------------- - ** - ** handle ncr chip timeouts - ** - ** Assumption: - ** We have a chance to arbitrate for the - ** SCSI bus at least every 10 seconds. - ** - **---------------------------------------------------- - */ -#if 0 - if (thistime < np->heartbeat + HZ + HZ) - np->latetime = 0; - else - np->latetime++; #endif - - /*---------------------------------------------------- - ** - ** handle ccb timeouts - ** - **---------------------------------------------------- - */ - - for (cp=np->ccb; cp; cp=cp->link_ccb) { - /* - ** look for timed out ccbs. - */ - if (!cp->host_status) continue; - count++; - /* - ** Have to force ordered tag to avoid timeouts - */ - if (cp->cmd && cp->tlimit && cp->tlimit <= - thistime + NCR_TIMEOUT_INCREASE + SCSI_NCR_TIMEOUT_ALERT) { - lcb_p lp; - lp = np->target[cp->cmd->target].lp[cp->cmd->lun]; - if (lp && !lp->force_ordered_tag) { - lp->force_ordered_tag = 1; - } - } - /* - ** ncr_abort_command() cannot complete canceled - ** commands immediately. It sets tlimit to zero - ** and ask the script to skip the scsi process if - ** necessary. We have to complete this work here. - */ - - if (cp->tlimit) continue; - - switch (cp->host_status) { - - case HS_BUSY: - case HS_NEGOTIATE: - /* - ** still in start queue ? - */ - if (cp->phys.header.launch.l_paddr == - cpu_to_scr(NCB_SCRIPT_PHYS (np, skip))) - continue; - - /* fall through */ - case HS_DISCONNECT: - cp->host_status=HS_ABORTED; - }; - cp->tag = 0; - - /* - ** wakeup this ccb. - */ - ncr_complete (np, cp); - -#ifdef SCSI_NCR_DEBUG_ERROR_RECOVERY_SUPPORT - if (!np->stalling) -#endif - OUTB (nc_istat, SIGP); - } - restore_flags(flags); } #ifdef SCSI_NCR_BROKEN_INTR @@ -6823,11 +6787,9 @@ /* ** Process pending interrupts. */ - save_flags(flags); cli(); - if (DEBUG_FLAGS & DEBUG_TINY) printf ("{"); + if (DEBUG_FLAGS & DEBUG_TINY) printk ("{"); ncr_exception (np); - if (DEBUG_FLAGS & DEBUG_TINY) printf ("}"); - restore_flags(flags); + if (DEBUG_FLAGS & DEBUG_TINY) printk ("}"); } #endif /* SCSI_NCR_BROKEN_INTR */ } @@ -6876,14 +6838,14 @@ if (dsp > np->p_script && dsp <= np->p_script + sizeof(struct script)) { script_ofs = dsp - np->p_script; script_size = sizeof(struct script); - script_base = (u_char *) np->script; + script_base = (u_char *) np->script0; script_name = "script"; } else if (np->p_scripth < dsp && dsp <= np->p_scripth + sizeof(struct scripth)) { script_ofs = dsp - np->p_scripth; script_size = sizeof(struct scripth); - script_base = (u_char *) np->scripth; + script_base = (u_char *) np->scripth0; script_name = "scripth"; } else { script_ofs = dsp; @@ -6892,22 +6854,22 @@ script_name = "mem"; } - printf ("%s:%d: ERROR (%x:%x) (%x-%x-%x) (%x/%x) @ (%s %x:%08x).\n", - ncr_name (np), (unsigned)INB (nc_ctest0)&0x0f, dstat, sist, + printk ("%s:%d: ERROR (%x:%x) (%x-%x-%x) (%x/%x) @ (%s %x:%08x).\n", + ncr_name (np), (unsigned)INB (nc_sdid)&0x0f, dstat, sist, (unsigned)INB (nc_socl), (unsigned)INB (nc_sbcl), (unsigned)INB (nc_sbdl), (unsigned)INB (nc_sxfer),(unsigned)INB (nc_scntl3), script_name, script_ofs, (unsigned)INL (nc_dbc)); if (((script_ofs & 3) == 0) && (unsigned)script_ofs < script_size) { - printf ("%s: script cmd = %08x\n", ncr_name(np), - (int) *(ncrcmd *)(script_base + script_ofs)); + printk ("%s: script cmd = %08x\n", ncr_name(np), + scr_to_cpu((int) *(ncrcmd *)(script_base + script_ofs))); } - printf ("%s: regdump:", ncr_name(np)); + printk ("%s: regdump:", ncr_name(np)); for (i=0; i<16;i++) - printf (" %02x", (unsigned)INB_OFF(i)); - printf (".\n"); + printk (" %02x", (unsigned)INB_OFF(i)); + printk (".\n"); } /*============================================================ @@ -6953,23 +6915,25 @@ ** Since the global header may be copied back to a CCB ** using a posted PCI memory write, the last operation on ** the istat register is a READ in order to flush posted - ** PCI commands (Btw, the 'do' loop is probably useless). + ** PCI write commands. */ istat = INB (nc_istat); if (istat & INTF) { - do { - OUTB (nc_istat, (istat & SIGP) | INTF); - istat = INB (nc_istat); - } while (istat & INTF); - if (DEBUG_FLAGS & DEBUG_TINY) printf ("F "); + OUTB (nc_istat, (istat & SIGP) | INTF); + istat = INB (nc_istat); + if (DEBUG_FLAGS & DEBUG_TINY) printk ("F "); +#ifdef SCSI_NCR_PROFILE_SUPPORT np->profile.num_fly++; - ncr_wakeup (np, 0); +#endif + ncr_wakeup_done (np); }; if (!(istat & (SIP|DIP))) return; +#ifdef SCSI_NCR_PROFILE_SUPPORT np->profile.num_int++; +#endif if (istat & CABRT) OUTB (nc_istat, CABRT); @@ -6983,7 +6947,7 @@ dstat = (istat & DIP) ? INB (nc_dstat) : 0; if (DEBUG_FLAGS & DEBUG_TINY) - printf ("<%d|%x:%x|%x:%x>", + printk ("<%d|%x:%x|%x:%x>", (int)INB(nc_scr0), dstat,sist, (unsigned)INL(nc_dsp), @@ -7020,12 +6984,11 @@ ** DEL 397 - 53C875 Rev 3 - Part Number 609-0392410 - ITEM 2. */ if (!(sist & (SBMC|PAR)) && !(dstat & SSI)) { - printf( "%s: unknown interrupt(s) ignored, " + printk( "%s: unknown interrupt(s) ignored, " "ISTAT=%x DSTAT=%x SIST=%x\n", ncr_name(np), istat, dstat, sist); return; } - OUTONB (nc_dcntl, (STD|NOCOM)); return; }; @@ -7083,29 +7046,26 @@ ncr_log_hard_error(np, sist, dstat); - printf ("%s: have to clear fifos.\n", ncr_name (np)); + printk ("%s: have to clear fifos.\n", ncr_name (np)); OUTB (nc_stest3, TE|CSF); OUTONB (nc_ctest3, CLF); if ((sist & (SGE)) || (dstat & (MDPE|BF|ABORT|IID))) { - ncr_start_reset(np, driver_setup.settle_delay); + ncr_start_reset(np); return; }; if (sist & HTH) { - printf ("%s: handshake timeout\n", ncr_name(np)); - ncr_start_reset(np, driver_setup.settle_delay); + printk ("%s: handshake timeout\n", ncr_name(np)); + ncr_start_reset(np); return; }; if (sist & UDC) { - printf ("%s: unexpected disconnect\n", ncr_name(np)); - if (INB (nc_scr1) != 0xff) { - OUTB (nc_scr1, HS_UNEXPECTED); - OUTL (nc_dsp, NCB_SCRIPT_PHYS (np, cleanup)); - }; - ncr_start_reset(np, driver_setup.settle_delay); + printk ("%s: unexpected disconnect\n", ncr_name(np)); + OUTB (HS_PRT, HS_UNEXPECTED); + OUTL (nc_dsp, NCB_SCRIPT_PHYS (np, cleanup)); return; }; @@ -7114,7 +7074,7 @@ ** Print a message. The timeout will do the real work. **========================================================= */ - printf ("%s: unknown interrupt\n", ncr_name(np)); + printk ("%s: unknown interrupt\n", ncr_name(np)); } /*========================================================== @@ -7135,9 +7095,9 @@ void ncr_int_sto (ncb_p np) { - u_long dsa, scratcha, diff; + u_long dsa; ccb_p cp; - if (DEBUG_FLAGS & DEBUG_TINY) printf ("T"); + if (DEBUG_FLAGS & DEBUG_TINY) printk ("T"); /* ** look for ccb and set the status. @@ -7154,21 +7114,11 @@ }; /* - ** repair start queue + ** repair start queue and jump to start point. */ - scratcha = INL (nc_scratcha); - diff = scratcha - NCB_SCRIPTH_PHYS (np, tryloop); - -/* assert ((diff <= MAX_START * 20) && !(diff % 20));*/ - - if ((diff <= MAX_START * 20) && !(diff % 20)) { - np->script->startpos[0] = cpu_to_scr(scratcha); - OUTL (nc_dsp, NCB_SCRIPT_PHYS (np, start)); - return; - }; - ncr_init (np, 1, "selection timeout", HS_FAIL); - np->disc = 1; + OUTL (nc_dsp, NCB_SCRIPTH_PHYS (np, sto_restart)); + return; } /*========================================================== @@ -7192,19 +7142,22 @@ { u_char scsi_mode = INB (nc_stest4) & SMODE; - printf("%s: SCSI bus mode change from %x to %x.\n", - ncr_name(np), np->scsi_mode, scsi_mode); + if (scsi_mode != np->scsi_mode) { + printk("%s: SCSI bus mode change from %x to %x.\n", + ncr_name(np), np->scsi_mode, scsi_mode); - np->scsi_mode = scsi_mode; + np->scsi_mode = scsi_mode; - /* - ** Suspend command processing for 1 second and - ** reinitialize all except the chip. - */ - np->settle_time = jiffies + HZ; - ncr_init (np, 0, bootverbose ? "scsi mode change" : NULL, HS_RESET); - return 1; + /* + ** Suspend command processing for 1 second and + ** reinitialize all except the chip. + */ + np->settle_time = jiffies + HZ; + ncr_init (np, 0, bootverbose ? "scsi mode change" : NULL, HS_RESET); + return 1; + } + return 0; } /*========================================================== @@ -7213,16 +7166,73 @@ ** **========================================================== ** -** SCSI parity errors are handled by the SCSI script. -** So, we just print some message. ** **---------------------------------------------------------- */ static int ncr_int_par (ncb_p np) { - printf("%s: SCSI parity error detected\n", ncr_name(np)); - return 0; + u_char hsts = INB (HS_PRT); + u_int32 dbc = INL (nc_dbc); + u_char sstat1 = INB (nc_sstat1); + int phase = -1; + int msg = -1; + u_int32 jmp; + + printk("%s: SCSI parity error detected: SCR1=%d DBC=%x SSTAT1=%x\n", + ncr_name(np), hsts, dbc, sstat1); + + /* + * Ignore the interrupt if the NCR is not connected + * to the SCSI bus, since the right work should have + * been done on unexpected disconnection handling. + */ + if (!(INB (nc_scntl1) & ISCON)) + return 0; + + /* + * If the nexus is not clearly identified, reset the bus. + * We will try to do better later. + */ + if (hsts & HS_INVALMASK) + goto reset_all; + + /* + * If the SCSI parity error occurs in MSG IN phase, prepare a + * MSG PARITY message. Otherwise, prepare a INITIATOR DETECTED + * ERROR message and let the device decide to retry the command + * or to terminate with check condition. If we were in MSG IN + * phase waiting for the response of a negotiation, we will + * get SIR_NEGO_FAILED at dispatch. + */ + if (!(dbc & 0xc0000000)) + phase = (dbc >> 24) & 7; + if (phase == 7) + msg = M_PARITY; + else + msg = M_ID_ERROR; + + /* + * If the NCR stopped on a MOVE ^ DATA_IN, we jump to a + * script that will ignore all data in bytes until phase + * change, since we are not sure the chip will wait the phase + * change prior to delivering the interrupt. + */ + if (phase == 1) + jmp = NCB_SCRIPTH_PHYS (np, par_err_data_in); + else + jmp = NCB_SCRIPTH_PHYS (np, par_err_other); + + OUTONB (nc_ctest3, CLF ); /* clear dma fifo */ + OUTB (nc_stest3, TE|CSF); /* clear scsi fifo */ + + np->msgout[0] = msg; + OUTL (nc_dsp, jmp); + return 1; + +reset_all: + ncr_start_reset(np); + return 1; } /*========================================================== @@ -7292,72 +7302,89 @@ if (ss2 & ORF1) rest++; }; - OUTONB (nc_ctest3, CLF ); /* clear dma fifo */ - OUTB (nc_stest3, TE|CSF); /* clear scsi fifo */ - if (DEBUG_FLAGS & (DEBUG_TINY|DEBUG_PHASE)) - printf ("P%x%x RL=%d D=%d SS0=%x ", cmd&7, sbcl&7, + printk ("P%x%x RL=%d D=%d SS0=%x ", cmd&7, sbcl&7, (unsigned) rest, (unsigned) delta, ss0); } else { if (DEBUG_FLAGS & (DEBUG_TINY|DEBUG_PHASE)) - printf ("P%x%x RL=%d ", cmd&7, sbcl&7, rest); - if ((cmd & 7) != 1) { - OUTONB (nc_ctest3, CLF ); - OUTB (nc_stest3, TE|CSF); - } + printk ("P%x%x RL=%d ", cmd&7, sbcl&7, rest); } /* - ** locate matching cp + ** Clear fifos. */ - dsa = INL (nc_dsa); - cp = np->ccb; - while (cp && (CCB_PHYS (cp, phys) != dsa)) - cp = cp->link_ccb; + OUTONB (nc_ctest3, CLF ); /* clear dma fifo */ + OUTB (nc_stest3, TE|CSF); /* clear scsi fifo */ - if (!cp) { - printf ("%s: SCSI phase error fixup: CCB already dequeued (0x%08lx)\n", - ncr_name (np), (u_long) np->header.cp); - return; - } - if (cp != np->header.cp) { - printf ("%s: SCSI phase error fixup: CCB address mismatch (0x%08lx != 0x%08lx)\n", - ncr_name (np), (u_long) cp, (u_long) np->header.cp); -/* return;*/ + /* + ** locate matching cp. + ** if the interrupted phase is DATA IN or DATA OUT, + ** trust the global header. + */ + dsa = INL (nc_dsa); + if (!(cmd & 6)) { + cp = np->header.cp; + if (CCB_PHYS(cp, phys) != dsa) + cp = 0; + } else { + cp = np->ccb; + while (cp && (CCB_PHYS (cp, phys) != dsa)) + cp = cp->link_ccb; } /* - ** find the interrupted script command, + ** try to find the interrupted script command, ** and the address at which to continue. */ - - if (dsp == vtophys (&cp->patch[2])) { - vdsp = &cp->patch[0]; - nxtdsp = vdsp[3]; - } else if (dsp == vtophys (&cp->patch[6])) { - vdsp = &cp->patch[4]; - nxtdsp = vdsp[3]; - } else if (dsp > np->p_script && dsp <= np->p_script + sizeof(struct script)) { - vdsp = (u_int32 *) ((char*)np->script - np->p_script + dsp -8); + vdsp = 0; + nxtdsp = 0; + if (dsp > np->p_script && + dsp <= np->p_script + sizeof(struct script)) { + vdsp = (u_int32 *)((char*)np->script0 + (dsp-np->p_script-8)); nxtdsp = dsp; - } else { - vdsp = (u_int32 *) ((char*)np->scripth - np->p_scripth + dsp -8); + } + else if (dsp > np->p_scripth && + dsp <= np->p_scripth + sizeof(struct scripth)) { + vdsp = (u_int32 *)((char*)np->scripth0 + (dsp-np->p_scripth-8)); nxtdsp = dsp; - }; + } + else if (cp) { + if (dsp == vtophys (&cp->patch[2])) { + vdsp = &cp->patch[0]; + nxtdsp = scr_to_cpu(vdsp[3]); + } + else if (dsp == vtophys (&cp->patch[6])) { + vdsp = &cp->patch[4]; + nxtdsp = scr_to_cpu(vdsp[3]); + } + } /* ** log the information */ if (DEBUG_FLAGS & DEBUG_PHASE) { - printf ("\nCP=%p CP2=%p DSP=%x NXT=%x VDSP=%p CMD=%x ", + printk ("\nCP=%p CP2=%p DSP=%x NXT=%x VDSP=%p CMD=%x ", cp, np->header.cp, (unsigned)dsp, (unsigned)nxtdsp, vdsp, cmd); }; /* + ** cp=0 means that the DSA does not point to a valid control + ** block. This should not happen since we donnot use multi-byte + ** move while we are being reselected ot after command complete. + ** We are not able to recover from such a phase error. + */ + if (!cp) { + printk ("%s: SCSI phase error fixup: " + "CCB already dequeued (0x%08lx)\n", + ncr_name (np), (u_long) np->header.cp); + goto reset_all; + } + + /* ** get old startaddress and old length. */ @@ -7373,7 +7400,7 @@ }; if (DEBUG_FLAGS & DEBUG_PHASE) { - printf ("OCMD=%x\nTBLP=%p OLEN=%x OADR=%x\n", + printk ("OCMD=%x\nTBLP=%p OLEN=%x OADR=%x\n", (unsigned) (scr_to_cpu(vdsp[0]) >> 24), tblp, (unsigned) olen, @@ -7386,18 +7413,23 @@ if (cmd != (scr_to_cpu(vdsp[0]) >> 24)) { PRINT_ADDR(cp->cmd); - printf ("internal error: cmd=%02x != %02x=(vdsp[0] >> 24)\n", + printk ("internal error: cmd=%02x != %02x=(vdsp[0] >> 24)\n", (unsigned)cmd, (unsigned)scr_to_cpu(vdsp[0]) >> 24); - - return; + + goto reset_all; } -#ifdef SCSI_NCR_DEBUG_ERROR_RECOVERY_SUPPORT - if ((cmd & 7) == 1 && np->assert_atn) { - np->assert_atn = 0; - OUTONB(nc_socl, CATN); + /* + ** cp != np->header.cp means that the header of the CCB + ** currently being processed has not yet been copied to + ** the global header area. That may happen if the device did + ** not accept all our messages after having been selected. + */ + if (cp != np->header.cp) { + printk ("%s: SCSI phase error fixup: " + "CCB address mismatch (0x%08lx != 0x%08lx)\n", + ncr_name (np), (u_long) cp, (u_long) np->header.cp); } -#endif /* ** if old phase not dataphase, leave here. @@ -7405,52 +7437,261 @@ if (cmd & 0x06) { PRINT_ADDR(cp->cmd); - printf ("phase change %x-%x %d@%08x resid=%d.\n", + printk ("phase change %x-%x %d@%08x resid=%d.\n", cmd&7, sbcl&7, (unsigned)olen, (unsigned)oadr, (unsigned)rest); + goto unexpected_phase; + }; + + /* + ** choose the correct patch area. + ** if savep points to one, choose the other. + */ + + newcmd = cp->patch; + if (cp->phys.header.savep == cpu_to_scr(vtophys (newcmd))) newcmd+=4; + + /* + ** fillin the commands + */ + + newcmd[0] = cpu_to_scr(((cmd & 0x0f) << 24) | rest); + newcmd[1] = cpu_to_scr(oadr + olen - rest); + newcmd[2] = cpu_to_scr(SCR_JUMP); + newcmd[3] = cpu_to_scr(nxtdsp); + + if (DEBUG_FLAGS & DEBUG_PHASE) { + PRINT_ADDR(cp->cmd); + printk ("newcmd[%d] %x %x %x %x.\n", + (int) (newcmd - cp->patch), + (unsigned)scr_to_cpu(newcmd[0]), + (unsigned)scr_to_cpu(newcmd[1]), + (unsigned)scr_to_cpu(newcmd[2]), + (unsigned)scr_to_cpu(newcmd[3])); + } + /* + ** fake the return address (to the patch). + ** and restart script processor at dispatcher. + */ +#ifdef SCSI_NCR_PROFILE_SUPPORT + np->profile.num_break++; +#endif + OUTL (nc_temp, vtophys (newcmd)); + OUTL (nc_dsp, NCB_SCRIPT_PHYS (np, dispatch)); + return; + + /* + ** Unexpected phase changes that occurs when the current phase + ** is not a DATA IN or DATA OUT phase are due to error conditions. + ** Such event may only happen when the SCRIPTS is using a + ** multibyte SCSI MOVE. + ** + ** Phase change Some possible cause + ** + ** COMMAND --> MSG IN SCSI parity error detected by target. + ** COMMAND --> STATUS Bad command or refused by target. + ** MSG OUT --> MSG IN Message rejected by target. + ** MSG OUT --> COMMAND Bogus target that discards extended + ** negotiation messages. + ** + ** The code below does not care of the new phase and so + ** trusts the target. Why to annoy it ? + ** If the interrupted phase is COMMAND phase, we restart at + ** dispatcher. + ** If a target does not get all the messages after selection, + ** the code assumes blindly that the target discards extended + ** messages and clears the negotiation status. + ** If the target does not want all our response to negotiation, + ** we force a SIR_NEGO_PROTO interrupt (it is a hack that avoids + ** bloat for such a should_not_happen situation). + ** In all other situation, we reset the BUS. + ** Are these assumptions reasonnable ? (Wait and see ...) + */ +unexpected_phase: + dsp -= 8; + nxtdsp = 0; + + switch (cmd & 7) { + case 2: /* COMMAND phase */ + nxtdsp = NCB_SCRIPT_PHYS (np, dispatch); + break; +#if 0 + case 3: /* STATUS phase */ + nxtdsp = NCB_SCRIPT_PHYS (np, dispatch); + break; +#endif + case 6: /* MSG OUT phase */ + np->scripth->nxtdsp_go_on[0] = cpu_to_scr(dsp + 8); + if (dsp == NCB_SCRIPT_PHYS (np, send_ident)) { + cp->host_status = HS_BUSY; + nxtdsp = NCB_SCRIPTH_PHYS (np, clratn_go_on); + } + else if (dsp == NCB_SCRIPTH_PHYS (np, send_wdtr) || + dsp == NCB_SCRIPTH_PHYS (np, send_sdtr)) { + nxtdsp = dsp - 8; /* Should raise SIR_NEGO_PROTO */ + } + break; +#if 0 + case 7: /* MSG IN phase */ + nxtdsp = NCB_SCRIPT_PHYS (np, clrack); + break; +#endif + } + + if (nxtdsp) { + OUTL (nc_dsp, nxtdsp); + return; + } + +reset_all: + ncr_start_reset(np); +} + + +static void ncr_sir_to_redo(ncb_p np, int num, ccb_p cp) +{ + Scsi_Cmnd *cmd = cp->cmd; + tcb_p tp = &np->target[cmd->target]; + lcb_p lp = tp->lp[cmd->lun]; + XPT_QUEHEAD *qp; + ccb_p cp2; + int disc_cnt = 0; + int busy_cnt = 0; + u_int32 startp; + u_char s_status = INB (SS_PRT); + + /* + ** Let the SCRIPTS processor skip all not yet started CCBs, + ** and count disconnected CCBs. Since the busy queue is in + ** the same order as the chip start queue, disconnected CCBs + ** are before cp and busy ones after. + */ + if (lp) { + qp = lp->busy_ccbq.blink; + while (qp != &lp->busy_ccbq) { + cp2 = xpt_que_entry(qp, struct ccb, link_ccbq); + qp = qp->blink; + ++busy_cnt; + if (cp2 == cp) + break; + cp2->start.schedule.l_paddr = + cpu_to_scr(NCB_SCRIPTH_PHYS (np, skip)); + } + lp->held_ccb = cp; /* Requeue when this one completes */ + disc_cnt = lp->queuedccbs - busy_cnt; + } + + switch(s_status) { + default: /* Just for safety, should never happen */ + case S_QUEUE_FULL: + /* + ** Decrease number of tags to the number of + ** disconnected commands. + */ + if (!lp) + goto out; + if (bootverbose >= 1) { + PRINT_ADDR(cmd); + printk ("QUEUE FULL! %d busy, %d disconnected CCBs\n", + busy_cnt, disc_cnt); + } + if (disc_cnt < lp->numtags) { + lp->numtags = disc_cnt > 2 ? disc_cnt : 2; + lp->num_good = 0; + ncr_setup_tags (np, cmd->target, cmd->lun); + } + /* + ** Requeue the command to the start queue. + ** If any disconnected commands, + ** Clear SIGP. + ** Jump to reselect. + */ + cp->phys.header.savep = cp->startp; + cp->host_status = HS_BUSY; + cp->scsi_status = S_ILLEGAL; + + ncr_put_start_queue(np, cp); + if (disc_cnt) + INB (nc_ctest2); /* Clear SIGP */ + OUTL (nc_dsp, NCB_SCRIPT_PHYS (np, reselect)); + return; + case S_TERMINATED: + case S_CHECK_COND: + /* + ** If we were requesting sense, give up. + */ + if (cp->auto_sense) + goto out; + + /* + ** Device returned CHECK CONDITION status. + ** Prepare all needed data strutures for getting + ** sense data. + ** + ** identify message + */ + cp->scsi_smsg2[0] = M_IDENTIFY | cmd->lun; + cp->phys.smsg.addr = cpu_to_scr(CCB_PHYS (cp, scsi_smsg2)); + cp->phys.smsg.size = cpu_to_scr(1); + + /* + ** sense command + */ + cp->phys.cmd.addr = cpu_to_scr(CCB_PHYS (cp, sensecmd)); + cp->phys.cmd.size = cpu_to_scr(6); + + /* + ** patch requested size into sense command + */ + cp->sensecmd[0] = 0x03; + cp->sensecmd[1] = cmd->lun << 5; + cp->sensecmd[4] = sizeof(cmd->sense_buffer); + + /* + ** sense data + */ + cp->phys.sense.addr = + cpu_to_scr(vtophys (&cmd->sense_buffer[0])); + cp->phys.sense.size = + cpu_to_scr(sizeof(cmd->sense_buffer)); - OUTONB (nc_dcntl, (STD|NOCOM)); - return; - }; + /* + ** requeue the command. + */ + startp = cpu_to_scr(NCB_SCRIPTH_PHYS (np, sdata_in)); - /* - ** choose the correct patch area. - ** if savep points to one, choose the other. - */ + cp->phys.header.savep = startp; + cp->phys.header.goalp = startp + 24; + cp->phys.header.lastp = startp; + cp->phys.header.wgoalp = startp + 24; + cp->phys.header.wlastp = startp; - newcmd = cp->patch; - if (cp->phys.header.savep == cpu_to_scr(vtophys (newcmd))) newcmd+=4; + cp->host_status = HS_BUSY; + cp->scsi_status = S_ILLEGAL; + cp->auto_sense = s_status; - /* - ** fillin the commands - */ + cp->start.schedule.l_paddr = + cpu_to_scr(NCB_SCRIPT_PHYS (np, select)); - newcmd[0] = cpu_to_scr(((cmd & 0x0f) << 24) | rest); - newcmd[1] = cpu_to_scr(oadr + olen - rest); - newcmd[2] = cpu_to_scr(SCR_JUMP); - newcmd[3] = cpu_to_scr(nxtdsp); + /* + ** Select without ATN for quirky devices. + */ + if (tp->quirks & QUIRK_NOMSG) + cp->start.schedule.l_paddr = + cpu_to_scr(NCB_SCRIPTH_PHYS (np, select_no_atn)); - if (DEBUG_FLAGS & DEBUG_PHASE) { - PRINT_ADDR(cp->cmd); - printf ("newcmd[%d] %x %x %x %x.\n", - (int) (newcmd - cp->patch), - (unsigned)scr_to_cpu(newcmd[0]), - (unsigned)scr_to_cpu(newcmd[1]), - (unsigned)scr_to_cpu(newcmd[2]), - (unsigned)scr_to_cpu(newcmd[3])); + ncr_put_start_queue(np, cp); + + OUTL (nc_dsp, NCB_SCRIPT_PHYS (np, start)); + return; } - /* - ** fake the return address (to the patch). - ** and restart script processor at dispatcher. - */ - np->profile.num_break++; - OUTL (nc_temp, vtophys (newcmd)); - if ((cmd & 7) == 0) - OUTL (nc_dsp, NCB_SCRIPT_PHYS (np, dispatch)); - else - OUTL (nc_dsp, NCB_SCRIPT_PHYS (np, checkatn)); + +out: + OUTONB (nc_dcntl, (STD|NOCOM)); + return; } + /*========================================================== ** ** @@ -7463,159 +7704,79 @@ static int ncr_show_msg (u_char * msg) { u_char i; - printf ("%x",*msg); + printk ("%x",*msg); if (*msg==M_EXTENDED) { for (i=1;i<8;i++) { if (i-1>msg[1]) break; - printf ("-%x",msg[i]); + printk ("-%x",msg[i]); }; return (i+1); } else if ((*msg & 0xf0) == 0x20) { - printf ("-%x",msg[1]); + printk ("-%x",msg[1]); return (2); }; return (1); } + void ncr_int_sir (ncb_p np) { u_char scntl3; u_char chg, ofs, per, fak, wide; u_char num = INB (nc_dsps); ccb_p cp=0; - u_long dsa; - u_char target = INB (nc_ctest0) & 0x0f; + u_long dsa = INL (nc_dsa); + u_char target = INB (nc_sdid) & 0x0f; tcb_p tp = &np->target[target]; - int i; - if (DEBUG_FLAGS & DEBUG_TINY) printf ("I#%d", num); + + if (DEBUG_FLAGS & DEBUG_TINY) printk ("I#%d", num); switch (num) { - case SIR_SENSE_RESTART: - case SIR_STALL_RESTART: - break; - case SIR_STALL_QUEUE: /* Ignore, just restart the script */ + case SIR_RESEL_NO_MSG_IN: + case SIR_RESEL_NO_IDENTIFY: + /* + ** If devices reselecting without sending an IDENTIFY + ** message still exist, this should help. + ** We just assume lun=0, 1 CCB, no tag. + */ + if (tp->lp[0]) { + OUTL (nc_dsp, scr_to_cpu(tp->lp[0]->jump_ccb[0])); + return; + } + case SIR_RESEL_BAD_TARGET: /* Will send a TARGET RESET message */ + case SIR_RESEL_BAD_LUN: /* Will send a TARGET RESET message */ + case SIR_RESEL_BAD_I_T_L_Q: /* Will send an ABORT TAG message */ + case SIR_RESEL_BAD_I_T_L: /* Will send an ABORT message */ + printk ("%s:%d: SIR %d, " + "incorrect nexus identification on reselection\n", + ncr_name (np), target, num); goto out; - + case SIR_DONE_OVERFLOW: + printk ("%s:%d: SIR %d, " + "CCB done queue overflow\n", + ncr_name (np), target, num); + goto out; + case SIR_BAD_STATUS: + cp = np->header.cp; + if (!cp || CCB_PHYS (cp, phys) != dsa) + goto out; + ncr_sir_to_redo(np, num, cp); + return; default: /* ** lookup the ccb */ - dsa = INL (nc_dsa); cp = np->ccb; while (cp && (CCB_PHYS (cp, phys) != dsa)) cp = cp->link_ccb; - assert (cp); - if (!cp) - goto out; - assert (cp == np->header.cp); - if (cp != np->header.cp) + assert (cp && cp == np->header.cp); + + if (!cp || cp != np->header.cp) goto out; } switch (num) { - u_long endp; - case SIR_DATA_IO_IS_OUT: - case SIR_DATA_IO_IS_IN: -/* -** We did not guess the direction of transfer. We have to wait for -** actual data direction driven by the target before setting -** pointers. We must patch the global header too. -*/ - if (num == SIR_DATA_IO_IS_OUT) { - endp = NCB_SCRIPTH_PHYS (np, data_out) + MAX_SCATTER*16; - cp->phys.header.goalp = cpu_to_scr(endp + 8); - cp->phys.header.savep = - cpu_to_scr(endp - cp->segments*16); - } else { - endp = NCB_SCRIPT_PHYS (np, data_in) + MAX_SCATTER*16; - cp->phys.header.goalp = cpu_to_scr(endp + 8); - cp->phys.header.savep = - cpu_to_scr(endp - cp->segments*16); - } - - cp->phys.header.lastp = cp->phys.header.savep; - np->header.savep = cp->phys.header.savep; - np->header.goalp = cp->phys.header.goalp; - np->header.lastp = cp->phys.header.lastp; - - OUTL (nc_temp, scr_to_cpu(np->header.savep)); - OUTL (nc_dsp, scr_to_cpu(np->header.savep)); - return; - /* break; */ - -/*-------------------------------------------------------------------- -** -** Processing of interrupted getcc selects -** -**-------------------------------------------------------------------- -*/ - - case SIR_SENSE_RESTART: - /*------------------------------------------ - ** Script processor is idle. - ** Look for interrupted "check cond" - **------------------------------------------ - */ - - if (DEBUG_FLAGS & DEBUG_RESTART) - printf ("%s: int#%d",ncr_name (np),num); - cp = (ccb_p) 0; - for (i=0; itarget[i]; - if (DEBUG_FLAGS & DEBUG_RESTART) printf ("+"); - cp = tp->hold_cp; - if (!cp) continue; - if (DEBUG_FLAGS & DEBUG_RESTART) printf ("+"); - if ((cp->host_status==HS_BUSY) && - (cp->scsi_status==S_CHECK_COND)) - break; - if (DEBUG_FLAGS & DEBUG_RESTART) printf ("- (remove)"); - tp->hold_cp = cp = (ccb_p) 0; - }; - - if (cp) { - if (DEBUG_FLAGS & DEBUG_RESTART) - printf ("+ restart job ..\n"); - OUTL (nc_dsa, CCB_PHYS (cp, phys)); - OUTL (nc_dsp, NCB_SCRIPTH_PHYS (np, getcc)); - return; - }; - - /* - ** no job, resume normal processing - */ - if (DEBUG_FLAGS & DEBUG_RESTART) printf (" -- remove trap\n"); - np->script->start0[0] = cpu_to_scr(SCR_INT ^ IFFALSE (0)); - break; - - case SIR_SENSE_FAILED: - /*------------------------------------------- - ** While trying to select for - ** getting the condition code, - ** a target reselected us. - **------------------------------------------- - */ - if (DEBUG_FLAGS & DEBUG_RESTART) { - PRINT_ADDR(cp->cmd); - printf ("in getcc reselect by t%d.\n", - (int)INB(nc_ssid) & 0x0f); - } - - /* - ** Mark this job - */ - cp->host_status = HS_BUSY; - cp->scsi_status = S_CHECK_COND; - np->target[cp->cmd->target].hold_cp = cp; - - /* - ** And patch code to restart it. - */ - np->script->start0[0] = cpu_to_scr(SCR_INT); - break; - /*----------------------------------------------------------------------------- ** ** Was Sie schon immer ueber transfermode negotiation wissen wollten ... @@ -7699,7 +7860,7 @@ if (DEBUG_FLAGS & DEBUG_NEGO) { PRINT_ADDR(cp->cmd); - printf ("negotiation failed sir=%x status=%x.\n", + printk ("negotiation failed sir=%x status=%x.\n", num, cp->nego_status); }; @@ -7722,7 +7883,8 @@ np->msgout[0] = M_NOOP; cp->nego_status = 0; OUTL (nc_dsp, NCB_SCRIPT_PHYS (np, dispatch)); - break; + return; +/* break; */ case SIR_NEGO_SYNC: /* @@ -7731,9 +7893,9 @@ if (DEBUG_FLAGS & DEBUG_NEGO) { PRINT_ADDR(cp->cmd); - printf ("sync msgin: "); + printk ("sync msgin: "); (void) ncr_show_msg (np->msgin); - printf (".\n"); + printk (".\n"); }; /* @@ -7751,7 +7913,7 @@ */ if (ofs) - tp->inqdata[7] |= INQ7_SYNC; + tp->inq_byte7 |= INQ7_SYNC; /* ** check values against driver limits. @@ -7785,7 +7947,7 @@ if (DEBUG_FLAGS & DEBUG_NEGO) { PRINT_ADDR(cp->cmd); - printf ("sync: per=%d scntl3=0x%x ofs=%d fak=%d chg=%d.\n", + printk ("sync: per=%d scntl3=0x%x ofs=%d fak=%d chg=%d.\n", per, scntl3, ofs, fak, chg); } @@ -7819,20 +7981,6 @@ }; /* - ** It was a request. - ** Check against the table of target capabilities. - ** If target not capable force M_REJECT and asynchronous. - */ - if (np->unit < SCSI_NCR_MAX_HOST) { - tp->inqdata[7] &= - (target_capabilities[np->unit].and_map[target]); - if (!(tp->inqdata[7] & INQ7_SYNC)) { - ofs = 0; - fak = 7; - } - } - - /* ** It was a request. Set value and ** prepare an answer message */ @@ -7849,9 +7997,9 @@ if (DEBUG_FLAGS & DEBUG_NEGO) { PRINT_ADDR(cp->cmd); - printf ("sync msgout: "); + printk ("sync msgout: "); (void) ncr_show_msg (np->msgout); - printf (".\n"); + printk (".\n"); } if (!ofs) { @@ -7868,9 +8016,9 @@ */ if (DEBUG_FLAGS & DEBUG_NEGO) { PRINT_ADDR(cp->cmd); - printf ("wide msgin: "); + printk ("wide msgin: "); (void) ncr_show_msg (np->msgin); - printf (".\n"); + printk (".\n"); }; /* @@ -7886,7 +8034,7 @@ */ if (wide) - tp->inqdata[7] |= INQ7_WIDE16; + tp->inq_byte7 |= INQ7_WIDE16; /* ** check values against driver limits. @@ -7897,7 +8045,7 @@ if (DEBUG_FLAGS & DEBUG_NEGO) { PRINT_ADDR(cp->cmd); - printf ("wide: wide=%d chg=%d.\n", wide, chg); + printk ("wide: wide=%d chg=%d.\n", wide, chg); } if (INB (HS_PRT) == HS_NEGOTIATE) { @@ -7947,9 +8095,9 @@ if (DEBUG_FLAGS & DEBUG_NEGO) { PRINT_ADDR(cp->cmd); - printf ("wide msgout: "); + printk ("wide msgout: "); (void) ncr_show_msg (np->msgin); - printf (".\n"); + printk (".\n"); } break; @@ -7969,7 +8117,7 @@ */ PRINT_ADDR(cp->cmd); - printf ("M_REJECT received (%x:%x).\n", + printk ("M_REJECT received (%x:%x).\n", (unsigned)scr_to_cpu(np->lastmsg), np->msgout[0]); break; @@ -7982,9 +8130,9 @@ */ PRINT_ADDR(cp->cmd); - printf ("M_REJECT sent for "); + printk ("M_REJECT sent for "); (void) ncr_show_msg (np->msgin); - printf (".\n"); + printk (".\n"); break; /*-------------------------------------------------------------------- @@ -8004,9 +8152,9 @@ */ PRINT_ADDR(cp->cmd); - printf ("M_IGN_RESIDUE received, but not yet implemented.\n"); + printk ("M_IGN_RESIDUE received, but not yet implemented.\n"); break; - +#if 0 case SIR_MISSING_SAVE: /*----------------------------------------------- ** @@ -8017,92 +8165,13 @@ */ PRINT_ADDR(cp->cmd); - printf ("M_DISCONNECT received, but datapointer not saved: " + printk ("M_DISCONNECT received, but datapointer not saved: " "data=%x save=%x goal=%x.\n", (unsigned) INL (nc_temp), (unsigned) scr_to_cpu(np->header.savep), (unsigned) scr_to_cpu(np->header.goalp)); break; - -#if 0 /* This stuff does not work */ -/*-------------------------------------------------------------------- -** -** Processing of a "S_QUEUE_FULL" status. -** -** The current command has been rejected, -** because there are too many in the command queue. -** We have started too many commands for that target. -** -** If possible, reinsert at head of queue. -** Stall queue until there are no disconnected jobs -** (ncr is REALLY idle). Then restart processing. -** -** We should restart the current job after the controller -** has become idle. But this is not yet implemented. -** -**-------------------------------------------------------------------- -*/ - case SIR_STALL_QUEUE: - /*----------------------------------------------- - ** - ** Stall the start queue. - ** - **----------------------------------------------- - */ - PRINT_ADDR(cp->cmd); - printf ("queue full.\n"); - - np->script->start1[0] = cpu_to_scr(SCR_INT); - - /* - ** Try to disable tagged transfers. - */ - ncr_setmaxtags (np, &np->target[target], 0); - - /* - ** @QUEUE@ - ** - ** Should update the launch field of the - ** current job to be able to restart it. - ** Then prepend it to the start queue. - */ - - /* fall through */ - - case SIR_STALL_RESTART: - /*----------------------------------------------- - ** - ** Enable selecting again, - ** if NO disconnected jobs. - ** - **----------------------------------------------- - */ - /* - ** Look for a disconnected job. - */ - cp = np->ccb; - while (cp && cp->host_status != HS_DISCONNECT) - cp = cp->link_ccb; - - /* - ** if there is one, ... - */ - if (cp) { - /* - ** wait for reselection - */ - OUTL (nc_dsp, NCB_SCRIPT_PHYS (np, reselect)); - return; - }; - - /* - ** else remove the interrupt. - */ - - printf ("%s: queue empty.\n", ncr_name (np)); - np->script->start1[0] = cpu_to_scr(SCR_INT ^ IFFALSE (0)); - break; -#endif /* This stuff does not work */ +#endif }; out: @@ -8118,48 +8187,71 @@ **========================================================== */ -static ccb_p ncr_get_ccb - (ncb_p np, u_long target, u_long lun) +static ccb_p ncr_get_ccb (ncb_p np, u_char tn, u_char ln) { - lcb_p lp; + tcb_p tp = &np->target[tn]; + lcb_p lp = tp->lp[ln]; + u_char tag = NO_TAG; ccb_p cp = (ccb_p) 0; /* ** Lun structure available ? */ + if (lp) { + XPT_QUEHEAD *qp; + /* + ** Keep from using more tags than we can handle. + */ + if (lp->usetags && lp->busyccbs >= lp->maxnxs) + return (ccb_p) 0; - lp = np->target[target].lp[lun]; - - if (lp && lp->opennings && (!lp->active || lp->active < lp->reqlink)) { - - cp = lp->next_ccb; + /* + ** Allocate a new CCB if needed. + */ + if (xpt_que_empty(&lp->free_ccbq)) + ncr_alloc_ccb(np, tn, ln); /* + ** Tune tag mode if asked by user. + */ + if (lp->queuedepth != lp->numtags) { + ncr_setup_tags(np, tn, ln); + } + + /* ** Look for free CCB */ - - while (cp && cp->magic) cp = cp->next_ccb; + qp = xpt_remque_head(&lp->free_ccbq); + if (qp) { + cp = xpt_que_entry(qp, struct ccb, link_ccbq); + if (cp->magic) { + PRINT_LUN(np, tn, ln); + printk ("ccb free list corrupted (@%p)\n", cp); + cp = 0; + } + else { + xpt_insque_tail(qp, &lp->wait_ccbq); + ++lp->busyccbs; + } + } /* - ** Increment active commands and decrement credit. + ** If a CCB is available, + ** Get a tag for this nexus if required. */ - if (cp) { - ++lp->active; - --lp->opennings; + if (lp->usetags) + tag = lp->cb_tags[lp->ia_tag]; } + else if (lp->actccbs > 0) + return (ccb_p) 0; } /* ** if nothing available, take the default. - ** DANGEROUS, because this ccb is not suitable for - ** reselection. - ** If lp->actccbs > 0 wait for a suitable ccb to be free. */ - if ((!cp) && lp && lp->actccbs > 0) - return ((ccb_p) 0); - - if (!cp) cp = np->ccb; + if (!cp) + cp = np->ccb; /* ** Wait until available. @@ -8176,7 +8268,32 @@ return ((ccb_p) 0); cp->magic = 1; - return (cp); + + /* + ** Move to next available tag if tag used. + */ + if (lp) { + if (tag != NO_TAG) { + ++lp->ia_tag; + if (lp->ia_tag == SCSI_NCR_MAX_TAGS) + lp->ia_tag = 0; + lp->tags_umap |= (((tagmap_t) 1) << tag); + } + } + + /* + ** Remember all informations needed to free this CCB. + */ + cp->tag = tag; + cp->target = tn; + cp->lun = ln; + + if (DEBUG_FLAGS & DEBUG_TAGS) { + PRINT_LUN(np, tn, ln); + printk ("ccb @%p using tag %d.\n", cp, tag); + } + + return cp; } /*========================================================== @@ -8188,252 +8305,417 @@ **========================================================== */ -void ncr_free_ccb (ncb_p np, ccb_p cp, u_long target, u_long lun) +static void ncr_free_ccb (ncb_p np, ccb_p cp) { - lcb_p lp; + tcb_p tp = &np->target[cp->target]; + lcb_p lp = tp->lp[cp->lun]; + + if (DEBUG_FLAGS & DEBUG_TAGS) { + PRINT_LUN(np, cp->target, cp->lun); + printk ("ccb @%p freeing tag %d.\n", cp, cp->tag); + } /* - ** sanity + ** If lun control block available, + ** decrement active commands and increment credit, + ** free the tag if any and remove the JUMP for reselect. */ - - assert (cp != NULL); + if (lp) { + if (cp->tag != NO_TAG) { + lp->cb_tags[lp->if_tag++] = cp->tag; + if (lp->if_tag == SCSI_NCR_MAX_TAGS) + lp->if_tag = 0; + lp->tags_umap &= ~(((tagmap_t) 1) << cp->tag); + lp->tags_smap &= lp->tags_umap; + lp->jump_ccb[cp->tag] = + cpu_to_scr(NCB_SCRIPTH_PHYS(np, bad_i_t_l_q)); + } else { + lp->jump_ccb[0] = + cpu_to_scr(NCB_SCRIPTH_PHYS(np, bad_i_t_l)); + } + } /* - ** Decrement active commands and increment credit. + ** Make this CCB available. */ - lp = np->target[target].lp[lun]; if (lp) { - --lp->active; - ++lp->opennings; + if (cp != np->ccb) { + xpt_remque(&cp->link_ccbq); + xpt_insque_head(&cp->link_ccbq, &lp->free_ccbq); + } + --lp->busyccbs; + if (cp->queued) { + --lp->queuedccbs; + } } - cp -> host_status = HS_IDLE; cp -> magic = 0; + if (cp->queued) { + --np->queuedccbs; + cp->queued = 0; + } + #if 0 if (cp == np->ccb) wakeup ((caddr_t) cp); #endif } -/*========================================================== -** -** -** Allocation of resources for Targets/Luns/Tags. -** -** -**========================================================== -*/ -static void ncr_alloc_ccb (ncb_p np, u_long target, u_long lun) +#define ncr_reg_bus_addr(r) \ + (bus_dvma_to_mem(np->paddr) + offsetof (struct ncr_reg, r)) + +/*------------------------------------------------------------------------ +** Initialize the fixed part of a CCB structure. +**------------------------------------------------------------------------ +**------------------------------------------------------------------------ +*/ +static void ncr_init_ccb(ncb_p np, ccb_p cp) { - tcb_p tp; - lcb_p lp; - ccb_p cp; + ncrcmd copy_4 = np->features & FE_PFEN ? SCR_COPY(4) : SCR_COPY_F(4); - assert (np != NULL); + /* + ** Remember virtual and bus address of this ccb. + */ + cp->p_ccb = vtophys(cp); + cp->phys.header.cp = cp; - if (target>=MAX_TARGET) return; - if (lun >=MAX_LUN ) return; + /* + ** This allows xpt_remque to work for the default ccb. + */ + xpt_que_init(&cp->link_ccbq); - tp=&np->target[target]; + /* + ** Initialyze the start and restart launch script. + ** + ** COPY(4) @(...p_phys), @(dsa) + ** JUMP @(sched_point) + */ + cp->start.setup_dsa[0] = cpu_to_scr(copy_4); + cp->start.setup_dsa[1] = cpu_to_scr(vtophys(&cp->start.p_phys)); + cp->start.setup_dsa[2] = cpu_to_scr(ncr_reg_bus_addr(nc_dsa)); + cp->start.schedule.l_cmd = cpu_to_scr(SCR_JUMP); + cp->start.p_phys = cpu_to_scr(vtophys(&cp->phys)); - if (!tp->jump_tcb.l_cmd) { - /* - ** initialize it. - */ - tp->jump_tcb.l_cmd = - cpu_to_scr((SCR_JUMP^IFFALSE (DATA (0x80 + target)))); - tp->jump_tcb.l_paddr = np->jump_tcb.l_paddr; + bcopy(&cp->start, &cp->restart, sizeof(cp->restart)); - tp->getscr[0] = (np->features & FE_PFEN) ? - cpu_to_scr(SCR_COPY(1)):cpu_to_scr(SCR_COPY_F(1)); - tp->getscr[1] = cpu_to_scr(vtophys (&tp->sval)); - tp->getscr[2] = - cpu_to_scr(np->paddr + offsetof (struct ncr_reg, nc_sxfer)); + cp->start.schedule.l_paddr = cpu_to_scr(NCB_SCRIPT_PHYS (np, idle)); + cp->restart.schedule.l_paddr = cpu_to_scr(NCB_SCRIPTH_PHYS (np, abort)); +} - tp->getscr[3] = (np->features & FE_PFEN) ? - cpu_to_scr(SCR_COPY(1)):cpu_to_scr(SCR_COPY_F(1)); - tp->getscr[4] = cpu_to_scr(vtophys (&tp->wval)); - tp->getscr[5] = - cpu_to_scr(np->paddr + offsetof (struct ncr_reg, nc_scntl3)); - assert (( (offsetof(struct ncr_reg, nc_sxfer) ^ - offsetof(struct tcb , sval )) &3) == 0); - assert (( (offsetof(struct ncr_reg, nc_scntl3) ^ - offsetof(struct tcb , wval )) &3) == 0); +/*------------------------------------------------------------------------ +** Allocate a CCB and initialize its fixed part. +**------------------------------------------------------------------------ +**------------------------------------------------------------------------ +*/ +static void ncr_alloc_ccb(ncb_p np, u_char tn, u_char ln) +{ + tcb_p tp = &np->target[tn]; + lcb_p lp = tp->lp[ln]; + ccb_p cp = 0; - tp->call_lun.l_cmd = cpu_to_scr(SCR_CALL); - tp->call_lun.l_paddr = - cpu_to_scr(NCB_SCRIPT_PHYS (np, resel_lun)); + /* + ** Allocate memory for this CCB. + */ + cp = m_alloc(sizeof(struct ccb), 5); + if (!cp) + return; - tp->jump_lcb.l_cmd = cpu_to_scr(SCR_JUMP); - tp->jump_lcb.l_paddr = cpu_to_scr(NCB_SCRIPTH_PHYS (np, abort)); - np->jump_tcb.l_paddr = cpu_to_scr(vtophys (&tp->jump_tcb)); + if (DEBUG_FLAGS & DEBUG_ALLOC) { + PRINT_LUN(np, tn, ln); + printk ("new ccb @%p.\n", cp); } /* - ** Logic unit control block + ** Count it and initialyze it. */ - lp = tp->lp[lun]; - if (!lp) { - /* - ** Allocate a lcb - */ - lp = (lcb_p) m_alloc (sizeof (struct lcb), LCB_ALIGN_SHIFT); - if (!lp) return; + lp->actccbs++; + np->actccbs++; + bzero (cp, sizeof (*cp)); + ncr_init_ccb(np, cp); - if (DEBUG_FLAGS & DEBUG_ALLOC) { - PRINT_LUN(np, target, lun); - printf ("new lcb @%p.\n", lp); - } + /* + ** Chain into wakeup list and free ccb queue and take it + ** into account for tagged commands. + */ + cp->link_ccb = np->ccb->link_ccb; + np->ccb->link_ccb = cp; - /* - ** Initialize it - */ - bzero (lp, sizeof (*lp)); - lp->jump_lcb.l_cmd = - cpu_to_scr(SCR_JUMP ^ IFFALSE (DATA (lun))); - lp->jump_lcb.l_paddr = tp->jump_lcb.l_paddr; + xpt_insque_head(&cp->link_ccbq, &lp->free_ccbq); + ncr_setup_tags (np, tn, ln); +} + +/*========================================================== +** +** +** Allocation of resources for Targets/Luns/Tags. +** +** +**========================================================== +*/ - lp->call_tag.l_cmd = cpu_to_scr(SCR_CALL); - lp->call_tag.l_paddr = - cpu_to_scr(NCB_SCRIPT_PHYS (np, resel_tag)); - lp->jump_ccb.l_cmd = cpu_to_scr(SCR_JUMP); - lp->jump_ccb.l_paddr = - cpu_to_scr(NCB_SCRIPTH_PHYS (np, aborttag)); +/*------------------------------------------------------------------------ +** Target control block initialisation. +**------------------------------------------------------------------------ +** This data structure is fully initialized after a SCSI command +** has been successfully completed for this target. +** It contains a SCRIPT that is called on target reselection. +**------------------------------------------------------------------------ +*/ +static void ncr_init_tcb (ncb_p np, u_char tn) +{ + tcb_p tp = &np->target[tn]; + ncrcmd copy_1 = np->features & FE_PFEN ? SCR_COPY(1) : SCR_COPY_F(1); + int th = tn & 3; + int i; - lp->actlink = 1; + /* + ** Jump to next tcb if SFBR does not match this target. + ** JUMP IF (SFBR != #target#), @(next tcb) + */ + tp->jump_tcb.l_cmd = + cpu_to_scr((SCR_JUMP ^ IFFALSE (DATA (0x80 + tn)))); + tp->jump_tcb.l_paddr = np->jump_tcb[th].l_paddr; - lp->active = 1; + /* + ** Load the synchronous transfer register. + ** COPY @(tp->sval), @(sxfer) + */ + tp->getscr[0] = cpu_to_scr(copy_1); + tp->getscr[1] = cpu_to_scr(vtophys (&tp->sval)); + tp->getscr[2] = cpu_to_scr(ncr_reg_bus_addr(nc_sxfer)); + + /* + ** Load the timing register. + ** COPY @(tp->wval), @(scntl3) + */ + tp->getscr[3] = cpu_to_scr(copy_1); + tp->getscr[4] = cpu_to_scr(vtophys (&tp->wval)); + tp->getscr[5] = cpu_to_scr(ncr_reg_bus_addr(nc_scntl3)); - /* - ** Chain into LUN list - */ - tp->jump_lcb.l_paddr = cpu_to_scr(vtophys (&lp->jump_lcb)); - tp->lp[lun] = lp; + /* + ** Get the IDENTIFY message and the lun. + ** CALL @script(resel_lun) + */ + tp->call_lun.l_cmd = cpu_to_scr(SCR_CALL); + tp->call_lun.l_paddr = cpu_to_scr(NCB_SCRIPT_PHYS (np, resel_lun)); - ncr_setmaxtags (np, tp, driver_setup.default_tags); + /* + ** Look for the lun control block of this nexus. + ** For i = 0 to 3 + ** JUMP ^ IFTRUE (MASK (i, 3)), @(next_lcb) + */ + for (i = 0 ; i < 4 ; i++) { + tp->jump_lcb[i].l_cmd = + cpu_to_scr((SCR_JUMP ^ IFTRUE (MASK (i, 3)))); + tp->jump_lcb[i].l_paddr = + cpu_to_scr(NCB_SCRIPTH_PHYS (np, bad_identify)); } /* - ** Allocate ccbs up to lp->reqccbs. + ** Link this target control block to the JUMP chain. */ + np->jump_tcb[th].l_paddr = cpu_to_scr(vtophys (&tp->jump_tcb)); /* - ** Limit possible number of ccbs. - ** - ** If tagged command queueing is enabled, - ** can use more than one ccb. + ** These assert's should be moved at driver initialisations. */ - if (np->actccbs >= MAX_START-2) return; - if (lp->actccbs && (lp->actccbs >= lp->reqccbs)) - return; + assert (( (offsetof(struct ncr_reg, nc_sxfer) ^ + offsetof(struct tcb , sval )) &3) == 0); + assert (( (offsetof(struct ncr_reg, nc_scntl3) ^ + offsetof(struct tcb , wval )) &3) == 0); +} + + +/*------------------------------------------------------------------------ +** Lun control block allocation and initialization. +**------------------------------------------------------------------------ +** This data structure is allocated and initialized after a SCSI +** command has been successfully completed for this target/lun. +**------------------------------------------------------------------------ +*/ +static lcb_p ncr_alloc_lcb (ncb_p np, u_char tn, u_char ln) +{ + tcb_p tp = &np->target[tn]; + lcb_p lp = tp->lp[ln]; + ncrcmd copy_4 = np->features & FE_PFEN ? SCR_COPY(4) : SCR_COPY_F(4); + int lh = ln & 3; /* - ** Allocate a ccb + ** Already done, return. */ - cp = (ccb_p) m_alloc (sizeof (struct ccb), CCB_ALIGN_SHIFT); - if (!cp) - return; + if (lp) + return lp; + + /* + ** Allocate the lcb. + */ + lp = m_alloc(sizeof(struct lcb), 3); + if (!lp) + goto fail; + bzero(lp, sizeof(*lp)); + tp->lp[ln] = lp; if (DEBUG_FLAGS & DEBUG_ALLOC) { - PRINT_LUN(np, target, lun); - printf ("new ccb @%p.\n", cp); + PRINT_LUN(np, tn, ln); + printk ("new lcb @%p.\n", lp); } /* - ** Count it + ** Initialize the target control block if not yet. */ - lp->actccbs++; - np->actccbs++; + if (!tp->jump_tcb.l_cmd) + ncr_init_tcb(np, tn); /* - ** Initialize it + ** Initialize the CCB queue headers. */ - bzero (cp, sizeof (*cp)); + xpt_que_init(&lp->free_ccbq); + xpt_que_init(&lp->busy_ccbq); + xpt_que_init(&lp->wait_ccbq); + xpt_que_init(&lp->skip_ccbq); /* - ** Fill in physical addresses + ** Set max CCBs to 1 and use the default 1 entry + ** jump table by default. */ - - cp->p_ccb = vtophys (cp); + lp->maxnxs = 1; + lp->jump_ccb = &lp->jump_ccb_0; + lp->p_jump_ccb = cpu_to_scr(vtophys(lp->jump_ccb)); /* - ** Chain into reselect list + ** Initilialyze the reselect script: + ** + ** Jump to next lcb if SFBR does not match this lun. + ** Load TEMP with the CCB direct jump table bus address. + ** Get the SIMPLE TAG message and the tag. + ** + ** JUMP IF (SFBR != #lun#), @(next lcb) + ** COPY @(lp->p_jump_ccb), @(temp) + ** JUMP @script(resel_notag) */ - cp->jump_ccb.l_cmd = cpu_to_scr(SCR_JUMP); - cp->jump_ccb.l_paddr = lp->jump_ccb.l_paddr; - lp->jump_ccb.l_paddr = cpu_to_scr(CCB_PHYS (cp, jump_ccb)); - cp->call_tmp.l_cmd = cpu_to_scr(SCR_CALL); - cp->call_tmp.l_paddr = cpu_to_scr(NCB_SCRIPT_PHYS (np, resel_tmp)); + lp->jump_lcb.l_cmd = + cpu_to_scr((SCR_JUMP ^ IFFALSE (MASK (0x80+ln, 0xff)))); + lp->jump_lcb.l_paddr = tp->jump_lcb[lh].l_paddr; + + lp->load_jump_ccb[0] = cpu_to_scr(copy_4); + lp->load_jump_ccb[1] = cpu_to_scr(vtophys (&lp->p_jump_ccb)); + lp->load_jump_ccb[2] = cpu_to_scr(ncr_reg_bus_addr(nc_temp)); + + lp->jump_tag.l_cmd = cpu_to_scr(SCR_JUMP); + lp->jump_tag.l_paddr = cpu_to_scr(NCB_SCRIPT_PHYS (np, resel_notag)); /* - ** Chain into wakeup list + ** Link this lun control block to the JUMP chain. */ - cp->link_ccb = np->ccb->link_ccb; - np->ccb->link_ccb = cp; + tp->jump_lcb[lh].l_paddr = cpu_to_scr(vtophys (&lp->jump_lcb)); /* - ** Chain into CCB list + ** Initialize command queuing control. */ - cp->next_ccb = lp->next_ccb; - lp->next_ccb = cp; + lp->busyccbs = 1; + lp->queuedccbs = 1; + lp->queuedepth = 1; +fail: + return lp; } -/*========================================================== -** -** -** Announce the number of ccbs/tags to the scsi driver. -** -** -**========================================================== -*/ -static void ncr_opennings (ncb_p np, lcb_p lp, Scsi_Cmnd * cmd) +/*------------------------------------------------------------------------ +** Lun control block setup on INQUIRY data received. +**------------------------------------------------------------------------ +** We only support WIDE, SYNC for targets and CMDQ for logical units. +** This setup is done on each INQUIRY since we are expecting user +** will play with CHANGE DEFINITION commands. :-) +**------------------------------------------------------------------------ +*/ +static lcb_p ncr_setup_lcb (ncb_p np, u_char tn, u_char ln, u_char *inq_data) { + tcb_p tp = &np->target[tn]; + lcb_p lp = tp->lp[ln]; + u_char inq_byte7; + /* - ** want to reduce the number ... + ** If no lcb, try to allocate it. */ - if (lp->actlink > lp->reqlink) { + if (!lp && !(lp = ncr_alloc_lcb(np, tn, ln))) + goto fail; - /* - ** Try to reduce the count. - ** We assume to run at splbio .. - */ - u_char diff = lp->actlink - lp->reqlink; + /* + ** Get device quirks from a speciality table. + */ + tp->quirks = ncr_lookup (inq_data); + if (tp->quirks && bootverbose) { + PRINT_LUN(np, tn, ln); + printk ("quirks=%x.\n", tp->quirks); + } - if (!diff) return; + /* + ** Evaluate trustable target/unit capabilities. + ** We only believe device version >= SCSI-2 that + ** use appropriate response data format (2). + */ + inq_byte7 = 0; + if ((inq_data[2] & 0x7) >= 2 && (inq_data[3] & 0xf) == 2) + inq_byte7 = inq_data[7]; - if (diff > lp->opennings) - diff = lp->opennings; + /* + ** Throw away announced LUN capabilities if we are told + ** that there is no real device supported by the logical unit. + */ + if ((inq_data[0] & 0xe0) > 0x20 || (inq_data[0] & 0x1f) == 0x1f) + inq_byte7 &= (INQ7_SYNC | INQ7_WIDE16); - lp->opennings -= diff; + /* + ** If user is wanting SYNC, force this feature. + */ + if (driver_setup.force_sync_nego) + inq_byte7 |= INQ7_SYNC; - lp->actlink -= diff; - if (DEBUG_FLAGS & DEBUG_TAGS) - printf ("%s: actlink: diff=%d, new=%d, req=%d\n", - ncr_name(np), diff, lp->actlink, lp->reqlink); - return; - }; + /* + ** Prepare negotiation if SIP capabilities have changed. + */ + tp->inq_done = 1; + if ((inq_byte7 ^ tp->inq_byte7) & (INQ7_SYNC | INQ7_WIDE16)) { + tp->inq_byte7 = inq_byte7; + ncr_negotiate(np, tp); + } /* - ** want to increase the number ? + ** If unit supports tagged commands, allocate the + ** CCB JUMP table if not yet. */ - if (lp->reqlink > lp->actlink) { - u_char diff = lp->reqlink - lp->actlink; + if ((inq_byte7 & INQ7_QUEUE) && lp->jump_ccb == &lp->jump_ccb_0) { + int i; + lp->jump_ccb = m_alloc(256, 8); + if (!lp->jump_ccb) { + lp->jump_ccb = &lp->jump_ccb_0; + goto fail; + } + lp->p_jump_ccb = cpu_to_scr(vtophys(lp->jump_ccb)); + for (i = 0 ; i < 64 ; i++) + lp->jump_ccb[i] = + cpu_to_scr(NCB_SCRIPTH_PHYS (np, bad_i_t_l_q)); + for (i = 0 ; i < SCSI_NCR_MAX_TAGS ; i++) + lp->cb_tags[i] = i; + lp->maxnxs = SCSI_NCR_MAX_TAGS; + lp->tags_stime = jiffies; + } - lp->opennings += diff; + /* + ** Adjust tagged queueing status if needed. + */ + if ((inq_byte7 ^ lp->inq_byte7) & INQ7_QUEUE) { + lp->inq_byte7 = inq_byte7; + lp->numtags = lp->maxtags; + ncr_setup_tags (np, tn, ln); + } - lp->actlink += diff; -#if 0 - wakeup ((caddr_t) xp->sc_link); -#endif - if (DEBUG_FLAGS & DEBUG_TAGS) - printf ("%s: actlink: diff=%d, new=%d, req=%d\n", - ncr_name(np), diff, lp->actlink, lp->reqlink); - }; +fail: + return lp; } /*========================================================== @@ -8471,9 +8753,6 @@ int segment = 0; int use_sg = (int) cmd->use_sg; -#if 0 - bzero (cp->phys.data, sizeof (cp->phys.data)); -#endif data = cp->phys.data; cp->data_len = 0; @@ -8522,7 +8801,7 @@ static int ncr_regtest (struct ncb* np) ) { - register volatile u_long data; + register volatile u_int32 data; /* ** ncr registers may NOT be cached. ** write 0xffffffff to a read only register area, @@ -8536,7 +8815,7 @@ #else if ((data & 0xe2f0fffd) != 0x02000080) { #endif - printf ("CACHE TEST FAILED: reg dstat-sstat2 readback %x.\n", + printk ("CACHE TEST FAILED: reg dstat-sstat2 readback %x.\n", (unsigned) data); return (0x10); }; @@ -8548,8 +8827,8 @@ static int ncr_snooptest (struct ncb* np) ) { - u_long ncr_rd, ncr_wr, ncr_bk, host_rd, host_wr, pc, err=0; - int i; + u_int32 ncr_rd, ncr_wr, ncr_bk, host_rd, host_wr, pc; + int i, err=0; #ifndef NCR_IOMAPPED if (np->reg) { err |= ncr_regtest (np); @@ -8591,22 +8870,22 @@ ** Reset ncr chip */ OUTB (nc_istat, SRST); - DELAY (1000); + UDELAY (100); OUTB (nc_istat, 0 ); /* ** check for timeout */ if (i>=NCR_SNOOP_TIMEOUT) { - printf ("CACHE TEST FAILED: timeout.\n"); + printk ("CACHE TEST FAILED: timeout.\n"); return (0x20); }; /* ** Check termination position. */ if (pc != NCB_SCRIPTH_PHYS (np, snoopend)+8) { - printf ("CACHE TEST FAILED: script execution failed.\n"); - printf ("start=%08lx, pc=%08lx, end=%08lx\n", - (u_long) NCB_SCRIPTH_PHYS (np, snooptest), pc, + printk ("CACHE TEST FAILED: script execution failed.\n"); + printk ("start=%08lx, pc=%08lx, end=%08lx\n", + (u_long) NCB_SCRIPTH_PHYS (np, snooptest), (u_long) pc, (u_long) NCB_SCRIPTH_PHYS (np, snoopend) +8); return (0x40); }; @@ -8614,17 +8893,17 @@ ** Show results. */ if (host_wr != ncr_rd) { - printf ("CACHE TEST FAILED: host wrote %d, ncr read %d.\n", + printk ("CACHE TEST FAILED: host wrote %d, ncr read %d.\n", (int) host_wr, (int) ncr_rd); err |= 1; }; if (host_rd != ncr_wr) { - printf ("CACHE TEST FAILED: ncr wrote %d, host read %d.\n", + printk ("CACHE TEST FAILED: ncr wrote %d, host read %d.\n", (int) ncr_wr, (int) host_rd); err |= 2; }; if (ncr_bk != ncr_wr) { - printf ("CACHE TEST FAILED: ncr wrote %d, read back %d.\n", + printk ("CACHE TEST FAILED: ncr wrote %d, read back %d.\n", (int) ncr_wr, (int) ncr_bk); err |= 4; }; @@ -8652,8 +8931,8 @@ #define PROFILE cp->phys.header.stamp static void ncb_profile (ncb_p np, ccb_p cp) { - int co, st, en, di, se, post,work,disc; - u_long diff; + long co, st, en, di, re, post, work, disc; + u_int diff; PROFILE.end = jiffies; @@ -8665,18 +8944,18 @@ en = ncr_delta (PROFILE.start,PROFILE.end), di = ncr_delta (PROFILE.start,PROFILE.disconnect), - se = ncr_delta (PROFILE.start,PROFILE.select); + re = ncr_delta (PROFILE.start,PROFILE.reselect); post = en - st; /* ** @PROFILE@ Disconnect time invalid if multiple disconnects */ - if (di>=0) disc = se-di; else disc = 0; + if (di>=0) disc = re - di; else disc = 0; work = (st - co) - disc; - diff = (np->disc_phys - np->disc_ref) & 0xff; + diff = (scr_to_cpu(np->disc_phys) - np->disc_ref) & 0xff; np->disc_ref += diff; np->profile.num_trans += 1; @@ -8718,13 +8997,13 @@ static struct table_entry device_tab[] = { -#ifdef NCR_GETCC_WITHMSG +#if 0 {"", "", "", QUIRK_NOMSG}, +#endif {"SONY", "SDT-5000", "3.17", QUIRK_NOMSG}, {"WangDAT", "Model 2600", "01.7", QUIRK_NOMSG}, {"WangDAT", "Model 3200", "02.2", QUIRK_NOMSG}, {"WangDAT", "Model 1300", "02.4", QUIRK_NOMSG}, -#endif {"", "", "", 0} /* catch all: must be last entry. */ }; @@ -8788,21 +9067,21 @@ } if (bootverbose >= 2) - printf ("%s: enabling clock multiplier\n", ncr_name(np)); + printk ("%s: enabling clock multiplier\n", ncr_name(np)); OUTB(nc_stest1, DBLEN); /* Enable clock multiplier */ if (np->multiplier > 2) { /* Poll bit 5 of stest4 for quadrupler */ int i = 20; while (!(INB(nc_stest4) & LCKFRQ) && --i > 0) - DELAY(20); + UDELAY (20); if (!i) - printf("%s: the chip cannot lock the frequency\n", ncr_name(np)); + printk("%s: the chip cannot lock the frequency\n", ncr_name(np)); } else /* Wait 20 micro-seconds for doubler */ - DELAY(20); + UDELAY (20); OUTB(nc_stest3, HSC); /* Halt the scsi clock */ OUTB(nc_scntl3, scntl3); OUTB(nc_stest1, (DBLEN|DBLSEL));/* Select clock multiplier */ - OUTB(nc_stest3, 0x00|TE); /* Restart scsi clock */ + OUTB(nc_stest3, 0x00); /* Restart scsi clock */ } @@ -8839,7 +9118,7 @@ OUTB (nc_stime1, 0); /* disable general purpose timer */ OUTB (nc_stime1, gen); /* set to nominal delay of 1<= 2) - printf ("%s: Delay (GEN=%d): %u msec\n", ncr_name(np), gen, ms); + printk ("%s: Delay (GEN=%d): %u msec\n", ncr_name(np), gen, ms); /* * adjust for prescaler, and convert into KHz */ @@ -8875,7 +9154,7 @@ */ if (mult > 1 && (stest1 & (DBLEN+DBLSEL)) == DBLEN+DBLSEL) { if (bootverbose >= 2) - printf ("%s: clock multiplier found\n", ncr_name(np)); + printk ("%s: clock multiplier found\n", ncr_name(np)); np->multiplier = mult; } @@ -8887,14 +9166,14 @@ if (np->multiplier != mult || (scntl3 & 7) < 3 || !(scntl3 & 1)) { unsigned f2; - OUTB(nc_istat, SRST); DELAY(5); OUTB(nc_istat, 0); + OUTB(nc_istat, SRST); UDELAY (5); OUTB(nc_istat, 0); (void) ncrgetfreq (np, 11); /* throw away first result */ f1 = ncrgetfreq (np, 11); f2 = ncrgetfreq (np, 11); if (bootverbose) - printf ("%s: NCR clock is %uKHz, %uKHz\n", ncr_name(np), f1, f2); + printk ("%s: NCR clock is %uKHz, %uKHz\n", ncr_name(np), f1, f2); if (f1 > f2) f1 = f2; /* trust lower result */ @@ -8904,7 +9183,7 @@ if (f1 < 80000 && mult > 1) { if (bootverbose >= 2) - printf ("%s: clock multiplier assumed\n", ncr_name(np)); + printk ("%s: clock multiplier assumed\n", ncr_name(np)); np->multiplier = mult; } } else { @@ -8943,6 +9222,12 @@ ** --------------------------------------------------------------------- */ +#ifdef MODULE +#define ARG_SEP ' ' +#else +#define ARG_SEP ',' +#endif + __initfunc( void ncr53c8xx_setup(char *str, int *ints) ) @@ -8955,33 +9240,33 @@ int c; while (cur != NULL && (pc = strchr(cur, ':')) != NULL) { + char *pe; + val = 0; pv = pc; c = *++pv; + if (c == 'n') val = 0; else if (c == 'y') val = 1; else { base = 0; -#if 0 - if (c == '0') { - c = *pv++; - base = 8; - } - if (c == 'x') { - ++pv; - base = 16; + val = (int) simple_strtoul(pv, &pe, base); + } + if (!strncmp(cur, "tags:", 5)) { + int i; + driver_setup.default_tags = val; + if (pe && *pe == '/') { + i = 0; + while (*pe && *pe != ARG_SEP && + i < sizeof(driver_setup.tag_ctrl)-1) { + driver_setup.tag_ctrl[i++] = *pe++; + } + driver_setup.tag_ctrl[i] = '\0'; } - else if (c >= '0' && c <= '9') - base = 10; - else - break; -#endif - val = (int) simple_strtoul(pv, NULL, base); } - - if (!strncmp(cur, "mpar:", 5)) + else if (!strncmp(cur, "mpar:", 5)) driver_setup.master_parity = val; else if (!strncmp(cur, "spar:", 5)) driver_setup.scsi_parity = val; @@ -8995,11 +9280,6 @@ driver_setup.force_sync_nego = val; else if (!strncmp(cur, "revprob:", 8)) driver_setup.reverse_probe = val; - else if (!strncmp(cur, "tags:", 5)) { - if (val > SCSI_NCR_MAX_TAGS) - val = SCSI_NCR_MAX_TAGS; - driver_setup.default_tags = val; - } else if (!strncmp(cur, "sync:", 5)) driver_setup.default_sync = val; else if (!strncmp(cur, "verb:", 5)) @@ -9030,13 +9310,9 @@ else if (!strncmp(cur, "safe:", 5) && val) memcpy(&driver_setup, &driver_safe_setup, sizeof(driver_setup)); else - printf("ncr53c8xx_setup: unexpected boot option '%.*s' ignored\n", (int)(pc-cur+1), cur); + printk("ncr53c8xx_setup: unexpected boot option '%.*s' ignored\n", (int)(pc-cur+1), cur); -#ifdef MODULE - if ((cur = strchr(cur, ' ')) != NULL) -#else - if ((cur = strchr(cur, ',')) != NULL) -#endif + if ((cur = strchr(cur, ARG_SEP)) != NULL) ++cur; } #endif /* SCSI_NCR_BOOT_COMMAND_LINE_SUPPORT */ @@ -9065,24 +9341,31 @@ ) { #define YesNo(y) y ? 'y' : 'n' - printk("ncr53c8xx: setup=disc:%c,specf:%d,ultra:%c,tags:%d,sync:%d,burst:%d,wide:%c,diff:%d\n", - YesNo(driver_setup.disconnection), - driver_setup.special_features, - YesNo(driver_setup.ultra_scsi), - driver_setup.default_tags, - driver_setup.default_sync, - driver_setup.burst_max, - YesNo(driver_setup.max_wide), - driver_setup.diff_support); - printk("ncr53c8xx: setup=mpar:%c,spar:%c,fsn=%c,verb:%d,debug:0x%x,led:%c,settle:%d,irqm:%d\n", - YesNo(driver_setup.master_parity), - YesNo(driver_setup.scsi_parity), - YesNo(driver_setup.force_sync_nego), - driver_setup.verbose, - driver_setup.debug, - YesNo(driver_setup.led_pin), - driver_setup.settle_delay, - driver_setup.irqm); + printk ("ncr53c8xx: setup=disc:%c,specf:%d,ultra:%d,tags:%d,sync:%d," + "burst:%d,wide:%c,diff:%d,revprob:%c,buschk:0x%x\n", + YesNo(driver_setup.disconnection), + driver_setup.special_features, + driver_setup.ultra_scsi, + driver_setup.default_tags, + driver_setup.default_sync, + driver_setup.burst_max, + YesNo(driver_setup.max_wide), + driver_setup.diff_support, + YesNo(driver_setup.reverse_probe), + driver_setup.bus_check); + + printk ("ncr53c8xx: setup=mpar:%c,spar:%c,fsn=%c,verb:%d,debug:0x%x," + "led:%c,settle:%d,irqm:%d,nvram:0x%x,pcifix:0x%x\n", + YesNo(driver_setup.master_parity), + YesNo(driver_setup.scsi_parity), + YesNo(driver_setup.force_sync_nego), + driver_setup.verbose, + driver_setup.debug, + YesNo(driver_setup.led_pin), + driver_setup.settle_delay, + driver_setup.irqm, + driver_setup.use_nvram, + driver_setup.pci_fix_up); #undef YesNo } @@ -9102,7 +9385,7 @@ int i, j; int attach_count = 0; ncr_nvram *nvram; - ncr_device *devp; + ncr_device *devp = 0; /* to shut up gcc */ if (!nvram_index) return 0; @@ -9117,13 +9400,13 @@ if (nvram_index == -1) nvram_index = i; #ifdef SCSI_NCR_DEBUG_NVRAM - printf("ncr53c8xx: NVRAM: Symbios format Boot Block, 53c%s, PCI bus %d, device %d, function %d\n", + printk("ncr53c8xx: NVRAM: Symbios format Boot Block, 53c%s, PCI bus %d, device %d, function %d\n", devp->chip.name, devp->slot.bus, (int) (devp->slot.device_fn & 0xf8) >> 3, (int) devp->slot.device_fn & 7); for (j = 0 ; j < 4 ; j++) { Symbios_host *h = &nvram->data.Symbios.host[j]; - printf("ncr53c8xx: BOOT[%d] device_id=%04x vendor_id=%04x device_fn=%02x io_port=%04x %s\n", + printk("ncr53c8xx: BOOT[%d] device_id=%04x vendor_id=%04x device_fn=%02x io_port=%04x %s\n", j, h->device_id, h->vendor_id, h->device_fn, h->io_port, (h->flags & SYMBIOS_INIT_SCAN_AT_BOOT) ? "SCAN AT BOOT" : ""); @@ -9131,7 +9414,7 @@ } else if (nvram->type == SCSI_NCR_TEKRAM_NVRAM) { /* display Tekram nvram data */ - printf("ncr53c8xx: NVRAM: Tekram format data, 53c%s, PCI bus %d, device %d, function %d\n", + printk("ncr53c8xx: NVRAM: Tekram format data, 53c%s, PCI bus %d, device %d, function %d\n", devp->chip.name, devp->slot.bus, (int) (devp->slot.device_fn & 0xf8) >> 3, (int) devp->slot.device_fn & 7); @@ -9198,18 +9481,14 @@ #ifdef SCSI_NCR_NVRAM_SUPPORT int nvram_index = 0; #endif - if (initverbose >= 2) - ncr_print_driver_setup(); #ifdef SCSI_NCR_DEBUG_INFO_SUPPORT ncr_debug = driver_setup.debug; #endif -#if LINUX_VERSION_CODE >= LinuxVersionCode(1,3,0) tpnt->proc_dir = &proc_scsi_ncr53c8xx; -# ifdef SCSI_NCR_PROC_INFO_SUPPORT +#ifdef SCSI_NCR_PROC_INFO_SUPPORT tpnt->proc_info = ncr53c8xx_proc_info; -# endif #endif #if defined(SCSI_NCR_BOOT_COMMAND_LINE_SUPPORT) && defined(MODULE) @@ -9217,6 +9496,9 @@ ncr53c8xx_setup(ncr53c8xx, (int *) 0); #endif + if (initverbose >= 2) + ncr_print_driver_setup(); + /* ** Detect all 53c8xx hosts and then attach them. ** @@ -9228,7 +9510,11 @@ ** the order they are detected. */ +#if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,92) + if (!pci_present()) +#else if (!pcibios_present()) +#endif return 0; chips = sizeof(ncr_chip_ids) / sizeof(ncr_chip_ids[0]); @@ -9276,7 +9562,7 @@ } } #endif - printf(KERN_INFO "ncr53c8xx: 53c%s detected %s\n", + printk(KERN_INFO "ncr53c8xx: 53c%s detected %s\n", device[count].chip.name, msg); ++count; } @@ -9292,7 +9578,7 @@ for (i= 0; i < count; i++) { if (!device[i].attach_done && !ncr_attach (tpnt, attach_count, &device[i])) { - attach_count++; + attach_count++; } } @@ -9312,11 +9598,14 @@ { ushort vendor_id, device_id, command; uchar cache_line_size, latency_timer; - uchar irq, revision; -#if LINUX_VERSION_CODE >= LinuxVersionCode(1,3,0) - uint base, base_2, io_port; + uchar revision; +#if LINUX_VERSION_CODE > LinuxVersionCode(2,1,92) + struct pci_dev *pdev; + ulong base, base_2, io_port; + uint irq; #else - ulong base, base_2; + uchar irq; + uint base, base_2, io_port; #endif int i; @@ -9325,8 +9614,6 @@ #endif ncr_chip *chip; - printk(KERN_INFO "ncr53c8xx: at PCI bus %d, device %d, function %d\n", - bus, (int) (device_fn & 0xf8) >> 3, (int) device_fn & 7); /* * Read info from the PCI config space. * pcibios_read_config_xxx() functions are assumed to be used for @@ -9340,16 +9627,29 @@ PCI_DEVICE_ID, &device_id); (void) pcibios_read_config_word(bus, device_fn, PCI_COMMAND, &command); +#if LINUX_VERSION_CODE > LinuxVersionCode(2,1,92) + pdev = pci_find_slot(bus, device_fn); + io_port = pdev->base_address[0]; + base = pdev->base_address[1]; + base_2 = pdev->base_address[2]; + irq = pdev->irq; +#else (void) pcibios_read_config_dword(bus, device_fn, PCI_BASE_ADDRESS_0, &io_port); (void) pcibios_read_config_dword(bus, device_fn, PCI_BASE_ADDRESS_1, &base); (void) pcibios_read_config_dword(bus, device_fn, PCI_BASE_ADDRESS_2, &base_2); - (void) pcibios_read_config_byte(bus, device_fn, - PCI_CLASS_REVISION,&revision); + + /* Handle 64bit base adresses for 53C896. */ + if ((base & PCI_BASE_ADDRESS_MEM_TYPE_MASK) == PCI_BASE_ADDRESS_MEM_TYPE_64) + (void) pcibios_read_config_dword(bus, device_fn, + PCI_BASE_ADDRESS_3, &base_2); (void) pcibios_read_config_byte(bus, device_fn, PCI_INTERRUPT_LINE, &irq); +#endif + (void) pcibios_read_config_byte(bus, device_fn, + PCI_CLASS_REVISION,&revision); (void) pcibios_read_config_byte(bus, device_fn, PCI_CACHE_LINE_SIZE, &cache_line_size); (void) pcibios_read_config_byte(bus, device_fn, @@ -9369,6 +9669,34 @@ chip->revision_id = revision; break; } + +#if defined(__i386__) + /* + * Ignore Symbios chips controlled by SISL RAID controller. + */ + if (chip && (base_2 & PCI_BASE_ADDRESS_MEM_MASK)) { + unsigned int ScriptsSize, MagicValue; + vm_offset_t ScriptsRAM; + + if (chip->features & FE_RAM8K) + ScriptsSize = 8192; + else + ScriptsSize = 4096; + + ScriptsRAM = remap_pci_mem(base_2 & PCI_BASE_ADDRESS_MEM_MASK, + ScriptsSize); + if (ScriptsRAM) { + MagicValue = readl(ScriptsRAM + ScriptsSize - 16); + unmap_pci_mem(ScriptsRAM, ScriptsSize); + if (MagicValue == 0x52414944) + return -1; + } + } +#endif + + printk(KERN_INFO "ncr53c8xx: at PCI bus %d, device %d, function %d\n", + bus, (int) (device_fn & 0xf8) >> 3, (int) device_fn & 7); + if (!chip) { printk("ncr53c8xx: not initializing, device not supported\n"); return -1; @@ -9376,25 +9704,111 @@ #ifdef __powerpc__ /* - * Severall fix-up for power/pc. + * Several fix-up for power/pc. * Should not be performed by the driver. */ - if ((command & - (PCI_COMMAND_MASTER|PCI_COMMAND_IO|PCI_COMMAND_MEMORY)) != - (PCI_COMMAND_MASTER|PCI_COMMAND_IO|PCI_COMMAND_MEMORY)) { - printk("ncr53c8xx : setting PCI master/io/command bit\n"); - command |= PCI_COMMAND_MASTER|PCI_COMMAND_IO|PCI_COMMAND_MEMORY; + if (!(command & PCI_COMMAND_MASTER)) { + printk("ncr53c8xx: attempting to force PCI_COMMAND_MASTER..."); + command |= PCI_COMMAND_MASTER; pcibios_write_config_word(bus, device_fn, PCI_COMMAND, command); + pcibios_read_config_word(bus, device_fn, PCI_COMMAND, &command); + if (!(command & PCI_COMMAND_MASTER)) { + printk("failed!\n"); + } else { + printk("succeeded.\n"); + } } - if (io_port >= 0x10000000) { - io_port = (io_port & 0x00FFFFFF) | 0x01000000; - pcibios_write_config_dword(bus, device_fn, PCI_BASE_ADDRESS_0, io_port); - } - if (base >= 0x10000000) { - base = (base & 0x00FFFFFF) | 0x01000000; - pcibios_write_config_dword(bus, device_fn, PCI_BASE_ADDRESS_1, base); + + if (!(command & PCI_COMMAND_IO)) { + printk("ncr53c8xx: attempting to force PCI_COMMAND_IO..."); + command |= PCI_COMMAND_IO; + pcibios_write_config_word(bus, device_fn, PCI_COMMAND, command); + pcibios_read_config_word(bus, device_fn, PCI_COMMAND, &command); + if (!(command & PCI_COMMAND_IO)) { + printk("failed!\n"); + } else { + printk("succeeded.\n"); + } } -#endif + + if (!(command & PCI_COMMAND_MEMORY)) { + printk("ncr53c8xx: attempting to force PCI_COMMAND_MEMORY..."); + command |= PCI_COMMAND_MEMORY; + pcibios_write_config_word(bus, device_fn, PCI_COMMAND, command); + pcibios_read_config_word(bus, device_fn, PCI_COMMAND, &command); + if (!(command & PCI_COMMAND_MEMORY)) { + printk("failed!\n"); + } else { + printk("succeeded.\n"); + } + } + + if ( is_prep ) { + if (io_port >= 0x10000000) { + printk("ncr53c8xx: reallocating io_port (Wacky IBM)"); + io_port = (io_port & 0x00FFFFFF) | 0x01000000; + pcibios_write_config_dword(bus, device_fn, PCI_BASE_ADDRESS_0, io_port); + } + if (base >= 0x10000000) { + printk("ncr53c8xx: reallocating base (Wacky IBM)"); + base = (base & 0x00FFFFFF) | 0x01000000; + pcibios_write_config_dword(bus, device_fn, PCI_BASE_ADDRESS_1, base); + } + if (base_2 >= 0x10000000) { + printk("ncr53c8xx: reallocating base2 (Wacky IBM)"); + base_2 = (base_2 & 0x00FFFFFF) | 0x01000000; + pcibios_write_config_dword(bus, device_fn, PCI_BASE_ADDRESS_2, base_2); + } + } +#endif /* __powerpc__ */ + +#ifdef __sparc__ + /* + * Severall fix-ups for sparc. + * + * Should not be performed by the driver, but how can OBP know + * each and every PCI card, if they don't use Fcode? + */ + + base = __pa(base); + base_2 = __pa(base_2); + + if (!(command & PCI_COMMAND_MASTER)) { + if (initverbose >= 2) + printk("ncr53c8xx: setting PCI_COMMAND_MASTER bit (fixup)\n"); + command |= PCI_COMMAND_MASTER; + pcibios_write_config_word(bus, device_fn, PCI_COMMAND, command); + pcibios_read_config_word(bus, device_fn, PCI_COMMAND, &command); + } + + if ((chip->features & FE_WRIE) && !(command & PCI_COMMAND_INVALIDATE)) { + if (initverbose >= 2) + printk("ncr53c8xx: setting PCI_COMMAND_INVALIDATE bit (fixup)\n"); + command |= PCI_COMMAND_INVALIDATE; + pcibios_write_config_word(bus, device_fn, PCI_COMMAND, command); + pcibios_read_config_word(bus, device_fn, PCI_COMMAND, &command); + } + + if ((chip->features & FE_CLSE) && !cache_line_size) { + cache_line_size = CACHE_LINE_SIZE; + if (initverbose >= 2) + printk("ncr53c8xx: setting PCI_CACHE_LINE_SIZE to %d (fixup)\n", cache_line_size); + pcibios_write_config_byte(bus, device_fn, + PCI_CACHE_LINE_SIZE, cache_line_size); + pcibios_read_config_byte(bus, device_fn, + PCI_CACHE_LINE_SIZE, &cache_line_size); + } + + if (!latency_timer) { + latency_timer = 248; + if (initverbose >= 2) + printk("ncr53c8xx: setting PCI_LATENCY_TIMER to %d bus clocks (fixup)\n", latency_timer); + pcibios_write_config_byte(bus, device_fn, + PCI_LATENCY_TIMER, latency_timer); + pcibios_read_config_byte(bus, device_fn, + PCI_LATENCY_TIMER, &latency_timer); + } +#endif /* __sparc__ */ /* * Check availability of IO space, memory space and master capability. @@ -9431,8 +9845,13 @@ base_2 &= PCI_BASE_ADDRESS_MEM_MASK; if (io_port && check_region (io_port, 128)) { +#ifdef __sparc__ + printk("ncr53c8xx: IO region 0x%lx to 0x%lx is in use\n", + io_port, (io_port + 127)); +#else printk("ncr53c8xx: IO region 0x%x to 0x%x is in use\n", (int) io_port, (int) (io_port + 127)); +#endif return -1; } @@ -9465,7 +9884,7 @@ /* * Try to fix up PCI config according to wished features. */ -#if defined(__i386) && !defined(MODULE) +#if defined(__i386__) && !defined(MODULE) if ((driver_setup.pci_fix_up & 1) && (chip->features & FE_CLSE) && cache_line_size == 0) { #if LINUX_VERSION_CODE < LinuxVersionCode(2,1,75) @@ -9475,6 +9894,7 @@ switch(boot_cpu_data.x86) { #endif case 4: cache_line_size = 4; break; + case 6: case 5: cache_line_size = 8; break; } if (cache_line_size) @@ -9610,35 +10030,111 @@ return 0; } -#if LINUX_VERSION_CODE >= LinuxVersionCode(2,0,0) /* ** Linux select queue depths function */ + +#define DEF_DEPTH (driver_setup.default_tags) +#define ALL_TARGETS -2 +#define NO_TARGET -1 +#define ALL_LUNS -2 +#define NO_LUN -1 + +static int device_queue_depth(ncb_p np, int target, int lun) +{ + int c, h, t, u, v; + char *p = driver_setup.tag_ctrl; + char *ep; + + h = -1; + t = NO_TARGET; + u = NO_LUN; + while ((c = *p++) != 0) { + v = simple_strtoul(p, &ep, 0); + switch(c) { + case '/': + ++h; + t = ALL_TARGETS; + u = ALL_LUNS; + break; + case 't': + if (t != target) + t = (target == v) ? v : NO_TARGET; + u = ALL_LUNS; + break; + case 'u': + if (u != lun) + u = (lun == v) ? v : NO_LUN; + break; + case 'q': + if (h == np->unit && + (t == ALL_TARGETS || t == target) && + (u == ALL_LUNS || u == lun)) + return v; + break; + case '-': + t = ALL_TARGETS; + u = ALL_LUNS; + break; + default: + break; + } + p = ep; + } + return DEF_DEPTH; +} + static void ncr53c8xx_select_queue_depths(struct Scsi_Host *host, struct scsi_device *devlist) { struct scsi_device *device; for (device = devlist; device; device = device->next) { - if (device->host == host) { -#if SCSI_NCR_MAX_TAGS > 1 - if (device->tagged_supported) { - device->queue_depth = SCSI_NCR_MAX_TAGS; - } - else { - device->queue_depth = 2; - } -#else - device->queue_depth = 1; -#endif + ncb_p np; + tcb_p tp; + lcb_p lp; + int numtags; + + if (device->host != host) + continue; + + np = ((struct host_data *) host->hostdata)->ncb; + tp = &np->target[device->id]; + lp = tp->lp[device->lun]; + + /* + ** Select queue depth from driver setup. + ** Donnot use more than configured by user. + ** Use at least 2. + ** Donnot use more than our maximum. + */ + numtags = device_queue_depth(np, device->id, device->lun); + if (numtags > tp->usrtags) + numtags = tp->usrtags; + if (!device->tagged_supported) + numtags = 1; + device->queue_depth = numtags; + if (device->queue_depth < 2) + device->queue_depth = 2; + if (device->queue_depth > SCSI_NCR_MAX_TAGS) + device->queue_depth = SCSI_NCR_MAX_TAGS; + + /* + ** Since the queue depth is not tunable under Linux, + ** we need to know this value in order not to + ** announce stupid things to user. + */ + if (lp) { + lp->numtags = lp->maxtags = numtags; + lp->scdev_depth = device->queue_depth; + } + ncr_setup_tags (np, device->id, device->lun); #ifdef DEBUG_NCR53C8XX -printk("ncr53c8xx_select_queue_depth: id=%d, lun=%d, queue_depth=%d\n", - device->id, device->lun, device->queue_depth); +printk("ncr53c8xx_select_queue_depth: host=%d, id=%d, lun=%d, depth=%d\n", + np->unit, device->id, device->lun, device->queue_depth); #endif - } } } -#endif /* ** Linux entry point of queuecommand() function @@ -9646,69 +10142,96 @@ int ncr53c8xx_queue_command (Scsi_Cmnd *cmd, void (* done)(Scsi_Cmnd *)) { + ncb_p np = ((struct host_data *) cmd->host->hostdata)->ncb; + unsigned long flags; int sts; + #ifdef DEBUG_NCR53C8XX printk("ncr53c8xx_queue_command\n"); #endif - if ((sts = ncr_queue_command(cmd, done)) != DID_OK) { + cmd->scsi_done = done; + cmd->host_scribble = NULL; + cmd->SCp.ptr = NULL; + cmd->SCp.buffer = NULL; + + NCR_LOCK_NCB(np, flags); + + if ((sts = ncr_queue_command(np, cmd)) != DID_OK) { cmd->result = ScsiResult(sts, 0); - done(cmd); #ifdef DEBUG_NCR53C8XX printk("ncr53c8xx : command not queued - result=%d\n", sts); #endif - return sts; } #ifdef DEBUG_NCR53C8XX + else printk("ncr53c8xx : command successfully queued\n"); #endif + + NCR_UNLOCK_NCB(np, flags); + + if (sts != DID_OK) + done(cmd); + return sts; } /* ** Linux entry point of the interrupt handler. -** Fort linux versions > 1.3.70, we trust the kernel for +** Since linux versions > 1.3.70, we trust the kernel for ** passing the internal host descriptor as 'dev_id'. ** Otherwise, we scan the host list and call the interrupt ** routine for each host that uses this IRQ. */ -#if LINUX_VERSION_CODE >= LinuxVersionCode(1,3,70) static void ncr53c8xx_intr(int irq, void *dev_id, struct pt_regs * regs) { + unsigned long flags; + ncb_p np = (ncb_p) dev_id; + Scsi_Cmnd *done_list; + #ifdef DEBUG_NCR53C8XX printk("ncr53c8xx : interrupt received\n"); #endif - if (DEBUG_FLAGS & DEBUG_TINY) printf ("["); - ncr_exception((ncb_p) dev_id); - if (DEBUG_FLAGS & DEBUG_TINY) printf ("]\n"); -} - -#else -static void ncr53c8xx_intr(int irq, struct pt_regs * regs) -{ - struct Scsi_Host *host; - struct host_data *host_data; + if (DEBUG_FLAGS & DEBUG_TINY) printk ("["); - for (host = first_host; host; host = host->next) { - if (host->hostt == the_template && host->irq == irq) { - host_data = (struct host_data *) host->hostdata; - if (DEBUG_FLAGS & DEBUG_TINY) printf ("["); - ncr_exception(host_data->ncb); - if (DEBUG_FLAGS & DEBUG_TINY) printf ("]\n"); - } + NCR_LOCK_NCB(np, flags); + ncr_exception(np); + done_list = np->done_list; + np->done_list = 0; + NCR_UNLOCK_NCB(np, flags); + + if (DEBUG_FLAGS & DEBUG_TINY) printk ("]\n"); + + if (done_list) { + NCR_LOCK_SCSI_DONE(np, flags); + ncr_flush_done_cmds(done_list); + NCR_UNLOCK_SCSI_DONE(np, flags); } } -#endif /* ** Linux entry point of the timer handler */ -static void ncr53c8xx_timeout(unsigned long np) +static void ncr53c8xx_timeout(unsigned long npref) { + ncb_p np = (ncb_p) npref; + unsigned long flags; + Scsi_Cmnd *done_list; + + NCR_LOCK_NCB(np, flags); ncr_timeout((ncb_p) np); + done_list = np->done_list; + np->done_list = 0; + NCR_UNLOCK_NCB(np, flags); + + if (done_list) { + NCR_LOCK_SCSI_DONE(np, flags); + ncr_flush_done_cmds(done_list); + NCR_UNLOCK_SCSI_DONE(np, flags); + } } /* @@ -9716,16 +10239,24 @@ */ #if defined SCSI_RESET_SYNCHRONOUS && defined SCSI_RESET_ASYNCHRONOUS - int ncr53c8xx_reset(Scsi_Cmnd *cmd, unsigned int reset_flags) +#else +int ncr53c8xx_reset(Scsi_Cmnd *cmd) +#endif { + ncb_p np = ((struct host_data *) cmd->host->hostdata)->ncb; int sts; unsigned long flags; + Scsi_Cmnd *done_list; +#if defined SCSI_RESET_SYNCHRONOUS && defined SCSI_RESET_ASYNCHRONOUS printk("ncr53c8xx_reset: pid=%lu reset_flags=%x serial_number=%ld serial_number_at_timeout=%ld\n", cmd->pid, reset_flags, cmd->serial_number, cmd->serial_number_at_timeout); +#else + printk("ncr53c8xx_reset: command pid %lu\n", cmd->pid); +#endif - save_flags(flags); cli(); + NCR_LOCK_NCB(np, flags); /* * We have to just ignore reset requests in some situations. @@ -9743,8 +10274,13 @@ * before returning SCSI_RESET_SUCCESS. */ - sts = ncr_reset_bus(cmd, +#if defined SCSI_RESET_SYNCHRONOUS && defined SCSI_RESET_ASYNCHRONOUS + sts = ncr_reset_bus(np, cmd, (reset_flags & (SCSI_RESET_SYNCHRONOUS | SCSI_RESET_ASYNCHRONOUS)) == SCSI_RESET_SYNCHRONOUS); +#else + sts = ncr_reset_bus(np, cmd, 0); +#endif + /* * Since we always reset the controller, when we return success, * we add this information to the return code. @@ -9755,33 +10291,36 @@ #endif out: - restore_flags(flags); + done_list = np->done_list; + np->done_list = 0; + NCR_UNLOCK_NCB(np, flags); + + ncr_flush_done_cmds(done_list); + return sts; } -#else -int ncr53c8xx_reset(Scsi_Cmnd *cmd) -{ - printk("ncr53c8xx_reset: command pid %lu\n", cmd->pid); - return ncr_reset_bus(cmd, 1); -} -#endif /* ** Linux entry point of abort() function */ -#if defined SCSI_RESET_SYNCHRONOUS && defined SCSI_RESET_ASYNCHRONOUS - int ncr53c8xx_abort(Scsi_Cmnd *cmd) { + ncb_p np = ((struct host_data *) cmd->host->hostdata)->ncb; int sts; unsigned long flags; + Scsi_Cmnd *done_list; +#if defined SCSI_RESET_SYNCHRONOUS && defined SCSI_RESET_ASYNCHRONOUS printk("ncr53c8xx_abort: pid=%lu serial_number=%ld serial_number_at_timeout=%ld\n", cmd->pid, cmd->serial_number, cmd->serial_number_at_timeout); +#else + printk("ncr53c8xx_abort: command pid %lu\n", cmd->pid); +#endif - save_flags(flags); cli(); + NCR_LOCK_NCB(np, flags); +#if defined SCSI_RESET_SYNCHRONOUS && defined SCSI_RESET_ASYNCHRONOUS /* * We have to just ignore abort requests in some situations. */ @@ -9789,19 +10328,19 @@ sts = SCSI_ABORT_NOT_RUNNING; goto out; } +#endif - sts = ncr_abort_command(cmd); + sts = ncr_abort_command(np, cmd); out: - restore_flags(flags); + done_list = np->done_list; + np->done_list = 0; + NCR_UNLOCK_NCB(np, flags); + + ncr_flush_done_cmds(done_list); + return sts; } -#else -int ncr53c8xx_abort(Scsi_Cmnd *cmd) -{ - printk("ncr53c8xx_abort: command pid %lu\n", cmd->pid); - return ncr_abort_command(cmd); -} -#endif + #ifdef MODULE int ncr53c8xx_release(struct Scsi_Host *host) @@ -9836,7 +10375,7 @@ Scsi_Cmnd *wcmd; #ifdef DEBUG_WAITING_LIST - printf("%s: cmd %lx inserted into waiting list\n", ncr_name(np), (u_long) cmd); + printk("%s: cmd %lx inserted into waiting list\n", ncr_name(np), (u_long) cmd); #endif cmd->next_wcmd = 0; if (!(wcmd = np->waiting_list)) np->waiting_list = cmd; @@ -9859,7 +10398,7 @@ cmd->next_wcmd = 0; } #ifdef DEBUG_WAITING_LIST - printf("%s: cmd %lx retrieved from waiting list\n", ncr_name(np), (u_long) cmd); + printk("%s: cmd %lx retrieved from waiting list\n", ncr_name(np), (u_long) cmd); #endif return cmd; } @@ -9875,70 +10414,29 @@ np->waiting_list = 0; #ifdef DEBUG_WAITING_LIST - if (waiting_list) printf("%s: waiting_list=%lx processing sts=%d\n", ncr_name(np), (u_long) waiting_list, sts); + if (waiting_list) printk("%s: waiting_list=%lx processing sts=%d\n", ncr_name(np), (u_long) waiting_list, sts); #endif while ((wcmd = waiting_list) != 0) { waiting_list = (Scsi_Cmnd *) wcmd->next_wcmd; wcmd->next_wcmd = 0; if (sts == DID_OK) { #ifdef DEBUG_WAITING_LIST - printf("%s: cmd %lx trying to requeue\n", ncr_name(np), (u_long) wcmd); + printk("%s: cmd %lx trying to requeue\n", ncr_name(np), (u_long) wcmd); #endif - sts = ncr_queue_command(wcmd, wcmd->scsi_done); + sts = ncr_queue_command(np, wcmd); } if (sts != DID_OK) { #ifdef DEBUG_WAITING_LIST - printf("%s: cmd %lx done forced sts=%d\n", ncr_name(np), (u_long) wcmd, sts); + printk("%s: cmd %lx done forced sts=%d\n", ncr_name(np), (u_long) wcmd, sts); #endif wcmd->result = ScsiResult(sts, 0); - wcmd->scsi_done(wcmd); + ncr_queue_done_cmd(np, wcmd); } } } #undef next_wcmd -/* -** Returns data transfer direction for common op-codes. -*/ - -static int guess_xfer_direction(int opcode) -{ - int d; - - switch(opcode) { - case 0x12: /* INQUIRY 12 */ - case 0x4D: /* LOG SENSE 4D */ - case 0x5A: /* MODE SENSE(10) 5A */ - case 0x1A: /* MODE SENSE(6) 1A */ - case 0x3C: /* READ BUFFER 3C */ - case 0x1C: /* RECEIVE DIAGNOSTIC RESULTS 1C */ - case 0x03: /* REQUEST SENSE 03 */ - d = XferIn; - break; - case 0x39: /* COMPARE 39 */ - case 0x3A: /* COPY AND VERIFY 3A */ - case 0x18: /* COPY 18 */ - case 0x4C: /* LOG SELECT 4C */ - case 0x55: /* MODE SELECT(10) 55 */ - case 0x3B: /* WRITE BUFFER 3B */ - case 0x1D: /* SEND DIAGNOSTIC 1D */ - case 0x40: /* CHANGE DEFINITION 40 */ - case 0x15: /* MODE SELECT(6) 15 */ - d = XferOut; - break; - case 0x00: /* TEST UNIT READY 00 */ - d = XferNone; - break; - default: - d = XferBoth; - break; - } - - return d; -} - - #ifdef SCSI_NCR_PROC_INFO_SUPPORT /*========================================================================= @@ -10026,6 +10524,8 @@ uc->cmd = UC_SETTAGS; else if ((arg_len = is_keyword(ptr, len, "setorder")) != 0) uc->cmd = UC_SETORDER; + else if ((arg_len = is_keyword(ptr, len, "setverbose")) != 0) + uc->cmd = UC_SETVERBOSE; else if ((arg_len = is_keyword(ptr, len, "setwide")) != 0) uc->cmd = UC_SETWIDE; else if ((arg_len = is_keyword(ptr, len, "setdebug")) != 0) @@ -10034,15 +10534,11 @@ uc->cmd = UC_SETFLAG; else if ((arg_len = is_keyword(ptr, len, "clearprof")) != 0) uc->cmd = UC_CLEARPROF; -#ifdef UC_DEBUG_ERROR_RECOVERY - else if ((arg_len = is_keyword(ptr, len, "debug_error_recovery")) != 0) - uc->cmd = UC_DEBUG_ERROR_RECOVERY; -#endif else arg_len = 0; #ifdef DEBUG_PROC_INFO -printf("ncr_user_command: arg_len=%d, cmd=%ld\n", arg_len, uc->cmd); +printk("ncr_user_command: arg_len=%d, cmd=%ld\n", arg_len, uc->cmd); #endif if (!arg_len) @@ -10062,20 +10558,21 @@ GET_INT_ARG(target); uc->target = (1<cmd) { + case UC_SETVERBOSE: case UC_SETSYNC: case UC_SETTAGS: case UC_SETWIDE: SKIP_SPACES(1); GET_INT_ARG(uc->data); #ifdef DEBUG_PROC_INFO -printf("ncr_user_command: data=%ld\n", uc->data); +printk("ncr_user_command: data=%ld\n", uc->data); #endif break; case UC_SETORDER: @@ -10123,7 +10620,7 @@ ptr += arg_len; len -= arg_len; } #ifdef DEBUG_PROC_INFO -printf("ncr_user_command: data=%ld\n", uc->data); +printk("ncr_user_command: data=%ld\n", uc->data); #endif break; case UC_SETFLAG: @@ -10138,24 +10635,6 @@ ptr += arg_len; len -= arg_len; } break; -#ifdef UC_DEBUG_ERROR_RECOVERY - case UC_DEBUG_ERROR_RECOVERY: - SKIP_SPACES(1); - if ((arg_len = is_keyword(ptr, len, "sge"))) - uc->data = 1; - else if ((arg_len = is_keyword(ptr, len, "abort"))) - uc->data = 2; - else if ((arg_len = is_keyword(ptr, len, "reset"))) - uc->data = 3; - else if ((arg_len = is_keyword(ptr, len, "parity"))) - uc->data = 4; - else if ((arg_len = is_keyword(ptr, len, "none"))) - uc->data = 0; - else - return -EINVAL; - ptr += arg_len; len -= arg_len; - break; -#endif default: break; } @@ -10165,9 +10644,9 @@ else { long flags; - save_flags(flags); cli(); + NCR_LOCK_NCB(np, flags); ncr_usercmd (np); - restore_flags(flags); + NCR_UNLOCK_NCB(np, flags); } return length; } @@ -10239,7 +10718,11 @@ copy_info(&info, "revision id 0x%x\n", np->revision_id); copy_info(&info, " IO port address 0x%lx, ", (u_long) np->port); +#ifdef __sparc__ + copy_info(&info, "IRQ number %s\n", __irq_itoa(np->irq)); +#else copy_info(&info, "IRQ number %d\n", (int) np->irq); +#endif #ifndef NCR_IOMAPPED if (np->reg) @@ -10288,7 +10771,7 @@ int retv; #ifdef DEBUG_PROC_INFO -printf("ncr53c8xx_proc_info: hostno=%d, func=%d\n", hostno, func); +printk("ncr53c8xx_proc_info: hostno=%d, func=%d\n", hostno, func); #endif for (host = first_host; host; host = host->next) { @@ -10426,7 +10909,7 @@ nvram_stop(np, &gpreg); #ifdef SCSI_NCR_DEBUG_NVRAM -printf("ncr53c8xx: NvRAM marker=%x trailer=%x %x %x %x %x %x byte_count=%d/%d checksum=%x/%x\n", +printk("ncr53c8xx: NvRAM marker=%x trailer=%x %x %x %x %x %x byte_count=%d/%d checksum=%x/%x\n", nvram->start_marker, nvram->trailer[0], nvram->trailer[1], nvram->trailer[2], nvram->trailer[3], nvram->trailer[4], nvram->trailer[5], @@ -10576,7 +11059,7 @@ static void nvram_setBit(ncr_slot *np, u_char write_bit, u_char *gpreg, int bit_mode) ) { - DELAY(5); + UDELAY (5); switch (bit_mode){ case SET_BIT: *gpreg |= write_bit; @@ -10593,7 +11076,7 @@ } OUTB (nc_gpreg, *gpreg); - DELAY(5); + UDELAY (5); } #undef SET_BIT 0 @@ -10730,7 +11213,7 @@ static void Tnvram_Read_Bit(ncr_slot *np, u_char *read_bit, u_char *gpreg) ) { - DELAY(2); + UDELAY (2); Tnvram_Clk(np, gpreg); *read_bit = INB (nc_gpreg); } @@ -10750,7 +11233,7 @@ *gpreg |= 0x10; OUTB (nc_gpreg, *gpreg); - DELAY(2); + UDELAY (2); Tnvram_Clk(np, gpreg); } @@ -10764,7 +11247,7 @@ { *gpreg &= 0xef; OUTB (nc_gpreg, *gpreg); - DELAY(2); + UDELAY (2); Tnvram_Clk(np, gpreg); } @@ -10777,7 +11260,7 @@ ) { OUTB (nc_gpreg, *gpreg | 0x04); - DELAY(2); + UDELAY (2); OUTB (nc_gpreg, *gpreg); } diff -urN linux-2.0.37-pre2/drivers/scsi/ncr53c8xx.h linux-2.0.37-pre3/drivers/scsi/ncr53c8xx.h --- linux-2.0.37-pre2/drivers/scsi/ncr53c8xx.h 1998-06-03 15:17:49.000000000 -0700 +++ linux-2.0.37-pre3/drivers/scsi/ncr53c8xx.h 2003-08-15 15:04:26.000000000 -0700 @@ -45,7 +45,7 @@ /* ** Name and revision of the driver */ -#define SCSI_NCR_DRIVER_NAME "ncr53c8xx - revision 2.5f.1" +#define SCSI_NCR_DRIVER_NAME "ncr53c8xx - revision 3.1e" /* ** Check supported Linux versions @@ -56,51 +56,34 @@ #endif #include -/* -** During make dep of linux-1.2.13, LINUX_VERSION_CODE is undefined -** Under linux-1.3.X, all seems to be OK. -** So, we have only to define it under 1.2.13 -*/ - #define LinuxVersionCode(v, p, s) (((v)<<16)+((p)<<8)+(s)) -#if !defined(LINUX_VERSION_CODE) -#define LINUX_VERSION_CODE LinuxVersionCode(1,2,13) +/* + * No more an option, enabled by default. + */ +#ifndef CONFIG_SCSI_NCR53C8XX_NVRAM_DETECT +#define CONFIG_SCSI_NCR53C8XX_NVRAM_DETECT #endif /* -** Normal IO or memory mapped IO. -** -** Memory mapped IO only works with linux-1.3.X -** If your motherboard does not work with memory mapped IO, -** define SCSI_NCR_IOMAPPED for PATCHLEVEL 3 too. +** These options are not tunable from 'make config' */ - -#if LINUX_VERSION_CODE < LinuxVersionCode(1,3,0) -# define SCSI_NCR_IOMAPPED -#endif - -#if LINUX_VERSION_CODE >= LinuxVersionCode(1,3,0) -# define SCSI_NCR_PROC_INFO_SUPPORT -#endif - -#if LINUX_VERSION_CODE >= LinuxVersionCode(1,3,72) -# define SCSI_NCR_SHARE_IRQ -#endif +#define SCSI_NCR_PROC_INFO_SUPPORT +#define SCSI_NCR_SHARE_IRQ /* ** If you want a driver as small as possible, donnot define the ** following options. */ - #define SCSI_NCR_BOOT_COMMAND_LINE_SUPPORT #define SCSI_NCR_DEBUG_INFO_SUPPORT #define SCSI_NCR_PCI_FIX_UP_SUPPORT #ifdef SCSI_NCR_PROC_INFO_SUPPORT -# define SCSI_NCR_PROFILE_SUPPORT +# ifdef CONFIG_SCSI_NCR53C8XX_PROFILE +# define SCSI_NCR_PROFILE_SUPPORT +# endif # define SCSI_NCR_USER_COMMAND_SUPPORT # define SCSI_NCR_USER_INFO_SUPPORT -/* # define SCSI_NCR_DEBUG_ERROR_RECOVERY_SUPPORT */ #endif /*========================================================== @@ -130,25 +113,27 @@ #define SCSI_NCR_MAX_SYNC (40) /* - * Allow tags from 2 to 12, default 4 + * Allow tags from 2 to 64, default 8 */ #ifdef CONFIG_SCSI_NCR53C8XX_MAX_TAGS #if CONFIG_SCSI_NCR53C8XX_MAX_TAGS < 2 #define SCSI_NCR_MAX_TAGS (2) -#elif CONFIG_SCSI_NCR53C8XX_MAX_TAGS > 12 -#define SCSI_NCR_MAX_TAGS (12) +#elif CONFIG_SCSI_NCR53C8XX_MAX_TAGS > 64 +#define SCSI_NCR_MAX_TAGS (64) #else #define SCSI_NCR_MAX_TAGS CONFIG_SCSI_NCR53C8XX_MAX_TAGS #endif #else -#define SCSI_NCR_MAX_TAGS (4) +#define SCSI_NCR_MAX_TAGS (8) #endif /* * Allow tagged command queuing support if configured with default number * of tags set to max (see above). */ -#ifdef CONFIG_SCSI_NCR53C8XX_TAGGED_QUEUE +#ifdef CONFIG_SCSI_NCR53C8XX_DEFAULT_TAGS +#define SCSI_NCR_SETUP_DEFAULT_TAGS CONFIG_SCSI_NCR53C8XX_DEFAULT_TAGS +#elif defined CONFIG_SCSI_NCR53C8XX_TAGGED_QUEUE #define SCSI_NCR_SETUP_DEFAULT_TAGS SCSI_NCR_MAX_TAGS #else #define SCSI_NCR_SETUP_DEFAULT_TAGS (0) @@ -161,16 +146,19 @@ #define SCSI_NCR_IOMAPPED #elif defined(__alpha__) || defined(__powerpc__) #define SCSI_NCR_IOMAPPED +#elif defined(__sparc__) +#undef SCSI_NCR_IOMAPPED #endif /* * Sync transfer frequency at startup. - * Allow from 5Mhz to 40Mhz default 10 Mhz. + * Allow from 5Mhz to 40Mhz default 20 Mhz. */ #ifndef CONFIG_SCSI_NCR53C8XX_SYNC -#define CONFIG_SCSI_NCR53C8XX_SYNC (5) +#define CONFIG_SCSI_NCR53C8XX_SYNC (20) #elif CONFIG_SCSI_NCR53C8XX_SYNC > SCSI_NCR_MAX_SYNC -#define SCSI_NCR_SETUP_DEFAULT_SYNC SCSI_NCR_MAX_SYNC +#undef CONFIG_SCSI_NCR53C8XX_SYNC +#define CONFIG_SCSI_NCR53C8XX_SYNC SCSI_NCR_MAX_SYNC #endif #if CONFIG_SCSI_NCR53C8XX_SYNC == 0 @@ -245,14 +233,18 @@ #define SCSI_NCR_ALWAYS_SIMPLE_TAG #define SCSI_NCR_MAX_SCATTER (127) #define SCSI_NCR_MAX_TARGET (16) -#define SCSI_NCR_MAX_HOST (2) -#define SCSI_NCR_TIMEOUT_ALERT (3*HZ) +/* No need to use a too large adapter queue */ +#if SCSI_NCR_MAX_TAGS <= 32 #define SCSI_NCR_CAN_QUEUE (7*SCSI_NCR_MAX_TAGS) +#else +#define SCSI_NCR_CAN_QUEUE (250) +#endif + #define SCSI_NCR_CMD_PER_LUN (SCSI_NCR_MAX_TAGS) #define SCSI_NCR_SG_TABLESIZE (SCSI_NCR_MAX_SCATTER) -#define SCSI_NCR_TIMER_INTERVAL ((HZ+5-1)/5) +#define SCSI_NCR_TIMER_INTERVAL (HZ) #if 1 /* defined CONFIG_SCSI_MULTI_LUN */ #define SCSI_NCR_MAX_LUN (8) @@ -268,21 +260,12 @@ #if defined(HOSTS_C) || defined(MODULE) -#if LINUX_VERSION_CODE >= LinuxVersionCode(1,3,98) #include -#else -#include -#endif int ncr53c8xx_abort(Scsi_Cmnd *); int ncr53c8xx_detect(Scsi_Host_Template *tpnt); int ncr53c8xx_queue_command(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); - -#if LINUX_VERSION_CODE >= LinuxVersionCode(1,3,98) int ncr53c8xx_reset(Scsi_Cmnd *, unsigned int); -#else -int ncr53c8xx_reset(Scsi_Cmnd *); -#endif #ifdef MODULE int ncr53c8xx_release(struct Scsi_Host *); @@ -304,34 +287,22 @@ sg_tablesize: SCSI_NCR_SG_TABLESIZE, \ cmd_per_lun: SCSI_NCR_CMD_PER_LUN, \ use_clustering: DISABLE_CLUSTERING} - -#elif LINUX_VERSION_CODE >= LinuxVersionCode(1,3,0) - -#define NCR53C8XX { NULL, NULL, NULL, NULL, \ - SCSI_NCR_DRIVER_NAME, ncr53c8xx_detect, \ - ncr53c8xx_release, NULL, NULL, \ - ncr53c8xx_queue_command,ncr53c8xx_abort, \ - ncr53c8xx_reset, NULL, scsicam_bios_param, \ - SCSI_NCR_CAN_QUEUE, 7, \ - SCSI_NCR_SG_TABLESIZE, SCSI_NCR_CMD_PER_LUN, \ - 0, 0, DISABLE_CLUSTERING} #else -#define NCR53C8XX { NULL, NULL, \ +#define NCR53C8XX { NULL, NULL, NULL, NULL, \ SCSI_NCR_DRIVER_NAME, ncr53c8xx_detect, \ - ncr53c8xx_release, NULL, NULL, \ + ncr53c8xx_release, NULL, NULL, \ ncr53c8xx_queue_command,ncr53c8xx_abort, \ ncr53c8xx_reset, NULL, scsicam_bios_param, \ SCSI_NCR_CAN_QUEUE, 7, \ SCSI_NCR_SG_TABLESIZE, SCSI_NCR_CMD_PER_LUN, \ 0, 0, DISABLE_CLUSTERING} - + #endif /* LINUX_VERSION_CODE */ #endif /* defined(HOSTS_C) || defined(MODULE) */ - #ifndef HOSTS_C /* @@ -347,13 +318,18 @@ #error "BIG ENDIAN byte ordering needs kernel version >= 2.1.0" #endif -#ifdef __powerpc__ +#if defined(__powerpc__) #define inw_l2b inw #define inl_l2b inl #define outw_b2l outw #define outl_b2l outl +#elif defined(__sparc__) +#define readw_l2b readw +#define readl_l2b readl +#define writew_b2l writew +#define writel_b2l writel #else -#error "Support for BIG ENDIAN is only available for the PowerPC" +#error "Support for BIG ENDIAN is only available for PowerPC and SPARC" #endif #else /* Assumed x86 or alpha */ @@ -448,6 +424,10 @@ #define FE_LDSTR (1<<13) #define FE_RAM (1<<14) #define FE_CLK80 (1<<15) +#define FE_RAM8K (1<<16) +#define FE_64BIT (1<<17) +#define FE_IO256 (1<<18) +#define FE_NOPM (1<<19) #define FE_CACHE_SET (FE_ERL|FE_CLSE|FE_WRIE|FE_ERMP) #define FE_SCSI_SET (FE_WIDE|FE_ULTRA|FE_ULTRA2|FE_DBLR|FE_QUAD|F_CLK80) #define FE_SPECIAL_SET (FE_CACHE_SET|FE_BOF|FE_DFS|FE_LDSTR|FE_PFEN|FE_RAM) @@ -492,7 +472,10 @@ {PCI_DEVICE_ID_NCR_53C875, 0x01, "875", 6, 16, 5, \ FE_WIDE|FE_ULTRA|FE_CLK80|FE_CACHE0_SET|FE_BOF|FE_DFS|FE_LDSTR|FE_PFEN|FE_RAM}\ , \ - {PCI_DEVICE_ID_NCR_53C875, 0xff, "875", 6, 16, 5, \ + {PCI_DEVICE_ID_NCR_53C875, 0x0f, "875", 6, 16, 5, \ + FE_WIDE|FE_ULTRA|FE_DBLR|FE_CACHE0_SET|FE_BOF|FE_DFS|FE_LDSTR|FE_PFEN|FE_RAM}\ + , \ + {PCI_DEVICE_ID_NCR_53C875, 0xff, "876", 6, 16, 5, \ FE_WIDE|FE_ULTRA|FE_DBLR|FE_CACHE0_SET|FE_BOF|FE_DFS|FE_LDSTR|FE_PFEN|FE_RAM}\ , \ {PCI_DEVICE_ID_NCR_53C875J,0xff, "875J", 6, 16, 5, \ @@ -505,7 +488,8 @@ FE_WIDE|FE_ULTRA2|FE_QUAD|FE_CACHE_SET|FE_BOF|FE_DFS|FE_LDSTR|FE_PFEN|FE_RAM}\ , \ {PCI_DEVICE_ID_NCR_53C896, 0xff, "896", 7, 31, 7, \ - FE_WIDE|FE_ULTRA2|FE_QUAD|FE_CACHE_SET|FE_BOF|FE_DFS|FE_LDSTR|FE_PFEN|FE_RAM}\ + FE_WIDE|FE_ULTRA2|FE_QUAD|FE_CACHE_SET|FE_BOF|FE_DFS|FE_LDSTR|FE_PFEN|FE_RAM|\ + FE_RAM8K|FE_64BIT|FE_IO256|FE_NOPM}\ } /* @@ -582,94 +566,6 @@ 1 \ } -/* -** Define the table of target capabilities by host and target -** -** If you have problems with a scsi device, note the host unit and the -** corresponding target number. -** -** Edit the corresponding entry of the table below and try successively: -** NQ7_Questionnable -** NQ7_IdeLike -** -** This bitmap is anded with the byte 7 of inquiry data on completion of -** INQUIRY command. -** The driver never see the zeroed bits and will ignore the corresponding -** capabilities of the target. -*/ - -#define INQ7_SftRe 1 -#define INQ7_CmdQueue (1<<1) /* Tagged Command */ -#define INQ7_Reserved (1<<2) -#define INQ7_Linked (1<<3) -#define INQ7_Sync (1<<4) /* Synchronous Negotiation */ -#define INQ7_WBus16 (1<<5) -#define INQ7_WBus32 (1<<6) -#define INQ7_RelAdr (1<<7) - -#define INQ7_IdeLike 0 -#define INQ7_Scsi1Like INQ7_IdeLike -#define INQ7_Perfect 0xff -#define INQ7_Questionnable ~(INQ7_CmdQueue|INQ7_Sync) -#define INQ7_VeryQuestionnable \ - ~(INQ7_CmdQueue|INQ7_Sync|INQ7_WBus16|INQ7_WBus32) - -#define INQ7_Default INQ7_Perfect - -#define NCR53C8XX_TARGET_CAPABILITIES \ -/* Host 0 */ \ -{ \ - { \ - /* Target 0 */ INQ7_Default, \ - /* Target 1 */ INQ7_Default, \ - /* Target 2 */ INQ7_Default, \ - /* Target 3 */ INQ7_Default, \ - /* Target 4 */ INQ7_Default, \ - /* Target 5 */ INQ7_Default, \ - /* Target 6 */ INQ7_Default, \ - /* Target 7 */ INQ7_Default, \ - /* Target 8 */ INQ7_Default, \ - /* Target 9 */ INQ7_Default, \ - /* Target 10 */ INQ7_Default, \ - /* Target 11 */ INQ7_Default, \ - /* Target 12 */ INQ7_Default, \ - /* Target 13 */ INQ7_Default, \ - /* Target 14 */ INQ7_Default, \ - /* Target 15 */ INQ7_Default, \ - } \ -}, \ -/* Host 1 */ \ -{ \ - { \ - /* Target 0 */ INQ7_Default, \ - /* Target 1 */ INQ7_Default, \ - /* Target 2 */ INQ7_Default, \ - /* Target 3 */ INQ7_Default, \ - /* Target 4 */ INQ7_Default, \ - /* Target 5 */ INQ7_Default, \ - /* Target 6 */ INQ7_Default, \ - /* Target 7 */ INQ7_Default, \ - /* Target 8 */ INQ7_Default, \ - /* Target 9 */ INQ7_Default, \ - /* Target 10 */ INQ7_Default, \ - /* Target 11 */ INQ7_Default, \ - /* Target 12 */ INQ7_Default, \ - /* Target 13 */ INQ7_Default, \ - /* Target 14 */ INQ7_Default, \ - /* Target 15 */ INQ7_Default, \ - } \ -} - -/* -** Replace the proc_dir_entry of the standard ncr driver. -*/ - -#if LINUX_VERSION_CODE >= LinuxVersionCode(1,3,0) -#if defined(CONFIG_SCSI_NCR53C7xx) || !defined(CONFIG_SCSI_NCR53C8XX) -#define PROC_SCSI_NCR53C8XX PROC_SCSI_NCR53C7xx -#endif -#endif - /**************** ORIGINAL CONTENT of ncrreg.h from FreeBSD ******************/ /*----------------------------------------------------------------- @@ -794,7 +690,11 @@ /*28*/ u_int32 nc_dnad; /* ### Next command register */ /*2c*/ u_int32 nc_dsp; /* --> Script Pointer */ /*30*/ u_int32 nc_dsps; /* --> Script pointer save/opcode#2 */ -/*34*/ u_int32 nc_scratcha; /* ??? Temporary register a */ + +/*34*/ u_char nc_scratcha; /* Temporary register a */ +/*35*/ u_char nc_scratcha1; +/*36*/ u_char nc_scratcha2; +/*37*/ u_char nc_scratcha3; /*38*/ u_char nc_dmode; #define BL_2 0x80 /* mod: burst length shift value +2 */ @@ -868,7 +768,20 @@ /*53*/ u_char nc_53_; /*54*/ u_short nc_sodl; /* Lowlevel: data out to scsi data */ -/*56*/ u_short nc_56_; +/*56*/ u_char nc_ccntl0; /* Chip Control 0 (896) */ + #define ENPMJ 0x80 /* Enable Phase Mismatch Jump */ + #define PMJCTL 0x40 /* Phase Mismatch Jump Control */ + #define ENNDJ 0x20 /* Enable Non Data PM Jump */ + #define DISFC 0x10 /* Disable Auto FIFO Clear */ + #define DILS 0x02 /* Disable Internal Load/Store */ + #define DPR 0x01 /* Disable Pipe Req */ + +/*57*/ u_char nc_ccntl1; /* Chip Control 1 (896) */ + #define ZMOD 0x80 /* High Impedance Mode */ + #define DDAC 0x08 /* Disable Dual Address Cycle */ + #define XTIMOD 0x04 /* 64-bit Table Ind. Indexing Mode */ + #define EXTIBMV 0x02 /* Enable 64-bit Table Ind. BMOV */ + #define EXDBMV 0x01 /* Enable 64-bit Direct BMOV */ /*58*/ u_short nc_sbdl; /* Lowlevel: data from scsi data */ /*5a*/ u_short nc_5a_; /*5c*/ u_char nc_scr0; /* Working register B */ @@ -1073,10 +986,10 @@ /*----------------------------------------------------------- ** -** FROM_REG (reg) reg = SFBR +** FROM_REG (reg) SFBR = reg ** << 0 >> ** -** TO_REG (reg) SFBR = reg +** TO_REG (reg) reg = SFBR ** << 0 >> ** ** LOAD_REG (reg, data) reg = @@ -1102,6 +1015,42 @@ /*----------------------------------------------------------- ** +** LOAD from memory to register. +** STORE from register to memory. +** +**----------------------------------------------------------- +** +** LOAD_ABS (LEN) +** <> +** +** LOAD_REL (LEN) (DSA relative) +** <> +** +**----------------------------------------------------------- +*/ + +#define SCR_NO_FLUSH2 0x02000000 +#define SCR_DSA_REL2 0x10000000 + +#define SCR_LOAD_R(reg, how, n) \ + (0xe1000000 | how | (SCR_REG_OFS(REG(reg))) | (n)) + +#define SCR_STORE_R(reg, how, n) \ + (0xe0000000 | how | (SCR_REG_OFS(REG(reg))) | (n)) + +#define SCR_LOAD_ABS(reg, n) SCR_LOAD_R(reg, SCR_NO_FLUSH2, n) +#define SCR_LOAD_REL(reg, n) SCR_LOAD_R(reg, SCR_NO_FLUSH2|SCR_DSA_REL2, n) +#define SCR_LOAD_ABS_F(reg, n) SCR_LOAD_R(reg, 0, n) +#define SCR_LOAD_REL_F(reg, n) SCR_LOAD_R(reg, SCR_DSA_REL2, n) + +#define SCR_STORE_ABS(reg, n) SCR_STORE_R(reg, SCR_NO_FLUSH2, n) +#define SCR_STORE_REL(reg, n) SCR_STORE_R(reg, SCR_NO_FLUSH2|SCR_DSA_REL2,n) +#define SCR_STORE_ABS_F(reg, n) SCR_STORE_R(reg, 0, n) +#define SCR_STORE_REL_F(reg, n) SCR_STORE_R(reg, SCR_DSA_REL2, n) + + +/*----------------------------------------------------------- +** ** Waiting for Disconnect or Reselect ** **----------------------------------------------------------- @@ -1136,7 +1085,7 @@ **----------------------------------------------------------- */ -#define SCR_NO_OP 0x80000000 +#define SCR_NO_OP 0x80000000 #define SCR_JUMP 0x80080000 #define SCR_JUMPR 0x80880000 #define SCR_CALL 0x88080000 diff -urN linux-2.0.37-pre2/drivers/scsi/README.ncr53c8xx linux-2.0.37-pre3/drivers/scsi/README.ncr53c8xx --- linux-2.0.37-pre2/drivers/scsi/README.ncr53c8xx 1998-11-15 10:33:06.000000000 -0800 +++ linux-2.0.37-pre3/drivers/scsi/README.ncr53c8xx 2003-08-15 15:04:26.000000000 -0700 @@ -4,7 +4,7 @@ 21 Rue Carnot 95170 DEUIL LA BARRE - FRANCE -2 January 1998 +13 December 1998 =============================================================================== 1. Introduction @@ -21,8 +21,8 @@ 8.4 Set order type for tagged command 8.5 Set debug mode 8.6 Clear profile counters - 8.7 Set flag (no_sync) - 8.8 Debug error recovery + 8.7 Set flag (no_disc) + 8.8 Set verbose level 9. Configuration parameters 10. Boot setup commands 10.1 Syntax @@ -33,9 +33,7 @@ 10.6 SCSI BUS checking boot option 11. Some constants and flags of the ncr53c8xx.h header file 12. Installation - 12.1 Provided files - 12.2 Installation procedure -13. Control commands under linux-1.2.13 +13. Architecture dependant features 14. Known problems 14.1 Tagged commands with Iomega Jaz device 14.2 Device names change when another controller is added @@ -93,7 +91,7 @@ Latest driver version and patches are available at: - ftp://linux.wauug.org/pub/roudier + ftp://ftp.tux.org/pub/people/gerard-roudier I am not a native speaker of English and there are probably lots of mistakes in this README file. Any help will be welcome. @@ -112,19 +110,32 @@ "Wide negotiation" is supported for chips that allow it. The following table shows some characteristics of NCR 8xx family chips: - On board Supported by Tested with -Chip SDMS BIOS Wide Ultra SCSI the driver the driver ----- --------- ---- ---------- ------------ ----------- -810 N N N Y Y -810A N N N Y Y -815 Y N N Y Y -825 Y Y N Y Y -825A Y Y N Y Y -860 N N Y Y Y -875 Y Y Y Y Y -895 Y Y Y(1) Y not yet + On board Supported by +Chip SDMS BIOS Wide SCSI std. Max. sync the driver +---- --------- ---- --------- ---------- ------------ +810 N N FAST10 10 MB/s Y +810A N N FAST10 10 MB/s Y(2) +815 Y N FAST10 10 MB/s Y +825 Y Y FAST10 20 MB/s Y +825A Y Y FAST10 20 MB/s Y(2) +860 N N FAST20 20 MB/s Y(2) +875 Y Y FAST20 40 MB/s Y(2) +876 Y Y FAST20 40 MB/s Y(2) +895 Y Y FAST40 80 MB/s Y(2) +896 Y Y FAST40 80 MB/s Y(1) + +(1) The ncr53c8xx driver does not support the following features of + the 896: + - Hardware phase mismatch. + - 8k on-chip RAM. + If you have a 896 chip, you may want to use the enhanced sym53c8xx + driver that supports all the features of the 896. + The sym53c8xx driver is available at the following URL: + + ftp://ftp.tux.org/pub/roudier/896/ + +(2) Chip also supported by the sym53c8xx enhanced driver. -(1) The 895 chip is supported 'on paper'. 3. Summary of other supported features. @@ -152,49 +163,88 @@ 5. Tagged command queueing -Some SCSI devices do not properly support tagged command queuing. A -safe configuration is to not enable tagged command queuing support at -boot-up, and to enable support of it with the control command -"settags" described further in this text. - -Once you are sure that all your devices properly support tagged -command queuing, you can enable it by default with the -CONFIG_SCSI_NCR53C8XX_TAGGED_QUEUE configuration option. +Queuing more than 1 command at a time to a device allows it to perform +optimizations based on actual head positions and its mechanical +characteristics. This feature may also reduce average command latency. +In order to really gain advantage of this feature, devices must have +a reasonnable cache size (No miracle is to be expected for a low-end +hard disk with 128 KB or less). +Some kown SCSI devices do not properly support tagged command queuing. +Generally, firmware revisions that fix this kind of problems are available +at respective vendor web/ftp sites. +All I can say is that the hard disks I use on my machines behave well with +this driver with tagged command queuing enabled: + +- IBM S12 0662 +- Conner 1080S +- Quantum Atlas I +- Quantum Atlas II + +If your controller has NVRAM, you can configure this feature per target +from the user setup tool. The Tekram Setup program allows to tune the +maximum number of queued commands up to 32. The Symbios Setup only allows +to enable or disable this feature. The maximum number of simultaneous tagged commands queued to a device -is currently set to 4 by default. It is defined in the file -ncr53c8xx.h by SCSI_NCR_MAX_TAGS. This value is suitable for most SCSI -disks. With large SCSI disks (> 2GB, cache > 512KB average seek time -< 10 ms), 8 tagged commands may give better performance. +is currently set to 8 by default. This value is suitable for most SCSI +disks. With large SCSI disks (>= 2GB, cache >= 512KB, average seek time +<= 10 ms), using a larger value may give better performances. +The driver supports up to 64 commands per device, but using more than +32 is generally not worth it, unless you are using a very large disk +or disk array. + +If your controller does not have NVRAM or if it is managed by the SDMS +BIOS/SETUP, you can configure tagged queueing feature and device queue +depths from the boot command-line. For example: + + ncr53c8xx=tags:4/t2t3q15-t4q7/t1u0q32 + +will set tagged commands queue depths as follow: + +- target 2 all luns on controller 0 --> 15 +- target 3 all luns on controller 0 --> 15 +- target 4 all luns on controller 0 --> 7 +- target 1 lun 0 on controller 1 --> 32 +- all other target/lun --> 4 In some special conditions, some SCSI disk firmwares may return a QUEUE FULL status for a SCSI command. This behaviour is managed by the -driver by the following heuristic: +driver using the following heuristic: -- Each time a QUEUE FULL status is returned, tagged command queueing is - temporarily disabled. +- Each time a QUEUE FULL status is returned, tagged queue depth is reduced + to the actual number of disconnected commands. -- Every 100 successfully completed SCSI commands, if allowed by the - current limit, the maximum number of queueable commands is - incremented and tagged command queueing is reenabled. +- Every 1000 successfully completed SCSI commands, if allowed by the + current limit, the maximum number of queueable commands is incremented. +Since QUEUE FULL status reception and handling is resource wasting, the +driver notifies by default this problem to user by indicating the actual +number of commands used and their status, as well as its decision on the +device queue depth change. +The heuristic used by the driver in handling QUEUE FULL ensures that the +impact on performances is not too bad. You can get rid of the messages by +setting verbose level to zero, as follow: + +1st method: boot your system using 'ncr53c8xx=verb:0' option. +2nd method: apply "setverbose 0" control command to the proc fs entry + corresponding to your controller after boot-up. 6. Parity checking The driver supports SCSI parity checking and PCI bus master parity checking. These features must be enabled in order to ensure safe data transfers. However, some flawed devices or mother boards will have -problems with parity. You can disable parity by choosing first -"CONFIG_EXPERIMENTAL". Then, "make config" will allow to set the -following configuration options: - - CONFIG_SCSI_NCR53C8XX_DISABLE_PARITY_CHECK (disable SCSI parity checking) - CONFIG_SCSI_NCR53C8XX_DISABLE_MPARITY_CHECK (disable master parity checking) - +problems with parity. You can disable either PCI parity or SCSI parity +checking by entering appropriate options from the boot command line. +(See 10: Boot setup commands). 7. Profiling information Profiling information is available through the proc SCSI file system. +Since gathering profiling information may impact performances, this +feature is disabled by default and requires a compilation configuration +option to be set to Y. + The device associated with a host has the following pathname: /proc/scsi/ncr53c8xx/N (N=0,1,2 ....) @@ -346,7 +396,7 @@ target: target number tags: number of concurrent tagged commands - must not be greater than SCSI_NCR_MAX_TAGS (default: 4) + must not be greater than SCSI_NCR_MAX_TAGS (default: 8) 8.4 Set order type for tagged command @@ -387,7 +437,7 @@ The "clearprof" command allows you to clear these counters at any time. -8.7 Set flag (no_sync) +8.7 Set flag (no_disc) setflag @@ -395,35 +445,21 @@ For the moment, only one flag is available: - no_sync: not allow target to disconnect. + no_disc: not allow target to disconnect. Do not specify any flag in order to reset the flag. For example: - setflag 4 - will reset no_sync flag for target 4, so will allow it disconnections. + will reset no_disc flag for target 4, so will allow it disconnections. - setflag all will allow disconnection for all devices on the SCSI bus. -8.8 Debug error recovery +8.8 Set verbose level - debug_error_recovery + setverbose #level - Available error type to trigger: - sge: SCSI gross error - abort: abort command from the middle-level driver - reset: reset command from the middle-level driver - parity: scsi parity detected in DATA IN phase - none: restore driver normal behaviour - - The code corresponding to this feature is normally not compiled. - Its purpose is driver testing only. In order to compile the code - that allows to trigger error recovery you must define at compile time - SCSI_NCR_DEBUG_ERROR_RECOVERY. - If you have compiled the driver with this option, nothing will happen - as long as you donnot use the control command 'debug_error_recovery' - with sge, abort, reset or parity as argument. - If you select an error type, it will be triggered by the driver every - 30 seconds. + The driver default verbose level is 1. This command allows to change + th driver verbose level after boot-up. 9. Configuration parameters @@ -433,6 +469,11 @@ support by the driver of this feature at linux start-up and enable this feature after boot-up only for devices that support it safely. +CONFIG_SCSI_NCR53C8XX_PROFILE_SUPPORT (default answer: n) + This option must be set for profiling information to be gathered + and printed out through the proc file system. This features may + impact performances. + CONFIG_SCSI_NCR53C8XX_IOMAPPED (default answer: n) Answer "y" if you suspect your mother board to not allow memory mapped I/O. May slow down performance a little. This option is required by @@ -440,13 +481,12 @@ suffers no performance loss with this option since all IO is memory mapped anyway. -CONFIG_SCSI_NCR53C8XX_TAGGED_QUEUE (default answer: n) - Answer "y" if you are sure that all your SCSI devices that are able to - accept tagged commands will proceed safely. +CONFIG_SCSI_NCR53C8XX_DEFAULT_TAGS (default answer: 8) + Default tagged command queue depth. -CONFIG_SCSI_NCR53C8XX_MAX_TAGS (default answer: 4) +CONFIG_SCSI_NCR53C8XX_MAX_TAGS (default answer: 8) This option allows you to specify the maximum number of tagged commands - that can be queued to a device. + that can be queued to a device. The maximum supported value is 64. CONFIG_SCSI_NCR53C8XX_SYNC (default answer: 5) This option allows you to specify the frequency in MHz the driver @@ -535,8 +575,8 @@ disc:n disabled Special features - Only apply to 810A, 825A, 860 and 875 controllers. - Have no effect with normal 810 and 825. + Only apply to 810A, 825A, 860, 875 and 895 controllers. + Have no effect with other ones. specf:y (or 1) enabled specf:n (or 0) disabled specf:3 enabled except Memory Write And Invalidate @@ -545,17 +585,25 @@ Invalidate. Ultra SCSI support - Only apply to 860 and 875 controllers. + Only apply to 860, 875 and 895 controllers. Have no effect with other ones. - ultra:y enabled + ultra:2 Ultra2 enabled + ultra:1 Ultra enabled ultra:n disabled -Number of tagged commands +Default number of tagged commands tags:0 (or tags:1 ) tagged command queuing disabled tags:#tags (#tags > 1) tagged command queuing enabled #tags will be truncated to the max queued commands configuration parameter. - If the driver is configured with a maximum of 4 queued commands, tags:4 is - the right argument to specify. + This option also allows to specify a command queue depth for each device + that support tagged command queueing. + Example: + ncr53c8xx=tags:10/t2t3q16-t5q24/t1u2q32 + will set devices queue depth as follow: + - controller #0 target #2 and target #3 -> 16 commands, + - controller #0 target #5 -> 24 commands, + - controller #1 target #1 logical unit #2 -> 32 commands, + - all other logical units (all targets, all controllers) -> 10 commands. Default synchronous period factor sync:255 disabled (asynchronous transfer mode) @@ -692,7 +740,7 @@ If the driver has been configured with default options, the equivalent boot setup is: - ncr53c8xx=mpar:y,spar:y,disc:y,specf:3,fsn:n,ultra:y,fsn:n,revprob:n,verb:1\ + ncr53c8xx=mpar:y,spar:y,disc:y,specf:3,fsn:n,ultra:2,fsn:n,revprob:n,verb:1\ tags:0,sync:50,debug:0,burst:7,led:0,wide:1,settle:2,diff:0,irqm:0 For an installation diskette or a safe but not fast system, @@ -705,8 +753,8 @@ My personnal system works flawlessly with the following equivalent setup: - ncr53c8xx=mpar:y,spar:y,disc:y,specf:1,fsn:n,ultra:y,fsn:n,revprob:n,verb:1\ - tags:8,sync:12,debug:0,burst:7,led:1,wide:1,settle:2,diff:0,irqm:0 + ncr53c8xx=mpar:y,spar:y,disc:y,specf:1,fsn:n,ultra:2,fsn:n,revprob:n,verb:1\ + tags:32,sync:12,debug:0,burst:7,led:1,wide:1,settle:2,diff:0,irqm:0 The driver prints its actual setup when verbosity level is 2. You can try "ncr53c8xx=verb:2" to get the "static" setup of the driver, or add "verb:2" @@ -723,8 +771,8 @@ Use 'pcifix:3' in order to allow the driver to fix both PCI features. -These options only apply to new SYMBIOS chips 810A, 825A, 860 and 875 -and are only supported for Pentium and 486 class processors. +These options only apply to new SYMBIOS chips 810A, 825A, 860, 875 +and 895 and are only supported for Pentium and 486 class processors. Recent SYMBIOS 53C8XX scsi processors are able to use PCI read multiple and PCI write and invalidate commands. These features require the cache line size register to be properly set in the PCI configuration @@ -737,7 +785,7 @@ Optimized PCI accesses may be broken for some PCI/memory controllers or make problems with some PCI boards. -This fix-up works flawlessly on my system. +This fix-up worked flawlessly on my previous system. (MB Triton HX / 53C875 / 53C810A) I use these options at my own risks as you will do if you decide to use them too. @@ -812,17 +860,12 @@ change other "defines", you must edit the header file. Do that only if you know what you are doing. -SCSI_NCR_SETUP_ULTRA_SUPPORT (default: defined) - Ultra SCSI support. - Can be changed by the following boot setup command: - ncr53c8xx=ultra:n - SCSI_NCR_SETUP_SPECIAL_FEATURES (default: defined) If defined, the driver will enable some special features according to chip and revision id. - For 810A, 860, 825A and 875 scsi chips, this option enables support - of features that reduce load of PCI bus and memory accesses during - scsi transfer processing: burst op-code fetch, read multiple, + For 810A, 860, 825A, 875 and 895 scsi chips, this option enables + support of features that reduce load of PCI bus and memory accesses + during scsi transfer processing: burst op-code fetch, read multiple, read line, prefetch, cache line, write and invalidate, burst 128 (875 only), large dma fifo (875 only), offset 16 (875 only). Can be changed by the following boot setup command: @@ -834,7 +877,7 @@ SCSI_NCR_SHARE_IRQ (default: defined) If defined, request shared IRQ. -SCSI_NCR_MAX_TAGS (default: 4) +SCSI_NCR_MAX_TAGS (default: 8) Maximum number of simultaneous tagged commands to a device. Can be changed by "settags " @@ -843,7 +886,7 @@ negotiation. 0 means asynchronous. Can be changed by "setsync " -SCSI_NCR_SETUP_DEFAULT_TAGS (default: 4) +SCSI_NCR_SETUP_DEFAULT_TAGS (default: 8) Default number of simultaneous tagged commands to a device. < 1 means tagged command queuing disabled at start-up. @@ -864,7 +907,7 @@ SCSI_NCR_SETUP_MASTER_PARITY (default: defined) If defined, SCSI parity checking is enabled. -SCSI_NCR_PROFILE (default: defined) +SCSI_NCR_PROFILE_SUPPORT (default: not defined) If defined, profiling information is gathered. SCSI_NCR_MAX_SCATTER (default: 128) @@ -899,67 +942,28 @@ 12. Installation -12.1 Provided files +This driver is part of the linux kernel distribution. +Driver files are located in the sub-directory "drivers/scsi" of the +kernel source tree. -Driver and common files: +Driver files: README.ncr53c8xx : this file ChangeLog.ncr53c8xx : change log - ConfigHelp.ncr53c8xx : Part of Configure.help about the driver ncr53c8xx.h : definitions ncr53c8xx.c : the driver code - scsitag.c : command tool to enable tagged queue - conf.modules : sample of /etc/conf.modules - - Install.ncr53c8xx : installation script - - Patch-1.2.13.ncr53c8xx : patch for linux-1.2.13 - Patch-2.0.29.ncr53c8xx : patch for linux-2.0.29 - -You must untar the distribution with the following command: - - tar zxvf ncrBsd2Linux-2.2b-src.tar.gz - -The sub-directory ncr53c8xx-2.2b will be created. Change to this directory. - - -12.2 Installation procedure - -This install script has been tested with linux-1.2.13 and 2.0.29. - -This procedure copies the new driver files to the kernel tree and -applies a patch to some files of the kernel tree. - - If your linux directory is at the standard location - "/usr/src/linux", just enter: - Install.ncr53c8xx - - Else enter: - Install.ncr53c8xx - - Make the kernel: - Change to linux source directory - Configure with NCR53C7,8XX support = N - Configure with NCR53C8XX support = Y (or m) - Make dependancies - Make the kernel (use make zdisk first) - Make and install modules if you have configured with 'm' - - -13. Control commands under linux-1.2.13 -Profiling data and control commands using the proc SCSI file system -are not available for linux-1.2.13. The only control command -available is "scsitag" which allows you to enable tagged command -queuing support after linux boot-up. +New driver versions are made available separately in order to allow testing +changes and new features prior to including them into the linux kernel +distribution. The following URL provides informations on latest avalaible +patches: -Tagged command queueing is disabled by default at system startup. + ftp://ftp.tux.org/pub/people/gerard-roudier/README -You can enable tagged queue per device with the following command: - scsitag device_name (ex: scsitag /dev/sda) +13. Architecture dependant features. -Use "cc -o scsitag scsitag.c" to create the "scsitag" executable. + 14. Known problems @@ -1076,10 +1080,10 @@ Will enable fast synchronous data transfer negotiation for all targets. - echo "setflag 3" >/proc/scsi/ncr53c8xx/0 - Will reset flags (no_sync) for target 3, and so will allow it to disconnect + Will reset flags (no_disc) for target 3, and so will allow it to disconnect the SCSI Bus. -- echo "settags 3 4" >/proc/scsi/ncr53c8xx/0 +- echo "settags 3 8" >/proc/scsi/ncr53c8xx/0 Will enable tagged command queuing for target 3 if that device supports it. Once you have found the device and the feature that cause problems, just @@ -1100,12 +1104,14 @@ 1 Mega-transfers/second means 1 MB/s with 8 bits SCSI and 2 MB/s with Wide16 SCSI. -16.1 Synchronous timings for 53C875 and 53C860 Ultra-SCSI controllers +16.1 Synchronous timings for 53C895, 53C875 and 53C860 SCSI controllers ---------------------------------------------- Negotiated NCR settings Factor Period Speed Period Speed ------ ------ ------ ------ ------ + 10 25 40.000 25 40.000 (53C895 only) + 11 30.2 33.112 31.25 32.000 (53C895 only) 12 50 20.000 50 20.000 13 52 19.230 62 16.000 14 56 17.857 62 16.000 diff -urN linux-2.0.37-pre2/drivers/sound/audio.c linux-2.0.37-pre3/drivers/sound/audio.c --- linux-2.0.37-pre2/drivers/sound/audio.c 1996-10-08 09:12:33.000000000 -0700 +++ linux-2.0.37-pre3/drivers/sound/audio.c 2003-08-15 15:04:26.000000000 -0700 @@ -201,6 +201,9 @@ p = 0; c = count; + if (count < 0) + return -EINVAL; + if ((audio_mode[dev] & AM_READ) && !(audio_devs[dev]->flags & DMA_DUPLEX)) { /* Direction change */ } diff -urN linux-2.0.37-pre2/drivers/sound/Config.in linux-2.0.37-pre3/drivers/sound/Config.in --- linux-2.0.37-pre2/drivers/sound/Config.in 2003-08-15 15:04:26.000000000 -0700 +++ linux-2.0.37-pre3/drivers/sound/Config.in 1997-09-05 20:43:58.000000000 -0700 @@ -1,251 +1,15 @@ -bool 'ProAudioSpectrum 16 support' CONFIG_PAS -bool 'Sound Blaster (SB, SBPro, SB16, clones) support' CONFIG_SB -bool 'Generic OPL2/OPL3 FM synthesizer support' CONFIG_ADLIB -bool 'Gravis Ultrasound support' CONFIG_GUS -bool 'MPU-401 support (NOT for SB16)' CONFIG_MPU401 -bool '6850 UART Midi support' CONFIG_UART6850 -bool 'PSS (ECHO-ADI2111) support' CONFIG_PSS -bool '16 bit sampling option of GUS (_NOT_ GUS MAX)' CONFIG_GUS16 -bool 'GUS MAX support' CONFIG_GUSMAX -bool 'Microsoft Sound System support' CONFIG_MSS -bool 'Ensoniq SoundScape support' CONFIG_SSCAPE -bool 'MediaTrix AudioTrix Pro support' CONFIG_TRIX -bool 'Support for MAD16 and/or Mozart based cards' CONFIG_MAD16 -bool 'Support for Crystal CS4232 based (PnP) cards' CONFIG_CS4232 -bool 'Support for Turtle Beach Wave Front (Maui, Tropez) synthesizers' CONFIG_MAUI -bool '/dev/dsp and /dev/audio support' CONFIG_AUDIO -bool 'MIDI interface support' CONFIG_MIDI -bool 'FM synthesizer (YM3812/OPL-3) support' CONFIG_YM3812 - -if [ "$CONFIG_SB" = "y" ]; then -hex 'I/O base for SB Check from manual of the card' SBC_BASE 220 -fi - -if [ "$CONFIG_SB" = "y" ]; then -int 'Sound Blaster IRQ Check from manual of the card' SBC_IRQ 7 -fi - -if [ "$CONFIG_SB" = "y" ]; then -int 'Sound Blaster DMA 0, 1 or 3' SBC_DMA 1 -fi - -if [ "$CONFIG_SB" = "y" ]; then -int 'Sound Blaster 16 bit DMA (_REQUIRED_for SB16, Jazz16, SMW) 5, 6 or 7 (use 1 for 8 bit cards)' SB_DMA2 5 -fi - -if [ "$CONFIG_SB" = "y" ]; then -hex 'MPU401 I/O base of SB16, Jazz16 and ES1688 Check from manual of the card' SB_MPU_BASE 0 -fi - -if [ "$CONFIG_SB" = "y" ]; then -int 'SB MPU401 IRQ (Jazz16, SM Wave and ES1688) Use -1 with SB16' SB_MPU_IRQ -1 -fi - -if [ "$CONFIG_PAS" = "y" ]; then -int 'PAS16 IRQ 3, 4, 5, 7, 9, 10, 11, 12, 14 or 15' PAS_IRQ 10 -fi - -if [ "$CONFIG_PAS" = "y" ]; then -int 'PAS16 DMA 0, 1, 3, 5, 6 or 7' PAS_DMA 3 -fi - -if [ "$CONFIG_GUS" = "y" ]; then -hex 'I/O base for GUS 210, 220, 230, 240, 250 or 260' GUS_BASE 220 -fi - -if [ "$CONFIG_GUS" = "y" ]; then -int 'GUS IRQ 3, 5, 7, 9, 11, 12 or 15' GUS_IRQ 15 -fi - -if [ "$CONFIG_GUS" = "y" ]; then -int 'GUS DMA 1, 3, 5, 6 or 7' GUS_DMA 6 -fi - -if [ "$CONFIG_GUS" = "y" ]; then -int 'Second DMA channel for GUS 1, 3, 5, 6 or 7' GUS_DMA2 -1 -fi - -if [ "$CONFIG_GUS16" = "y" ]; then -hex 'I/O base for the 16 bit daughtercard of GUS 530, 604, E80 or F40' GUS16_BASE 530 -fi - -if [ "$CONFIG_GUS16" = "y" ]; then -int 'GUS 16 bit daughtercard IRQ 3, 4, 5, 7, or 9' GUS16_IRQ 7 -fi - -if [ "$CONFIG_GUS16" = "y" ]; then -int 'GUS DMA 0, 1 or 3' GUS16_DMA 3 -fi - -if [ "$CONFIG_MPU401" = "y" ]; then -hex 'I/O base for MPU401 Check from manual of the card' MPU_BASE 330 -fi - -if [ "$CONFIG_MPU401" = "y" ]; then -int 'MPU401 IRQ Check from manual of the card' MPU_IRQ 9 -fi - -if [ "$CONFIG_MAUI" = "y" ]; then -hex 'I/O base for Maui 210, 230, 260, 290, 300, 320, 338 or 330' MAUI_BASE 330 -fi - -if [ "$CONFIG_MAUI" = "y" ]; then -int 'Maui IRQ 5, 9, 12 or 15' MAUI_IRQ 9 -fi - -if [ "$CONFIG_UART6850" = "y" ]; then -hex 'I/O base for UART 6850 MIDI port (Unknown)' U6850_BASE 0 -fi - -if [ "$CONFIG_UART6850" = "y" ]; then -int 'UART6850 IRQ (Unknown)' U6850_IRQ -1 -fi - -if [ "$CONFIG_PSS" = "y" ]; then -hex 'PSS I/O base 220 or 240' PSS_BASE 220 -fi - -if [ "$CONFIG_PSS" = "y" ]; then -hex 'PSS audio I/O base 530, 604, E80 or F40' PSS_MSS_BASE 530 -fi - -if [ "$CONFIG_PSS" = "y" ]; then -int 'PSS audio IRQ 7, 9, 10 or 11' PSS_MSS_IRQ 11 -fi - -if [ "$CONFIG_PSS" = "y" ]; then -int 'PSS audio DMA 0, 1 or 3' PSS_MSS_DMA 3 -fi - -if [ "$CONFIG_PSS" = "y" ]; then -hex 'PSS MIDI I/O base ' PSS_MPU_BASE 330 -fi - -if [ "$CONFIG_PSS" = "y" ]; then -int 'PSS MIDI IRQ 3, 4, 5, 7 or 9' PSS_MPU_IRQ 9 -fi - -if [ "$CONFIG_MSS" = "y" ]; then -hex 'MSS/WSS I/O base 530, 604, E80 or F40' MSS_BASE 530 -fi - -if [ "$CONFIG_MSS" = "y" ]; then -int 'MSS/WSS IRQ 7, 9, 10 or 11' MSS_IRQ 11 -fi - -if [ "$CONFIG_MSS" = "y" ]; then -int 'MSS/WSS DMA 0, 1 or 3' MSS_DMA 3 -fi - -if [ "$CONFIG_SSCAPE" = "y" ]; then -hex 'SoundScape MIDI I/O base 320, 330, 340 or 350' SSCAPE_BASE 330 -fi - -if [ "$CONFIG_SSCAPE" = "y" ]; then -int 'SoundScape MIDI IRQ ' SSCAPE_IRQ 9 -fi - -if [ "$CONFIG_SSCAPE" = "y" ]; then -int 'SoundScape initialization DMA 0, 1 or 3' SSCAPE_DMA 3 -fi - -if [ "$CONFIG_SSCAPE" = "y" ]; then -hex 'SoundScape audio I/O base 534, 608, E84 or F44' SSCAPE_MSS_BASE 534 -fi - -if [ "$CONFIG_SSCAPE" = "y" ]; then -int 'SoundScape audio IRQ 7, 9, 10 or 11' SSCAPE_MSS_IRQ 11 -fi - -if [ "$CONFIG_TRIX" = "y" ]; then -hex 'AudioTrix audio I/O base 530, 604, E80 or F40' TRIX_BASE 530 -fi - -if [ "$CONFIG_TRIX" = "y" ]; then -int 'AudioTrix audio IRQ 7, 9, 10 or 11' TRIX_IRQ 11 -fi - -if [ "$CONFIG_TRIX" = "y" ]; then -int 'AudioTrix audio DMA 0, 1 or 3' TRIX_DMA 0 -fi - -if [ "$CONFIG_TRIX" = "y" ]; then -int 'AudioTrix second (duplex) DMA 0, 1 or 3' TRIX_DMA2 3 -fi - -if [ "$CONFIG_TRIX" = "y" ]; then -hex 'AudioTrix MIDI I/O base 330, 370, 3B0 or 3F0' TRIX_MPU_BASE 330 -fi - -if [ "$CONFIG_TRIX" = "y" ]; then -int 'AudioTrix MIDI IRQ 3, 4, 5, 7 or 9' TRIX_MPU_IRQ 9 -fi - -if [ "$CONFIG_TRIX" = "y" ]; then -hex 'AudioTrix SB I/O base 220, 210, 230, 240, 250, 260 or 270' TRIX_SB_BASE 220 -fi - -if [ "$CONFIG_TRIX" = "y" ]; then -int 'AudioTrix SB IRQ 3, 4, 5 or 7' TRIX_SB_IRQ 7 -fi - -if [ "$CONFIG_TRIX" = "y" ]; then -int 'AudioTrix SB DMA 1 or 3' TRIX_SB_DMA 1 -fi - -if [ "$CONFIG_CS4232" = "y" ]; then -hex 'CS4232 audio I/O base 530, 604, E80 or F40' CS4232_BASE 530 -fi - -if [ "$CONFIG_CS4232" = "y" ]; then -int 'CS4232 audio IRQ 5, 7, 9, 11, 12 or 15' CS4232_IRQ 11 -fi - -if [ "$CONFIG_CS4232" = "y" ]; then -int 'CS4232 audio DMA 0, 1 or 3' CS4232_DMA 0 -fi - -if [ "$CONFIG_CS4232" = "y" ]; then -int 'CS4232 second (duplex) DMA 0, 1 or 3' CS4232_DMA2 3 -fi - -if [ "$CONFIG_CS4232" = "y" ]; then -hex 'CS4232 MIDI I/O base 330, 370, 3B0 or 3F0' CS4232_MPU_BASE 330 -fi - -if [ "$CONFIG_CS4232" = "y" ]; then -int 'CS4232 MIDI IRQ 5, 7, 9, 11, 12 or 15' CS4232_MPU_IRQ 9 -fi - -if [ "$CONFIG_MAD16" = "y" ]; then -hex 'MAD16 audio I/O base 530, 604, E80 or F40' MAD16_BASE 530 -fi - -if [ "$CONFIG_MAD16" = "y" ]; then -int 'MAD16 audio IRQ 7, 9, 10 or 11' MAD16_IRQ 11 -fi - -if [ "$CONFIG_MAD16" = "y" ]; then -int 'MAD16 audio DMA 0, 1 or 3' MAD16_DMA 3 -fi - -if [ "$CONFIG_MAD16" = "y" ]; then -int 'MAD16 second (duplex) DMA 0, 1 or 3' MAD16_DMA2 0 -fi - -if [ "$CONFIG_MAD16" = "y" ]; then -hex 'MAD16 MIDI I/O base 300, 310, 320 or 330 (0 disables)' MAD16_MPU_BASE 330 -fi - -if [ "$CONFIG_MAD16" = "y" ]; then -int 'MAD16 MIDI IRQ 5, 7, 9 or 10' MAD16_MPU_IRQ 9 -fi - -if [ "$CONFIG_AUDIO" = "y" ]; then -int 'Audio DMA buffer size 4096, 16384, 32768 or 65536' DSP_BUFFSIZE 65536 -fi # -$MAKE -C drivers/sound kernelconfig || exit 1 +# Sound driver configuration +# +#-------- +# There is another config script which is compatible with rest of +# the kernel. It can be activated by running 'make mkscript' in this +# directory. Please note that this is an _experimental_ feature which +# doesn't work with all cards (PSS, SM Wave, AudioTrix Pro, Maui). +#-------- +# +$MAKE -C drivers/sound config || exit 1 + bool 'Additional low level drivers' CONFIG_LOWLEVEL_SOUND if [ "$CONFIG_LOWLEVEL_SOUND" = "y" ]; then diff -urN linux-2.0.37-pre2/fs/Config.in linux-2.0.37-pre3/fs/Config.in --- linux-2.0.37-pre2/fs/Config.in 2003-08-15 15:04:26.000000000 -0700 +++ linux-2.0.37-pre3/fs/Config.in 2003-08-15 15:04:26.000000000 -0700 @@ -19,6 +19,8 @@ dep_tristate 'MSDOS fs support' CONFIG_MSDOS_FS $CONFIG_FAT_FS dep_tristate 'umsdos: Unix like fs on top of std MSDOS FAT fs' CONFIG_UMSDOS_FS $CONFIG_MSDOS_FS dep_tristate 'VFAT (Windows-95) fs support' CONFIG_VFAT_FS $CONFIG_FAT_FS + mainmenu_option next_comment + comment 'Select available code pages' dep_tristate 'Codepage 437 (United States, Canada)' CONFIG_NLS_CODEPAGE_437 $CONFIG_NLS dep_tristate 'Codepage 737 (Greek)' CONFIG_NLS_CODEPAGE_737 $CONFIG_NLS dep_tristate 'Codepage 775 (Baltic Rim)' CONFIG_NLS_CODEPAGE_775 $CONFIG_NLS @@ -45,6 +47,7 @@ dep_tristate 'NLS ISO 8859-8 (Hebrew)' CONFIG_NLS_ISO8859_8 $CONFIG_NLS dep_tristate 'NLS ISO 8859-9 (Latin 5; Turkey)' CONFIG_NLS_ISO8859_9 $CONFIG_NLS dep_tristate 'NLS KOI8-R (Russian)' CONFIG_NLS_KOI8_R $CONFIG_NLS + endmenu fi bool '/proc filesystem support' CONFIG_PROC_FS diff -urN linux-2.0.37-pre2/include/asm-i386/pgtable.h linux-2.0.37-pre3/include/asm-i386/pgtable.h --- linux-2.0.37-pre2/include/asm-i386/pgtable.h 2003-08-15 15:04:26.000000000 -0700 +++ linux-2.0.37-pre3/include/asm-i386/pgtable.h 2003-08-15 15:04:26.000000000 -0700 @@ -54,7 +54,7 @@ * address. */ #define __invlpg_mem(addr) \ - (((char *)(addr)-__PAGE_OFFSET)) + (*((char *)(addr)-__PAGE_OFFSET)) #define __invlpg(addr) \ __asm__ __volatile__("invlpg %0": :"m" (__invlpg_mem(addr))) diff -urN linux-2.0.37-pre2/include/linux/nls.h linux-2.0.37-pre3/include/linux/nls.h --- linux-2.0.37-pre2/include/linux/nls.h 1998-06-03 15:17:49.000000000 -0700 +++ linux-2.0.37-pre3/include/linux/nls.h 2003-08-15 15:04:26.000000000 -0700 @@ -58,5 +58,6 @@ extern int init_nls_cp866(void); extern int init_nls_cp869(void); extern int init_nls_cp874(void); +extern int init_nls_koi8_r(void); #endif /* _LINUX_NLS_H */ diff -urN linux-2.0.37-pre2/include/linux/pci.h linux-2.0.37-pre3/include/linux/pci.h --- linux-2.0.37-pre2/include/linux/pci.h 2003-08-15 15:04:26.000000000 -0700 +++ linux-2.0.37-pre3/include/linux/pci.h 2003-08-15 15:04:26.000000000 -0700 @@ -354,7 +354,11 @@ #define PCI_DEVICE_ID_MATROX_MYS 0x051A #define PCI_DEVICE_ID_MATROX_MIL_2 0x051b #define PCI_DEVICE_ID_MATROX_MIL_2_AGP 0x051f +#define PCI_DEVICE_ID_MATROX_G200_PCI 0x0520 +#define PCI_DEVICE_ID_MATROX_G200_AGP 0x0521 #define PCI_DEVICE_ID_MATROX_MGA_IMP 0x0d10 +#define PCI_DEVICE_ID_MATROX_G100_MM 0x1000 +#define PCI_DEVICE_ID_MATROX_G100_AGP 0x1001 #define PCI_VENDOR_ID_CT 0x102c #define PCI_DEVICE_ID_CT_65545 0x00d8 @@ -660,6 +664,7 @@ #define PCI_DEVICE_ID_VIA_82C586_0 0x0586 #define PCI_DEVICE_ID_VIA_82C595 0x0595 #define PCI_DEVICE_ID_VIA_82C597_0 0x0597 +#define PCI_DEVICE_ID_VIA_82C598_0 0x0598 #define PCI_DEVICE_ID_VIA_82C926 0x0926 #define PCI_DEVICE_ID_VIA_82C416 0x1571 #define PCI_DEVICE_ID_VIA_82C595_97 0x1595 @@ -667,6 +672,7 @@ #define PCI_DEVICE_ID_VIA_82C586_3 0x3040 #define PCI_DEVICE_ID_VIA_86C100A 0x6100 #define PCI_DEVICE_ID_VIA_82C597_1 0x8597 +#define PCI_DEVICE_ID_VIA_82C598_1 0x8598 #define PCI_VENDOR_ID_SMC2 0x1113 #define PCI_DEVICE_ID_SMC2_1211TX 0x1211 diff -urN linux-2.0.37-pre2/MAINTAINERS linux-2.0.37-pre3/MAINTAINERS --- linux-2.0.37-pre2/MAINTAINERS 2003-08-15 15:04:26.000000000 -0700 +++ linux-2.0.37-pre3/MAINTAINERS 2003-08-15 15:04:26.000000000 -0700 @@ -291,9 +291,9 @@ NCP FILESYSTEM: P: Volker Lendecke -M: lendecke@namu01.Num.Math.Uni-Goettingen.de +M: vl@kki.org L: linware@sh.cvut.cz -S: Maintained +S: Odd Fixes NETROM NETWORK LAYER P: Jon Naylor @@ -327,7 +327,7 @@ SMB FILESYSTEM: P: Volker Lendecke -M: lendecke@namu01.Num.Math.Uni-Goettingen.de +M: vl@kki.org L: samba@listproc.anu.edu.au S: Odd Fixes diff -urN linux-2.0.37-pre2/net/bridge/br.c linux-2.0.37-pre3/net/bridge/br.c --- linux-2.0.37-pre2/net/bridge/br.c 2003-08-15 15:04:26.000000000 -0700 +++ linux-2.0.37-pre3/net/bridge/br.c 2003-08-15 15:04:26.000000000 -0700 @@ -871,10 +871,9 @@ int send_config_bpdu(int port_no, Config_bpdu *config_bpdu) { -struct sk_buff *skb; -struct device *dev = port_info[port_no].dev; -int size; -unsigned long flags; + struct sk_buff *skb; + struct device *dev = port_info[port_no].dev; + int size; if (port_info[port_no].state == Disabled) { printk(KERN_DEBUG "send_config_bpdu: port %i not valid\n",port_no); @@ -927,10 +926,9 @@ int send_tcn_bpdu(int port_no, Tcn_bpdu *bpdu) { -struct sk_buff *skb; -struct device *dev = port_info[port_no].dev; -int size; -unsigned long flags; + struct sk_buff *skb; + struct device *dev = port_info[port_no].dev; + int size; if (port_info[port_no].state == Disabled) { printk(KERN_DEBUG "send_tcn_bpdu: port %i not valid\n",port_no); @@ -1047,7 +1045,6 @@ int br_receive_frame(struct sk_buff *skb) /* 3.5 */ { int port; - int i; if (br_stats.flags & BR_DEBUG) printk("br_receive_frame: "); diff -urN linux-2.0.37-pre2/net/ipv4/rarp.c linux-2.0.37-pre3/net/ipv4/rarp.c --- linux-2.0.37-pre2/net/ipv4/rarp.c 1998-07-13 13:47:41.000000000 -0700 +++ linux-2.0.37-pre3/net/ipv4/rarp.c 2003-08-15 15:04:26.000000000 -0700 @@ -189,6 +189,8 @@ rarp_pkt_inited=1; } +#ifdef MODULE + static void rarp_end_pkt(void) { if(!rarp_pkt_inited) @@ -198,6 +200,8 @@ rarp_pkt_inited=0; } +#endif + /* * Receive an arp request by the device layer. Maybe it should be