- np->base_io = device->slot.io_port;
-#endif /* !defined SCSI_NCR_IOMAPPED */
-
-#ifdef SCSI_NCR_NVRAM_SUPPORT
- if (nvram) {
- switch(nvram->type) {
- case SCSI_NCR_SYMBIOS_NVRAM:
-#ifdef SCSI_NCR_DEBUG_NVRAM
- ncr_display_Symbios_nvram(&nvram->data.Symbios);
-#endif
- break;
- case SCSI_NCR_TEKRAM_NVRAM:
-#ifdef SCSI_NCR_DEBUG_NVRAM
- ncr_display_Tekram_nvram(&nvram->data.Tekram);
-#endif
- break;
- default:
- nvram = 0;
-#ifdef SCSI_NCR_DEBUG_NVRAM
- printk(KERN_DEBUG "%s: NVRAM: None or invalid data.\n", ncr_name(np));
-#endif
- }
- }
-#endif
-
- /*
- ** Do chip dependent initialization.
- */
- (void)ncr_prepare_setting(np, nvram);
-
- if (np->paddr2 && sizeof(struct script) > 4096) {
- np->paddr2 = 0;
- printk(KERN_WARNING "%s: script too large, NOT using on chip RAM.\n",
- ncr_name(np));
- }
-
- /*
- ** Fill Linux host instance structure
- */
- instance->max_channel = 0;
- instance->this_id = np->myaddr;
- instance->max_id = np->maxwide ? 16 : 8;
- instance->max_lun = SCSI_NCR_MAX_LUN;
-#ifndef SCSI_NCR_IOMAPPED
- instance->base = (unsigned long) np->reg;
-#endif
- instance->irq = device->slot.irq;
- instance->unique_id = device->slot.io_port;
- instance->io_port = device->slot.io_port;
- instance->n_io_port = 128;
- instance->dma_channel = 0;
- instance->cmd_per_lun = MAX_TAGS;
- instance->can_queue = (MAX_START-4);
- 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);
-
- np->scripth = np->scripth0;
- np->p_scripth = vtobus(np->scripth);
-
- np->p_script = (np->paddr2) ? np->paddr2 : vtobus(np->script0);
-
- ncr_script_copy_and_bind (np, (ncrcmd *) &script0, (ncrcmd *) np->script0, sizeof(struct script));
- ncr_script_copy_and_bind (np, (ncrcmd *) &scripth0, (ncrcmd *) np->scripth0, sizeof(struct scripth));
- np->ccb->p_ccb = vtobus (np->ccb);
-
- /*
- ** Patch the script for LED support.
- */
-
- if (np->features & FE_LED0) {
- np->script0->idle[0] =
- cpu_to_scr(SCR_REG_REG(gpreg, SCR_OR, 0x01));
- np->script0->reselected[0] =
- cpu_to_scr(SCR_REG_REG(gpreg, SCR_AND, 0xfe));
- np->script0->start[0] =
- cpu_to_scr(SCR_REG_REG(gpreg, SCR_AND, 0xfe));
- }
-
- /*
- ** Look for the target control block of this nexus.
- ** For i = 0 to 3
- ** JUMP ^ IFTRUE (MASK (i, 3)), @(next_lcb)
- */
- for (i = 0 ; i < 4 ; i++) {
- np->jump_tcb[i].l_cmd =
- cpu_to_scr((SCR_JUMP ^ IFTRUE (MASK (i, 3))));
- np->jump_tcb[i].l_paddr =
- cpu_to_scr(NCB_SCRIPTH_PHYS (np, bad_target));
- }
-
- /*
- ** Reset chip.
- */
- ncr_chip_reset(np, 100);
-
- /*
- ** Now check the cache handling of the chipset.
- */
-
- if (ncr_snooptest (np)) {
- printk (KERN_ERR "CACHE INCORRECTLY CONFIGURED.\n");
- goto attach_error;
- };
-
- /*
- ** Install the interrupt handler.
- */
-
- np->irq = device->slot.irq;
-
- /*
- ** Initialize the fixed part of the default ccb.
- */
- ncr_init_ccb(np, np->ccb);
-
- /*
- ** After SCSI devices have been opened, we cannot
- ** reset the bus safely, so we do it here.
- ** Interrupt handler does the real work.
- ** Process the reset exception,
- ** if interrupts are not enabled yet.
- ** Then enable disconnects.
- */
- NCR_LOCK_NCB(np, 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);
- goto attach_error;
- }
- ncr_exception (np);
-
- np->disc = 1;
-
- /*
- ** The middle-level SCSI driver does not
- ** wait for devices to settle.
- ** Wait synchronously if more than 2 seconds.
- */
- 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);
- }
-
- /*
- ** Now let the generic SCSI driver
- ** look for the SCSI devices on the bus ..
- */
-
- /*
- ** start the timeout daemon
- */
- np->lasttime=0;
- ncr_timeout (np);
-
- /*
- ** use SIMPLE TAG messages by default
- */
-#ifdef SCSI_NCR_ALWAYS_SIMPLE_TAG
- np->order = M_SIMPLE_TAG;
-#endif
-
- NCR_UNLOCK_NCB(np, flags);
-
- return instance;
-
-attach_error:
- if (!instance) return NULL;
- printk(KERN_INFO "%s: detaching...\n", ncr_name(np));
- if (!np)
- goto unregister;
- if (np->scripth0)
- m_free_dma(np->scripth0, sizeof(struct scripth), "SCRIPTH");
- if (np->script0)
- m_free_dma(np->script0, sizeof(struct script), "SCRIPT");
- if (np->ccb)
- m_free_dma(np->ccb, sizeof(struct ccb), "CCB");
- m_free_dma(np, sizeof(struct ncb), "NCB");
-
-unregister:
- scsi_host_put(instance);
-
- return NULL;
-}
-
-
-/*==========================================================
-**
-**
-** Done SCSI commands list management.
-**
-** We donnot enter the scsi_done() callback immediately
-** after a command has been seen as completed but we
-** insert it into a list which is flushed outside any kind
-** of driver critical section.
-** This allows to do minimal stuff under interrupt and
-** inside critical sections and to also avoid locking up
-** on recursive calls to driver entry points under SMP.
-** In fact, the only kernel point which is entered by the
-** driver with a driver lock set is kmalloc(GFP_ATOMIC)
-** that shall not reenter the driver under any circumstances,
-** AFAIK.
-**
-**==========================================================
-*/
-static inline void ncr_queue_done_cmd(ncb_p np, Scsi_Cmnd *cmd)
-{
- unmap_scsi_data(np, cmd);
- cmd->host_scribble = (char *) np->done_list;
- np->done_list = cmd;
-}
-
-static inline void ncr_flush_done_cmds(Scsi_Cmnd *lcmd)
-{
- Scsi_Cmnd *cmd;
-
- while (lcmd) {
- cmd = lcmd;
- lcmd = (Scsi_Cmnd *) cmd->host_scribble;
- cmd->scsi_done(cmd);
- }
-}
-
-/*==========================================================
-**
-**
-** 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(ncb_p np, ccb_p cp, Scsi_Cmnd *cmd, u_char *msgptr)
-{
- tcb_p 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 */
-
-/*==========================================================
-**
-**
-** Prepare the next negotiation message 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.
-**
-**
-**==========================================================
-*/
-
-
-static int ncr_prepare_nego(ncb_p np, ccb_p cp, u_char *msgptr)
-{
- tcb_p tp = &np->target[cp->target];
- int msglen = 0;
- int nego = 0;
-
- if (tp->inq_done) {
-
- /*
- ** negotiate wide transfers ?
- */
-
- if (!tp->widedone) {
- if (tp->inq_byte7 & INQ7_WIDE16) {
- nego = NS_WIDE;
-#ifdef SCSI_NCR_INTEGRITY_CHECKING
- if (tp->ic_done)
- tp->usrwide &= tp->ic_max_width;
-#endif
- } else
- tp->widedone=1;
-
- };
-
- /*
- ** negotiate synchronous transfers?
- */
-
- if (!nego && !tp->period) {
- if (tp->inq_byte7 & INQ7_SYNC) {
- 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);
- printk ("target did not report SYNC.\n");
- };
- };
- };
-
- switch (nego) {
- case NS_SYNC:
- msgptr[msglen++] = M_EXTENDED;
- msgptr[msglen++] = 3;
- msgptr[msglen++] = M_X_SYNC_REQ;
- msgptr[msglen++] = tp->maxoffs ? tp->minsync : 0;
- msgptr[msglen++] = tp->maxoffs;
- break;
- case NS_WIDE:
- msgptr[msglen++] = M_EXTENDED;
- msgptr[msglen++] = 2;
- msgptr[msglen++] = M_X_WIDE_REQ;
- msgptr[msglen++] = tp->usrwide;
- break;
- };
-
- cp->nego_status = nego;
-
- if (nego) {
- tp->nego_cp = cp;
- if (DEBUG_FLAGS & DEBUG_NEGO) {
- ncr_print_msg(cp, nego == NS_WIDE ?
- "wide msgout":"sync_msgout", msgptr);
- };
- };
-
- return msglen;
-}
-
-
-
-/*==========================================================
-**
-**
-** Start execution of a SCSI command.
-** This is called from the generic SCSI driver.
-**
-**
-**==========================================================
-*/
-static int ncr_queue_command (ncb_p np, Scsi_Cmnd *cmd)
-{
-/* Scsi_Device *device = cmd->device; */
- tcb_p tp = &np->target[cmd->device->id];
- lcb_p lp = tp->lp[cmd->device->lun];
- ccb_p cp;
-
- int segments;
- u_char idmsg, *msgptr;
- u_int msglen;
- int direction;
- u32 lastp, goalp;