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 <scsi/scsi_cmnd.h>
 #include <scsi/scsi_device.h>
-#include <scsi/scsi_tcq.h>
 #include <scsi/scsi.h>
 #include <scsi/scsi_host.h>
 #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 <linux/init.h>		/* __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 <asm/byteorder.h>
 #include <asm/io.h>
 
+#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 <linux/interrupt.h> /* For tasklet support. */
 #include <linux/config.h>
 #include <linux/slab.h>
+#else
+#include <linux/malloc.h>
+#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 <linux/spinlock.h>
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,93)
+#include <linux/smp.h>
+#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 <linux/init.h>		/* __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 <asm/byteorder.h>
 #include <asm/io.h>
 
+#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 <linux/interrupt.h> /* For tasklet support. */
 #include <linux/config.h>
 #include <linux/slab.h>
+#else
+#include <linux/malloc.h>
+#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 <linux/spinlock.h>
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,93)
+#include <linux/smp.h>
+#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 <dev/aic7xxx/aic7xxx_93cx6.h>
 #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 <asm/io.h>
 #include <asm/system.h>
 
+#include "scsi.h"
+#include <scsi/scsi_host.h>
-#include <scsi/scsi.h>
-#include <scsi/scsi_cmnd.h>
-#include <scsi/scsi_device.h>
-#include <scsi/scsi_tcq.h>
 
 #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; i<MAX_SCATTERH+MAX_SCATTERL; i++) {
@@ -2852,8 +2859,7 @@
 		*p++ =SCR_MOVE_TBL ^ SCR_DATA_IN;
 		*p++ =offsetof (struct dsb, data[i]);
 	};
+	assert ((u_long)p == (u_long)&scr->data_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; i<MAX_SCATTERH; i++) {
@@ -2862,8 +2868,7 @@
 		*p++ =SCR_MOVE_TBL ^ SCR_DATA_OUT;
 		*p++ =offsetof (struct dsb, data[i]);
 	};
+	assert ((u_long)p==(u_long)&scrh->hdata_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; i<MAX_SCATTERH+MAX_SCATTERL; i++) {
@@ -2873,7 +2878,7 @@
 		*p++ =offsetof (struct dsb, data[i]);
 	};
 
+	assert ((u_long)p == (u_long)&scr->data_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; t<MAX_TARGET; t++) {
+			if (!((np->user.target>>t)&1)) continue;
+			tp = &np->target[t];
+			tp->usrsync = np->user.data;
+			ncr_negotiate (np, tp);
+		};
+		break;
+
+	case UC_SETTAGS:
+		for (t=0; t<MAX_TARGET; t++) {
+			int ln;
+			if (!((np->user.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; t<MAX_TARGET; t++) {
+			u_long size;
+			if (!((np->user.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; t<MAX_TARGET; t++) {
+			if (!((np->user.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<<gen * 125us */
 	while (!(INW(nc_sist) & GEN) && ms++ < 100000) {
 		for (count = 0; count < 10; count ++)
+			UDELAY (100);	/* count ms */
-			udelay(100);	/* count ms */
 	}
 	OUTB (nc_stime1, 0);	/* disable general purpose timer */
  	/*
@@ -7850,14 +7971,22 @@
 
 /*===================== LINUX ENTRY POINTS SECTION ==========================*/
 
+/*
+**   Linux select queue depths function
+*/
+
+int ncr53c8xx_slave_configure(struct scsi_device *device)
-static int ncr53c8xx_slave_configure(struct scsi_device *device)
 {
 	struct Scsi_Host *host = device->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<<target);
+#ifdef DEBUG_PROC_INFO
+printk("ncr_user_command: target=%ld\n", target);
+#endif
+		}
+		break;
+	}
+
+	switch(uc->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 <scsi/scsi_host.h>
 
+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(&reg->ctrl_status, CSR_ISP_SOFT_RESET);
+		RD_REG_WORD(&reg->ctrl_status);		/* PCI Posting. */
 	}
 
 	for (cnt = 30000; RD_MAILBOX_REG(ha, reg, 0) != 0 &&
@@ -745,6 +746,7 @@
 
 			/* Release RISC. */
 			WRT_REG_WORD(&reg->hccr, HCCR_RELEASE_RISC);
+			RD_REG_WORD(&reg->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(&reg->hccr, HCCR_CLR_RISC_INT);
+	RD_REG_WORD(&reg->hccr);			/* PCI Posting. */
 	WRT_REG_WORD(&reg->hccr, HCCR_CLR_HOST_INT);
+	RD_REG_WORD(&reg->hccr);			/* PCI Posting. */
 
 	/* Reset ISP chip. */
 	WRT_REG_WORD(&reg->ctrl_status, CSR_ISP_SOFT_RESET);
+	RD_REG_WORD(&reg->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(&reg->hccr, HCCR_RESET_RISC);
+	RD_REG_WORD(&reg->hccr);			/* PCI Posting. */
 
 	WRT_REG_WORD(&reg->semaphore, 0);
 
@@ -555,6 +559,7 @@
 
 	/* Reset ISP chip. */
 	WRT_REG_WORD(&reg->ctrl_status, CSR_ISP_SOFT_RESET);
+	RD_REG_WORD(&reg->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(&reg->hccr, HCCR_RESET_RISC);
+	RD_REG_WORD(&reg->hccr);			/* PCI Posting. */
 	WRT_REG_WORD(&reg->hccr, HCCR_RELEASE_RISC);
+	RD_REG_WORD(&reg->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 <scsi/scsi_host.h>
 #include <scsi/scsi_ioctl.h>
 #include <scsi/scsi_request.h>
-#include <scsi/sg.h>
 
 #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, &current_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 <asm/dma.h>
 #include <asm/system.h>
 
-#include <scsi/scsi.h>
-#include <scsi/scsi_dbg.h>
-#include <scsi/scsi_device.h>
-#include <scsi/scsi_driver.h>
-#include <scsi/scsi_eh.h>
-#include <scsi/scsi_host.h>
-#include <scsi/scsi_ioctl.h>
-#include <scsi/scsi_request.h>
-
-
 /* 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 <scsi/scsi_host.h>
+
+#include <scsi/scsi_driver.h>
+#include <scsi/scsi_ioctl.h>
+
 #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 <linux/completion.h>
 
-
 /* 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 <groudier@free.fr>
- * Copyright (c) 2003-2004  Matthew Wilcox <matthew@wil.cx>
  *
  * 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 <groudier@free.fr>
- * Copyright (c) 2003-2004  Matthew Wilcox <matthew@wil.cx>
  *
  * 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 <asm/irq.h>
 #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 <linux/config.h>
 
+/* 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 <linux/mca.h>
 #include <asm/io.h>
 #include <scsi/scsi_host.h>
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_transport.h>
+#include <scsi/scsi_transport_spi.h>
 
 #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 <asm/delay.h>
 
 #include <scsi/scsi_host.h>
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_transport.h>
+#include <scsi/scsi_transport_spi.h>
 
 #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 <asm/scatterlist.h>
 #include <asm/io.h>
 #include <scsi/scsi.h>
+#include "scsi_priv.h"
 #include <scsi/scsi_device.h>
 #include <scsi/scsi_host.h>
 #include <scsi/scsi_request.h>
 #include <scsi/scsi_transport.h>
 #include <scsi/scsi_transport_spi.h>
 
-#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 <linux/eisa.h>
 #include <linux/interrupt.h>
 #include <scsi/scsi_host.h>
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_transport.h>
+#include <scsi/scsi_transport_spi.h>
 
 #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