Parent repository is bk://linux-scsi.bkbits.net/scsi-misc-2.6 ======== ChangeSet 1.1597 ======== D 1.1597 04/02/22 12:58:17-08:00 akpm@mnm.(none) 37222 37221 0/0/1 P ChangeSet C Merge bk://linux-scsi.bkbits.net/scsi-misc-2.6 C into mnm.(none):/usr/src/bk-scsi ------------------------------------------------ diff -Nru a/Documentation/scsi/st.txt b/Documentation/scsi/st.txt --- a/Documentation/scsi/st.txt Sun Feb 22 12:59:47 2004 +++ b/Documentation/scsi/st.txt Sun Feb 22 12:59:47 2004 @@ -2,7 +2,7 @@ The driver is currently maintained by Kai Mäkisara (email Kai.Makisara@kolumbus.fi) -Last modified: Sun Nov 9 22:36:02 2003 by makisara +Last modified: Thu Feb 19 21:57:30 2004 by makisara BASICS @@ -113,6 +113,26 @@ only 8 bits wide. +SYSFS SUPPORT + +The driver creates the directory /sys/class/scsi_tape and populates it with +directories corresponding to the existing tape devices. There are autorewind +and non-rewind entries for each mode. The names are stxmy and stxmyn, where x +is the tape number and y is the mode. For example, the directories for the +first tape device are (assuming four modes): st0m0 st0m0n st0m1 st0m1n +st0m2 st0m2n st0m3 st0m3n. + +Each directory contains the entries: default_blksize default_compression +default_density defined dev device driver. The file 'defined' contains 1 +if the mode is defined and zero if not defined. The files 'default_*' contain +the defaults set by the user. The value -1 means the default is not set. The +file 'dev' contains the device numbers corresponding to this device. The links +'device' and 'driver' point to the SCSI device and driver entries. + +A link named 'tape' is made from the SCSI device directory to the class +directory corresponding to the mode 0 auto-rewind device (e.g., st0m0). + + BSD AND SYS V SEMANTICS The user can choose between these two behaviours of the tape driver by @@ -126,7 +146,7 @@ BUFFERING -The driver tries to do tranfers directly to/from user space. If this +The driver tries to do transfers directly to/from user space. If this is not possible, a driver buffer allocated at run-time is used. If direct i/o is not possible for the whole transfer, the driver buffer is used (i.e., bounce buffers for individual pages are not @@ -147,6 +167,12 @@ size). Because of this the actual buffer size may be larger than the minimum allowable buffer size. +NOTE that if direct i/o is used, the small writes are not buffered. This may +cause a surprise when moving from 2.4. There small writes (e.g., tar without +-b option) may have had good throughput but this is not true any more with +2.6. Direct i/o can be turned off to solve this problem but a better solution +is to use bigger write() byte counts (e.g., tar -b 64). + Asynchronous writing. Writing the buffer contents to the tape is started and the write call returns immediately. The status is checked at the next tape operation. Asynchronous writes are not done with @@ -453,7 +479,7 @@ To enable debugging messages, edit st.c and #define DEBUG 1. As seen above, debugging can be switched off with an ioctl if debugging is -compiled into the driver. The debugging output is not voluminuous. +compiled into the driver. The debugging output is not voluminous. If the tape seems to hang, I would be very interested to hear where the driver is waiting. With the command 'ps -l' you can see the state diff -Nru a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c --- a/drivers/message/fusion/mptbase.c Sun Feb 22 12:59:47 2004 +++ b/drivers/message/fusion/mptbase.c Sun Feb 22 12:59:47 2004 @@ -714,6 +714,7 @@ MptCallbacks[i] = cbfunc; MptDriverClass[i] = dclass; MptEvHandlers[i] = NULL; + MptDeviceDriverHandlers[i] = NULL; last_drv_idx = i; if (cbfunc != mpt_base_reply) { mpt_inc_use_count(); @@ -838,11 +839,28 @@ int mpt_device_driver_register(struct mpt_pci_driver * dd_cbfunc, int cb_idx) { - if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS) - return -1; + MPT_ADAPTER *ioc; + int error=0; + + if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS) { + error= -EINVAL; + return error; + } MptDeviceDriverHandlers[cb_idx] = dd_cbfunc; - return 0; + + /* call per pci device probe entry point */ + for(ioc = mpt_adapter_find_first(); ioc != NULL; + ioc = mpt_adapter_find_next(ioc)) { + if(dd_cbfunc->probe) { + error = dd_cbfunc->probe(ioc->pcidev, + ioc->pcidev->driver->id_table); + if(error != 0) + return error; + } + } + + return error; } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ @@ -1502,9 +1520,14 @@ ioc->name, r); } - if(r != 0 ) + if(r != 0 ) { + Q_DEL_ITEM(ioc); + mpt_adapters[ioc->id] = NULL; + free_irq(ioc->pci_irq, ioc); + iounmap(mem); + kfree(ioc); return r; - + } /* call per device driver probe entry point */ for(ii=0; iifacts.NumberOfPorts; portnum++) { @@ -1542,8 +1543,10 @@ */ sz = hd->ioc->req_depth * sizeof(void *); mem = kmalloc(sz, GFP_ATOMIC); - if (mem == NULL) + if (mem == NULL) { + error = -ENOMEM; goto mptscsih_probe_failed; + } memset(mem, 0, sz); hd->ScsiLookup = (struct scsi_cmnd **) mem; @@ -1551,15 +1554,19 @@ dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p, sz=%d\n", ioc->name, hd->ScsiLookup, sz)); - if (mptscsih_initChainBuffers(hd, 1) < 0) + if (mptscsih_initChainBuffers(hd, 1) < 0) { + error = -EINVAL; goto mptscsih_probe_failed; + } /* Allocate memory for free and doneQ's */ sz = sh->can_queue * sizeof(MPT_DONE_Q); mem = kmalloc(sz, GFP_ATOMIC); - if (mem == NULL) + if (mem == NULL) { + error = -ENOMEM; goto mptscsih_probe_failed; + } memset(mem, 0xFF, sz); hd->memQ = mem; @@ -1591,8 +1598,10 @@ */ sz = sh->max_id * sizeof(void *); mem = kmalloc(sz, GFP_ATOMIC); - if (mem == NULL) + if (mem == NULL) { + error = -ENOMEM; goto mptscsih_probe_failed; + } memset(mem, 0, sz); hd->Targets = (VirtDevice **) mem; @@ -1683,7 +1692,8 @@ mpt_scsi_hosts++; - if(scsi_add_host (sh, &ioc->pcidev->dev)) { + error = scsi_add_host (sh, &ioc->pcidev->dev); + if(error) { dprintk((KERN_ERR MYNAM, "scsi_add_host failed\n")); goto mptscsih_probe_failed; @@ -1691,7 +1701,6 @@ scsi_scan_host(sh); return 0; - } /* scsi_host_alloc */ } /* for each adapter port */ @@ -1699,8 +1708,7 @@ mptscsih_probe_failed: mptscsih_remove(pdev); - return -ENODEV; - + return error; } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ @@ -1828,6 +1836,7 @@ } scsi_host_put(host); + mpt_scsi_hosts--; } @@ -1928,10 +1937,9 @@ * * Returns 0 for success, non-zero for failure. */ -static int -__init mptscsih_init(void) +static int __init +mptscsih_init(void) { - MPT_ADAPTER *ioc; show_mptmod_ver(my_NAME, my_VERSION); @@ -1939,12 +1947,6 @@ ScsiTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTSCSIH_DRIVER); ScsiScanDvCtx = mpt_register(mptscsih_scandv_complete, MPTSCSIH_DRIVER); - if(mpt_device_driver_register(&mptscsih_driver, - MPTSCSIH_DRIVER) != 0 ) { - dprintk((KERN_INFO MYNAM - ": failed to register dd callbacks\n")); - } - if (mpt_event_register(ScsiDoneCtx, mptscsih_event_process) == 0) { dprintk((KERN_INFO MYNAM ": Registered for IOC event notifications\n")); @@ -1961,20 +1963,13 @@ mptscsih_setup(mptscsih); #endif - /* probing for devices */ - for(ioc = mpt_adapter_find_first(); ioc != NULL; - ioc = mpt_adapter_find_next(ioc)) { - if(mptscsih_probe(ioc->pcidev, ioc->pcidev->driver->id_table)) { - dprintk((KERN_INFO MYNAM ": probe failed\n")); - return -ENODEV; - } + if(mpt_device_driver_register(&mptscsih_driver, + MPTSCSIH_DRIVER) != 0 ) { + dprintk((KERN_INFO MYNAM + ": failed to register dd callbacks\n")); } - if (mpt_scsi_hosts > 0) - return 0; - - mptscsih_exit(); - return -ENODEV; + return 0; } @@ -1984,7 +1979,7 @@ * mptscsih_exit - Unregisters MPT adapter(s) * */ -static void +static void __exit mptscsih_exit(void) { MPT_ADAPTER *ioc; diff -Nru a/drivers/scsi/53c700.h b/drivers/scsi/53c700.h --- a/drivers/scsi/53c700.h Sun Feb 22 12:59:47 2004 +++ b/drivers/scsi/53c700.h Sun Feb 22 12:59:47 2004 @@ -37,7 +37,7 @@ #define NCR_700_LUN_MASK (NCR_700_MAX_LUNS - 1) /* Alter this with care: too many tags won't give the elevator a chance to * work; too few will cause the device to operate less efficiently */ -#define NCR_700_MAX_TAGS 16 +#define NCR_700_MAX_TAGS 4 /* This is the default number of commands per LUN in the untagged case. * two is a good value because it means we can have one command active and * one command fully prepared and waiting diff -Nru a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig --- a/drivers/scsi/Kconfig Sun Feb 22 12:59:47 2004 +++ b/drivers/scsi/Kconfig Sun Feb 22 12:59:47 2004 @@ -23,7 +23,7 @@ config SCSI_PROC_FS bool "legacy /proc/scsi/ support" - depends on SCSI + depends on SCSI && PROC_FS default y ---help--- This option enables support for the various files in @@ -1267,28 +1267,9 @@ Note that this driver does NOT support Tekram DC390W/U/F, which are based on NCR/Symbios chips. Use "NCR53C8XX SCSI support" for those. - Also note that there is another generic Am53C974 driver, - "AM53/79C974 PCI SCSI support" below. You can pick either one. To compile this driver as a module, choose M here: the module will be called tmscsim. - -config SCSI_DC390T_NOGENSUPP - bool "_omit_ support for non-DC390 adapters" - depends on SCSI_DC390T - ---help--- - If you say N here, the DC390(T) SCSI driver relies on the DC390 - EEPROM to get initial values for its settings, such as speed, - termination, etc. If it can't find this EEPROM, it will use - defaults or the user supplied boot/module parameters. For details - on driver configuration see . - - If you say Y here and if no EEPROM is found, the driver gives up and - thus only supports Tekram DC390(T) adapters. This can be useful if - you have a DC390(T) and another Am53C974 based adapter, which, for - some reason, you want to drive with the other AM53C974 driver. - - If unsure, say N. config SCSI_T128 tristate "Trantor T128/T128F/T228 SCSI support" diff -Nru a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c --- a/drivers/scsi/NCR5380.c Sun Feb 22 12:59:47 2004 +++ b/drivers/scsi/NCR5380.c Sun Feb 22 12:59:47 2004 @@ -1326,81 +1326,71 @@ static irqreturn_t NCR5380_intr(int irq, void *dev_id, struct pt_regs *regs) { NCR5380_local_declare(); - struct Scsi_Host *instance; + struct Scsi_Host *instance = (struct Scsi_Host *)dev_id; + struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *) instance->hostdata; int done; unsigned char basr; - struct NCR5380_hostdata *hostdata; - int handled = 0; dprintk(NDEBUG_INTR, ("scsi : NCR5380 irq %d triggered\n", irq)); do { done = 1; - /* The instance list is constant while the driver is - loaded */ - for (hostdata = first_host; hostdata != NULL; hostdata = hostdata->next) - { - instance = hostdata->host; - if (instance->irq == irq) { - handled = 1; - spin_lock_irq(instance->host_lock); - /* Look for pending interrupts */ - NCR5380_setup(instance); - basr = NCR5380_read(BUS_AND_STATUS_REG); - /* XXX dispatch to appropriate routine if found and done=0 */ - if (basr & BASR_IRQ) { - NCR5380_dprint(NDEBUG_INTR, instance); - if ((NCR5380_read(STATUS_REG) & (SR_SEL | SR_IO)) == (SR_SEL | SR_IO)) { - done = 0; - dprintk(NDEBUG_INTR, ("scsi%d : SEL interrupt\n", instance->host_no)); - NCR5380_reselect(instance); - (void) NCR5380_read(RESET_PARITY_INTERRUPT_REG); - } else if (basr & BASR_PARITY_ERROR) { - dprintk(NDEBUG_INTR, ("scsi%d : PARITY interrupt\n", instance->host_no)); - (void) NCR5380_read(RESET_PARITY_INTERRUPT_REG); - } else if ((NCR5380_read(STATUS_REG) & SR_RST) == SR_RST) { - dprintk(NDEBUG_INTR, ("scsi%d : RESET interrupt\n", instance->host_no)); - (void) NCR5380_read(RESET_PARITY_INTERRUPT_REG); - } else { + spin_lock_irq(instance->host_lock); + /* Look for pending interrupts */ + NCR5380_setup(instance); + basr = NCR5380_read(BUS_AND_STATUS_REG); + /* XXX dispatch to appropriate routine if found and done=0 */ + if (basr & BASR_IRQ) { + NCR5380_dprint(NDEBUG_INTR, instance); + if ((NCR5380_read(STATUS_REG) & (SR_SEL | SR_IO)) == (SR_SEL | SR_IO)) { + done = 0; + dprintk(NDEBUG_INTR, ("scsi%d : SEL interrupt\n", instance->host_no)); + NCR5380_reselect(instance); + (void) NCR5380_read(RESET_PARITY_INTERRUPT_REG); + } else if (basr & BASR_PARITY_ERROR) { + dprintk(NDEBUG_INTR, ("scsi%d : PARITY interrupt\n", instance->host_no)); + (void) NCR5380_read(RESET_PARITY_INTERRUPT_REG); + } else if ((NCR5380_read(STATUS_REG) & SR_RST) == SR_RST) { + dprintk(NDEBUG_INTR, ("scsi%d : RESET interrupt\n", instance->host_no)); + (void) NCR5380_read(RESET_PARITY_INTERRUPT_REG); + } else { #if defined(REAL_DMA) - /* - * We should only get PHASE MISMATCH and EOP interrupts - * if we have DMA enabled, so do a sanity check based on - * the current setting of the MODE register. - */ - - if ((NCR5380_read(MODE_REG) & MR_DMA) && ((basr & BASR_END_DMA_TRANSFER) || !(basr & BASR_PHASE_MATCH))) { - int transfered; - - if (!hostdata->connected) - panic("scsi%d : received end of DMA interrupt with no connected cmd\n", instance->hostno); - - transfered = (hostdata->dmalen - NCR5380_dma_residual(instance)); - hostdata->connected->SCp.this_residual -= transferred; - hostdata->connected->SCp.ptr += transferred; - hostdata->dmalen = 0; + /* + * We should only get PHASE MISMATCH and EOP interrupts + * if we have DMA enabled, so do a sanity check based on + * the current setting of the MODE register. + */ + + if ((NCR5380_read(MODE_REG) & MR_DMA) && ((basr & BASR_END_DMA_TRANSFER) || !(basr & BASR_PHASE_MATCH))) { + int transfered; + + if (!hostdata->connected) + panic("scsi%d : received end of DMA interrupt with no connected cmd\n", instance->hostno); + + transfered = (hostdata->dmalen - NCR5380_dma_residual(instance)); + hostdata->connected->SCp.this_residual -= transferred; + hostdata->connected->SCp.ptr += transferred; + hostdata->dmalen = 0; - (void) NCR5380_read(RESET_PARITY_INTERRUPT_REG); + (void) NCR5380_read(RESET_PARITY_INTERRUPT_REG); - /* FIXME: we need to poll briefly then defer a workqueue task ! */ - NCR5380_poll_politely(hostdata, BUS_AND_STATUS_REG, BASR_ACK, 0, 2*HZ); + /* FIXME: we need to poll briefly then defer a workqueue task ! */ + NCR5380_poll_politely(hostdata, BUS_AND_STATUS_REG, BASR_ACK, 0, 2*HZ); - NCR5380_write(MODE_REG, MR_BASE); - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); - } + NCR5380_write(MODE_REG, MR_BASE); + NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); + } #else - dprintk(NDEBUG_INTR, ("scsi : unknown interrupt, BASR 0x%X, MR 0x%X, SR 0x%x\n", basr, NCR5380_read(MODE_REG), NCR5380_read(STATUS_REG))); - (void) NCR5380_read(RESET_PARITY_INTERRUPT_REG); + dprintk(NDEBUG_INTR, ("scsi : unknown interrupt, BASR 0x%X, MR 0x%X, SR 0x%x\n", basr, NCR5380_read(MODE_REG), NCR5380_read(STATUS_REG))); + (void) NCR5380_read(RESET_PARITY_INTERRUPT_REG); #endif - } - } /* if BASR_IRQ */ - spin_unlock_irq(instance->host_lock); - if(!done) - schedule_work(&hostdata->coroutine); - } /* if (instance->irq == irq) */ - } + } + } /* if BASR_IRQ */ + spin_unlock_irq(instance->host_lock); + if(!done) + schedule_work(&hostdata->coroutine); } while (!done); - return IRQ_RETVAL(handled); + return IRQ_HANDLED; } #endif diff -Nru a/drivers/scsi/NCR53C9x.c b/drivers/scsi/NCR53C9x.c --- a/drivers/scsi/NCR53C9x.c Sun Feb 22 12:59:47 2004 +++ b/drivers/scsi/NCR53C9x.c Sun Feb 22 12:59:47 2004 @@ -3615,6 +3615,27 @@ } #endif +int esp_slave_alloc(Scsi_Device *SDptr) +{ + struct esp_device *esp_dev = + kmalloc(sizeof(struct esp_device), GFP_ATOMIC); + + if (!esp_dev) + return -ENOMEM; + memset(esp_dev, 0, sizeof(struct esp_device)); + SDptr->hostdata = esp_dev; + return 0; +} + +void esp_slave_destroy(Scsi_Device *SDptr) +{ + struct NCR_ESP *esp = (struct NCR_ESP *) SDptr->host->hostdata; + + esp->targets_present &= ~(1 << SDptr->id); + kfree(SDptr->hostdata); + SDptr->hostdata = NULL; +} + #ifdef MODULE int init_module(void) { return 0; } void cleanup_module(void) {} diff -Nru a/drivers/scsi/NCR53C9x.h b/drivers/scsi/NCR53C9x.h --- a/drivers/scsi/NCR53C9x.h Sun Feb 22 12:59:47 2004 +++ b/drivers/scsi/NCR53C9x.h Sun Feb 22 12:59:47 2004 @@ -665,4 +665,6 @@ extern int esp_reset(Scsi_Cmnd *); extern int esp_proc_info(struct Scsi_Host *shost, char *buffer, char **start, off_t offset, int length, int inout); +extern int esp_slave_alloc(Scsi_Device *); +extern void esp_slave_destroy(Scsi_Device *); #endif /* !(NCR53C9X_H) */ diff -Nru a/drivers/scsi/aacraid/Makefile b/drivers/scsi/aacraid/Makefile --- a/drivers/scsi/aacraid/Makefile Sun Feb 22 12:59:47 2004 +++ b/drivers/scsi/aacraid/Makefile Sun Feb 22 12:59:47 2004 @@ -3,6 +3,6 @@ obj-$(CONFIG_SCSI_AACRAID) := aacraid.o aacraid-objs := linit.o aachba.o commctrl.o comminit.o commsup.o \ - dpcsup.o rx.o sa.o + dpcsup.o rx.o sa.o rkt.o EXTRA_CFLAGS := -Idrivers/scsi diff -Nru a/drivers/scsi/aacraid/aacraid.h b/drivers/scsi/aacraid/aacraid.h --- a/drivers/scsi/aacraid/aacraid.h Sun Feb 22 12:59:47 2004 +++ b/drivers/scsi/aacraid/aacraid.h Sun Feb 22 12:59:47 2004 @@ -512,6 +512,7 @@ void (*adapter_enable_int)(struct aac_dev *dev, u32 event); void (*adapter_disable_int)(struct aac_dev *dev, u32 event); int (*adapter_sync_cmd)(struct aac_dev *dev, u32 command, u32 p1, u32 *status); + int (*adapter_check_health)(struct aac_dev *dev); }; /* @@ -713,6 +714,24 @@ #define rx_writeb(AEP, CSR, value) writeb(value, &((AEP)->regs.rx->CSR)) #define rx_writel(AEP, CSR, value) writel(value, &((AEP)->regs.rx->CSR)) +/* + * Rkt Message Unit Registers (same as Rx, except a larger reserve region) + */ + +#define rkt_mu_registers rx_mu_registers +#define rkt_inbound rx_inbound + +struct rkt_registers { + struct rkt_mu_registers MUnit; /* 1300h - 1334h */ + u32 reserved1[1010]; /* 1338h - 22fch */ + struct rkt_inbound IndexRegs; /* 2300h - */ +}; + +#define rkt_readb(AEP, CSR) readb(&((AEP)->regs.rkt->CSR)) +#define rkt_readl(AEP, CSR) readl(&((AEP)->regs.rkt->CSR)) +#define rkt_writeb(AEP, CSR, value) writeb(value, &((AEP)->regs.rkt->CSR)) +#define rkt_writel(AEP, CSR, value) writel(value, &((AEP)->regs.rkt->CSR)) + struct fib; typedef void (*fib_callback)(void *ctxt, struct fib *fibctx); @@ -889,7 +908,9 @@ { struct sa_registers *sa; struct rx_registers *rx; + struct rkt_registers *rkt; } regs; + u32 OIMR; /* Mask Register Cache */ /* * The following is the number of the individual adapter */ @@ -922,6 +943,8 @@ #define aac_adapter_disable_int(dev, event) \ dev->a_ops.adapter_disable_int(dev, event) +#define aac_adapter_check_health(dev) \ + (dev)->a_ops.adapter_check_health(dev) #define FIB_CONTEXT_FLAG_TIMED_OUT (0x00000001) @@ -1492,6 +1515,7 @@ int aac_dev_ioctl(struct aac_dev *dev, int cmd, void *arg); int aac_do_ioctl(struct aac_dev * dev, int cmd, void *arg); int aac_rx_init(struct aac_dev *dev, unsigned long devNumber); +int aac_rkt_init(struct aac_dev *dev, unsigned long devNumber); int aac_sa_init(struct aac_dev *dev, unsigned long devNumber); unsigned int aac_response_normal(struct aac_queue * q); unsigned int aac_command_normal(struct aac_queue * q); diff -Nru a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c --- a/drivers/scsi/aacraid/linit.c Sun Feb 22 12:59:47 2004 +++ b/drivers/scsi/aacraid/linit.c Sun Feb 22 12:59:47 2004 @@ -49,6 +49,7 @@ #include #include #include +#include #include "aacraid.h" @@ -101,14 +102,20 @@ { 0x9005, 0x0285, 0x9005, 0x028a, 0, 0, 18 }, /* ASR-2020S PCI-X ZCR (Skyhawk)*/ { 0x9005, 0x0285, 0x9005, 0x028b, 0, 0, 19 }, /* ASR-2020S SO-DIMM PCI-X ZCR(Terminator)*/ { 0x9005, 0x0285, 0x9005, 0x0290, 0, 0, 20 }, /* AAR-2410SA PCI SATA 4ch (Jaguar II)*/ - { 0x9005, 0x0250, 0x1014, 0x0279, 0, 0, 21 }, /* (Marco)*/ - { 0x9005, 0x0250, 0x1014, 0x028c, 0, 0, 22 }, /* (Sebring)*/ - { 0x9005, 0x0285, 0x1028, 0x0287, 0, 0, 23 }, /* Perc 320/DC*/ - { 0x1011, 0x0046, 0x9005, 0x0365, 0, 0, 24 }, /* Adaptec 5400S (Mustang)*/ - { 0x1011, 0x0046, 0x9005, 0x0364, 0, 0, 25 }, /* Adaptec 5400S (Mustang)*/ - { 0x1011, 0x0046, 0x9005, 0x1364, 0, 0, 26 }, /* Dell PERC2 "Quad Channel" */ - { 0x1011, 0x0046, 0x103c, 0x10c2, 0, 0, 27 }, /* HP NetRAID-4M */ + { 0x9005, 0x0285, 0x1028, 0x0287, 0, 0, 21 }, /* Perc 320/DC*/ + { 0x1011, 0x0046, 0x9005, 0x0365, 0, 0, 22 }, /* Adaptec 5400S (Mustang)*/ + { 0x1011, 0x0046, 0x9005, 0x0364, 0, 0, 23 }, /* Adaptec 5400S (Mustang)*/ + { 0x1011, 0x0046, 0x9005, 0x1364, 0, 0, 24 }, /* Dell PERC2 "Quad Channel" */ + { 0x1011, 0x0046, 0x103c, 0x10c2, 0, 0, 25 }, /* HP NetRAID-4M */ + + { 0x9005, 0x0285, 0x1028, 0x0291, 0, 0, 26 }, /* CERC SATA RAID 2 PCI SATA 6ch (DellCorsair) */ + { 0x9005, 0x0285, 0x9005, 0x0292, 0, 0, 27 }, /* AAR-2810SA PCI SATA 8ch (Corsair-8) */ + { 0x9005, 0x0285, 0x9005, 0x0293, 0, 0, 28 }, /* AAR-21610SA PCI SATA 16ch (Corsair-16) */ + { 0x9005, 0x0285, 0x9005, 0x0294, 0, 0, 29 }, /* ESD SO-DIMM PCI-X SATA ZCR (Prowler) */ + { 0x9005, 0x0285, 0x0E11, 0x0295, 0, 0, 30 }, /* SATA 6Ch (Bearcat) */ + + { 0x9005, 0x0286, 0x9005, 0x028c, 0, 0, 31 }, /* ASR-2230S + ASR-2230SLP PCI-X (Lancer) */ { 0,} }; MODULE_DEVICE_TABLE(pci, aac_pci_tbl); @@ -141,14 +148,20 @@ { aac_rx_init, "aacraid", "ADAPTEC ", "ASR-2020S PCI-X ", 2 }, /* ASR-2020S PCI-X ZCR (Skyhawk)*/ { aac_rx_init, "aacraid", "ADAPTEC ", "ASR-2020S PCI-X ", 2 }, /* ASR-2020S SO-DIMM PCI-X ZCR(Terminator)*/ { aac_rx_init, "aacraid", "ADAPTEC ", "AAR-2410SA SATA ", 2 }, /* AAR-2410SA PCI SATA 4ch (Jaguar II)*/ - { aac_rx_init, "aacraid", "ADAPTEC ", "Adaptec ", 2 }, /* (Marco)*/ - { aac_rx_init, "aacraid", "ADAPTEC ", "Adaptec ", 2 }, /* (Sebring)*/ { aac_rx_init, "percraid", "DELL ", "PERC 320/DC ", 2, AAC_QUIRK_31BIT }, /* Perc 320/DC*/ { aac_sa_init, "aacraid", "ADAPTEC ", "Adaptec 5400S ", 4 }, /* Adaptec 5400S (Mustang)*/ { aac_sa_init, "aacraid", "ADAPTEC ", "AAC-364 ", 4 }, /* Adaptec 5400S (Mustang)*/ { aac_sa_init, "percraid", "DELL ", "PERCRAID ", 4, AAC_QUIRK_31BIT }, /* Dell PERC2 "Quad Channel" */ - { aac_sa_init, "hpnraid", "HP ", "NetRAID ", 4 } /* HP NetRAID-4M */ + { aac_sa_init, "hpnraid", "HP ", "NetRAID ", 4 }, /* HP NetRAID-4M */ + + { aac_rx_init, "aacraid", "DELL ", "CERC SR2 ", 1 }, /* CERC SATA RAID 2 PCI SATA 6ch (DellCorsair) */ + { aac_rx_init, "aacraid", "ADAPTEC ", "AAR-2810SA SATA ", 1 }, /* AAR-2810SA PCI SATA 8ch (Corsair-8) */ + { aac_rx_init, "aacraid", "ADAPTEC ", "AAR-21610SA SATA", 1 }, /* AAR-21610SA PCI SATA 16ch (Corsair-16) */ + { aac_rx_init, "aacraid", "ADAPTEC ", "SO-DIMM SATA ZCR", 1 }, /* ESD SO-DIMM PCI-X SATA ZCR (Prowler) */ + { aac_rx_init, "aacraid", "ADAPTEC ", "SATA 6Channel ", 1 }, /* SATA 6Ch (Bearcat) */ + + { aac_rkt_init,"aacraid", "ADAPTEC ", "ASR-2230S PCI-X ", 2 }, /* ASR-2230S + ASR-2230SLP PCI-X (Lancer) */ }; /** @@ -327,6 +340,51 @@ return FAILED; } +/* + * aac_eh_reset - Reset command handling + * @scsi_cmd: SCSI command block causing the reset + * + */ +static int aac_eh_reset(struct scsi_cmnd* cmd) +{ + struct scsi_device * dev = cmd->device; + struct Scsi_Host * host = dev->host; + struct scsi_cmnd * command; + int count; + unsigned long flags; + + printk(KERN_ERR "%s: Host adapter reset request. SCSI hang ?\n", + AAC_DRIVERNAME); + + + if (aac_adapter_check_health((struct aac_dev *)host->hostdata)) { + printk(KERN_ERR "%s: Host adapter appears dead\n", + AAC_DRIVERNAME); + return -ENODEV; + } + /* + * Wait for all commands to complete to this specific + * target (block maximum 60 seconds). + */ + for (count = 60; count; --count) { + __shost_for_each_device(dev, host) { + spin_lock_irqsave(&dev->list_lock, flags); + list_for_each_entry(command, &dev->cmd_list, list) { + if (command->serial_number) { + spin_unlock_irqrestore(&dev->list_lock, flags); + return SUCCESS; + } + } + spin_unlock_irqrestore(&dev->list_lock, flags); + } + spin_unlock_irq(host->host_lock); + scsi_sleep(HZ); + spin_lock_irq(host->host_lock); + } + printk(KERN_ERR "%s: SCSI bus appears hung\n", AAC_DRIVERNAME); + return -ETIMEDOUT; +} + /** * aac_cfg_open - open a configuration file * @inode: inode being opened @@ -385,6 +443,7 @@ .bios_param = aac_biosparm, .slave_configure = aac_slave_configure, .eh_abort_handler = aac_eh_abort, + .eh_host_reset_handler = aac_eh_reset, .can_queue = AAC_NUM_IO_FIB, .this_id = 16, .sg_tablesize = 16, diff -Nru a/drivers/scsi/aacraid/rkt.c b/drivers/scsi/aacraid/rkt.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/scsi/aacraid/rkt.c Sun Feb 22 12:59:47 2004 @@ -0,0 +1,448 @@ +/* + * Adaptec AAC series RAID controller driver + * (c) Copyright 2001 Red Hat Inc. + * + * based on the old aacraid driver that is.. + * Adaptec aacraid device driver for Linux. + * + * Copyright (c) 2000 Adaptec, Inc. (aacraid@adaptec.com) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * + * Module Name: + * rkt.c + * + * Abstract: Hardware miniport for Drawbridge specific hardware functions. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "aacraid.h" + +static irqreturn_t aac_rkt_intr(int irq, void *dev_id, struct pt_regs *regs) +{ + struct aac_dev *dev = dev_id; + unsigned long bellbits; + u8 intstat, mask; + intstat = rkt_readb(dev, MUnit.OISR); + /* + * Read mask and invert because drawbridge is reversed. + * This allows us to only service interrupts that have + * been enabled. + */ + mask = ~(dev->OIMR); + /* Check to see if this is our interrupt. If it isn't just return */ + if (intstat & mask) + { + bellbits = rkt_readl(dev, OutboundDoorbellReg); + if (bellbits & DoorBellPrintfReady) { + aac_printf(dev, le32_to_cpu(rkt_readl (dev, IndexRegs.Mailbox[5]))); + rkt_writel(dev, MUnit.ODR,DoorBellPrintfReady); + rkt_writel(dev, InboundDoorbellReg,DoorBellPrintfDone); + } + else if (bellbits & DoorBellAdapterNormCmdReady) { + aac_command_normal(&dev->queues->queue[HostNormCmdQueue]); + rkt_writel(dev, MUnit.ODR, DoorBellAdapterNormCmdReady); + } + else if (bellbits & DoorBellAdapterNormRespReady) { + aac_response_normal(&dev->queues->queue[HostNormRespQueue]); + rkt_writel(dev, MUnit.ODR,DoorBellAdapterNormRespReady); + } + else if (bellbits & DoorBellAdapterNormCmdNotFull) { + rkt_writel(dev, MUnit.ODR, DoorBellAdapterNormCmdNotFull); + } + else if (bellbits & DoorBellAdapterNormRespNotFull) { + rkt_writel(dev, MUnit.ODR, DoorBellAdapterNormCmdNotFull); + rkt_writel(dev, MUnit.ODR, DoorBellAdapterNormRespNotFull); + } + return IRQ_HANDLED; + } + return IRQ_NONE; +} + +/** + * aac_rkt_enable_interrupt - Enable event reporting + * @dev: Adapter + * @event: Event to enable + * + * Enable event reporting from the i960 for a given event. + */ + +static void aac_rkt_enable_interrupt(struct aac_dev * dev, u32 event) +{ + switch (event) { + + case HostNormCmdQue: + dev->irq_mask &= ~(OUTBOUNDDOORBELL_1); + break; + + case HostNormRespQue: + dev->irq_mask &= ~(OUTBOUNDDOORBELL_2); + break; + + case AdapNormCmdNotFull: + dev->irq_mask &= ~(OUTBOUNDDOORBELL_3); + break; + + case AdapNormRespNotFull: + dev->irq_mask &= ~(OUTBOUNDDOORBELL_4); + break; + } +} + +/** + * aac_rkt_disable_interrupt - Disable event reporting + * @dev: Adapter + * @event: Event to enable + * + * Disable event reporting from the i960 for a given event. + */ + +static void aac_rkt_disable_interrupt(struct aac_dev *dev, u32 event) +{ + switch (event) { + + case HostNormCmdQue: + dev->irq_mask |= (OUTBOUNDDOORBELL_1); + break; + + case HostNormRespQue: + dev->irq_mask |= (OUTBOUNDDOORBELL_2); + break; + + case AdapNormCmdNotFull: + dev->irq_mask |= (OUTBOUNDDOORBELL_3); + break; + + case AdapNormRespNotFull: + dev->irq_mask |= (OUTBOUNDDOORBELL_4); + break; + } +} + +/** + * rkt_sync_cmd - send a command and wait + * @dev: Adapter + * @command: Command to execute + * @p1: first parameter + * @ret: adapter status + * + * This routine will send a synchronous comamnd to the adapter and wait + * for its completion. + */ + +static int rkt_sync_cmd(struct aac_dev *dev, u32 command, u32 p1, u32 *status) +{ + unsigned long start; + int ok; + /* + * Write the command into Mailbox 0 + */ + rkt_writel(dev, InboundMailbox0, cpu_to_le32(command)); + /* + * Write the parameters into Mailboxes 1 - 4 + */ + rkt_writel(dev, InboundMailbox1, cpu_to_le32(p1)); + rkt_writel(dev, InboundMailbox2, 0); + rkt_writel(dev, InboundMailbox3, 0); + rkt_writel(dev, InboundMailbox4, 0); + /* + * Clear the synch command doorbell to start on a clean slate. + */ + rkt_writel(dev, OutboundDoorbellReg, OUTBOUNDDOORBELL_0); + /* + * Disable doorbell interrupts + */ + rkt_writeb(dev, MUnit.OIMR, dev->OIMR |= 0x04); + /* + * Force the completion of the mask register write before issuing + * the interrupt. + */ + rkt_readb (dev, MUnit.OIMR); + /* + * Signal that there is a new synch command + */ + rkt_writel(dev, InboundDoorbellReg, INBOUNDDOORBELL_0); + + ok = 0; + start = jiffies; + + /* + * Wait up to 30 seconds + */ + while (time_before(jiffies, start+30*HZ)) + { + udelay(5); /* Delay 5 microseconds to let Mon960 get info. */ + /* + * Mon960 will set doorbell0 bit when it has completed the command. + */ + if (rkt_readl(dev, OutboundDoorbellReg) & OUTBOUNDDOORBELL_0) { + /* + * Clear the doorbell. + */ + rkt_writel(dev, OutboundDoorbellReg, OUTBOUNDDOORBELL_0); + ok = 1; + break; + } + /* + * Yield the processor in case we are slow + */ + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(1); + } + if (ok != 1) { + /* + * Restore interrupt mask even though we timed out + */ + rkt_writeb(dev, MUnit.OIMR, dev->OIMR &= 0xfb); + return -ETIMEDOUT; + } + /* + * Pull the synch status from Mailbox 0. + */ + *status = le32_to_cpu(rkt_readl(dev, IndexRegs.Mailbox[0])); + /* + * Clear the synch command doorbell. + */ + rkt_writel(dev, OutboundDoorbellReg, OUTBOUNDDOORBELL_0); + /* + * Restore interrupt mask + */ + rkt_writeb(dev, MUnit.OIMR, dev->OIMR &= 0xfb); + return 0; + +} + +/** + * aac_rkt_interrupt_adapter - interrupt adapter + * @dev: Adapter + * + * Send an interrupt to the i960 and breakpoint it. + */ + +static void aac_rkt_interrupt_adapter(struct aac_dev *dev) +{ + u32 ret; + rkt_sync_cmd(dev, BREAKPOINT_REQUEST, 0, &ret); +} + +/** + * aac_rkt_notify_adapter - send an event to the adapter + * @dev: Adapter + * @event: Event to send + * + * Notify the i960 that something it probably cares about has + * happened. + */ + +static void aac_rkt_notify_adapter(struct aac_dev *dev, u32 event) +{ + switch (event) { + + case AdapNormCmdQue: + rkt_writel(dev, MUnit.IDR,INBOUNDDOORBELL_1); + break; + case HostNormRespNotFull: + rkt_writel(dev, MUnit.IDR,INBOUNDDOORBELL_4); + break; + case AdapNormRespQue: + rkt_writel(dev, MUnit.IDR,INBOUNDDOORBELL_2); + break; + case HostNormCmdNotFull: + rkt_writel(dev, MUnit.IDR,INBOUNDDOORBELL_3); + break; + case HostShutdown: +// rkt_sync_cmd(dev, HOST_CRASHING, 0, 0, 0, 0, &ret); + break; + case FastIo: + rkt_writel(dev, MUnit.IDR,INBOUNDDOORBELL_6); + break; + case AdapPrintfDone: + rkt_writel(dev, MUnit.IDR,INBOUNDDOORBELL_5); + break; + default: + BUG(); + break; + } +} + +/** + * aac_rkt_start_adapter - activate adapter + * @dev: Adapter + * + * Start up processing on an i960 based AAC adapter + */ + +static void aac_rkt_start_adapter(struct aac_dev *dev) +{ + u32 status; + struct aac_init *init; + + init = dev->init; + init->HostElapsedSeconds = cpu_to_le32(jiffies/HZ); + /* + * Tell the adapter we are back and up and running so it will scan + * its command queues and enable our interrupts + */ + dev->irq_mask = (DoorBellPrintfReady | OUTBOUNDDOORBELL_1 | OUTBOUNDDOORBELL_2 | OUTBOUNDDOORBELL_3 | OUTBOUNDDOORBELL_4); + /* + * First clear out all interrupts. Then enable the one's that we + * can handle. + */ + rkt_writeb(dev, MUnit.OIMR, 0xff); + rkt_writel(dev, MUnit.ODR, 0xffffffff); +// rkt_writeb(dev, MUnit.OIMR, ~(u8)OUTBOUND_DOORBELL_INTERRUPT_MASK); + rkt_writeb(dev, MUnit.OIMR, dev->OIMR = 0xfb); + + // We can only use a 32 bit address here + rkt_sync_cmd(dev, INIT_STRUCT_BASE_ADDRESS, (u32)(ulong)dev->init_pa, &status); +} + +/** + * aac_rkt_check_health + * @dev: device to check if healthy + * + * Will attempt to determine if the specified adapter is alive and + * capable of handling requests, returning 0 if alive. + */ +static int aac_rkt_check_health(struct aac_dev *dev) +{ + long status = rkt_readl(dev, IndexRegs.Mailbox[7]); + + /* + * Check to see if the board failed any self tests. + */ + if (status & SELF_TEST_FAILED) + return -1; + /* + * Check to see if the board panic'd while booting. + */ + if (status & KERNEL_PANIC) + return -2; + /* + * Wait for the adapter to be up and running. Wait up to 3 minutes + */ + if (!(status & KERNEL_UP_AND_RUNNING)) + return -3; + /* + * Everything is OK + */ + return 0; +} /* aac_rkt_check_health */ + +/** + * aac_rkt_init - initialize an i960 based AAC card + * @dev: device to configure + * @devnum: adapter number + * + * Allocate and set up resources for the i960 based AAC variants. The + * device_interface in the commregion will be allocated and linked + * to the comm region. + */ + +int aac_rkt_init(struct aac_dev *dev, unsigned long num) +{ + unsigned long start; + unsigned long status; + int instance; + const char * name; + + dev->devnum = num; + instance = dev->id; + name = dev->name; + + /* + * Map in the registers from the adapter. + */ + if((dev->regs.rkt = (struct rkt_registers *)ioremap((unsigned long)dev->scsi_host_ptr->base, 8192))==NULL) + { + printk(KERN_WARNING "aacraid: unable to map i960.\n" ); + return -1; + } + /* + * Check to see if the board failed any self tests. + */ + if (rkt_readl(dev, IndexRegs.Mailbox[7]) & SELF_TEST_FAILED) { + printk(KERN_ERR "%s%d: adapter self-test failed.\n", dev->name, instance); + return -1; + } + /* + * Check to see if the board panic'd while booting. + */ + if (rkt_readl(dev, IndexRegs.Mailbox[7]) & KERNEL_PANIC) { + printk(KERN_ERR "%s%d: adapter kernel panic'd.\n", dev->name, instance); + return -1; + } + start = jiffies; + /* + * Wait for the adapter to be up and running. Wait up to 3 minutes + */ + while (!(rkt_readl(dev, IndexRegs.Mailbox[7]) & KERNEL_UP_AND_RUNNING)) + { + if(time_after(jiffies, start+180*HZ)) + { + status = rkt_readl(dev, IndexRegs.Mailbox[7]) >> 16; + printk(KERN_ERR "%s%d: adapter kernel failed to start, init status = %ld.\n", dev->name, instance, status); + return -1; + } + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(1); + } + if (request_irq(dev->scsi_host_ptr->irq, aac_rkt_intr, SA_SHIRQ|SA_INTERRUPT, "aacraid", (void *)dev)<0) + { + printk(KERN_ERR "%s%d: Interrupt unavailable.\n", name, instance); + return -1; + } + /* + * Fill in the function dispatch table. + */ + dev->a_ops.adapter_interrupt = aac_rkt_interrupt_adapter; + dev->a_ops.adapter_enable_int = aac_rkt_enable_interrupt; + dev->a_ops.adapter_disable_int = aac_rkt_disable_interrupt; + dev->a_ops.adapter_notify = aac_rkt_notify_adapter; + dev->a_ops.adapter_sync_cmd = rkt_sync_cmd; + + if (aac_init_adapter(dev) == NULL) + return -1; + /* + * Start any kernel threads needed + */ + dev->thread_pid = kernel_thread((int (*)(void *))aac_command_thread, dev, 0); + if(dev->thread_pid < 0) + { + printk(KERN_ERR "aacraid: Unable to create rkt thread.\n"); + return -1; + } + /* + * Tell the adapter that all is configured, and it can start + * accepting requests + */ + aac_rkt_start_adapter(dev); + return 0; +} diff -Nru a/drivers/scsi/aacraid/rx.c b/drivers/scsi/aacraid/rx.c --- a/drivers/scsi/aacraid/rx.c Sun Feb 22 12:59:47 2004 +++ b/drivers/scsi/aacraid/rx.c Sun Feb 22 12:59:47 2004 @@ -56,7 +56,7 @@ * This allows us to only service interrupts that have * been enabled. */ - mask = ~(rx_readb(dev, MUnit.OIMR)); + mask = ~(dev->OIMR); /* Check to see if this is our interrupt. If it isn't just return */ if (intstat & mask) { @@ -179,7 +179,7 @@ /* * Disable doorbell interrupts */ - rx_writeb(dev, MUnit.OIMR, rx_readb(dev, MUnit.OIMR) | 0x04); + rx_writeb(dev, MUnit.OIMR, dev->OIMR |= 0x04); /* * Force the completion of the mask register write before issuing * the interrupt. @@ -220,7 +220,7 @@ /* * Restore interrupt mask even though we timed out */ - rx_writeb(dev, MUnit.OIMR, rx_readl(dev, MUnit.OIMR) & 0xfb); + rx_writeb(dev, MUnit.OIMR, dev->OIMR &= 0xfb); return -ETIMEDOUT; } /* @@ -234,7 +234,7 @@ /* * Restore interrupt mask */ - rx_writeb(dev, MUnit.OIMR, rx_readl(dev, MUnit.OIMR) & 0xfb); + rx_writeb(dev, MUnit.OIMR, dev->OIMR &= 0xfb); return 0; } @@ -318,11 +318,43 @@ rx_writeb(dev, MUnit.OIMR, 0xff); rx_writel(dev, MUnit.ODR, 0xffffffff); // rx_writeb(dev, MUnit.OIMR, ~(u8)OUTBOUND_DOORBELL_INTERRUPT_MASK); - rx_writeb(dev, MUnit.OIMR, 0xfb); + rx_writeb(dev, MUnit.OIMR, dev->OIMR = 0xfb); // We can only use a 32 bit address here rx_sync_cmd(dev, INIT_STRUCT_BASE_ADDRESS, (u32)(ulong)dev->init_pa, &status); } + +/** + * aac_rx_check_health + * @dev: device to check if healthy + * + * Will attempt to determine if the specified adapter is alive and + * capable of handling requests, returning 0 if alive. + */ +static int aac_rx_check_health(struct aac_dev *dev) +{ + long status = rx_readl(dev, IndexRegs.Mailbox[7]); + + /* + * Check to see if the board failed any self tests. + */ + if (status & SELF_TEST_FAILED) + return -1; + /* + * Check to see if the board panic'd while booting. + */ + if (status & KERNEL_PANIC) + return -2; + /* + * Wait for the adapter to be up and running. Wait up to 3 minutes + */ + if (!(status & KERNEL_UP_AND_RUNNING)) + return -3; + /* + * Everything is OK + */ + return 0; +} /* aac_rx_check_health */ /** * aac_rx_init - initialize an i960 based AAC card diff -Nru a/drivers/scsi/aacraid/sa.c b/drivers/scsi/aacraid/sa.c --- a/drivers/scsi/aacraid/sa.c Sun Feb 22 12:59:47 2004 +++ b/drivers/scsi/aacraid/sa.c Sun Feb 22 12:59:47 2004 @@ -300,6 +300,38 @@ } /** + * aac_sa_check_health + * @dev: device to check if healthy + * + * Will attempt to determine if the specified adapter is alive and + * capable of handling requests, returning 0 if alive. + */ +static int aac_sa_check_health(struct aac_dev *dev) +{ + long status = sa_readl(dev, Mailbox7); + + /* + * Check to see if the board failed any self tests. + */ + if (status & SELF_TEST_FAILED) + return -1; + /* + * Check to see if the board panic'd while booting. + */ + if (status & KERNEL_PANIC) + return -2; + /* + * Wait for the adapter to be up and running. Wait up to 3 minutes + */ + if (!(status & KERNEL_UP_AND_RUNNING)) + return -3; + /* + * Everything is OK + */ + return 0; +} /* aac_sa_check_health */ + +/** * aac_sa_init - initialize an ARM based AAC card * @dev: device to configure * @devnum: adapter number diff -Nru a/drivers/scsi/blz1230.c b/drivers/scsi/blz1230.c --- a/drivers/scsi/blz1230.c Sun Feb 22 12:59:47 2004 +++ b/drivers/scsi/blz1230.c Sun Feb 22 12:59:47 2004 @@ -333,6 +333,8 @@ .proc_info = esp_proc_info, .name = "Blizzard1230 SCSI IV", .detect = blz1230_esp_detect, + .slave_alloc = esp_slave_alloc, + .slave_destroy = esp_slave_destroy, .release = blz1230_esp_release, .queuecommand = esp_queue, .eh_abort_handler = esp_abort, diff -Nru a/drivers/scsi/blz2060.c b/drivers/scsi/blz2060.c --- a/drivers/scsi/blz2060.c Sun Feb 22 12:59:47 2004 +++ b/drivers/scsi/blz2060.c Sun Feb 22 12:59:47 2004 @@ -287,6 +287,8 @@ .proc_info = esp_proc_info, .name = "Blizzard2060 SCSI", .detect = blz2060_esp_detect, + .slave_alloc = esp_slave_alloc, + .slave_destroy = esp_slave_destroy, .release = blz2060_esp_release, .queuecommand = esp_queue, .eh_abort_handler = esp_abort, diff -Nru a/drivers/scsi/cyberstorm.c b/drivers/scsi/cyberstorm.c --- a/drivers/scsi/cyberstorm.c Sun Feb 22 12:59:47 2004 +++ b/drivers/scsi/cyberstorm.c Sun Feb 22 12:59:47 2004 @@ -358,6 +358,8 @@ .proc_info = esp_proc_info, .name = "CyberStorm SCSI", .detect = cyber_esp_detect, + .slave_alloc = esp_slave_alloc, + .slave_destroy = esp_slave_destroy, .release = cyber_esp_release, .queuecommand = esp_queue, .eh_abort_handler = esp_abort, diff -Nru a/drivers/scsi/cyberstormII.c b/drivers/scsi/cyberstormII.c --- a/drivers/scsi/cyberstormII.c Sun Feb 22 12:59:47 2004 +++ b/drivers/scsi/cyberstormII.c Sun Feb 22 12:59:47 2004 @@ -295,6 +295,8 @@ .proc_info = esp_proc_info, .name = "CyberStorm Mk II SCSI", .detect = cyberII_esp_detect, + .slave_alloc = esp_slave_alloc, + .slave_destroy = esp_slave_destroy, .release = cyberII_esp_release, .queuecommand = esp_queue, .eh_abort_handler = esp_abort, diff -Nru a/drivers/scsi/dec_esp.c b/drivers/scsi/dec_esp.c --- a/drivers/scsi/dec_esp.c Sun Feb 22 12:59:47 2004 +++ b/drivers/scsi/dec_esp.c Sun Feb 22 12:59:47 2004 @@ -124,6 +124,8 @@ .proc_info = &esp_proc_info, .name = "NCR53C94", .detect = dec_esp_detect, + .slave_alloc = esp_slave_alloc, + .slave_destroy = esp_slave_destroy, .release = dec_esp_release, .info = esp_info, .queuecommand = esp_queue, diff -Nru a/drivers/scsi/fastlane.c b/drivers/scsi/fastlane.c --- a/drivers/scsi/fastlane.c Sun Feb 22 12:59:47 2004 +++ b/drivers/scsi/fastlane.c Sun Feb 22 12:59:47 2004 @@ -404,6 +404,8 @@ .proc_info = esp_proc_info, .name = "Fastlane SCSI", .detect = fastlane_esp_detect, + .slave_alloc = esp_slave_alloc, + .slave_destroy = esp_slave_destroy, .release = fastlane_esp_release, .queuecommand = esp_queue, .eh_abort_handler = esp_abort, diff -Nru a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c --- a/drivers/scsi/g_NCR5380.c Sun Feb 22 12:59:47 2004 +++ b/drivers/scsi/g_NCR5380.c Sun Feb 22 12:59:47 2004 @@ -450,7 +450,7 @@ instance->irq = NCR5380_probe_irq(instance, 0xffff); if (instance->irq != SCSI_IRQ_NONE) - if (request_irq(instance->irq, generic_NCR5380_intr, SA_INTERRUPT, "NCR5380", NULL)) { + if (request_irq(instance->irq, generic_NCR5380_intr, SA_INTERRUPT, "NCR5380", instance)) { printk(KERN_WARNING "scsi%d : IRQ%d not free, interrupts disabled\n", instance->host_no, instance->irq); instance->irq = SCSI_IRQ_NONE; } diff -Nru a/drivers/scsi/ini9100u.c b/drivers/scsi/ini9100u.c --- a/drivers/scsi/ini9100u.c Sun Feb 22 12:59:47 2004 +++ b/drivers/scsi/ini9100u.c Sun Feb 22 12:59:47 2004 @@ -272,6 +272,17 @@ return (pSRB); } +static irqreturn_t i91u_intr(int irqno, void *dev_id, struct pt_regs *regs) +{ + struct Scsi_Host *dev = dev_id; + unsigned long flags; + + spin_lock_irqsave(dev->host_lock, flags); + tul_isr((HCS *)hreg->base); + spin_unlock_irqrestore(dev->host_lock, flags); + return IRQ_HANDLED; +} + /* called from init/main.c */ void i91u_setup(char *str, int *ints) @@ -396,8 +407,7 @@ pHCB->HCS_Index = i; /* 7/29/98 */ hreg = scsi_register(tpnt, sizeof(HCS)); - if(hreg == NULL) - { + if(hreg == NULL) { release_region(pHCB->HCS_Base, 256); return 0; } @@ -413,48 +423,10 @@ hreg->sg_tablesize = TOTAL_SG_ENTRY; /* Maximun support is 32 */ /* Initial tulip chip */ - switch (i) { - case 0: - ok = request_irq(pHCB->HCS_Intr, i91u_intr0, SA_INTERRUPT | SA_SHIRQ, "i91u", hreg); - break; - case 1: - ok = request_irq(pHCB->HCS_Intr, i91u_intr1, SA_INTERRUPT | SA_SHIRQ, "i91u", hreg); - break; - case 2: - ok = request_irq(pHCB->HCS_Intr, i91u_intr2, SA_INTERRUPT | SA_SHIRQ, "i91u", hreg); - break; - case 3: - ok = request_irq(pHCB->HCS_Intr, i91u_intr3, SA_INTERRUPT | SA_SHIRQ, "i91u", hreg); - break; - case 4: - ok = request_irq(pHCB->HCS_Intr, i91u_intr4, SA_INTERRUPT | SA_SHIRQ, "i91u", hreg); - break; - case 5: - ok = request_irq(pHCB->HCS_Intr, i91u_intr5, SA_INTERRUPT | SA_SHIRQ, "i91u", hreg); - break; - case 6: - ok = request_irq(pHCB->HCS_Intr, i91u_intr6, SA_INTERRUPT | SA_SHIRQ, "i91u", hreg); - break; - case 7: - ok = request_irq(pHCB->HCS_Intr, i91u_intr7, SA_INTERRUPT | SA_SHIRQ, "i91u", hreg); - break; - default: - i91u_panic("i91u: Too many host adapters\n"); - break; - } + ok = request_irq(pHCB->HCS_Intr, i91u_intr, SA_INTERRUPT | SA_SHIRQ, "i91u", hreg); 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"); + printk(KERN_WARNING "i91u: unable to request IRQ %d\n\n", pHCB->HCS_Intr); + return 0; } } @@ -729,137 +701,6 @@ tul_release_scb(pHCB, pSCB); /* Release SCB for current channel */ } return; -} - -/* - * Interrupts handler (main routine of the driver) - */ -static irqreturn_t i91u_intr0(int irqno, void *dev_id, struct pt_regs *regs) -{ - unsigned long flags; - struct Scsi_Host *dev = dev_id; - - if (tul_hcs[0].HCS_Intr != irqno) - return IRQ_NONE; - - spin_lock_irqsave(dev->host_lock, flags); - - tul_isr(&tul_hcs[0]); - - spin_unlock_irqrestore(dev->host_lock, flags); - return IRQ_HANDLED; -} - -static irqreturn_t i91u_intr1(int irqno, void *dev_id, struct pt_regs *regs) -{ - unsigned long flags; - struct Scsi_Host *dev = dev_id; - - if (tul_hcs[1].HCS_Intr != irqno) - return IRQ_NONE; - - spin_lock_irqsave(dev->host_lock, flags); - - tul_isr(&tul_hcs[1]); - - spin_unlock_irqrestore(dev->host_lock, flags); - return IRQ_HANDLED; -} - -static irqreturn_t i91u_intr2(int irqno, void *dev_id, struct pt_regs *regs) -{ - unsigned long flags; - struct Scsi_Host *dev = dev_id; - - if (tul_hcs[2].HCS_Intr != irqno) - return IRQ_NONE; - - spin_lock_irqsave(dev->host_lock, flags); - - tul_isr(&tul_hcs[2]); - - spin_unlock_irqrestore(dev->host_lock, flags); - return IRQ_HANDLED; -} - -static irqreturn_t i91u_intr3(int irqno, void *dev_id, struct pt_regs *regs) -{ - unsigned long flags; - struct Scsi_Host *dev = dev_id; - - if (tul_hcs[3].HCS_Intr != irqno) - return IRQ_NONE; - - spin_lock_irqsave(dev->host_lock, flags); - - tul_isr(&tul_hcs[3]); - - spin_unlock_irqrestore(dev->host_lock, flags); - return IRQ_HANDLED; -} - -static irqreturn_t i91u_intr4(int irqno, void *dev_id, struct pt_regs *regs) -{ - unsigned long flags; - struct Scsi_Host *dev = dev_id; - - if (tul_hcs[4].HCS_Intr != irqno) - return IRQ_NONE; - - spin_lock_irqsave(dev->host_lock, flags); - - tul_isr(&tul_hcs[4]); - - spin_unlock_irqrestore(dev->host_lock, flags); - return IRQ_HANDLED; -} - -static irqreturn_t i91u_intr5(int irqno, void *dev_id, struct pt_regs *regs) -{ - unsigned long flags; - struct Scsi_Host *dev = dev_id; - - if (tul_hcs[5].HCS_Intr != irqno) - return IRQ_NONE; - - spin_lock_irqsave(dev->host_lock, flags); - - tul_isr(&tul_hcs[5]); - - spin_unlock_irqrestore(dev->host_lock, flags); - return IRQ_HANDLED; -} - -static irqreturn_t i91u_intr6(int irqno, void *dev_id, struct pt_regs *regs) -{ - unsigned long flags; - struct Scsi_Host *dev = dev_id; - - if (tul_hcs[6].HCS_Intr != irqno) - return IRQ_NONE; - - spin_lock_irqsave(dev->host_lock, flags); - - tul_isr(&tul_hcs[6]); - - spin_unlock_irqrestore(dev->host_lock, flags); - return IRQ_HANDLED; -} - -static irqreturn_t i91u_intr7(int irqno, void *dev_id, struct pt_regs *regs) -{ - unsigned long flags; - struct Scsi_Host *dev = dev_id; - - if (tul_hcs[7].HCS_Intr != irqno) - return IRQ_NONE; - - spin_lock_irqsave(dev->host_lock, flags); - - tul_isr(&tul_hcs[7]); - - spin_unlock_irqrestore(dev->host_lock, flags); - return IRQ_HANDLED; } /* diff -Nru a/drivers/scsi/jazz_esp.c b/drivers/scsi/jazz_esp.c --- a/drivers/scsi/jazz_esp.c Sun Feb 22 12:59:47 2004 +++ b/drivers/scsi/jazz_esp.c Sun Feb 22 12:59:47 2004 @@ -290,6 +290,8 @@ .proc_info = &esp_proc_info, .name = "ESP 100/100a/200", .detect = jazz_esp_detect, + .slave_alloc = esp_slave_alloc, + .slave_destroy = esp_slave_destroy, .release = jazz_esp_release, .info = esp_info, .queuecommand = esp_queue, diff -Nru a/drivers/scsi/mac_esp.c b/drivers/scsi/mac_esp.c --- a/drivers/scsi/mac_esp.c Sun Feb 22 12:59:47 2004 +++ b/drivers/scsi/mac_esp.c Sun Feb 22 12:59:47 2004 @@ -734,6 +734,8 @@ .proc_name = "esp", .name = "Mac 53C9x SCSI", .detect = mac_esp_detect, + .slave_alloc = esp_slave_alloc, + .slave_destroy = esp_slave_destroy, .release = mac_esp_release, .info = esp_info, .queuecommand = esp_queue, diff -Nru a/drivers/scsi/mca_53c9x.c b/drivers/scsi/mca_53c9x.c --- a/drivers/scsi/mca_53c9x.c Sun Feb 22 12:59:47 2004 +++ b/drivers/scsi/mca_53c9x.c Sun Feb 22 12:59:47 2004 @@ -448,6 +448,8 @@ .proc_name = "esp", .name = "NCR 53c9x SCSI", .detect = mca_esp_detect, + .slave_alloc = esp_slave_alloc, + .slave_destroy = esp_slave_destroy, .release = mca_esp_release, .queuecommand = esp_queue, .eh_abort_handler = esp_abort, diff -Nru a/drivers/scsi/oktagon_esp.c b/drivers/scsi/oktagon_esp.c --- a/drivers/scsi/oktagon_esp.c Sun Feb 22 12:59:47 2004 +++ b/drivers/scsi/oktagon_esp.c Sun Feb 22 12:59:47 2004 @@ -595,6 +595,8 @@ .proc_info = &esp_proc_info, .name = "BSC Oktagon SCSI", .detect = oktagon_esp_detect, + .slave_alloc = esp_slave_alloc, + .slave_destroy = esp_slave_destroy, .release = oktagon_esp_release, .queuecommand = esp_queue, .eh_abort_handler = esp_abort, diff -Nru a/drivers/scsi/qla1280.c b/drivers/scsi/qla1280.c --- a/drivers/scsi/qla1280.c Sun Feb 22 12:59:47 2004 +++ b/drivers/scsi/qla1280.c Sun Feb 22 12:59:47 2004 @@ -348,7 +348,6 @@ #include #if LINUX_VERSION_CODE >= 0x020545 -#include /* for flush_cache_all() */ #include #include #include @@ -2122,8 +2121,6 @@ for(i = 0; i < cnt; i++) ((uint16_t *)ha->request_ring)[i] = cpu_to_le16(risc_code_address[i]); - - flush_cache_all(); mb[0] = MBC_LOAD_RAM; mb[1] = risc_address; diff -Nru a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c --- a/drivers/scsi/qla2xxx/qla_init.c Sun Feb 22 12:59:47 2004 +++ b/drivers/scsi/qla2xxx/qla_init.c Sun Feb 22 12:59:47 2004 @@ -690,12 +690,6 @@ for (i = 0; i < cnt; i++) req_ring[i] = cpu_to_le16(risc_code[i]); - /* - * Flush written firmware to the ha->request_ring buffer - * before DMA. - */ - flush_cache_all(); - if (fw_iter->addressing == FW_INFO_ADDR_NORMAL) { rval = qla2x00_load_ram(ha, ha->request_dma, risc_address, cnt); diff -Nru a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c --- a/drivers/scsi/qla2xxx/qla_isr.c Sun Feb 22 12:59:47 2004 +++ b/drivers/scsi/qla2xxx/qla_isr.c Sun Feb 22 12:59:47 2004 @@ -828,6 +828,7 @@ uint8_t lscsi_status; uint32_t resid; uint8_t sense_sz = 0; + uint16_t rsp_info_len; /* Fast path completion. */ if (le16_to_cpu(pkt->comp_status) == CS_COMPLETE && @@ -915,6 +916,24 @@ qla2x00_extend_timeout(cp, EXTEND_CMD_TIMEOUT); add_to_retry_queue(ha, sp); + return; + } + } + + /* Check for any FCP transport errors. */ + if (scsi_status & SS_RESPONSE_INFO_LEN_VALID) { + rsp_info_len = le16_to_cpu(pkt->rsp_info_len); + if (rsp_info_len > 3 && pkt->rsp_info[3]) { + DEBUG2(printk("scsi(%ld:%d:%d:%d) FCP I/O protocol " + "failure (%x/%02x%02x%02x%02x%02x%02x%02x%02x)..." + "retrying command\n", ha->host_no, b, t, l, + rsp_info_len, pkt->rsp_info[0], pkt->rsp_info[1], + pkt->rsp_info[2], pkt->rsp_info[3], + pkt->rsp_info[4], pkt->rsp_info[5], + pkt->rsp_info[6], pkt->rsp_info[7])); + + cp->result = DID_BUS_BUSY << 16; + add_to_done_queue(ha, sp); return; } } diff -Nru a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c --- a/drivers/scsi/qla2xxx/qla_mbx.c Sun Feb 22 12:59:47 2004 +++ b/drivers/scsi/qla2xxx/qla_mbx.c Sun Feb 22 12:59:47 2004 @@ -1421,7 +1421,7 @@ mcp->in_mb = MBX_0; mcp->buf_size = PORT_DATABASE_SIZE; mcp->flags = MBX_DMA_IN; - mcp->tov = ha->login_timeout * 2; + mcp->tov = (ha->login_timeout * 2) + (ha->login_timeout / 2); rval = qla2x00_mailbox_command(ha, mcp); if (rval == QLA_SUCCESS) { @@ -1774,8 +1774,7 @@ mcp->in_mb = MBX_0|MBX_1; mcp->buf_size = buf_size; mcp->flags = MBX_DMA_OUT|MBX_DMA_IN; - /*mcp->tov = ha->retry_count * ha->login_timeout * 2;*/ - mcp->tov = ha->login_timeout * 2; + mcp->tov = (ha->login_timeout * 2) + (ha->login_timeout / 2); rval = qla2x00_mailbox_command(ha, mcp); if (rval != QLA_SUCCESS) { @@ -1836,8 +1835,7 @@ mcp->mb[3] = area << 8 | al_pa; mcp->in_mb = MBX_7|MBX_6|MBX_2|MBX_1|MBX_0; - /*mcp->tov = ha->retry_count * ha->login_timeout * 2;*/ - mcp->tov = ha->login_timeout * 2; + mcp->tov = (ha->login_timeout * 2) + (ha->login_timeout / 2); mcp->flags = 0; rval = qla2x00_mailbox_command(ha, mcp); @@ -1909,7 +1907,7 @@ mcp->mb[2] = opt; mcp->out_mb = MBX_2|MBX_1|MBX_0; mcp->in_mb = MBX_7|MBX_6|MBX_1|MBX_0; - mcp->tov = ha->login_timeout * 2; + mcp->tov = (ha->login_timeout * 2) + (ha->login_timeout / 2); mcp->flags = 0; rval = qla2x00_mailbox_command(ha, mcp); @@ -2412,7 +2410,7 @@ mcp->in_mb = MBX_1|MBX_0; mcp->buf_size = FCAL_MAP_SIZE; mcp->flags = MBX_DMA_IN; - mcp->tov = ha->login_timeout * 2; + mcp->tov = (ha->login_timeout * 2) + (ha->login_timeout / 2); rval = qla2x00_mailbox_command(ha, mcp); if (rval == QLA_SUCCESS) { diff -Nru a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c --- a/drivers/scsi/scsi.c Sun Feb 22 12:59:47 2004 +++ b/drivers/scsi/scsi.c Sun Feb 22 12:59:47 2004 @@ -784,7 +784,7 @@ */ memset(cmd->sense_buffer, 0, sizeof(cmd->sense_buffer)); - return scsi_dispatch_cmd(cmd); + return scsi_queue_insert(cmd, SCSI_MLQUEUE_EH_RETRY); } /* diff -Nru a/drivers/scsi/scsi.h b/drivers/scsi/scsi.h --- a/drivers/scsi/scsi.h Sun Feb 22 12:59:47 2004 +++ b/drivers/scsi/scsi.h Sun Feb 22 12:59:47 2004 @@ -34,51 +34,11 @@ #define FALSE 0 #endif -#define MAX_SCSI_DEVICE_CODE 14 -extern const char *const scsi_device_types[MAX_SCSI_DEVICE_CODE]; - #ifdef DEBUG #define SCSI_TIMEOUT (5*HZ) #else #define SCSI_TIMEOUT (2*HZ) #endif - -/* - * Use these to separate status msg and our bytes - * - * These are set by: - * - * status byte = set from target device - * msg_byte = return status from host adapter itself. - * host_byte = set by low-level driver to indicate status. - * driver_byte = set by mid-level. - */ -#define status_byte(result) (((result) >> 1) & 0x1f) -#define msg_byte(result) (((result) >> 8) & 0xff) -#define host_byte(result) (((result) >> 16) & 0xff) -#define driver_byte(result) (((result) >> 24) & 0xff) -#define suggestion(result) (driver_byte(result) & SUGGEST_MASK) - -#define sense_class(sense) (((sense) >> 4) & 0x7) -#define sense_error(sense) ((sense) & 0xf) -#define sense_valid(sense) ((sense) & 0x80); - - -#define IDENTIFY_BASE 0x80 -#define IDENTIFY(can_disconnect, lun) (IDENTIFY_BASE |\ - ((can_disconnect) ? 0x40 : 0) |\ - ((lun) & 0x07)) - -/* - * SCSI command sets - */ - -#define SCSI_UNKNOWN 0 -#define SCSI_1 1 -#define SCSI_1_CCS 2 -#define SCSI_2 3 -#define SCSI_3 4 - struct Scsi_Host; struct scsi_cmnd; diff -Nru a/drivers/scsi/st.c b/drivers/scsi/st.c --- a/drivers/scsi/st.c Sun Feb 22 12:59:47 2004 +++ b/drivers/scsi/st.c Sun Feb 22 12:59:47 2004 @@ -17,7 +17,7 @@ Last modified: 18-JAN-1998 Richard Gooch Devfs support */ -static char *verstr = "20040122"; +static char *verstr = "20040213"; #include @@ -77,6 +77,8 @@ static int st_dev_max; static int st_nr_dev; +static struct class_simple *st_sysfs_class; + MODULE_AUTHOR("Kai Makisara"); MODULE_DESCRIPTION("SCSI Tape Driver"); MODULE_LICENSE("GPL"); @@ -183,7 +185,7 @@ static void do_create_driverfs_files(void); static void do_remove_driverfs_files(void); - +static void do_create_class_files(Scsi_Tape *, int, int); static struct scsi_driver st_template = { .owner = THIS_MODULE, @@ -3902,20 +3904,8 @@ } STm->cdevs[j] = cdev; - error = sysfs_create_link(&STm->cdevs[j]->kobj, &SDp->sdev_gendev.kobj, - "device"); - if (error) { - printk(KERN_ERR - "st%d: Can't create sysfs link from SCSI device.\n", - dev_num); - } } - } - error = sysfs_create_link(&SDp->sdev_gendev.kobj, &tpnt->modes[0].cdevs[0]->kobj, - "tape"); - if (error) { - printk(KERN_ERR "st%d: Can't create sysfs link from SCSI device.\n", - dev_num); + do_create_class_files(tpnt, dev_num, mode); } for (mode = 0; mode < ST_NBR_MODES; ++mode) { @@ -3941,11 +3931,14 @@ out_free_tape: for (mode=0; mode < ST_NBR_MODES; mode++) { STm = &(tpnt->modes[mode]); + sysfs_remove_link(&tpnt->device->sdev_gendev.kobj, + "tape"); for (j=0; j < 2; j++) { if (STm->cdevs[j]) { if (cdev == STm->cdevs[j]) cdev = NULL; - sysfs_remove_link(&STm->cdevs[j]->kobj, "device"); + class_simple_device_remove(MKDEV(SCSI_TAPE_MAJOR, + TAPE_MINOR(i, mode, j))); cdev_del(STm->cdevs[j]); } } @@ -3981,13 +3974,14 @@ st_nr_dev--; write_unlock(&st_dev_arr_lock); devfs_unregister_tape(tpnt->disk->number); - sysfs_remove_link(&SDp->sdev_gendev.kobj, "tape"); + sysfs_remove_link(&tpnt->device->sdev_gendev.kobj, + "tape"); for (mode = 0; mode < ST_NBR_MODES; ++mode) { devfs_remove("%s/mt%s", SDp->devfs_name, st_formats[mode]); devfs_remove("%s/mt%sn", SDp->devfs_name, st_formats[mode]); for (j=0; j < 2; j++) { - sysfs_remove_link(&tpnt->modes[mode].cdevs[j]->kobj, - "device"); + class_simple_device_remove(MKDEV(SCSI_TAPE_MAJOR, + TAPE_MINOR(i, mode, j))); cdev_del(tpnt->modes[mode].cdevs[j]); tpnt->modes[mode].cdevs[j] = NULL; } @@ -4052,13 +4046,23 @@ "st: Version %s, fixed bufsize %d, s/g segs %d\n", verstr, st_fixed_buffer_size, st_max_sg_segs); + st_sysfs_class = class_simple_create(THIS_MODULE, "scsi_tape"); + if (IS_ERR(st_sysfs_class)) { + st_sysfs_class = NULL; + printk(KERN_ERR "Unable create sysfs class for SCSI tapes\n"); + return 1; + } + if (!register_chrdev_region(MKDEV(SCSI_TAPE_MAJOR, 0), ST_MAX_TAPE_ENTRIES, "st")) { if (scsi_register_driver(&st_template.gendrv) == 0) { do_create_driverfs_files(); return 0; } + if (st_sysfs_class) + class_simple_destroy(st_sysfs_class); unregister_chrdev_region(MKDEV(SCSI_TAPE_MAJOR, 0), + ST_MAX_TAPE_ENTRIES); } @@ -4068,6 +4072,9 @@ static void __exit exit_st(void) { + if (st_sysfs_class) + class_simple_destroy(st_sysfs_class); + st_sysfs_class = NULL; do_remove_driverfs_files(); scsi_unregister_driver(&st_template.gendrv); unregister_chrdev_region(MKDEV(SCSI_TAPE_MAJOR, 0), @@ -4080,7 +4087,7 @@ module_exit(exit_st); -/* The sysfs interface. Read-only at the moment */ +/* The sysfs driver interface. Read-only at the moment */ static ssize_t st_try_direct_io_show(struct device_driver *ddp, char *buf) { return snprintf(buf, PAGE_SIZE, "%d\n", try_direct_io); @@ -4123,6 +4130,99 @@ driver_remove_file(driverfs, &driver_attr_max_sg_segs); driver_remove_file(driverfs, &driver_attr_fixed_buffer_size); driver_remove_file(driverfs, &driver_attr_try_direct_io); +} + + +/* The sysfs simple class interface */ +static ssize_t st_defined_show(struct class_device *class_dev, char *buf) +{ + ST_mode *STm = (ST_mode *)class_get_devdata(class_dev); + ssize_t l = 0; + + l = snprintf(buf, PAGE_SIZE, "%d\n", STm->defined); + return l; +} + +CLASS_DEVICE_ATTR(defined, S_IRUGO, st_defined_show, NULL); + +static ssize_t st_defblk_show(struct class_device *class_dev, char *buf) +{ + ST_mode *STm = (ST_mode *)class_get_devdata(class_dev); + ssize_t l = 0; + + l = snprintf(buf, PAGE_SIZE, "%d\n", STm->default_blksize); + return l; +} + +CLASS_DEVICE_ATTR(default_blksize, S_IRUGO, st_defblk_show, NULL); + +static ssize_t st_defdensity_show(struct class_device *class_dev, char *buf) +{ + ST_mode *STm = (ST_mode *)class_get_devdata(class_dev); + ssize_t l = 0; + char *fmt; + + fmt = STm->default_density >= 0 ? "0x%02x\n" : "%d\n"; + l = snprintf(buf, PAGE_SIZE, fmt, STm->default_density); + return l; +} + +CLASS_DEVICE_ATTR(default_density, S_IRUGO, st_defdensity_show, NULL); + +static ssize_t st_defcompression_show(struct class_device *class_dev, char *buf) +{ + ST_mode *STm = (ST_mode *)class_get_devdata(class_dev); + ssize_t l = 0; + + l = snprintf(buf, PAGE_SIZE, "%d\n", STm->default_compression - 1); + return l; +} + +CLASS_DEVICE_ATTR(default_compression, S_IRUGO, st_defcompression_show, NULL); + +static void do_create_class_files(Scsi_Tape *STp, int dev_num, int mode) +{ + int rew, error; + struct class_device *st_class_member; + + if (!st_sysfs_class) + return; + + for (rew=0; rew < 2; rew++) { + st_class_member = + class_simple_device_add(st_sysfs_class, + MKDEV(SCSI_TAPE_MAJOR, + TAPE_MINOR(dev_num, mode, rew)), + &STp->device->sdev_gendev, "%s", + STp->modes[mode].cdevs[rew]->kobj.name); + if (!st_class_member) { + printk(KERN_WARNING "st%d: class_simple_device_add failed\n", + dev_num); + goto out; + } + class_set_devdata(st_class_member, &STp->modes[mode]); + + class_device_create_file(st_class_member, + &class_device_attr_defined); + class_device_create_file(st_class_member, + &class_device_attr_default_blksize); + class_device_create_file(st_class_member, + &class_device_attr_default_density); + class_device_create_file(st_class_member, + &class_device_attr_default_compression); + if (mode == 0 && rew == 0) { + error = sysfs_create_link(&STp->device->sdev_gendev.kobj, + &st_class_member->kobj, + "tape"); + if (error) { + printk(KERN_ERR + "st%d: Can't create sysfs link from SCSI device.\n", + dev_num); + } + } + } + out: + return; } diff -Nru a/drivers/scsi/sun3x_esp.c b/drivers/scsi/sun3x_esp.c --- a/drivers/scsi/sun3x_esp.c Sun Feb 22 12:59:47 2004 +++ b/drivers/scsi/sun3x_esp.c Sun Feb 22 12:59:47 2004 @@ -46,12 +46,6 @@ static void dma_mmu_release_scsi_sgl (struct NCR_ESP *esp, Scsi_Cmnd *sp); static void dma_advance_sg (Scsi_Cmnd *sp); -static volatile unsigned char cmd_buffer[16]; - /* This is where all commands are put - * before they are trasfered to the ESP chip - * via PIO. - */ - /* Detecting ESP chips on the machine. This is the simple and easy * version. */ @@ -101,14 +95,8 @@ esp->eregs = (struct ESP_regs *)(SUN3X_ESP_BASE); esp->dregs = (void *)SUN3X_ESP_DMA; -#if 0 - esp->esp_command = (volatile unsigned char *)cmd_buffer; - esp->esp_command_dvma = dvma_map((unsigned long)cmd_buffer, - sizeof (cmd_buffer)); -#else esp->esp_command = (volatile unsigned char *)dvma_malloc(DVMA_PAGE_SIZE); esp->esp_command_dvma = dvma_vtob((unsigned long)esp->esp_command); -#endif esp->irq = 2; if (request_irq(esp->irq, esp_intr, SA_INTERRUPT, @@ -373,29 +361,6 @@ { sp->SCp.ptr = (char *)((unsigned long)sp->SCp.buffer->dvma_address); } - - -static int esp_slave_alloc(Scsi_Device *SDptr) -{ - struct esp_device *esp_dev = - kmalloc(sizeof(struct esp_device), GFP_ATOMIC); - - if (!esp_dev) - return -ENOMEM; - memset(esp_dev, 0, sizeof(struct esp_device)); - SDptr->hostdata = esp_dev; - return 0; -} - -static void esp_slave_destroy(Scsi_Device *SDptr) -{ - struct NCR_ESP *esp = (struct NCR_ESP *) SDptr->host->hostdata; - - esp->targets_present &= ~(1 << SDptr->id); - kfree(SDptr->hostdata); - SDptr->hostdata = NULL; -} - static int sun3x_esp_release(struct Scsi_Host *instance) { diff -Nru a/drivers/scsi/tmscsim.c b/drivers/scsi/tmscsim.c --- a/drivers/scsi/tmscsim.c Sun Feb 22 12:59:47 2004 +++ b/drivers/scsi/tmscsim.c Sun Feb 22 12:59:47 2004 @@ -518,7 +518,6 @@ } -#ifndef CONFIG_SCSI_DC390T_NOGENSUPP int __initdata tmscsim_def[] = {7, 0 /* 10MHz */, PARITY_CHK_ | SEND_START_ | EN_DISCONNECT_ | SYNC_NEGO_ | TAG_QUEUEING_, @@ -546,7 +545,6 @@ if (tmscsim[4] > 5) tmscsim[4] = 4; if (tmscsim[5] > 180) tmscsim[5] = 180; } -#endif /* Override defaults on cmdline: * tmscsim: AdaptID, MaxSpeed (Index), DevMode (Bitmapped), AdaptMode (Bitmapped) @@ -2105,10 +2103,6 @@ if (dc390_CheckEEpromCheckSum (PDEV, index)) { -#ifdef CONFIG_SCSI_DC390T_NOGENSUPP - printk (KERN_ERR "DC390_init: No EEPROM found!\n"); - return( -1 ); -#else int speed; dc390_adapname = "AM53C974"; printk (KERN_INFO "DC390_init: No EEPROM found! Trying default settings ...\n"); @@ -2120,7 +2114,6 @@ " DevMode=0x%02x, AdaptMode=0x%02x, TaggedCmnds=%i (%i), DelayReset=%is\n", tmscsim[0], tmscsim[1], speed/10, speed%10, (UCHAR)tmscsim[2], (UCHAR)tmscsim[3], tmscsim[4], 2 << (tmscsim[4]), tmscsim[5]); -#endif } else { diff -Nru a/include/scsi/scsi.h b/include/scsi/scsi.h --- a/include/scsi/scsi.h Sun Feb 22 12:59:47 2004 +++ b/include/scsi/scsi.h Sun Feb 22 12:59:47 2004 @@ -12,13 +12,20 @@ /* - * SCSI command lengths + * SCSI command lengths */ extern const unsigned char scsi_command_size[8]; #define COMMAND_SIZE(opcode) scsi_command_size[((opcode) >> 5) & 7] /* + * SCSI device types + */ + +#define MAX_SCSI_DEVICE_CODE 14 +extern const char *const scsi_device_types[MAX_SCSI_DEVICE_CODE]; + +/* * SCSI opcodes */ @@ -310,6 +317,42 @@ #define SCSI_MLQUEUE_HOST_BUSY 0x1055 #define SCSI_MLQUEUE_DEVICE_BUSY 0x1056 #define SCSI_MLQUEUE_EH_RETRY 0x1057 + +/* + * Use these to separate status msg and our bytes + * + * These are set by: + * + * status byte = set from target device + * msg_byte = return status from host adapter itself. + * host_byte = set by low-level driver to indicate status. + * driver_byte = set by mid-level. + */ +#define status_byte(result) (((result) >> 1) & 0x1f) +#define msg_byte(result) (((result) >> 8) & 0xff) +#define host_byte(result) (((result) >> 16) & 0xff) +#define driver_byte(result) (((result) >> 24) & 0xff) +#define suggestion(result) (driver_byte(result) & SUGGEST_MASK) + +#define sense_class(sense) (((sense) >> 4) & 0x7) +#define sense_error(sense) ((sense) & 0xf) +#define sense_valid(sense) ((sense) & 0x80); + + +#define IDENTIFY_BASE 0x80 +#define IDENTIFY(can_disconnect, lun) (IDENTIFY_BASE |\ + ((can_disconnect) ? 0x40 : 0) |\ + ((lun) & 0x07)) + +/* + * SCSI command sets + */ + +#define SCSI_UNKNOWN 0 +#define SCSI_1 1 +#define SCSI_1_CCS 2 +#define SCSI_2 3 +#define SCSI_3 4 /*