reverted: --- b/drivers/message/fusion/mptbase.c 2004-09-26 11:11:46 -07:00 +++ a/drivers/message/fusion/mptbase.c 2004-09-26 11:11:46 -07:00 @@ -437,7 +437,7 @@ /* Put Request back on FreeQ! */ spin_lock_irqsave(&ioc->FreeQlock, flags); + Q_ADD_TAIL(&ioc->FreeQ, &mf->u.frame.linkage, MPT_FRAME_HDR); - list_add_tail(&mf->u.frame.linkage.list, &ioc->FreeQ); #ifdef MFCNT ioc->mfcnt--; #endif @@ -533,7 +533,7 @@ del_timer(&pCfg->timer); spin_lock_irqsave(&ioc->FreeQlock, flags); + Q_DEL_ITEM(&pCfg->linkage); - list_del(&pCfg->linkage); spin_unlock_irqrestore(&ioc->FreeQlock, flags); /* @@ -819,12 +819,11 @@ return NULL; spin_lock_irqsave(&ioc->FreeQlock, flags); + if (! Q_IS_EMPTY(&ioc->FreeQ)) { - if (!list_empty(&ioc->FreeQ)) { int req_offset; + mf = ioc->FreeQ.head; + Q_DEL_ITEM(&mf->u.frame.linkage); - mf = list_entry(ioc->FreeQ.next, MPT_FRAME_HDR, - u.frame.linkage.list); - list_del(&mf->u.frame.linkage.list); mf->u.frame.hwhdr.msgctxu.fld.cb_idx = handle; /* byte */ req_offset = (u8 *)mf - (u8 *)ioc->req_frames; /* u16! */ @@ -920,7 +919,7 @@ /* Put Request back on FreeQ! */ spin_lock_irqsave(&ioc->FreeQlock, flags); + Q_ADD_TAIL(&ioc->FreeQ, &mf->u.frame.linkage, MPT_FRAME_HDR); - list_add_tail(&mf->u.frame.linkage.list, &ioc->FreeQ); #ifdef MFCNT ioc->mfcnt--; #endif @@ -1199,7 +1198,7 @@ /* Initialize the running configQ head. */ + Q_INIT(&ioc->configQ, Q_ITEM); - INIT_LIST_HEAD(&ioc->configQ); /* Find lookup slot. */ INIT_LIST_HEAD(&ioc->list); @@ -3593,14 +3592,14 @@ /* Initialize the free chain Q. */ + Q_INIT(&ioc->FreeChainQ, MPT_FRAME_HDR); - INIT_LIST_HEAD(&ioc->FreeChainQ); /* Post the chain buffers to the FreeChainQ. */ mem = (u8 *)ioc->ChainBuffer; for (i=0; i < num_chain; i++) { mf = (MPT_FRAME_HDR *) mem; + Q_ADD_TAIL(&ioc->FreeChainQ.head, &mf->u.frame.linkage, MPT_FRAME_HDR); - list_add_tail(&mf->u.frame.linkage.list, &ioc->FreeChainQ); mem += ioc->req_sz; } @@ -3610,13 +3609,12 @@ mem = (u8 *) ioc->req_frames; spin_lock_irqsave(&ioc->FreeQlock, flags); + Q_INIT(&ioc->FreeQ, MPT_FRAME_HDR); - INIT_LIST_HEAD(&ioc->FreeQ); for (i = 0; i < ioc->req_depth; i++) { mf = (MPT_FRAME_HDR *) mem; /* Queue REQUESTs *internally*! */ + Q_ADD_TAIL(&ioc->FreeQ.head, &mf->u.frame.linkage, MPT_FRAME_HDR); - list_add_tail(&mf->u.frame.linkage.list, &ioc->FreeQ); - mem += ioc->req_sz; } spin_unlock_irqrestore(&ioc->FreeQlock, flags); @@ -4905,7 +4903,7 @@ /* Add to end of Q, set timer and then issue this command */ spin_lock_irqsave(&ioc->FreeQlock, flags); + Q_ADD_TAIL(&ioc->configQ.head, &pCfg->linkage, Q_ITEM); - list_add_tail(&pCfg->linkage, &ioc->configQ); spin_unlock_irqrestore(&ioc->FreeQlock, flags); add_timer(&pCfg->timer); @@ -5016,7 +5014,7 @@ /* Add to end of Q, set timer and then issue this command */ spin_lock_irqsave(&ioc->FreeQlock, flags); + Q_ADD_TAIL(&ioc->configQ.head, &pCfg->linkage, Q_ITEM); - list_add_tail(&pCfg->linkage, &ioc->configQ); spin_unlock_irqrestore(&ioc->FreeQlock, flags); add_timer(&pCfg->timer); @@ -5083,8 +5081,13 @@ * the FIFO's are primed. */ spin_lock_irqsave(&ioc->FreeQlock, flags); + if (! Q_IS_EMPTY(&ioc->configQ)){ + pCfg = (CONFIGPARMS *)ioc->configQ.head; + do { + del_timer(&pCfg->timer); + pCfg = (CONFIGPARMS *) (pCfg->linkage.forw); + } while (pCfg != (CONFIGPARMS *)&ioc->configQ); + } - list_for_each_entry(pCfg, &ioc->configQ, linkage) - del_timer(&pCfg->timer); spin_unlock_irqrestore(&ioc->FreeQlock, flags); } else { @@ -5094,12 +5097,19 @@ * Flush the Q, and wake up all suspended threads. */ spin_lock_irqsave(&ioc->FreeQlock, flags); + if (! Q_IS_EMPTY(&ioc->configQ)){ + pCfg = (CONFIGPARMS *)ioc->configQ.head; + do { + pNext = (CONFIGPARMS *) pCfg->linkage.forw; + + Q_DEL_ITEM(&pCfg->linkage); + + pCfg->status = MPT_CONFIG_ERROR; + pCfg->wait_done = 1; + wake_up(&mpt_waitq); - list_for_each_entry_safe(pCfg, pNext, &ioc->configQ, linkage) { - list_del(&pCfg->linkage); + pCfg = pNext; + } while (pCfg != (CONFIGPARMS *)&ioc->configQ); - pCfg->status = MPT_CONFIG_ERROR; - pCfg->wait_done = 1; - wake_up(&mpt_waitq); } spin_unlock_irqrestore(&ioc->FreeQlock, flags); } reverted: --- b/drivers/message/fusion/mptbase.h 2004-09-26 11:11:45 -07:00 +++ a/drivers/message/fusion/mptbase.h 2004-09-26 11:11:45 -07:00 @@ -226,7 +226,8 @@ typedef union _MPT_FRAME_TRACKER { struct { + struct _MPT_FRAME_HDR *forw; + struct _MPT_FRAME_HDR *back; - struct list_head list; u32 arg1; u32 pad; void *argp1; @@ -289,6 +290,15 @@ #define MPT_REQ_MSGFLAGS_DROPME 0x80 +/* Used for tracking the free request frames + * and free reply frames. + */ +typedef struct _MPT_Q_TRACKER { + MPT_FRAME_HDR *head; + MPT_FRAME_HDR *tail; +} MPT_Q_TRACKER; + + typedef struct _MPT_SGL_HDR { SGESimple32_t sge[1]; } MPT_SGL_HDR; @@ -298,6 +308,16 @@ } MPT_SGL64_HDR; +typedef struct _Q_ITEM { + struct _Q_ITEM *forw; + struct _Q_ITEM *back; +} Q_ITEM; + +typedef struct _Q_TRACKER { + struct _Q_ITEM *head; + struct _Q_ITEM *tail; +} Q_TRACKER; + /* * Chip-specific stuff... FC929 delineates break between * FC and Parallel SCSI parts. Do NOT re-order. @@ -381,6 +401,8 @@ * (used to be FCSCSI_TARGET) */ typedef struct _VirtDevice { + struct _VirtDevice *forw; + struct _VirtDevice *back; struct scsi_device *device; rwlock_t VdevLock; int ref_cnt; @@ -404,6 +426,9 @@ struct timer_list stall_timer; struct timer_list retry_timer; struct timer_list gone_timer; + ScsiCmndTracker WaitQ; + ScsiCmndTracker SentQ; + ScsiCmndTracker DoneQ; u32 num_luns; u32 luns[8]; /* Max LUNs is 256 */ u8 pad[4]; @@ -550,6 +575,8 @@ */ typedef struct _MPT_ADAPTER { + struct _MPT_ADAPTER *forw; + struct _MPT_ADAPTER *back; int id; /* Unique adapter id N {0,1,2,...} */ int pci_irq; /* This irq */ char name[MPT_NAME_LENGTH]; /* "iocN" */ @@ -580,7 +607,7 @@ int *ChainToChain; u8 *ChainBuffer; dma_addr_t ChainBufferDMA; + MPT_Q_TRACKER FreeChainQ; - struct list_head FreeChainQ; spinlock_t FreeChainQlock; CHIP_TYPE chip_type; /* We (host driver) get to manage our own RequestQueue! */ @@ -590,7 +617,7 @@ int req_depth; /* Number of request frames */ int req_sz; /* Request frame size (bytes) */ spinlock_t FreeQlock; + MPT_Q_TRACKER FreeQ; - struct list_head FreeQ; /* Pool of SCSI sense buffers for commands coming from * the SCSI mid-layer. We have one 256 byte sense buffer * for each REQ entry. @@ -621,7 +648,7 @@ struct _mpt_ioctl_events *events; /* pointer to event log */ u8 *cached_fw; /* Pointer to FW */ dma_addr_t cached_fw_dma; + Q_TRACKER configQ; /* linked list of config. requests */ - struct list_head configQ; /* linked list of config. requests */ int hs_reply_idx; #ifndef MFCNT u32 pad0; @@ -875,6 +902,34 @@ #define MPT_INDEX_2_RFPTR(ioc,idx) \ (MPT_FRAME_HDR*)( (u8*)(ioc)->reply_frames + (ioc)->req_sz * (idx) ) +#define Q_INIT(q,type) (q)->head = (q)->tail = (type*)(q) +#define Q_IS_EMPTY(q) ((Q_ITEM*)(q)->head == (Q_ITEM*)(q)) + +#define Q_ADD_TAIL(qt,i,type) { \ + Q_TRACKER *_qt = (Q_TRACKER*)(qt); \ + Q_ITEM *oldTail = _qt->tail; \ + (i)->forw = (type*)_qt; \ + (i)->back = (type*)oldTail; \ + oldTail->forw = (Q_ITEM*)(i); \ + _qt->tail = (Q_ITEM*)(i); \ +} + +#define Q_ADD_HEAD(qt,i,type) { \ + Q_TRACKER *_qt = (Q_TRACKER*)(qt); \ + Q_ITEM *oldHead = _qt->head; \ + (i)->forw = (type*)oldHead; \ + (i)->back = (type*)_qt; \ + oldHead->back = (Q_ITEM*)(i); \ + _qt->head = (Q_ITEM*)(i); \ +} + +#define Q_DEL_ITEM(i) { \ + Q_ITEM *_forw = (Q_ITEM*)(i)->forw; \ + Q_ITEM *_back = (Q_ITEM*)(i)->back; \ + _back->forw = _forw; \ + _forw->back = _back; \ +} + #define SWAB4(value) \ (u32)( (((value) & 0x000000ff) << 24) \ | (((value) & 0x0000ff00) << 8) \ @@ -962,6 +1017,8 @@ /* Pool of memory for holding SCpnts before doing * OS callbacks. freeQ is the free pool. */ + MPT_Q_TRACKER taskQ; /* TM request Q */ + int taskQcnt; u8 tmPending; u8 resetPending; u8 is_spi; /* Parallel SCSI i/f */ @@ -1012,7 +1069,7 @@ * Generic structure passed to the base mpt_config function. */ typedef struct _x_config_parms { + Q_ITEM linkage; /* linked list */ - struct list_head linkage; /* linked list */ struct timer_list timer; /* timer function for this request */ ConfigPageHeader_t *hdr; dma_addr_t physAddr; reverted: --- b/drivers/message/fusion/mptscsih.c 2004-09-26 11:11:47 -07:00 +++ a/drivers/message/fusion/mptscsih.c 2004-09-26 11:11:47 -07:00 @@ -340,18 +340,19 @@ dsgprintk((MYIOC_s_INFO_FMT "getFreeChainBuffer called\n", ioc->name)); spin_lock_irqsave(&ioc->FreeQlock, flags); + if (!Q_IS_EMPTY(&ioc->FreeChainQ)) { + - if (!list_empty(&ioc->FreeChainQ)) { int offset; + chainBuf = ioc->FreeChainQ.head; + Q_DEL_ITEM(&chainBuf->u.frame.linkage); - chainBuf = list_entry(ioc->FreeChainQ.next, MPT_FRAME_HDR, - u.frame.linkage.list); - list_del(&chainBuf->u.frame.linkage.list); offset = (u8 *)chainBuf - (u8 *)ioc->ChainBuffer; chain_idx = offset / ioc->req_sz; rc = SUCCESS; dsgprintk((MYIOC_s_INFO_FMT "getFreeChainBuffer (index %d), got buf=%p\n", ioc->name, *retIndex, chainBuf)); + } + else { - } else { rc = FAILED; chain_idx = MPT_HOST_NO_CHAIN; dfailprintk((MYIOC_s_ERR_FMT "getFreeChainBuffer failed\n", @@ -359,7 +360,9 @@ } spin_unlock_irqrestore(&ioc->FreeQlock, flags); + *retIndex = chain_idx; + return rc; } /* mptscsih_getFreeChainBuffer() */ @@ -1215,6 +1218,12 @@ dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p, sz=%d\n", ioc->name, hd->ScsiLookup, sz)); + /* Initialize this Scsi_Host + * internal task Q. + */ + Q_INIT(&hd->taskQ, MPT_FRAME_HDR); + hd->taskQcnt = 0; + /* Allocate memory for the device structures. * A non-Null pointer at an offset * indicates a device exists. @@ -2093,9 +2102,9 @@ chain = (MPT_FRAME_HDR *) (ioc->ChainBuffer + (chain_idx * ioc->req_sz)); - spin_lock_irqsave(&ioc->FreeQlock, flags); + Q_ADD_TAIL(&ioc->FreeChainQ.head, + &chain->u.frame.linkage, MPT_FRAME_HDR); - list_add_tail(&chain->u.frame.linkage.list, &ioc->FreeChainQ); spin_unlock_irqrestore(&ioc->FreeQlock, flags); dmfprintk((MYIOC_s_INFO_FMT "FreeChainBuffers (index %d)\n", @@ -2655,6 +2664,8 @@ if (hd->tmPtr) { del_timer(&hd->TMtimer); } + dtmprintk((MYIOC_s_WARN_FMT "taskQcnt (%d)\n", + ioc->name, hd->taskQcnt)); } else { dtmprintk((MYIOC_s_WARN_FMT "TaskMgmt Complete: NULL Scsi Host Ptr\n", ioc->name)); @@ -2788,6 +2799,9 @@ } else { memset(vdev, 0, sizeof(VirtDevice)); rwlock_init(&vdev->VdevLock); + Q_INIT(&vdev->WaitQ, void); + Q_INIT(&vdev->SentQ, void); + Q_INIT(&vdev->DoneQ, void); vdev->tflags = MPT_TARGET_FLAGS_Q_YES; vdev->ioc_id = hd->ioc->id; vdev->target_id = device->id; diff -u b/drivers/scsi/3w-xxxx.c b/drivers/scsi/3w-xxxx.c --- b/drivers/scsi/3w-xxxx.c 2004-09-26 11:11:46 -07:00 +++ b/drivers/scsi/3w-xxxx.c 2004-09-26 11:13:18 -07:00 @@ -207,7 +207,7 @@ #include "3w-xxxx.h" /* Globals */ -#define TW_DRIVER_VERSION "1.26.02.000" +static const char *tw_driver_version="1.26.02.000"; static TW_Device_Extension *tw_device_extension_list[TW_MAX_SLOT]; static int tw_device_extension_count = 0; static int twe_major = -1; @@ -216,7 +216,6 @@ MODULE_AUTHOR("AMCC"); MODULE_DESCRIPTION("3ware Storage Controller Linux Driver"); MODULE_LICENSE("GPL"); -MODULE_VERSION(TW_DRIVER_VERSION); /* Function prototypes */ static int tw_reset_device_extension(TW_Device_Extension *tw_dev, int ioctl_reset); @@ -224,7 +223,7 @@ /* Functions */ /* This function will check the status register for unexpected bits */ -static int tw_check_bits(u32 status_reg_value) +int tw_check_bits(u32 status_reg_value) { if ((status_reg_value & TW_STATUS_EXPECTED_BITS) != TW_STATUS_EXPECTED_BITS) { dprintk(KERN_WARNING "3w-xxxx: tw_check_bits(): No expected bits (0x%x).\n", status_reg_value); @@ -493,7 +492,7 @@ "Max sector count: %4d\n" "SCSI Host Resets: %4d\n" "AEN's: %4d\n", - TW_DRIVER_VERSION, + tw_driver_version, tw_dev->posted_request_count, tw_dev->max_posted_request_count, tw_dev->pending_request_count, @@ -885,7 +884,7 @@ /* This function handles ioctl for the character device */ static int tw_chrdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { - int request_id; + int error, request_id; dma_addr_t dma_handle; unsigned short tw_aen_code; unsigned long flags; @@ -906,7 +905,8 @@ return -EINTR; /* First copy down the buffer length */ - if (copy_from_user(&data_buffer_length, argp, sizeof(unsigned int))) + error = copy_from_user(&data_buffer_length, argp, sizeof(unsigned int)); + if (error) goto out; /* Check size */ @@ -919,7 +919,7 @@ data_buffer_length_adjusted = (data_buffer_length + 511) & ~511; /* Now allocate ioctl buf memory */ - cpu_addr = dma_alloc_coherent(&tw_dev->tw_pci_dev->dev, data_buffer_length_adjusted+sizeof(TW_New_Ioctl) - 1, &dma_handle, GFP_KERNEL); + cpu_addr = pci_alloc_consistent(tw_dev->tw_pci_dev, data_buffer_length_adjusted+sizeof(TW_New_Ioctl) - 1, &dma_handle); if (cpu_addr == NULL) { retval = -ENOMEM; goto out; @@ -928,7 +928,8 @@ tw_ioctl = (TW_New_Ioctl *)cpu_addr; /* Now copy down the entire ioctl */ - if (copy_from_user(tw_ioctl, argp, data_buffer_length + sizeof(TW_New_Ioctl) - 1)) + error = copy_from_user(tw_ioctl, argp, data_buffer_length + sizeof(TW_New_Ioctl) - 1); + if (error) goto out2; passthru = (TW_Passthru *)&tw_ioctl->firmware_command; @@ -1041,12 +1042,12 @@ } /* Now copy the response to userspace */ - if (copy_to_user(argp, tw_ioctl, sizeof(TW_New_Ioctl) + data_buffer_length - 1)) - goto out2; - retval = 0; + error = copy_to_user(argp, tw_ioctl, sizeof(TW_New_Ioctl) + data_buffer_length - 1); + if (error == 0) + retval = 0; out2: /* Now free ioctl buf memory */ - dma_free_coherent(&tw_dev->tw_pci_dev->dev, data_buffer_length_adjusted+sizeof(TW_New_Ioctl) - 1, cpu_addr, dma_handle); + pci_free_consistent(tw_dev->tw_pci_dev, data_buffer_length_adjusted+sizeof(TW_New_Ioctl) - 1, cpu_addr, dma_handle); out: up(&tw_dev->ioctl_sem); return retval; @@ -1543,7 +1544,7 @@ request_buffer[4] = 31; /* Additional length */ memcpy(&request_buffer[8], "3ware ", 8); /* Vendor ID */ sprintf(&request_buffer[16], "Logical Disk %-2d ", tw_dev->srb[request_id]->device->id); - memcpy(&request_buffer[32], TW_DRIVER_VERSION, 3); + memcpy(&request_buffer[32], tw_driver_version, 3); param = (TW_Param *)tw_dev->alignment_virtual_address[request_id]; if (param == NULL) { @@ -2483,7 +2484,7 @@ /* This function is called on driver initialization */ static int __init tw_init(void) { - printk(KERN_WARNING "3ware Storage Controller device driver for Linux v%s.\n", TW_DRIVER_VERSION); + printk(KERN_WARNING "3ware Storage Controller device driver for Linux v%s.\n", tw_driver_version); return pci_module_init(&tw_driver); } /* End tw_init() */ diff -u b/drivers/scsi/BusLogic.c b/drivers/scsi/BusLogic.c --- b/drivers/scsi/BusLogic.c 2004-09-26 11:11:46 -07:00 +++ b/drivers/scsi/BusLogic.c 2004-09-26 11:13:18 -07:00 @@ -2344,8 +2344,6 @@ Remove Host Adapter from the list of registered BusLogic Host Adapters. */ list_del(&HostAdapter->host_list); - - scsi_host_put(Host); return 0; } @@ -2621,7 +2619,7 @@ /* Acquire exclusive access to Host Adapter. */ - spin_lock_irqsave(HostAdapter->SCSI_Host->host_lock, ProcessorFlags); + BusLogic_AcquireHostAdapterLockIH(HostAdapter, &ProcessorFlags); /* Handle Interrupts appropriately for each Host Adapter type. */ @@ -2689,7 +2687,7 @@ /* Release exclusive access to Host Adapter. */ - spin_unlock_irqrestore(HostAdapter->SCSI_Host->host_lock, ProcessorFlags); + BusLogic_ReleaseHostAdapterLockIH(HostAdapter, &ProcessorFlags); return IRQ_HANDLED; } @@ -2777,9 +2775,9 @@ */ CCB = BusLogic_AllocateCCB(HostAdapter); if (CCB == NULL) { - spin_unlock_irq(HostAdapter->SCSI_Host->host_lock); + BusLogic_ReleaseHostAdapterLock(HostAdapter); BusLogic_Delay(1); - spin_lock_irq(HostAdapter->SCSI_Host->host_lock); + BusLogic_AcquireHostAdapterLock(HostAdapter); CCB = BusLogic_AllocateCCB(HostAdapter); if (CCB == NULL) { Command->result = DID_ERROR << 16; @@ -2903,10 +2901,10 @@ error as a Host Adapter Hard Reset should be initiated soon. */ if (!BusLogic_WriteOutgoingMailbox(HostAdapter, BusLogic_MailboxStartCommand, CCB)) { - spin_unlock_irq(HostAdapter->SCSI_Host->host_lock); + BusLogic_ReleaseHostAdapterLock(HostAdapter); BusLogic_Warning("Unable to write Outgoing Mailbox - " "Pausing for 1 second\n", HostAdapter); BusLogic_Delay(1); - spin_lock_irq(HostAdapter->SCSI_Host->host_lock); + BusLogic_AcquireHostAdapterLock(HostAdapter); if (!BusLogic_WriteOutgoingMailbox(HostAdapter, BusLogic_MailboxStartCommand, CCB)) { BusLogic_Warning("Still unable to write Outgoing Mailbox - " "Host Adapter Dead?\n", HostAdapter); BusLogic_DeallocateCCB(CCB); @@ -3044,9 +3042,9 @@ */ if (HardReset) { - spin_unlock_irq(HostAdapter->SCSI_Host->host_lock); + BusLogic_ReleaseHostAdapterLock(HostAdapter); BusLogic_Delay(HostAdapter->BusSettleTime); - spin_lock_irq(HostAdapter->SCSI_Host->host_lock); + BusLogic_AcquireHostAdapterLock(HostAdapter); } for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++) { diff -u b/drivers/scsi/BusLogic.h b/drivers/scsi/BusLogic.h --- b/drivers/scsi/BusLogic.h 2004-09-26 11:11:46 -07:00 +++ b/drivers/scsi/BusLogic.h 2004-09-26 11:13:18 -07:00 @@ -1169,6 +1169,46 @@ unsigned char ProductRevisionLevel[4]; /* Bytes 32-35 */ }; +/* + BusLogic_AcquireHostAdapterLock acquires exclusive access to Host Adapter. +*/ + +static inline void BusLogic_AcquireHostAdapterLock(struct BusLogic_HostAdapter *HostAdapter) +{ + spin_lock_irq(HostAdapter->SCSI_Host->host_lock); +} + +/* + BusLogic_ReleaseHostAdapterLock releases exclusive access to Host Adapter. +*/ + +static inline void BusLogic_ReleaseHostAdapterLock(struct BusLogic_HostAdapter *HostAdapter) +{ + spin_unlock_irq(HostAdapter->SCSI_Host->host_lock); +} + + +/* + BusLogic_AcquireHostAdapterLockIH acquires exclusive access to Host Adapter, + but is only called from the interrupt handler. +*/ + +static inline void BusLogic_AcquireHostAdapterLockIH(struct BusLogic_HostAdapter *HostAdapter, unsigned long *ProcessorFlags) +{ + spin_lock_irqsave(HostAdapter->SCSI_Host->host_lock, *ProcessorFlags); +} + + +/* + BusLogic_ReleaseHostAdapterLockIH releases exclusive access to Host Adapter, + but is only called from the interrupt handler. +*/ + +static inline void BusLogic_ReleaseHostAdapterLockIH(struct BusLogic_HostAdapter *HostAdapter, unsigned long *ProcessorFlags) +{ + spin_unlock_irqrestore(HostAdapter->SCSI_Host->host_lock, *ProcessorFlags); +} + /* Define functions to provide an abstraction for reading and writing the diff -u b/drivers/scsi/Kconfig b/drivers/scsi/Kconfig --- b/drivers/scsi/Kconfig 2004-09-26 11:11:46 -07:00 +++ b/drivers/scsi/Kconfig 2004-09-26 11:13:18 -07:00 @@ -313,8 +313,8 @@ module will be called aha1740. config SCSI_AACRAID - tristate "Adaptec AACRAID support" - depends on SCSI && PCI + tristate "Adaptec AACRAID support (EXPERIMENTAL)" + depends on EXPERIMENTAL && SCSI && PCI source "drivers/scsi/aic7xxx/Kconfig.aic7xxx" @@ -783,7 +783,7 @@ config SCSI_INITIO tristate "Initio 9100U(W) support" - depends on PCI && SCSI + depends on PCI && SCSI && BROKEN help This is support for the Initio 91XXU(W) SCSI host adapter. Please read the SCSI-HOWTO, available from reverted: --- b/drivers/scsi/aacraid/aachba.c 2004-09-26 11:11:46 -07:00 +++ a/drivers/scsi/aacraid/aachba.c 2004-09-26 11:11:46 -07:00 @@ -193,80 +193,6 @@ static int nondasd = -1; static int dacmode = -1; -static int commit = -1; - -/** - * aac_get_config_status - check the adapter configuration - * @common: adapter to query - * - * Query config status, and commit the configuration if needed. - */ -int aac_get_config_status(struct aac_dev *dev) -{ - int status = 0; - struct fib * fibptr; - - if (!(fibptr = fib_alloc(dev))) - return -ENOMEM; - - fib_init(fibptr); - { - struct aac_get_config_status *dinfo; - dinfo = (struct aac_get_config_status *) fib_data(fibptr); - - dinfo->command = cpu_to_le32(VM_ContainerConfig); - dinfo->type = cpu_to_le32(CT_GET_CONFIG_STATUS); - dinfo->count = cpu_to_le32(sizeof(((struct aac_get_config_status_resp *)NULL)->data)); - } - - status = fib_send(ContainerCommand, - fibptr, - sizeof (struct aac_get_config_status), - FsaNormal, - 1, 1, - NULL, NULL); - if (status < 0 ) { - printk(KERN_WARNING "aac_get_config_status: SendFIB failed.\n"); - } else { - struct aac_get_config_status_resp *reply - = (struct aac_get_config_status_resp *) fib_data(fibptr); - dprintk((KERN_WARNING - "aac_get_config_status: response=%d status=%d action=%d\n", - reply->response, reply->status, reply->data.action)); - if ((reply->response != ST_OK) - || (reply->status != CT_OK) - || (reply->data.action > CFACT_PAUSE)) { - printk(KERN_WARNING "aac_get_config_status: Will not issue the Commit Configuration\n"); - status = -EINVAL; - } - } - fib_complete(fibptr); - /* Send a CT_COMMIT_CONFIG to enable discovery of devices */ - if (status >= 0) { - if (commit == 1) { - struct aac_commit_config * dinfo; - fib_init(fibptr); - dinfo = (struct aac_commit_config *) fib_data(fibptr); - - dinfo->command = cpu_to_le32(VM_ContainerConfig); - dinfo->type = cpu_to_le32(CT_COMMIT_CONFIG); - - status = fib_send(ContainerCommand, - fibptr, - sizeof (struct aac_commit_config), - FsaNormal, - 1, 1, - NULL, NULL); - fib_complete(fibptr); - } else if (commit == 0) { - printk(KERN_WARNING - "aac_get_config_status: Foreign device configurations are being ignored\n"); - } - } - fib_free(fibptr); - return status; -} - /** * aac_get_containers - list containers * @common: adapter to probe reverted: --- b/drivers/scsi/aacraid/aacraid.h 2004-09-26 11:11:45 -07:00 +++ a/drivers/scsi/aacraid/aacraid.h 2004-09-26 11:11:45 -07:00 @@ -7,6 +7,7 @@ *----------------------------------------------------------------------------*/ #define MAXIMUM_NUM_CONTAINERS 32 +#define MAXIMUM_NUM_ADAPTERS 8 #define AAC_NUM_FIB (256 + 64) #define AAC_NUM_IO_FIB 100 @@ -56,7 +57,6 @@ #define CT_VOLUME_OF_MIRRORS 12 /* volume of mirror */ #define CT_PSEUDO_RAID 13 /* really raid4 */ #define CT_LAST_VOLUME_TYPE 14 -#define CT_OK 218 /* * Types of objects addressable in some fashion by the client. @@ -771,7 +771,7 @@ struct aac_dev { + struct aac_dev *next; - struct list_head entry; const char *name; int id; @@ -1169,52 +1169,6 @@ }; /* - * Query for Container Configuration Status - */ - -#define CT_GET_CONFIG_STATUS 147 -struct aac_get_config_status { - u32 command; /* VM_ContainerConfig */ - u32 type; /* CT_GET_CONFIG_STATUS */ - u32 parm1; - u32 parm2; - u32 parm3; - u32 parm4; - u32 parm5; - u32 count; /* sizeof(((struct aac_get_config_status_resp *)NULL)->data) */ -}; - -#define CFACT_CONTINUE 0 -#define CFACT_PAUSE 1 -#define CFACT_ABORT 2 -struct aac_get_config_status_resp { - u32 response; /* ST_OK */ - u32 dummy0; - u32 status; /* CT_OK */ - u32 parm1; - u32 parm2; - u32 parm3; - u32 parm4; - u32 parm5; - struct { - u32 action; /* CFACT_CONTINUE, CFACT_PAUSE or CFACT_ABORT */ - u16 flags; - s16 count; - } data; -}; - -/* - * Accept the configuration as-is - */ - -#define CT_COMMIT_CONFIG 152 - -struct aac_commit_config { - u32 command; /* VM_ContainerConfig */ - u32 type; /* CT_COMMIT_CONFIG */ -}; - -/* * Query for "mountable" objects, ie, objects that are typically * associated with a drive letter on the client (host) side. */ @@ -1489,7 +1443,6 @@ int fib_complete(struct fib * context); #define fib_data(fibctx) ((void *)(fibctx)->hw_fib->data) struct aac_dev *aac_init_adapter(struct aac_dev *dev); -int aac_get_config_status(struct aac_dev *dev); int aac_get_containers(struct aac_dev *dev); int aac_scsi_cmd(struct scsi_cmnd *cmd); int aac_dev_ioctl(struct aac_dev *dev, int cmd, void __user *arg); reverted: --- b/drivers/scsi/aacraid/linit.c 2004-09-26 11:11:46 -07:00 +++ a/drivers/scsi/aacraid/linit.c 2004-09-26 11:11:46 -07:00 @@ -65,7 +65,8 @@ MODULE_LICENSE("GPL"); MODULE_VERSION(AAC_DRIVER_VERSION); +struct aac_dev *aac_devices[MAXIMUM_NUM_ADAPTERS]; +static unsigned aac_count; -static LIST_HEAD(aac_devices); static int aac_cfg_major = -1; /* @@ -451,18 +452,11 @@ static int aac_cfg_open(struct inode *inode, struct file *file) { - struct aac_dev *aac; unsigned minor = iminor(inode); - int err = -ENODEV; - - list_for_each_entry(aac, &aac_devices, entry) { - if (aac->id == minor) { - file->private_data = aac; - err = 0; - break; - } - } + if (minor >= aac_count) + return -ENODEV; + file->private_data = aac_devices[minor]; return 0; } @@ -523,18 +517,8 @@ struct Scsi_Host *shost; struct fsa_scsi_hba *fsa_dev_ptr; struct aac_dev *aac; + int container; - struct list_head *insert = &aac_devices; int error = -ENODEV; - int unique_id = 0; - int container; - - list_for_each_entry(aac, &aac_devices, entry) { - if (aac->id > unique_id) { - insert = &aac->entry; - break; - } - unique_id++; - } if (pci_enable_device(pdev)) goto out; @@ -553,13 +537,16 @@ pci_set_master(pdev); + /* Increment the host adapter count */ + aac_count++; + shost = scsi_host_alloc(&aac_driver_template, sizeof(struct aac_dev)); if (!shost) goto out_disable_pdev; shost->irq = pdev->irq; shost->base = pci_resource_start(pdev, 0); + shost->unique_id = aac_count - 1; - shost->unique_id = unique_id; aac = (struct aac_dev *)shost->hostdata; aac->scsi_host_ptr = shost; @@ -567,7 +554,6 @@ aac->name = aac_driver_template.name; aac->id = shost->unique_id; aac->cardtype = index; - INIT_LIST_HEAD(&aac->entry); aac->fibs = kmalloc(sizeof(struct fib) * AAC_NUM_FIB, GFP_KERNEL); if (!aac->fibs) @@ -603,9 +589,8 @@ else shost->max_channel = 1; - aac_get_config_status(aac); aac_get_containers(aac); + aac_devices[aac_count-1] = aac; - list_add(&aac->entry, insert); /* * dmb - we may need to move the setting of these parms somewhere else once @@ -614,16 +599,16 @@ shost->max_id = MAXIMUM_NUM_CONTAINERS; shost->max_lun = AAC_MAX_LUN; - pci_set_drvdata(pdev, shost); - error = scsi_add_host(shost, &pdev->dev); if (error) goto out_deinit; + + pci_set_drvdata(pdev, shost); scsi_scan_host(shost); return 0; + out_deinit: -out_deinit: kill_proc(aac->thread_pid, SIGKILL, 0); wait_for_completion(&aac->aif_completion); @@ -639,6 +624,7 @@ scsi_host_put(shost); out_disable_pdev: pci_disable_device(pdev); + aac_count--; out: return error; } @@ -667,7 +653,15 @@ scsi_host_put(shost); pci_disable_device(pdev); + /* + * We don't decrement aac_count here because adapters can be unplugged + * in a different order than they were detected. If we're ever going + * to overflow MAXIMUM_NUM_ADAPTERS we'll have to consider using a + * bintmap of free aac_devices slots. + */ +#if 0 + aac_count--; +#endif - list_del(&aac->entry); } static struct pci_driver aac_pci_driver = { reverted: --- b/drivers/scsi/advansys.c 2004-09-26 11:11:46 -07:00 +++ a/drivers/scsi/advansys.c 2004-09-26 11:11:46 -07:00 @@ -796,7 +796,6 @@ #include #include -#include #include #include #include "advansys.h" reverted: --- b/drivers/scsi/aic7xxx/aic79xx.h 2004-09-26 11:11:46 -07:00 +++ a/drivers/scsi/aic7xxx/aic79xx.h 2004-09-26 11:11:46 -07:00 @@ -549,7 +549,7 @@ struct map_node { bus_dmamap_t dmamap; + bus_addr_t physaddr; - dma_addr_t physaddr; uint8_t *vaddr; SLIST_ENTRY(map_node) links; }; @@ -626,8 +626,8 @@ struct map_node *sense_map; void *sg_list; uint8_t *sense_data; + bus_addr_t sg_list_busaddr; + bus_addr_t sense_busaddr; - dma_addr_t sg_list_busaddr; - dma_addr_t sense_busaddr; u_int sg_count;/* How full ahd_dma_seg is */ #define AHD_MAX_LQ_CRC_ERRORS 5 u_int crc_retry_count; @@ -1198,7 +1198,7 @@ bus_dma_tag_t parent_dmat; bus_dma_tag_t shared_data_dmat; bus_dmamap_t shared_data_dmamap; + bus_addr_t shared_data_busaddr; - dma_addr_t shared_data_busaddr; /* Information saved through suspend/resume cycles */ struct ahd_suspend_state suspend_state; reverted: --- b/drivers/scsi/aic7xxx/aic79xx_core.c 2004-09-26 11:11:45 -07:00 +++ a/drivers/scsi/aic7xxx/aic79xx_core.c 2004-09-26 11:11:45 -07:00 @@ -5493,9 +5493,9 @@ static void ahd_dmamap_cb(void *arg, bus_dma_segment_t *segs, int nseg, int error) { + bus_addr_t *baddr; - dma_addr_t *baddr; + baddr = (bus_addr_t *)arg; - baddr = (dma_addr_t *)arg; *baddr = segs->ds_addr; } @@ -5926,9 +5926,9 @@ struct map_node *sense_map; uint8_t *segs; uint8_t *sense_data; + bus_addr_t hscb_busaddr; + bus_addr_t sg_busaddr; + bus_addr_t sense_busaddr; - dma_addr_t hscb_busaddr; - dma_addr_t sg_busaddr; - dma_addr_t sense_busaddr; int newcount; int i; @@ -6161,7 +6161,7 @@ { uint8_t *base_vaddr; uint8_t *next_vaddr; + bus_addr_t next_baddr; - dma_addr_t next_baddr; size_t driver_data_size; int i; int error; @@ -6205,7 +6205,7 @@ if (ahd_dma_tag_create(ahd, ahd->parent_dmat, /*alignment*/1, /*boundary*/BUS_SPACE_MAXADDR_32BIT + 1, /*lowaddr*/ahd->flags & AHD_39BIT_ADDRESSING + ? (bus_addr_t)0x7FFFFFFFFFULL - ? (dma_addr_t)0x7FFFFFFFFFULL : BUS_SPACE_MAXADDR_32BIT, /*highaddr*/BUS_SPACE_MAXADDR, /*filter*/NULL, /*filterarg*/NULL, reverted: --- b/drivers/scsi/aic7xxx/aic79xx_inline.h 2004-09-26 11:11:46 -07:00 +++ a/drivers/scsi/aic7xxx/aic79xx_inline.h 2004-09-26 11:11:46 -07:00 @@ -231,7 +231,7 @@ /*********************** Scatter Gather List Handling *************************/ static __inline void *ahd_sg_setup(struct ahd_softc *ahd, struct scb *scb, + void *sgptr, bus_addr_t addr, - void *sgptr, dma_addr_t addr, bus_size_t len, int last); static __inline void ahd_setup_scb_common(struct ahd_softc *ahd, struct scb *scb); @@ -242,10 +242,10 @@ static __inline void * ahd_sg_setup(struct ahd_softc *ahd, struct scb *scb, + void *sgptr, bus_addr_t addr, bus_size_t len, int last) - void *sgptr, dma_addr_t addr, bus_size_t len, int last) { scb->sg_count++; + if (sizeof(bus_addr_t) > 4 - if (sizeof(dma_addr_t) > 4 && (ahd->flags & AHD_64BIT_ADDRESSING) != 0) { struct ahd_dma64_seg *sg; @@ -361,7 +361,7 @@ static __inline void * ahd_sg_bus_to_virt(struct ahd_softc *ahd, struct scb *scb, uint32_t sg_busaddr) { + bus_addr_t sg_offset; - dma_addr_t sg_offset; /* sg_list_phys points to entry 1, not 0 */ sg_offset = sg_busaddr - (scb->sg_list_busaddr - ahd_sg_size(ahd)); @@ -371,7 +371,7 @@ static __inline uint32_t ahd_sg_virt_to_bus(struct ahd_softc *ahd, struct scb *scb, void *sg) { + bus_addr_t sg_offset; - dma_addr_t sg_offset; /* sg_list_phys points to entry 1, not 0 */ sg_offset = ((uint8_t *)sg - (uint8_t *)scb->sg_list) diff -u b/drivers/scsi/aic7xxx/aic79xx_osm.c b/drivers/scsi/aic7xxx/aic79xx_osm.c --- b/drivers/scsi/aic7xxx/aic79xx_osm.c 2004-09-26 11:11:46 -07:00 +++ b/drivers/scsi/aic7xxx/aic79xx_osm.c 2004-09-26 11:13:18 -07:00 @@ -52,7 +52,9 @@ */ #include "aiclib.c" +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) #include /* __setup */ +#endif #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) #include "sd.h" /* For geometry detection */ @@ -66,6 +68,14 @@ */ spinlock_t ahd_list_spinlock; +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0) +struct proc_dir_entry proc_scsi_aic79xx = { + PROC_SCSI_AIC79XX, 7, "aic79xx", + S_IFDIR | S_IRUGO | S_IXUGO, 2, + 0, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL +}; +#endif + #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) /* For dynamic sglist size calculation. */ u_int ahd_linux_nseg; @@ -551,7 +561,7 @@ static __inline int ahd_linux_map_seg(struct ahd_softc *ahd, struct scb *scb, struct ahd_dma_seg *sg, - dma_addr_t addr, bus_size_t len); + bus_addr_t addr, bus_size_t len); static __inline void ahd_schedule_completeq(struct ahd_softc *ahd) @@ -569,20 +579,31 @@ static __inline void ahd_schedule_runq(struct ahd_softc *ahd) { +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) tasklet_schedule(&ahd->platform_data->runq_tasklet); +#else + /* + * Tasklets are not available, so run inline. + */ + ahd_runq_tasklet((unsigned long)ahd); +#endif } static __inline void ahd_setup_runq_tasklet(struct ahd_softc *ahd) { +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) tasklet_init(&ahd->platform_data->runq_tasklet, ahd_runq_tasklet, (unsigned long)ahd); +#endif } static __inline void ahd_teardown_runq_tasklet(struct ahd_softc *ahd) { +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) tasklet_kill(&ahd->platform_data->runq_tasklet); +#endif } static __inline struct ahd_linux_device* @@ -713,7 +734,7 @@ static __inline int ahd_linux_map_seg(struct ahd_softc *ahd, struct scb *scb, - struct ahd_dma_seg *sg, dma_addr_t addr, bus_size_t len) + struct ahd_dma_seg *sg, bus_addr_t addr, bus_size_t len) { int consumed; @@ -725,7 +746,7 @@ sg->addr = ahd_htole32(addr & 0xFFFFFFFF); scb->platform_data->xfer_len += len; - if (sizeof(dma_addr_t) > 4 + if (sizeof(bus_addr_t) > 4 && (ahd->flags & AHD_39BIT_ADDRESSING) != 0) len |= (addr >> 8) & AHD_SG_HIGH_ADDR_MASK; @@ -869,7 +890,11 @@ "aic79xx: insmod or else it might trash certain memory areas.\n"); #endif +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,0) template->proc_name = "aic79xx"; +#else + template->proc_dir = &proc_scsi_aic79xx; +#endif /* * Initialize our softc list lock prior to @@ -1676,27 +1701,35 @@ { struct ahd_softc* ahd; struct ahd_linux_device *dev; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) u_long flags; +#endif ahd = (struct ahd_softc *)data; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) ahd_lock(ahd, &flags); +#endif while ((dev = ahd_linux_next_device_to_run(ahd)) != NULL) { TAILQ_REMOVE(&ahd->platform_data->device_runq, dev, links); dev->flags &= ~AHD_DEV_ON_RUN_LIST; ahd_linux_check_device_queue(ahd, dev); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) /* Yeild to our interrupt handler */ ahd_unlock(ahd, &flags); ahd_lock(ahd, &flags); +#endif } +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) ahd_unlock(ahd, &flags); +#endif } /******************************** Bus DMA *************************************/ int ahd_dma_tag_create(struct ahd_softc *ahd, bus_dma_tag_t parent, bus_size_t alignment, bus_size_t boundary, - dma_addr_t lowaddr, dma_addr_t highaddr, + bus_addr_t lowaddr, bus_addr_t highaddr, bus_dma_filter_t *filter, void *filterarg, bus_size_t maxsize, int nsegments, bus_size_t maxsegsz, int flags, bus_dma_tag_t *ret_tag) @@ -1733,6 +1766,7 @@ { bus_dmamap_t map; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) map = malloc(sizeof(*map), M_DEVBUF, M_NOWAIT); if (map == NULL) return (ENOMEM); @@ -1744,7 +1778,7 @@ * our dma mask when doing allocations. */ if (ahd->dev_softc != NULL) - if (pci_set_dma_mask(ahd->dev_softc, 0xFFFFFFFF)) { + if (ahd_pci_set_dma_mask(ahd->dev_softc, 0xFFFFFFFF)) { printk(KERN_WARNING "aic79xx: No suitable DMA available.\n"); kfree(map); return (ENODEV); @@ -1752,12 +1786,22 @@ *vaddr = pci_alloc_consistent(ahd->dev_softc, dmat->maxsize, &map->bus_addr); if (ahd->dev_softc != NULL) - if (pci_set_dma_mask(ahd->dev_softc, + if (ahd_pci_set_dma_mask(ahd->dev_softc, ahd->platform_data->hw_dma_mask)) { printk(KERN_WARNING "aic79xx: No suitable DMA available.\n"); kfree(map); return (ENODEV); } +#else /* LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0) */ + /* + * At least in 2.2.14, malloc is a slab allocator so all + * allocations are aligned. We assume for these kernel versions + * that all allocations will be bellow 4Gig, physically contiguous, + * and accessible via DMA by the controller. + */ + map = NULL; /* No additional information to store */ + *vaddr = malloc(dmat->maxsize, M_DEVBUF, M_NOWAIT); +#endif if (*vaddr == NULL) return (ENOMEM); *mapp = map; @@ -1768,8 +1812,12 @@ ahd_dmamem_free(struct ahd_softc *ahd, bus_dma_tag_t dmat, void* vaddr, bus_dmamap_t map) { +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) pci_free_consistent(ahd->dev_softc, dmat->maxsize, vaddr, map->bus_addr); +#else + free(vaddr, M_DEVBUF); +#endif } int @@ -1783,7 +1831,12 @@ */ bus_dma_segment_t stack_sg; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) stack_sg.ds_addr = map->bus_addr; +#else +#define VIRT_TO_BUS(a) (uint32_t)virt_to_bus((void *)(a)) + stack_sg.ds_addr = VIRT_TO_BUS(buf); +#endif stack_sg.ds_len = dmat->maxsize; cb(cb_arg, &stack_sg, /*nseg*/1, /*error*/0); return (0); @@ -2015,7 +2068,9 @@ return 1; } +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,0) __setup("aic79xx=", aic79xx_setup); +#endif uint32_t aic79xx_verbose; @@ -2058,7 +2113,8 @@ ahd_set_name(ahd, new_name); } host->unique_id = ahd->unit; -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,4) && \ + LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) scsi_set_pci_device(host, ahd->dev_softc); #endif ahd_linux_setup_user_rd_strm_settings(ahd); @@ -2210,9 +2266,15 @@ ahd->platform_data->completeq_timer.data = (u_long)ahd; ahd->platform_data->completeq_timer.function = (ahd_linux_callback_t *)ahd_linux_thread_run_complete_queue; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) init_MUTEX_LOCKED(&ahd->platform_data->eh_sem); init_MUTEX_LOCKED(&ahd->platform_data->dv_sem); init_MUTEX_LOCKED(&ahd->platform_data->dv_cmd_sem); +#else + ahd->platform_data->eh_sem = MUTEX_LOCKED; + ahd->platform_data->dv_sem = MUTEX_LOCKED; + ahd->platform_data->dv_cmd_sem = MUTEX_LOCKED; +#endif ahd_setup_runq_tasklet(ahd); ahd->seltime = (aic79xx_seltime & 0x3) << 4; return (0); @@ -2272,10 +2334,13 @@ base_addr = (u_long)ahd->bshs[0].maddr; base_addr &= PAGE_MASK; iounmap((void *)base_addr); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) release_mem_region(ahd->platform_data->mem_busaddr, 0x1000); +#endif } -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) && \ + LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) /* * In 2.4 we detach from the scsi midlayer before the PCI * layer invokes our remove callback. No per-instance @@ -4065,7 +4130,7 @@ cmd->use_sg, dir); scb->platform_data->xfer_len = 0; for (sg = scb->sg_list; nseg > 0; nseg--, cur_seg++) { - dma_addr_t addr; + bus_addr_t addr; bus_size_t len; addr = sg_dma_address(cur_seg); @@ -4076,7 +4141,7 @@ } } else if (cmd->request_bufflen != 0) { void *sg; - dma_addr_t addr; + bus_addr_t addr; int dir; sg = scb->sg_list; @@ -4310,7 +4375,7 @@ WARN_ON(lun != CAM_LUN_WILDCARD); scsi_report_device_reset(ahd->platform_data->host, channel - 'A', target); -#else +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) Scsi_Device *scsi_dev; /* @@ -4331,10 +4396,12 @@ break; } case AC_BUS_RESET: +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) if (ahd->platform_data->host != NULL) { scsi_report_bus_reset(ahd->platform_data->host, channel - 'A'); } +#endif break; default: panic("ahd_send_async: Unexpected async event"); reverted: --- b/drivers/scsi/aic7xxx/aic79xx_osm.h 2004-09-26 11:11:46 -07:00 +++ a/drivers/scsi/aic7xxx/aic79xx_osm.h 2004-09-26 11:11:46 -07:00 @@ -53,9 +53,17 @@ #include #include +#ifndef KERNEL_VERSION +#define KERNEL_VERSION(x,y,z) (((x)<<16)+((y)<<8)+(z)) +#endif + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) #include /* For tasklet support. */ #include #include +#else +#include +#endif /* Core SCSI definitions */ #define AIC_LIB_PREFIX ahd @@ -136,6 +144,11 @@ /***************************** Bus Space/DMA **********************************/ +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,2,17) +typedef dma_addr_t bus_addr_t; +#else +typedef uint32_t bus_addr_t; +#endif typedef uint32_t bus_size_t; typedef enum { @@ -150,7 +163,7 @@ typedef struct bus_dma_segment { + bus_addr_t ds_addr; - dma_addr_t ds_addr; bus_size_t ds_len; } bus_dma_segment_t; @@ -164,11 +177,11 @@ struct ahd_linux_dmamap { + bus_addr_t bus_addr; - dma_addr_t bus_addr; }; typedef struct ahd_linux_dmamap* bus_dmamap_t; +typedef int bus_dma_filter_t(void*, bus_addr_t); -typedef int bus_dma_filter_t(void*, dma_addr_t); typedef void bus_dmamap_callback_t(void *, bus_dma_segment_t *, int, int); #define BUS_DMA_WAITOK 0x0 @@ -185,7 +198,7 @@ int ahd_dma_tag_create(struct ahd_softc *, bus_dma_tag_t /*parent*/, bus_size_t /*alignment*/, bus_size_t /*boundary*/, + bus_addr_t /*lowaddr*/, bus_addr_t /*highaddr*/, - dma_addr_t /*lowaddr*/, dma_addr_t /*highaddr*/, bus_dma_filter_t*/*filter*/, void */*filterarg*/, bus_size_t /*maxsize*/, int /*nsegments*/, bus_size_t /*maxsegsz*/, int /*flags*/, @@ -267,7 +280,11 @@ } /***************************** SMP support ************************************/ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,17) #include +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,93) +#include +#endif #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) || defined(SCSI_HAS_HOST_LOCK)) #define AHD_SCSI_HAS_HOST_LOCK 1 @@ -492,8 +509,11 @@ struct scb_platform_data { struct ahd_linux_device *dev; + bus_addr_t buf_busaddr; - dma_addr_t buf_busaddr; uint32_t xfer_len; +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0) + uint32_t resid; /* Transfer residual */ +#endif uint32_t sense_resid; /* Auto-Sense residual */ ahd_linux_scb_flags flags; }; @@ -523,7 +543,9 @@ struct ahd_completeq completeq; spinlock_t spin_lock; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) struct tasklet_struct runq_tasklet; +#endif u_int qfrozen; pid_t dv_pid; struct timer_list completeq_timer; @@ -540,7 +562,7 @@ uint32_t irq; /* IRQ for this adapter */ uint32_t bios_address; uint32_t mem_busaddr; /* Mem Base Addr */ + bus_addr_t hw_dma_mask; - dma_addr_t hw_dma_mask; ahd_linux_softc_flags flags; }; @@ -837,7 +859,9 @@ #define PCIXM_STATUS_MAXCRDS 0x1C00 /* Maximum Cumulative Read Size */ #define PCIXM_STATUS_RCVDSCEM 0x2000 /* Received a Split Comp w/Error msg */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) extern struct pci_driver aic79xx_pci_driver; +#endif typedef enum { @@ -941,6 +965,25 @@ ahd_inb(ahd, INTSTAT); } +#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,3,0) +#define pci_map_sg(pdev, sg_list, nseg, direction) (nseg) +#define pci_unmap_sg(pdev, sg_list, nseg, direction) +#define sg_dma_address(sg) (VIRT_TO_BUS((sg)->address)) +#define sg_dma_len(sg) ((sg)->length) +#define pci_map_single(pdev, buffer, bufflen, direction) \ + (VIRT_TO_BUS(buffer)) +#define pci_unmap_single(pdev, buffer, buflen, direction) +#endif + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,3) +#define ahd_pci_set_dma_mask pci_set_dma_mask +#else +/* + * Always "return" 0 for success. + */ +#define ahd_pci_set_dma_mask(dev_softc, mask) \ + (((dev_softc)->dma_mask = mask) && 0) +#endif /**************************** Proc FS Support *********************************/ #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) int ahd_linux_proc_info(char *, char **, off_t, int, int, int); @@ -1048,13 +1091,35 @@ static __inline int ahd_get_transfer_dir(struct scb *scb) { +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,40) return (scb->io_ctx->sc_data_direction); +#else + if (scb->io_ctx->bufflen == 0) + return (CAM_DIR_NONE); + + switch(scb->io_ctx->cmnd[0]) { + case 0x08: /* READ(6) */ + case 0x28: /* READ(10) */ + case 0xA8: /* READ(12) */ + return (CAM_DIR_IN); + case 0x0A: /* WRITE(6) */ + case 0x2A: /* WRITE(10) */ + case 0xAA: /* WRITE(12) */ + return (CAM_DIR_OUT); + default: + return (CAM_DIR_NONE); + } +#endif } static __inline void ahd_set_residual(struct scb *scb, u_long resid) { +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) scb->io_ctx->resid = resid; +#else + scb->platform_data->resid = resid; +#endif } static __inline @@ -1066,7 +1131,11 @@ static __inline u_long ahd_get_residual(struct scb *scb) { +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) return (scb->io_ctx->resid); +#else + return (scb->platform_data->resid); +#endif } static __inline diff -u b/drivers/scsi/aic7xxx/aic79xx_osm_pci.c b/drivers/scsi/aic7xxx/aic79xx_osm_pci.c --- b/drivers/scsi/aic7xxx/aic79xx_osm_pci.c 2004-09-26 11:11:46 -07:00 +++ b/drivers/scsi/aic7xxx/aic79xx_osm_pci.c 2004-09-26 11:13:18 -07:00 @@ -42,6 +42,12 @@ #include "aic79xx_osm.h" #include "aic79xx_inline.h" +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0) +struct pci_device_id +{ +}; +#endif + static int ahd_linux_pci_dev_probe(struct pci_dev *pdev, const struct pci_device_id *ent); static int ahd_linux_pci_reserve_io_regions(struct ahd_softc *ahd, @@ -49,6 +55,7 @@ static int ahd_linux_pci_reserve_mem_region(struct ahd_softc *ahd, u_long *bus_addr, uint8_t **maddr); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) static void ahd_linux_pci_dev_remove(struct pci_dev *pdev); /* We do our own ID filtering. So, grab all SCSI storage class devices. */ @@ -96,6 +103,7 @@ } ahd_list_unlock(&l); } +#endif /* !LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0) */ static int ahd_linux_pci_dev_probe(struct pci_dev *pdev, const struct pci_device_id *ent) @@ -144,39 +152,42 @@ ahd = ahd_alloc(NULL, name); if (ahd == NULL) return (-ENOMEM); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) if (pci_enable_device(pdev)) { ahd_free(ahd); return (-ENODEV); } pci_set_master(pdev); - if (sizeof(dma_addr_t) > 4) { + if (sizeof(bus_addr_t) > 4) { uint64_t memsize; - dma_addr_t mask_64bit; - dma_addr_t mask_39bit; + bus_addr_t mask_64bit; + bus_addr_t mask_39bit; memsize = ahd_linux_get_memsize(); - mask_64bit = (dma_addr_t)0xFFFFFFFFFFFFFFFFULL; - mask_39bit = (dma_addr_t)0x7FFFFFFFFFULL; + mask_64bit = (bus_addr_t)0xFFFFFFFFFFFFFFFFULL; + mask_39bit = (bus_addr_t)0x7FFFFFFFFFULL; if (memsize >= 0x8000000000ULL - && pci_set_dma_mask(pdev, mask_64bit) == 0) { + && ahd_pci_set_dma_mask(pdev, mask_64bit) == 0) { ahd->flags |= AHD_64BIT_ADDRESSING; ahd->platform_data->hw_dma_mask = mask_64bit; } else if (memsize > 0x80000000 - && pci_set_dma_mask(pdev, mask_39bit) == 0) { + && ahd_pci_set_dma_mask(pdev, mask_39bit) == 0) { ahd->flags |= AHD_39BIT_ADDRESSING; ahd->platform_data->hw_dma_mask = mask_39bit; } } else { - pci_set_dma_mask(pdev, 0xFFFFFFFF); + ahd_pci_set_dma_mask(pdev, 0xFFFFFFFF); ahd->platform_data->hw_dma_mask = 0xFFFFFFFF; } +#endif ahd->dev_softc = pci; error = ahd_pci_config(ahd, entry); if (error != 0) { ahd_free(ahd); return (-error); } +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) pci_set_drvdata(pdev, ahd); if (aic79xx_detect_complete) { #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) @@ -187,13 +198,38 @@ return (-ENODEV); #endif } +#endif return (0); } int ahd_linux_pci_init(void) { +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) return (pci_module_init(&aic79xx_pci_driver)); +#else + struct pci_dev *pdev; + u_int class; + int found; + + /* If we don't have a PCI bus, we can't find any adapters. */ + if (pci_present() == 0) + return (0); + + found = 0; + pdev = NULL; + class = PCI_CLASS_STORAGE_SCSI << 8; + while ((pdev = pci_find_class(class, pdev)) != NULL) { + ahd_dev_softc_t pci; + int error; + + pci = pdev; + error = ahd_linux_pci_dev_probe(pdev, /*pci_devid*/NULL); + if (error == 0) + found++; + } + return (found); +#endif } void @@ -206,6 +242,7 @@ ahd_linux_pci_reserve_io_regions(struct ahd_softc *ahd, u_long *base, u_long *base2) { +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) *base = pci_resource_start(ahd->dev_softc, 0); /* * This is really the 3rd bar and should be at index 2, @@ -213,14 +250,28 @@ * bars. */ *base2 = pci_resource_start(ahd->dev_softc, 3); +#else + *base = ahd_pci_read_config(ahd->dev_softc, AHD_PCI_IOADDR0, 4); + *base2 = ahd_pci_read_config(ahd->dev_softc, AHD_PCI_IOADDR1, 4); + *base &= PCI_BASE_ADDRESS_IO_MASK; + *base2 &= PCI_BASE_ADDRESS_IO_MASK; +#endif if (*base == 0 || *base2 == 0) return (ENOMEM); +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0) + if (check_region(*base, 256) != 0 + || check_region(*base2, 256) != 0) + return (ENOMEM); + request_region(*base, 256, "aic79xx"); + request_region(*base2, 256, "aic79xx"); +#else if (request_region(*base, 256, "aic79xx") == 0) return (ENOMEM); if (request_region(*base2, 256, "aic79xx") == 0) { release_region(*base2, 256); return (ENOMEM); } +#endif return (0); } @@ -241,18 +292,29 @@ return (ENOMEM); error = 0; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) start = pci_resource_start(ahd->dev_softc, 1); base_page = start & PAGE_MASK; base_offset = start - base_page; +#else + start = ahd_pci_read_config(ahd->dev_softc, PCIR_MAPS+4, 4); + base_offset = start & PCI_BASE_ADDRESS_MEM_MASK; + base_page = base_offset & PAGE_MASK; + base_offset -= base_page; +#endif if (start != 0) { *bus_addr = start; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) if (request_mem_region(start, 0x1000, "aic79xx") == 0) error = ENOMEM; +#endif if (error == 0) { *maddr = ioremap_nocache(base_page, base_offset + 256); if (*maddr == NULL) { error = ENOMEM; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) release_mem_region(start, 0x1000); +#endif } else *maddr += base_offset; } @@ -294,8 +356,10 @@ ahd_get_pci_slot(ahd->dev_softc), ahd_get_pci_function(ahd->dev_softc)); iounmap((void *)((u_long)maddr & PAGE_MASK)); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) release_mem_region(ahd->platform_data->mem_busaddr, 0x1000); +#endif ahd->bshs[0].maddr = NULL; maddr = NULL; } else @@ -350,3 +414,36 @@ { +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) pci_set_power_state(ahd->dev_softc, new_state); +#else + uint32_t cap; + u_int cap_offset; + + /* + * Traverse the capability list looking for + * the power management capability. + */ + cap = 0; + cap_offset = ahd_pci_read_config(ahd->dev_softc, + PCIR_CAP_PTR, /*bytes*/1); + while (cap_offset != 0) { + + cap = ahd_pci_read_config(ahd->dev_softc, + cap_offset, /*bytes*/4); + if ((cap & 0xFF) == 1 + && ((cap >> 16) & 0x3) > 0) { + uint32_t pm_control; + + pm_control = ahd_pci_read_config(ahd->dev_softc, + cap_offset + 4, + /*bytes*/4); + pm_control &= ~0x3; + pm_control |= new_state; + ahd_pci_write_config(ahd->dev_softc, + cap_offset + 4, + pm_control, /*bytes*/2); + break; + } + cap_offset = (cap >> 8) & 0xFF; + } +#endif } reverted: --- b/drivers/scsi/aic7xxx/aic7xxx.h 2004-09-26 11:11:46 -07:00 +++ a/drivers/scsi/aic7xxx/aic7xxx.h 2004-09-26 11:11:46 -07:00 @@ -521,7 +521,7 @@ struct sg_map_node { bus_dmamap_t sg_dmamap; + bus_addr_t sg_physaddr; - dma_addr_t sg_physaddr; struct ahc_dma_seg* sg_vaddr; SLIST_ENTRY(sg_map_node) links; }; @@ -584,7 +584,7 @@ struct scb_platform_data *platform_data; struct sg_map_node *sg_map; struct ahc_dma_seg *sg_list; + bus_addr_t sg_list_phys; - dma_addr_t sg_list_phys; u_int sg_count;/* How full ahc_dma_seg is */ }; @@ -611,10 +611,10 @@ */ bus_dma_tag_t hscb_dmat; /* dmat for our hardware SCB array */ bus_dmamap_t hscb_dmamap; + bus_addr_t hscb_busaddr; - dma_addr_t hscb_busaddr; bus_dma_tag_t sense_dmat; bus_dmamap_t sense_dmamap; + bus_addr_t sense_busaddr; - dma_addr_t sense_busaddr; bus_dma_tag_t sg_dmat; /* dmat for our sg segments */ SLIST_HEAD(, sg_map_node) sg_maps; uint8_t numscbs; @@ -1069,14 +1069,14 @@ bus_dma_tag_t parent_dmat; bus_dma_tag_t shared_data_dmat; bus_dmamap_t shared_data_dmamap; + bus_addr_t shared_data_busaddr; - dma_addr_t shared_data_busaddr; /* * Bus address of the one byte buffer used to * work-around a DMA bug for chips <= aic7880 * in target mode. */ + bus_addr_t dma_bug_buf; - dma_addr_t dma_bug_buf; /* Number of enabled target mode device on this card */ u_int enabled_luns; reverted: --- b/drivers/scsi/aic7xxx/aic7xxx_core.c 2004-09-26 11:11:46 -07:00 +++ a/drivers/scsi/aic7xxx/aic7xxx_core.c 2004-09-26 11:11:46 -07:00 @@ -4199,9 +4199,9 @@ static void ahc_dmamap_cb(void *arg, bus_dma_segment_t *segs, int nseg, int error) { + bus_addr_t *baddr; - dma_addr_t *baddr; + baddr = (bus_addr_t *)arg; - baddr = (dma_addr_t *)arg; *baddr = segs->ds_addr; } @@ -4456,7 +4456,7 @@ struct scb_data *scb_data; struct scb *next_scb; struct sg_map_node *sg_map; + bus_addr_t physaddr; - dma_addr_t physaddr; struct ahc_dma_seg *segs; int newcount; int i; @@ -4820,7 +4820,7 @@ if (ahc_dma_tag_create(ahc, ahc->parent_dmat, /*alignment*/1, /*boundary*/BUS_SPACE_MAXADDR_32BIT + 1, /*lowaddr*/ahc->flags & AHC_39BIT_ADDRESSING + ? (bus_addr_t)0x7FFFFFFFFFULL - ? (dma_addr_t)0x7FFFFFFFFFULL : BUS_SPACE_MAXADDR_32BIT, /*highaddr*/BUS_SPACE_MAXADDR, /*filter*/NULL, /*filterarg*/NULL, diff -u b/drivers/scsi/aic7xxx/aic7xxx_osm.c b/drivers/scsi/aic7xxx/aic7xxx_osm.c --- b/drivers/scsi/aic7xxx/aic7xxx_osm.c 2004-09-26 11:11:45 -07:00 +++ b/drivers/scsi/aic7xxx/aic7xxx_osm.c 2004-09-26 11:13:18 -07:00 @@ -129,7 +129,10 @@ */ #include "aiclib.c" +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) #include /* __setup */ +#endif + #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) #include "sd.h" /* For geometry detection */ @@ -149,6 +152,14 @@ u_int ahc_linux_nseg; #endif +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0) +struct proc_dir_entry proc_scsi_aic7xxx = { + PROC_SCSI_AIC7XXX, 7, "aic7xxx", + S_IFDIR | S_IRUGO | S_IXUGO, 2, + 0, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL +}; +#endif + /* * Set this to the delay in seconds after SCSI bus reset. * Note, we honor this only for the initial bus reset. @@ -561,7 +572,7 @@ static __inline int ahc_linux_map_seg(struct ahc_softc *ahc, struct scb *scb, struct ahc_dma_seg *sg, - dma_addr_t addr, bus_size_t len); + bus_addr_t addr, bus_size_t len); static __inline void ahc_schedule_completeq(struct ahc_softc *ahc) @@ -579,7 +590,14 @@ static __inline void ahc_schedule_runq(struct ahc_softc *ahc) { +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) tasklet_schedule(&ahc->platform_data->runq_tasklet); +#else + /* + * Tasklets are not available, so run inline. + */ + ahc_runq_tasklet((unsigned long)ahc); +#endif } static __inline struct ahc_linux_device* @@ -710,7 +728,7 @@ static __inline int ahc_linux_map_seg(struct ahc_softc *ahc, struct scb *scb, - struct ahc_dma_seg *sg, dma_addr_t addr, bus_size_t len) + struct ahc_dma_seg *sg, bus_addr_t addr, bus_size_t len) { int consumed; @@ -722,7 +740,7 @@ sg->addr = ahc_htole32(addr & 0xFFFFFFFF); scb->platform_data->xfer_len += len; - if (sizeof(dma_addr_t) > 4 + if (sizeof(bus_addr_t) > 4 && (ahc->flags & AHC_39BIT_ADDRESSING) != 0) len |= (addr >> 8) & AHC_SG_HIGH_ADDR_MASK; @@ -859,7 +877,11 @@ "aic7xxx: insmod or else it might trash certain memory areas.\n"); #endif +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,0) template->proc_name = "aic7xxx"; +#else + template->proc_dir = &proc_scsi_aic7xxx; +#endif /* * Initialize our softc list lock prior to @@ -1301,20 +1323,28 @@ { struct ahc_softc* ahc; struct ahc_linux_device *dev; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) u_long flags; +#endif ahc = (struct ahc_softc *)data; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) ahc_lock(ahc, &flags); +#endif while ((dev = ahc_linux_next_device_to_run(ahc)) != NULL) { TAILQ_REMOVE(&ahc->platform_data->device_runq, dev, links); dev->flags &= ~AHC_DEV_ON_RUN_LIST; ahc_linux_check_device_queue(ahc, dev); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) /* Yeild to our interrupt handler */ ahc_unlock(ahc, &flags); ahc_lock(ahc, &flags); +#endif } +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) ahc_unlock(ahc, &flags); +#endif } /******************************** Macros **************************************/ @@ -1327,7 +1357,7 @@ int ahc_dma_tag_create(struct ahc_softc *ahc, bus_dma_tag_t parent, bus_size_t alignment, bus_size_t boundary, - dma_addr_t lowaddr, dma_addr_t highaddr, + bus_addr_t lowaddr, bus_addr_t highaddr, bus_dma_filter_t *filter, void *filterarg, bus_size_t maxsize, int nsegments, bus_size_t maxsegsz, int flags, bus_dma_tag_t *ret_tag) @@ -1364,6 +1394,7 @@ { bus_dmamap_t map; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) map = malloc(sizeof(*map), M_DEVBUF, M_NOWAIT); if (map == NULL) return (ENOMEM); @@ -1375,7 +1406,7 @@ * our dma mask when doing allocations. */ if (ahc->dev_softc != NULL) - if (pci_set_dma_mask(ahc->dev_softc, 0xFFFFFFFF)) { + if (ahc_pci_set_dma_mask(ahc->dev_softc, 0xFFFFFFFF)) { printk(KERN_WARNING "aic7xxx: No suitable DMA available.\n"); kfree(map); return (ENODEV); @@ -1383,12 +1414,22 @@ *vaddr = pci_alloc_consistent(ahc->dev_softc, dmat->maxsize, &map->bus_addr); if (ahc->dev_softc != NULL) - if (pci_set_dma_mask(ahc->dev_softc, + if (ahc_pci_set_dma_mask(ahc->dev_softc, ahc->platform_data->hw_dma_mask)) { printk(KERN_WARNING "aic7xxx: No suitable DMA available.\n"); kfree(map); return (ENODEV); } +#else /* LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0) */ + /* + * At least in 2.2.14, malloc is a slab allocator so all + * allocations are aligned. We assume for these kernel versions + * that all allocations will be bellow 4Gig, physically contiguous, + * and accessible via DMA by the controller. + */ + map = NULL; /* No additional information to store */ + *vaddr = malloc(dmat->maxsize, M_DEVBUF, M_NOWAIT); +#endif if (*vaddr == NULL) return (ENOMEM); *mapp = map; @@ -1399,8 +1440,12 @@ ahc_dmamem_free(struct ahc_softc *ahc, bus_dma_tag_t dmat, void* vaddr, bus_dmamap_t map) { +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) pci_free_consistent(ahc->dev_softc, dmat->maxsize, vaddr, map->bus_addr); +#else + free(vaddr, M_DEVBUF); +#endif } int @@ -1414,7 +1459,12 @@ */ bus_dma_segment_t stack_sg; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) stack_sg.ds_addr = map->bus_addr; +#else +#define VIRT_TO_BUS(a) (uint32_t)virt_to_bus((void *)(a)) + stack_sg.ds_addr = VIRT_TO_BUS(buf); +#endif stack_sg.ds_len = dmat->maxsize; cb(cb_arg, &stack_sg, /*nseg*/1, /*error*/0); return (0); @@ -1425,10 +1475,9 @@ { /* * The map may is NULL in our < 2.3.X implementation. - * Now it's 2.6.5, but just in case... */ - BUG_ON(map == NULL); - free(map, M_DEVBUF); + if (map != NULL) + free(map, M_DEVBUF); } int @@ -1644,7 +1693,9 @@ return 1; } +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,0) __setup("aic7xxx=", aic7xxx_setup); +#endif uint32_t aic7xxx_verbose; @@ -1687,7 +1738,8 @@ ahc_set_name(ahc, new_name); } host->unique_id = ahc->unit; -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,4) && \ + LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) scsi_set_pci_device(host, ahc->dev_softc); #endif ahc_linux_initialize_scsi_bus(ahc); @@ -1873,11 +1925,19 @@ ahc->platform_data->completeq_timer.data = (u_long)ahc; ahc->platform_data->completeq_timer.function = (ahc_linux_callback_t *)ahc_linux_thread_run_complete_queue; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) init_MUTEX_LOCKED(&ahc->platform_data->eh_sem); init_MUTEX_LOCKED(&ahc->platform_data->dv_sem); init_MUTEX_LOCKED(&ahc->platform_data->dv_cmd_sem); +#else + ahc->platform_data->eh_sem = MUTEX_LOCKED; + ahc->platform_data->dv_sem = MUTEX_LOCKED; + ahc->platform_data->dv_cmd_sem = MUTEX_LOCKED; +#endif +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) tasklet_init(&ahc->platform_data->runq_tasklet, ahc_runq_tasklet, (unsigned long)ahc); +#endif ahc->seltime = (aic7xxx_seltime & 0x3) << 4; ahc->seltime_b = (aic7xxx_seltime & 0x3) << 4; if (aic7xxx_pci_parity == 0) @@ -1896,7 +1956,9 @@ if (ahc->platform_data != NULL) { del_timer_sync(&ahc->platform_data->completeq_timer); ahc_linux_kill_dv_thread(ahc); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) tasklet_kill(&ahc->platform_data->runq_tasklet); +#endif if (ahc->platform_data->host != NULL) { #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) scsi_remove_host(ahc->platform_data->host); @@ -1937,10 +1999,13 @@ base_addr = (u_long)ahc->bsh.maddr; base_addr &= PAGE_MASK; iounmap((void *)base_addr); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) release_mem_region(ahc->platform_data->mem_busaddr, 0x1000); +#endif } -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) && \ + LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) /* * In 2.4 we detach from the scsi midlayer before the PCI * layer invokes our remove callback. No per-instance @@ -3686,7 +3751,7 @@ * a transfer crosses a 32bit page. */ while (cur_seg < end_seg) { - dma_addr_t addr; + bus_addr_t addr; bus_size_t len; int consumed; @@ -3715,7 +3780,7 @@ scb->hscb->datacnt = scb->sg_list->len; } else if (cmd->request_bufflen != 0) { struct ahc_dma_seg *sg; - dma_addr_t addr; + bus_addr_t addr; sg = scb->sg_list; addr = pci_map_single(ahc->dev_softc, @@ -3999,7 +4064,7 @@ WARN_ON(lun != CAM_LUN_WILDCARD); scsi_report_device_reset(ahc->platform_data->host, channel - 'A', target); -#else +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) Scsi_Device *scsi_dev; /* @@ -4020,10 +4085,12 @@ break; } case AC_BUS_RESET: +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) if (ahc->platform_data->host != NULL) { scsi_report_bus_reset(ahc->platform_data->host, channel - 'A'); } +#endif break; default: panic("ahc_send_async: Unexpected async event"); reverted: --- b/drivers/scsi/aic7xxx/aic7xxx_osm.h 2004-09-26 11:11:46 -07:00 +++ a/drivers/scsi/aic7xxx/aic7xxx_osm.h 2004-09-26 11:11:46 -07:00 @@ -70,9 +70,17 @@ #include #include +#ifndef KERNEL_VERSION +#define KERNEL_VERSION(x,y,z) (((x)<<16)+((y)<<8)+(z)) +#endif + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) #include /* For tasklet support. */ #include #include +#else +#include +#endif /* Core SCSI definitions */ #define AIC_LIB_PREFIX ahc @@ -148,6 +156,11 @@ /***************************** Bus Space/DMA **********************************/ +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,2,17) +typedef dma_addr_t bus_addr_t; +#else +typedef uint32_t bus_addr_t; +#endif typedef uint32_t bus_size_t; typedef enum { @@ -162,7 +175,7 @@ typedef struct bus_dma_segment { + bus_addr_t ds_addr; - dma_addr_t ds_addr; bus_size_t ds_len; } bus_dma_segment_t; @@ -176,11 +189,11 @@ struct ahc_linux_dmamap { + bus_addr_t bus_addr; - dma_addr_t bus_addr; }; typedef struct ahc_linux_dmamap* bus_dmamap_t; +typedef int bus_dma_filter_t(void*, bus_addr_t); -typedef int bus_dma_filter_t(void*, dma_addr_t); typedef void bus_dmamap_callback_t(void *, bus_dma_segment_t *, int, int); #define BUS_DMA_WAITOK 0x0 @@ -197,7 +210,7 @@ int ahc_dma_tag_create(struct ahc_softc *, bus_dma_tag_t /*parent*/, bus_size_t /*alignment*/, bus_size_t /*boundary*/, + bus_addr_t /*lowaddr*/, bus_addr_t /*highaddr*/, - dma_addr_t /*lowaddr*/, dma_addr_t /*highaddr*/, bus_dma_filter_t*/*filter*/, void */*filterarg*/, bus_size_t /*maxsize*/, int /*nsegments*/, bus_size_t /*maxsegsz*/, int /*flags*/, @@ -279,7 +292,11 @@ } /***************************** SMP support ************************************/ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,17) #include +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,93) +#include +#endif #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) || defined(SCSI_HAS_HOST_LOCK)) #define AHC_SCSI_HAS_HOST_LOCK 1 @@ -498,8 +515,11 @@ struct scb_platform_data { struct ahc_linux_device *dev; + bus_addr_t buf_busaddr; - dma_addr_t buf_busaddr; uint32_t xfer_len; +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0) + uint32_t resid; /* Transfer residual */ +#endif uint32_t sense_resid; /* Auto-Sense residual */ ahc_linux_scb_flags flags; }; @@ -529,7 +549,9 @@ struct ahc_completeq completeq; spinlock_t spin_lock; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) struct tasklet_struct runq_tasklet; +#endif u_int qfrozen; pid_t dv_pid; struct timer_list completeq_timer; @@ -545,7 +567,7 @@ uint32_t irq; /* IRQ for this adapter */ uint32_t bios_address; uint32_t mem_busaddr; /* Mem Base Addr */ + bus_addr_t hw_dma_mask; - dma_addr_t hw_dma_mask; ahc_linux_softc_flags flags; }; @@ -797,7 +819,9 @@ #define PCIR_SUBVEND_0 0x2c #define PCIR_SUBDEV_0 0x2e +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) extern struct pci_driver aic7xxx_pci_driver; +#endif typedef enum { @@ -930,6 +954,25 @@ ahc_inb(ahc, INTSTAT); } +#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,3,0) +#define pci_map_sg(pdev, sg_list, nseg, direction) (nseg) +#define pci_unmap_sg(pdev, sg_list, nseg, direction) +#define sg_dma_address(sg) (VIRT_TO_BUS((sg)->address)) +#define sg_dma_len(sg) ((sg)->length) +#define pci_map_single(pdev, buffer, bufflen, direction) \ + (VIRT_TO_BUS(buffer)) +#define pci_unmap_single(pdev, buffer, buflen, direction) +#endif + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,3) +#define ahc_pci_set_dma_mask pci_set_dma_mask +#else +/* + * Always "return" 0 for success. + */ +#define ahc_pci_set_dma_mask(dev_softc, mask) \ + (((dev_softc)->dma_mask = mask) && 0) +#endif /**************************** Proc FS Support *********************************/ #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) int ahc_linux_proc_info(char *, char **, off_t, int, int, int); @@ -1037,13 +1080,35 @@ static __inline int ahc_get_transfer_dir(struct scb *scb) { +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,40) return (scb->io_ctx->sc_data_direction); +#else + if (scb->io_ctx->bufflen == 0) + return (CAM_DIR_NONE); + + switch(scb->io_ctx->cmnd[0]) { + case 0x08: /* READ(6) */ + case 0x28: /* READ(10) */ + case 0xA8: /* READ(12) */ + return (CAM_DIR_IN); + case 0x0A: /* WRITE(6) */ + case 0x2A: /* WRITE(10) */ + case 0xAA: /* WRITE(12) */ + return (CAM_DIR_OUT); + default: + return (CAM_DIR_NONE); + } +#endif } static __inline void ahc_set_residual(struct scb *scb, u_long resid) { +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) scb->io_ctx->resid = resid; +#else + scb->platform_data->resid = resid; +#endif } static __inline @@ -1055,7 +1120,11 @@ static __inline u_long ahc_get_residual(struct scb *scb) { +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) return (scb->io_ctx->resid); +#else + return (scb->platform_data->resid); +#endif } static __inline reverted: --- b/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c 2004-09-26 11:11:46 -07:00 +++ a/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c 2004-09-26 11:11:46 -07:00 @@ -40,7 +40,6 @@ */ #include "aic7xxx_osm.h" -#include "aic7xxx_pci.h" #if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0) struct pci_device_id @@ -58,77 +57,16 @@ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) static void ahc_linux_pci_dev_remove(struct pci_dev *pdev); +/* We do our own ID filtering. So, grab all SCSI storage class devices. */ static struct pci_device_id ahc_linux_pci_id_table[] = { + { + 0x9004, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, + PCI_CLASS_STORAGE_SCSI << 8, 0xFFFF00, 0 + }, + { + 0x9005, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, + PCI_CLASS_STORAGE_SCSI << 8, 0xFFFF00, 0 + }, -#define LINUXID(x,s) (unsigned)((((x) >> s) & 0xffff) ?: PCI_ANY_ID) -#define ID(x) \ - { \ - LINUXID(x,32), LINUXID(x,48), LINUXID(x,0), LINUXID(x,16), \ - PCI_CLASS_STORAGE_SCSI << 8, 0xFFFF00, 0 \ - } -#define ID4(x,y) \ - ID(x | ((y+0)<<48)), ID(x | ((y+1)<<48)), ID(x | ((y+2)<<48)), \ - ID(x | ((y+3)<<48)) -#define ID16(x) ID4(x,0ULL), ID4(x,4ULL), ID4(x,8ULL), ID4(x,12ULL) - ID(ID_AHA_2902_04_10_15_20C_30C), - ID(ID_AHA_2930CU), - ID(ID_AHA_1480A & ID_DEV_VENDOR_MASK), - ID(ID_AHA_2940AU_0 & ID_DEV_VENDOR_MASK), - ID(ID_AHA_2940AU_CN & ID_DEV_VENDOR_MASK), - ID(ID_AHA_2930C_VAR & ID_DEV_VENDOR_MASK), - ID(ID_AHA_2940), - ID(ID_AHA_3940), - ID(ID_AHA_398X), - ID(ID_AHA_2944), - ID(ID_AHA_3944), - ID(ID_AHA_4944), - ID(ID_AHA_2940U & ID_DEV_VENDOR_MASK), - ID(ID_AHA_3940U & ID_DEV_VENDOR_MASK), - ID(ID_AHA_2944U & ID_DEV_VENDOR_MASK), - ID(ID_AHA_3944U & ID_DEV_VENDOR_MASK), - ID(ID_AHA_398XU & ID_DEV_VENDOR_MASK), - ID(ID_AHA_4944U & ID_DEV_VENDOR_MASK), - ID(ID_AHA_2930U & ID_DEV_VENDOR_MASK), - ID(ID_AHA_2940U_PRO & ID_DEV_VENDOR_MASK), - ID(ID_AHA_2940U_CN & ID_DEV_VENDOR_MASK), - ID(ID_AHA_2930U2), - ID(ID_AHA_2940U2B), - ID(ID_AHA_2940U2_OEM), - ID(ID_AHA_2940U2), - ID(ID_AHA_2950U2B), - ID(ID_AIC7890_ARO), - ID(ID_AAA_131U2), - ID(ID_AHA_29160), - ID(ID_AHA_29160_CPQ), - ID(ID_AHA_29160N), - ID(ID_AHA_29160C), - ID(ID_AHA_29160B), - ID(ID_AHA_19160B), - ID(ID_AIC7892_ARO), - ID(ID_AHA_2940U_DUAL), - ID(ID_AHA_3940AU), - ID(ID_AHA_3944AU), - ID(ID_AIC7895_ARO), - ID(ID_AHA_3950U2B_0), - ID(ID_AHA_3950U2B_1), - ID(ID_AHA_3950U2D_0), - ID(ID_AHA_3950U2D_1), - ID(ID_AIC7896_ARO), - ID(ID_AHA_3960D), - ID(ID_AHA_3960D_CPQ), - ID(ID_AIC7899_ARO), - ID(ID_AIC7850 & ID_DEV_VENDOR_MASK), - ID(ID_AIC7855 & ID_DEV_VENDOR_MASK), - ID(ID_AIC7859 & ID_DEV_VENDOR_MASK), - ID(ID_AIC7860 & ID_DEV_VENDOR_MASK), - ID(ID_AIC7870 & ID_DEV_VENDOR_MASK), - ID(ID_AIC7880 & ID_DEV_VENDOR_MASK), - ID16(ID_AIC7890), - ID16(ID_AIC7892), - ID(ID_AIC7895 & ID_DEV_VENDOR_MASK), - ID(ID_AIC7896), - ID(ID_AIC7899), - ID(ID_AIC7810 & ID_DEV_VENDOR_MASK), - ID(ID_AIC7815 & ID_DEV_VENDOR_MASK), { 0 } }; @@ -170,7 +108,7 @@ ahc_linux_pci_dev_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { char buf[80]; + bus_addr_t mask_39bit; - dma_addr_t mask_39bit; struct ahc_softc *ahc; ahc_dev_softc_t pci; struct ahc_pci_identity *entry; @@ -221,14 +159,14 @@ } pci_set_master(pdev); + mask_39bit = (bus_addr_t)0x7FFFFFFFFFULL; + if (sizeof(bus_addr_t) > 4 - mask_39bit = 0x7FFFFFFFFFULL; - if (sizeof(dma_addr_t) > 4 && ahc_linux_get_memsize() > 0x80000000 + && ahc_pci_set_dma_mask(pdev, mask_39bit) == 0) { - && pci_set_dma_mask(pdev, mask_39bit) == 0) { ahc->flags |= AHC_39BIT_ADDRESSING; ahc->platform_data->hw_dma_mask = mask_39bit; } else { + if (ahc_pci_set_dma_mask(pdev, 0xFFFFFFFF)) { - if (pci_set_dma_mask(pdev, 0xFFFFFFFF)) { printk(KERN_WARNING "aic7xxx: No suitable DMA available.\n"); return (-ENODEV); } reverted: --- b/drivers/scsi/aic7xxx/aic7xxx_pci.c 2004-09-26 11:11:45 -07:00 +++ a/drivers/scsi/aic7xxx/aic7xxx_pci.c 2004-09-26 11:11:45 -07:00 @@ -54,10 +54,100 @@ #include #endif -#include "aic7xxx_pci.h" - #define AHC_PCI_IOADDR PCIR_MAPS /* I/O Address */ #define AHC_PCI_MEMADDR (PCIR_MAPS + 4) /* Mem I/O Address */ + +static __inline uint64_t +ahc_compose_id(u_int device, u_int vendor, u_int subdevice, u_int subvendor) +{ + uint64_t id; + + id = subvendor + | (subdevice << 16) + | ((uint64_t)vendor << 32) + | ((uint64_t)device << 48); + + return (id); +} + +#define ID_ALL_MASK 0xFFFFFFFFFFFFFFFFull +#define ID_DEV_VENDOR_MASK 0xFFFFFFFF00000000ull +#define ID_9005_GENERIC_MASK 0xFFF0FFFF00000000ull +#define ID_9005_SISL_MASK 0x000FFFFF00000000ull +#define ID_9005_SISL_ID 0x0005900500000000ull +#define ID_AIC7850 0x5078900400000000ull +#define ID_AHA_2902_04_10_15_20C_30C 0x5078900478509004ull +#define ID_AIC7855 0x5578900400000000ull +#define ID_AIC7859 0x3860900400000000ull +#define ID_AHA_2930CU 0x3860900438699004ull +#define ID_AIC7860 0x6078900400000000ull +#define ID_AIC7860C 0x6078900478609004ull +#define ID_AHA_1480A 0x6075900400000000ull +#define ID_AHA_2940AU_0 0x6178900400000000ull +#define ID_AHA_2940AU_1 0x6178900478619004ull +#define ID_AHA_2940AU_CN 0x2178900478219004ull +#define ID_AHA_2930C_VAR 0x6038900438689004ull + +#define ID_AIC7870 0x7078900400000000ull +#define ID_AHA_2940 0x7178900400000000ull +#define ID_AHA_3940 0x7278900400000000ull +#define ID_AHA_398X 0x7378900400000000ull +#define ID_AHA_2944 0x7478900400000000ull +#define ID_AHA_3944 0x7578900400000000ull +#define ID_AHA_4944 0x7678900400000000ull + +#define ID_AIC7880 0x8078900400000000ull +#define ID_AIC7880_B 0x8078900478809004ull +#define ID_AHA_2940U 0x8178900400000000ull +#define ID_AHA_3940U 0x8278900400000000ull +#define ID_AHA_2944U 0x8478900400000000ull +#define ID_AHA_3944U 0x8578900400000000ull +#define ID_AHA_398XU 0x8378900400000000ull +#define ID_AHA_4944U 0x8678900400000000ull +#define ID_AHA_2940UB 0x8178900478819004ull +#define ID_AHA_2930U 0x8878900478889004ull +#define ID_AHA_2940U_PRO 0x8778900478879004ull +#define ID_AHA_2940U_CN 0x0078900478009004ull + +#define ID_AIC7895 0x7895900478959004ull +#define ID_AIC7895_ARO 0x7890900478939004ull +#define ID_AIC7895_ARO_MASK 0xFFF0FFFFFFFFFFFFull +#define ID_AHA_2940U_DUAL 0x7895900478919004ull +#define ID_AHA_3940AU 0x7895900478929004ull +#define ID_AHA_3944AU 0x7895900478949004ull + +#define ID_AIC7890 0x001F9005000F9005ull +#define ID_AIC7890_ARO 0x00139005000F9005ull +#define ID_AAA_131U2 0x0013900500039005ull +#define ID_AHA_2930U2 0x0011900501819005ull +#define ID_AHA_2940U2B 0x00109005A1009005ull +#define ID_AHA_2940U2_OEM 0x0010900521809005ull +#define ID_AHA_2940U2 0x00109005A1809005ull +#define ID_AHA_2950U2B 0x00109005E1009005ull + +#define ID_AIC7892 0x008F9005FFFF9005ull +#define ID_AIC7892_ARO 0x00839005FFFF9005ull +#define ID_AHA_29160 0x00809005E2A09005ull +#define ID_AHA_29160_CPQ 0x00809005E2A00E11ull +#define ID_AHA_29160N 0x0080900562A09005ull +#define ID_AHA_29160C 0x0080900562209005ull +#define ID_AHA_29160B 0x00809005E2209005ull +#define ID_AHA_19160B 0x0081900562A19005ull + +#define ID_AIC7896 0x005F9005FFFF9005ull +#define ID_AIC7896_ARO 0x00539005FFFF9005ull +#define ID_AHA_3950U2B_0 0x00509005FFFF9005ull +#define ID_AHA_3950U2B_1 0x00509005F5009005ull +#define ID_AHA_3950U2D_0 0x00519005FFFF9005ull +#define ID_AHA_3950U2D_1 0x00519005B5009005ull + +#define ID_AIC7899 0x00CF9005FFFF9005ull +#define ID_AIC7899_ARO 0x00C39005FFFF9005ull +#define ID_AHA_3960D 0x00C09005F6209005ull +#define ID_AHA_3960D_CPQ 0x00C09005F6200E11ull + +#define ID_AIC7810 0x1078900400000000ull +#define ID_AIC7815 0x7815900400000000ull #define DEVID_9005_TYPE(id) ((id) & 0xF) #define DEVID_9005_TYPE_HBA 0x0 /* Standard Card */ reverted: --- b/drivers/scsi/aic7xxx/aic7xxx_pci.h 2004-09-26 11:11:47 -07:00 +++ /dev/null Wed Dec 31 16:00:00 196900 @@ -1,92 +0,0 @@ - -static __inline uint64_t -ahc_compose_id(u_int device, u_int vendor, u_int subdevice, u_int subvendor) -{ - uint64_t id; - - id = subvendor - | (subdevice << 16) - | ((uint64_t)vendor << 32) - | ((uint64_t)device << 48); - - return (id); -} - -#define ID_ALL_MASK 0xFFFFFFFFFFFFFFFFull -#define ID_DEV_VENDOR_MASK 0xFFFFFFFF00000000ull -#define ID_9005_GENERIC_MASK 0xFFF0FFFF00000000ull -#define ID_9005_SISL_MASK 0x000FFFFF00000000ull -#define ID_9005_SISL_ID 0x0005900500000000ull -#define ID_AIC7850 0x5078900400000000ull -#define ID_AHA_2902_04_10_15_20C_30C 0x5078900478509004ull -#define ID_AIC7855 0x5578900400000000ull -#define ID_AIC7859 0x3860900400000000ull -#define ID_AHA_2930CU 0x3860900438699004ull -#define ID_AIC7860 0x6078900400000000ull -#define ID_AIC7860C 0x6078900478609004ull -#define ID_AHA_1480A 0x6075900400000000ull -#define ID_AHA_2940AU_0 0x6178900400000000ull -#define ID_AHA_2940AU_1 0x6178900478619004ull -#define ID_AHA_2940AU_CN 0x2178900478219004ull -#define ID_AHA_2930C_VAR 0x6038900438689004ull - -#define ID_AIC7870 0x7078900400000000ull -#define ID_AHA_2940 0x7178900400000000ull -#define ID_AHA_3940 0x7278900400000000ull -#define ID_AHA_398X 0x7378900400000000ull -#define ID_AHA_2944 0x7478900400000000ull -#define ID_AHA_3944 0x7578900400000000ull -#define ID_AHA_4944 0x7678900400000000ull - -#define ID_AIC7880 0x8078900400000000ull -#define ID_AIC7880_B 0x8078900478809004ull -#define ID_AHA_2940U 0x8178900400000000ull -#define ID_AHA_3940U 0x8278900400000000ull -#define ID_AHA_2944U 0x8478900400000000ull -#define ID_AHA_3944U 0x8578900400000000ull -#define ID_AHA_398XU 0x8378900400000000ull -#define ID_AHA_4944U 0x8678900400000000ull -#define ID_AHA_2940UB 0x8178900478819004ull -#define ID_AHA_2930U 0x8878900478889004ull -#define ID_AHA_2940U_PRO 0x8778900478879004ull -#define ID_AHA_2940U_CN 0x0078900478009004ull - -#define ID_AIC7895 0x7895900478959004ull -#define ID_AIC7895_ARO 0x7890900478939004ull -#define ID_AIC7895_ARO_MASK 0xFFF0FFFFFFFFFFFFull -#define ID_AHA_2940U_DUAL 0x7895900478919004ull -#define ID_AHA_3940AU 0x7895900478929004ull -#define ID_AHA_3944AU 0x7895900478949004ull - -#define ID_AIC7890 0x001F9005000F9005ull -#define ID_AIC7890_ARO 0x00139005000F9005ull -#define ID_AAA_131U2 0x0013900500039005ull -#define ID_AHA_2930U2 0x0011900501819005ull -#define ID_AHA_2940U2B 0x00109005A1009005ull -#define ID_AHA_2940U2_OEM 0x0010900521809005ull -#define ID_AHA_2940U2 0x00109005A1809005ull -#define ID_AHA_2950U2B 0x00109005E1009005ull - -#define ID_AIC7892 0x008F9005FFFF9005ull -#define ID_AIC7892_ARO 0x00839005FFFF9005ull -#define ID_AHA_29160 0x00809005E2A09005ull -#define ID_AHA_29160_CPQ 0x00809005E2A00E11ull -#define ID_AHA_29160N 0x0080900562A09005ull -#define ID_AHA_29160C 0x0080900562209005ull -#define ID_AHA_29160B 0x00809005E2209005ull -#define ID_AHA_19160B 0x0081900562A19005ull - -#define ID_AIC7896 0x005F9005FFFF9005ull -#define ID_AIC7896_ARO 0x00539005FFFF9005ull -#define ID_AHA_3950U2B_0 0x00509005FFFF9005ull -#define ID_AHA_3950U2B_1 0x00509005F5009005ull -#define ID_AHA_3950U2D_0 0x00519005FFFF9005ull -#define ID_AHA_3950U2D_1 0x00519005B5009005ull - -#define ID_AIC7899 0x00CF9005FFFF9005ull -#define ID_AIC7899_ARO 0x00C39005FFFF9005ull -#define ID_AHA_3960D 0x00C09005F6209005ull -#define ID_AHA_3960D_CPQ 0x00C09005F6200E11ull - -#define ID_AIC7810 0x1078900400000000ull -#define ID_AIC7815 0x7815900400000000ull reverted: --- b/drivers/scsi/aic7xxx/cam.h 2004-09-26 11:11:46 -07:00 +++ a/drivers/scsi/aic7xxx/cam.h 2004-09-26 11:11:46 -07:00 @@ -85,6 +85,12 @@ CAM_STATUS_MASK = 0x3F } cam_status; +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0) +#define SCSI_DATA_READ 1 +#define SCSI_DATA_WRITE 2 +#define SCSI_DATA_NONE 3 +#endif + /* * Definitions for the asynchronous callback CCB fields. */ reverted: --- b/drivers/scsi/ncr53c8xx.c 2004-09-26 11:11:46 -07:00 +++ a/drivers/scsi/ncr53c8xx.c 2004-09-26 11:11:46 -07:00 @@ -83,6 +83,11 @@ ** ** Supported NCR/SYMBIOS chips: ** 53C720 (Wide, Fast SCSI-2, intfly problems) +** +** Other features: +** Memory mapped IO (linux-1.3.X and above only) +** Module +** Shared IRQ (since linux-1.3.72) */ /* Name and version of the driver */ @@ -119,10 +124,8 @@ #include #include +#include "scsi.h" +#include -#include -#include -#include -#include #include "ncr53c8xx.h" @@ -137,6 +140,7 @@ #define NAME53C "ncr53c" #define NAME53C8XX "ncr53c8xx" +#define DRIVER_SMP_LOCK ncr53c8xx_lock #include "sym53c8xx_comm.h" @@ -312,6 +316,10 @@ #define ScsiResult(host_code, scsi_code) (((host_code) << 16) + ((scsi_code) & 0x7f)) +static void ncr53c8xx_timeout(unsigned long np); +static int ncr53c8xx_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t offset, + int length, int func); + #define initverbose (driver_setup.verbose) #define bootverbose (np->verbose) @@ -618,10 +626,10 @@ ** 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 */ - struct list_head free_ccbq; /* Queue of available CCBs */ - struct list_head busy_ccbq; /* Queue of busy CCBs */ - struct list_head wait_ccbq; /* Queue of waiting for IO CCBs */ - struct list_head 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*/ @@ -912,7 +920,7 @@ u_char queued; u_char auto_sense; struct ccb * link_ccb; /* Host adapter CCB chain */ + XPT_QUEHEAD link_ccbq; /* Link to unit CCB queue */ - struct list_head link_ccbq; /* Link to unit CCB queue */ u32 startp; /* Initial data pointer */ u_long magic; /* Free / busy CCB flag */ }; @@ -989,9 +997,9 @@ ** 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. */ - unsigned long vaddr; /* Virtual and bus address of */ - unsigned long paddr; /* chip's IO registers. */ - unsigned long paddr2; /* On-chip RAM bus address. */ volatile /* Pointer to volatile for */ struct ncr_reg *reg; /* memory mapped IO. */ @@ -2818,7 +2826,7 @@ *p++ =PADDR (idle); }; + assert ((u_long)p == (u_long)&scrh->tryloop + sizeof (scrh->tryloop)); - BUG_ON((u_long)p != (u_long)&scrh->tryloop + sizeof (scrh->tryloop)); #ifdef SCSI_NCR_CCB_DONE_SUPPORT @@ -2831,7 +2839,7 @@ *p++ =PADDR (done_end); } + assert ((u_long)p ==(u_long)&scrh->done_queue+sizeof(scrh->done_queue)); - BUG_ON((u_long)p != (u_long)&scrh->done_queue+sizeof(scrh->done_queue)); #endif /* SCSI_NCR_CCB_DONE_SUPPORT */ @@ -2842,8 +2850,7 @@ *p++ =SCR_MOVE_TBL ^ SCR_DATA_IN; *p++ =offsetof (struct dsb, data[i]); }; + assert ((u_long)p == (u_long)&scrh->hdata_in + sizeof (scrh->hdata_in)); - - BUG_ON((u_long)p != (u_long)&scrh->hdata_in + sizeof (scrh->hdata_in)); p = scr->data_in; for (i=MAX_SCATTERH; idata_in + sizeof (scr->data_in)); - - BUG_ON((u_long)p != (u_long)&scr->data_in + sizeof (scr->data_in)); p = scrh->hdata_out; for (i=0; ihdata_out + sizeof (scrh->hdata_out)); - - BUG_ON((u_long)p != (u_long)&scrh->hdata_out + sizeof (scrh->hdata_out)); p = scr->data_out; for (i=MAX_SCATTERH; idata_out + sizeof (scr->data_out)); - BUG_ON((u_long) p != (u_long)&scr->data_out + sizeof (scr->data_out)); } /*========================================================== @@ -2911,7 +2916,7 @@ if (opcode == 0) { printk (KERN_ERR "%s: ERROR0 IN SCRIPT at %d.\n", ncr_name(np), (int) (src-start-1)); + MDELAY (1000); - mdelay(1000); }; if (DEBUG_FLAGS & DEBUG_SCRIPT) @@ -2941,7 +2946,7 @@ if ((tmp1 ^ tmp2) & 3) { printk (KERN_ERR"%s: ERROR1 IN SCRIPT at %d.\n", ncr_name(np), (int) (src-start-1)); + MDELAY (1000); - mdelay(1000); } /* ** If PREFETCH feature not enabled, remove @@ -3031,8 +3036,21 @@ }; } +/*========================================================== +** +** +** Auto configuration: attach and init a host adapter. +** +** +**========================================================== +*/ + /* ** Linux host data structure +** +** The script area is allocated in the host data structure +** because kmalloc() returns NULL during scsi initialisations +** with Linux 1.2.X */ struct host_data { @@ -3825,8 +3843,8 @@ **---------------------------------------------------- */ + direction = scsi_data_direction(cmd); + if (direction != SCSI_DATA_NONE) { - direction = cmd->sc_data_direction; - if (direction != DMA_NONE) { segments = ncr_scatter(np, cp, cp->cmd); if (segments < 0) { ncr_free_ccb(np, cp); @@ -3923,17 +3941,17 @@ **---------------------------------------------------- */ if (!cp->data_len) + direction = SCSI_DATA_NONE; - direction = DMA_NONE; /* + ** If data direction is UNKNOWN, speculate DATA_READ + ** but prepare alternate pointers for WRITE in case - ** If data direction is BIDIRECTIONAL, speculate FROM_DEVICE - ** but prepare alternate pointers for TO_DEVICE in case ** of our speculation will be just wrong. ** SCRIPTS will swap values if needed. */ switch(direction) { + case SCSI_DATA_UNKNOWN: + case SCSI_DATA_WRITE: - case DMA_BIDIRECTIONAL: - case DMA_TO_DEVICE: goalp = NCB_SCRIPT_PHYS (np, data_out2) + 8; if (segments <= MAX_SCATTERL) lastp = goalp - 8 - (segments * 16); @@ -3941,12 +3959,12 @@ lastp = NCB_SCRIPTH_PHYS (np, hdata_out2); lastp -= (segments - MAX_SCATTERL) * 16; } + if (direction != SCSI_DATA_UNKNOWN) - if (direction != DMA_BIDIRECTIONAL) break; cp->phys.header.wgoalp = cpu_to_scr(goalp); cp->phys.header.wlastp = cpu_to_scr(lastp); /* fall through */ + case SCSI_DATA_READ: - case DMA_FROM_DEVICE: goalp = NCB_SCRIPT_PHYS (np, data_in2) + 8; if (segments <= MAX_SCATTERL) lastp = goalp - 8 - (segments * 16); @@ -3956,7 +3974,7 @@ } break; default: + case SCSI_DATA_NONE: - case DMA_NONE: lastp = goalp = NCB_SCRIPT_PHYS (np, no_data); break; } @@ -3968,7 +3986,7 @@ cp->phys.header.lastp = cpu_to_scr(lastp); cp->phys.header.goalp = cpu_to_scr(goalp); + if (direction == SCSI_DATA_UNKNOWN) - if (direction == DMA_BIDIRECTIONAL) cp->phys.header.savep = cpu_to_scr(NCB_SCRIPTH_PHYS (np, data_io)); else @@ -4071,19 +4089,19 @@ static void ncr_start_next_ccb(struct ncb *np, struct lcb *lp, int maxn) { + XPT_QUEHEAD *qp; - struct list_head *qp; struct ccb *cp; if (lp->held_ccb) return; while (maxn-- && lp->queuedccbs < lp->queuedepth) { + qp = xpt_remque_head(&lp->wait_ccbq); - qp = ncr_list_pop(&lp->wait_ccbq); if (!qp) break; ++lp->queuedccbs; + cp = xpt_que_entry(qp, struct ccb, link_ccbq); + xpt_insque_tail(qp, &lp->busy_ccbq); - cp = list_entry(qp, struct ccb, link_ccbq); - list_add_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); @@ -4134,7 +4152,7 @@ ncr_name(np), settle_delay); ncr_chip_reset(np, 100); + UDELAY (2000); /* The 895 needs time for the bus mode to settle */ - udelay(2000); /* The 895 needs time for the bus mode to settle */ if (enab_int) OUTW (nc_sien, RST); /* @@ -4143,7 +4161,7 @@ */ OUTB (nc_stest3, TE); OUTB (nc_scntl1, CRST); + UDELAY (200); - udelay(200); if (!driver_setup.bus_check) goto out; @@ -4262,7 +4280,6 @@ return SUCCESS; } -#if 0 /* unused and broken.. */ /*========================================================== ** ** @@ -4343,7 +4360,17 @@ return retv; } + +/*========================================================== +** +** Linux release module stuff. +** +** Called before unloading the module +** Detach the host. +** We have to free resources and halt the NCR chip +** +**========================================================== +*/ -#endif static void ncr_detach(struct ncb *np) { @@ -4368,8 +4395,7 @@ printk("%s: stopping the timer\n", ncr_name(np)); #endif np->release_stage = 1; + for (i = 50 ; i && np->release_stage != 2 ; i--) MDELAY (100); - for (i = 50 ; i && np->release_stage != 2 ; i--) - mdelay(100); if (np->release_stage != 2) printk("%s: the timer seems to be already stopped\n", ncr_name(np)); else np->release_stage = 2; @@ -4510,7 +4536,8 @@ 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); - list_splice_init(&lp->skip_ccbq, &lp->wait_ccbq); lp->held_ccb = NULL; } } @@ -4721,7 +4748,7 @@ ** requeue awaiting scsi commands for this lun. */ if (lp && lp->queuedccbs < lp->queuedepth && + !xpt_que_empty(&lp->wait_ccbq)) - !list_empty(&lp->wait_ccbq)) ncr_start_next_ccb(np, lp, 2); /* @@ -4758,8 +4785,8 @@ 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); - list_del(&cp->link_ccbq); - list_add_tail(&cp->link_ccbq, &lp->skip_ccbq); if (cp->queued) { --lp->queuedccbs; } @@ -4844,7 +4871,7 @@ static void ncr_chip_reset(struct ncb *np, int delay) { OUTB (nc_istat, SRST); + UDELAY (delay); - udelay(delay); OUTB (nc_istat, 0 ); if (np->features & FE_EHP) @@ -4873,7 +4900,7 @@ if (reset) { OUTB (nc_istat, SRST); + UDELAY (100); - udelay(100); } else { OUTB (nc_stest3, TE|CSF); @@ -5188,12 +5215,18 @@ static void ncr_setsync (struct ncb *np, struct ccb *cp, u_char scntl3, u_char sxfer) { + struct scsi_cmnd *cmd; - struct scsi_cmnd *cmd = cp->cmd; struct tcb *tp; u_char target = INB (nc_sdid) & 0x0f; u_char idiv; + assert (cp && cp->cmd); + if (!cp) return; + + cmd = cp->cmd; + if (!cmd) return; + + assert (target == (cmd->device->id & 0xf)); - BUG_ON(target != (cmd->device->id & 0xf)); tp = &np->target[target]; @@ -5266,13 +5299,19 @@ static void ncr_setwide (struct ncb *np, struct ccb *cp, u_char wide, u_char ack) { + struct scsi_cmnd *cmd; - struct scsi_cmnd *cmd = cp->cmd; u16 target = INB (nc_sdid) & 0x0f; struct tcb *tp; u_char scntl3; u_char sxfer; + assert (cp && cp->cmd); + if (!cp) return; + + cmd = cp->cmd; + if (!cmd) return; + + assert (target == (cmd->device->id & 0xf)); - BUG_ON(target != (cmd->device->id & 0xf)); tp = &np->target[target]; tp->widedone = wide+1; @@ -5399,6 +5438,86 @@ } } +/*---------------------------------------------------- +** +** handle user commands +** +**---------------------------------------------------- +*/ + +#ifdef SCSI_NCR_USER_COMMAND_SUPPORT + +static void ncr_usercmd (struct ncb *np) +{ + u_char t; + struct tcb *tp; + + switch (np->user.cmd) { + + case 0: return; + + case UC_SETSYNC: + for (t=0; tuser.target>>t)&1)) continue; + tp = &np->target[t]; + tp->usrsync = np->user.data; + ncr_negotiate (np, tp); + }; + break; + + case UC_SETTAGS: + for (t=0; tuser.target>>t)&1)) continue; + np->target[t].usrtags = np->user.data; + for (ln = 0; ln < MAX_LUN; ln++) { + struct lcb *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: +#ifdef SCSI_NCR_DEBUG_INFO_SUPPORT + ncr_debug = np->user.data; +#endif + break; + + case UC_SETORDER: + np->order = np->user.data; + break; + + case UC_SETVERBOSE: + np->verbose = np->user.data; + break; + + case UC_SETWIDE: + for (t=0; tuser.target>>t)&1)) continue; + tp = &np->target[t]; + size = np->user.data; + if (size > np->maxwide) size=np->maxwide; + tp->usrwide = size; + ncr_negotiate (np, tp); + }; + break; + + case UC_SETFLAG: + for (t=0; tuser.target>>t)&1)) continue; + tp = &np->target[t]; + tp->usrflag = np->user.data; + }; + break; + } + np->user.cmd=0; +} +#endif + /*========================================================== ** ** @@ -6234,7 +6353,7 @@ struct scsi_cmnd *cmd = cp->cmd; struct tcb *tp = &np->target[cmd->device->id]; struct lcb *lp = tp->lp[cmd->device->lun]; + XPT_QUEHEAD *qp; - struct list_head *qp; struct ccb * cp2; int disc_cnt = 0; int busy_cnt = 0; @@ -6248,10 +6367,10 @@ ** are before cp and busy ones after. */ if (lp) { + qp = lp->busy_ccbq.blink; - qp = lp->busy_ccbq.prev; while (qp != &lp->busy_ccbq) { + cp2 = xpt_que_entry(qp, struct ccb, link_ccbq); + qp = qp->blink; - cp2 = list_entry(qp, struct ccb, link_ccbq); - qp = qp->prev; ++busy_cnt; if (cp2 == cp) break; @@ -6331,7 +6450,7 @@ /* ** sense data */ + bzero(cp->sense_buf, sizeof(cp->sense_buf)); - memset(cp->sense_buf, 0, sizeof(cp->sense_buf)); cp->phys.sense.addr = cpu_to_scr(CCB_PHYS(cp,sense_buf[0])); cp->phys.sense.size = cpu_to_scr(sizeof(cp->sense_buf)); @@ -6472,8 +6591,7 @@ while (cp && (CCB_PHYS (cp, phys) != dsa)) cp = cp->link_ccb; + assert (cp && cp == np->header.cp); - BUG_ON(!cp); - BUG_ON(cp != np->header.cp); if (!cp || cp != np->header.cp) goto out; @@ -6899,7 +7017,7 @@ ** Lun structure available ? */ if (lp) { + XPT_QUEHEAD *qp; - struct list_head *qp; /* ** Keep from using more tags than we can handle. */ @@ -6909,7 +7027,7 @@ /* ** Allocate a new CCB if needed. */ + if (xpt_que_empty(&lp->free_ccbq)) - if (list_empty(&lp->free_ccbq)) ncr_alloc_ccb(np, tn, ln); /* @@ -6922,15 +7040,16 @@ /* ** Look for free CCB */ + qp = xpt_remque_head(&lp->free_ccbq); - qp = ncr_list_pop(&lp->free_ccbq); if (qp) { + cp = xpt_que_entry(qp, struct ccb, link_ccbq); - cp = list_entry(qp, struct ccb, link_ccbq); if (cp->magic) { PRINT_LUN(np, tn, ln); printk ("ccb free list corrupted (@%p)\n", cp); cp = NULL; + } + else { + xpt_insque_tail(qp, &lp->wait_ccbq); - } else { - list_add_tail(qp, &lp->wait_ccbq); ++lp->busyccbs; } } @@ -7040,8 +7159,10 @@ */ if (lp) { + if (cp != np->ccb) { + xpt_remque(&cp->link_ccbq); + xpt_insque_head(&cp->link_ccbq, &lp->free_ccbq); + } - if (cp != np->ccb) - list_move(&cp->link_ccbq, &lp->free_ccbq); --lp->busyccbs; if (cp->queued) { --lp->queuedccbs; @@ -7079,9 +7200,9 @@ cp->phys.header.cp = cp; /* + ** This allows xpt_remque to work for the default ccb. - ** This allows list_del to work for the default ccb. */ + xpt_que_init(&cp->link_ccbq); - INIT_LIST_HEAD(&cp->link_ccbq); /* ** Initialyze the start and restart launch script. @@ -7125,7 +7246,7 @@ */ lp->actccbs++; np->actccbs++; + bzero (cp, sizeof (*cp)); - memset(cp, 0, sizeof (*cp)); ncr_init_ccb(np, cp); /* @@ -7135,7 +7256,7 @@ cp->link_ccb = np->ccb->link_ccb; np->ccb->link_ccb = cp; + xpt_insque_head(&cp->link_ccbq, &lp->free_ccbq); - list_add(&cp->link_ccbq, &lp->free_ccbq); ncr_setup_tags (np, tn, ln); } @@ -7224,15 +7345,15 @@ ** These assert's should be moved at driver initialisations. */ #ifdef SCSI_NCR_BIG_ENDIAN + assert (( (offsetof(struct ncr_reg, nc_sxfer) ^ + offsetof(struct tcb , sval )) &3) == 3); + assert (( (offsetof(struct ncr_reg, nc_scntl3) ^ + offsetof(struct tcb , wval )) &3) == 3); - BUG_ON(((offsetof(struct ncr_reg, nc_sxfer) ^ - offsetof(struct tcb , sval )) &3) != 3); - BUG_ON(((offsetof(struct ncr_reg, nc_scntl3) ^ - offsetof(struct tcb , wval )) &3) != 3); #else + 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); - BUG_ON(((offsetof(struct ncr_reg, nc_sxfer) ^ - offsetof(struct tcb , sval )) &3) != 0); - BUG_ON(((offsetof(struct ncr_reg, nc_scntl3) ^ - offsetof(struct tcb , wval )) &3) != 0); #endif } @@ -7263,7 +7384,7 @@ lp = m_calloc_dma(sizeof(struct lcb), "LCB"); if (!lp) goto fail; + bzero(lp, sizeof(*lp)); - memset(lp, 0, sizeof(*lp)); tp->lp[ln] = lp; /* @@ -7275,10 +7396,10 @@ /* ** Initialize the CCB queue headers. */ + xpt_que_init(&lp->free_ccbq); + xpt_que_init(&lp->busy_ccbq); + xpt_que_init(&lp->wait_ccbq); + xpt_que_init(&lp->skip_ccbq); - INIT_LIST_HEAD(&lp->free_ccbq); - INIT_LIST_HEAD(&lp->busy_ccbq); - INIT_LIST_HEAD(&lp->wait_ccbq); - INIT_LIST_HEAD(&lp->skip_ccbq); /* ** Set max CCBs to 1 and use the default 1 entry @@ -7721,11 +7842,11 @@ if (np->multiplier > 2) { /* Poll bit 5 of stest4 for quadrupler */ int i = 20; while (!(INB(nc_stest4) & LCKFRQ) && --i > 0) + UDELAY (20); - udelay(20); if (!i) printk("%s: the chip cannot lock the frequency\n", ncr_name(np)); } else /* Wait 20 micro-seconds for doubler */ + UDELAY (20); - udelay(20); OUTB(nc_stest3, HSC); /* Halt the scsi clock */ OUTB(nc_scntl3, scntl3); OUTB(nc_stest1, (DBLEN|DBLSEL));/* Select clock multiplier */ @@ -7766,7 +7887,7 @@ OUTB (nc_stime1, gen); /* set to nominal delay of 1<host; + struct ncb *np; + struct tcb *tp; + struct lcb *lp; - struct ncb *np = ((struct host_data *) host->hostdata)->ncb; - struct tcb *tp = &np->target[device->id]; - struct lcb *lp = tp->lp[device->lun]; int numtags, depth_to_use; + 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. @@ -7884,10 +8013,6 @@ ** Since the queue depth is not tunable under Linux, ** we need to know this value in order not to ** announce stupid things to user. - ** - ** XXX(hch): As of Linux 2.6 it certainly _is_ tunable.. - ** In fact we just tuned it, or did I miss - ** something important? :) */ if (lp) { lp->numtags = lp->maxtags = numtags; @@ -7903,7 +8028,11 @@ return 0; } +/* +** Linux entry point of queuecommand() function +*/ + +int ncr53c8xx_queue_command (struct scsi_cmnd *cmd, void (* done)(struct scsi_cmnd *)) -static int ncr53c8xx_queue_command (struct scsi_cmnd *cmd, void (* done)(struct scsi_cmnd *)) { struct ncb *np = ((struct host_data *) cmd->device->host->hostdata)->ncb; unsigned long flags; @@ -7918,7 +8047,7 @@ cmd->__data_mapped = 0; cmd->__data_mapping = 0; + NCR_LOCK_NCB(np, flags); - spin_lock_irqsave(&np->smp_lock, flags); if ((sts = ncr_queue_command(np, cmd)) != DID_OK) { cmd->result = ScsiResult(sts, 0); @@ -7931,7 +8060,7 @@ printk("ncr53c8xx : command successfully queued\n"); #endif + NCR_UNLOCK_NCB(np, flags); - spin_unlock_irqrestore(&np->smp_lock, flags); if (sts != DID_OK) { unmap_scsi_data(np, cmd); @@ -7941,6 +8070,14 @@ return sts; } +/* +** Linux entry point of the interrupt handler. +** 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. +*/ + irqreturn_t ncr53c8xx_intr(int irq, void *dev_id, struct pt_regs * regs) { unsigned long flags; @@ -7955,42 +8092,58 @@ if (DEBUG_FLAGS & DEBUG_TINY) printk ("["); + NCR_LOCK_NCB(np, flags); - spin_lock_irqsave(&np->smp_lock, flags); ncr_exception(np); done_list = np->done_list; np->done_list = NULL; + NCR_UNLOCK_NCB(np, flags); - spin_unlock_irqrestore(&np->smp_lock, flags); if (DEBUG_FLAGS & DEBUG_TINY) printk ("]\n"); + if (done_list) { + NCR_LOCK_SCSI_DONE(done_list->device->host, flags); + ncr_flush_done_cmds(done_list); + NCR_UNLOCK_SCSI_DONE(done_list->device->host, flags); + } - if (done_list) - ncr_flush_done_cmds(done_list); return IRQ_HANDLED; } +/* +** Linux entry point of the timer handler +*/ + static void ncr53c8xx_timeout(unsigned long npref) { + struct ncb *np = (struct ncb *) npref; + unsigned long flags; + struct scsi_cmnd *done_list; - struct ncb *np = (struct ncb *) npref; - unsigned long flags; - struct scsi_cmnd *done_list; + NCR_LOCK_NCB(np, flags); + ncr_timeout(np); + done_list = np->done_list; + np->done_list = NULL; + NCR_UNLOCK_NCB(np, flags); - spin_lock_irqsave(&np->smp_lock, flags); - ncr_timeout(np); - done_list = np->done_list; - np->done_list = NULL; - spin_unlock_irqrestore(&np->smp_lock, flags); + if (done_list) { + NCR_LOCK_SCSI_DONE(done_list->device->host, flags); + ncr_flush_done_cmds(done_list); + NCR_UNLOCK_SCSI_DONE(done_list->device->host, flags); + } - if (done_list) - ncr_flush_done_cmds(done_list); } +/* +** Linux entry point of reset() function +*/ + +int ncr53c8xx_bus_reset(struct scsi_cmnd *cmd) -static int ncr53c8xx_bus_reset(struct scsi_cmnd *cmd) { struct ncb *np = ((struct host_data *) cmd->device->host->hostdata)->ncb; int sts; unsigned long flags; struct scsi_cmnd *done_list; + NCR_LOCK_NCB(np, flags); + /* * If the mid-level driver told us reset is synchronous, it seems * that we must call the done() callback for the involved command, @@ -7998,20 +8151,22 @@ * before returning SUCCESS. */ - spin_lock_irqsave(&np->smp_lock, flags); sts = ncr_reset_bus(np, cmd, 1); done_list = np->done_list; np->done_list = NULL; + NCR_UNLOCK_NCB(np, flags); - spin_unlock_irqrestore(&np->smp_lock, flags); ncr_flush_done_cmds(done_list); return sts; } +/* +** Linux entry point of abort() function +*/ + +int ncr53c8xx_abort(struct scsi_cmnd *cmd) -#if 0 /* unused and broken */ -static int ncr53c8xx_abort(struct scsi_cmnd *cmd) { struct ncb *np = ((struct host_data *) cmd->device->host->hostdata)->ncb; int sts; @@ -8047,7 +8202,6 @@ return sts; } -#endif /* @@ -8132,23 +8286,291 @@ #undef next_wcmd +#ifdef SCSI_NCR_PROC_INFO_SUPPORT + +/*========================================================================= +** Proc file system stuff +** +** A read operation returns profile information. +** A write operation is a control command. +** The string is parsed in the driver code and the command is passed +** to the ncr_usercmd() function. +**========================================================================= +*/ + +#ifdef SCSI_NCR_USER_COMMAND_SUPPORT + +#define is_digit(c) ((c) >= '0' && (c) <= '9') +#define digit_to_bin(c) ((c) - '0') +#define is_space(c) ((c) == ' ' || (c) == '\t') + +static int skip_spaces(char *ptr, int len) +{ + int cnt, c; + + for (cnt = len; cnt > 0 && (c = *ptr++) && is_space(c); cnt--); + + return (len - cnt); +} + +static int get_int_arg(char *ptr, int len, u_long *pv) +{ + int cnt, c; + u_long v; + + for (v = 0, cnt = len; cnt > 0 && (c = *ptr++) && is_digit(c); cnt--) { + v = (v * 10) + digit_to_bin(c); + } + + if (pv) + *pv = v; + + return (len - cnt); +} + +static int is_keyword(char *ptr, int len, char *verb) -static ssize_t show_ncr53c8xx_revision(struct class_device *dev, char *buf) { + int verb_len = strlen(verb); + + if (len >= strlen(verb) && !memcmp(verb, ptr, verb_len)) + return verb_len; + else + return 0; + +} + +#define SKIP_SPACES(min_spaces) \ + if ((arg_len = skip_spaces(ptr, len)) < (min_spaces)) \ + return -EINVAL; \ + ptr += arg_len; len -= arg_len; + +#define GET_INT_ARG(v) \ + if (!(arg_len = get_int_arg(ptr, len, &(v)))) \ + return -EINVAL; \ + ptr += arg_len; len -= arg_len; + + +/* +** Parse a control command +*/ + +static int ncr_user_command(struct ncb *np, char *buffer, int length) +{ + char *ptr = buffer; + int len = length; + struct usrcmd *uc = &np->user; + int arg_len; + u_long target; + + bzero(uc, sizeof(*uc)); + + if (len > 0 && ptr[len-1] == '\n') + --len; + + if ((arg_len = is_keyword(ptr, len, "setsync")) != 0) + uc->cmd = UC_SETSYNC; + else if ((arg_len = is_keyword(ptr, len, "settags")) != 0) + 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) + uc->cmd = UC_SETDEBUG; + else if ((arg_len = is_keyword(ptr, len, "setflag")) != 0) + uc->cmd = UC_SETFLAG; + else + arg_len = 0; + +#ifdef DEBUG_PROC_INFO +printk("ncr_user_command: arg_len=%d, cmd=%ld\n", arg_len, uc->cmd); +#endif + + if (!arg_len) + return -EINVAL; + ptr += arg_len; len -= arg_len; + + switch(uc->cmd) { + case UC_SETSYNC: + case UC_SETTAGS: + case UC_SETWIDE: + case UC_SETFLAG: + SKIP_SPACES(1); + if ((arg_len = is_keyword(ptr, len, "all")) != 0) { + ptr += arg_len; len -= arg_len; + uc->target = ~0; + } else { + 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 +printk("ncr_user_command: data=%ld\n", uc->data); +#endif + break; + case UC_SETORDER: + SKIP_SPACES(1); + if ((arg_len = is_keyword(ptr, len, "simple"))) + uc->data = M_SIMPLE_TAG; + else if ((arg_len = is_keyword(ptr, len, "ordered"))) + uc->data = M_ORDERED_TAG; + else if ((arg_len = is_keyword(ptr, len, "default"))) + uc->data = 0; + else + return -EINVAL; + break; + case UC_SETDEBUG: + while (len > 0) { + SKIP_SPACES(1); + if ((arg_len = is_keyword(ptr, len, "alloc"))) + uc->data |= DEBUG_ALLOC; + else if ((arg_len = is_keyword(ptr, len, "phase"))) + uc->data |= DEBUG_PHASE; + else if ((arg_len = is_keyword(ptr, len, "queue"))) + uc->data |= DEBUG_QUEUE; + else if ((arg_len = is_keyword(ptr, len, "result"))) + uc->data |= DEBUG_RESULT; + else if ((arg_len = is_keyword(ptr, len, "scatter"))) + uc->data |= DEBUG_SCATTER; + else if ((arg_len = is_keyword(ptr, len, "script"))) + uc->data |= DEBUG_SCRIPT; + else if ((arg_len = is_keyword(ptr, len, "tiny"))) + uc->data |= DEBUG_TINY; + else if ((arg_len = is_keyword(ptr, len, "timing"))) + uc->data |= DEBUG_TIMING; + else if ((arg_len = is_keyword(ptr, len, "nego"))) + uc->data |= DEBUG_NEGO; + else if ((arg_len = is_keyword(ptr, len, "tags"))) + uc->data |= DEBUG_TAGS; + else + return -EINVAL; + ptr += arg_len; len -= arg_len; + } +#ifdef DEBUG_PROC_INFO +printk("ncr_user_command: data=%ld\n", uc->data); +#endif + break; + case UC_SETFLAG: + while (len > 0) { + SKIP_SPACES(1); + if ((arg_len = is_keyword(ptr, len, "trace"))) + uc->data |= UF_TRACE; + else if ((arg_len = is_keyword(ptr, len, "no_disc"))) + uc->data |= UF_NODISC; + else + return -EINVAL; + ptr += arg_len; len -= arg_len; + } + break; + default: + break; + } + + if (len) + return -EINVAL; + else { + unsigned long flags; + + NCR_LOCK_NCB(np, flags); + ncr_usercmd (np); + NCR_UNLOCK_NCB(np, flags); + } + return length; +} + +#endif /* SCSI_NCR_USER_COMMAND_SUPPORT */ + + +#ifdef SCSI_NCR_USER_INFO_SUPPORT +/* +** Copy formatted information into the input buffer. +*/ + +static int ncr_host_info(struct ncb *np, char *ptr, off_t offset, int len) +{ + struct info_str info; + + info.buffer = ptr; + info.length = len; + info.offset = offset; + info.pos = 0; + + copy_info(&info, " Chip NCR53C720, revision id 0x%x, IRQ %d\n", + np->revision_id, (int) np->irq); + copy_info(&info, " Synchronous period factor %d, " + "max commands per lun %d\n", + (int) np->minsync, MAX_TAGS); + + if (driver_setup.debug || driver_setup.verbose > 1) { + copy_info(&info, " Debug flags 0x%x, verbosity level %d\n", + driver_setup.debug, driver_setup.verbose); + } + + return info.pos > info.offset? info.pos - info.offset : 0; +} + +#endif /* SCSI_NCR_USER_INFO_SUPPORT */ + +/* +** Entry point of the scsi proc fs of the driver. +** - func = 0 means read (returns profile data) +** - func = 1 means write (parse user control command) +*/ + +static int ncr53c8xx_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t offset, + int length, int func) +{ + struct host_data *host_data; + struct ncb *ncb = NULL; + int retv; + +#ifdef DEBUG_PROC_INFO +printk("ncr53c8xx_proc_info: hostno=%d, func=%d\n", host->host_no, func); +#endif + + host_data = (struct host_data *) host->hostdata; + ncb = host_data->ncb; + + if (func) { +#ifdef SCSI_NCR_USER_COMMAND_SUPPORT + retv = ncr_user_command(ncb, buffer, length); +#else + retv = -EINVAL; +#endif + } + else { + if (start) + *start = buffer; +#ifdef SCSI_NCR_USER_INFO_SUPPORT + retv = ncr_host_info(ncb, buffer, offset, length); +#else + retv = -EINVAL; +#endif + } + + return retv; +} + +/*========================================================================= +** End of proc file system stuff +**========================================================================= +*/ +#endif + - struct Scsi_Host *host = class_to_shost(dev); - struct host_data *host_data = (struct host_data *)host->hostdata; - - return snprintf(buf, 20, "0x%x\n", host_data->ncb->revision_id); -} - -static struct class_device_attribute ncr53c8xx_revision_attr = { - .attr = { .name = "revision", .mode = S_IRUGO, }, - .show = show_ncr53c8xx_revision, -}; - -static struct class_device_attribute *ncr53c8xx_host_attrs[] = { - &ncr53c8xx_revision_attr, - NULL -}; /*========================================================== ** @@ -8161,7 +8583,7 @@ MODULE_PARM(ncr53c8xx, "s"); #endif +int __init ncr53c8xx_setup(char *str) -static int __init ncr53c8xx_setup(char *str) { return sym53c8xx__setup(str); } @@ -8170,6 +8592,17 @@ __setup("ncr53c8xx=", ncr53c8xx_setup); #endif +/*========================================================== +** +** Entry point for info() function +** +**========================================================== +*/ +const char *ncr53c8xx_info (struct Scsi_Host *host) +{ + return SCSI_NCR_DRIVER_NAME; +} + /* * Host attach and initialisations. @@ -8189,14 +8622,13 @@ u_long flags = 0; int i; +#ifdef SCSI_NCR_PROC_INFO_SUPPORT + tpnt->proc_info = ncr53c8xx_proc_info, +#endif + tpnt->info = ncr53c8xx_info; - if (!tpnt->name) - tpnt->name = SCSI_NCR_DRIVER_NAME; - if (!tpnt->shost_attrs) - tpnt->shost_attrs = ncr53c8xx_host_attrs; - tpnt->queuecommand = ncr53c8xx_queue_command; tpnt->slave_configure = ncr53c8xx_slave_configure; + tpnt->eh_bus_reset_handler = ncr53c8xx_bus_reset; - tpnt->eh_bus_reset_handler = ncr53c8xx_bus_reset; tpnt->can_queue = SCSI_NCR_CAN_QUEUE; tpnt->this_id = 7; tpnt->sg_tablesize = SCSI_NCR_SG_TABLESIZE; @@ -8217,7 +8649,7 @@ np = __m_calloc_dma(device->dev, sizeof(struct ncb), "NCB"); if (!np) goto attach_error; + NCR_INIT_LOCK_NCB(np); - spin_lock_init(&np->smp_lock); np->dev = device->dev; np->p_ncb = vtobus(np); host_data->ncb = np; @@ -8284,6 +8716,7 @@ ncr_name(np)); } + /* Fill Linux host instance structure */ instance->max_channel = 0; instance->this_id = np->myaddr; instance->max_id = np->maxwide ? 16 : 8; @@ -8364,11 +8797,11 @@ * Process the reset exception if interrupts are not enabled yet. * Then enable disconnects. */ + NCR_LOCK_NCB(np, flags); - spin_lock_irqsave(&np->smp_lock, flags); if (ncr_reset_scsi_bus(np, 0, driver_setup.settle_delay) != 0) { printk(KERN_ERR "%s: FATAL ERROR: CHECK SCSI BUS - CABLES, TERMINATION, DEVICE POWER etc.!\n", ncr_name(np)); + NCR_UNLOCK_NCB(np, flags); - spin_unlock_irqrestore(&np->smp_lock, flags); goto attach_error; } ncr_exception(np); @@ -8382,7 +8815,7 @@ if (driver_setup.settle_delay > 2) { printk(KERN_INFO "%s: waiting %d seconds for scsi devices to settle...\n", ncr_name(np), driver_setup.settle_delay); + MDELAY (1000 * driver_setup.settle_delay); - mdelay(1000 * driver_setup.settle_delay); } /* start the timeout daemon */ @@ -8394,7 +8827,7 @@ np->order = M_SIMPLE_TAG; #endif + NCR_UNLOCK_NCB(np, flags); - spin_unlock_irqrestore(&np->smp_lock, flags); return instance; reverted: --- b/drivers/scsi/ncr53c8xx.h 2004-09-26 11:11:46 -07:00 +++ a/drivers/scsi/ncr53c8xx.h 2004-09-26 11:11:46 -07:00 @@ -44,6 +44,8 @@ #include +typedef u_long vm_offset_t; + #include "sym53c8xx_defs.h" /* reverted: --- b/drivers/scsi/qla1280.c 2004-09-26 11:11:47 -07:00 +++ a/drivers/scsi/qla1280.c 2004-09-26 11:11:47 -07:00 @@ -4641,7 +4641,6 @@ #if LINUX_VERSION_CODE >= 0x020600 static struct scsi_host_template qla1280_driver_template = { - .module = THIS_MODULE, .proc_name = "qla1280", .name = "Qlogic ISP 1280/12160", .info = qla1280_info, diff -u b/drivers/scsi/qla2xxx/qla_dbg.c b/drivers/scsi/qla2xxx/qla_dbg.c --- b/drivers/scsi/qla2xxx/qla_dbg.c 2004-09-26 11:11:46 -07:00 +++ b/drivers/scsi/qla2xxx/qla_dbg.c 2004-09-26 11:13:18 -07:00 @@ -712,6 +712,7 @@ /* Reset the ISP. */ WRT_REG_WORD(®->ctrl_status, CSR_ISP_SOFT_RESET); + RD_REG_WORD(®->ctrl_status); /* PCI Posting. */ } for (cnt = 30000; RD_MAILBOX_REG(ha, reg, 0) != 0 && @@ -745,6 +746,7 @@ /* Release RISC. */ WRT_REG_WORD(®->hccr, HCCR_RELEASE_RISC); + RD_REG_WORD(®->hccr); /* PCI Posting. */ } } diff -u b/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c --- b/drivers/scsi/qla2xxx/qla_init.c 2004-09-26 11:11:46 -07:00 +++ b/drivers/scsi/qla2xxx/qla_init.c 2004-09-26 11:13:18 -07:00 @@ -463,10 +463,13 @@ } WRT_REG_WORD(®->hccr, HCCR_CLR_RISC_INT); + RD_REG_WORD(®->hccr); /* PCI Posting. */ WRT_REG_WORD(®->hccr, HCCR_CLR_HOST_INT); + RD_REG_WORD(®->hccr); /* PCI Posting. */ /* Reset ISP chip. */ WRT_REG_WORD(®->ctrl_status, CSR_ISP_SOFT_RESET); + RD_REG_WORD(®->ctrl_status); /* PCI Posting. */ /* Wait for RISC to recover from reset. */ if (IS_QLA2100(ha) || IS_QLA2200(ha) || IS_QLA2300(ha)) { @@ -487,6 +490,7 @@ /* Reset RISC processor. */ WRT_REG_WORD(®->hccr, HCCR_RESET_RISC); + RD_REG_WORD(®->hccr); /* PCI Posting. */ WRT_REG_WORD(®->semaphore, 0); @@ -555,6 +559,7 @@ /* Reset ISP chip. */ WRT_REG_WORD(®->ctrl_status, CSR_ISP_SOFT_RESET); + RD_REG_WORD(®->ctrl_status); /* PCI Posting. */ /* * We need to have a delay here since the card will not respond while @@ -576,7 +581,9 @@ /* Reset RISC processor. */ WRT_REG_WORD(®->hccr, HCCR_RESET_RISC); + RD_REG_WORD(®->hccr); /* PCI Posting. */ WRT_REG_WORD(®->hccr, HCCR_RELEASE_RISC); + RD_REG_WORD(®->hccr); /* PCI Posting. */ /* Workaround for QLA2312 PCI parity error */ if (IS_QLA2100(ha) || IS_QLA2200(ha) || IS_QLA2300(ha)) { diff -u b/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c --- b/drivers/scsi/qla2xxx/qla_os.c 2004-09-26 11:11:47 -07:00 +++ b/drivers/scsi/qla2xxx/qla_os.c 2004-09-26 11:13:18 -07:00 @@ -2892,19 +2892,6 @@ continue; } - /* get consistent memory allocated for init control block */ - ha->init_cb = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, - &ha->init_cb_dma); - if (ha->init_cb == NULL) { - qla_printk(KERN_WARNING, ha, - "Memory Allocation failed - init_cb\n"); - - qla2x00_mem_free(ha); - msleep(100); - - continue; - } - memset(ha->init_cb, 0, sizeof(init_cb_t)); /* Get consistent memory allocated for Get Port Database cmd */ ha->iodesc_pd = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, @@ -2996,6 +2983,21 @@ memset(ha->ct_sns, 0, sizeof(struct ct_sns_pkt)); } + /* Get consistent memory allocated for Get Port Database cmd */ + ha->iodesc_pd = pci_alloc_consistent(ha->pdev, + PORT_DATABASE_SIZE, &ha->iodesc_pd_dma); + if (ha->iodesc_pd == NULL) { + /* error */ + qla_printk(KERN_WARNING, ha, + "Memory Allocation failed - iodesc_pd\n"); + + qla2x00_mem_free(ha); + msleep(100); + + continue; + } + memset(ha->iodesc_pd, 0, PORT_DATABASE_SIZE); + /* Done all allocations without any error. */ status = 0; reverted: --- b/drivers/scsi/qlogicfc.c 2004-09-26 11:11:46 -07:00 +++ a/drivers/scsi/qlogicfc.c 2004-09-26 11:11:46 -07:00 @@ -815,11 +815,9 @@ some time before recognizing it is attached to a fabric */ #if ISP2x00_FABRIC + for (wait_time = jiffies + 5 * HZ; time_before(jiffies, wait_time);) { + barrier(); + cpu_relax(); - if (hosts) { - for (wait_time = jiffies + 5 * HZ; time_before(jiffies, wait_time);) { - barrier(); - cpu_relax(); - } } #endif diff -u b/drivers/scsi/scsi_devinfo.c b/drivers/scsi/scsi_devinfo.c --- b/drivers/scsi/scsi_devinfo.c 2004-09-26 11:11:46 -07:00 +++ b/drivers/scsi/scsi_devinfo.c 2004-09-26 11:13:18 -07:00 @@ -185,7 +185,6 @@ {"SGI", "RAID3", "*", BLIST_SPARSELUN}, {"SGI", "RAID5", "*", BLIST_SPARSELUN}, {"SGI", "TP9100", "*", BLIST_REPORTLUN2}, - {"SGI", "Universal Xport", "*", BLIST_NO_ULD_ATTACH}, {"SMSC", "USB 2 HS-CF", NULL, BLIST_SPARSELUN | BLIST_INQUIRY_36}, {"SONY", "CD-ROM CDU-8001", NULL, BLIST_BORKEN}, {"SONY", "TSL", NULL, BLIST_FORCELUN}, /* DDS3 & DDS4 autoloaders */ reverted: --- b/drivers/scsi/scsi_ioctl.c 2004-09-26 11:11:46 -07:00 +++ a/drivers/scsi/scsi_ioctl.c 2004-09-26 11:11:46 -07:00 @@ -20,7 +20,6 @@ #include #include #include -#include #include "scsi_logging.h" @@ -457,51 +456,3 @@ } return -EINVAL; } - -/* - * the scsi_nonblock_ioctl() function is designed for ioctls which may - * be executed even if the device is in recovery. - */ -int scsi_nonblockable_ioctl(struct scsi_device *sdev, int cmd, - void __user *arg, struct file *filp) -{ - int val, result; - - /* The first set of iocts may be executed even if we're doing - * error processing, as long as the device was opened - * non-blocking */ - if (filp && filp->f_flags & O_NONBLOCK) { - if (test_bit(SHOST_RECOVERY, - &sdev->host->shost_state)) - return -ENODEV; - } else if (!scsi_block_when_processing_errors(sdev)) - return -ENODEV; - - switch (cmd) { - case SG_SCSI_RESET: - result = get_user(val, (int __user *)arg); - if (result) - return result; - if (val == SG_SCSI_RESET_NOTHING) - return 0; - switch (val) { - case SG_SCSI_RESET_DEVICE: - val = SCSI_TRY_RESET_DEVICE; - break; - case SG_SCSI_RESET_BUS: - val = SCSI_TRY_RESET_BUS; - break; - case SG_SCSI_RESET_HOST: - val = SCSI_TRY_RESET_HOST; - break; - default: - return -EINVAL; - } - if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO)) - return -EACCES; - return (scsi_reset_provider(sdev, val) == - SUCCESS) ? 0 : -EIO; - } - return -ENODEV; -} -EXPORT_SYMBOL(scsi_nonblockable_ioctl); diff -u b/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c --- b/drivers/scsi/scsi_lib.c 2004-09-26 11:11:46 -07:00 +++ b/drivers/scsi/scsi_lib.c 2004-09-26 11:13:18 -07:00 @@ -365,7 +365,7 @@ unsigned long flags; spin_lock_irqsave(shost->host_lock, flags); - current_sdev->sdev_target->starget_sdev_user = NULL; + scsi_target(current_sdev)->starget_sdev_user = NULL; spin_unlock_irqrestore(shost->host_lock, flags); /* @@ -377,7 +377,7 @@ blk_run_queue(current_sdev->request_queue); spin_lock_irqsave(shost->host_lock, flags); - if (current_sdev->sdev_target->starget_sdev_user) + if (scsi_target(current_sdev)->starget_sdev_user) goto out; list_for_each_entry_safe(sdev, tmp, ¤t_sdev->same_target_siblings, same_target_siblings) { @@ -1253,10 +1253,10 @@ if (!scsi_host_queue_ready(q, shost, sdev)) goto not_ready; if (sdev->single_lun) { - if (sdev->sdev_target->starget_sdev_user && - sdev->sdev_target->starget_sdev_user != sdev) + if (scsi_target(sdev)->starget_sdev_user && + scsi_target(sdev)->starget_sdev_user != sdev) goto not_ready; - sdev->sdev_target->starget_sdev_user = sdev; + scsi_target(sdev)->starget_sdev_user = sdev; } shost->host_busy++; @@ -1753,0 +1754,28 @@ + +static int +device_quiesce_fn(struct device *dev, void *data) +{ + scsi_device_quiesce(to_scsi_device(dev)); + return 0; +} + +void +scsi_target_quiesce(struct scsi_target *starget) +{ + device_for_each_child(&starget->dev, NULL, device_quiesce_fn); +} +EXPORT_SYMBOL(scsi_target_quiesce); + +static int +device_resume_fn(struct device *dev, void *data) +{ + scsi_device_resume(to_scsi_device(dev)); + return 0; +} + +void +scsi_target_resume(struct scsi_target *starget) +{ + device_for_each_child(&starget->dev, NULL, device_resume_fn); +} +EXPORT_SYMBOL(scsi_target_resume); diff -u b/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c --- b/drivers/scsi/scsi_scan.c 2004-09-26 11:11:46 -07:00 +++ b/drivers/scsi/scsi_scan.c 2004-09-26 11:13:18 -07:00 @@ -202,11 +202,11 @@ static struct scsi_device *scsi_alloc_sdev(struct Scsi_Host *shost, uint channel, uint id, uint lun, void *hostdata) { - struct scsi_device *sdev, *device; + struct scsi_device *sdev; unsigned long flags; - int display_failure_msg = 1, ret; - sdev = kmalloc(sizeof(*sdev) + shost->transportt->size, GFP_ATOMIC); + sdev = kmalloc(sizeof(*sdev) + shost->transportt->device_size, + GFP_ATOMIC); if (!sdev) goto out; @@ -253,79 +253,32 @@ scsi_adjust_queue_depth(sdev, 0, sdev->host->cmd_per_lun); if (shost->hostt->slave_alloc) { - ret = shost->hostt->slave_alloc(sdev); - if (ret) { - /* - * if LLDD reports slave not present, don't clutter - * console with alloc failure messages - */ - if (ret == -ENXIO) - display_failure_msg = 0; + if (shost->hostt->slave_alloc(sdev)) goto out_free_queue; - } } - if (shost->transportt->setup) { - if (shost->transportt->setup(sdev)) + if (shost->transportt->device_setup) { + if (shost->transportt->device_setup(sdev)) goto out_cleanup_slave; } - if (get_device(&sdev->host->shost_gendev)) { + if (get_device(&sdev->host->shost_gendev) == NULL || + scsi_sysfs_device_initialize(sdev) != 0) + goto out_cleanup_slave; - device_initialize(&sdev->sdev_gendev); - sdev->sdev_gendev.parent = &sdev->host->shost_gendev; - sdev->sdev_gendev.bus = &scsi_bus_type; - sdev->sdev_gendev.release = scsi_device_dev_release; - sprintf(sdev->sdev_gendev.bus_id,"%d:%d:%d:%d", - sdev->host->host_no, sdev->channel, sdev->id, - sdev->lun); - class_device_initialize(&sdev->sdev_classdev); - sdev->sdev_classdev.dev = &sdev->sdev_gendev; - sdev->sdev_classdev.class = &sdev_class; - snprintf(sdev->sdev_classdev.class_id, BUS_ID_SIZE, - "%d:%d:%d:%d", sdev->host->host_no, - sdev->channel, sdev->id, sdev->lun); + /* NOTE: this target initialisation code depends critically on + * lun scanning being sequential. */ + if (scsi_sysfs_target_initialize(sdev)) + goto out_remove_siblings; - class_device_initialize(&sdev->transport_classdev); - sdev->transport_classdev.dev = &sdev->sdev_gendev; - sdev->transport_classdev.class = sdev->host->transportt->class; - snprintf(sdev->transport_classdev.class_id, BUS_ID_SIZE, - "%d:%d:%d:%d", sdev->host->host_no, - sdev->channel, sdev->id, sdev->lun); - } else - goto out_cleanup_transport; + return sdev; - /* - * If there are any same target siblings, add this to the - * sibling list - */ +out_remove_siblings: spin_lock_irqsave(shost->host_lock, flags); - list_for_each_entry(device, &shost->__devices, siblings) { - if (device->id == sdev->id && - device->channel == sdev->channel) { - list_add_tail(&sdev->same_target_siblings, - &device->same_target_siblings); - sdev->scsi_level = device->scsi_level; - break; - } - } - - /* - * If there wasn't another lun already configured at this - * target, then default this device to SCSI_2 until we - * know better - */ - if (!sdev->scsi_level) - sdev->scsi_level = SCSI_2; - - list_add_tail(&sdev->siblings, &shost->__devices); + list_del(&sdev->siblings); + list_del(&sdev->same_target_siblings); spin_unlock_irqrestore(shost->host_lock, flags); - return sdev; - -out_cleanup_transport: - if (shost->transportt->cleanup) - shost->transportt->cleanup(sdev); out_cleanup_slave: if (shost->hostt->slave_destroy) shost->hostt->slave_destroy(sdev); @@ -334,8 +287,7 @@ out_free_dev: kfree(sdev); out: - if (display_failure_msg) - printk(ALLOC_FAILURE_MSG, __FUNCTION__); + printk(ALLOC_FAILURE_MSG, __FUNCTION__); return NULL; } @@ -510,10 +462,6 @@ **/ static int scsi_add_lun(struct scsi_device *sdev, char *inq_result, int *bflags) { - struct scsi_device *sdev_sibling; - struct scsi_target *starget; - unsigned long flags; - /* * XXX do not save the inquiry, since it can change underneath us, * save just vendor/model/rev. @@ -543,8 +491,7 @@ */ inq_result[0] = TYPE_ROM; inq_result[1] |= 0x80; /* removable */ - } else if (*bflags & BLIST_NO_ULD_ATTACH) - sdev->no_uld_attach = 1; + } switch (sdev->type = (inq_result[0] & 0x1f)) { case TYPE_TAPE: @@ -623,40 +570,9 @@ if (*bflags & BLIST_NOSTARTONADD) sdev->no_start_on_add = 1; - /* - * If we need to allow I/O to only one of the luns attached to - * this target id at a time set single_lun, and allocate or modify - * sdev_target. - */ - if (*bflags & BLIST_SINGLELUN) { + if (*bflags & BLIST_SINGLELUN) sdev->single_lun = 1; - spin_lock_irqsave(sdev->host->host_lock, flags); - starget = NULL; - /* - * Search for an existing target for this sdev. - */ - list_for_each_entry(sdev_sibling, &sdev->same_target_siblings, - same_target_siblings) { - if (sdev_sibling->sdev_target != NULL) { - starget = sdev_sibling->sdev_target; - break; - } - } - if (!starget) { - starget = kmalloc(sizeof(*starget), GFP_ATOMIC); - if (!starget) { - printk(ALLOC_FAILURE_MSG, __FUNCTION__); - spin_unlock_irqrestore(sdev->host->host_lock, - flags); - return SCSI_SCAN_NO_RESPONSE; - } - starget->starget_refcnt = 0; - starget->starget_sdev_user = NULL; - } - starget->starget_refcnt++; - sdev->sdev_target = starget; - spin_unlock_irqrestore(sdev->host->host_lock, flags); - } + sdev->use_10_for_rw = 1; @@ -796,8 +712,6 @@ } else { if (sdev->host->hostt->slave_destroy) sdev->host->hostt->slave_destroy(sdev); - if (sdev->host->transportt->cleanup) - sdev->host->transportt->cleanup(sdev); put_device(&sdev->sdev_gendev); } out: @@ -1357,6 +1271,4 @@ if (sdev->host->hostt->slave_destroy) sdev->host->hostt->slave_destroy(sdev); - if (sdev->host->transportt->cleanup) - sdev->host->transportt->cleanup(sdev); put_device(&sdev->sdev_gendev); } diff -u b/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c --- b/drivers/scsi/scsi_sysfs.c 2004-09-26 11:11:45 -07:00 +++ b/drivers/scsi/scsi_sysfs.c 2004-09-26 11:13:18 -07:00 @@ -153,25 +153,36 @@ struct scsi_device *sdev; struct device *parent; unsigned long flags; + int delete; parent = dev->parent; sdev = to_scsi_device(dev); spin_lock_irqsave(sdev->host->host_lock, flags); + /* If we're the last LUN on the target, destroy the target */ + delete = list_empty(&sdev->same_target_siblings); list_del(&sdev->siblings); list_del(&sdev->same_target_siblings); list_del(&sdev->starved_entry); - if (sdev->single_lun && --sdev->sdev_target->starget_refcnt == 0) - kfree(sdev->sdev_target); spin_unlock_irqrestore(sdev->host->host_lock, flags); + if (delete) { + struct scsi_target *starget = to_scsi_target(parent); + if (!starget->create) { + device_del(parent); + if (starget->transport_classdev.class) + class_device_unregister(&starget->transport_classdev); + } + put_device(parent); + } if (sdev->request_queue) scsi_free_queue(sdev->request_queue); kfree(sdev->inquiry); kfree(sdev); - put_device(parent); + if (parent) + put_device(parent); } struct class sdev_class = { @@ -183,8 +194,6 @@ static int scsi_bus_match(struct device *dev, struct device_driver *gendrv) { struct scsi_device *sdp = to_scsi_device(dev); - if (sdp->no_uld_attach) - return 0; return (sdp->inq_periph_qual == SCSI_INQ_PQ_CON)? 1: 0; } @@ -432,6 +441,14 @@ return device_create_file(dev, attr); } +static void scsi_target_dev_release(struct device *dev) +{ + struct scsi_target *starget = to_scsi_target(dev); + struct device *parent = dev->parent; + kfree(starget); + put_device(parent); +} + /** * scsi_sysfs_add_sdev - add scsi device to sysfs * @sdev: scsi_device to add @@ -442,13 +459,55 @@ int scsi_sysfs_add_sdev(struct scsi_device *sdev) { struct class_device_attribute **attrs; - int error, i; + struct scsi_target *starget = sdev->sdev_target; + struct Scsi_Host *shost = sdev->host; + int error, i, create; + unsigned long flags; + + spin_lock_irqsave(shost->host_lock, flags); + create = starget->create; + starget->create = 0; + spin_unlock_irqrestore(shost->host_lock, flags); + + if (create) { + error = device_add(&starget->dev); + if (error) { + printk(KERN_ERR "Target device_add failed\n"); + return error; + } + if (starget->transport_classdev.class) { + int i; + struct class_device_attribute **attrs = + sdev->host->transportt->target_attrs; + + error = class_device_add(&starget->transport_classdev); + if (error) { + dev_printk(KERN_ERR, &starget->dev, + "Target transport add failed\n"); + return error; + } + + /* take a reference for the transport_classdev; this + * is released by the transport_class .release */ + get_device(&starget->dev); + for (i = 0; attrs[i]; i++) { + error = class_device_create_file(&starget->transport_classdev, + attrs[i]); + if (error) { + dev_printk(KERN_ERR, &starget->dev, + "Target transport attr add failed\n"); + return error; + } + } + } + } if ((error = scsi_device_set_state(sdev, SDEV_RUNNING)) != 0) return error; error = device_add(&sdev->sdev_gendev); if (error) { + put_device(sdev->sdev_gendev.parent); printk(KERN_INFO "error 1\n"); return error; } @@ -461,7 +520,6 @@ /* take a reference for the sdev_classdev; this is * released by the sdev_class .release */ get_device(&sdev->sdev_gendev); - if (sdev->transport_classdev.class) { error = class_device_add(&sdev->transport_classdev); if (error) @@ -496,7 +554,7 @@ } if (sdev->transport_classdev.class) { - attrs = sdev->host->transportt->attrs; + attrs = sdev->host->transportt->device_attrs; for (i = 0; attrs[i]; i++) { error = class_device_create_file(&sdev->transport_classdev, attrs[i]); @@ -540,8 +598,6 @@ scsi_device_set_state(sdev, SDEV_DEL); if (sdev->host->hostt->slave_destroy) sdev->host->hostt->slave_destroy(sdev); - if (sdev->host->transportt->cleanup) - sdev->host->transportt->cleanup(sdev); put_device(&sdev->sdev_gendev); out: @@ -628,6 +684,121 @@ } } + class_device_initialize(&shost->transport_classdev); + shost->transport_classdev.class = shost->transportt->host_class; + shost->transport_classdev.dev = &shost->shost_gendev; + snprintf(shost->transport_classdev.class_id, BUS_ID_SIZE, + "host%d", shost->host_no); + + if (shost->transport_classdev.class) { + struct class_device_attribute **attrs = + shost->transportt->host_attrs; + error = class_device_add(&shost->transport_classdev); + if (error) + return error; + /* take a reference for the transport_classdev; this + * is released by the transport_class .release */ + get_device(&shost->shost_gendev); + for (i = 0; attrs[i]; i++) { + error = class_device_create_file(&shost->transport_classdev, + attrs[i]); + if (error) + return error; + } + } + + return 0; +} + +int scsi_sysfs_device_initialize(struct scsi_device *sdev) +{ + device_initialize(&sdev->sdev_gendev); + sdev->sdev_gendev.bus = &scsi_bus_type; + sdev->sdev_gendev.release = scsi_device_dev_release; + sprintf(sdev->sdev_gendev.bus_id,"%d:%d:%d:%d", + sdev->host->host_no, sdev->channel, sdev->id, + sdev->lun); + + class_device_initialize(&sdev->sdev_classdev); + sdev->sdev_classdev.dev = &sdev->sdev_gendev; + sdev->sdev_classdev.class = &sdev_class; + snprintf(sdev->sdev_classdev.class_id, BUS_ID_SIZE, + "%d:%d:%d:%d", sdev->host->host_no, + sdev->channel, sdev->id, sdev->lun); + + class_device_initialize(&sdev->transport_classdev); + sdev->transport_classdev.dev = &sdev->sdev_gendev; + sdev->transport_classdev.class = sdev->host->transportt->device_class; + snprintf(sdev->transport_classdev.class_id, BUS_ID_SIZE, + "%d:%d:%d:%d", sdev->host->host_no, + sdev->channel, sdev->id, sdev->lun); + return 0; +} + +int scsi_sysfs_target_initialize(struct scsi_device *sdev) +{ + struct scsi_target *starget = NULL; + struct Scsi_Host *shost = sdev->host; + struct scsi_device *device; + struct device *dev = NULL; + unsigned long flags; + int create = 0; + + spin_lock_irqsave(shost->host_lock, flags); + /* + * Search for an existing target for this sdev. + */ + list_for_each_entry(device, &shost->__devices, siblings) { + if (device->id == sdev->id && + device->channel == sdev->channel) { + list_add_tail(&sdev->same_target_siblings, + &device->same_target_siblings); + sdev->scsi_level = device->scsi_level; + starget = device->sdev_target; + break; + } + } + + if (!starget) { + const int size = sizeof(*starget) + + shost->transportt->target_size; + starget = kmalloc(size, GFP_ATOMIC); + if (!starget) { + printk(KERN_ERR "%s: allocation failure\n", __FUNCTION__); + spin_unlock_irqrestore(shost->host_lock, + flags); + return -ENOMEM; + } + memset(starget, 0, size); + dev = &starget->dev; + device_initialize(dev); + dev->parent = &shost->shost_gendev; + dev->release = scsi_target_dev_release; + sprintf(dev->bus_id, "target%d:%d:%d", + shost->host_no, sdev->channel, sdev->id); + class_device_initialize(&starget->transport_classdev); + starget->transport_classdev.dev = &starget->dev; + starget->transport_classdev.class = shost->transportt->target_class; + snprintf(starget->transport_classdev.class_id, BUS_ID_SIZE, + "target%d:%d:%d", + shost->host_no, sdev->channel, sdev->id); + starget->id = sdev->id; + starget->channel = sdev->channel; + create = starget->create = 1; + /* + * If there wasn't another lun already configured at + * this target, then default this device to SCSI_2 + * until we know better + */ + sdev->scsi_level = SCSI_2; + } + get_device(&starget->dev); + sdev->sdev_gendev.parent = &starget->dev; + sdev->sdev_target = starget; + list_add_tail(&sdev->siblings, &shost->__devices); + spin_unlock_irqrestore(shost->host_lock, flags); + if (create && shost->transportt->target_setup) + shost->transportt->target_setup(starget); return 0; } diff -u b/drivers/scsi/sd.c b/drivers/scsi/sd.c --- b/drivers/scsi/sd.c 2004-09-26 11:11:46 -07:00 +++ b/drivers/scsi/sd.c 2004-09-26 11:13:18 -07:00 @@ -574,9 +574,8 @@ * may try and take the device offline, in which case all further * access to the device is prohibited. */ - error = scsi_nonblockable_ioctl(sdp, cmd, p, filp); - if (!scsi_block_when_processing_errors(sdp) || !error) - return error; + if (!scsi_block_when_processing_errors(sdp)) + return -ENODEV; if (cmd == HDIO_GETGEO) { if (!arg) reverted: --- b/drivers/scsi/sr_ioctl.c 2004-09-26 11:11:46 -07:00 +++ a/drivers/scsi/sr_ioctl.c 2004-09-26 11:11:46 -07:00 @@ -549,17 +549,5 @@ unsigned int cmd, unsigned long arg) { Scsi_CD *cd = cdi->handle; - int ret; - - ret = scsi_nonblockable_ioctl(cd->device, cmd, - (void __user *)arg, NULL); - /* - * ENODEV means that we didn't recognise the ioctl, or that we - * cannot execute it in the current device state. In either - * case fall through to scsi_ioctl, which will return ENDOEV again - * if it doesn't recognise the ioctl - */ - if (ret != -ENODEV) - return ret; return scsi_ioctl(cd->device, cmd, (void __user *)arg); } reverted: --- b/drivers/scsi/st.c 2004-09-26 11:11:46 -07:00 +++ a/drivers/scsi/st.c 2004-09-26 11:11:46 -07:00 @@ -40,16 +40,6 @@ #include #include -#include -#include -#include -#include -#include -#include -#include -#include - - /* The driver prints some debugging information on the console if DEBUG is defined and non-zero. */ #define DEBUG 0 @@ -66,6 +56,13 @@ #define DEBC(a) #endif + +#include "scsi.h" +#include + +#include +#include + #define ST_KILOBYTE 1024 #include "st_options.h" @@ -74,8 +71,8 @@ static int buffer_kbs; static int max_sg_segs; static int try_direct_io = TRY_DIRECT_IO; +static int try_rdio = TRUE; +static int try_wdio = TRUE; -static int try_rdio = 1; -static int try_wdio = 1; static int st_dev_max; static int st_nr_dev; @@ -240,7 +237,7 @@ /* If the device signature is on the list of incompatible drives, the function returns a pointer to the name of the correct driver (if known) */ +static char * st_incompatible(Scsi_Device* SDp) -static char * st_incompatible(struct scsi_device* SDp) { struct st_reject_data *rp; @@ -263,7 +260,7 @@ } /* Convert the result to success code */ +static int st_chk_result(Scsi_Tape *STp, Scsi_Request * SRpnt) -static int st_chk_result(Scsi_Tape *STp, struct scsi_request * SRpnt) { int result = SRpnt->sr_result; unsigned char *sense = SRpnt->sr_sense_buffer, scode; @@ -290,7 +287,7 @@ SRpnt->sr_cmnd[3], SRpnt->sr_cmnd[4], SRpnt->sr_cmnd[5], SRpnt->sr_bufflen); if (driver_byte(result) & DRIVER_SENSE) + print_req_sense("st", SRpnt); - scsi_print_req_sense("st", SRpnt); } else ) /* end DEB */ if (!(driver_byte(result) & DRIVER_SENSE) || ((sense[0] & 0x70) == 0x70 && @@ -303,7 +300,7 @@ SRpnt->sr_cmnd[0] != TEST_UNIT_READY)) { /* Abnormal conditions for tape */ if (driver_byte(result) & DRIVER_SENSE) { printk(KERN_WARNING "%s: Error with sense data: ", name); + print_req_sense("st", SRpnt); - scsi_print_req_sense("st", SRpnt); } else printk(KERN_WARNING "%s: Error %x (sugg. bt 0x%x, driver bt 0x%x, host bt 0x%x).\n", @@ -354,7 +351,7 @@ /* Wakeup from interrupt */ +static void st_sleep_done(Scsi_Cmnd * SCpnt) -static void st_sleep_done(struct scsi_cmnd * SCpnt) { int remainder; Scsi_Tape *STp = container_of(SCpnt->request->rq_disk->private_data, @@ -388,9 +385,9 @@ /* Do the scsi command. Waits until command performed if do_wait is true. Otherwise write_behind_check() is used to check that the command has finished. */ +static Scsi_Request * + st_do_scsi(Scsi_Request * SRpnt, Scsi_Tape * STp, unsigned char *cmd, int bytes, + int direction, int timeout, int retries, int do_wait) -static struct scsi_request * -st_do_scsi(struct scsi_request * SRpnt, Scsi_Tape * STp, unsigned char *cmd, - int bytes, int direction, int timeout, int retries, int do_wait) { unsigned char *bp; @@ -473,7 +470,7 @@ it messes up the block number). */ static int cross_eof(Scsi_Tape * STp, int forward) { + Scsi_Request *SRpnt; - struct scsi_request *SRpnt; unsigned char cmd[MAX_COMMAND_SIZE]; cmd[0] = SPACE; @@ -488,8 +485,8 @@ DEBC(printk(ST_DEB_MSG "%s: Stepping over filemark %s.\n", tape_name(STp), forward ? "forward" : "backward")); + SRpnt = st_do_scsi(NULL, STp, cmd, 0, SCSI_DATA_NONE, + STp->device->timeout, MAX_RETRIES, TRUE); - SRpnt = st_do_scsi(NULL, STp, cmd, 0, DMA_NONE, - STp->device->timeout, MAX_RETRIES, 1); if (!SRpnt) return (STp->buffer)->syscall_result; @@ -510,7 +507,7 @@ int offset, transfer, blks; int result; unsigned char cmd[MAX_COMMAND_SIZE]; + Scsi_Request *SRpnt; - struct scsi_request *SRpnt; ST_partstat *STps; if ((STp->buffer)->writing) { @@ -546,8 +543,8 @@ cmd[3] = blks >> 8; cmd[4] = blks; + SRpnt = st_do_scsi(NULL, STp, cmd, transfer, SCSI_DATA_WRITE, + STp->device->timeout, MAX_WRITE_RETRIES, TRUE); - SRpnt = st_do_scsi(NULL, STp, cmd, transfer, DMA_TO_DEVICE, - STp->device->timeout, MAX_WRITE_RETRIES, 1); if (!SRpnt) return (STp->buffer)->syscall_result; @@ -613,7 +610,7 @@ result = 0; if (!seek_next) { if (STps->eof == ST_FM_HIT) { + result = cross_eof(STp, FALSE); /* Back over the EOF hit */ - result = cross_eof(STp, 0); /* Back over the EOF hit */ if (!result) STps->eof = ST_NOEOF; else { @@ -637,7 +634,7 @@ /* Set the mode parameters */ static int set_mode_densblk(Scsi_Tape * STp, ST_mode * STm) { + int set_it = FALSE; - int set_it = 0; unsigned long arg; char *name = tape_name(STp); @@ -645,7 +642,7 @@ STm->default_density >= 0 && STm->default_density != STp->density) { arg = STm->default_density; + set_it = TRUE; - set_it = 1; } else arg = STp->density; arg <<= MT_ST_DENSITY_SHIFT; @@ -653,7 +650,7 @@ STm->default_blksize >= 0 && STm->default_blksize != STp->block_size) { arg |= STm->default_blksize; + set_it = TRUE; - set_it = 1; } else arg |= STp->block_size; if (set_it && @@ -668,7 +665,7 @@ } +/* Lock or unlock the drive door. Don't use when Scsi_Request allocated. */ -/* Lock or unlock the drive door. Don't use when scsi_request allocated. */ static int do_door_lock(Scsi_Tape * STp, int do_lock) { int retval, cmd; @@ -701,7 +698,7 @@ STps->rw = ST_IDLE; STps->eof = ST_NOEOF; STps->at_sm = 0; + STps->last_block_valid = FALSE; - STps->last_block_valid = 0; STps->drv_block = -1; STps->drv_file = -1; } @@ -725,17 +722,17 @@ static int test_ready(Scsi_Tape *STp, int do_wait) { int attentions, waits, max_wait, scode; + int retval = CHKRES_READY, new_session = FALSE; - int retval = CHKRES_READY, new_session = 0; unsigned char cmd[MAX_COMMAND_SIZE]; + Scsi_Request *SRpnt = NULL; - struct scsi_request *SRpnt = NULL; max_wait = do_wait ? ST_BLOCK_SECONDS : 0; for (attentions=waits=0; ; ) { memset((void *) &cmd[0], 0, MAX_COMMAND_SIZE); cmd[0] = TEST_UNIT_READY; + SRpnt = st_do_scsi(SRpnt, STp, cmd, 0, SCSI_DATA_NONE, + STp->long_timeout, MAX_READY_RETRIES, TRUE); - SRpnt = st_do_scsi(SRpnt, STp, cmd, 0, DMA_NONE, - STp->long_timeout, MAX_READY_RETRIES, 1); if (!SRpnt) { retval = (STp->buffer)->syscall_result; @@ -747,7 +744,7 @@ scode = (SRpnt->sr_sense_buffer[2] & 0x0f); if (scode == UNIT_ATTENTION) { /* New media? */ + new_session = TRUE; - new_session = 1; if (attentions < MAX_ATTENTIONS) { attentions++; continue; @@ -799,10 +796,10 @@ */ static int check_tape(Scsi_Tape *STp, struct file *filp) { + int i, retval, new_session = FALSE, do_wait; - int i, retval, new_session = 0, do_wait; unsigned char cmd[MAX_COMMAND_SIZE], saved_cleaning; unsigned short st_flags = filp->f_flags; + Scsi_Request *SRpnt = NULL; - struct scsi_request *SRpnt = NULL; ST_mode *STm; ST_partstat *STps; char *name = tape_name(STp); @@ -814,7 +811,7 @@ if (mode != STp->current_mode) { DEBC(printk(ST_DEB_MSG "%s: Mode change from %d to %d.\n", name, STp->current_mode, mode)); + new_session = TRUE; - new_session = 1; STp->current_mode = mode; } STm = &(STp->modes[STp->current_mode]); @@ -839,11 +836,11 @@ STps->rw = ST_IDLE; STps->eof = ST_NOEOF; STps->at_sm = 0; + STps->last_block_valid = FALSE; - STps->last_block_valid = 0; STps->drv_block = 0; STps->drv_file = 0; } + new_session = TRUE; - new_session = 1; } else { STp->cleaning_req |= saved_cleaning; @@ -870,8 +867,8 @@ memset((void *) &cmd[0], 0, MAX_COMMAND_SIZE); cmd[0] = READ_BLOCK_LIMITS; + SRpnt = st_do_scsi(SRpnt, STp, cmd, 6, SCSI_DATA_READ, STp->device->timeout, + MAX_READY_RETRIES, TRUE); - SRpnt = st_do_scsi(SRpnt, STp, cmd, 6, DMA_FROM_DEVICE, - STp->device->timeout, MAX_READY_RETRIES, 1); if (!SRpnt) { retval = (STp->buffer)->syscall_result; goto err_out; @@ -897,8 +894,8 @@ cmd[0] = MODE_SENSE; cmd[4] = 12; + SRpnt = st_do_scsi(SRpnt, STp, cmd, 12, SCSI_DATA_READ, STp->device->timeout, + MAX_READY_RETRIES, TRUE); - SRpnt = st_do_scsi(SRpnt, STp, cmd, 12, DMA_FROM_DEVICE, - STp->device->timeout, MAX_READY_RETRIES, 1); if (!SRpnt) { retval = (STp->buffer)->syscall_result; goto err_out; @@ -931,7 +928,7 @@ } scsi_release_request(SRpnt); SRpnt = NULL; + STp->inited = TRUE; - STp->inited = 1; if (STp->block_size > 0) (STp->buffer)->buffer_blocks = @@ -973,8 +970,8 @@ } if (new_session) { /* Change the drive parameters for the new mode */ + STp->density_changed = STp->blksize_changed = FALSE; + STp->compression_changed = FALSE; - STp->density_changed = STp->blksize_changed = 0; - STp->compression_changed = 0; if (!(STm->defaults_for_writes) && (retval = set_mode_densblk(STp, STm)) < 0) goto err_out; @@ -1079,7 +1076,7 @@ { int result = 0, result2; unsigned char cmd[MAX_COMMAND_SIZE]; + Scsi_Request *SRpnt; - struct scsi_request *SRpnt; Scsi_Tape *STp = filp->private_data; ST_mode *STm = &(STp->modes[STp->current_mode]); ST_partstat *STps = &(STp->ps[STp->partition]); @@ -1119,8 +1116,8 @@ cmd[0] = WRITE_FILEMARKS; cmd[4] = 1 + STp->two_fm; + SRpnt = st_do_scsi(NULL, STp, cmd, 0, SCSI_DATA_NONE, + STp->device->timeout, MAX_WRITE_RETRIES, TRUE); - SRpnt = st_do_scsi(NULL, STp, cmd, 0, DMA_NONE, - STp->device->timeout, MAX_WRITE_RETRIES, 1); if (!SRpnt) { result = (STp->buffer)->syscall_result; goto out; @@ -1146,7 +1143,7 @@ STps->drv_file++; STps->drv_block = 0; if (STp->two_fm) + cross_eof(STp, FALSE); - cross_eof(STp, 0); STps->eof = ST_FM; } @@ -1158,7 +1155,7 @@ if (STp->can_bsr) result = flush_buffer(STp, 0); else if (STps->eof == ST_FM_HIT) { + result = cross_eof(STp, FALSE); - result = cross_eof(STp, 0); if (result) { if (STps->drv_file >= 0) STps->drv_file++; @@ -1168,7 +1165,7 @@ STps->eof = ST_NOEOF; } } else if ((STps->eof == ST_NOEOF && + !(result = cross_eof(STp, TRUE))) || - !(result = cross_eof(STp, 1))) || STps->eof == ST_FM_HIT) { if (STps->drv_file >= 0) STps->drv_file++; @@ -1293,7 +1290,7 @@ STbp->buffer_bytes = 0; /* can be used as transfer counter */ } else + STbp->do_dio = FALSE; /* fall back to buffering with any error */ - STbp->do_dio = 0; /* fall back to buffering with any error */ STbp->sg_segs = STbp->do_dio; STbp->frp_sg_current = 0; DEB( @@ -1306,7 +1303,7 @@ } ) } else + STbp->do_dio = FALSE; - STbp->do_dio = 0; DEB( STp->nbr_requests++; ) if (!STbp->do_dio) { @@ -1338,7 +1335,7 @@ STbp = STp->buffer; if (STbp->do_dio) { + sgl_unmap_user_pages(&(STbp->sg[0]), STbp->do_dio, FALSE); - sgl_unmap_user_pages(&(STbp->sg[0]), STbp->do_dio, 0); STbp->do_dio = 0; } } @@ -1355,7 +1352,7 @@ int async_write; unsigned char cmd[MAX_COMMAND_SIZE]; const char __user *b_point; + Scsi_Request *SRpnt = NULL; - struct scsi_request *SRpnt = NULL; Scsi_Tape *STp = filp->private_data; ST_mode *STm; ST_partstat *STps; @@ -1441,7 +1438,7 @@ goto out; } + retval = setup_buffering(STp, buf, count, FALSE); - retval = setup_buffering(STp, buf, count, 0); if (retval) goto out; @@ -1485,7 +1482,7 @@ if (STp->block_size != 0 && STm->do_buffer_writes && !(STp->try_dio && try_wdio) && STps->eof < ST_EOM_OK && STbp->buffer_bytes < STbp->buffer_size) { + STp->dirty = TRUE; - STp->dirty = 1; /* Don't write a buffer that is not full enough. */ if (!async_write && count == 0) break; @@ -1506,7 +1503,7 @@ cmd[3] = blks >> 8; cmd[4] = blks; + SRpnt = st_do_scsi(SRpnt, STp, cmd, transfer, SCSI_DATA_WRITE, - SRpnt = st_do_scsi(SRpnt, STp, cmd, transfer, DMA_TO_DEVICE, STp->device->timeout, MAX_WRITE_RETRIES, !async_write); if (!SRpnt) { retval = STbp->syscall_result; @@ -1562,7 +1559,7 @@ if (!retry_eot && (SRpnt->sr_sense_buffer[0] & 1) == 0 && (scode == NO_SENSE || scode == RECOVERED_ERROR)) { move_buffer_data(STp->buffer, transfer - undone); + retry_eot = TRUE; - retry_eot = 1; if (STps->drv_block >= 0) { STps->drv_block += (transfer - undone) / STp->block_size; @@ -1633,11 +1630,11 @@ Does release user buffer mapping if it is set. */ +static long read_tape(Scsi_Tape *STp, long count, Scsi_Request ** aSRpnt) -static long read_tape(Scsi_Tape *STp, long count, struct scsi_request ** aSRpnt) { int transfer, blks, bytes; unsigned char cmd[MAX_COMMAND_SIZE]; + Scsi_Request *SRpnt; - struct scsi_request *SRpnt; ST_mode *STm; ST_partstat *STps; ST_buffer *STbp; @@ -1676,8 +1673,8 @@ cmd[4] = blks; SRpnt = *aSRpnt; + SRpnt = st_do_scsi(SRpnt, STp, cmd, bytes, SCSI_DATA_READ, + STp->device->timeout, MAX_RETRIES, TRUE); - SRpnt = st_do_scsi(SRpnt, STp, cmd, bytes, DMA_FROM_DEVICE, - STp->device->timeout, MAX_RETRIES, 1); release_buffering(STp); *aSRpnt = SRpnt; if (!SRpnt) @@ -1821,7 +1818,7 @@ ssize_t retval = 0; ssize_t i, transfer; int special, do_dio = 0; + Scsi_Request *SRpnt = NULL; - struct scsi_request *SRpnt = NULL; Scsi_Tape *STp = filp->private_data; ST_mode *STm; ST_partstat *STps; @@ -1855,7 +1852,7 @@ STps->eof, STbp->buffer_bytes); ) /* end DEB */ + retval = setup_buffering(STp, buf, count, TRUE); - retval = setup_buffering(STp, buf, count, 1); if (retval) goto out; do_dio = STbp->do_dio; @@ -1999,7 +1996,7 @@ cd0 = STm->cdevs[0]; cd1 = STm->cdevs[1]; memcpy(STm, &(STp->modes[0]), sizeof(ST_mode)); STm->cdevs[0] = cd0; STm->cdevs[1] = cd1; + modes_defined = TRUE; - modes_defined = 1; DEBC(printk(ST_DEB_MSG "%s: Initialized mode %d definition from mode 0\n", name, STp->current_mode)); @@ -2068,7 +2065,7 @@ DEBC( printk(KERN_INFO "%s: Default block size set to %d bytes.\n", name, STm->default_blksize)); if (STp->ready == ST_READY) { + STp->blksize_changed = FALSE; - STp->blksize_changed = 0; set_mode_densblk(STp, STm); } } @@ -2107,7 +2104,7 @@ DEBC( printk(KERN_INFO "%s: Density default set to %x\n", name, STm->default_density)); if (STp->ready == ST_READY) { + STp->density_changed = FALSE; - STp->density_changed = 0; set_mode_densblk(STp, STm); } } @@ -2140,7 +2137,7 @@ DEBC( printk(KERN_INFO "%s: Compression default set to %x\n", name, (value & 1))); if (STp->ready == ST_READY) { + STp->compression_changed = FALSE; - STp->compression_changed = 0; st_compression(STp, (STm->default_compression == ST_YES)); } } @@ -2177,7 +2174,7 @@ static int read_mode_page(Scsi_Tape *STp, int page, int omit_block_descs) { unsigned char cmd[MAX_COMMAND_SIZE]; + Scsi_Request *SRpnt = NULL; - struct scsi_request *SRpnt = NULL; memset(cmd, 0, MAX_COMMAND_SIZE); cmd[0] = MODE_SENSE; @@ -2186,8 +2183,8 @@ cmd[2] = page; cmd[4] = 255; + SRpnt = st_do_scsi(SRpnt, STp, cmd, cmd[4], SCSI_DATA_READ, + STp->device->timeout, 0, TRUE); - SRpnt = st_do_scsi(SRpnt, STp, cmd, cmd[4], DMA_FROM_DEVICE, - STp->device->timeout, 0, 1); if (SRpnt == NULL) return (STp->buffer)->syscall_result; @@ -2203,7 +2200,7 @@ { int pgo; unsigned char cmd[MAX_COMMAND_SIZE]; + Scsi_Request *SRpnt = NULL; - struct scsi_request *SRpnt = NULL; memset(cmd, 0, MAX_COMMAND_SIZE); cmd[0] = MODE_SELECT; @@ -2217,8 +2214,8 @@ (STp->buffer)->b_data[MH_OFF_DEV_SPECIFIC] &= ~MH_BIT_WP; (STp->buffer)->b_data[pgo + MP_OFF_PAGE_NBR] &= MP_MSK_PAGE_NBR; + SRpnt = st_do_scsi(SRpnt, STp, cmd, cmd[4], SCSI_DATA_WRITE, + (slow ? STp->long_timeout : STp->device->timeout), 0, TRUE); - SRpnt = st_do_scsi(SRpnt, STp, cmd, cmd[4], DMA_TO_DEVICE, - (slow ? STp->long_timeout : STp->device->timeout), 0, 1); if (SRpnt == NULL) return (STp->buffer)->syscall_result; @@ -2256,7 +2253,7 @@ return (-EIO); /* Read the current page contents */ + retval = read_mode_page(STp, COMPRESSION_PAGE, FALSE); - retval = read_mode_page(STp, COMPRESSION_PAGE, 0); if (retval) { DEBC(printk(ST_DEB_MSG "%s: Compression mode page not supported.\n", name)); @@ -2285,7 +2282,7 @@ b_data[mpoffs + CP_OFF_C_ALGO] = 0; /* no compression */ } + retval = write_mode_page(STp, COMPRESSION_PAGE, FALSE); - retval = write_mode_page(STp, COMPRESSION_PAGE, 0); if (retval) { DEBC(printk(ST_DEB_MSG "%s: Compression change failed.\n", name)); return (-EIO); @@ -2293,7 +2290,7 @@ DEBC(printk(ST_DEB_MSG "%s: Compression state changed to %d.\n", name, state)); + STp->compression_changed = TRUE; - STp->compression_changed = 1; return 0; } @@ -2305,7 +2302,7 @@ DEB( char *name = tape_name(STp); ) unsigned char cmd[MAX_COMMAND_SIZE]; ST_partstat *STps; + Scsi_Request *SRpnt; - struct scsi_request *SRpnt; if (STp->ready != ST_READY && !load_code) { if (STp->ready == ST_NO_TAPE) @@ -2342,8 +2339,8 @@ printk(ST_DEB_MSG "%s: Loading tape.\n", name); ); + SRpnt = st_do_scsi(NULL, STp, cmd, 0, SCSI_DATA_NONE, + timeout, MAX_RETRIES, TRUE); - SRpnt = st_do_scsi(NULL, STp, cmd, 0, DMA_NONE, - timeout, MAX_RETRIES, 1); if (!SRpnt) return (STp->buffer)->syscall_result; @@ -2378,12 +2375,12 @@ int timeout; long ltmp; int ioctl_result; + int chg_eof = TRUE; - int chg_eof = 1; unsigned char cmd[MAX_COMMAND_SIZE]; + Scsi_Request *SRpnt; - struct scsi_request *SRpnt; ST_partstat *STps; int fileno, blkno, at_sm, undone; + int datalen = 0, direction = SCSI_DATA_NONE; - int datalen = 0, direction = DMA_NONE; char *name = tape_name(STp); WARN_ON(STp->buffer->do_dio != 0); @@ -2402,7 +2399,7 @@ memset(cmd, 0, MAX_COMMAND_SIZE); switch (cmd_in) { case MTFSFM: + chg_eof = FALSE; /* Changed from the FSF after this */ - chg_eof = 0; /* Changed from the FSF after this */ case MTFSF: cmd[0] = SPACE; cmd[1] = 0x01; /* Space FileMarks */ @@ -2417,7 +2414,7 @@ at_sm &= (arg == 0); break; case MTBSFM: + chg_eof = FALSE; /* Changed from the FSF after this */ - chg_eof = 0; /* Changed from the FSF after this */ case MTBSF: cmd[0] = SPACE; cmd[1] = 0x01; /* Space FileMarks */ @@ -2586,7 +2583,7 @@ case MTSETDENSITY: /* Set tape density */ case MTSETDRVBUFFER: /* Set drive buffering */ case SET_DENS_AND_BLK: /* Set density and block size */ + chg_eof = FALSE; - chg_eof = 0; if (STp->dirty || (STp->buffer)->buffer_bytes != 0) return (-EIO); /* Not allowed if data in buffer */ if ((cmd_in == MTSETBLK || cmd_in == SET_DENS_AND_BLK) && @@ -2601,7 +2598,7 @@ if ((STp->use_pf & USE_PF)) cmd[1] = MODE_SELECT_PAGE_FORMAT; cmd[4] = datalen = 12; + direction = SCSI_DATA_WRITE; - direction = DMA_TO_DEVICE; memset((STp->buffer)->b_data, 0, 12); if (cmd_in == MTSETDRVBUFFER) @@ -2612,7 +2609,7 @@ (STp->buffer)->b_data[3] = 8; /* block descriptor length */ if (cmd_in == MTSETDENSITY) { (STp->buffer)->b_data[4] = arg; + STp->density_changed = TRUE; /* At least we tried ;-) */ - STp->density_changed = 1; /* At least we tried ;-) */ } else if (cmd_in == SET_DENS_AND_BLK) (STp->buffer)->b_data[4] = arg >> 24; else @@ -2620,7 +2617,7 @@ if (cmd_in == MTSETBLK || cmd_in == SET_DENS_AND_BLK) { ltmp = arg & MT_ST_BLKSIZE_MASK; if (cmd_in == MTSETBLK) + STp->blksize_changed = TRUE; /* At least we tried ;-) */ - STp->blksize_changed = 1; /* At least we tried ;-) */ } else ltmp = STp->block_size; (STp->buffer)->b_data[9] = (ltmp >> 16); @@ -2649,7 +2646,7 @@ } SRpnt = st_do_scsi(NULL, STp, cmd, datalen, direction, + timeout, MAX_RETRIES, TRUE); - timeout, MAX_RETRIES, 1); if (!SRpnt) return (STp->buffer)->syscall_result; @@ -2792,7 +2789,7 @@ { int result; unsigned char scmd[MAX_COMMAND_SIZE]; + Scsi_Request *SRpnt; - struct scsi_request *SRpnt; DEB( char *name = tape_name(STp); ) if (STp->ready != ST_READY) @@ -2807,8 +2804,8 @@ if (!logical && !STp->scsi2_logical) scmd[1] = 1; } + SRpnt = st_do_scsi(NULL, STp, scmd, 20, SCSI_DATA_READ, STp->device->timeout, + MAX_READY_RETRIES, TRUE); - SRpnt = st_do_scsi(NULL, STp, scmd, 20, DMA_FROM_DEVICE, - STp->device->timeout, MAX_READY_RETRIES, 1); if (!SRpnt) return (STp->buffer)->syscall_result; @@ -2855,7 +2852,7 @@ unsigned int blk; int timeout; unsigned char scmd[MAX_COMMAND_SIZE]; + Scsi_Request *SRpnt; - struct scsi_request *SRpnt; DEB( char *name = tape_name(STp); ) if (STp->ready != ST_READY) @@ -2874,9 +2871,9 @@ return (-EINVAL); if (partition != STp->partition) { if (get_location(STp, &blk, &p, 1)) + STps->last_block_valid = FALSE; - STps->last_block_valid = 0; else { + STps->last_block_valid = TRUE; - STps->last_block_valid = 1; STps->last_block_visited = blk; DEBC(printk(ST_DEB_MSG "%s: Visited block %d for partition %d saved.\n", @@ -2912,8 +2909,8 @@ timeout = STp->device->timeout; } + SRpnt = st_do_scsi(NULL, STp, scmd, 0, SCSI_DATA_NONE, + timeout, MAX_READY_RETRIES, TRUE); - SRpnt = st_do_scsi(NULL, STp, scmd, 0, DMA_NONE, - timeout, MAX_READY_RETRIES, 1); if (!SRpnt) return (STp->buffer)->syscall_result; @@ -3000,7 +2997,7 @@ if (STp->ready != ST_READY) return (-EIO); + result = read_mode_page(STp, PART_PAGE, TRUE); - result = read_mode_page(STp, PART_PAGE, 1); if (result) { DEBC(printk(ST_DEB_MSG "%s: Can't read medium partition page.\n", @@ -3042,7 +3039,7 @@ int pgo, psd_cnt, psdo; unsigned char *bp; + result = read_mode_page(STp, PART_PAGE, FALSE); - result = read_mode_page(STp, PART_PAGE, 0); if (result) { DEBC(printk(ST_DEB_MSG "%s: Can't read partition mode page.\n", name)); return result; @@ -3085,7 +3082,7 @@ bp[pgo + PP_OFF_RESERVED] = 0; bp[pgo + PP_OFF_FLAGS] = PP_BIT_IDP | PP_MSK_PSUM_MB; + result = write_mode_page(STp, PART_PAGE, TRUE); - result = write_mode_page(STp, PART_PAGE, 1); if (result) { printk(KERN_INFO "%s: Partitioning of tape failed.\n", name); result = (-EIO); @@ -3128,10 +3125,10 @@ * may try and take the device offline, in which case all further * access to the device is prohibited. */ + if (!scsi_block_when_processing_errors(STp->device)) { + retval = (-ENXIO); - retval = scsi_nonblockable_ioctl(STp->device, cmd_in, p, file); - if (!scsi_block_when_processing_errors(STp->device) || !retval) goto out; + } - cmd_type = _IOC_TYPE(cmd_in); cmd_nr = _IOC_NR(cmd_in); @@ -3262,7 +3259,7 @@ for (i = 0; i < ST_NBR_PARTITIONS; i++) { STp->ps[i].rw = ST_IDLE; STp->ps[i].at_sm = 0; + STp->ps[i].last_block_valid = FALSE; - STp->ps[i].last_block_valid = 0; } STp->partition = STp->new_partition = 0; STp->nbr_partitions = 1; /* Bad guess ?-) */ @@ -3311,7 +3308,7 @@ goto out; } + if ((i = flush_buffer(STp, FALSE)) < 0) { - if ((i = flush_buffer(STp, 0)) < 0) { retval = i; goto out; } @@ -3451,7 +3448,7 @@ tb->b_data = page_address(tb->sg[0].page); tb->frp = (struct st_buf_fragment *)(&(tb->sg[0]) + max_sg); + tb->in_use = TRUE; - tb->in_use = 1; tb->dma = need_dma; tb->buffer_size = got; @@ -3465,7 +3462,7 @@ int segs, nbr, max_segs, b_size, priority, order, got; if (new_size <= STbuffer->buffer_size) + return TRUE; - return 1; if (STbuffer->buffer_size <= PAGE_SIZE) normalize_buffer(STbuffer); /* Avoid extra segment */ @@ -3473,7 +3470,7 @@ max_segs = STbuffer->use_sg; nbr = max_segs - STbuffer->frp_segs; if (nbr <= 0) + return FALSE; - return 0; priority = GFP_KERNEL | __GFP_NOWARN; if (need_dma) @@ -3494,7 +3491,7 @@ } DEB(STbuffer->buffer_size = got); normalize_buffer(STbuffer); + return FALSE; - return 0; } STbuffer->frp[segs].length = b_size; STbuffer->frp_segs += 1; @@ -3504,7 +3501,7 @@ } STbuffer->b_data = page_address(STbuffer->frp[0].page); + return TRUE; - return 1; } @@ -3744,7 +3741,7 @@ i = SDp->host->sg_tablesize; if (st_max_sg_segs < i) i = st_max_sg_segs; + buffer = new_tape_buffer(TRUE, (SDp->host)->unchecked_isa_dma, i); - buffer = new_tape_buffer(1, (SDp->host)->unchecked_isa_dma, i); if (buffer == NULL) { printk(KERN_ERR "st: Can't allocate new tape buffer. Device not attached.\n"); goto out; @@ -3847,7 +3844,7 @@ for (i = 0; i < ST_NBR_MODES; i++) { STm = &(tpnt->modes[i]); + STm->defined = FALSE; - STm->defined = 0; STm->sysv = ST_SYSV; STm->defaults_for_writes = 0; STm->do_async_writes = ST_ASYNC_WRITES; @@ -3863,16 +3860,16 @@ STps->rw = ST_IDLE; STps->eof = ST_NOEOF; STps->at_sm = 0; + STps->last_block_valid = FALSE; - STps->last_block_valid = 0; STps->drv_block = (-1); STps->drv_file = (-1); } tpnt->current_mode = 0; + tpnt->modes[0].defined = TRUE; - tpnt->modes[0].defined = 1; tpnt->density_changed = tpnt->compression_changed = + tpnt->blksize_changed = FALSE; - tpnt->blksize_changed = 0; init_MUTEX(&tpnt->lock); st_nr_dev++; @@ -3964,7 +3961,7 @@ static int st_remove(struct device *dev) { + Scsi_Device *SDp = to_scsi_device(dev); - struct scsi_device *SDp = to_scsi_device(dev); Scsi_Tape *tpnt; int i, j, mode; @@ -4256,7 +4253,7 @@ return nr_pages; out_unmap: + sgl_unmap_user_pages(sgl, nr_pages, FALSE); - sgl_unmap_user_pages(sgl, nr_pages, 0); return 0; } reverted: --- b/drivers/scsi/st.h 2004-09-26 11:11:46 -07:00 +++ a/drivers/scsi/st.h 2004-09-26 11:11:46 -07:00 @@ -2,9 +2,11 @@ #ifndef _ST_H #define _ST_H +#ifndef _SCSI_H +#include "scsi.h" +#endif #include - /* The tape buffer descriptor. */ typedef struct { unsigned char in_use; @@ -17,7 +19,7 @@ int writing; int midlevel_result; int syscall_result; + Scsi_Request *last_SRpnt; - struct scsi_request *last_SRpnt; unsigned char *b_data; unsigned short use_sg; /* zero or max number of s/g segments for this adapter */ unsigned short sg_segs; /* number of segments in s/g list */ @@ -74,7 +76,7 @@ /* The tape drive descriptor */ typedef struct { struct scsi_driver *driver; + Scsi_Device *device; - struct scsi_device *device; struct semaphore lock; /* For serialization */ struct completion wait; /* For SCSI commands */ ST_buffer *buffer; reverted: --- b/drivers/scsi/sym53c8xx_2/sym53c8xx.h 2004-09-26 11:11:47 -07:00 +++ a/drivers/scsi/sym53c8xx_2/sym53c8xx.h 2004-09-26 11:11:47 -07:00 @@ -22,19 +22,32 @@ * *----------------------------------------------------------------------------- * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. * + * Where this Software is combined with software released under the terms of + * the GNU Public License ("GPL") and the terms of the GPL would require the + * combined work to also be released under the terms of the GPL, the terms + * and conditions of this License will apply in addition to those of the + * GPL with the exception of any terms or conditions of this License that + * conflict with, or are expressly prohibited by, the GPL. - * 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. * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef SYM53C8XX_H reverted: --- b/drivers/scsi/sym53c8xx_2/sym_conf.h 2004-09-26 11:11:46 -07:00 +++ a/drivers/scsi/sym53c8xx_2/sym_conf.h 2004-09-26 11:11:46 -07:00 @@ -22,19 +22,32 @@ * *----------------------------------------------------------------------------- * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. * + * Where this Software is combined with software released under the terms of + * the GNU Public License ("GPL") and the terms of the GPL would require the + * combined work to also be released under the terms of the GPL, the terms + * and conditions of this License will apply in addition to those of the + * GPL with the exception of any terms or conditions of this License that + * conflict with, or are expressly prohibited by, the GPL. - * 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. * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef SYM_CONF_H reverted: --- b/drivers/scsi/sym53c8xx_2/sym_defs.h 2004-09-26 11:11:46 -07:00 +++ a/drivers/scsi/sym53c8xx_2/sym_defs.h 2004-09-26 11:11:46 -07:00 @@ -22,25 +22,38 @@ * *----------------------------------------------------------------------------- * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. * + * Where this Software is combined with software released under the terms of + * the GNU Public License ("GPL") and the terms of the GPL would require the + * combined work to also be released under the terms of the GPL, the terms + * and conditions of this License will apply in addition to those of the + * GPL with the exception of any terms or conditions of this License that + * conflict with, or are expressly prohibited by, the GPL. - * 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. * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef SYM_DEFS_H #define SYM_DEFS_H +#define SYM_VERSION "2.1.18j" -#define SYM_VERSION "2.1.18k" #define SYM_DRIVER_NAME "sym-" SYM_VERSION /* reverted: --- b/drivers/scsi/sym53c8xx_2/sym_fw.c 2004-09-26 11:11:46 -07:00 +++ a/drivers/scsi/sym53c8xx_2/sym_fw.c 2004-09-26 11:11:46 -07:00 @@ -22,19 +22,32 @@ * *----------------------------------------------------------------------------- * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. * + * Where this Software is combined with software released under the terms of + * the GNU Public License ("GPL") and the terms of the GPL would require the + * combined work to also be released under the terms of the GPL, the terms + * and conditions of this License will apply in addition to those of the + * GPL with the exception of any terms or conditions of this License that + * conflict with, or are expressly prohibited by, the GPL. - * 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. * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifdef __FreeBSD__ @@ -398,6 +411,7 @@ if (opcode == 0) { printf ("%s: ERROR0 IN SCRIPT at %d.\n", sym_name(np), (int) (cur-start)); + MDELAY (10000); ++cur; continue; }; @@ -441,6 +455,7 @@ if ((tmp1 ^ tmp2) & 3) { printf ("%s: ERROR1 IN SCRIPT at %d.\n", sym_name(np), (int) (cur-start)); + MDELAY (10000); } /* * If PREFETCH feature not enabled, remove reverted: --- b/drivers/scsi/sym53c8xx_2/sym_fw.h 2004-09-26 11:11:46 -07:00 +++ a/drivers/scsi/sym53c8xx_2/sym_fw.h 2004-09-26 11:11:46 -07:00 @@ -22,19 +22,32 @@ * *----------------------------------------------------------------------------- * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. * + * Where this Software is combined with software released under the terms of + * the GNU Public License ("GPL") and the terms of the GPL would require the + * combined work to also be released under the terms of the GPL, the terms + * and conditions of this License will apply in addition to those of the + * GPL with the exception of any terms or conditions of this License that + * conflict with, or are expressly prohibited by, the GPL. - * 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. * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef SYM_FW_H reverted: --- b/drivers/scsi/sym53c8xx_2/sym_fw1.h 2004-09-26 11:11:46 -07:00 +++ a/drivers/scsi/sym53c8xx_2/sym_fw1.h 2004-09-26 11:11:46 -07:00 @@ -22,19 +22,32 @@ * *----------------------------------------------------------------------------- * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. * + * Where this Software is combined with software released under the terms of + * the GNU Public License ("GPL") and the terms of the GPL would require the + * combined work to also be released under the terms of the GPL, the terms + * and conditions of this License will apply in addition to those of the + * GPL with the exception of any terms or conditions of this License that + * conflict with, or are expressly prohibited by, the GPL. - * 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. * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* reverted: --- b/drivers/scsi/sym53c8xx_2/sym_fw2.h 2004-09-26 11:11:46 -07:00 +++ a/drivers/scsi/sym53c8xx_2/sym_fw2.h 2004-09-26 11:11:46 -07:00 @@ -22,19 +22,32 @@ * *----------------------------------------------------------------------------- * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. * + * Where this Software is combined with software released under the terms of + * the GNU Public License ("GPL") and the terms of the GPL would require the + * combined work to also be released under the terms of the GPL, the terms + * and conditions of this License will apply in addition to those of the + * GPL with the exception of any terms or conditions of this License that + * conflict with, or are expressly prohibited by, the GPL. - * 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. * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* diff -u b/drivers/scsi/sym53c8xx_2/sym_glue.c b/drivers/scsi/sym53c8xx_2/sym_glue.c --- b/drivers/scsi/sym53c8xx_2/sym_glue.c 2004-09-26 11:11:47 -07:00 +++ b/drivers/scsi/sym53c8xx_2/sym_glue.c 2004-09-26 11:13:18 -07:00 @@ -3,7 +3,6 @@ * of PCI-SCSI IO processors. * * Copyright (C) 1999-2001 Gerard Roudier - * Copyright (c) 2003-2004 Matthew Wilcox * * This driver is derived from the Linux sym53c8xx driver. * Copyright (C) 1998-2000 Gerard Roudier @@ -23,19 +22,32 @@ * *----------------------------------------------------------------------------- * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. * - * 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. + * Where this Software is combined with software released under the terms of + * the GNU Public License ("GPL") and the terms of the GPL would require the + * combined work to also be released under the terms of the GPL, the terms + * and conditions of this License will apply in addition to those of the + * GPL with the exception of any terms or conditions of this License that + * conflict with, or are expressly prohibited by, the GPL. * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. */ #define SYM_GLUE_C @@ -561,6 +573,7 @@ switch (cp->cdb_buf[0]) { case 0x0A: case 0x2A: case 0xAA: panic("XXXXXXXXXXXXX WRITE NOT YET ALLOWED XXXXXXXXXXXXXX\n"); + MDELAY(10000); break; default: break; @@ -1083,7 +1096,8 @@ lp->s.scdev_depth = depth_to_use; sym_tune_dev_queuing(np, device->id, device->lun, reqtags); - spi_dv_device(device); + if (!spi_initial_dv(device->sdev_target)) + spi_dv_device(device); return 0; } @@ -1966,14 +1980,39 @@ __setup("sym53c8xx=", sym53c8xx_setup); #endif -static int __devinit sym_check_supported(struct sym_device *device) +/* + * Read and check the PCI configuration for any detected NCR + * boards and save data for attaching after all boards have + * been detected. + */ +static int __devinit +sym53c8xx_pci_init(struct pci_dev *pdev, struct sym_device *device) { struct sym_pci_chip *chip; - struct pci_dev *pdev = device->pdev; - u_char revision; - unsigned long io_port = device->s.io_port; - unsigned long base = device->s.base; + u_long base, base_2; + u_long base_c, base_2_c, io_port; int i; + u_short device_id, status_reg; + u_char revision; + + /* Choose some short name for this device */ + sprintf(device->s.inst_name, "sym.%d.%d.%d", pdev->bus->number, + PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn)); + + device_id = pdev->device; + + io_port = pdev->resource[0].start; + + base_c = pdev->resource[1].start; + i = pci_get_base_address(pdev, 1, &base); + + base_2_c = pdev->resource[i].start; + pci_get_base_address(pdev, i, &base_2); + + base &= PCI_BASE_ADDRESS_MEM_MASK; + base_2 &= PCI_BASE_ADDRESS_MEM_MASK; + + pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision); /* * If user excluded this chip, do not initialize it. @@ -1981,11 +2020,20 @@ if (io_port) { for (i = 0 ; i < 8 ; i++) { if (sym_driver_setup.excludes[i] == io_port) - return -ENODEV; + return -1; } } /* + * Check if the chip is supported. + */ + chip = sym_lookup_pci_chip_table(device_id, revision); + if (!chip) { + printf_info("%s: device not supported\n", sym_name(device)); + return -1; + } + + /* * Check if the chip has been assigned resources we need. * XXX: can this still happen with Linux 2.6's PCI layer? */ @@ -1993,84 +2041,66 @@ if (!io_port) { printf_info("%s: IO base address disabled.\n", sym_name(device)); - return -ENODEV; + return -1; } #else if (!base) { printf_info("%s: MMIO base address disabled.\n", sym_name(device)); - return -ENODEV; + return -1; } #endif /* - * Check if the chip is supported. Then copy the chip description - * to our device structure so we can make it match the actual device - * and options. + * Ignore Symbios chips controlled by various RAID controllers. + * These controllers set value 0x52414944 at RAM end - 16. */ - pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision); - chip = sym_lookup_pci_chip_table(pdev->device, revision); - if (!chip) { - printf_info("%s: device not supported\n", sym_name(device)); - return -ENODEV; +#if defined(__i386__) + if (base_2_c) { + unsigned int ram_size, ram_val; + void *ram_ptr; + + if (chip->features & FE_RAM8K) + ram_size = 8192; + else + ram_size = 4096; + + ram_ptr = ioremap(base_2_c, ram_size); + if (ram_ptr) { + ram_val = readl_raw(ram_ptr + ram_size - 16); + iounmap(ram_ptr); + if (ram_val == 0x52414944) { + printf_info("%s: not initializing, " + "driven by RAID controller.\n", + sym_name(device)); + return -1; + } + } } +#endif /* i386 and PCI MEMORY accessible */ + + /* + * Copy the chip description to our device structure, + * so we can make it match the actual device and options. + */ memcpy(&device->chip, chip, sizeof(device->chip)); device->chip.revision_id = revision; - return 0; -} - -/* - * Ignore Symbios chips controlled by various RAID controllers. - * These controllers set value 0x52414944 at RAM end - 16. - */ -static int __devinit sym_check_raid(struct sym_device *device) -{ - unsigned long base_2_c = device->s.base_2_c; - unsigned int ram_size, ram_val; - void *ram_ptr; - - if (!base_2_c) - return 0; - - if (device->chip.features & FE_RAM8K) - ram_size = 8192; - else - ram_size = 4096; - - ram_ptr = ioremap(base_2_c, ram_size); - if (!ram_ptr) - return 0; - - ram_val = readl(ram_ptr + ram_size - 16); - iounmap(ram_ptr); - if (ram_val != 0x52414944) - return 0; - - printf_info("%s: not initializing, driven by RAID controller.\n", - sym_name(device)); - return -ENODEV; -} - -static int __devinit sym_set_workarounds(struct sym_device *device) -{ - struct sym_pci_chip *chip = &device->chip; - struct pci_dev *pdev = device->pdev; - u_short status_reg; - /* + * Some features are required to be enabled in order to + * work around some chip problems. :) ;) * (ITEM 12 of a DEL about the 896 I haven't yet). * We must ensure the chip will use WRITE AND INVALIDATE. * The revision number limit is for now arbitrary. */ - if (pdev->device == PCI_DEVICE_ID_NCR_53C896 && chip->revision_id < 0x4) { + if (device_id == PCI_DEVICE_ID_NCR_53C896 && revision < 0x4) { chip->features |= (FE_WRIE | FE_CLSE); } /* If the chip can do Memory Write Invalidate, enable it */ if (chip->features & FE_WRIE) { if (pci_set_mwi(pdev)) - return -ENODEV; + return -1; } /* @@ -2096,36 +2126,18 @@ } } - return 0; -} - -/* - * Read and check the PCI configuration for any detected NCR - * boards and save data for attaching after all boards have - * been detected. - */ -static void __devinit -sym_init_device(struct pci_dev *pdev, struct sym_device *device) -{ - unsigned long base, base_2; - int i; - - device->pdev = pdev; - device->s.irq = pdev->irq; - - /* Choose some short name for this device */ - sprintf(device->s.inst_name, "sym.%d.%d.%d", pdev->bus->number, - PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn)); - - device->s.io_port = pdev->resource[0].start; - - device->s.base_c = pdev->resource[1].start; - i = pci_get_base_address(pdev, 1, &base); - device->s.base = base & PCI_BASE_ADDRESS_MEM_MASK; + /* + * Initialise device structure with items required by sym_attach. + */ + device->pdev = pdev; + device->s.base = base; + device->s.base_2 = base_2; + device->s.base_c = base_c; + device->s.base_2_c = base_2_c; + device->s.io_port = io_port; + device->s.irq = pdev->irq; - device->s.base_2_c = pdev->resource[i].start; - pci_get_base_address(pdev, i, &base_2); - device->s.base_2 = base_2 & PCI_BASE_ADDRESS_MEM_MASK; + return 0; } /* @@ -2204,7 +2216,7 @@ return 1; } -MODULE_LICENSE("GPL"); +MODULE_LICENSE("Dual BSD/GPL"); MODULE_VERSION(SYM_VERSION); /* @@ -2241,7 +2253,7 @@ memset(&nvram, 0, sizeof(nvram)); if (pci_enable_device(pdev)) - goto leave; + return -ENODEV; pci_set_master(pdev); @@ -2249,15 +2261,7 @@ goto disable; sym_dev.host_id = SYM_SETUP_HOST_ID; - - sym_init_device(pdev, &sym_dev); - if (sym_check_supported(&sym_dev)) - goto free; - - if (sym_check_raid(&sym_dev)) - goto leave; /* Don't disable the device */ - - if (sym_set_workarounds(&sym_dev)) + if (sym53c8xx_pci_init(pdev, &sym_dev)) goto free; sym_config_pqs(pdev, &sym_dev); @@ -2282,7 +2286,6 @@ pci_release_regions(pdev); disable: pci_disable_device(pdev); - leave: return -ENODEV; } @@ -2302,35 +2305,61 @@ attach_count--; } -static void sym2_get_offset(struct scsi_device *sdev) +static void sym2_get_signalling(struct Scsi_Host *shost) +{ + struct sym_hcb *np = ((struct host_data *)shost->hostdata)->ncb; + enum spi_signal_type type; + + switch (np->scsi_mode) { + case SMODE_SE: + type = SPI_SIGNAL_SE; + break; + case SMODE_LVD: + type = SPI_SIGNAL_LVD; + break; + case SMODE_HVD: + type = SPI_SIGNAL_HVD; + break; + default: + type = SPI_SIGNAL_UNKNOWN; + break; + } + spi_signalling(shost) = type; +} + +static void sym2_get_offset(struct scsi_target *starget) { - struct sym_hcb *np = ((struct host_data *)sdev->host->hostdata)->ncb; - struct sym_tcb *tp = &np->target[sdev->id]; + struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); + struct sym_hcb *np = ((struct host_data *)shost->hostdata)->ncb; + struct sym_tcb *tp = &np->target[starget->id]; - spi_offset(sdev) = tp->tinfo.curr.offset; + spi_offset(starget) = tp->tinfo.curr.offset; } -static void sym2_set_offset(struct scsi_device *sdev, int offset) +static void sym2_set_offset(struct scsi_target *starget, int offset) { - struct sym_hcb *np = ((struct host_data *)sdev->host->hostdata)->ncb; - struct sym_tcb *tp = &np->target[sdev->id]; + struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); + struct sym_hcb *np = ((struct host_data *)shost->hostdata)->ncb; + struct sym_tcb *tp = &np->target[starget->id]; tp->tinfo.goal.offset = offset; } -static void sym2_get_period(struct scsi_device *sdev) +static void sym2_get_period(struct scsi_target *starget) { - struct sym_hcb *np = ((struct host_data *)sdev->host->hostdata)->ncb; - struct sym_tcb *tp = &np->target[sdev->id]; + struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); + struct sym_hcb *np = ((struct host_data *)shost->hostdata)->ncb; + struct sym_tcb *tp = &np->target[starget->id]; - spi_period(sdev) = tp->tinfo.curr.period; + spi_period(starget) = tp->tinfo.curr.period; } -static void sym2_set_period(struct scsi_device *sdev, int period) +static void sym2_set_period(struct scsi_target *starget, int period) { - struct sym_hcb *np = ((struct host_data *)sdev->host->hostdata)->ncb; - struct sym_tcb *tp = &np->target[sdev->id]; + struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); + struct sym_hcb *np = ((struct host_data *)shost->hostdata)->ncb; + struct sym_tcb *tp = &np->target[starget->id]; /* have to have DT for these transfers */ if (period <= np->minsync) @@ -2339,18 +2368,20 @@ tp->tinfo.goal.period = period; } -static void sym2_get_width(struct scsi_device *sdev) +static void sym2_get_width(struct scsi_target *starget) { - struct sym_hcb *np = ((struct host_data *)sdev->host->hostdata)->ncb; - struct sym_tcb *tp = &np->target[sdev->id]; + struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); + struct sym_hcb *np = ((struct host_data *)shost->hostdata)->ncb; + struct sym_tcb *tp = &np->target[starget->id]; - spi_width(sdev) = tp->tinfo.curr.width ? 1 : 0; + spi_width(starget) = tp->tinfo.curr.width ? 1 : 0; } -static void sym2_set_width(struct scsi_device *sdev, int width) +static void sym2_set_width(struct scsi_target *starget, int width) { - struct sym_hcb *np = ((struct host_data *)sdev->host->hostdata)->ncb; - struct sym_tcb *tp = &np->target[sdev->id]; + struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); + struct sym_hcb *np = ((struct host_data *)shost->hostdata)->ncb; + struct sym_tcb *tp = &np->target[starget->id]; /* It is illegal to have DT set on narrow transfers */ if (width == 0) @@ -2359,18 +2390,20 @@ tp->tinfo.goal.width = width; } -static void sym2_get_dt(struct scsi_device *sdev) +static void sym2_get_dt(struct scsi_target *starget) { - struct sym_hcb *np = ((struct host_data *)sdev->host->hostdata)->ncb; - struct sym_tcb *tp = &np->target[sdev->id]; + struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); + struct sym_hcb *np = ((struct host_data *)shost->hostdata)->ncb; + struct sym_tcb *tp = &np->target[starget->id]; - spi_dt(sdev) = (tp->tinfo.curr.options & PPR_OPT_DT) ? 1 : 0; + spi_dt(starget) = (tp->tinfo.curr.options & PPR_OPT_DT) ? 1 : 0; } -static void sym2_set_dt(struct scsi_device *sdev, int dt) +static void sym2_set_dt(struct scsi_target *starget, int dt) { - struct sym_hcb *np = ((struct host_data *)sdev->host->hostdata)->ncb; - struct sym_tcb *tp = &np->target[sdev->id]; + struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); + struct sym_hcb *np = ((struct host_data *)shost->hostdata)->ncb; + struct sym_tcb *tp = &np->target[starget->id]; if (dt) tp->tinfo.goal.options |= PPR_OPT_DT; @@ -2392,6 +2425,7 @@ .get_dt = sym2_get_dt, .set_dt = sym2_set_dt, .show_dt = 1, + .get_signalling = sym2_get_signalling, }; static struct pci_device_id sym2_id_table[] __devinitdata = { reverted: --- b/drivers/scsi/sym53c8xx_2/sym_glue.h 2004-09-26 11:11:47 -07:00 +++ a/drivers/scsi/sym53c8xx_2/sym_glue.h 2004-09-26 11:11:47 -07:00 @@ -22,19 +22,32 @@ * *----------------------------------------------------------------------------- * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. * + * Where this Software is combined with software released under the terms of + * the GNU Public License ("GPL") and the terms of the GPL would require the + * combined work to also be released under the terms of the GPL, the terms + * and conditions of this License will apply in addition to those of the + * GPL with the exception of any terms or conditions of this License that + * conflict with, or are expressly prohibited by, the GPL. - * 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. * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef SYM_GLUE_H @@ -76,6 +89,7 @@ #define SYM_OPT_HANDLE_DIR_UNKNOWN #define SYM_OPT_HANDLE_DEVICE_QUEUEING +#define SYM_OPT_NVRAM_PRE_READ #define SYM_OPT_LIMIT_COMMAND_REORDERING #define SYM_OPT_ANNOUNCE_TRANSFER_RATE @@ -93,9 +107,10 @@ #define printf(args...) printk(args) /* + * Insert a delay in micro-seconds and milli-seconds. - * Insert a delay in micro-seconds */ #define sym_udelay(us) udelay(us) +#define sym_mdelay(ms) mdelay(ms) /* * A 'read barrier' flushes any data that have been prefetched reverted: --- b/drivers/scsi/sym53c8xx_2/sym_hipd.c 2004-09-26 11:11:45 -07:00 +++ a/drivers/scsi/sym53c8xx_2/sym_hipd.c 2004-09-26 11:11:45 -07:00 @@ -3,7 +3,6 @@ * of PCI-SCSI IO processors. * * Copyright (C) 1999-2001 Gerard Roudier - * Copyright (c) 2003-2004 Matthew Wilcox * * This driver is derived from the Linux sym53c8xx driver. * Copyright (C) 1998-2000 Gerard Roudier @@ -23,19 +22,32 @@ * *----------------------------------------------------------------------------- * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * Where this Software is combined with software released under the terms of + * the GNU Public License ("GPL") and the terms of the GPL would require the + * combined work to also be released under the terms of the GPL, the terms + * and conditions of this License will apply in addition to those of the + * GPL with the exception of any terms or conditions of this License that + * conflict with, or are expressly prohibited by, the GPL. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "sym_glue.h" #include "sym_nvram.h" @@ -287,6 +299,7 @@ } out: OUTB (nc_scntl1, 0); + /* MDELAY(100); */ return retv; } @@ -1942,7 +1955,7 @@ if (np->features & (FE_ULTRA2|FE_ULTRA3)) { OUTONW (nc_sien, SBMC); if (reason == 0) { + MDELAY(100); - mdelay(100); INW (nc_sist); } np->scsi_mode = INB (nc_stest4) & SMODE; @@ -5505,6 +5518,7 @@ printf ("CCB=%lx STAT=%x/%x/%x DEV=%d/%d\n", (unsigned long)cp, cp->host_status, cp->ssss_status, cp->host_flags, cp->target, cp->lun); + MDELAY(100); } /* @@ -5732,8 +5746,15 @@ /* * Soft-attach the controller. */ +#ifdef SYM_OPT_NVRAM_PRE_READ int sym_hcb_attach(hcb_p np, struct sym_fw *fw, struct sym_nvram *nvram) +#else +int sym_hcb_attach(hcb_p np, struct sym_fw *fw) +#endif { +#ifndef SYM_OPT_NVRAM_PRE_READ + struct sym_nvram nvram_buf, *nvram = &nvram_buf; +#endif int i; /* @@ -5758,6 +5779,13 @@ * if the chip is currently active. */ sym_chip_reset (np); + + /* + * Try to read the user set-up. + */ +#ifndef SYM_OPT_NVRAM_PRE_READ + (void) sym_read_nvram(np, nvram); +#endif /* * Prepare controller and devices settings, according reverted: --- b/drivers/scsi/sym53c8xx_2/sym_hipd.h 2004-09-26 11:11:46 -07:00 +++ a/drivers/scsi/sym53c8xx_2/sym_hipd.h 2004-09-26 11:11:46 -07:00 @@ -22,19 +22,32 @@ * *----------------------------------------------------------------------------- * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. * + * Where this Software is combined with software released under the terms of + * the GNU Public License ("GPL") and the terms of the GPL would require the + * combined work to also be released under the terms of the GPL, the terms + * and conditions of this License will apply in addition to those of the + * GPL with the exception of any terms or conditions of this License that + * conflict with, or are expressly prohibited by, the GPL. - * 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. * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef SYM_HIPD_H @@ -1108,7 +1121,12 @@ int sym_abort_ccb(hcb_p np, ccb_p cp, int timed_out); int sym_reset_scsi_target(hcb_p np, int target); void sym_hcb_free(hcb_p np); + +#ifdef SYM_OPT_NVRAM_PRE_READ int sym_hcb_attach(hcb_p np, struct sym_fw *fw, struct sym_nvram *nvram); +#else +int sym_hcb_attach(hcb_p np, struct sym_fw *fw); +#endif /* * Optionnaly, the driver may handle IO timeouts. @@ -1332,6 +1350,7 @@ #define PRINT_ADDR sym_print_addr #define PRINT_TARGET sym_print_target #define PRINT_LUN sym_print_lun +#define MDELAY sym_mdelay #define UDELAY sym_udelay #endif /* SYM_HIPD_H */ reverted: --- b/drivers/scsi/sym53c8xx_2/sym_malloc.c 2004-09-26 11:11:46 -07:00 +++ a/drivers/scsi/sym53c8xx_2/sym_malloc.c 2004-09-26 11:11:46 -07:00 @@ -22,19 +22,32 @@ * *----------------------------------------------------------------------------- * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. * + * Where this Software is combined with software released under the terms of + * the GNU Public License ("GPL") and the terms of the GPL would require the + * combined work to also be released under the terms of the GPL, the terms + * and conditions of this License will apply in addition to those of the + * GPL with the exception of any terms or conditions of this License that + * conflict with, or are expressly prohibited by, the GPL. - * 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. * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifdef __FreeBSD__ reverted: --- b/drivers/scsi/sym53c8xx_2/sym_misc.c 2004-09-26 11:11:46 -07:00 +++ a/drivers/scsi/sym53c8xx_2/sym_misc.c 2004-09-26 11:11:46 -07:00 @@ -22,19 +22,32 @@ * *----------------------------------------------------------------------------- * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. * + * Where this Software is combined with software released under the terms of + * the GNU Public License ("GPL") and the terms of the GPL would require the + * combined work to also be released under the terms of the GPL, the terms + * and conditions of this License will apply in addition to those of the + * GPL with the exception of any terms or conditions of this License that + * conflict with, or are expressly prohibited by, the GPL. - * 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. * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifdef __FreeBSD__ reverted: --- b/drivers/scsi/sym53c8xx_2/sym_misc.h 2004-09-26 11:11:47 -07:00 +++ a/drivers/scsi/sym53c8xx_2/sym_misc.h 2004-09-26 11:11:47 -07:00 @@ -22,19 +22,32 @@ * *----------------------------------------------------------------------------- * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. * + * Where this Software is combined with software released under the terms of + * the GNU Public License ("GPL") and the terms of the GPL would require the + * combined work to also be released under the terms of the GPL, the terms + * and conditions of this License will apply in addition to those of the + * GPL with the exception of any terms or conditions of this License that + * conflict with, or are expressly prohibited by, the GPL. - * 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. * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef SYM_MISC_H reverted: --- b/drivers/scsi/sym53c8xx_2/sym_nvram.c 2004-09-26 11:11:46 -07:00 +++ a/drivers/scsi/sym53c8xx_2/sym_nvram.c 2004-09-26 11:11:46 -07:00 @@ -22,19 +22,32 @@ * *----------------------------------------------------------------------------- * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. * + * Where this Software is combined with software released under the terms of + * the GNU Public License ("GPL") and the terms of the GPL would require the + * combined work to also be released under the terms of the GPL, the terms + * and conditions of this License will apply in addition to those of the + * GPL with the exception of any terms or conditions of this License that + * conflict with, or are expressly prohibited by, the GPL. - * 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. * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "sym_glue.h" reverted: --- b/drivers/scsi/sym53c8xx_2/sym_nvram.h 2004-09-26 11:11:46 -07:00 +++ a/drivers/scsi/sym53c8xx_2/sym_nvram.h 2004-09-26 11:11:46 -07:00 @@ -22,19 +22,32 @@ * *----------------------------------------------------------------------------- * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. * + * Where this Software is combined with software released under the terms of + * the GNU Public License ("GPL") and the terms of the GPL would require the + * combined work to also be released under the terms of the GPL, the terms + * and conditions of this License will apply in addition to those of the + * GPL with the exception of any terms or conditions of this License that + * conflict with, or are expressly prohibited by, the GPL. - * 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. * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef SYM_NVRAM_H reverted: --- b/drivers/scsi/sym53c8xx_comm.h 2004-09-26 11:11:46 -07:00 +++ a/drivers/scsi/sym53c8xx_comm.h 2004-09-26 11:11:46 -07:00 @@ -54,6 +54,57 @@ ******************************************************************************* */ +/* +** This file contains definitions and code that the +** sym53c8xx and ncr53c8xx drivers should share. +** The sharing will be achieved in a further version +** of the driver bundle. For now, only the ncr53c8xx +** driver includes this file. +*/ + +/*========================================================== +** +** Hmmm... What complex some PCI-HOST bridges actually +** are, despite the fact that the PCI specifications +** are looking so smart and simple! ;-) +** +**========================================================== +*/ + +/*========================================================== +** +** Miscallaneous defines. +** +**========================================================== +*/ + +#define u_char unsigned char +#define u_long unsigned long + +#ifndef bzero +#define bzero(d, n) memset((d), 0, (n)) +#endif + +/*========================================================== +** +** assert () +** +**========================================================== +** +** modified copy from 386bsd:/usr/include/sys/assert.h +** +**---------------------------------------------------------- +*/ + +#define assert(expression) { \ + if (!(expression)) { \ + (void)panic( \ + "assertion \"%s\" failed: file \"%s\", line %d\n", \ + #expression, \ + __FILE__, __LINE__); \ + } \ +} + /*========================================================== ** ** Debugging tags @@ -86,22 +137,170 @@ #define DEBUG_FLAGS SCSI_NCR_DEBUG_FLAGS #endif +/*========================================================== +** +** 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) -static inline struct list_head *ncr_list_pop(struct list_head *head) { + struct xpt_quehead *first = list->flink; + + if (first != list) { + struct xpt_quehead *last = list->blink; + struct xpt_quehead *at = head->flink; - if (!list_empty(head)) { - struct list_head *elem = head->next; + first->blink = head; + head->flink = first; + + last->flink = at; + at->blink = last; - list_del(elem); - return elem; } +} + +#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 = NULL; + 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; - return NULL; } + +/*========================================================== +** +** 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.: by controller). +** +**========================================================== +*/ + +spinlock_t DRIVER_SMP_LOCK = SPIN_LOCK_UNLOCKED; +#define NCR_LOCK_DRIVER(flags) spin_lock_irqsave(&DRIVER_SMP_LOCK, flags) +#define NCR_UNLOCK_DRIVER(flags) \ + spin_unlock_irqrestore(&DRIVER_SMP_LOCK, flags) + +#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) + +#define NCR_LOCK_SCSI_DONE(host, flags) \ + spin_lock_irqsave((host)->host_lock, flags) +#define NCR_UNLOCK_SCSI_DONE(host, flags) \ + spin_unlock_irqrestore(((host)->host_lock), flags) + +/*========================================================== +** +** Memory mapped IO +** +** Since linux-2.1, we must use ioremap() to map the io +** memory space and iounmap() to unmap it. This allows +** portability. Linux 1.3.X and 2.0.X allow to remap +** physical pages addresses greater than the highest +** physical memory address to kernel virtual pages with +** vremap() / vfree(). That was not portable but worked +** with i386 architecture. +** +**========================================================== +*/ + #ifdef __sparc__ #include #endif +#define memcpy_to_pci(a, b, c) memcpy_toio((a), (b), (c)) + +/*========================================================== +** +** 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. +** +**========================================================== +*/ + +#define UDELAY udelay +#define MDELAY mdelay + /*========================================================== ** ** Simple power of two buddy-like allocator. @@ -120,6 +319,8 @@ **========================================================== */ +#define __GetFreePages(flags, order) __get_free_pages(flags, order) + #define MEMO_SHIFT 4 /* 16 bytes minimum memory chunk */ #if PAGE_SIZE >= 8192 #define MEMO_PAGE_ORDER 0 /* 1 PAGE maximum */ @@ -155,6 +356,10 @@ m_bush_t bush; m_addr_t (*getp)(struct m_pool *); void (*freep)(struct m_pool *, m_addr_t); +#define M_GETP() mp->getp(mp) +#define M_FREEP(p) mp->freep(mp, p) +#define GetPages() __GetFreePages(MEMO_GFP_FLAGS, MEMO_PAGE_ORDER) +#define FreePages(p) free_pages(p, MEMO_PAGE_ORDER) int nump; m_vtob_s *(vtob[VTOB_HASH_SIZE]); struct m_pool *next; @@ -180,7 +385,7 @@ j = i; while (!h[j].next) { if (s == (PAGE_SIZE << MEMO_PAGE_ORDER)) { + h[j].next = (m_link_s *) M_GETP(); - h[j].next = (m_link_s *)mp->getp(mp); if (h[j].next) h[j].next->next = NULL; break; @@ -229,7 +434,7 @@ while (1) { #ifdef MEMO_FREE_UNUSED if (s == (PAGE_SIZE << MEMO_PAGE_ORDER)) { + M_FREEP(a); - mp->freep(mp, a); break; } #endif @@ -250,8 +455,6 @@ } } -static spinlock_t ncr53c8xx_lock = SPIN_LOCK_UNLOCKED; - static void *__m_calloc2(m_pool_s *mp, int size, char *name, int uflags) { void *p; @@ -262,7 +465,7 @@ printk ("new %-10s[%4d] @%p.\n", name, size, p); if (p) + bzero(p, size); - memset(p, 0, size); else if (uflags & MEMO_WARN) printk (NAME53C8XX ": failed to allocate %s[%d]\n", name, size); @@ -288,7 +491,7 @@ static m_addr_t ___mp0_getp(m_pool_s *mp) { + m_addr_t m = GetPages(); - m_addr_t m = __get_free_pages(MEMO_GFP_FLAGS, MEMO_PAGE_ORDER); if (m) ++mp->nump; return m; @@ -296,7 +499,7 @@ static void ___mp0_freep(m_pool_s *mp, m_addr_t m) { + FreePages(m); - free_pages(m, MEMO_PAGE_ORDER); --mp->nump; } @@ -366,7 +569,7 @@ m_pool_s *mp; mp = __m_calloc(&mp0, sizeof(*mp), "MPOOL"); if (mp) { + bzero(mp, sizeof(*mp)); - memset(mp, 0, sizeof(*mp)); mp->bush = bush; mp->getp = ___dma_getp; mp->freep = ___dma_freep; @@ -394,7 +597,7 @@ struct m_pool *mp; void *m = NULL; + NCR_LOCK_DRIVER(flags); - spin_lock_irqsave(&ncr53c8xx_lock, flags); mp = ___get_dma_pool(bush); if (!mp) mp = ___cre_dma_pool(bush); @@ -402,7 +605,7 @@ m = __m_calloc(mp, size, name); if (mp && !mp->nump) ___del_dma_pool(mp); + NCR_UNLOCK_DRIVER(flags); - spin_unlock_irqrestore(&ncr53c8xx_lock, flags); return m; } @@ -412,13 +615,13 @@ u_long flags; struct m_pool *mp; + NCR_LOCK_DRIVER(flags); - spin_lock_irqsave(&ncr53c8xx_lock, flags); mp = ___get_dma_pool(bush); if (mp) __m_free(mp, m, size, name); if (mp && !mp->nump) ___del_dma_pool(mp); + NCR_UNLOCK_DRIVER(flags); - spin_unlock_irqrestore(&ncr53c8xx_lock, flags); } static m_addr_t __vtobus(m_bush_t bush, void *m) @@ -429,14 +632,14 @@ m_vtob_s *vp = NULL; m_addr_t a = ((m_addr_t) m) & ~MEMO_CLUSTER_MASK; + NCR_LOCK_DRIVER(flags); - spin_lock_irqsave(&ncr53c8xx_lock, flags); mp = ___get_dma_pool(bush); if (mp) { vp = mp->vtob[hc]; while (vp && (m_addr_t) vp->vaddr != a) vp = vp->next; } + NCR_UNLOCK_DRIVER(flags); - spin_unlock_irqrestore(&ncr53c8xx_lock, flags); return vp ? vp->baddr + (((m_addr_t) m) - a) : 0; } @@ -455,89 +658,100 @@ #define __data_mapped SCp.phase #define __data_mapping SCp.have_data_in +static void __unmap_scsi_data(struct device *dev, Scsi_Cmnd *cmd) -static void __unmap_scsi_data(struct device *dev, struct scsi_cmnd *cmd) { + enum dma_data_direction dma_dir = + (enum dma_data_direction)scsi_to_pci_dma_dir(cmd->sc_data_direction); + switch(cmd->__data_mapped) { case 2: + dma_unmap_sg(dev, cmd->buffer, cmd->use_sg, dma_dir); - dma_unmap_sg(dev, cmd->buffer, cmd->use_sg, - cmd->sc_data_direction); break; case 1: dma_unmap_single(dev, cmd->__data_mapping, + cmd->request_bufflen, dma_dir); - cmd->request_bufflen, - cmd->sc_data_direction); break; } cmd->__data_mapped = 0; } +static u_long __map_scsi_single_data(struct device *dev, Scsi_Cmnd *cmd) -static u_long __map_scsi_single_data(struct device *dev, struct scsi_cmnd *cmd) { dma_addr_t mapping; + enum dma_data_direction dma_dir = + (enum dma_data_direction)scsi_to_pci_dma_dir(cmd->sc_data_direction); + if (cmd->request_bufflen == 0) return 0; mapping = dma_map_single(dev, cmd->request_buffer, + cmd->request_bufflen, dma_dir); - cmd->request_bufflen, - cmd->sc_data_direction); cmd->__data_mapped = 1; cmd->__data_mapping = mapping; return mapping; } +static int __map_scsi_sg_data(struct device *dev, Scsi_Cmnd *cmd) -static int __map_scsi_sg_data(struct device *dev, struct scsi_cmnd *cmd) { int use_sg; + enum dma_data_direction dma_dir = + (enum dma_data_direction)scsi_to_pci_dma_dir(cmd->sc_data_direction); if (cmd->use_sg == 0) return 0; + use_sg = dma_map_sg(dev, cmd->buffer, cmd->use_sg, dma_dir); - use_sg = dma_map_sg(dev, cmd->buffer, cmd->use_sg, - cmd->sc_data_direction); cmd->__data_mapped = 2; cmd->__data_mapping = use_sg; return use_sg; } +static void __sync_scsi_data_for_cpu(struct device *dev, Scsi_Cmnd *cmd) -static void __sync_scsi_data_for_cpu(struct device *dev, struct scsi_cmnd *cmd) { + enum dma_data_direction dma_dir = + (enum dma_data_direction)scsi_to_pci_dma_dir(cmd->sc_data_direction); + switch(cmd->__data_mapped) { case 2: + dma_sync_sg_for_cpu(dev, cmd->buffer, cmd->use_sg, dma_dir); - dma_sync_sg_for_cpu(dev, cmd->buffer, cmd->use_sg, - cmd->sc_data_direction); break; case 1: dma_sync_single_for_cpu(dev, cmd->__data_mapping, + cmd->request_bufflen, dma_dir); - cmd->request_bufflen, - cmd->sc_data_direction); break; } } +static void __sync_scsi_data_for_device(struct device *dev, Scsi_Cmnd *cmd) -static void __sync_scsi_data_for_device(struct device *dev, struct scsi_cmnd *cmd) { + enum dma_data_direction dma_dir = + (enum dma_data_direction)scsi_to_pci_dma_dir(cmd->sc_data_direction); + switch(cmd->__data_mapped) { case 2: + dma_sync_sg_for_device(dev, cmd->buffer, cmd->use_sg, dma_dir); - dma_sync_sg_for_device(dev, cmd->buffer, cmd->use_sg, - cmd->sc_data_direction); break; case 1: dma_sync_single_for_device(dev, cmd->__data_mapping, + cmd->request_bufflen, dma_dir); - cmd->request_bufflen, - cmd->sc_data_direction); break; } } +#define scsi_sg_dma_address(sc) sg_dma_address(sc) +#define scsi_sg_dma_len(sc) sg_dma_len(sc) + #define unmap_scsi_data(np, cmd) __unmap_scsi_data(np->dev, cmd) #define map_scsi_single_data(np, cmd) __map_scsi_single_data(np->dev, cmd) #define map_scsi_sg_data(np, cmd) __map_scsi_sg_data(np->dev, cmd) #define sync_scsi_data_for_cpu(np, cmd) __sync_scsi_data_for_cpu(np->dev, cmd) #define sync_scsi_data_for_device(np, cmd) __sync_scsi_data_for_device(np->dev, cmd) +#define scsi_data_direction(cmd) (cmd->sc_data_direction) + /*========================================================== ** ** Driver setup. @@ -559,6 +773,58 @@ #define initverbose (driver_setup.verbose) #define bootverbose (np->verbose) + +/*=================================================================== +** +** Utility routines that protperly return data through /proc FS. +** +**=================================================================== +*/ +#ifdef SCSI_NCR_USER_INFO_SUPPORT + +struct info_str +{ + char *buffer; + int length; + int offset; + int pos; +}; + +static void copy_mem_info(struct info_str *info, char *data, int len) +{ + if (info->pos + len > info->length) + len = info->length - info->pos; + + if (info->pos + len < info->offset) { + info->pos += len; + return; + } + if (info->pos < info->offset) { + data += (info->offset - info->pos); + len -= (info->offset - info->pos); + } + + if (len > 0) { + memcpy(info->buffer + info->pos, data, len); + info->pos += len; + } +} + +static int copy_info(struct info_str *info, char *fmt, ...) +{ + va_list args; + char buf[81]; + int len; + + va_start(args, fmt); + len = vsprintf(buf, fmt, args); + va_end(args); + + copy_mem_info(info, buf, len); + return len; +} + +#endif /*=================================================================== ** reverted: --- b/drivers/scsi/sym53c8xx_defs.h 2004-09-26 11:11:47 -07:00 +++ a/drivers/scsi/sym53c8xx_defs.h 2004-09-26 11:11:47 -07:00 @@ -66,12 +66,19 @@ #include +/* These options are not tunable from 'make config' */ +#define SCSI_NCR_PROC_INFO_SUPPORT + /* ** 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 +#ifdef SCSI_NCR_PROC_INFO_SUPPORT +# define SCSI_NCR_USER_COMMAND_SUPPORT +# define SCSI_NCR_USER_INFO_SUPPORT +#endif /* ** To disable integrity checking, do not define the diff -u b/drivers/scsi/tmscsim.c b/drivers/scsi/tmscsim.c --- b/drivers/scsi/tmscsim.c 2004-09-26 11:11:47 -07:00 +++ b/drivers/scsi/tmscsim.c 2004-09-26 11:13:18 -07:00 @@ -388,6 +388,22 @@ * Lists are managed using two pointers and eventually a counter */ +/* Return next free SRB */ +static __inline__ struct dc390_srb* dc390_Free_get ( struct dc390_acb* pACB ) +{ + struct dc390_srb* pSRB; + + pSRB = pACB->pFreeSRB; + DEBUG0(printk ("DC390: Get Free SRB %p\n", pSRB)); + if( pSRB ) + { + pACB->pFreeSRB = pSRB->pNextSRB; + pSRB->pNextSRB = NULL; + } + + return( pSRB ); +} + /* Insert SRB oin top of free list */ static __inline__ void dc390_Free_insert (struct dc390_acb* pACB, struct dc390_srb* pSRB) { @@ -409,6 +425,21 @@ } +/* Queue SRB to waiting list */ +static __inline__ void dc390_Waiting_append ( struct dc390_dcb* pDCB, struct dc390_srb* pSRB) +{ + DEBUG0(printk ("DC390: Append pSRB %p cmd %li to Waiting\n", pSRB, pSRB->pcmd->pid)); + if( pDCB->pWaitingSRB ) + pDCB->pWaitLast->pNextSRB = pSRB; + else + pDCB->pWaitingSRB = pSRB; + + pDCB->pWaitLast = pSRB; + pSRB->pNextSRB = NULL; + pDCB->WaitSRBCnt++; + pDCB->pDCBACB->CmdInQ++; +} + static __inline__ void dc390_Going_append (struct dc390_dcb* pDCB, struct dc390_srb* pSRB) { pDCB->GoingSRBCnt++; @@ -528,6 +559,47 @@ spin_unlock_irqrestore(pACB->pScsiHost->host_lock, iflags); } +/*********************************************************************** + * Function: static void dc390_SendSRB (struct dc390_acb* pACB, struct dc390_srb* pSRB) + * + * Purpose: Send SCSI Request Block (pSRB) to adapter (pACB) + * + ***********************************************************************/ + +static void dc390_SendSRB( struct dc390_acb* pACB, struct dc390_srb* pSRB ) +{ + struct dc390_dcb* pDCB; + + pDCB = pSRB->pSRBDCB; + if( (pDCB->MaxCommand <= pDCB->GoingSRBCnt) || (pACB->pActiveDCB) || + (pACB->ACBFlag & (RESET_DETECT+RESET_DONE+RESET_DEV)) ) + { + dc390_Waiting_append (pDCB, pSRB); + dc390_Waiting_process (pACB); + return; + } + +#if 0 + if( pDCB->pWaitingSRB ) + { + dc390_Waiting_append (pDCB, pSRB); +/* pSRB = GetWaitingSRB(pDCB); */ /* non-existent */ + pSRB = pDCB->pWaitingSRB; + /* Remove from waiting list */ + pDCB->pWaitingSRB = pSRB->pNextSRB; + pSRB->pNextSRB = NULL; + if (!pDCB->pWaitingSRB) pDCB->pWaitLast = NULL; + } +#endif + + if (!dc390_StartSCSI(pACB, pDCB, pSRB)) + dc390_Going_append (pDCB, pSRB); + else { + dc390_Waiting_insert (pDCB, pSRB); + dc390_waiting_timer (pACB, HZ/5); + } +} + static struct scatterlist* dc390_sg_build_single(struct scatterlist *sg, void *addr, unsigned int length) { memset(sg, 0, sizeof(struct scatterlist)); @@ -603,72 +675,86 @@ } } -static int DC390_queuecommand(struct scsi_cmnd *cmd, - void (*done)(struct scsi_cmnd *)) -{ - struct scsi_device *sdev = cmd->device; - struct dc390_acb *acb = (struct dc390_acb *)sdev->host->hostdata; - struct dc390_dcb *dcb = sdev->hostdata; - struct dc390_srb *srb; - - if (dcb->pWaitingSRB) - goto device_busy; - if (dcb->MaxCommand <= dcb->GoingSRBCnt) - goto device_busy; - if (acb->pActiveDCB) - goto host_busy; - if (acb->ACBFlag & (RESET_DETECT|RESET_DONE|RESET_DEV)) - goto host_busy; - - srb = acb->pFreeSRB; - if (unlikely(srb == NULL)) - goto host_busy; - - cmd->scsi_done = done; - cmd->result = 0; - acb->Cmds++; - acb->pFreeSRB = srb->pNextSRB; - srb->pNextSRB = NULL; +/*********************************************************************** + * Function: static void dc390_BuildSRB (Scsi_Cmd *pcmd, struct dc390_dcb* pDCB, + * struct dc390_srb* pSRB) + * + * Purpose: Prepare SRB for being sent to Device DCB w/ command *pcmd + * + ***********************************************************************/ - srb->pSRBDCB = dcb; - srb->pcmd = cmd; +static void dc390_BuildSRB (struct scsi_cmnd *pcmd, struct dc390_dcb* pDCB, struct dc390_srb* pSRB) +{ + pSRB->pSRBDCB = pDCB; + pSRB->pcmd = pcmd; - srb->SGIndex = 0; - srb->AdaptStatus = 0; - srb->TargetStatus = 0; - srb->MsgCnt = 0; - if (dcb->DevType == TYPE_TAPE) - srb->RetryCnt = 0; - else - srb->RetryCnt = 1; - srb->SRBStatus = 0; - srb->SRBFlag = 0; - srb->SRBState = 0; - srb->TotalXferredLen = 0; - srb->SGBusAddr = 0; - srb->SGToBeXferLen = 0; - srb->ScsiPhase = 0; - srb->EndMessage = 0; - srb->TagNumber = 255; - - if (dc390_StartSCSI(acb, dcb, srb)) { - dc390_Waiting_insert(dcb, srb); - dc390_waiting_timer(acb, HZ/5); - goto done; - } + pSRB->SGIndex = 0; + pSRB->AdaptStatus = 0; + pSRB->TargetStatus = 0; + pSRB->MsgCnt = 0; + if( pDCB->DevType != TYPE_TAPE ) + pSRB->RetryCnt = 1; + else + pSRB->RetryCnt = 0; + pSRB->SRBStatus = 0; + pSRB->SRBFlag = 0; + pSRB->SRBState = 0; + pSRB->TotalXferredLen = 0; + pSRB->SGBusAddr = 0; + pSRB->SGToBeXferLen = 0; + pSRB->ScsiPhase = 0; + pSRB->EndMessage = 0; + pSRB->TagNumber = 255; + /* KG: deferred PCI mapping to dc390_StartSCSI */ +} - dc390_Going_append(dcb, srb); - done: - return 0; +/*********************************************************************** + * Function : static int DC390_queue_command (struct scsi_cmnd *cmd, + * void (*done)(struct scsi_cmnd *)) + * + * Purpose : enqueues a SCSI command + * + * Inputs : cmd - SCSI command, done - callback function called on + * completion, with a pointer to the command descriptor. + * + * Returns : (depending on kernel version) + * 2.0.x: always return 0 + * 2.1.x: old model: (use_new_eh_code == 0): like 2.0.x + * TO BE DONE: + * new model: return 0 if successful, or must not be re-queued + * return 1 if command cannot be queued (queue full) + * command will be inserted in midlevel queue then ... + * + ***********************************************************************/ + +static int DC390_queue_command(struct scsi_cmnd *cmd, + void (* done)(struct scsi_cmnd *)) +{ + struct dc390_dcb* pDCB = (struct dc390_dcb*) cmd->device->hostdata; + struct dc390_srb* pSRB; + struct dc390_acb* pACB = (struct dc390_acb*) cmd->device->host->hostdata; + + pACB->Cmds++; + cmd->scsi_done = done; + cmd->result = 0; + + pSRB = dc390_Free_get(pACB); + if (!pSRB) + goto requeue; + + dc390_BuildSRB(cmd, pDCB, pSRB); + if (pDCB->pWaitingSRB) { + dc390_Waiting_append(pDCB, pSRB); + dc390_Waiting_process(pACB); + } else + dc390_SendSRB(pACB, pSRB); + + DEBUG1(printk (KERN_DEBUG " ... command (pid %li) queued successfully.\n", cmd->pid)); + return(0); - host_busy: - dc390_Waiting_process(acb); - return SCSI_MLQUEUE_HOST_BUSY; - - device_busy: - dc390_Waiting_process(acb); - return SCSI_MLQUEUE_DEVICE_BUSY; + requeue: + return 1; } static void dc390_dumpinfo (struct dc390_acb* pACB, struct dc390_dcb* pDCB, struct dc390_srb* pSRB) @@ -979,7 +1065,7 @@ .slave_alloc = dc390_slave_alloc, .slave_configure = dc390_slave_configure, .slave_destroy = dc390_slave_destroy, - .queuecommand = DC390_queuecommand, + .queuecommand = DC390_queue_command, .eh_abort_handler = DC390_abort, .eh_bus_reset_handler = DC390_bus_reset, .can_queue = 42, @@ -989,7 +1075,7 @@ .use_clustering = DISABLE_CLUSTERING, }; -static void __devinit dc390_eeprom_prepare_read(struct pci_dev *pdev, u8 cmd) +static void __devinit dc390_eeprom_prepare_read(struct pci_dev *pdev, u8 cd) { u8 carryFlag = 1, j = 0x80, i, bval, regval; diff -u b/include/scsi/scsi_device.h b/include/scsi/scsi_device.h --- b/include/scsi/scsi_device.h 2004-09-26 11:11:45 -07:00 +++ b/include/scsi/scsi_device.h 2004-09-26 11:13:18 -07:00 @@ -106,7 +106,6 @@ unsigned use_192_bytes_for_3f:1; /* ask for 192 bytes from page 0x3f */ unsigned no_start_on_add:1; /* do not issue start on add */ unsigned allow_restart:1; /* issue START_UNIT in error handler */ - unsigned no_uld_attach:1; /* disable connecting to upper level drivers */ unsigned int device_blocked; /* Device returned QUEUE_FULL. */ @@ -121,7 +120,7 @@ struct class_device transport_classdev; enum scsi_device_state sdev_state; - unsigned long transport_data[0]; + unsigned long sdev_data[0]; } __attribute__((aligned(sizeof(unsigned long)))); #define to_scsi_device(d) \ container_of(d, struct scsi_device, sdev_gendev) @@ -130,6 +129,30 @@ #define transport_class_to_sdev(class_dev) \ container_of(class_dev, struct scsi_device, transport_classdev) +/* + * scsi_target: representation of a scsi target, for now, this is only + * used for single_lun devices. If no one has active IO to the target, + * starget_sdev_user is NULL, else it points to the active sdev. + */ +struct scsi_target { + struct scsi_device *starget_sdev_user; + struct device dev; + unsigned int channel; + unsigned int id; /* target id ... replace + * scsi_device.id eventually */ + struct class_device transport_classdev; + unsigned long create:1; /* signal that it needs to be added */ + unsigned long starget_data[0]; +} __attribute__((aligned(sizeof(unsigned long)))); + +#define to_scsi_target(d) container_of(d, struct scsi_target, dev) +static inline struct scsi_target *scsi_target(struct scsi_device *sdev) +{ + return to_scsi_target(sdev->sdev_gendev.parent); +} +#define transport_class_to_starget(class_dev) \ + container_of(class_dev, struct scsi_target, transport_classdev) + extern struct scsi_device *__scsi_add_device(struct Scsi_Host *, uint, uint, uint, void *hostdata); #define scsi_add_device(host, channel, target, lun) \ @@ -192,6 +215,8 @@ enum scsi_device_state state); extern int scsi_device_quiesce(struct scsi_device *sdev); extern void scsi_device_resume(struct scsi_device *sdev); +extern void scsi_target_quiesce(struct scsi_target *); +extern void scsi_target_resume(struct scsi_target *); extern const char *scsi_device_state_name(enum scsi_device_state); static inline int scsi_device_online(struct scsi_device *sdev) { reverted: --- b/include/scsi/scsi_devinfo.h 2004-09-26 11:11:45 -07:00 +++ a/include/scsi/scsi_devinfo.h 2004-09-26 11:11:45 -07:00 @@ -25,5 +25,4 @@ (if HBA supports more than 8 LUNs) */ #define BLIST_NOREPORTLUN 0x40000 /* don't try REPORT_LUNS scan (SCSI-3 devs) */ #define BLIST_NOT_LOCKABLE 0x80000 /* don't use PREVENT-ALLOW commands */ -#define BLIST_NO_ULD_ATTACH 0x100000 /* device is actually for RAID config */ #endif diff -u b/include/scsi/scsi_host.h b/include/scsi/scsi_host.h --- b/include/scsi/scsi_host.h 2004-09-26 11:11:45 -07:00 +++ b/include/scsi/scsi_host.h 2004-09-26 11:13:18 -07:00 @@ -146,6 +146,15 @@ enum scsi_eh_timer_return (* eh_timed_out)(struct scsi_cmnd *); /* + * Old EH handlers, no longer used. Make them warn the user of old + * drivers by using a wrong type + * + * Status: MORE THAN OBSOLETE + */ + int (* abort)(int); + int (* reset)(int, int); + + /* * Before the mid layer attempts to scan for a new device where none * currently exists, it will call this entry in your driver. Should * your driver need to allocate any structs or perform any other init @@ -502,6 +511,13 @@ struct list_head sht_legacy_list; /* + * Points to the transport data (if any) which is allocated + * separately + */ + void *shost_data; + struct class_device transport_classdev; + + /* * We should ensure that this is aligned, both for better performance * and also because some compilers (m68k) don't automatically force * alignment to a long boundary. @@ -513,9 +529,12 @@ container_of(d, struct Scsi_Host, shost_gendev) #define class_to_shost(d) \ container_of(d, struct Scsi_Host, shost_classdev) +#define transport_class_to_shost(class_dev) \ + container_of(class_dev, struct Scsi_Host, transport_classdev) + extern struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *, int); -extern int __must_check scsi_add_host(struct Scsi_Host *, struct device *); +extern int scsi_add_host(struct Scsi_Host *, struct device *); extern void scsi_scan_host(struct Scsi_Host *); extern void scsi_remove_host(struct Scsi_Host *); extern struct Scsi_Host *scsi_host_get(struct Scsi_Host *); reverted: --- b/include/scsi/scsi_ioctl.h 2004-09-26 11:11:45 -07:00 +++ a/include/scsi/scsi_ioctl.h 2004-09-26 11:11:45 -07:00 @@ -43,8 +43,6 @@ extern int scsi_ioctl(struct scsi_device *, int, void __user *); extern int scsi_ioctl_send_command(struct scsi_device *, struct scsi_ioctl_command __user *); -extern int scsi_nonblockable_ioctl(struct scsi_device *sdev, int cmd, - void __user *arg, struct file *filp); #endif /* __KERNEL__ */ #endif /* _SCSI_IOCTL_H */ only in patch2: unchanged: --- a/drivers/scsi/53c700.c 2004-09-26 11:13:18 -07:00 +++ b/drivers/scsi/53c700.c 2004-09-26 11:13:18 -07:00 @@ -287,8 +287,9 @@ struct NCR_700_Host_Parameters *hostdata = (struct NCR_700_Host_Parameters *)SDp->host->hostdata[0]; - return NCR_700_offset_period_to_sxfer(hostdata, spi_offset(SDp), - spi_period(SDp)); + return NCR_700_offset_period_to_sxfer(hostdata, + spi_offset(SDp->sdev_target), + spi_period(SDp->sdev_target)); } struct Scsi_Host * @@ -403,6 +404,8 @@ (hostdata->fast ? "53c700-66" : "53c700"), hostdata->rev, hostdata->differential ? "(Differential)" : ""); + spi_signalling(host) = hostdata->differential ? SPI_SIGNAL_HVD : + SPI_SIGNAL_SE; /* reset the chip */ NCR_700_chip_reset(host); @@ -803,7 +806,7 @@ } if(NCR_700_is_flag_set(SCp->device, NCR_700_DEV_PRINT_SYNC_NEGOTIATION)) { - if(spi_offset(SCp->device) != 0) + if(spi_offset(SCp->device->sdev_target) != 0) printk(KERN_INFO "scsi%d: (%d:%d) Synchronous at offset %d, period %dns\n", host->host_no, pun, lun, offset, period*4); @@ -813,8 +816,8 @@ NCR_700_clear_flag(SCp->device, NCR_700_DEV_PRINT_SYNC_NEGOTIATION); } - spi_offset(SCp->device) = offset; - spi_period(SCp->device) = period; + spi_offset(SCp->device->sdev_target) = offset; + spi_period(SCp->device->sdev_target) = period; NCR_700_set_flag(SCp->device, NCR_700_DEV_NEGOTIATED_SYNC); @@ -894,7 +897,8 @@ case A_REJECT_MSG: if(SCp != NULL && NCR_700_is_flag_set(SCp->device, NCR_700_DEV_BEGIN_SYNC_NEGOTIATION)) { /* Rejected our sync negotiation attempt */ - spi_period(SCp->device) = spi_offset(SCp->device) = 0; + spi_period(SCp->device->sdev_target) = + spi_offset(SCp->device->sdev_target) = 0; NCR_700_set_flag(SCp->device, NCR_700_DEV_NEGOTIATED_SYNC); NCR_700_clear_flag(SCp->device, NCR_700_DEV_BEGIN_SYNC_NEGOTIATION); } else if(SCp != NULL && NCR_700_is_flag_set(SCp->device, NCR_700_DEV_BEGIN_TAG_QUEUEING)) { @@ -1420,8 +1424,8 @@ NCR_700_is_flag_clear(SCp->device, NCR_700_DEV_NEGOTIATED_SYNC)) { memcpy(&hostdata->msgout[count], NCR_700_SDTR_msg, sizeof(NCR_700_SDTR_msg)); - hostdata->msgout[count+3] = spi_period(SCp->device); - hostdata->msgout[count+4] = spi_offset(SCp->device); + hostdata->msgout[count+3] = spi_period(SCp->device->sdev_target); + hostdata->msgout[count+4] = spi_offset(SCp->device->sdev_target); count += sizeof(NCR_700_SDTR_msg); NCR_700_set_flag(SCp->device, NCR_700_DEV_BEGIN_SYNC_NEGOTIATION); } @@ -1999,10 +2003,11 @@ } STATIC void -NCR_700_set_period(struct scsi_device *SDp, int period) +NCR_700_set_period(struct scsi_target *STp, int period) { + struct Scsi_Host *SHp = dev_to_shost(STp->dev.parent); struct NCR_700_Host_Parameters *hostdata = - (struct NCR_700_Host_Parameters *)SDp->host->hostdata[0]; + (struct NCR_700_Host_Parameters *)SHp->hostdata[0]; if(!hostdata->fast) return; @@ -2010,17 +2015,18 @@ if(period < hostdata->min_period) period = hostdata->min_period; - spi_period(SDp) = period; - NCR_700_clear_flag(SDp, NCR_700_DEV_NEGOTIATED_SYNC); - NCR_700_clear_flag(SDp, NCR_700_DEV_BEGIN_SYNC_NEGOTIATION); - NCR_700_set_flag(SDp, NCR_700_DEV_PRINT_SYNC_NEGOTIATION); + spi_period(STp) = period; + spi_flags(STp) &= ~(NCR_700_DEV_NEGOTIATED_SYNC | + NCR_700_DEV_BEGIN_SYNC_NEGOTIATION); + spi_flags(STp) |= NCR_700_DEV_PRINT_SYNC_NEGOTIATION; } STATIC void -NCR_700_set_offset(struct scsi_device *SDp, int offset) +NCR_700_set_offset(struct scsi_target *STp, int offset) { + struct Scsi_Host *SHp = dev_to_shost(STp->dev.parent); struct NCR_700_Host_Parameters *hostdata = - (struct NCR_700_Host_Parameters *)SDp->host->hostdata[0]; + (struct NCR_700_Host_Parameters *)SHp->hostdata[0]; int max_offset = hostdata->chip710 ? NCR_710_MAX_OFFSET : NCR_700_MAX_OFFSET; @@ -2031,14 +2037,14 @@ offset = max_offset; /* if we're currently async, make sure the period is reasonable */ - if(spi_offset(SDp) == 0 && (spi_period(SDp) < hostdata->min_period || - spi_period(SDp) > 0xff)) - spi_period(SDp) = hostdata->min_period; - - spi_offset(SDp) = offset; - NCR_700_clear_flag(SDp, NCR_700_DEV_NEGOTIATED_SYNC); - NCR_700_clear_flag(SDp, NCR_700_DEV_BEGIN_SYNC_NEGOTIATION); - NCR_700_set_flag(SDp, NCR_700_DEV_PRINT_SYNC_NEGOTIATION); + if(spi_offset(STp) == 0 && (spi_period(STp) < hostdata->min_period || + spi_period(STp) > 0xff)) + spi_period(STp) = hostdata->min_period; + + spi_offset(STp) = offset; + spi_flags(STp) &= ~(NCR_700_DEV_NEGOTIATED_SYNC | + NCR_700_DEV_BEGIN_SYNC_NEGOTIATION); + spi_flags(STp) |= NCR_700_DEV_PRINT_SYNC_NEGOTIATION; } @@ -2058,10 +2064,11 @@ } if(hostdata->fast) { /* Find the correct offset and period via domain validation */ - spi_dv_device(SDp); + if (!spi_initial_dv(SDp->sdev_target)) + spi_dv_device(SDp); } else { - spi_offset(SDp) = 0; - spi_period(SDp) = 0; + spi_offset(SDp->sdev_target) = 0; + spi_period(SDp->sdev_target) = 0; } return 0; } only in patch2: unchanged: --- a/drivers/scsi/53c700.h 2004-09-26 11:13:18 -07:00 +++ b/drivers/scsi/53c700.h 2004-09-26 11:13:18 -07:00 @@ -121,22 +121,22 @@ static inline int NCR_700_is_flag_set(struct scsi_device *SDp, __u32 flag) { - return (((unsigned long)SDp->hostdata) & flag) == flag; + return (spi_flags(SDp->sdev_target) & flag) == flag; } static inline int NCR_700_is_flag_clear(struct scsi_device *SDp, __u32 flag) { - return (((unsigned long)SDp->hostdata) & flag) == 0; + return (spi_flags(SDp->sdev_target) & flag) == 0; } static inline void NCR_700_set_flag(struct scsi_device *SDp, __u32 flag) { - SDp->hostdata = (void *)((long)SDp->hostdata | (flag & 0xffff0000)); + spi_flags(SDp->sdev_target) |= flag; } static inline void NCR_700_clear_flag(struct scsi_device *SDp, __u32 flag) { - SDp->hostdata = (void *)((long)SDp->hostdata & ~(flag & 0xffff0000)); + spi_flags(SDp->sdev_target) &= ~flag; } struct NCR_700_command_slot { only in patch2: unchanged: --- a/drivers/scsi/NCR_D700.c 2004-09-26 11:13:18 -07:00 +++ b/drivers/scsi/NCR_D700.c 2004-09-26 11:13:18 -07:00 @@ -99,6 +99,9 @@ #include #include #include +#include +#include +#include #include "53c700.h" #include "NCR_D700.h" only in patch2: unchanged: --- a/drivers/scsi/hosts.c 2004-09-26 11:13:18 -07:00 +++ b/drivers/scsi/hosts.c 2004-09-26 11:13:18 -07:00 @@ -82,6 +82,8 @@ set_bit(SHOST_DEL, &shost->shost_state); class_device_unregister(&shost->shost_classdev); + if (shost->transport_classdev.class) + class_device_unregister(&shost->transport_classdev); device_del(&shost->shost_gendev); } @@ -154,6 +156,7 @@ scsi_proc_hostdir_rm(shost->hostt); scsi_destroy_command_freelist(shost); + kfree(shost->shost_data); /* * Some drivers (eg aha1542) do scsi_register()/scsi_unregister() @@ -278,15 +281,26 @@ snprintf(shost->shost_classdev.class_id, BUS_ID_SIZE, "host%d", shost->host_no); + if (shost->transportt->host_size && + (shost->shost_data = kmalloc(shost->transportt->host_size, + GFP_KERNEL)) == NULL) + goto fail_destroy_freelist; + + if (shost->transportt->host_setup) + shost->transportt->host_setup(shost); + shost->eh_notify = &complete; rval = kernel_thread(scsi_error_handler, shost, 0); if (rval < 0) - goto fail_destroy_freelist; + goto fail_free_shost_data; wait_for_completion(&complete); shost->eh_notify = NULL; + scsi_proc_hostdir_add(shost->hostt); return shost; + fail_free_shost_data: + kfree(shost->shost_data); fail_destroy_freelist: scsi_destroy_command_freelist(shost); fail_kfree: only in patch2: unchanged: --- a/drivers/scsi/lasi700.c 2004-09-26 11:13:18 -07:00 +++ b/drivers/scsi/lasi700.c 2004-09-26 11:13:18 -07:00 @@ -50,6 +50,9 @@ #include #include +#include +#include +#include #include "lasi700.h" #include "53c700.h" only in patch2: unchanged: --- a/drivers/scsi/scsi_priv.h 2004-09-26 11:13:18 -07:00 +++ b/drivers/scsi/scsi_priv.h 2004-09-26 11:13:18 -07:00 @@ -58,16 +58,6 @@ */ #define SCAN_WILD_CARD ~0 -/* - * scsi_target: representation of a scsi target, for now, this is only - * used for single_lun devices. If no one has active IO to the target, - * starget_sdev_user is NULL, else it points to the active sdev. - */ -struct scsi_target { - struct scsi_device *starget_sdev_user; - unsigned int starget_refcnt; -}; - /* hosts.c */ extern int scsi_init_hosts(void); extern void scsi_exit_hosts(void); @@ -156,6 +146,8 @@ extern int scsi_sysfs_add_host(struct Scsi_Host *); extern int scsi_sysfs_register(void); extern void scsi_sysfs_unregister(void); +extern int scsi_sysfs_device_initialize(struct scsi_device *); +extern int scsi_sysfs_target_initialize(struct scsi_device *); extern struct scsi_transport_template blank_transport_template; extern struct class sdev_class; only in patch2: unchanged: --- a/drivers/scsi/scsi_transport_fc.c 2004-09-26 11:13:18 -07:00 +++ b/drivers/scsi/scsi_transport_fc.c 2004-09-26 11:13:18 -07:00 @@ -84,7 +84,7 @@ struct scsi_device *sdev = transport_class_to_sdev(cdev); \ struct fc_transport_attrs *tp; \ struct fc_internal *i = to_fc_internal(sdev->host->transportt); \ - tp = (struct fc_transport_attrs *)&sdev->transport_data; \ + tp = (struct fc_transport_attrs *)&sdev->sdev_data; \ if (i->f->get_##field) \ i->f->get_##field(sdev); \ return snprintf(buf, 20, format_string, cast tp->field); \ @@ -156,10 +156,10 @@ memset(i, 0, sizeof(struct fc_internal)); - i->t.attrs = &i->attrs[0]; - i->t.class = &fc_transport_class; - i->t.setup = &fc_setup_transport_attrs; - i->t.size = sizeof(struct fc_transport_attrs); + i->t.device_attrs = &i->attrs[0]; + i->t.device_class = &fc_transport_class; + i->t.device_setup = &fc_setup_transport_attrs; + i->t.device_size = sizeof(struct fc_transport_attrs); i->f = ft; SETUP_ATTRIBUTE_RD(port_id); only in patch2: unchanged: --- a/drivers/scsi/scsi_transport_spi.c 2004-09-26 11:13:18 -07:00 +++ b/drivers/scsi/scsi_transport_spi.c 2004-09-26 11:13:18 -07:00 @@ -27,25 +27,28 @@ #include #include #include +#include "scsi_priv.h" #include #include #include #include #include -#define SPI_PRINTK(x, l, f, a...) printk(l "scsi(%d:%d:%d:%d): " f, (x)->host->host_no, (x)->channel, (x)->id, (x)->lun , ##a) +#define SPI_PRINTK(x, l, f, a...) dev_printk(l, &(x)->dev, f , ##a) static void transport_class_release(struct class_device *class_dev); +static void host_class_release(struct class_device *class_dev); #define SPI_NUM_ATTRS 10 /* increase this if you add attributes */ #define SPI_OTHER_ATTRS 1 /* Increase this if you add "always * on" attributes */ +#define SPI_HOST_ATTRS 1 #define SPI_MAX_ECHO_BUFFER_SIZE 4096 /* Private data accessors (keep these out of the header file) */ -#define spi_dv_pending(x) (((struct spi_transport_attrs *)&(x)->transport_data)->dv_pending) -#define spi_dv_sem(x) (((struct spi_transport_attrs *)&(x)->transport_data)->dv_sem) +#define spi_dv_pending(x) (((struct spi_transport_attrs *)&(x)->starget_data)->dv_pending) +#define spi_dv_sem(x) (((struct spi_transport_attrs *)&(x)->starget_data)->dv_sem) struct spi_internal { struct scsi_transport_template t; @@ -55,6 +58,8 @@ /* The array of null terminated pointers to attributes * needed by scsi_sysfs.c */ struct class_device_attribute *attrs[SPI_NUM_ATTRS + SPI_OTHER_ATTRS + 1]; + struct class_device_attribute private_host_attrs[SPI_HOST_ATTRS]; + struct class_device_attribute *host_attrs[SPI_HOST_ATTRS + 1]; }; #define to_spi_internal(tmpl) container_of(tmpl, struct spi_internal, t) @@ -80,43 +85,100 @@ * by 4 */ #define SPI_STATIC_PPR 0x0c +static struct { + enum spi_signal_type value; + char *name; +} signal_types[] = { + { SPI_SIGNAL_UNKNOWN, "unknown" }, + { SPI_SIGNAL_SE, "SE" }, + { SPI_SIGNAL_LVD, "LVD" }, + { SPI_SIGNAL_HVD, "HVD" }, +}; + +static inline const char *spi_signal_to_string(enum spi_signal_type type) +{ + int i; + + for (i = 0; i < sizeof(signal_types)/sizeof(signal_types[0]); i++) { + if (type == signal_types[i].value) + return signal_types[i].name; + } + return NULL; +} +static inline enum spi_signal_type spi_signal_to_value(const char *name) +{ + int i, len; + + for (i = 0; i < sizeof(signal_types)/sizeof(signal_types[0]); i++) { + len = strlen(signal_types[i].name); + if (strncmp(name, signal_types[i].name, len) == 0 && + (name[len] == '\n' || name[len] == '\0')) + return signal_types[i].value; + } + return SPI_SIGNAL_UNKNOWN; +} + + struct class spi_transport_class = { .name = "spi_transport", .release = transport_class_release, }; +struct class spi_host_class = { + .name = "spi_host", + .release = host_class_release, +}; + static __init int spi_transport_init(void) { + int error = class_register(&spi_host_class); + if (error) + return error; return class_register(&spi_transport_class); } static void __exit spi_transport_exit(void) { class_unregister(&spi_transport_class); + class_unregister(&spi_host_class); +} + +static int spi_setup_host_attrs(struct Scsi_Host *shost) +{ + spi_signalling(shost) = SPI_SIGNAL_UNKNOWN; + + return 0; } -static int spi_setup_transport_attrs(struct scsi_device *sdev) +static int spi_setup_transport_attrs(struct scsi_target *starget) { - spi_period(sdev) = -1; /* illegal value */ - spi_offset(sdev) = 0; /* async */ - spi_width(sdev) = 0; /* narrow */ - spi_iu(sdev) = 0; /* no IU */ - spi_dt(sdev) = 0; /* ST */ - spi_qas(sdev) = 0; - spi_wr_flow(sdev) = 0; - spi_rd_strm(sdev) = 0; - spi_rti(sdev) = 0; - spi_pcomp_en(sdev) = 0; - spi_dv_pending(sdev) = 0; - init_MUTEX(&spi_dv_sem(sdev)); + spi_period(starget) = -1; /* illegal value */ + spi_offset(starget) = 0; /* async */ + spi_width(starget) = 0; /* narrow */ + spi_iu(starget) = 0; /* no IU */ + spi_dt(starget) = 0; /* ST */ + spi_qas(starget) = 0; + spi_wr_flow(starget) = 0; + spi_rd_strm(starget) = 0; + spi_rti(starget) = 0; + spi_pcomp_en(starget) = 0; + spi_dv_pending(starget) = 0; + spi_initial_dv(starget) = 0; + init_MUTEX(&spi_dv_sem(starget)); return 0; } static void transport_class_release(struct class_device *class_dev) { - struct scsi_device *sdev = transport_class_to_sdev(class_dev); - put_device(&sdev->sdev_gendev); + struct scsi_target *starget = transport_class_to_starget(class_dev); + put_device(&starget->dev); +} + +static void host_class_release(struct class_device *class_dev) +{ + struct Scsi_Host *shost = transport_class_to_shost(class_dev); + put_device(&shost->shost_gendev); } #define spi_transport_show_function(field, format_string) \ @@ -124,12 +186,13 @@ static ssize_t \ show_spi_transport_##field(struct class_device *cdev, char *buf) \ { \ - struct scsi_device *sdev = transport_class_to_sdev(cdev); \ + struct scsi_target *starget = transport_class_to_starget(cdev); \ + struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); \ struct spi_transport_attrs *tp; \ - struct spi_internal *i = to_spi_internal(sdev->host->transportt); \ - tp = (struct spi_transport_attrs *)&sdev->transport_data; \ + struct spi_internal *i = to_spi_internal(shost->transportt); \ + tp = (struct spi_transport_attrs *)&starget->starget_data; \ if (i->f->get_##field) \ - i->f->get_##field(sdev); \ + i->f->get_##field(starget); \ return snprintf(buf, 20, format_string, tp->field); \ } @@ -139,11 +202,12 @@ size_t count) \ { \ int val; \ - struct scsi_device *sdev = transport_class_to_sdev(cdev); \ - struct spi_internal *i = to_spi_internal(sdev->host->transportt); \ + struct scsi_target *starget = transport_class_to_starget(cdev); \ + struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); \ + struct spi_internal *i = to_spi_internal(shost->transportt); \ \ val = simple_strtoul(buf, NULL, 0); \ - i->f->set_##field(sdev, val); \ + i->f->set_##field(starget, val); \ return count; \ } @@ -168,8 +232,13 @@ static ssize_t store_spi_revalidate(struct class_device *cdev, const char *buf, size_t count) { - struct scsi_device *sdev = transport_class_to_sdev(cdev); + struct scsi_target *starget = transport_class_to_starget(cdev); + /* FIXME: we're relying on an awful lot of device internals + * here. We really need a function to get the first available + * child */ + struct device *dev = container_of(starget->dev.children.next, struct device, node); + struct scsi_device *sdev = to_scsi_device(dev); spi_dv_device(sdev); return count; } @@ -180,15 +249,16 @@ static ssize_t show_spi_transport_period(struct class_device *cdev, char *buf) { - struct scsi_device *sdev = transport_class_to_sdev(cdev); + struct scsi_target *starget = transport_class_to_starget(cdev); + struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); struct spi_transport_attrs *tp; const char *str; - struct spi_internal *i = to_spi_internal(sdev->host->transportt); + struct spi_internal *i = to_spi_internal(shost->transportt); - tp = (struct spi_transport_attrs *)&sdev->transport_data; + tp = (struct spi_transport_attrs *)&starget->starget_data; if (i->f->get_period) - i->f->get_period(sdev); + i->f->get_period(starget); switch(tp->period) { @@ -212,8 +282,9 @@ store_spi_transport_period(struct class_device *cdev, const char *buf, size_t count) { - struct scsi_device *sdev = transport_class_to_sdev(cdev); - struct spi_internal *i = to_spi_internal(sdev->host->transportt); + struct scsi_target *starget = transport_class_to_starget(cdev); + struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); + struct spi_internal *i = to_spi_internal(shost->transportt); int j, period = -1; for (j = 0; j < SPI_STATIC_PPR; j++) { @@ -246,7 +317,7 @@ if (period > 0xff) period = 0xff; - i->f->set_period(sdev, period); + i->f->set_period(starget, period); return count; } @@ -255,9 +326,36 @@ show_spi_transport_period, store_spi_transport_period); +static ssize_t show_spi_host_signalling(struct class_device *cdev, char *buf) +{ + struct Scsi_Host *shost = transport_class_to_shost(cdev); + struct spi_internal *i = to_spi_internal(shost->transportt); + + if (i->f->get_signalling) + i->f->get_signalling(shost); + + return sprintf(buf, "%s\n", spi_signal_to_string(spi_signalling(shost))); +} +static ssize_t store_spi_host_signalling(struct class_device *cdev, + const char *buf, size_t count) +{ + struct Scsi_Host *shost = transport_class_to_shost(cdev); + struct spi_internal *i = to_spi_internal(shost->transportt); + enum spi_signal_type type = spi_signal_to_value(buf); + + if (type != SPI_SIGNAL_UNKNOWN) + return count; + + i->f->set_signalling(shost, type); + return count; +} +static CLASS_DEVICE_ATTR(signalling, S_IRUGO | S_IWUSR, + show_spi_host_signalling, + store_spi_host_signalling); + #define DV_SET(x, y) \ if(i->f->set_##x) \ - i->f->set_##x(sdev, y) + i->f->set_##x(sdev->sdev_target, y) #define DV_LOOPS 3 #define DV_TIMEOUT (10*HZ) @@ -325,7 +423,7 @@ DV_TIMEOUT, DV_RETRIES); if(sreq->sr_result || !scsi_device_online(sdev)) { scsi_device_set_state(sdev, SDEV_QUIESCE); - SPI_PRINTK(sdev, KERN_ERR, "Write Buffer failure %x\n", sreq->sr_result); + SPI_PRINTK(sdev->sdev_target, KERN_ERR, "Write Buffer failure %x\n", sreq->sr_result); return 0; } @@ -401,8 +499,8 @@ /* OK, retrain, fallback */ if (i->f->get_period) - i->f->get_period(sdev); - newperiod = spi_period(sdev); + i->f->get_period(sdev->sdev_target); + newperiod = spi_period(sdev->sdev_target); period = newperiod > period ? newperiod : period; if (period < 0x0d) period++; @@ -411,11 +509,11 @@ if (unlikely(period > 0xff || period == prevperiod)) { /* Total failure; set to async and return */ - SPI_PRINTK(sdev, KERN_ERR, "Domain Validation Failure, dropping back to Asynchronous\n"); + SPI_PRINTK(sdev->sdev_target, KERN_ERR, "Domain Validation Failure, dropping back to Asynchronous\n"); DV_SET(offset, 0); return 0; } - SPI_PRINTK(sdev, KERN_ERR, "Domain Validation detected failure, dropping back\n"); + SPI_PRINTK(sdev->sdev_target, KERN_ERR, "Domain Validation detected failure, dropping back\n"); DV_SET(period, period); prevperiod = period; } @@ -486,20 +584,20 @@ DV_SET(width, 0); if (!spi_dv_device_compare_inquiry(sreq, buffer, buffer, DV_LOOPS)) { - SPI_PRINTK(sdev, KERN_ERR, "Domain Validation Initial Inquiry Failed\n"); + SPI_PRINTK(sdev->sdev_target, KERN_ERR, "Domain Validation Initial Inquiry Failed\n"); /* FIXME: should probably offline the device here? */ return; } /* test width */ if (i->f->set_width && sdev->wdtr) { - i->f->set_width(sdev, 1); + i->f->set_width(sdev->sdev_target, 1); if (!spi_dv_device_compare_inquiry(sreq, buffer, buffer + len, DV_LOOPS)) { - SPI_PRINTK(sdev, KERN_ERR, "Wide Transfers Fail\n"); - i->f->set_width(sdev, 0); + SPI_PRINTK(sdev->sdev_target, KERN_ERR, "Wide Transfers Fail\n"); + i->f->set_width(sdev->sdev_target, 0); } } @@ -521,11 +619,11 @@ * test, now try an echo buffer test (if the device allows it) */ if ((len = spi_dv_device_get_echo_buffer(sreq, buffer)) == 0) { - SPI_PRINTK(sdev, KERN_INFO, "Domain Validation skipping write tests\n"); + SPI_PRINTK(sdev->sdev_target, KERN_INFO, "Domain Validation skipping write tests\n"); return; } if (len > SPI_MAX_ECHO_BUFFER_SIZE) { - SPI_PRINTK(sdev, KERN_WARNING, "Echo buffer size %d is too big, trimming to %d\n", len, SPI_MAX_ECHO_BUFFER_SIZE); + SPI_PRINTK(sdev->sdev_target, KERN_WARNING, "Echo buffer size %d is too big, trimming to %d\n", len, SPI_MAX_ECHO_BUFFER_SIZE); len = SPI_MAX_ECHO_BUFFER_SIZE; } @@ -547,6 +645,7 @@ spi_dv_device(struct scsi_device *sdev) { struct scsi_request *sreq = scsi_allocate_request(sdev, GFP_KERNEL); + struct scsi_target *starget = sdev->sdev_target; u8 *buffer; const int len = SPI_MAX_ECHO_BUFFER_SIZE*2; @@ -563,22 +662,28 @@ memset(buffer, 0, len); + /* We need to verify that the actual device will quiesce; the + * later target quiesce is just a nice to have */ if (unlikely(scsi_device_quiesce(sdev))) goto out_free; - spi_dv_pending(sdev) = 1; - down(&spi_dv_sem(sdev)); + scsi_target_quiesce(starget); + + spi_dv_pending(starget) = 1; + down(&spi_dv_sem(starget)); - SPI_PRINTK(sdev, KERN_INFO, "Beginning Domain Validation\n"); + SPI_PRINTK(starget, KERN_INFO, "Beginning Domain Validation\n"); spi_dv_device_internal(sreq, buffer); - SPI_PRINTK(sdev, KERN_INFO, "Ending Domain Validation\n"); + SPI_PRINTK(starget, KERN_INFO, "Ending Domain Validation\n"); - up(&spi_dv_sem(sdev)); - spi_dv_pending(sdev) = 0; + up(&spi_dv_sem(starget)); + spi_dv_pending(starget) = 0; - scsi_device_resume(sdev); + scsi_target_resume(starget); + + spi_initial_dv(starget) = 1; out_free: kfree(buffer); @@ -602,7 +707,7 @@ kfree(wqw); spi_dv_device(sdev); - spi_dv_pending(sdev) = 0; + spi_dv_pending(sdev->sdev_target) = 0; scsi_device_put(sdev); } @@ -625,15 +730,15 @@ if (unlikely(!wqw)) return; - if (unlikely(spi_dv_pending(sdev))) { + if (unlikely(spi_dv_pending(sdev->sdev_target))) { kfree(wqw); return; } /* Set pending early (dv_device doesn't check it, only sets it) */ - spi_dv_pending(sdev) = 1; + spi_dv_pending(sdev->sdev_target) = 1; if (unlikely(scsi_device_get(sdev))) { kfree(wqw); - spi_dv_pending(sdev) = 0; + spi_dv_pending(sdev->sdev_target) = 0; return; } @@ -654,6 +759,15 @@ if (i->f->show_##field) \ count++ +#define SETUP_HOST_ATTRIBUTE(field) \ + i->private_host_attrs[count] = class_device_attr_##field; \ + if (!i->f->set_##field) { \ + i->private_host_attrs[count].attr.mode = S_IRUGO; \ + i->private_host_attrs[count].store = NULL; \ + } \ + i->host_attrs[count] = &i->private_host_attrs[count]; \ + count++ + struct scsi_transport_template * spi_attach_transport(struct spi_function_template *ft) { @@ -666,10 +780,14 @@ memset(i, 0, sizeof(struct spi_internal)); - i->t.attrs = &i->attrs[0]; - i->t.class = &spi_transport_class; - i->t.setup = &spi_setup_transport_attrs; - i->t.size = sizeof(struct spi_transport_attrs); + i->t.target_attrs = &i->attrs[0]; + i->t.target_class = &spi_transport_class; + i->t.target_setup = &spi_setup_transport_attrs; + i->t.target_size = sizeof(struct spi_transport_attrs); + i->t.host_attrs = &i->host_attrs[0]; + i->t.host_class = &spi_host_class; + i->t.host_setup = &spi_setup_host_attrs; + i->t.host_size = sizeof(struct spi_host_attrs); i->f = ft; SETUP_ATTRIBUTE(period); @@ -690,6 +808,13 @@ i->attrs[count++] = &class_device_attr_revalidate; i->attrs[count] = NULL; + + count = 0; + SETUP_HOST_ATTRIBUTE(signalling); + + BUG_ON(count > SPI_HOST_ATTRS); + + i->host_attrs[count] = NULL; return &i->t; } only in patch2: unchanged: --- a/drivers/scsi/sim710.c 2004-09-26 11:13:18 -07:00 +++ b/drivers/scsi/sim710.c 2004-09-26 11:13:18 -07:00 @@ -36,6 +36,9 @@ #include #include #include +#include +#include +#include #include "53c700.h" only in patch2: unchanged: --- a/include/scsi/scsi_transport.h 2004-09-26 11:13:18 -07:00 +++ b/include/scsi/scsi_transport.h 2004-09-26 11:13:18 -07:00 @@ -24,18 +24,27 @@ /* The NULL terminated list of transport attributes * that should be exported. */ - struct class_device_attribute **attrs; + struct class_device_attribute **device_attrs; + struct class_device_attribute **target_attrs; + struct class_device_attribute **host_attrs; + /* The transport class that the device is in */ - struct class *class; + struct class *device_class; + struct class *target_class; + struct class *host_class; + + /* Constructor functions */ + int (*device_setup)(struct scsi_device *); + int (*target_setup)(struct scsi_target *); + int (*host_setup)(struct Scsi_Host *); - /* Constructor/Destructor functions */ - int (* setup)(struct scsi_device *); - void (* cleanup)(struct scsi_device *); /* The size of the specific transport attribute structure (a * space of this size will be left at the end of the - * scsi_device structure */ - int size; + * scsi_* structure */ + int device_size; + int target_size; + int host_size; }; #endif /* SCSI_TRANSPORT_H */ only in patch2: unchanged: --- a/include/scsi/scsi_transport_fc.h 2004-09-26 11:13:18 -07:00 +++ b/include/scsi/scsi_transport_fc.h 2004-09-26 11:13:18 -07:00 @@ -31,9 +31,9 @@ }; /* accessor functions */ -#define fc_port_id(x) (((struct fc_transport_attrs *)&(x)->transport_data)->port_id) -#define fc_node_name(x) (((struct fc_transport_attrs *)&(x)->transport_data)->node_name) -#define fc_port_name(x) (((struct fc_transport_attrs *)&(x)->transport_data)->port_name) +#define fc_port_id(x) (((struct fc_transport_attrs *)&(x)->sdev_data)->port_id) +#define fc_node_name(x) (((struct fc_transport_attrs *)&(x)->sdev_data)->node_name) +#define fc_port_name(x) (((struct fc_transport_attrs *)&(x)->sdev_data)->port_name) /* The functions by which the transport class and the driver communicate */ struct fc_function_template { only in patch2: unchanged: --- a/include/scsi/scsi_transport_spi.h 2004-09-26 11:13:18 -07:00 +++ b/include/scsi/scsi_transport_spi.h 2004-09-26 11:13:18 -07:00 @@ -35,45 +35,63 @@ unsigned int rd_strm:1; /* Read streaming enabled */ unsigned int rti:1; /* Retain Training Information */ unsigned int pcomp_en:1;/* Precompensation enabled */ + unsigned int initial_dv:1; /* DV done to this target yet */ + unsigned long flags; /* flags field for drivers to use */ /* Private Fields */ unsigned int dv_pending:1; /* Internal flag */ struct semaphore dv_sem; /* semaphore to serialise dv */ }; +enum spi_signal_type { + SPI_SIGNAL_UNKNOWN = 1, + SPI_SIGNAL_SE, + SPI_SIGNAL_LVD, + SPI_SIGNAL_HVD, +}; + +struct spi_host_attrs { + enum spi_signal_type signalling; +}; + /* accessor functions */ -#define spi_period(x) (((struct spi_transport_attrs *)&(x)->transport_data)->period) -#define spi_offset(x) (((struct spi_transport_attrs *)&(x)->transport_data)->offset) -#define spi_width(x) (((struct spi_transport_attrs *)&(x)->transport_data)->width) -#define spi_iu(x) (((struct spi_transport_attrs *)&(x)->transport_data)->iu) -#define spi_dt(x) (((struct spi_transport_attrs *)&(x)->transport_data)->dt) -#define spi_qas(x) (((struct spi_transport_attrs *)&(x)->transport_data)->qas) -#define spi_wr_flow(x) (((struct spi_transport_attrs *)&(x)->transport_data)->wr_flow) -#define spi_rd_strm(x) (((struct spi_transport_attrs *)&(x)->transport_data)->rd_strm) -#define spi_rti(x) (((struct spi_transport_attrs *)&(x)->transport_data)->rti) -#define spi_pcomp_en(x) (((struct spi_transport_attrs *)&(x)->transport_data)->pcomp_en) +#define spi_period(x) (((struct spi_transport_attrs *)&(x)->starget_data)->period) +#define spi_offset(x) (((struct spi_transport_attrs *)&(x)->starget_data)->offset) +#define spi_width(x) (((struct spi_transport_attrs *)&(x)->starget_data)->width) +#define spi_iu(x) (((struct spi_transport_attrs *)&(x)->starget_data)->iu) +#define spi_dt(x) (((struct spi_transport_attrs *)&(x)->starget_data)->dt) +#define spi_qas(x) (((struct spi_transport_attrs *)&(x)->starget_data)->qas) +#define spi_wr_flow(x) (((struct spi_transport_attrs *)&(x)->starget_data)->wr_flow) +#define spi_rd_strm(x) (((struct spi_transport_attrs *)&(x)->starget_data)->rd_strm) +#define spi_rti(x) (((struct spi_transport_attrs *)&(x)->starget_data)->rti) +#define spi_pcomp_en(x) (((struct spi_transport_attrs *)&(x)->starget_data)->pcomp_en) +#define spi_initial_dv(x) (((struct spi_transport_attrs *)&(x)->starget_data)->initial_dv) +#define spi_flags(x) (((struct spi_transport_attrs *)&(x)->starget_data)->flags) +#define spi_signalling(h) (((struct spi_host_attrs *)&(h)->shost_data)->signalling) /* The functions by which the transport class and the driver communicate */ struct spi_function_template { - void (*get_period)(struct scsi_device *); - void (*set_period)(struct scsi_device *, int); - void (*get_offset)(struct scsi_device *); - void (*set_offset)(struct scsi_device *, int); - void (*get_width)(struct scsi_device *); - void (*set_width)(struct scsi_device *, int); - void (*get_iu)(struct scsi_device *); - void (*set_iu)(struct scsi_device *, int); - void (*get_dt)(struct scsi_device *); - void (*set_dt)(struct scsi_device *, int); - void (*get_qas)(struct scsi_device *); - void (*set_qas)(struct scsi_device *, int); - void (*get_wr_flow)(struct scsi_device *); - void (*set_wr_flow)(struct scsi_device *, int); - void (*get_rd_strm)(struct scsi_device *); - void (*set_rd_strm)(struct scsi_device *, int); - void (*get_rti)(struct scsi_device *); - void (*set_rti)(struct scsi_device *, int); - void (*get_pcomp_en)(struct scsi_device *); - void (*set_pcomp_en)(struct scsi_device *, int); + void (*get_period)(struct scsi_target *); + void (*set_period)(struct scsi_target *, int); + void (*get_offset)(struct scsi_target *); + void (*set_offset)(struct scsi_target *, int); + void (*get_width)(struct scsi_target *); + void (*set_width)(struct scsi_target *, int); + void (*get_iu)(struct scsi_target *); + void (*set_iu)(struct scsi_target *, int); + void (*get_dt)(struct scsi_target *); + void (*set_dt)(struct scsi_target *, int); + void (*get_qas)(struct scsi_target *); + void (*set_qas)(struct scsi_target *, int); + void (*get_wr_flow)(struct scsi_target *); + void (*set_wr_flow)(struct scsi_target *, int); + void (*get_rd_strm)(struct scsi_target *); + void (*set_rd_strm)(struct scsi_target *, int); + void (*get_rti)(struct scsi_target *); + void (*set_rti)(struct scsi_target *, int); + void (*get_pcomp_en)(struct scsi_target *); + void (*set_pcomp_en)(struct scsi_target *, int); + void (*get_signalling)(struct Scsi_Host *); + void (*set_signalling)(struct Scsi_Host *, enum spi_signal_type); /* The driver sets these to tell the transport class it * wants the attributes displayed in sysfs. If the show_ flag * is not set, the attribute will be private to the transport