X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fscsi%2Fncr53c8xx.c;h=9b91b2efe4d2bd2ece1c0531a395bf33a57c7b65;hb=6a77f38946aaee1cd85eeec6cf4229b204c15071;hp=3fcefa3d4531d90c717b6f4f1e9925aaac142a32;hpb=87fc8d1bb10cd459024a742c6a10961fefcef18f;p=linux-2.6.git diff --git a/drivers/scsi/ncr53c8xx.c b/drivers/scsi/ncr53c8xx.c index 3fcefa3d4..9b91b2efe 100644 --- a/drivers/scsi/ncr53c8xx.c +++ b/drivers/scsi/ncr53c8xx.c @@ -83,11 +83,6 @@ ** ** 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 */ @@ -124,23 +119,17 @@ #include #include -#include "scsi.h" -#include +#include +#include +#include +#include +#include +#include #include "ncr53c8xx.h" -/* -** Donnot compile integrity checking code for Linux-2.3.0 -** and above since SCSI data structures are not ready yet. -*/ -/* #if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0) */ -#if 0 -#define SCSI_NCR_INTEGRITY_CHECKING -#endif - #define NAME53C "ncr53c" #define NAME53C8XX "ncr53c8xx" -#define DRIVER_SMP_LOCK ncr53c8xx_lock #include "sym53c8xx_comm.h" @@ -316,10 +305,6 @@ typedef u32 tagmap_t; #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) @@ -413,31 +398,6 @@ static int ncr53c8xx_proc_info(struct Scsi_Host *host, char *buffer, char **star #define NS_WIDE (2) #define NS_PPR (4) -/*========================================================== -** -** "Special features" of targets. -** quirks field of struct tcb. -** actualquirks field of struct ccb. -** -**========================================================== -*/ - -#define QUIRK_AUTOSAVE (0x01) -#define QUIRK_NOMSG (0x02) -#define QUIRK_NOSYNC (0x10) -#define QUIRK_NOWIDE16 (0x20) - -/*========================================================== -** -** Capability bits in Inquire response byte 7. -** -**========================================================== -*/ - -#define INQ7_QUEUE (0x02) -#define INQ7_SYNC (0x10) -#define INQ7_WIDE16 (0x20) - /*========================================================== ** ** Misc. @@ -454,6 +414,8 @@ static int ncr53c8xx_proc_info(struct Scsi_Host *host, char *buffer, char **star **========================================================== */ +static struct scsi_transport_template *ncr53c8xx_transport_template = NULL; + struct tcb; struct lcb; struct ccb; @@ -531,8 +493,6 @@ struct tcb { */ struct link jump_lcb[4]; /* JUMPs for reselection */ struct lcb * lp[MAX_LUN]; /* The lcb's of this tcb */ - u_char inq_done; /* Target capabilities received */ - u_char inq_byte7; /* Contains these capabilities */ /*---------------------------------------------------------------- ** Pointer to the ccb used for negotiation. @@ -571,18 +531,12 @@ struct tcb { /*3*/ u_char wval; #endif -#ifdef SCSI_NCR_INTEGRITY_CHECKING - u_char ic_min_sync; - u_char ic_max_width; - u_char ic_maximums_set; - u_char ic_done; -#endif - /* User settable limits and options. */ u_char usrsync; u_char usrwide; u_char usrtags; u_char usrflag; + struct scsi_target *starget; }; /*======================================================================== @@ -626,10 +580,10 @@ struct lcb { ** 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*/ @@ -649,7 +603,6 @@ struct lcb { u_char usetags; /* Command queuing is active */ u_char maxtags; /* Max nr of tags asked by user */ u_char numtags; /* Current number of tags */ - u_char inq_byte7; /* Store unit CmdQ capabitility */ /*---------------------------------------------------------------- ** QUEUE FULL control and ORDERED tag control. @@ -920,7 +873,7 @@ struct ccb { 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 */ }; @@ -997,11 +950,11 @@ struct ncb { ** 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. */ + void __iomem *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. */ + struct ncr_reg __iomem *reg; /* memory mapped IO. */ /*---------------------------------------------------------------- ** SCRIPTS virtual and physical bus addresses. @@ -1096,17 +1049,6 @@ struct ncb { struct ccb *ccb; /* Global CCB */ struct usrcmd user; /* Command from user */ volatile u_char release_stage; /* Synchronisation stage on release */ - -#ifdef SCSI_NCR_INTEGRITY_CHECKING - /*---------------------------------------------------------------- - ** Fields that are used for integrity check - **---------------------------------------------------------------- - */ - unsigned char check_integrity; /* Enable midlayer integ.check on - * bus scan. */ - unsigned char check_integ_par; /* Set if par or Init. Det. error - * used only during integ check */ -#endif }; #define NCB_SCRIPT_PHYS(np,lbl) (np->p_script + offsetof (struct script, lbl)) @@ -1186,7 +1128,7 @@ struct script { #endif ncrcmd save_dp [ 7]; ncrcmd restore_dp [ 5]; - ncrcmd disconnect [ 17]; + ncrcmd disconnect [ 10]; ncrcmd msg_out [ 9]; ncrcmd msg_out_done [ 7]; ncrcmd idle [ 2]; @@ -1274,8 +1216,7 @@ static void ncr_free_ccb (struct ncb *np, struct ccb *cp); static void ncr_init_ccb (struct ncb *np, struct ccb *cp); static void ncr_init_tcb (struct ncb *np, u_char tn); static struct lcb * ncr_alloc_lcb (struct ncb *np, u_char tn, u_char ln); -static struct lcb * ncr_setup_lcb (struct ncb *np, u_char tn, u_char ln, - u_char *inq_data); +static struct lcb * ncr_setup_lcb (struct ncb *np, struct scsi_device *sdev); static void ncr_getclock (struct ncb *np, int mult); static void ncr_selectclock (struct ncb *np, u_char scntl3); static struct ccb *ncr_get_ccb (struct ncb *np, u_char tn, u_char ln); @@ -1286,12 +1227,8 @@ static int ncr_int_par (struct ncb *np); static void ncr_int_ma (struct ncb *np); static void ncr_int_sir (struct ncb *np); static void ncr_int_sto (struct ncb *np); -static u_long ncr_lookup (char* id); static void ncr_negotiate (struct ncb* np, struct tcb* tp); static int ncr_prepare_nego(struct ncb *np, struct ccb *cp, u_char *msgptr); -#ifdef SCSI_NCR_INTEGRITY_CHECKING -static int ncr_ic_nego(struct ncb *np, struct ccb *cp, struct scsi_cmnd *cmd, u_char *msgptr); -#endif static void ncr_script_copy_and_bind (struct ncb *np, ncrcmd *src, ncrcmd *dst, int len); @@ -1299,7 +1236,7 @@ static void ncr_script_fill (struct script * scr, struct scripth * scripth); static int ncr_scatter (struct ncb *np, struct ccb *cp, struct scsi_cmnd *cmd); static void ncr_getsync (struct ncb *np, u_char sfac, u_char *fakp, u_char *scntl3p); static void ncr_setsync (struct ncb *np, struct ccb *cp, u_char scntl3, u_char sxfer); -static void ncr_setup_tags (struct ncb *np, u_char tn, u_char ln); +static void ncr_setup_tags (struct ncb *np, struct scsi_device *sdev); static void ncr_setwide (struct ncb *np, struct ccb *cp, u_char wide, u_char ack); static int ncr_show_msg (u_char * msg); static void ncr_print_msg (struct ccb *cp, char *label, u_char *msg); @@ -1882,21 +1819,6 @@ static struct script script0 __initdata = { */ SCR_LOAD_REG (HS_REG, HS_DISCONNECT), 0, - /* - ** If QUIRK_AUTOSAVE is set, - ** do an "save pointer" operation. - */ - SCR_FROM_REG (QU_REG), - 0, - SCR_JUMP ^ IFFALSE (MASK (QUIRK_AUTOSAVE, QUIRK_AUTOSAVE)), - PADDR (cleanup_ok), - /* - ** like SAVE_DP message: - ** Copy TEMP register to SAVEP in header. - */ - SCR_COPY (4), - RADDR (temp), - NADDR (header.savep), SCR_JUMP, PADDR (cleanup_ok), @@ -2826,7 +2748,7 @@ void __init ncr_script_fill (struct script * scr, struct scripth * scrh) *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 @@ -2839,7 +2761,7 @@ void __init ncr_script_fill (struct script * scr, struct scripth * scrh) *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 */ @@ -2850,7 +2772,8 @@ void __init ncr_script_fill (struct script * scr, struct scripth * scrh) *p++ =SCR_MOVE_TBL ^ SCR_DATA_IN; *p++ =offsetof (struct dsb, data[i]); }; - assert ((u_long)p == (u_long)&scrh->hdata_in + sizeof (scrh->hdata_in)); + + BUG_ON((u_long)p != (u_long)&scrh->hdata_in + sizeof (scrh->hdata_in)); p = scr->data_in; for (i=MAX_SCATTERH; idata_in + sizeof (scr->data_in)); + + BUG_ON((u_long)p != (u_long)&scr->data_in + sizeof (scr->data_in)); p = scrh->hdata_out; for (i=0; ihdata_out + sizeof (scrh->hdata_out)); + + BUG_ON((u_long)p != (u_long)&scrh->hdata_out + sizeof (scrh->hdata_out)); p = scr->data_out; for (i=MAX_SCATTERH; idata_out + sizeof (scr->data_out)); + BUG_ON((u_long) p != (u_long)&scr->data_out + sizeof (scr->data_out)); } /*========================================================== @@ -2916,7 +2841,7 @@ ncr_script_copy_and_bind (struct ncb *np, ncrcmd *src, ncrcmd *dst, int len) 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) @@ -2946,7 +2871,7 @@ ncr_script_copy_and_bind (struct ncb *np, ncrcmd *src, ncrcmd *dst, int len) 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 @@ -3036,21 +2961,8 @@ ncr_script_copy_and_bind (struct ncb *np, ncrcmd *src, ncrcmd *dst, int len) }; } -/*========================================================== -** -** -** 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 { @@ -3436,182 +3348,6 @@ static inline void ncr_flush_done_cmds(struct scsi_cmnd *lcmd) } } -/*========================================================== -** -** -** Prepare the next negotiation message for integrity check, -** if needed. -** -** Fill in the part of message buffer that contains the -** negotiation and the nego_status field of the CCB. -** Returns the size of the message in bytes. -** -** -**========================================================== -*/ - -#ifdef SCSI_NCR_INTEGRITY_CHECKING -static int ncr_ic_nego(struct ncb *np, struct ccb *cp, struct scsi_cmnd *cmd, u_char *msgptr) -{ - struct tcb *tp = &np->target[cp->target]; - int msglen = 0; - int nego = 0; - u_char no_increase; - - if (tp->inq_done) { - - if (!tp->ic_maximums_set) { - tp->ic_maximums_set = 1; - - /* check target and host adapter capabilities */ - if ( (tp->inq_byte7 & INQ7_WIDE16) && - np->maxwide && tp->usrwide ) - tp->ic_max_width = 1; - else - tp->ic_max_width = 0; - - if ((tp->inq_byte7 & INQ7_SYNC) && tp->maxoffs) { - tp->ic_min_sync = (tp->minsync < np->minsync) ? - np->minsync : tp->minsync; - } - else - tp->ic_min_sync = 255; - - tp->period = 1; - tp->widedone = 1; - } - - if (DEBUG_FLAGS & DEBUG_IC) { - printk("%s: cmd->ic_nego %d, 1st byte 0x%2X\n", - ncr_name(np), cmd->ic_nego, cmd->cmnd[0]); - } - - /* First command from integrity check routine will request - * a PPR message. Disable. - */ - if ((cmd->ic_nego & NS_PPR) == NS_PPR) - cmd->ic_nego &= ~NS_PPR; - /* Previous command recorded a parity or an initiator - * detected error condition. Force bus to narrow for this - * target. Clear flag. Negotation on request sense. - * Note: kernel forces 2 bus resets :o( but clears itself out. - * Minor bug? in scsi_obsolete.c (ugly) - */ - if (np->check_integ_par) { - printk("%s: Parity Error. Target set to narrow.\n", - ncr_name(np)); - tp->ic_max_width = 0; - tp->widedone = tp->period = 0; - } - - /* In case of a bus reset, ncr_negotiate will reset - * the flags tp->widedone and tp->period to 0, forcing - * a new negotiation. - */ - no_increase = 0; - if (tp->widedone == 0) { - cmd->ic_nego = NS_WIDE; - tp->widedone = 1; - no_increase = 1; - } - else if (tp->period == 0) { - cmd->ic_nego = NS_SYNC; - tp->period = 1; - no_increase = 1; - } - - switch (cmd->ic_nego) { - case NS_WIDE: - /* - ** negotiate wide transfers ? - ** Do NOT negotiate if device only supports - ** narrow. - */ - if (tp->ic_max_width | np->check_integ_par) { - nego = NS_WIDE; - - msgptr[msglen++] = M_EXTENDED; - msgptr[msglen++] = 2; - msgptr[msglen++] = M_X_WIDE_REQ; - msgptr[msglen++] = cmd->ic_nego_width & tp->ic_max_width; - } - else - cmd->ic_nego_width &= tp->ic_max_width; - - break; - - case NS_SYNC: - /* - ** negotiate synchronous transfers? - ** Target must support sync transfers. - ** - ** If period becomes longer than max, reset to async - */ - - if (tp->inq_byte7 & INQ7_SYNC) { - - nego = NS_SYNC; - - msgptr[msglen++] = M_EXTENDED; - msgptr[msglen++] = 3; - msgptr[msglen++] = M_X_SYNC_REQ; - - switch (cmd->ic_nego_sync) { - case 2: /* increase the period */ - if (!no_increase) { - if (tp->ic_min_sync <= 0x0A) - tp->ic_min_sync = 0x0C; - else if (tp->ic_min_sync <= 0x0C) - tp->ic_min_sync = 0x19; - else if (tp->ic_min_sync <= 0x19) - tp->ic_min_sync *= 2; - else { - tp->ic_min_sync = 255; - cmd->ic_nego_sync = 0; - tp->maxoffs = 0; - } - } - msgptr[msglen++] = tp->maxoffs?tp->ic_min_sync:0; - msgptr[msglen++] = tp->maxoffs; - break; - - case 1: /* nego. to maximum */ - msgptr[msglen++] = tp->maxoffs?tp->ic_min_sync:0; - msgptr[msglen++] = tp->maxoffs; - break; - - case 0: /* nego to async */ - default: - msgptr[msglen++] = 0; - msgptr[msglen++] = 0; - break; - }; - } - else - cmd->ic_nego_sync = 0; - break; - - case NS_NOCHANGE: - default: - break; - }; - }; - - cp->nego_status = nego; - np->check_integ_par = 0; - - if (nego) { - tp->nego_cp = cp; - if (DEBUG_FLAGS & DEBUG_NEGO) { - ncr_print_msg(cp, nego == NS_WIDE ? - "wide/narrow msgout": "sync/async msgout", msgptr); - }; - }; - - return msglen; -} -#endif /* SCSI_NCR_INTEGRITY_CHECKING */ - /*========================================================== ** ** @@ -3631,20 +3367,17 @@ static int ncr_prepare_nego(struct ncb *np, struct ccb *cp, u_char *msgptr) struct tcb *tp = &np->target[cp->target]; int msglen = 0; int nego = 0; + struct scsi_target *starget = tp->starget; - if (tp->inq_done) { + if (likely(starget)) { /* ** negotiate wide transfers ? */ if (!tp->widedone) { - if (tp->inq_byte7 & INQ7_WIDE16) { + if (spi_support_wide(starget)) { nego = NS_WIDE; -#ifdef SCSI_NCR_INTEGRITY_CHECKING - if (tp->ic_done) - tp->usrwide &= tp->ic_max_width; -#endif } else tp->widedone=1; @@ -3655,13 +3388,8 @@ static int ncr_prepare_nego(struct ncb *np, struct ccb *cp, u_char *msgptr) */ if (!nego && !tp->period) { - if (tp->inq_byte7 & INQ7_SYNC) { + if (spi_support_sync(starget)) { nego = NS_SYNC; -#ifdef SCSI_NCR_INTEGRITY_CHECKING - if ((tp->ic_done) && - (tp->minsync < tp->ic_min_sync)) - tp->minsync = tp->ic_min_sync; -#endif } else { tp->period =0xffff; PRINT_TARGET(np, cp->target); @@ -3843,8 +3571,8 @@ static int ncr_queue_command (struct ncb *np, struct scsi_cmnd *cmd) **---------------------------------------------------- */ - 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); @@ -3867,72 +3595,9 @@ static int ncr_queue_command (struct ncb *np, struct scsi_cmnd *cmd) cp->nego_status = 0; -#ifdef SCSI_NCR_INTEGRITY_CHECKING - if ((np->check_integrity && tp->ic_done) || !np->check_integrity) { - if ((!tp->widedone || !tp->period) && !tp->nego_cp && lp) { - msglen += ncr_prepare_nego (np, cp, msgptr + msglen); - } - } - else if (np->check_integrity && (cmd->ic_in_progress)) { - msglen += ncr_ic_nego (np, cp, cmd, msgptr + msglen); - } - else if (np->check_integrity && cmd->ic_complete) { - /* - * Midlayer signal to the driver that all of the scsi commands - * for the integrity check have completed. Save the negotiated - * parameters (extracted from sval and wval). - */ - - { - u_char idiv; - idiv = (tp->wval>>4) & 0x07; - if ((tp->sval&0x1f) && idiv ) - tp->period = (((tp->sval>>5)+4) - *div_10M[idiv-1])/np->clock_khz; - else - tp->period = 0xffff; - } - /* - * tp->period contains 10 times the transfer period, - * which itself is 4 * the requested negotiation rate. - */ - if (tp->period <= 250) tp->ic_min_sync = 10; - else if (tp->period <= 303) tp->ic_min_sync = 11; - else if (tp->period <= 500) tp->ic_min_sync = 12; - else - tp->ic_min_sync = (tp->period + 40 - 1) / 40; - - - /* - * Negotiation for this target it complete. - */ - tp->ic_max_width = (tp->wval & EWS) ? 1: 0; - tp->ic_done = 1; - tp->widedone = 1; - - printk("%s: Integrity Check Complete: \n", ncr_name(np)); - - printk("%s: %s %s SCSI", ncr_name(np), - (tp->sval&0x1f)?"SYNC":"ASYNC", - tp->ic_max_width?"WIDE":"NARROW"); - - if (tp->sval&0x1f) { - u_long mbs = 10000 * (tp->ic_max_width + 1); - - printk(" %d.%d MB/s", (int) (mbs / tp->period), - (int) (mbs % tp->period)); - - printk(" (%d ns, %d offset)\n", - tp->period/10, tp->sval&0x1f); - } else { - printk(" %d MB/s. \n ", (tp->ic_max_width+1)*5); - } - } -#else if ((!tp->widedone || !tp->period) && !tp->nego_cp && lp) { msglen += ncr_prepare_nego (np, cp, msgptr + msglen); } -#endif /* SCSI_NCR_INTEGRITY_CHECKING */ /*---------------------------------------------------- ** @@ -3941,17 +3606,17 @@ static int ncr_queue_command (struct ncb *np, struct scsi_cmnd *cmd) **---------------------------------------------------- */ 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); @@ -3959,12 +3624,12 @@ static int ncr_queue_command (struct ncb *np, struct scsi_cmnd *cmd) 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); @@ -3974,7 +3639,7 @@ static int ncr_queue_command (struct ncb *np, struct scsi_cmnd *cmd) } break; default: - case SCSI_DATA_NONE: + case DMA_NONE: lastp = goalp = NCB_SCRIPT_PHYS (np, no_data); break; } @@ -3986,7 +3651,7 @@ static int ncr_queue_command (struct ncb *np, struct scsi_cmnd *cmd) 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 @@ -4036,7 +3701,7 @@ static int ncr_queue_command (struct ncb *np, struct scsi_cmnd *cmd) /* ** status */ - cp->actualquirks = tp->quirks; + cp->actualquirks = 0; cp->host_status = cp->nego_status ? HS_NEGOTIATE : HS_BUSY; cp->scsi_status = S_ILLEGAL; cp->parity_status = 0; @@ -4089,19 +3754,19 @@ static int ncr_queue_command (struct ncb *np, struct scsi_cmnd *cmd) 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); @@ -4152,7 +3817,7 @@ static int ncr_reset_scsi_bus(struct ncb *np, int enab_int, int settle_delay) 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); /* @@ -4161,7 +3826,7 @@ static int ncr_reset_scsi_bus(struct ncb *np, int enab_int, int settle_delay) */ OUTB (nc_stest3, TE); OUTB (nc_scntl1, CRST); - UDELAY (200); + udelay(200); if (!driver_setup.bus_check) goto out; @@ -4280,6 +3945,7 @@ static int ncr_reset_bus (struct ncb *np, struct scsi_cmnd *cmd, int sync_reset) return SUCCESS; } +#if 0 /* unused and broken.. */ /*========================================================== ** ** @@ -4360,17 +4026,7 @@ static int ncr_abort_command (struct ncb *np, struct scsi_cmnd *cmd) 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) { @@ -4395,7 +4051,8 @@ static void ncr_detach(struct ncb *np) 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; @@ -4536,8 +4193,7 @@ void ncr_complete (struct ncb *np, struct ccb *cp) 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; } } @@ -4609,19 +4265,6 @@ void ncr_complete (struct ncb *np, struct ccb *cp) if (!lp) ncr_alloc_lcb (np, cmd->device->id, cmd->device->lun); - /* - ** On standard INQUIRY response (EVPD and CmDt - ** not set), setup logical unit according to - ** announced capabilities (we need the 1rst 7 bytes). - */ - if (cmd->cmnd[0] == 0x12 && !(cmd->cmnd[1] & 0x3) && - cmd->cmnd[4] >= 7 && !cmd->use_sg) { - sync_scsi_data_for_cpu(np, cmd); /* SYNC the data */ - ncr_setup_lcb (np, cmd->device->id, cmd->device->lun, - (char *) cmd->request_buffer); - sync_scsi_data_for_device(np, cmd); /* SYNC the data */ - } - tp->bytes += cp->data_len; tp->transfers ++; @@ -4634,7 +4277,7 @@ void ncr_complete (struct ncb *np, struct ccb *cp) if (lp->num_good >= 1000) { lp->num_good = 0; ++lp->numtags; - ncr_setup_tags (np, cmd->device->id, cmd->device->lun); + ncr_setup_tags (np, cmd->device); } } } else if ((cp->host_status == HS_COMPLETE) @@ -4748,7 +4391,7 @@ void ncr_complete (struct ncb *np, struct ccb *cp) ** 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); /* @@ -4785,8 +4428,8 @@ static void ncr_ccb_skipped(struct ncb *np, struct ccb *cp) 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; } @@ -4871,7 +4514,7 @@ void ncr_wakeup (struct ncb *np, u_long code) 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) @@ -4900,7 +4543,7 @@ void ncr_init (struct ncb *np, int reset, char * msg, u_long code) if (reset) { OUTB (nc_istat, SRST); - UDELAY (100); + udelay(100); } else { OUTB (nc_stest3, TE|CSF); @@ -5084,8 +4727,11 @@ static void ncr_negotiate (struct ncb* np, struct tcb* tp) if (minsync > np->maxsync) minsync = 255; + if (tp->maxoffs > np->maxoffs) + tp->maxoffs = np->maxoffs; + tp->minsync = minsync; - tp->maxoffs = (minsync<255 ? np->maxoffs : 0); + tp->maxoffs = (minsync<255 ? tp->maxoffs : 0); /* ** period=0: has to negotiate sync transfer @@ -5215,18 +4861,12 @@ static void ncr_set_sync_wide_status (struct ncb *np, u_char target) 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]; @@ -5299,19 +4939,13 @@ static void ncr_setsync (struct ncb *np, struct ccb *cp, u_char scntl3, u_char s 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; @@ -5351,8 +4985,9 @@ static void ncr_setwide (struct ncb *np, struct ccb *cp, u_char wide, u_char ack **========================================================== */ -static void ncr_setup_tags (struct ncb *np, u_char tn, u_char ln) +static void ncr_setup_tags (struct ncb *np, struct scsi_device *sdev) { + unsigned char tn = sdev->id, ln = sdev->lun; struct tcb *tp = &np->target[tn]; struct lcb *lp = tp->lp[ln]; u_char reqtags, maxdepth; @@ -5360,7 +4995,7 @@ static void ncr_setup_tags (struct ncb *np, u_char tn, u_char ln) /* ** Just in case ... */ - if ((!tp) || (!lp)) + if ((!tp) || (!lp) || !sdev) return; /* @@ -5384,7 +5019,7 @@ static void ncr_setup_tags (struct ncb *np, u_char tn, u_char ln) ** only devices capable of tagged commands ** only if enabled by user .. */ - if ((lp->inq_byte7 & INQ7_QUEUE) && lp->numtags > 1) { + if (sdev->tagged_supported && lp->numtags > 1) { reqtags = lp->numtags; } else { reqtags = 1; @@ -5438,86 +5073,6 @@ static void ncr_setup_tags (struct ncb *np, u_char tn, u_char ln) } } -/*---------------------------------------------------- -** -** handle user commands -** -**---------------------------------------------------- -*/ - -#ifdef SCSI_NCR_USER_COMMAND_SUPPORT - -static void ncr_usercmd (struct ncb *np) -{ - u_char t; - struct tcb *tp; - - switch (np->user.cmd) { - - case 0: return; - - case UC_SETSYNC: - for (t=0; tuser.target>>t)&1)) continue; - tp = &np->target[t]; - tp->usrsync = np->user.data; - ncr_negotiate (np, tp); - }; - break; - - case UC_SETTAGS: - for (t=0; tuser.target>>t)&1)) continue; - np->target[t].usrtags = np->user.data; - for (ln = 0; ln < MAX_LUN; ln++) { - struct lcb *lp = np->target[t].lp[ln]; - if (!lp) - continue; - lp->maxtags = lp->numtags = np->user.data; - ncr_setup_tags (np, t, ln); - } - }; - break; - - case UC_SETDEBUG: -#ifdef SCSI_NCR_DEBUG_INFO_SUPPORT - ncr_debug = np->user.data; -#endif - break; - - case UC_SETORDER: - np->order = np->user.data; - break; - - case UC_SETVERBOSE: - np->verbose = np->user.data; - break; - - case UC_SETWIDE: - for (t=0; tuser.target>>t)&1)) continue; - tp = &np->target[t]; - size = np->user.data; - if (size > np->maxwide) size=np->maxwide; - tp->usrwide = size; - ncr_negotiate (np, tp); - }; - break; - - case UC_SETFLAG: - for (t=0; tuser.target>>t)&1)) continue; - tp = &np->target[t]; - tp->usrflag = np->user.data; - }; - break; - } - np->user.cmd=0; -} -#endif - /*========================================================== ** ** @@ -6002,13 +5557,6 @@ static int ncr_int_par (struct ncb *np) else msg = M_ID_ERROR; -#ifdef SCSI_NCR_INTEGRITY_CHECKING - /* - ** Save error message. For integrity check use only. - */ - if (np->check_integrity) - np->check_integ_par = msg; -#endif /* * If the NCR stopped on a MOVE ^ DATA_IN, we jump to a @@ -6353,7 +5901,7 @@ static void ncr_sir_to_redo(struct ncb *np, int num, struct ccb *cp) 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; @@ -6367,10 +5915,10 @@ static void ncr_sir_to_redo(struct ncb *np, int num, struct ccb *cp) ** 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; @@ -6398,7 +5946,7 @@ static void ncr_sir_to_redo(struct ncb *np, int num, struct ccb *cp) if (disc_cnt < lp->numtags) { lp->numtags = disc_cnt > 2 ? disc_cnt : 2; lp->num_good = 0; - ncr_setup_tags (np, cmd->device->id, cmd->device->lun); + ncr_setup_tags (np, cmd->device); } /* ** Requeue the command to the start queue. @@ -6450,7 +5998,7 @@ static void ncr_sir_to_redo(struct ncb *np, int num, struct ccb *cp) /* ** 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)); @@ -6475,7 +6023,7 @@ static void ncr_sir_to_redo(struct ncb *np, int num, struct ccb *cp) /* ** Select without ATN for quirky devices. */ - if (tp->quirks & QUIRK_NOMSG) + if (cmd->device->select_no_atn) cp->start.schedule.l_paddr = cpu_to_scr(NCB_SCRIPTH_PHYS (np, select_no_atn)); @@ -6537,6 +6085,7 @@ void ncr_int_sir (struct ncb *np) u_long dsa = INL (nc_dsa); u_char target = INB (nc_sdid) & 0x0f; struct tcb *tp = &np->target[target]; + struct scsi_target *starget = tp->starget; if (DEBUG_FLAGS & DEBUG_TINY) printk ("I#%d", num); @@ -6591,7 +6140,8 @@ void ncr_int_sir (struct ncb *np) 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; @@ -6693,10 +6243,13 @@ void ncr_int_sir (struct ncb *np) case NS_SYNC: ncr_setsync (np, cp, 0, 0xe0); + spi_period(starget) = 0; + spi_offset(starget) = 0; break; case NS_WIDE: ncr_setwide (np, cp, 0, 0); + spi_width(starget) = 0; break; }; @@ -6731,8 +6284,8 @@ void ncr_int_sir (struct ncb *np) ** it CAN transfer synch. */ - if (ofs) - tp->inq_byte7 |= INQ7_SYNC; + if (ofs && tp->starget) + spi_support_sync(tp->starget) = 1; /* ** check values against driver limits. @@ -6783,18 +6336,23 @@ void ncr_int_sir (struct ncb *np) ** Answer wasn't acceptable. */ ncr_setsync (np, cp, 0, 0xe0); + spi_period(starget) = 0; + spi_offset(starget) = 0; OUTL_DSP (NCB_SCRIPT_PHYS (np, msg_bad)); } else { /* ** Answer is ok. */ ncr_setsync (np, cp, scntl3, (fak<<5)|ofs); + spi_period(starget) = per; + spi_offset(starget) = ofs; OUTL_DSP (NCB_SCRIPT_PHYS (np, clrack)); }; return; case NS_WIDE: ncr_setwide (np, cp, 0, 0); + spi_width(starget) = 0; break; }; }; @@ -6805,6 +6363,8 @@ void ncr_int_sir (struct ncb *np) */ ncr_setsync (np, cp, scntl3, (fak<<5)|ofs); + spi_period(starget) = per; + spi_offset(starget) = ofs; np->msgout[0] = M_EXTENDED; np->msgout[1] = 3; @@ -6852,8 +6412,8 @@ void ncr_int_sir (struct ncb *np) ** it CAN transfer wide. */ - if (wide) - tp->inq_byte7 |= INQ7_WIDE16; + if (wide && tp->starget) + spi_support_wide(tp->starget) = 1; /* ** check values against driver limits. @@ -6880,18 +6440,22 @@ void ncr_int_sir (struct ncb *np) ** Answer wasn't acceptable. */ ncr_setwide (np, cp, 0, 1); + spi_width(starget) = 0; OUTL_DSP (NCB_SCRIPT_PHYS (np, msg_bad)); } else { /* ** Answer is ok. */ ncr_setwide (np, cp, wide, 1); + spi_width(starget) = wide; OUTL_DSP (NCB_SCRIPT_PHYS (np, clrack)); }; return; case NS_SYNC: ncr_setsync (np, cp, 0, 0xe0); + spi_period(starget) = 0; + spi_offset(starget) = 0; break; }; }; @@ -6902,6 +6466,7 @@ void ncr_int_sir (struct ncb *np) */ ncr_setwide (np, cp, wide, 1); + spi_width(starget) = wide; np->msgout[0] = M_EXTENDED; np->msgout[1] = 2; @@ -7017,7 +6582,7 @@ static struct ccb *ncr_get_ccb (struct ncb *np, u_char tn, u_char ln) ** Lun structure available ? */ if (lp) { - XPT_QUEHEAD *qp; + struct list_head *qp; /* ** Keep from using more tags than we can handle. */ @@ -7027,29 +6592,21 @@ static struct ccb *ncr_get_ccb (struct ncb *np, u_char tn, u_char ln) /* ** 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); - /* - ** Tune tag mode if asked by user. - */ - if (lp->queuedepth != lp->numtags) { - ncr_setup_tags(np, tn, ln); - } - /* ** 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; } } @@ -7159,10 +6716,8 @@ static void ncr_free_ccb (struct ncb *np, struct ccb *cp) */ 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; @@ -7200,9 +6755,9 @@ static void ncr_init_ccb(struct ncb *np, struct ccb *cp) 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. @@ -7246,7 +6801,7 @@ static void ncr_alloc_ccb(struct ncb *np, u_char tn, u_char ln) */ lp->actccbs++; np->actccbs++; - bzero (cp, sizeof (*cp)); + memset(cp, 0, sizeof (*cp)); ncr_init_ccb(np, cp); /* @@ -7256,8 +6811,7 @@ static void ncr_alloc_ccb(struct ncb *np, u_char tn, u_char ln) cp->link_ccb = np->ccb->link_ccb; np->ccb->link_ccb = cp; - xpt_insque_head(&cp->link_ccbq, &lp->free_ccbq); - ncr_setup_tags (np, tn, ln); + list_add(&cp->link_ccbq, &lp->free_ccbq); } /*========================================================== @@ -7345,15 +6899,15 @@ static void ncr_init_tcb (struct ncb *np, u_char tn) ** 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 } @@ -7384,7 +6938,7 @@ static struct lcb *ncr_alloc_lcb (struct ncb *np, u_char tn, u_char ln) 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; /* @@ -7396,10 +6950,10 @@ static struct lcb *ncr_alloc_lcb (struct ncb *np, u_char tn, u_char ln) /* ** 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 @@ -7455,11 +7009,12 @@ fail: ** will play with CHANGE DEFINITION commands. :-) **------------------------------------------------------------------------ */ -static struct lcb *ncr_setup_lcb (struct ncb *np, u_char tn, u_char ln, u_char *inq_data) +static struct lcb *ncr_setup_lcb (struct ncb *np, struct scsi_device *sdev) { + unsigned char tn = sdev->id, ln = sdev->lun; struct tcb *tp = &np->target[tn]; struct lcb *lp = tp->lp[ln]; - u_char inq_byte7; + struct scsi_target *starget = tp->starget; /* ** If no lcb, try to allocate it. @@ -7468,55 +7023,16 @@ static struct lcb *ncr_setup_lcb (struct ncb *np, u_char tn, u_char ln, u_char * goto fail; /* - ** Get device quirks from a speciality table. - */ - tp->quirks = ncr_lookup (inq_data); - if (tp->quirks && bootverbose) { - PRINT_LUN(np, tn, ln); - printk ("quirks=%x.\n", tp->quirks); - } - - /* - ** Evaluate trustable target/unit capabilities. - ** We only believe device version >= SCSI-2 that - ** use appropriate response data format (2). - ** But it seems that some CCS devices also - ** support SYNC and I donnot want to frustrate - ** anybody. ;-) - */ - inq_byte7 = 0; - if ((inq_data[2] & 0x7) >= 2 && (inq_data[3] & 0xf) == 2) - inq_byte7 = inq_data[7]; - else if ((inq_data[2] & 0x7) == 1 && (inq_data[3] & 0xf) == 1) - inq_byte7 = INQ7_SYNC; - - /* - ** Throw away announced LUN capabilities if we are told - ** that there is no real device supported by the logical unit. - */ - if ((inq_data[0] & 0xe0) > 0x20 || (inq_data[0] & 0x1f) == 0x1f) - inq_byte7 &= (INQ7_SYNC | INQ7_WIDE16); - - /* - ** If user is wanting SYNC, force this feature. + ** Prepare negotiation */ - if (driver_setup.force_sync_nego) - inq_byte7 |= INQ7_SYNC; - - /* - ** Prepare negotiation if SIP capabilities have changed. - */ - tp->inq_done = 1; - if ((inq_byte7 ^ tp->inq_byte7) & (INQ7_SYNC | INQ7_WIDE16)) { - tp->inq_byte7 = inq_byte7; + if (spi_support_wide(starget) || spi_support_sync(starget)) ncr_negotiate(np, tp); - } /* ** If unit supports tagged commands, allocate the ** CCB JUMP table if not yet. */ - if ((inq_byte7 & INQ7_QUEUE) && lp->jump_ccb == &lp->jump_ccb_0) { + if (sdev->tagged_supported && lp->jump_ccb == &lp->jump_ccb_0) { int i; lp->jump_ccb = m_calloc_dma(256, "JUMP_CCB"); if (!lp->jump_ccb) { @@ -7531,16 +7047,9 @@ static struct lcb *ncr_setup_lcb (struct ncb *np, u_char tn, u_char ln, u_char * lp->cb_tags[i] = i; lp->maxnxs = MAX_TAGS; lp->tags_stime = ktime_get(3*HZ); + ncr_setup_tags (np, sdev); } - /* - ** Adjust tagged queueing status if needed. - */ - if ((inq_byte7 ^ lp->inq_byte7) & INQ7_QUEUE) { - lp->inq_byte7 = inq_byte7; - lp->numtags = lp->maxtags; - ncr_setup_tags (np, tn, ln); - } fail: return lp; @@ -7746,62 +7255,6 @@ static int __init ncr_snooptest (struct ncb* np) return (err); } -/*========================================================== -** -** -** Device lookup. -** -** @GENSCSI@ should be integrated to scsiconf.c -** -** -**========================================================== -*/ - -struct table_entry { - char * manufacturer; - char * model; - char * version; - u_long info; -}; - -static struct table_entry device_tab[] = -{ -#if 0 - {"", "", "", QUIRK_NOMSG}, -#endif - {"SONY", "SDT-5000", "3.17", QUIRK_NOMSG}, - {"WangDAT", "Model 2600", "01.7", QUIRK_NOMSG}, - {"WangDAT", "Model 3200", "02.2", QUIRK_NOMSG}, - {"WangDAT", "Model 1300", "02.4", QUIRK_NOMSG}, - {"", "", "", 0} /* catch all: must be last entry. */ -}; - -static u_long ncr_lookup(char * id) -{ - struct table_entry * p = device_tab; - char *d, *r, c; - - for (;;p++) { - - d = id+8; - r = p->manufacturer; - while ((c=*r++)) if (c!=*d++) break; - if (c) continue; - - d = id+16; - r = p->model; - while ((c=*r++)) if (c!=*d++) break; - if (c) continue; - - d = id+32; - r = p->version; - while ((c=*r++)) if (c!=*d++) break; - if (c) continue; - - return (p->info); - } -} - /*========================================================== ** ** Determine the ncr's clock frequency. @@ -7842,11 +7295,11 @@ static void ncr_selectclock(struct ncb *np, u_char scntl3) 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 */ @@ -7887,7 +7340,7 @@ static unsigned __init ncrgetfreq (struct ncb *np, int gen) OUTB (nc_stime1, gen); /* set to nominal delay of 1<host; - struct ncb *np; - struct tcb *tp; - struct lcb *lp; + struct ncb *np = ((struct host_data *) host->hostdata)->ncb; + struct tcb *tp = &np->target[device->id]; + struct lcb *lp = tp->lp[device->lun]; int numtags, depth_to_use; - np = ((struct host_data *) host->hostdata)->ncb; - tp = &np->target[device->id]; - lp = tp->lp[device->lun]; + tp->starget = device->sdev_target; + + ncr_setup_lcb(np, device); /* ** Select queue depth from driver setup. @@ -8013,26 +7462,29 @@ int ncr53c8xx_slave_configure(struct scsi_device *device) ** 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; lp->scdev_depth = depth_to_use; } - ncr_setup_tags (np, device->id, device->lun); + ncr_setup_tags (np, device); #ifdef DEBUG_NCR53C8XX printk("ncr53c8xx_select_queue_depth: host=%d, id=%d, lun=%d, depth=%d\n", np->unit, device->id, device->lun, depth_to_use); #endif + if (spi_support_sync(device->sdev_target) && + !spi_initial_dv(device->sdev_target)) + spi_dv_device(device); 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; @@ -8047,7 +7499,7 @@ printk("ncr53c8xx_queue_command\n"); 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); @@ -8060,24 +7512,17 @@ printk("ncr53c8xx : command not queued - result=%d\n", sts); 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); done(cmd); + sts = 0; } 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; @@ -8092,58 +7537,42 @@ irqreturn_t ncr53c8xx_intr(int irq, void *dev_id, struct pt_regs * regs) 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, @@ -8151,22 +7580,20 @@ int ncr53c8xx_bus_reset(struct scsi_cmnd *cmd) * 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; @@ -8202,6 +7629,7 @@ out: return sts; } +#endif /* @@ -8286,291 +7714,23 @@ static void process_waiting_list(struct ncb *np, int sts) #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) +static ssize_t show_ncr53c8xx_revision(struct class_device *dev, char *buf) { - 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); + 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 int is_keyword(char *ptr, int len, char *verb) -{ - int verb_len = strlen(verb); - - if (len >= strlen(verb) && !memcmp(verb, ptr, verb_len)) - return verb_len; - else - return 0; - -} - -#define SKIP_SPACES(min_spaces) \ - if ((arg_len = skip_spaces(ptr, len)) < (min_spaces)) \ - return -EINVAL; \ - ptr += arg_len; len -= arg_len; - -#define GET_INT_ARG(v) \ - if (!(arg_len = get_int_arg(ptr, len, &(v)))) \ - return -EINVAL; \ - ptr += arg_len; len -= arg_len; - - -/* -** Parse a control command -*/ - -static int ncr_user_command(struct ncb *np, char *buffer, int length) -{ - char *ptr = buffer; - int len = length; - struct usrcmd *uc = &np->user; - int arg_len; - u_long target; - - bzero(uc, sizeof(*uc)); - - if (len > 0 && ptr[len-1] == '\n') - --len; - - if ((arg_len = is_keyword(ptr, len, "setsync")) != 0) - uc->cmd = UC_SETSYNC; - else if ((arg_len = is_keyword(ptr, len, "settags")) != 0) - uc->cmd = UC_SETTAGS; - else if ((arg_len = is_keyword(ptr, len, "setorder")) != 0) - uc->cmd = UC_SETORDER; - else if ((arg_len = is_keyword(ptr, len, "setverbose")) != 0) - uc->cmd = UC_SETVERBOSE; - else if ((arg_len = is_keyword(ptr, len, "setwide")) != 0) - uc->cmd = UC_SETWIDE; - else if ((arg_len = is_keyword(ptr, len, "setdebug")) != 0) - uc->cmd = UC_SETDEBUG; - else if ((arg_len = is_keyword(ptr, len, "setflag")) != 0) - uc->cmd = UC_SETFLAG; - else - arg_len = 0; - -#ifdef DEBUG_PROC_INFO -printk("ncr_user_command: arg_len=%d, cmd=%ld\n", arg_len, uc->cmd); -#endif - - if (!arg_len) - return -EINVAL; - ptr += arg_len; len -= arg_len; - - switch(uc->cmd) { - case UC_SETSYNC: - case UC_SETTAGS: - case UC_SETWIDE: - case UC_SETFLAG: - SKIP_SPACES(1); - if ((arg_len = is_keyword(ptr, len, "all")) != 0) { - ptr += arg_len; len -= arg_len; - uc->target = ~0; - } else { - GET_INT_ARG(target); - uc->target = (1<cmd) { - case UC_SETVERBOSE: - case UC_SETSYNC: - case UC_SETTAGS: - case UC_SETWIDE: - SKIP_SPACES(1); - GET_INT_ARG(uc->data); -#ifdef DEBUG_PROC_INFO -printk("ncr_user_command: data=%ld\n", uc->data); -#endif - break; - case UC_SETORDER: - SKIP_SPACES(1); - if ((arg_len = is_keyword(ptr, len, "simple"))) - uc->data = M_SIMPLE_TAG; - else if ((arg_len = is_keyword(ptr, len, "ordered"))) - uc->data = M_ORDERED_TAG; - else if ((arg_len = is_keyword(ptr, len, "default"))) - uc->data = 0; - else - return -EINVAL; - break; - case UC_SETDEBUG: - while (len > 0) { - SKIP_SPACES(1); - if ((arg_len = is_keyword(ptr, len, "alloc"))) - uc->data |= DEBUG_ALLOC; - else if ((arg_len = is_keyword(ptr, len, "phase"))) - uc->data |= DEBUG_PHASE; - else if ((arg_len = is_keyword(ptr, len, "queue"))) - uc->data |= DEBUG_QUEUE; - else if ((arg_len = is_keyword(ptr, len, "result"))) - uc->data |= DEBUG_RESULT; - else if ((arg_len = is_keyword(ptr, len, "scatter"))) - uc->data |= DEBUG_SCATTER; - else if ((arg_len = is_keyword(ptr, len, "script"))) - uc->data |= DEBUG_SCRIPT; - else if ((arg_len = is_keyword(ptr, len, "tiny"))) - uc->data |= DEBUG_TINY; - else if ((arg_len = is_keyword(ptr, len, "timing"))) - uc->data |= DEBUG_TIMING; - else if ((arg_len = is_keyword(ptr, len, "nego"))) - uc->data |= DEBUG_NEGO; - else if ((arg_len = is_keyword(ptr, len, "tags"))) - uc->data |= DEBUG_TAGS; - else - return -EINVAL; - ptr += arg_len; len -= arg_len; - } -#ifdef DEBUG_PROC_INFO -printk("ncr_user_command: data=%ld\n", uc->data); -#endif - break; - case UC_SETFLAG: - while (len > 0) { - SKIP_SPACES(1); - if ((arg_len = is_keyword(ptr, len, "trace"))) - uc->data |= UF_TRACE; - else if ((arg_len = is_keyword(ptr, len, "no_disc"))) - uc->data |= UF_NODISC; - else - return -EINVAL; - ptr += arg_len; len -= arg_len; - } - break; - default: - break; - } - - if (len) - return -EINVAL; - else { - unsigned long flags; - - NCR_LOCK_NCB(np, flags); - ncr_usercmd (np); - NCR_UNLOCK_NCB(np, flags); - } - return length; -} - -#endif /* SCSI_NCR_USER_COMMAND_SUPPORT */ - - -#ifdef SCSI_NCR_USER_INFO_SUPPORT -/* -** Copy formatted information into the input buffer. -*/ - -static int ncr_host_info(struct ncb *np, char *ptr, off_t offset, int len) -{ - struct info_str info; - - info.buffer = ptr; - info.length = len; - info.offset = offset; - info.pos = 0; - - copy_info(&info, " Chip NCR53C720, revision id 0x%x, IRQ %d\n", - np->revision_id, (int) np->irq); - copy_info(&info, " Synchronous period factor %d, " - "max commands per lun %d\n", - (int) np->minsync, MAX_TAGS); - - if (driver_setup.debug || driver_setup.verbose > 1) { - copy_info(&info, " Debug flags 0x%x, verbosity level %d\n", - driver_setup.debug, driver_setup.verbose); - } - - return info.pos > info.offset? info.pos - info.offset : 0; -} - -#endif /* SCSI_NCR_USER_INFO_SUPPORT */ - -/* -** Entry point of the scsi proc fs of the driver. -** - func = 0 means read (returns profile data) -** - func = 1 means write (parse user control command) -*/ - -static int ncr53c8xx_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t offset, - int length, int func) -{ - struct host_data *host_data; - struct ncb *ncb = NULL; - int retv; - -#ifdef DEBUG_PROC_INFO -printk("ncr53c8xx_proc_info: hostno=%d, func=%d\n", host->host_no, func); -#endif - - host_data = (struct host_data *) host->hostdata; - ncb = host_data->ncb; - - if (func) { -#ifdef SCSI_NCR_USER_COMMAND_SUPPORT - retv = ncr_user_command(ncb, buffer, length); -#else - retv = -EINVAL; -#endif - } - else { - if (start) - *start = buffer; -#ifdef SCSI_NCR_USER_INFO_SUPPORT - retv = ncr_host_info(ncb, buffer, offset, length); -#else - retv = -EINVAL; -#endif - } - - return retv; -} - -/*========================================================================= -** End of proc file system stuff -**========================================================================= -*/ -#endif - + +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 +}; /*========================================================== ** @@ -8580,10 +7740,10 @@ printk("ncr53c8xx_proc_info: hostno=%d, func=%d\n", host->host_no, func); */ #ifdef MODULE char *ncr53c8xx; /* command line passed by insmod */ -MODULE_PARM(ncr53c8xx, "s"); +module_param(ncr53c8xx, charp, 0); #endif -int __init ncr53c8xx_setup(char *str) +static int __init ncr53c8xx_setup(char *str) { return sym53c8xx__setup(str); } @@ -8592,17 +7752,6 @@ int __init ncr53c8xx_setup(char *str) __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. @@ -8622,13 +7771,14 @@ struct Scsi_Host * __init ncr_attach(struct scsi_host_template *tpnt, 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; @@ -8649,7 +7799,7 @@ struct Scsi_Host * __init ncr_attach(struct scsi_host_template *tpnt, 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; @@ -8689,7 +7839,7 @@ struct Scsi_Host * __init ncr_attach(struct scsi_host_template *tpnt, if (device->slot.base_v) np->vaddr = device->slot.base_v; else - np->vaddr = (unsigned long)ioremap(device->slot.base_c, 128); + np->vaddr = ioremap(device->slot.base_c, 128); if (!np->vaddr) { printk(KERN_ERR @@ -8705,7 +7855,7 @@ struct Scsi_Host * __init ncr_attach(struct scsi_host_template *tpnt, * OUTB OUTW OUTL macros can be used safely. */ - np->reg = (struct ncr_reg*) np->vaddr; + np->reg = (struct ncr_reg __iomem *)np->vaddr; /* Do chip dependent initialization. */ ncr_prepare_setting(np); @@ -8716,7 +7866,6 @@ struct Scsi_Host * __init ncr_attach(struct scsi_host_template *tpnt, ncr_name(np)); } - /* Fill Linux host instance structure */ instance->max_channel = 0; instance->this_id = np->myaddr; instance->max_id = np->maxwide ? 16 : 8; @@ -8727,19 +7876,12 @@ struct Scsi_Host * __init ncr_attach(struct scsi_host_template *tpnt, instance->dma_channel = 0; instance->cmd_per_lun = MAX_TAGS; instance->can_queue = (MAX_START-4); + /* This can happen if you forget to call ncr53c8xx_init from + * your module_init */ + BUG_ON(!ncr53c8xx_transport_template); + instance->transportt = ncr53c8xx_transport_template; scsi_set_device(instance, device->dev); -#ifdef SCSI_NCR_INTEGRITY_CHECKING - np->check_integrity = 0; - instance->check_integrity = 0; - -#ifdef SCSI_NCR_ENABLE_INTEGRITY_CHECK - if ( !(driver_setup.bus_check & 0x04) ) { - np->check_integrity = 1; - instance->check_integrity = 1; - } -#endif -#endif /* Patch script to physical addresses */ ncr_script_fill(&script0, &scripth0); @@ -8797,11 +7939,11 @@ struct Scsi_Host * __init ncr_attach(struct scsi_host_template *tpnt, * 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); @@ -8815,7 +7957,7 @@ struct Scsi_Host * __init ncr_attach(struct scsi_host_template *tpnt, 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 */ @@ -8827,7 +7969,7 @@ struct Scsi_Host * __init ncr_attach(struct scsi_host_template *tpnt, np->order = M_SIMPLE_TAG; #endif - NCR_UNLOCK_NCB(np, flags); + spin_unlock_irqrestore(&np->smp_lock, flags); return instance; @@ -8866,3 +8008,73 @@ int ncr53c8xx_release(struct Scsi_Host *host) ncr_detach(host_data->ncb); return 1; } + +static void ncr53c8xx_set_period(struct scsi_target *starget, int period) +{ + struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); + struct ncb *np = ((struct host_data *)shost->hostdata)->ncb; + struct tcb *tp = &np->target[starget->id]; + + if (period > np->maxsync) + period = np->maxsync; + else if (period < np->minsync) + period = np->minsync; + + tp->usrsync = period; + + ncr_negotiate(np, tp); +} + +static void ncr53c8xx_set_offset(struct scsi_target *starget, int offset) +{ + struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); + struct ncb *np = ((struct host_data *)shost->hostdata)->ncb; + struct tcb *tp = &np->target[starget->id]; + + if (offset > np->maxoffs) + offset = np->maxoffs; + else if (offset < 0) + offset = 0; + + tp->maxoffs = offset; + + ncr_negotiate(np, tp); +} + +static void ncr53c8xx_set_width(struct scsi_target *starget, int width) +{ + struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); + struct ncb *np = ((struct host_data *)shost->hostdata)->ncb; + struct tcb *tp = &np->target[starget->id]; + + if (width > np->maxwide) + width = np->maxwide; + else if (width < 0) + width = 0; + + tp->usrwide = width; + + ncr_negotiate(np, tp); +} + +static struct spi_function_template ncr53c8xx_transport_functions = { + .set_period = ncr53c8xx_set_period, + .show_period = 1, + .set_offset = ncr53c8xx_set_offset, + .show_offset = 1, + .set_width = ncr53c8xx_set_width, + .show_width = 1, +}; + +int __init ncr53c8xx_init(void) +{ + ncr53c8xx_transport_template = spi_attach_transport(&ncr53c8xx_transport_functions); + if (!ncr53c8xx_transport_template) + return -ENODEV; + return 0; +} + +void ncr53c8xx_exit(void) +{ + spi_release_transport(ncr53c8xx_transport_template); +}