2965 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/**************************************************************************3 * Initio 9100 device driver for Linux.4 *5 * Copyright (c) 1994-1998 Initio Corporation6 * Copyright (c) 1998 Bas Vermeulen <bvermeul@blackstar.xs4all.nl>7 * Copyright (c) 2004 Christoph Hellwig <hch@lst.de>8 * Copyright (c) 2007 Red Hat9 *10 *************************************************************************11 *12 * DESCRIPTION:13 *14 * This is the Linux low-level SCSI driver for Initio INI-9X00U/UW SCSI host15 * adapters16 *17 * 08/06/97 hc - v1.01h18 * - Support inic-940 and inic-93519 * 09/26/97 hc - v1.01i20 * - Make correction from J.W. Schultz suggestion21 * 10/13/97 hc - Support reset function22 * 10/21/97 hc - v1.01j23 * - Support 32 LUN (SCSI 3)24 * 01/14/98 hc - v1.01k25 * - Fix memory allocation problem26 * 03/04/98 hc - v1.01l27 * - Fix tape rewind which will hang the system problem28 * - Set can_queue to initio_num_scb29 * 06/25/98 hc - v1.01m30 * - Get it work for kernel version >= 2.1.7531 * - Dynamic assign SCSI bus reset holding time in initio_init()32 * 07/02/98 hc - v1.01n33 * - Support 0002134A34 * 08/07/98 hc - v1.01o35 * - Change the initio_abort_srb routine to use scsi_done. <01>36 * 09/07/98 hl - v1.0237 * - Change the INI9100U define and proc_dir_entry to38 * reflect the newer Kernel 2.1.118, but the v1.o1o39 * should work with Kernel 2.1.118.40 * 09/20/98 wh - v1.02a41 * - Support Abort command.42 * - Handle reset routine.43 * 09/21/98 hl - v1.0344 * - remove comments.45 * 12/09/98 bv - v1.03a46 * - Removed unused code47 * 12/13/98 bv - v1.03b48 * - Remove cli() locking for kernels >= 2.1.95. This uses49 * spinlocks to serialize access to the pSRB_head and50 * pSRB_tail members of the HCS structure.51 * 09/01/99 bv - v1.03d52 * - Fixed a deadlock problem in SMP.53 * 21/01/99 bv - v1.03e54 * - Add support for the Domex 3192U PCI SCSI55 * This is a slightly modified patch by56 * Brian Macy <bmacy@sunshinecomputing.com>57 * 22/02/99 bv - v1.03f58 * - Didn't detect the INIC-950 in 2.0.x correctly.59 * Now fixed.60 * 05/07/99 bv - v1.03g61 * - Changed the assumption that HZ = 10062 * 10/17/03 mc - v1.0463 * - added new DMA API support64 * 06/01/04 jmd - v1.04a65 * - Re-add reset_bus support66 **************************************************************************/67 68#include <linux/module.h>69#include <linux/errno.h>70#include <linux/delay.h>71#include <linux/pci.h>72#include <linux/init.h>73#include <linux/blkdev.h>74#include <linux/spinlock.h>75#include <linux/stat.h>76#include <linux/kernel.h>77#include <linux/proc_fs.h>78#include <linux/string.h>79#include <linux/interrupt.h>80#include <linux/ioport.h>81#include <linux/slab.h>82#include <linux/jiffies.h>83#include <linux/dma-mapping.h>84#include <asm/io.h>85 86#include <scsi/scsi.h>87#include <scsi/scsi_cmnd.h>88#include <scsi/scsi_device.h>89#include <scsi/scsi_host.h>90#include <scsi/scsi_tcq.h>91 92#include "initio.h"93 94#define SENSE_SIZE 1495 96#define i91u_MAXQUEUE 297#define i91u_REVID "Initio INI-9X00U/UW SCSI device driver; Revision: 1.04a"98 99#ifdef DEBUG_i91u100static unsigned int i91u_debug = DEBUG_DEFAULT;101#endif102 103static int initio_tag_enable = 1;104 105#ifdef DEBUG_i91u106static int setup_debug = 0;107#endif108 109static void i91uSCBPost(u8 * pHcb, u8 * pScb);110 111#define DEBUG_INTERRUPT 0112#define DEBUG_QUEUE 0113#define DEBUG_STATE 0114#define INT_DISC 0115 116/*--- forward references ---*/117static struct scsi_ctrl_blk *initio_find_busy_scb(struct initio_host * host, u16 tarlun);118static struct scsi_ctrl_blk *initio_find_done_scb(struct initio_host * host);119 120static int tulip_main(struct initio_host * host);121 122static int initio_next_state(struct initio_host * host);123static int initio_state_1(struct initio_host * host);124static int initio_state_2(struct initio_host * host);125static int initio_state_3(struct initio_host * host);126static int initio_state_4(struct initio_host * host);127static int initio_state_5(struct initio_host * host);128static int initio_state_6(struct initio_host * host);129static int initio_state_7(struct initio_host * host);130static int initio_xfer_data_in(struct initio_host * host);131static int initio_xfer_data_out(struct initio_host * host);132static int initio_xpad_in(struct initio_host * host);133static int initio_xpad_out(struct initio_host * host);134static int initio_status_msg(struct initio_host * host);135 136static int initio_msgin(struct initio_host * host);137static int initio_msgin_sync(struct initio_host * host);138static int initio_msgin_accept(struct initio_host * host);139static int initio_msgout_reject(struct initio_host * host);140static int initio_msgin_extend(struct initio_host * host);141 142static int initio_msgout_ide(struct initio_host * host);143static int initio_msgout_abort_targ(struct initio_host * host);144static int initio_msgout_abort_tag(struct initio_host * host);145 146static int initio_bus_device_reset(struct initio_host * host);147static void initio_select_atn(struct initio_host * host, struct scsi_ctrl_blk * scb);148static void initio_select_atn3(struct initio_host * host, struct scsi_ctrl_blk * scb);149static void initio_select_atn_stop(struct initio_host * host, struct scsi_ctrl_blk * scb);150static int int_initio_busfree(struct initio_host * host);151static int int_initio_scsi_rst(struct initio_host * host);152static int int_initio_bad_seq(struct initio_host * host);153static int int_initio_resel(struct initio_host * host);154static int initio_sync_done(struct initio_host * host);155static int wdtr_done(struct initio_host * host);156static int wait_tulip(struct initio_host * host);157static int initio_wait_done_disc(struct initio_host * host);158static int initio_wait_disc(struct initio_host * host);159static void tulip_scsi(struct initio_host * host);160static int initio_post_scsi_rst(struct initio_host * host);161 162static void initio_se2_ew_en(unsigned long base);163static void initio_se2_ew_ds(unsigned long base);164static int initio_se2_rd_all(unsigned long base);165static void initio_se2_update_all(unsigned long base); /* setup default pattern */166static void initio_read_eeprom(unsigned long base);167 168/* ---- INTERNAL VARIABLES ---- */169 170static NVRAM i91unvram;171static NVRAM *i91unvramp;172 173static u8 i91udftNvRam[64] =174{175 /*----------- header -----------*/176 0x25, 0xc9, /* Signature */177 0x40, /* Size */178 0x01, /* Revision */179 /* -- Host Adapter Structure -- */180 0x95, /* ModelByte0 */181 0x00, /* ModelByte1 */182 0x00, /* ModelInfo */183 0x01, /* NumOfCh */184 NBC1_DEFAULT, /* BIOSConfig1 */185 0, /* BIOSConfig2 */186 0, /* HAConfig1 */187 0, /* HAConfig2 */188 /* SCSI channel 0 and target Structure */189 7, /* SCSIid */190 NCC1_DEFAULT, /* SCSIconfig1 */191 0, /* SCSIconfig2 */192 0x10, /* NumSCSItarget */193 194 NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT,195 NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT,196 NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT,197 NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT,198 199 /* SCSI channel 1 and target Structure */200 7, /* SCSIid */201 NCC1_DEFAULT, /* SCSIconfig1 */202 0, /* SCSIconfig2 */203 0x10, /* NumSCSItarget */204 205 NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT,206 NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT,207 NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT,208 NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT,209 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,210 0, 0}; /* - CheckSum - */211 212 213static u8 initio_rate_tbl[8] = /* fast 20 */214{215 /* nanosecond divide by 4 */216 12, /* 50ns, 20M */217 18, /* 75ns, 13.3M */218 25, /* 100ns, 10M */219 31, /* 125ns, 8M */220 37, /* 150ns, 6.6M */221 43, /* 175ns, 5.7M */222 50, /* 200ns, 5M */223 62 /* 250ns, 4M */224};225 226static void initio_do_pause(unsigned amount)227{228 /* Pause for amount jiffies */229 unsigned long the_time = jiffies + amount;230 231 while (time_before_eq(jiffies, the_time))232 cpu_relax();233}234 235/*-- forward reference --*/236 237/******************************************************************238 Input: instruction for Serial E2PROM239 240 EX: se2_rd(0 call se2_instr() to send address and read command241 242 StartBit OP_Code Address Data243 --------- -------- ------------------ -------244 1 1 , 0 A5,A4,A3,A2,A1,A0 D15-D0245 246 +-----------------------------------------------------247 |248 CS -----+249 +--+ +--+ +--+ +--+ +--+250 ^ | ^ | ^ | ^ | ^ |251 | | | | | | | | | |252 CLK -------+ +--+ +--+ +--+ +--+ +--253 (leading edge trigger)254 255 +--1-----1--+256 | SB OP | OP A5 A4257 DI ----+ +--0------------------258 (address and cmd sent to nvram)259 260 -------------------------------------------+261 |262 DO +---263 (data sent from nvram)264 265 266******************************************************************/267 268/**269 * initio_se2_instr - bitbang an instruction270 * @base: Base of InitIO controller271 * @instr: Instruction for serial E2PROM272 *273 * Bitbang an instruction out to the serial E2Prom274 */275 276static void initio_se2_instr(unsigned long base, u8 instr)277{278 int i;279 u8 b;280 281 outb(SE2CS | SE2DO, base + TUL_NVRAM); /* cs+start bit */282 udelay(30);283 outb(SE2CS | SE2CLK | SE2DO, base + TUL_NVRAM); /* +CLK */284 udelay(30);285 286 for (i = 0; i < 8; i++) {287 if (instr & 0x80)288 b = SE2CS | SE2DO; /* -CLK+dataBit */289 else290 b = SE2CS; /* -CLK */291 outb(b, base + TUL_NVRAM);292 udelay(30);293 outb(b | SE2CLK, base + TUL_NVRAM); /* +CLK */294 udelay(30);295 instr <<= 1;296 }297 outb(SE2CS, base + TUL_NVRAM); /* -CLK */298 udelay(30);299}300 301 302/**303 * initio_se2_ew_en - Enable erase/write304 * @base: Base address of InitIO controller305 *306 * Enable erase/write state of serial EEPROM307 */308void initio_se2_ew_en(unsigned long base)309{310 initio_se2_instr(base, 0x30); /* EWEN */311 outb(0, base + TUL_NVRAM); /* -CS */312 udelay(30);313}314 315 316/**317 * initio_se2_ew_ds - Disable erase/write318 * @base: Base address of InitIO controller319 *320 * Disable erase/write state of serial EEPROM321 */322void initio_se2_ew_ds(unsigned long base)323{324 initio_se2_instr(base, 0); /* EWDS */325 outb(0, base + TUL_NVRAM); /* -CS */326 udelay(30);327}328 329 330/**331 * initio_se2_rd - read E2PROM word332 * @base: Base of InitIO controller333 * @addr: Address of word in E2PROM334 *335 * Read a word from the NV E2PROM device336 */337static u16 initio_se2_rd(unsigned long base, u8 addr)338{339 u8 instr, rb;340 u16 val = 0;341 int i;342 343 instr = (u8) (addr | 0x80);344 initio_se2_instr(base, instr); /* READ INSTR */345 346 for (i = 15; i >= 0; i--) {347 outb(SE2CS | SE2CLK, base + TUL_NVRAM); /* +CLK */348 udelay(30);349 outb(SE2CS, base + TUL_NVRAM); /* -CLK */350 351 /* sample data after the following edge of clock */352 rb = inb(base + TUL_NVRAM);353 rb &= SE2DI;354 val += (rb << i);355 udelay(30); /* 6/20/95 */356 }357 358 outb(0, base + TUL_NVRAM); /* no chip select */359 udelay(30);360 return val;361}362 363/**364 * initio_se2_wr - read E2PROM word365 * @base: Base of InitIO controller366 * @addr: Address of word in E2PROM367 * @val: Value to write368 *369 * Write a word to the NV E2PROM device. Used when recovering from370 * a problem with the NV.371 */372static void initio_se2_wr(unsigned long base, u8 addr, u16 val)373{374 u8 instr;375 int i;376 377 instr = (u8) (addr | 0x40);378 initio_se2_instr(base, instr); /* WRITE INSTR */379 for (i = 15; i >= 0; i--) {380 if (val & 0x8000)381 outb(SE2CS | SE2DO, base + TUL_NVRAM); /* -CLK+dataBit 1 */382 else383 outb(SE2CS, base + TUL_NVRAM); /* -CLK+dataBit 0 */384 udelay(30);385 outb(SE2CS | SE2CLK, base + TUL_NVRAM); /* +CLK */386 udelay(30);387 val <<= 1;388 }389 outb(SE2CS, base + TUL_NVRAM); /* -CLK */390 udelay(30);391 outb(0, base + TUL_NVRAM); /* -CS */392 udelay(30);393 394 outb(SE2CS, base + TUL_NVRAM); /* +CS */395 udelay(30);396 397 for (;;) {398 outb(SE2CS | SE2CLK, base + TUL_NVRAM); /* +CLK */399 udelay(30);400 outb(SE2CS, base + TUL_NVRAM); /* -CLK */401 udelay(30);402 if (inb(base + TUL_NVRAM) & SE2DI)403 break; /* write complete */404 }405 outb(0, base + TUL_NVRAM); /* -CS */406}407 408/**409 * initio_se2_rd_all - read hostadapter NV configuration410 * @base: Base address of InitIO controller411 *412 * Reads the E2PROM data into main memory. Ensures that the checksum413 * and header marker are valid. Returns 1 on success -1 on error.414 */415 416static int initio_se2_rd_all(unsigned long base)417{418 int i;419 u16 chksum = 0;420 u16 *np;421 422 i91unvramp = &i91unvram;423 np = (u16 *) i91unvramp;424 for (i = 0; i < 32; i++)425 *np++ = initio_se2_rd(base, i);426 427 /* Is signature "ini" ok ? */428 if (i91unvramp->NVM_Signature != INI_SIGNATURE)429 return -1;430 /* Is ckecksum ok ? */431 np = (u16 *) i91unvramp;432 for (i = 0; i < 31; i++)433 chksum += *np++;434 if (i91unvramp->NVM_CheckSum != chksum)435 return -1;436 return 1;437}438 439/**440 * initio_se2_update_all - Update E2PROM441 * @base: Base of InitIO controller442 *443 * Update the E2PROM by wrting any changes into the E2PROM444 * chip, rewriting the checksum.445 */446static void initio_se2_update_all(unsigned long base)447{ /* setup default pattern */448 int i;449 u16 chksum = 0;450 u16 *np, *np1;451 452 i91unvramp = &i91unvram;453 /* Calculate checksum first */454 np = (u16 *) i91udftNvRam;455 for (i = 0; i < 31; i++)456 chksum += *np++;457 *np = chksum;458 initio_se2_ew_en(base); /* Enable write */459 460 np = (u16 *) i91udftNvRam;461 np1 = (u16 *) i91unvramp;462 for (i = 0; i < 32; i++, np++, np1++) {463 if (*np != *np1)464 initio_se2_wr(base, i, *np);465 }466 initio_se2_ew_ds(base); /* Disable write */467}468 469/**470 * initio_read_eeprom - Retrieve configuration471 * @base: Base of InitIO Host Adapter472 *473 * Retrieve the host adapter configuration data from E2Prom. If the474 * data is invalid then the defaults are used and are also restored475 * into the E2PROM. This forms the access point for the SCSI driver476 * into the E2PROM layer, the other functions for the E2PROM are all477 * internal use.478 *479 * Must be called single threaded, uses a shared global area.480 */481 482static void initio_read_eeprom(unsigned long base)483{484 u8 gctrl;485 486 i91unvramp = &i91unvram;487 /* Enable EEProm programming */488 gctrl = inb(base + TUL_GCTRL);489 outb(gctrl | TUL_GCTRL_EEPROM_BIT, base + TUL_GCTRL);490 if (initio_se2_rd_all(base) != 1) {491 initio_se2_update_all(base); /* setup default pattern */492 initio_se2_rd_all(base); /* load again */493 }494 /* Disable EEProm programming */495 gctrl = inb(base + TUL_GCTRL);496 outb(gctrl & ~TUL_GCTRL_EEPROM_BIT, base + TUL_GCTRL);497}498 499/**500 * initio_stop_bm - stop bus master501 * @host: InitIO we are stopping502 *503 * Stop any pending DMA operation, aborting the DMA if necessary504 */505 506static void initio_stop_bm(struct initio_host * host)507{508 509 if (inb(host->addr + TUL_XStatus) & XPEND) { /* if DMA xfer is pending, abort DMA xfer */510 outb(TAX_X_ABT | TAX_X_CLR_FIFO, host->addr + TUL_XCmd);511 /* wait Abort DMA xfer done */512 while ((inb(host->addr + TUL_Int) & XABT) == 0)513 cpu_relax();514 }515 outb(TSC_FLUSH_FIFO, host->addr + TUL_SCtrl0);516}517 518/**519 * initio_reset_scsi - Reset SCSI host controller520 * @host: InitIO host to reset521 * @seconds: Recovery time522 *523 * Perform a full reset of the SCSI subsystem.524 */525 526static int initio_reset_scsi(struct initio_host * host, int seconds)527{528 outb(TSC_RST_BUS, host->addr + TUL_SCtrl0);529 530 while (!((host->jsint = inb(host->addr + TUL_SInt)) & TSS_SCSIRST_INT))531 cpu_relax();532 533 /* reset tulip chip */534 outb(0, host->addr + TUL_SSignal);535 536 /* Stall for a while, wait for target's firmware ready,make it 2 sec ! */537 /* SONY 5200 tape drive won't work if only stall for 1 sec */538 /* FIXME: this is a very long busy wait right now */539 initio_do_pause(seconds * HZ);540 541 inb(host->addr + TUL_SInt);542 return SCSI_RESET_SUCCESS;543}544 545/**546 * initio_init - set up an InitIO host adapter547 * @host: InitIO host adapter548 * @bios_addr: BIOS address549 *550 * Set up the host adapter and devices according to the configuration551 * retrieved from the E2PROM.552 *553 * Locking: Calls E2PROM layer code which is not re-enterable so must554 * run single threaded for now.555 */556 557static void initio_init(struct initio_host * host, u8 *bios_addr)558{559 int i;560 u8 *flags;561 u8 *heads;562 563 /* Get E2Prom configuration */564 initio_read_eeprom(host->addr);565 if (i91unvramp->NVM_SCSIInfo[0].NVM_NumOfTarg == 8)566 host->max_tar = 8;567 else568 host->max_tar = 16;569 570 host->config = i91unvramp->NVM_SCSIInfo[0].NVM_ChConfig1;571 572 host->scsi_id = i91unvramp->NVM_SCSIInfo[0].NVM_ChSCSIID;573 host->idmask = ~(1 << host->scsi_id);574 575#ifdef CHK_PARITY576 /* Enable parity error response */577 outb(inb(host->addr + TUL_PCMD) | 0x40, host->addr + TUL_PCMD);578#endif579 580 /* Mask all the interrupt */581 outb(0x1F, host->addr + TUL_Mask);582 583 initio_stop_bm(host);584 /* --- Initialize the tulip --- */585 outb(TSC_RST_CHIP, host->addr + TUL_SCtrl0);586 587 /* program HBA's SCSI ID */588 outb(host->scsi_id << 4, host->addr + TUL_SScsiId);589 590 /* Enable Initiator Mode ,phase latch,alternate sync period mode,591 disable SCSI reset */592 if (host->config & HCC_EN_PAR)593 host->sconf1 = (TSC_INITDEFAULT | TSC_EN_SCSI_PAR);594 else595 host->sconf1 = (TSC_INITDEFAULT);596 outb(host->sconf1, host->addr + TUL_SConfig);597 598 /* Enable HW reselect */599 outb(TSC_HW_RESELECT, host->addr + TUL_SCtrl1);600 601 outb(0, host->addr + TUL_SPeriod);602 603 /* selection time out = 250 ms */604 outb(153, host->addr + TUL_STimeOut);605 606 /* Enable SCSI terminator */607 outb((host->config & (HCC_ACT_TERM1 | HCC_ACT_TERM2)),608 host->addr + TUL_XCtrl);609 outb(((host->config & HCC_AUTO_TERM) >> 4) |610 (inb(host->addr + TUL_GCTRL1) & 0xFE),611 host->addr + TUL_GCTRL1);612 613 for (i = 0,614 flags = & (i91unvramp->NVM_SCSIInfo[0].NVM_Targ0Config),615 heads = bios_addr + 0x180;616 i < host->max_tar;617 i++, flags++) {618 host->targets[i].flags = *flags & ~(TCF_SYNC_DONE | TCF_WDTR_DONE);619 if (host->targets[i].flags & TCF_EN_255)620 host->targets[i].drv_flags = TCF_DRV_255_63;621 else622 host->targets[i].drv_flags = 0;623 host->targets[i].js_period = 0;624 host->targets[i].sconfig0 = host->sconf1;625 host->targets[i].heads = *heads++;626 if (host->targets[i].heads == 255)627 host->targets[i].drv_flags = TCF_DRV_255_63;628 else629 host->targets[i].drv_flags = 0;630 host->targets[i].sectors = *heads++;631 host->targets[i].flags &= ~TCF_BUSY;632 host->act_tags[i] = 0;633 host->max_tags[i] = 0xFF;634 } /* for */635 printk("i91u: PCI Base=0x%04X, IRQ=%d, BIOS=0x%04X0, SCSI ID=%d\n",636 host->addr, host->pci_dev->irq,637 host->bios_addr, host->scsi_id);638 /* Reset SCSI Bus */639 if (host->config & HCC_SCSI_RESET) {640 printk(KERN_INFO "i91u: Reset SCSI Bus ... \n");641 initio_reset_scsi(host, 10);642 }643 outb(0x17, host->addr + TUL_SCFG1);644 outb(0xE9, host->addr + TUL_SIntEnable);645}646 647/**648 * initio_alloc_scb - Allocate an SCB649 * @host: InitIO host we are allocating for650 *651 * Walk the SCB list for the controller and allocate a free SCB if652 * one exists.653 */654static struct scsi_ctrl_blk *initio_alloc_scb(struct initio_host *host)655{656 struct scsi_ctrl_blk *scb;657 unsigned long flags;658 659 spin_lock_irqsave(&host->avail_lock, flags);660 if ((scb = host->first_avail) != NULL) {661#if DEBUG_QUEUE662 printk("find scb at %p\n", scb);663#endif664 if ((host->first_avail = scb->next) == NULL)665 host->last_avail = NULL;666 scb->next = NULL;667 scb->status = SCB_RENT;668 }669 spin_unlock_irqrestore(&host->avail_lock, flags);670 return scb;671}672 673/**674 * initio_release_scb - Release an SCB675 * @host: InitIO host that owns the SCB676 * @cmnd: SCB command block being returned677 *678 * Return an allocated SCB to the host free list679 */680 681static void initio_release_scb(struct initio_host * host, struct scsi_ctrl_blk * cmnd)682{683 unsigned long flags;684 685#if DEBUG_QUEUE686 printk("Release SCB %p; ", cmnd);687#endif688 spin_lock_irqsave(&(host->avail_lock), flags);689 cmnd->srb = NULL;690 cmnd->status = 0;691 cmnd->next = NULL;692 if (host->last_avail != NULL) {693 host->last_avail->next = cmnd;694 host->last_avail = cmnd;695 } else {696 host->first_avail = cmnd;697 host->last_avail = cmnd;698 }699 spin_unlock_irqrestore(&(host->avail_lock), flags);700}701 702/***************************************************************************/703static void initio_append_pend_scb(struct initio_host * host, struct scsi_ctrl_blk * scbp)704{705 706#if DEBUG_QUEUE707 printk("Append pend SCB %p; ", scbp);708#endif709 scbp->status = SCB_PEND;710 scbp->next = NULL;711 if (host->last_pending != NULL) {712 host->last_pending->next = scbp;713 host->last_pending = scbp;714 } else {715 host->first_pending = scbp;716 host->last_pending = scbp;717 }718}719 720/***************************************************************************/721static void initio_push_pend_scb(struct initio_host * host, struct scsi_ctrl_blk * scbp)722{723 724#if DEBUG_QUEUE725 printk("Push pend SCB %p; ", scbp);726#endif727 scbp->status = SCB_PEND;728 if ((scbp->next = host->first_pending) != NULL) {729 host->first_pending = scbp;730 } else {731 host->first_pending = scbp;732 host->last_pending = scbp;733 }734}735 736static struct scsi_ctrl_blk *initio_find_first_pend_scb(struct initio_host * host)737{738 struct scsi_ctrl_blk *first;739 740 741 first = host->first_pending;742 while (first != NULL) {743 if (first->opcode != ExecSCSI)744 return first;745 if (first->tagmsg == 0) {746 if ((host->act_tags[first->target] == 0) &&747 !(host->targets[first->target].flags & TCF_BUSY))748 return first;749 } else {750 if ((host->act_tags[first->target] >=751 host->max_tags[first->target]) |752 (host->targets[first->target].flags & TCF_BUSY)) {753 first = first->next;754 continue;755 }756 return first;757 }758 first = first->next;759 }760 return first;761}762 763static void initio_unlink_pend_scb(struct initio_host * host, struct scsi_ctrl_blk * scb)764{765 struct scsi_ctrl_blk *tmp, *prev;766 767#if DEBUG_QUEUE768 printk("unlink pend SCB %p; ", scb);769#endif770 771 prev = tmp = host->first_pending;772 while (tmp != NULL) {773 if (scb == tmp) { /* Unlink this SCB */774 if (tmp == host->first_pending) {775 if ((host->first_pending = tmp->next) == NULL)776 host->last_pending = NULL;777 } else {778 prev->next = tmp->next;779 if (tmp == host->last_pending)780 host->last_pending = prev;781 }782 tmp->next = NULL;783 break;784 }785 prev = tmp;786 tmp = tmp->next;787 }788}789 790static void initio_append_busy_scb(struct initio_host * host, struct scsi_ctrl_blk * scbp)791{792 793#if DEBUG_QUEUE794 printk("append busy SCB %p; ", scbp);795#endif796 if (scbp->tagmsg)797 host->act_tags[scbp->target]++;798 else799 host->targets[scbp->target].flags |= TCF_BUSY;800 scbp->status = SCB_BUSY;801 scbp->next = NULL;802 if (host->last_busy != NULL) {803 host->last_busy->next = scbp;804 host->last_busy = scbp;805 } else {806 host->first_busy = scbp;807 host->last_busy = scbp;808 }809}810 811/***************************************************************************/812static struct scsi_ctrl_blk *initio_pop_busy_scb(struct initio_host * host)813{814 struct scsi_ctrl_blk *tmp;815 816 817 if ((tmp = host->first_busy) != NULL) {818 if ((host->first_busy = tmp->next) == NULL)819 host->last_busy = NULL;820 tmp->next = NULL;821 if (tmp->tagmsg)822 host->act_tags[tmp->target]--;823 else824 host->targets[tmp->target].flags &= ~TCF_BUSY;825 }826#if DEBUG_QUEUE827 printk("Pop busy SCB %p; ", tmp);828#endif829 return tmp;830}831 832/***************************************************************************/833static void initio_unlink_busy_scb(struct initio_host * host, struct scsi_ctrl_blk * scb)834{835 struct scsi_ctrl_blk *tmp, *prev;836 837#if DEBUG_QUEUE838 printk("unlink busy SCB %p; ", scb);839#endif840 841 prev = tmp = host->first_busy;842 while (tmp != NULL) {843 if (scb == tmp) { /* Unlink this SCB */844 if (tmp == host->first_busy) {845 if ((host->first_busy = tmp->next) == NULL)846 host->last_busy = NULL;847 } else {848 prev->next = tmp->next;849 if (tmp == host->last_busy)850 host->last_busy = prev;851 }852 tmp->next = NULL;853 if (tmp->tagmsg)854 host->act_tags[tmp->target]--;855 else856 host->targets[tmp->target].flags &= ~TCF_BUSY;857 break;858 }859 prev = tmp;860 tmp = tmp->next;861 }862 return;863}864 865struct scsi_ctrl_blk *initio_find_busy_scb(struct initio_host * host, u16 tarlun)866{867 struct scsi_ctrl_blk *tmp;868 u16 scbp_tarlun;869 870 871 tmp = host->first_busy;872 while (tmp != NULL) {873 scbp_tarlun = (tmp->lun << 8) | (tmp->target);874 if (scbp_tarlun == tarlun) { /* Unlink this SCB */875 break;876 }877 tmp = tmp->next;878 }879#if DEBUG_QUEUE880 printk("find busy SCB %p; ", tmp);881#endif882 return tmp;883}884 885static void initio_append_done_scb(struct initio_host * host, struct scsi_ctrl_blk * scbp)886{887#if DEBUG_QUEUE888 printk("append done SCB %p; ", scbp);889#endif890 891 scbp->status = SCB_DONE;892 scbp->next = NULL;893 if (host->last_done != NULL) {894 host->last_done->next = scbp;895 host->last_done = scbp;896 } else {897 host->first_done = scbp;898 host->last_done = scbp;899 }900}901 902struct scsi_ctrl_blk *initio_find_done_scb(struct initio_host * host)903{904 struct scsi_ctrl_blk *tmp;905 906 if ((tmp = host->first_done) != NULL) {907 if ((host->first_done = tmp->next) == NULL)908 host->last_done = NULL;909 tmp->next = NULL;910 }911#if DEBUG_QUEUE912 printk("find done SCB %p; ",tmp);913#endif914 return tmp;915}916 917static int initio_abort_srb(struct initio_host * host, struct scsi_cmnd *srbp)918{919 unsigned long flags;920 struct scsi_ctrl_blk *tmp, *prev;921 922 spin_lock_irqsave(&host->semaph_lock, flags);923 924 if ((host->semaph == 0) && (host->active == NULL)) {925 /* disable Jasmin SCSI Int */926 outb(0x1F, host->addr + TUL_Mask);927 spin_unlock_irqrestore(&host->semaph_lock, flags);928 /* FIXME: synchronize_irq needed ? */929 tulip_main(host);930 spin_lock_irqsave(&host->semaph_lock, flags);931 host->semaph = 1;932 outb(0x0F, host->addr + TUL_Mask);933 spin_unlock_irqrestore(&host->semaph_lock, flags);934 return SCSI_ABORT_SNOOZE;935 }936 prev = tmp = host->first_pending; /* Check Pend queue */937 while (tmp != NULL) {938 /* 07/27/98 */939 if (tmp->srb == srbp) {940 if (tmp == host->active) {941 spin_unlock_irqrestore(&host->semaph_lock, flags);942 return SCSI_ABORT_BUSY;943 } else if (tmp == host->first_pending) {944 if ((host->first_pending = tmp->next) == NULL)945 host->last_pending = NULL;946 } else {947 prev->next = tmp->next;948 if (tmp == host->last_pending)949 host->last_pending = prev;950 }951 tmp->hastat = HOST_ABORTED;952 tmp->flags |= SCF_DONE;953 if (tmp->flags & SCF_POST)954 (*tmp->post) ((u8 *) host, (u8 *) tmp);955 spin_unlock_irqrestore(&host->semaph_lock, flags);956 return SCSI_ABORT_SUCCESS;957 }958 prev = tmp;959 tmp = tmp->next;960 }961 962 prev = tmp = host->first_busy; /* Check Busy queue */963 while (tmp != NULL) {964 if (tmp->srb == srbp) {965 if (tmp == host->active) {966 spin_unlock_irqrestore(&host->semaph_lock, flags);967 return SCSI_ABORT_BUSY;968 } else if (tmp->tagmsg == 0) {969 spin_unlock_irqrestore(&host->semaph_lock, flags);970 return SCSI_ABORT_BUSY;971 } else {972 host->act_tags[tmp->target]--;973 if (tmp == host->first_busy) {974 if ((host->first_busy = tmp->next) == NULL)975 host->last_busy = NULL;976 } else {977 prev->next = tmp->next;978 if (tmp == host->last_busy)979 host->last_busy = prev;980 }981 tmp->next = NULL;982 983 984 tmp->hastat = HOST_ABORTED;985 tmp->flags |= SCF_DONE;986 if (tmp->flags & SCF_POST)987 (*tmp->post) ((u8 *) host, (u8 *) tmp);988 spin_unlock_irqrestore(&host->semaph_lock, flags);989 return SCSI_ABORT_SUCCESS;990 }991 }992 prev = tmp;993 tmp = tmp->next;994 }995 spin_unlock_irqrestore(&host->semaph_lock, flags);996 return SCSI_ABORT_NOT_RUNNING;997}998 999/***************************************************************************/1000static int initio_bad_seq(struct initio_host * host)1001{1002 struct scsi_ctrl_blk *scb;1003 1004 printk("initio_bad_seg c=%d\n", host->index);1005 1006 if ((scb = host->active) != NULL) {1007 initio_unlink_busy_scb(host, scb);1008 scb->hastat = HOST_BAD_PHAS;1009 scb->tastat = 0;1010 initio_append_done_scb(host, scb);1011 }1012 initio_stop_bm(host);1013 initio_reset_scsi(host, 8); /* 7/29/98 */1014 return initio_post_scsi_rst(host);1015}1016 1017 1018/************************************************************************/1019static void initio_exec_scb(struct initio_host * host, struct scsi_ctrl_blk * scb)1020{1021 unsigned long flags;1022 1023 scb->mode = 0;1024 1025 scb->sgidx = 0;1026 scb->sgmax = scb->sglen;1027 1028 spin_lock_irqsave(&host->semaph_lock, flags);1029 1030 initio_append_pend_scb(host, scb); /* Append this SCB to Pending queue */1031 1032/* VVVVV 07/21/98 */1033 if (host->semaph == 1) {1034 /* Disable Jasmin SCSI Int */1035 outb(0x1F, host->addr + TUL_Mask);1036 host->semaph = 0;1037 spin_unlock_irqrestore(&host->semaph_lock, flags);1038 1039 tulip_main(host);1040 1041 spin_lock_irqsave(&host->semaph_lock, flags);1042 host->semaph = 1;1043 outb(0x0F, host->addr + TUL_Mask);1044 }1045 spin_unlock_irqrestore(&host->semaph_lock, flags);1046 return;1047}1048 1049/***************************************************************************/1050static int initio_isr(struct initio_host * host)1051{1052 if (inb(host->addr + TUL_Int) & TSS_INT_PENDING) {1053 if (host->semaph == 1) {1054 outb(0x1F, host->addr + TUL_Mask);1055 /* Disable Tulip SCSI Int */1056 host->semaph = 0;1057 1058 tulip_main(host);1059 1060 host->semaph = 1;1061 outb(0x0F, host->addr + TUL_Mask);1062 return 1;1063 }1064 }1065 return 0;1066}1067 1068static int tulip_main(struct initio_host * host)1069{1070 struct scsi_ctrl_blk *scb;1071 1072 for (;;) {1073 tulip_scsi(host); /* Call tulip_scsi */1074 1075 /* Walk the list of completed SCBs */1076 while ((scb = initio_find_done_scb(host)) != NULL) { /* find done entry */1077 if (scb->tastat == INI_QUEUE_FULL) {1078 host->max_tags[scb->target] =1079 host->act_tags[scb->target] - 1;1080 scb->tastat = 0;1081 initio_append_pend_scb(host, scb);1082 continue;1083 }1084 if (!(scb->mode & SCM_RSENS)) { /* not in auto req. sense mode */1085 if (scb->tastat == 2) {1086 1087 /* clr sync. nego flag */1088 1089 if (scb->flags & SCF_SENSE) {1090 u8 len;1091 len = scb->senselen;1092 if (len == 0)1093 len = 1;1094 scb->buflen = scb->senselen;1095 scb->bufptr = scb->senseptr;1096 scb->flags &= ~(SCF_SG | SCF_DIR); /* for xfer_data_in */1097 /* so, we won't report wrong direction in xfer_data_in,1098 and won't report HOST_DO_DU in state_6 */1099 scb->mode = SCM_RSENS;1100 scb->ident &= 0xBF; /* Disable Disconnect */1101 scb->tagmsg = 0;1102 scb->tastat = 0;1103 scb->cdblen = 6;1104 scb->cdb[0] = SCSICMD_RequestSense;1105 scb->cdb[1] = 0;1106 scb->cdb[2] = 0;1107 scb->cdb[3] = 0;1108 scb->cdb[4] = len;1109 scb->cdb[5] = 0;1110 initio_push_pend_scb(host, scb);1111 break;1112 }1113 }1114 } else { /* in request sense mode */1115 1116 if (scb->tastat == 2) { /* check contition status again after sending1117 requset sense cmd 0x3 */1118 scb->hastat = HOST_BAD_PHAS;1119 }1120 scb->tastat = 2;1121 }1122 scb->flags |= SCF_DONE;1123 if (scb->flags & SCF_POST) {1124 /* FIXME: only one post method and lose casts */1125 (*scb->post) ((u8 *) host, (u8 *) scb);1126 }1127 } /* while */1128 /* find_active: */1129 if (inb(host->addr + TUL_SStatus0) & TSS_INT_PENDING)1130 continue;1131 if (host->active) /* return to OS and wait for xfer_done_ISR/Selected_ISR */1132 return 1; /* return to OS, enable interrupt */1133 /* Check pending SCB */1134 if (initio_find_first_pend_scb(host) == NULL)1135 return 1; /* return to OS, enable interrupt */1136 } /* End of for loop */1137 /* statement won't reach here */1138}1139 1140static void tulip_scsi(struct initio_host * host)1141{1142 struct scsi_ctrl_blk *scb;1143 struct target_control *active_tc;1144 1145 /* make sure to service interrupt asap */1146 if ((host->jsstatus0 = inb(host->addr + TUL_SStatus0)) & TSS_INT_PENDING) {1147 host->phase = host->jsstatus0 & TSS_PH_MASK;1148 host->jsstatus1 = inb(host->addr + TUL_SStatus1);1149 host->jsint = inb(host->addr + TUL_SInt);1150 if (host->jsint & TSS_SCSIRST_INT) { /* SCSI bus reset detected */1151 int_initio_scsi_rst(host);1152 return;1153 }1154 if (host->jsint & TSS_RESEL_INT) { /* if selected/reselected interrupt */1155 if (int_initio_resel(host) == 0)1156 initio_next_state(host);1157 return;1158 }1159 if (host->jsint & TSS_SEL_TIMEOUT) {1160 int_initio_busfree(host);1161 return;1162 }1163 if (host->jsint & TSS_DISC_INT) { /* BUS disconnection */1164 int_initio_busfree(host); /* unexpected bus free or sel timeout */1165 return;1166 }1167 if (host->jsint & (TSS_FUNC_COMP | TSS_BUS_SERV)) { /* func complete or Bus service */1168 if (host->active)1169 initio_next_state(host);1170 return;1171 }1172 }1173 if (host->active != NULL)1174 return;1175 1176 if ((scb = initio_find_first_pend_scb(host)) == NULL)1177 return;1178 1179 /* program HBA's SCSI ID & target SCSI ID */1180 outb((host->scsi_id << 4) | (scb->target & 0x0F),1181 host->addr + TUL_SScsiId);1182 if (scb->opcode == ExecSCSI) {1183 active_tc = &host->targets[scb->target];1184 1185 if (scb->tagmsg)1186 active_tc->drv_flags |= TCF_DRV_EN_TAG;1187 else1188 active_tc->drv_flags &= ~TCF_DRV_EN_TAG;1189 1190 outb(active_tc->js_period, host->addr + TUL_SPeriod);1191 if ((active_tc->flags & (TCF_WDTR_DONE | TCF_NO_WDTR)) == 0) { /* do wdtr negotiation */1192 initio_select_atn_stop(host, scb);1193 } else {1194 if ((active_tc->flags & (TCF_SYNC_DONE | TCF_NO_SYNC_NEGO)) == 0) { /* do sync negotiation */1195 initio_select_atn_stop(host, scb);1196 } else {1197 if (scb->tagmsg)1198 initio_select_atn3(host, scb);1199 else1200 initio_select_atn(host, scb);1201 }1202 }1203 if (scb->flags & SCF_POLL) {1204 while (wait_tulip(host) != -1) {1205 if (initio_next_state(host) == -1)1206 break;1207 }1208 }1209 } else if (scb->opcode == BusDevRst) {1210 initio_select_atn_stop(host, scb);1211 scb->next_state = 8;1212 if (scb->flags & SCF_POLL) {1213 while (wait_tulip(host) != -1) {1214 if (initio_next_state(host) == -1)1215 break;1216 }1217 }1218 } else if (scb->opcode == AbortCmd) {1219 if (initio_abort_srb(host, scb->srb) != 0) {1220 initio_unlink_pend_scb(host, scb);1221 initio_release_scb(host, scb);1222 } else {1223 scb->opcode = BusDevRst;1224 initio_select_atn_stop(host, scb);1225 scb->next_state = 8;1226 }1227 } else {1228 initio_unlink_pend_scb(host, scb);1229 scb->hastat = 0x16; /* bad command */1230 initio_append_done_scb(host, scb);1231 }1232 return;1233}1234 1235/**1236 * initio_next_state - Next SCSI state1237 * @host: InitIO host we are processing1238 *1239 * Progress the active command block along the state machine1240 * until we hit a state which we must wait for activity to occur.1241 *1242 * Returns zero or a negative code.1243 */1244 1245static int initio_next_state(struct initio_host * host)1246{1247 int next;1248 1249 next = host->active->next_state;1250 for (;;) {1251 switch (next) {1252 case 1:1253 next = initio_state_1(host);1254 break;1255 case 2:1256 next = initio_state_2(host);1257 break;1258 case 3:1259 next = initio_state_3(host);1260 break;1261 case 4:1262 next = initio_state_4(host);1263 break;1264 case 5:1265 next = initio_state_5(host);1266 break;1267 case 6:1268 next = initio_state_6(host);1269 break;1270 case 7:1271 next = initio_state_7(host);1272 break;1273 case 8:1274 return initio_bus_device_reset(host);1275 default:1276 return initio_bad_seq(host);1277 }1278 if (next <= 0)1279 return next;1280 }1281}1282 1283 1284/**1285 * initio_state_1 - SCSI state machine1286 * @host: InitIO host we are controlling1287 *1288 * Perform SCSI state processing for Select/Attention/Stop1289 */1290 1291static int initio_state_1(struct initio_host * host)1292{1293 struct scsi_ctrl_blk *scb = host->active;1294 struct target_control *active_tc = host->active_tc;1295#if DEBUG_STATE1296 printk("-s1-");1297#endif1298 1299 /* Move the SCB from pending to busy */1300 initio_unlink_pend_scb(host, scb);1301 initio_append_busy_scb(host, scb);1302 1303 outb(active_tc->sconfig0, host->addr + TUL_SConfig );1304 /* ATN on */1305 if (host->phase == MSG_OUT) {1306 outb(TSC_EN_BUS_IN | TSC_HW_RESELECT, host->addr + TUL_SCtrl1);1307 outb(scb->ident, host->addr + TUL_SFifo);1308 1309 if (scb->tagmsg) {1310 outb(scb->tagmsg, host->addr + TUL_SFifo);1311 outb(scb->tagid, host->addr + TUL_SFifo);1312 }1313 if ((active_tc->flags & (TCF_WDTR_DONE | TCF_NO_WDTR)) == 0) {1314 active_tc->flags |= TCF_WDTR_DONE;1315 outb(EXTENDED_MESSAGE, host->addr + TUL_SFifo);1316 outb(2, host->addr + TUL_SFifo); /* Extended msg length */1317 outb(EXTENDED_SDTR, host->addr + TUL_SFifo); /* Sync request */1318 outb(1, host->addr + TUL_SFifo); /* Start from 16 bits */1319 } else if ((active_tc->flags & (TCF_SYNC_DONE | TCF_NO_SYNC_NEGO)) == 0) {1320 active_tc->flags |= TCF_SYNC_DONE;1321 outb(EXTENDED_MESSAGE, host->addr + TUL_SFifo);1322 outb(3, host->addr + TUL_SFifo); /* extended msg length */1323 outb(EXTENDED_SDTR, host->addr + TUL_SFifo); /* sync request */1324 outb(initio_rate_tbl[active_tc->flags & TCF_SCSI_RATE], host->addr + TUL_SFifo);1325 outb(MAX_OFFSET, host->addr + TUL_SFifo); /* REQ/ACK offset */1326 }1327 outb(TSC_XF_FIFO_OUT, host->addr + TUL_SCmd);1328 if (wait_tulip(host) == -1)1329 return -1;1330 }1331 outb(TSC_FLUSH_FIFO, host->addr + TUL_SCtrl0);1332 outb((inb(host->addr + TUL_SSignal) & (TSC_SET_ACK | 7)), host->addr + TUL_SSignal);1333 /* Into before CDB xfer */1334 return 3;1335}1336 1337 1338/**1339 * initio_state_2 - SCSI state machine1340 * @host: InitIO host we are controlling1341 *1342 * state after selection with attention1343 * state after selection with attention31344 */1345 1346static int initio_state_2(struct initio_host * host)1347{1348 struct scsi_ctrl_blk *scb = host->active;1349 struct target_control *active_tc = host->active_tc;1350#if DEBUG_STATE1351 printk("-s2-");1352#endif1353 1354 initio_unlink_pend_scb(host, scb);1355 initio_append_busy_scb(host, scb);1356 1357 outb(active_tc->sconfig0, host->addr + TUL_SConfig);1358 1359 if (host->jsstatus1 & TSS_CMD_PH_CMP)1360 return 4;1361 1362 outb(TSC_FLUSH_FIFO, host->addr + TUL_SCtrl0);1363 outb((inb(host->addr + TUL_SSignal) & (TSC_SET_ACK | 7)), host->addr + TUL_SSignal);1364 /* Into before CDB xfer */1365 return 3;1366}1367 1368/**1369 * initio_state_3 - SCSI state machine1370 * @host: InitIO host we are controlling1371 *1372 * state before CDB xfer is done1373 */1374 1375static int initio_state_3(struct initio_host * host)1376{1377 struct scsi_ctrl_blk *scb = host->active;1378 struct target_control *active_tc = host->active_tc;1379 int i;1380 1381#if DEBUG_STATE1382 printk("-s3-");1383#endif1384 for (;;) {1385 switch (host->phase) {1386 case CMD_OUT: /* Command out phase */1387 for (i = 0; i < (int) scb->cdblen; i++)1388 outb(scb->cdb[i], host->addr + TUL_SFifo);1389 outb(TSC_XF_FIFO_OUT, host->addr + TUL_SCmd);1390 if (wait_tulip(host) == -1)1391 return -1;1392 if (host->phase == CMD_OUT)1393 return initio_bad_seq(host);1394 return 4;1395 1396 case MSG_IN: /* Message in phase */1397 scb->next_state = 3;1398 if (initio_msgin(host) == -1)1399 return -1;1400 break;1401 1402 case STATUS_IN: /* Status phase */1403 if (initio_status_msg(host) == -1)1404 return -1;1405 break;1406 1407 case MSG_OUT: /* Message out phase */1408 if (active_tc->flags & (TCF_SYNC_DONE | TCF_NO_SYNC_NEGO)) {1409 outb(NOP, host->addr + TUL_SFifo); /* msg nop */1410 outb(TSC_XF_FIFO_OUT, host->addr + TUL_SCmd);1411 if (wait_tulip(host) == -1)1412 return -1;1413 } else {1414 active_tc->flags |= TCF_SYNC_DONE;1415 1416 outb(EXTENDED_MESSAGE, host->addr + TUL_SFifo);1417 outb(3, host->addr + TUL_SFifo); /* ext. msg len */1418 outb(EXTENDED_SDTR, host->addr + TUL_SFifo); /* sync request */1419 outb(initio_rate_tbl[active_tc->flags & TCF_SCSI_RATE], host->addr + TUL_SFifo);1420 outb(MAX_OFFSET, host->addr + TUL_SFifo); /* REQ/ACK offset */1421 outb(TSC_XF_FIFO_OUT, host->addr + TUL_SCmd);1422 if (wait_tulip(host) == -1)1423 return -1;1424 outb(TSC_FLUSH_FIFO, host->addr + TUL_SCtrl0);1425 outb(inb(host->addr + TUL_SSignal) & (TSC_SET_ACK | 7), host->addr + TUL_SSignal);1426 1427 }1428 break;1429 default:1430 return initio_bad_seq(host);1431 }1432 }1433}1434 1435/**1436 * initio_state_4 - SCSI state machine1437 * @host: InitIO host we are controlling1438 *1439 * SCSI state machine. State 41440 */1441 1442static int initio_state_4(struct initio_host * host)1443{1444 struct scsi_ctrl_blk *scb = host->active;1445 1446#if DEBUG_STATE1447 printk("-s4-");1448#endif1449 if ((scb->flags & SCF_DIR) == SCF_NO_XF) {1450 return 6; /* Go to state 6 (After data) */1451 }1452 for (;;) {1453 if (scb->buflen == 0)1454 return 6;1455 1456 switch (host->phase) {1457 1458 case STATUS_IN: /* Status phase */1459 if ((scb->flags & SCF_DIR) != 0) /* if direction bit set then report data underrun */1460 scb->hastat = HOST_DO_DU;1461 if ((initio_status_msg(host)) == -1)1462 return -1;1463 break;1464 1465 case MSG_IN: /* Message in phase */1466 scb->next_state = 0x4;1467 if (initio_msgin(host) == -1)1468 return -1;1469 break;1470 1471 case MSG_OUT: /* Message out phase */1472 if (host->jsstatus0 & TSS_PAR_ERROR) {1473 scb->buflen = 0;1474 scb->hastat = HOST_DO_DU;1475 if (initio_msgout_ide(host) == -1)1476 return -1;1477 return 6;1478 } else {1479 outb(NOP, host->addr + TUL_SFifo); /* msg nop */1480 outb(TSC_XF_FIFO_OUT, host->addr + TUL_SCmd);1481 if (wait_tulip(host) == -1)1482 return -1;1483 }1484 break;1485 1486 case DATA_IN: /* Data in phase */1487 return initio_xfer_data_in(host);1488 1489 case DATA_OUT: /* Data out phase */1490 return initio_xfer_data_out(host);1491 1492 default:1493 return initio_bad_seq(host);1494 }1495 }1496}1497 1498 1499/**1500 * initio_state_5 - SCSI state machine1501 * @host: InitIO host we are controlling1502 *1503 * State after dma xfer done or phase change before xfer done1504 */1505 1506static int initio_state_5(struct initio_host * host)1507{1508 struct scsi_ctrl_blk *scb = host->active;1509 long cnt, xcnt; /* cannot use unsigned !! code: if (xcnt < 0) */1510 1511#if DEBUG_STATE1512 printk("-s5-");1513#endif1514 /*------ get remaining count -------*/1515 cnt = inl(host->addr + TUL_SCnt0) & 0x0FFFFFF;1516 1517 if (inb(host->addr + TUL_XCmd) & 0x20) {1518 /* ----------------------- DATA_IN ----------------------------- */1519 /* check scsi parity error */1520 if (host->jsstatus0 & TSS_PAR_ERROR)1521 scb->hastat = HOST_DO_DU;1522 if (inb(host->addr + TUL_XStatus) & XPEND) { /* DMA xfer pending, Send STOP */1523 /* tell Hardware scsi xfer has been terminated */1524 outb(inb(host->addr + TUL_XCtrl) | 0x80, host->addr + TUL_XCtrl);1525 /* wait until DMA xfer not pending */1526 while (inb(host->addr + TUL_XStatus) & XPEND)1527 cpu_relax();1528 }1529 } else {1530 /*-------- DATA OUT -----------*/1531 if ((inb(host->addr + TUL_SStatus1) & TSS_XFER_CMP) == 0) {1532 if (host->active_tc->js_period & TSC_WIDE_SCSI)1533 cnt += (inb(host->addr + TUL_SFifoCnt) & 0x1F) << 1;1534 else1535 cnt += (inb(host->addr + TUL_SFifoCnt) & 0x1F);1536 }1537 if (inb(host->addr + TUL_XStatus) & XPEND) { /* if DMA xfer is pending, abort DMA xfer */1538 outb(TAX_X_ABT, host->addr + TUL_XCmd);1539 /* wait Abort DMA xfer done */1540 while ((inb(host->addr + TUL_Int) & XABT) == 0)1541 cpu_relax();1542 }1543 if ((cnt == 1) && (host->phase == DATA_OUT)) {1544 outb(TSC_XF_FIFO_OUT, host->addr + TUL_SCmd);1545 if (wait_tulip(host) == -1)1546 return -1;1547 cnt = 0;1548 } else {1549 if ((inb(host->addr + TUL_SStatus1) & TSS_XFER_CMP) == 0)1550 outb(TSC_FLUSH_FIFO, host->addr + TUL_SCtrl0);1551 }1552 }1553 if (cnt == 0) {1554 scb->buflen = 0;1555 return 6; /* After Data */1556 }1557 /* Update active data pointer */1558 xcnt = (long) scb->buflen - cnt; /* xcnt== bytes already xferred */1559 scb->buflen = (u32) cnt; /* cnt == bytes left to be xferred */1560 if (scb->flags & SCF_SG) {1561 struct sg_entry *sgp;1562 unsigned long i;1563 1564 sgp = &scb->sglist[scb->sgidx];1565 for (i = scb->sgidx; i < scb->sgmax; sgp++, i++) {1566 xcnt -= (long) sgp->len;1567 if (xcnt < 0) { /* this sgp xfer half done */1568 xcnt += (long) sgp->len; /* xcnt == bytes xferred in this sgp */1569 sgp->data += (u32) xcnt; /* new ptr to be xfer */1570 sgp->len -= (u32) xcnt; /* new len to be xfer */1571 scb->bufptr += ((u32) (i - scb->sgidx) << 3);1572 /* new SG table ptr */1573 scb->sglen = (u8) (scb->sgmax - i);1574 /* new SG table len */1575 scb->sgidx = (u16) i;1576 /* for next disc and come in this loop */1577 return 4; /* Go to state 4 */1578 }1579 /* else (xcnt >= 0 , i.e. this sgp already xferred */1580 } /* for */1581 return 6; /* Go to state 6 */1582 } else {1583 scb->bufptr += (u32) xcnt;1584 }1585 return 4; /* Go to state 4 */1586}1587 1588/**1589 * initio_state_6 - SCSI state machine1590 * @host: InitIO host we are controlling1591 *1592 * State after Data phase1593 */1594 1595static int initio_state_6(struct initio_host * host)1596{1597 struct scsi_ctrl_blk *scb = host->active;1598 1599#if DEBUG_STATE1600 printk("-s6-");1601#endif1602 for (;;) {1603 switch (host->phase) {1604 case STATUS_IN: /* Status phase */1605 if ((initio_status_msg(host)) == -1)1606 return -1;1607 break;1608 1609 case MSG_IN: /* Message in phase */1610 scb->next_state = 6;1611 if ((initio_msgin(host)) == -1)1612 return -1;1613 break;1614 1615 case MSG_OUT: /* Message out phase */1616 outb(NOP, host->addr + TUL_SFifo); /* msg nop */1617 outb(TSC_XF_FIFO_OUT, host->addr + TUL_SCmd);1618 if (wait_tulip(host) == -1)1619 return -1;1620 break;1621 1622 case DATA_IN: /* Data in phase */1623 return initio_xpad_in(host);1624 1625 case DATA_OUT: /* Data out phase */1626 return initio_xpad_out(host);1627 1628 default:1629 return initio_bad_seq(host);1630 }1631 }1632}1633 1634/**1635 * initio_state_7 - SCSI state machine1636 * @host: InitIO host we are controlling1637 *1638 */1639 1640static int initio_state_7(struct initio_host * host)1641{1642 int cnt, i;1643 1644#if DEBUG_STATE1645 printk("-s7-");1646#endif1647 /* flush SCSI FIFO */1648 cnt = inb(host->addr + TUL_SFifoCnt) & 0x1F;1649 if (cnt) {1650 for (i = 0; i < cnt; i++)1651 inb(host->addr + TUL_SFifo);1652 }1653 switch (host->phase) {1654 case DATA_IN: /* Data in phase */1655 case DATA_OUT: /* Data out phase */1656 return initio_bad_seq(host);1657 default:1658 return 6; /* Go to state 6 */1659 }1660}1661 1662/**1663 * initio_xfer_data_in - Commence data input1664 * @host: InitIO host in use1665 *1666 * Commence a block of data transfer. The transfer itself will1667 * be managed by the controller and we will get a completion (or1668 * failure) interrupt.1669 */1670static int initio_xfer_data_in(struct initio_host * host)1671{1672 struct scsi_ctrl_blk *scb = host->active;1673 1674 if ((scb->flags & SCF_DIR) == SCF_DOUT)1675 return 6; /* wrong direction */1676 1677 outl(scb->buflen, host->addr + TUL_SCnt0);1678 outb(TSC_XF_DMA_IN, host->addr + TUL_SCmd); /* 7/25/95 */1679 1680 if (scb->flags & SCF_SG) { /* S/G xfer */1681 outl(((u32) scb->sglen) << 3, host->addr + TUL_XCntH);1682 outl(scb->bufptr, host->addr + TUL_XAddH);1683 outb(TAX_SG_IN, host->addr + TUL_XCmd);1684 } else {1685 outl(scb->buflen, host->addr + TUL_XCntH);1686 outl(scb->bufptr, host->addr + TUL_XAddH);1687 outb(TAX_X_IN, host->addr + TUL_XCmd);1688 }1689 scb->next_state = 0x5;1690 return 0; /* return to OS, wait xfer done , let jas_isr come in */1691}1692 1693/**1694 * initio_xfer_data_out - Commence data output1695 * @host: InitIO host in use1696 *1697 * Commence a block of data transfer. The transfer itself will1698 * be managed by the controller and we will get a completion (or1699 * failure) interrupt.1700 */1701 1702static int initio_xfer_data_out(struct initio_host * host)1703{1704 struct scsi_ctrl_blk *scb = host->active;1705 1706 if ((scb->flags & SCF_DIR) == SCF_DIN)1707 return 6; /* wrong direction */1708 1709 outl(scb->buflen, host->addr + TUL_SCnt0);1710 outb(TSC_XF_DMA_OUT, host->addr + TUL_SCmd);1711 1712 if (scb->flags & SCF_SG) { /* S/G xfer */1713 outl(((u32) scb->sglen) << 3, host->addr + TUL_XCntH);1714 outl(scb->bufptr, host->addr + TUL_XAddH);1715 outb(TAX_SG_OUT, host->addr + TUL_XCmd);1716 } else {1717 outl(scb->buflen, host->addr + TUL_XCntH);1718 outl(scb->bufptr, host->addr + TUL_XAddH);1719 outb(TAX_X_OUT, host->addr + TUL_XCmd);1720 }1721 1722 scb->next_state = 0x5;1723 return 0; /* return to OS, wait xfer done , let jas_isr come in */1724}1725 1726int initio_xpad_in(struct initio_host * host)1727{1728 struct scsi_ctrl_blk *scb = host->active;1729 struct target_control *active_tc = host->active_tc;1730 1731 if ((scb->flags & SCF_DIR) != SCF_NO_DCHK)1732 scb->hastat = HOST_DO_DU; /* over run */1733 for (;;) {1734 if (active_tc->js_period & TSC_WIDE_SCSI)1735 outl(2, host->addr + TUL_SCnt0);1736 else1737 outl(1, host->addr + TUL_SCnt0);1738 1739 outb(TSC_XF_FIFO_IN, host->addr + TUL_SCmd);1740 if (wait_tulip(host) == -1)1741 return -1;1742 if (host->phase != DATA_IN) {1743 outb(TSC_FLUSH_FIFO, host->addr + TUL_SCtrl0);1744 return 6;1745 }1746 inb(host->addr + TUL_SFifo);1747 }1748}1749 1750int initio_xpad_out(struct initio_host * host)1751{1752 struct scsi_ctrl_blk *scb = host->active;1753 struct target_control *active_tc = host->active_tc;1754 1755 if ((scb->flags & SCF_DIR) != SCF_NO_DCHK)1756 scb->hastat = HOST_DO_DU; /* over run */1757 for (;;) {1758 if (active_tc->js_period & TSC_WIDE_SCSI)1759 outl(2, host->addr + TUL_SCnt0);1760 else1761 outl(1, host->addr + TUL_SCnt0);1762 1763 outb(0, host->addr + TUL_SFifo);1764 outb(TSC_XF_FIFO_OUT, host->addr + TUL_SCmd);1765 if ((wait_tulip(host)) == -1)1766 return -1;1767 if (host->phase != DATA_OUT) { /* Disable wide CPU to allow read 16 bits */1768 outb(TSC_HW_RESELECT, host->addr + TUL_SCtrl1);1769 outb(TSC_FLUSH_FIFO, host->addr + TUL_SCtrl0);1770 return 6;1771 }1772 }1773}1774 1775int initio_status_msg(struct initio_host * host)1776{ /* status & MSG_IN */1777 struct scsi_ctrl_blk *scb = host->active;1778 u8 msg;1779 1780 outb(TSC_CMD_COMP, host->addr + TUL_SCmd);1781 if (wait_tulip(host) == -1)1782 return -1;1783 1784 /* get status */1785 scb->tastat = inb(host->addr + TUL_SFifo);1786 1787 if (host->phase == MSG_OUT) {1788 if (host->jsstatus0 & TSS_PAR_ERROR)1789 outb(MSG_PARITY_ERROR, host->addr + TUL_SFifo);1790 else1791 outb(NOP, host->addr + TUL_SFifo);1792 outb(TSC_XF_FIFO_OUT, host->addr + TUL_SCmd);1793 return wait_tulip(host);1794 }1795 if (host->phase == MSG_IN) {1796 msg = inb(host->addr + TUL_SFifo);1797 if (host->jsstatus0 & TSS_PAR_ERROR) { /* Parity error */1798 if ((initio_msgin_accept(host)) == -1)1799 return -1;1800 if (host->phase != MSG_OUT)1801 return initio_bad_seq(host);1802 outb(MSG_PARITY_ERROR, host->addr + TUL_SFifo);1803 outb(TSC_XF_FIFO_OUT, host->addr + TUL_SCmd);1804 return wait_tulip(host);1805 }1806 if (msg == 0) { /* Command complete */1807 1808 if ((scb->tastat & 0x18) == 0x10) /* No link support */1809 return initio_bad_seq(host);1810 outb(TSC_FLUSH_FIFO, host->addr + TUL_SCtrl0);1811 outb(TSC_MSG_ACCEPT, host->addr + TUL_SCmd);1812 return initio_wait_done_disc(host);1813 1814 }1815 if (msg == LINKED_CMD_COMPLETE ||1816 msg == LINKED_FLG_CMD_COMPLETE) {1817 if ((scb->tastat & 0x18) == 0x10)1818 return initio_msgin_accept(host);1819 }1820 }1821 return initio_bad_seq(host);1822}1823 1824 1825/* scsi bus free */1826int int_initio_busfree(struct initio_host * host)1827{1828 struct scsi_ctrl_blk *scb = host->active;1829 1830 if (scb != NULL) {1831 if (scb->status & SCB_SELECT) { /* selection timeout */1832 initio_unlink_pend_scb(host, scb);1833 scb->hastat = HOST_SEL_TOUT;1834 initio_append_done_scb(host, scb);1835 } else { /* Unexpected bus free */1836 initio_unlink_busy_scb(host, scb);1837 scb->hastat = HOST_BUS_FREE;1838 initio_append_done_scb(host, scb);1839 }1840 host->active = NULL;1841 host->active_tc = NULL;1842 }1843 outb(TSC_FLUSH_FIFO, host->addr + TUL_SCtrl0); /* Flush SCSI FIFO */1844 outb(TSC_INITDEFAULT, host->addr + TUL_SConfig);1845 outb(TSC_HW_RESELECT, host->addr + TUL_SCtrl1); /* Enable HW reselect */1846 return -1;1847}1848 1849 1850/**1851 * int_initio_scsi_rst - SCSI reset occurred1852 * @host: Host seeing the reset1853 *1854 * A SCSI bus reset has occurred. Clean up any pending transfer1855 * the hardware is doing by DMA and then abort all active and1856 * disconnected commands. The mid layer should sort the rest out1857 * for us1858 */1859 1860static int int_initio_scsi_rst(struct initio_host * host)1861{1862 struct scsi_ctrl_blk *scb;1863 int i;1864 1865 /* if DMA xfer is pending, abort DMA xfer */1866 if (inb(host->addr + TUL_XStatus) & 0x01) {1867 outb(TAX_X_ABT | TAX_X_CLR_FIFO, host->addr + TUL_XCmd);1868 /* wait Abort DMA xfer done */1869 while ((inb(host->addr + TUL_Int) & 0x04) == 0)1870 cpu_relax();1871 outb(TSC_FLUSH_FIFO, host->addr + TUL_SCtrl0);1872 }1873 /* Abort all active & disconnected scb */1874 while ((scb = initio_pop_busy_scb(host)) != NULL) {1875 scb->hastat = HOST_BAD_PHAS;1876 initio_append_done_scb(host, scb);1877 }1878 host->active = NULL;1879 host->active_tc = NULL;1880 1881 /* clr sync nego. done flag */1882 for (i = 0; i < host->max_tar; i++)1883 host->targets[i].flags &= ~(TCF_SYNC_DONE | TCF_WDTR_DONE);1884 return -1;1885}1886 1887/**1888 * int_initio_resel - Reselection occurred1889 * @host: InitIO host adapter1890 *1891 * A SCSI reselection event has been signalled and the interrupt1892 * is now being processed. Work out which command block needs attention1893 * and continue processing that command.1894 */1895 1896int int_initio_resel(struct initio_host * host)1897{1898 struct scsi_ctrl_blk *scb;1899 struct target_control *active_tc;1900 u8 tag, msg = 0;1901 u8 tar, lun;1902 1903 if ((scb = host->active) != NULL) {1904 /* FIXME: Why check and not just clear ? */1905 if (scb->status & SCB_SELECT) /* if waiting for selection complete */1906 scb->status &= ~SCB_SELECT;1907 host->active = NULL;1908 }1909 /* --------- get target id---------------------- */1910 tar = inb(host->addr + TUL_SBusId);1911 /* ------ get LUN from Identify message----------- */1912 lun = inb(host->addr + TUL_SIdent) & 0x0F;1913 /* 07/22/98 from 0x1F -> 0x0F */1914 active_tc = &host->targets[tar];1915 host->active_tc = active_tc;1916 outb(active_tc->sconfig0, host->addr + TUL_SConfig);1917 outb(active_tc->js_period, host->addr + TUL_SPeriod);1918 1919 /* ------------- tag queueing ? ------------------- */1920 if (active_tc->drv_flags & TCF_DRV_EN_TAG) {1921 if ((initio_msgin_accept(host)) == -1)1922 return -1;1923 if (host->phase != MSG_IN)1924 goto no_tag;1925 outl(1, host->addr + TUL_SCnt0);1926 outb(TSC_XF_FIFO_IN, host->addr + TUL_SCmd);1927 if (wait_tulip(host) == -1)1928 return -1;1929 msg = inb(host->addr + TUL_SFifo); /* Read Tag Message */1930 1931 if (msg < SIMPLE_QUEUE_TAG || msg > ORDERED_QUEUE_TAG)1932 /* Is simple Tag */1933 goto no_tag;1934 1935 if (initio_msgin_accept(host) == -1)1936 return -1;1937 1938 if (host->phase != MSG_IN)1939 goto no_tag;1940 1941 outl(1, host->addr + TUL_SCnt0);1942 outb(TSC_XF_FIFO_IN, host->addr + TUL_SCmd);1943 if (wait_tulip(host) == -1)1944 return -1;1945 tag = inb(host->addr + TUL_SFifo); /* Read Tag ID */1946 scb = host->scb + tag;1947 if (scb->target != tar || scb->lun != lun) {1948 return initio_msgout_abort_tag(host);1949 }1950 if (scb->status != SCB_BUSY) { /* 03/24/95 */1951 return initio_msgout_abort_tag(host);1952 }1953 host->active = scb;1954 if ((initio_msgin_accept(host)) == -1)1955 return -1;1956 } else { /* No tag */1957 no_tag:1958 if ((scb = initio_find_busy_scb(host, tar | (lun << 8))) == NULL) {1959 return initio_msgout_abort_targ(host);1960 }1961 host->active = scb;1962 if (!(active_tc->drv_flags & TCF_DRV_EN_TAG)) {1963 if ((initio_msgin_accept(host)) == -1)1964 return -1;1965 }1966 }1967 return 0;1968}1969 1970/**1971 * int_initio_bad_seq - out of phase1972 * @host: InitIO host flagging event1973 *1974 * We have ended up out of phase somehow. Reset the host controller1975 * and throw all our toys out of the pram. Let the midlayer clean up1976 */1977 1978static int int_initio_bad_seq(struct initio_host * host)1979{ /* target wrong phase */1980 struct scsi_ctrl_blk *scb;1981 int i;1982 1983 initio_reset_scsi(host, 10);1984 1985 while ((scb = initio_pop_busy_scb(host)) != NULL) {1986 scb->hastat = HOST_BAD_PHAS;1987 initio_append_done_scb(host, scb);1988 }1989 for (i = 0; i < host->max_tar; i++)1990 host->targets[i].flags &= ~(TCF_SYNC_DONE | TCF_WDTR_DONE);1991 return -1;1992}1993 1994 1995/**1996 * initio_msgout_abort_targ - abort a tag1997 * @host: InitIO host1998 *1999 * Abort when the target/lun does not match or when our SCB is not2000 * busy. Used by untagged commands.2001 */2002 2003static int initio_msgout_abort_targ(struct initio_host * host)2004{2005 2006 outb(((inb(host->addr + TUL_SSignal) & (TSC_SET_ACK | 7)) | TSC_SET_ATN), host->addr + TUL_SSignal);2007 if (initio_msgin_accept(host) == -1)2008 return -1;2009 if (host->phase != MSG_OUT)2010 return initio_bad_seq(host);2011 2012 outb(ABORT_TASK_SET, host->addr + TUL_SFifo);2013 outb(TSC_XF_FIFO_OUT, host->addr + TUL_SCmd);2014 2015 return initio_wait_disc(host);2016}2017 2018/**2019 * initio_msgout_abort_tag - abort a tag2020 * @host: InitIO host2021 *2022 * Abort when the target/lun does not match or when our SCB is not2023 * busy. Used for tagged commands.2024 */2025 2026static int initio_msgout_abort_tag(struct initio_host * host)2027{2028 2029 outb(((inb(host->addr + TUL_SSignal) & (TSC_SET_ACK | 7)) | TSC_SET_ATN), host->addr + TUL_SSignal);2030 if (initio_msgin_accept(host) == -1)2031 return -1;2032 if (host->phase != MSG_OUT)2033 return initio_bad_seq(host);2034 2035 outb(ABORT_TASK, host->addr + TUL_SFifo);2036 outb(TSC_XF_FIFO_OUT, host->addr + TUL_SCmd);2037 2038 return initio_wait_disc(host);2039 2040}2041 2042/**2043 * initio_msgin - Message in2044 * @host: InitIO Host2045 *2046 * Process incoming message2047 */2048static int initio_msgin(struct initio_host * host)2049{2050 struct target_control *active_tc;2051 2052 for (;;) {2053 outb(TSC_FLUSH_FIFO, host->addr + TUL_SCtrl0);2054 2055 outl(1, host->addr + TUL_SCnt0);2056 outb(TSC_XF_FIFO_IN, host->addr + TUL_SCmd);2057 if (wait_tulip(host) == -1)2058 return -1;2059 2060 switch (inb(host->addr + TUL_SFifo)) {2061 case DISCONNECT: /* Disconnect msg */2062 outb(TSC_MSG_ACCEPT, host->addr + TUL_SCmd);2063 return initio_wait_disc(host);2064 case SAVE_POINTERS:2065 case RESTORE_POINTERS:2066 case NOP:2067 initio_msgin_accept(host);2068 break;2069 case MESSAGE_REJECT: /* Clear ATN first */2070 outb((inb(host->addr + TUL_SSignal) & (TSC_SET_ACK | 7)),2071 host->addr + TUL_SSignal);2072 active_tc = host->active_tc;2073 if ((active_tc->flags & (TCF_SYNC_DONE | TCF_NO_SYNC_NEGO)) == 0) /* do sync nego */2074 outb(((inb(host->addr + TUL_SSignal) & (TSC_SET_ACK | 7)) | TSC_SET_ATN),2075 host->addr + TUL_SSignal);2076 initio_msgin_accept(host);2077 break;2078 case EXTENDED_MESSAGE: /* extended msg */2079 initio_msgin_extend(host);2080 break;2081 case IGNORE_WIDE_RESIDUE:2082 initio_msgin_accept(host);2083 break;2084 case COMMAND_COMPLETE:2085 outb(TSC_FLUSH_FIFO, host->addr + TUL_SCtrl0);2086 outb(TSC_MSG_ACCEPT, host->addr + TUL_SCmd);2087 return initio_wait_done_disc(host);2088 default:2089 initio_msgout_reject(host);2090 break;2091 }2092 if (host->phase != MSG_IN)2093 return host->phase;2094 }2095 /* statement won't reach here */2096}2097 2098static int initio_msgout_reject(struct initio_host * host)2099{2100 outb(((inb(host->addr + TUL_SSignal) & (TSC_SET_ACK | 7)) | TSC_SET_ATN), host->addr + TUL_SSignal);2101 2102 if (initio_msgin_accept(host) == -1)2103 return -1;2104 2105 if (host->phase == MSG_OUT) {2106 outb(MESSAGE_REJECT, host->addr + TUL_SFifo); /* Msg reject */2107 outb(TSC_XF_FIFO_OUT, host->addr + TUL_SCmd);2108 return wait_tulip(host);2109 }2110 return host->phase;2111}2112 2113static int initio_msgout_ide(struct initio_host * host)2114{2115 outb(INITIATOR_ERROR, host->addr + TUL_SFifo); /* Initiator Detected Error */2116 outb(TSC_XF_FIFO_OUT, host->addr + TUL_SCmd);2117 return wait_tulip(host);2118}2119 2120static int initio_msgin_extend(struct initio_host * host)2121{2122 u8 len, idx;2123 2124 if (initio_msgin_accept(host) != MSG_IN)2125 return host->phase;2126 2127 /* Get extended msg length */2128 outl(1, host->addr + TUL_SCnt0);2129 outb(TSC_XF_FIFO_IN, host->addr + TUL_SCmd);2130 if (wait_tulip(host) == -1)2131 return -1;2132 2133 len = inb(host->addr + TUL_SFifo);2134 host->msg[0] = len;2135 for (idx = 1; len != 0; len--) {2136 2137 if ((initio_msgin_accept(host)) != MSG_IN)2138 return host->phase;2139 outl(1, host->addr + TUL_SCnt0);2140 outb(TSC_XF_FIFO_IN, host->addr + TUL_SCmd);2141 if (wait_tulip(host) == -1)2142 return -1;2143 host->msg[idx++] = inb(host->addr + TUL_SFifo);2144 }2145 if (host->msg[1] == 1) { /* if it's synchronous data transfer request */2146 u8 r;2147 if (host->msg[0] != 3) /* if length is not right */2148 return initio_msgout_reject(host);2149 if (host->active_tc->flags & TCF_NO_SYNC_NEGO) { /* Set OFFSET=0 to do async, nego back */2150 host->msg[3] = 0;2151 } else {2152 if (initio_msgin_sync(host) == 0 &&2153 (host->active_tc->flags & TCF_SYNC_DONE)) {2154 initio_sync_done(host);2155 return initio_msgin_accept(host);2156 }2157 }2158 2159 r = inb(host->addr + TUL_SSignal);2160 outb((r & (TSC_SET_ACK | 7)) | TSC_SET_ATN,2161 host->addr + TUL_SSignal);2162 if (initio_msgin_accept(host) != MSG_OUT)2163 return host->phase;2164 /* sync msg out */2165 outb(TSC_FLUSH_FIFO, host->addr + TUL_SCtrl0);2166 2167 initio_sync_done(host);2168 2169 outb(EXTENDED_MESSAGE, host->addr + TUL_SFifo);2170 outb(3, host->addr + TUL_SFifo);2171 outb(EXTENDED_SDTR, host->addr + TUL_SFifo);2172 outb(host->msg[2], host->addr + TUL_SFifo);2173 outb(host->msg[3], host->addr + TUL_SFifo);2174 outb(TSC_XF_FIFO_OUT, host->addr + TUL_SCmd);2175 return wait_tulip(host);2176 }2177 if (host->msg[0] != 2 || host->msg[1] != 3)2178 return initio_msgout_reject(host);2179 /* if it's WIDE DATA XFER REQ */2180 if (host->active_tc->flags & TCF_NO_WDTR) {2181 host->msg[2] = 0;2182 } else {2183 if (host->msg[2] > 2) /* > 32 bits */2184 return initio_msgout_reject(host);2185 if (host->msg[2] == 2) { /* == 32 */2186 host->msg[2] = 1;2187 } else {2188 if ((host->active_tc->flags & TCF_NO_WDTR) == 0) {2189 wdtr_done(host);2190 if ((host->active_tc->flags & (TCF_SYNC_DONE | TCF_NO_SYNC_NEGO)) == 0)2191 outb(((inb(host->addr + TUL_SSignal) & (TSC_SET_ACK | 7)) | TSC_SET_ATN), host->addr + TUL_SSignal);2192 return initio_msgin_accept(host);2193 }2194 }2195 }2196 outb(((inb(host->addr + TUL_SSignal) & (TSC_SET_ACK | 7)) | TSC_SET_ATN), host->addr + TUL_SSignal);2197 2198 if (initio_msgin_accept(host) != MSG_OUT)2199 return host->phase;2200 /* WDTR msg out */2201 outb(EXTENDED_MESSAGE, host->addr + TUL_SFifo);2202 outb(2, host->addr + TUL_SFifo);2203 outb(EXTENDED_WDTR, host->addr + TUL_SFifo);2204 outb(host->msg[2], host->addr + TUL_SFifo);2205 outb(TSC_XF_FIFO_OUT, host->addr + TUL_SCmd);2206 return wait_tulip(host);2207}2208 2209static int initio_msgin_sync(struct initio_host * host)2210{2211 char default_period;2212 2213 default_period = initio_rate_tbl[host->active_tc->flags & TCF_SCSI_RATE];2214 if (host->msg[3] > MAX_OFFSET) {2215 host->msg[3] = MAX_OFFSET;2216 if (host->msg[2] < default_period) {2217 host->msg[2] = default_period;2218 return 1;2219 }2220 if (host->msg[2] >= 59) /* Change to async */2221 host->msg[3] = 0;2222 return 1;2223 }2224 /* offset requests asynchronous transfers ? */2225 if (host->msg[3] == 0) {2226 return 0;2227 }2228 if (host->msg[2] < default_period) {2229 host->msg[2] = default_period;2230 return 1;2231 }2232 if (host->msg[2] >= 59) {2233 host->msg[3] = 0;2234 return 1;2235 }2236 return 0;2237}2238 2239static int wdtr_done(struct initio_host * host)2240{2241 host->active_tc->flags &= ~TCF_SYNC_DONE;2242 host->active_tc->flags |= TCF_WDTR_DONE;2243 2244 host->active_tc->js_period = 0;2245 if (host->msg[2]) /* if 16 bit */2246 host->active_tc->js_period |= TSC_WIDE_SCSI;2247 host->active_tc->sconfig0 &= ~TSC_ALT_PERIOD;2248 outb(host->active_tc->sconfig0, host->addr + TUL_SConfig);2249 outb(host->active_tc->js_period, host->addr + TUL_SPeriod);2250 2251 return 1;2252}2253 2254static int initio_sync_done(struct initio_host * host)2255{2256 int i;2257 2258 host->active_tc->flags |= TCF_SYNC_DONE;2259 2260 if (host->msg[3]) {2261 host->active_tc->js_period |= host->msg[3];2262 for (i = 0; i < 8; i++) {2263 if (initio_rate_tbl[i] >= host->msg[2]) /* pick the big one */2264 break;2265 }2266 host->active_tc->js_period |= (i << 4);2267 host->active_tc->sconfig0 |= TSC_ALT_PERIOD;2268 }2269 outb(host->active_tc->sconfig0, host->addr + TUL_SConfig);2270 outb(host->active_tc->js_period, host->addr + TUL_SPeriod);2271 2272 return -1;2273}2274 2275 2276static int initio_post_scsi_rst(struct initio_host * host)2277{2278 struct scsi_ctrl_blk *scb;2279 struct target_control *active_tc;2280 int i;2281 2282 host->active = NULL;2283 host->active_tc = NULL;2284 host->flags = 0;2285 2286 while ((scb = initio_pop_busy_scb(host)) != NULL) {2287 scb->hastat = HOST_BAD_PHAS;2288 initio_append_done_scb(host, scb);2289 }2290 /* clear sync done flag */2291 active_tc = &host->targets[0];2292 for (i = 0; i < host->max_tar; active_tc++, i++) {2293 active_tc->flags &= ~(TCF_SYNC_DONE | TCF_WDTR_DONE);2294 /* Initialize the sync. xfer register values to an asyn xfer */2295 active_tc->js_period = 0;2296 active_tc->sconfig0 = host->sconf1;2297 host->act_tags[0] = 0; /* 07/22/98 */2298 host->targets[i].flags &= ~TCF_BUSY; /* 07/22/98 */2299 } /* for */2300 2301 return -1;2302}2303 2304static void initio_select_atn_stop(struct initio_host * host, struct scsi_ctrl_blk * scb)2305{2306 scb->status |= SCB_SELECT;2307 scb->next_state = 0x1;2308 host->active = scb;2309 host->active_tc = &host->targets[scb->target];2310 outb(TSC_SELATNSTOP, host->addr + TUL_SCmd);2311}2312 2313 2314static void initio_select_atn(struct initio_host * host, struct scsi_ctrl_blk * scb)2315{2316 int i;2317 2318 scb->status |= SCB_SELECT;2319 scb->next_state = 0x2;2320 2321 outb(scb->ident, host->addr + TUL_SFifo);2322 for (i = 0; i < (int) scb->cdblen; i++)2323 outb(scb->cdb[i], host->addr + TUL_SFifo);2324 host->active_tc = &host->targets[scb->target];2325 host->active = scb;2326 outb(TSC_SEL_ATN, host->addr + TUL_SCmd);2327}2328 2329static void initio_select_atn3(struct initio_host * host, struct scsi_ctrl_blk * scb)2330{2331 int i;2332 2333 scb->status |= SCB_SELECT;2334 scb->next_state = 0x2;2335 2336 outb(scb->ident, host->addr + TUL_SFifo);2337 outb(scb->tagmsg, host->addr + TUL_SFifo);2338 outb(scb->tagid, host->addr + TUL_SFifo);2339 for (i = 0; i < scb->cdblen; i++)2340 outb(scb->cdb[i], host->addr + TUL_SFifo);2341 host->active_tc = &host->targets[scb->target];2342 host->active = scb;2343 outb(TSC_SEL_ATN3, host->addr + TUL_SCmd);2344}2345 2346/**2347 * initio_bus_device_reset - SCSI Bus Device Reset2348 * @host: InitIO host to reset2349 *2350 * Perform a device reset and abort all pending SCBs for the2351 * victim device2352 */2353int initio_bus_device_reset(struct initio_host * host)2354{2355 struct scsi_ctrl_blk *scb = host->active;2356 struct target_control *active_tc = host->active_tc;2357 struct scsi_ctrl_blk *tmp, *prev;2358 u8 tar;2359 2360 if (host->phase != MSG_OUT)2361 return int_initio_bad_seq(host); /* Unexpected phase */2362 2363 initio_unlink_pend_scb(host, scb);2364 initio_release_scb(host, scb);2365 2366 2367 tar = scb->target; /* target */2368 active_tc->flags &= ~(TCF_SYNC_DONE | TCF_WDTR_DONE | TCF_BUSY);2369 /* clr sync. nego & WDTR flags 07/22/98 */2370 2371 /* abort all SCB with same target */2372 prev = tmp = host->first_busy; /* Check Busy queue */2373 while (tmp != NULL) {2374 if (tmp->target == tar) {2375 /* unlink it */2376 if (tmp == host->first_busy) {2377 if ((host->first_busy = tmp->next) == NULL)2378 host->last_busy = NULL;2379 } else {2380 prev->next = tmp->next;2381 if (tmp == host->last_busy)2382 host->last_busy = prev;2383 }2384 tmp->hastat = HOST_ABORTED;2385 initio_append_done_scb(host, tmp);2386 }2387 /* Previous haven't change */2388 else {2389 prev = tmp;2390 }2391 tmp = tmp->next;2392 }2393 outb(TARGET_RESET, host->addr + TUL_SFifo);2394 outb(TSC_XF_FIFO_OUT, host->addr + TUL_SCmd);2395 return initio_wait_disc(host);2396 2397}2398 2399static int initio_msgin_accept(struct initio_host * host)2400{2401 outb(TSC_MSG_ACCEPT, host->addr + TUL_SCmd);2402 return wait_tulip(host);2403}2404 2405static int wait_tulip(struct initio_host * host)2406{2407 2408 while (!((host->jsstatus0 = inb(host->addr + TUL_SStatus0))2409 & TSS_INT_PENDING))2410 cpu_relax();2411 2412 host->jsint = inb(host->addr + TUL_SInt);2413 host->phase = host->jsstatus0 & TSS_PH_MASK;2414 host->jsstatus1 = inb(host->addr + TUL_SStatus1);2415 2416 if (host->jsint & TSS_RESEL_INT) /* if SCSI bus reset detected */2417 return int_initio_resel(host);2418 if (host->jsint & TSS_SEL_TIMEOUT) /* if selected/reselected timeout interrupt */2419 return int_initio_busfree(host);2420 if (host->jsint & TSS_SCSIRST_INT) /* if SCSI bus reset detected */2421 return int_initio_scsi_rst(host);2422 2423 if (host->jsint & TSS_DISC_INT) { /* BUS disconnection */2424 if (host->flags & HCF_EXPECT_DONE_DISC) {2425 outb(TSC_FLUSH_FIFO, host->addr + TUL_SCtrl0); /* Flush SCSI FIFO */2426 initio_unlink_busy_scb(host, host->active);2427 host->active->hastat = 0;2428 initio_append_done_scb(host, host->active);2429 host->active = NULL;2430 host->active_tc = NULL;2431 host->flags &= ~HCF_EXPECT_DONE_DISC;2432 outb(TSC_INITDEFAULT, host->addr + TUL_SConfig);2433 outb(TSC_HW_RESELECT, host->addr + TUL_SCtrl1); /* Enable HW reselect */2434 return -1;2435 }2436 if (host->flags & HCF_EXPECT_DISC) {2437 outb(TSC_FLUSH_FIFO, host->addr + TUL_SCtrl0); /* Flush SCSI FIFO */2438 host->active = NULL;2439 host->active_tc = NULL;2440 host->flags &= ~HCF_EXPECT_DISC;2441 outb(TSC_INITDEFAULT, host->addr + TUL_SConfig);2442 outb(TSC_HW_RESELECT, host->addr + TUL_SCtrl1); /* Enable HW reselect */2443 return -1;2444 }2445 return int_initio_busfree(host);2446 }2447 /* The old code really does the below. Can probably be removed */2448 if (host->jsint & (TSS_FUNC_COMP | TSS_BUS_SERV))2449 return host->phase;2450 return host->phase;2451}2452 2453static int initio_wait_disc(struct initio_host * host)2454{2455 while (!((host->jsstatus0 = inb(host->addr + TUL_SStatus0)) & TSS_INT_PENDING))2456 cpu_relax();2457 2458 host->jsint = inb(host->addr + TUL_SInt);2459 2460 if (host->jsint & TSS_SCSIRST_INT) /* if SCSI bus reset detected */2461 return int_initio_scsi_rst(host);2462 if (host->jsint & TSS_DISC_INT) { /* BUS disconnection */2463 outb(TSC_FLUSH_FIFO, host->addr + TUL_SCtrl0); /* Flush SCSI FIFO */2464 outb(TSC_INITDEFAULT, host->addr + TUL_SConfig);2465 outb(TSC_HW_RESELECT, host->addr + TUL_SCtrl1); /* Enable HW reselect */2466 host->active = NULL;2467 return -1;2468 }2469 return initio_bad_seq(host);2470}2471 2472static int initio_wait_done_disc(struct initio_host * host)2473{2474 while (!((host->jsstatus0 = inb(host->addr + TUL_SStatus0))2475 & TSS_INT_PENDING))2476 cpu_relax();2477 2478 host->jsint = inb(host->addr + TUL_SInt);2479 2480 if (host->jsint & TSS_SCSIRST_INT) /* if SCSI bus reset detected */2481 return int_initio_scsi_rst(host);2482 if (host->jsint & TSS_DISC_INT) { /* BUS disconnection */2483 outb(TSC_FLUSH_FIFO, host->addr + TUL_SCtrl0); /* Flush SCSI FIFO */2484 outb(TSC_INITDEFAULT, host->addr + TUL_SConfig);2485 outb(TSC_HW_RESELECT, host->addr + TUL_SCtrl1); /* Enable HW reselect */2486 initio_unlink_busy_scb(host, host->active);2487 2488 initio_append_done_scb(host, host->active);2489 host->active = NULL;2490 return -1;2491 }2492 return initio_bad_seq(host);2493}2494 2495/**2496 * i91u_intr - IRQ handler2497 * @irqno: IRQ number2498 * @dev_id: IRQ identifier2499 *2500 * Take the relevant locks and then invoke the actual isr processing2501 * code under the lock.2502 */2503 2504static irqreturn_t i91u_intr(int irqno, void *dev_id)2505{2506 struct Scsi_Host *dev = dev_id;2507 unsigned long flags;2508 int r;2509 2510 spin_lock_irqsave(dev->host_lock, flags);2511 r = initio_isr((struct initio_host *)dev->hostdata);2512 spin_unlock_irqrestore(dev->host_lock, flags);2513 if (r)2514 return IRQ_HANDLED;2515 else2516 return IRQ_NONE;2517}2518 2519 2520/**2521 * initio_build_scb - Build the mappings and SCB2522 * @host: InitIO host taking the command2523 * @cblk: Firmware command block2524 * @cmnd: SCSI midlayer command block2525 *2526 * Translate the abstract SCSI command into a firmware command block2527 * suitable for feeding to the InitIO host controller. This also requires2528 * we build the scatter gather lists and ensure they are mapped properly.2529 */2530 2531static void initio_build_scb(struct initio_host * host, struct scsi_ctrl_blk * cblk, struct scsi_cmnd * cmnd)2532{ /* Create corresponding SCB */2533 struct scatterlist *sglist;2534 struct sg_entry *sg; /* Pointer to SG list */2535 int i, nseg;2536 long total_len;2537 dma_addr_t dma_addr;2538 2539 /* Fill in the command headers */2540 cblk->post = i91uSCBPost; /* i91u's callback routine */2541 cblk->srb = cmnd;2542 cblk->opcode = ExecSCSI;2543 cblk->flags = SCF_POST; /* After SCSI done, call post routine */2544 cblk->target = cmnd->device->id;2545 cblk->lun = cmnd->device->lun;2546 cblk->ident = cmnd->device->lun | DISC_ALLOW;2547 2548 cblk->flags |= SCF_SENSE; /* Turn on auto request sense */2549 2550 /* Map the sense buffer into bus memory */2551 dma_addr = dma_map_single(&host->pci_dev->dev, cmnd->sense_buffer,2552 SENSE_SIZE, DMA_FROM_DEVICE);2553 cblk->senseptr = (u32)dma_addr;2554 cblk->senselen = SENSE_SIZE;2555 initio_priv(cmnd)->sense_dma_addr = dma_addr;2556 cblk->cdblen = cmnd->cmd_len;2557 2558 /* Clear the returned status */2559 cblk->hastat = 0;2560 cblk->tastat = 0;2561 /* Command the command */2562 memcpy(cblk->cdb, cmnd->cmnd, cmnd->cmd_len);2563 2564 /* Set up tags */2565 if (cmnd->device->tagged_supported) { /* Tag Support */2566 cblk->tagmsg = SIMPLE_QUEUE_TAG; /* Do simple tag only */2567 } else {2568 cblk->tagmsg = 0; /* No tag support */2569 }2570 2571 /* todo handle map_sg error */2572 nseg = scsi_dma_map(cmnd);2573 BUG_ON(nseg < 0);2574 if (nseg) {2575 dma_addr = dma_map_single(&host->pci_dev->dev, &cblk->sglist[0],2576 sizeof(struct sg_entry) * TOTAL_SG_ENTRY,2577 DMA_BIDIRECTIONAL);2578 cblk->bufptr = (u32)dma_addr;2579 initio_priv(cmnd)->sglist_dma_addr = dma_addr;2580 2581 cblk->sglen = nseg;2582 2583 cblk->flags |= SCF_SG; /* Turn on SG list flag */2584 total_len = 0;2585 sg = &cblk->sglist[0];2586 scsi_for_each_sg(cmnd, sglist, cblk->sglen, i) {2587 sg->data = cpu_to_le32((u32)sg_dma_address(sglist));2588 sg->len = cpu_to_le32((u32)sg_dma_len(sglist));2589 total_len += sg_dma_len(sglist);2590 ++sg;2591 }2592 2593 cblk->buflen = (scsi_bufflen(cmnd) > total_len) ?2594 total_len : scsi_bufflen(cmnd);2595 } else { /* No data transfer required */2596 cblk->buflen = 0;2597 cblk->sglen = 0;2598 }2599}2600 2601/**2602 * i91u_queuecommand_lck - Queue a new command if possible2603 * @cmd: SCSI command block from the mid layer2604 *2605 * Attempts to queue a new command with the host adapter. Will return2606 * zero if successful or indicate a host busy condition if not (which2607 * will cause the mid layer to call us again later with the command)2608 */2609static int i91u_queuecommand_lck(struct scsi_cmnd *cmd)2610{2611 struct initio_host *host = (struct initio_host *) cmd->device->host->hostdata;2612 struct scsi_ctrl_blk *cmnd;2613 2614 cmnd = initio_alloc_scb(host);2615 if (!cmnd)2616 return SCSI_MLQUEUE_HOST_BUSY;2617 2618 initio_build_scb(host, cmnd, cmd);2619 initio_exec_scb(host, cmnd);2620 return 0;2621}2622 2623static DEF_SCSI_QCMD(i91u_queuecommand)2624 2625/**2626 * i91u_bus_reset - reset the SCSI bus2627 * @cmnd: Command block we want to trigger the reset for2628 *2629 * Initiate a SCSI bus reset sequence2630 */2631 2632static int i91u_bus_reset(struct scsi_cmnd * cmnd)2633{2634 struct initio_host *host;2635 2636 host = (struct initio_host *) cmnd->device->host->hostdata;2637 2638 spin_lock_irq(cmnd->device->host->host_lock);2639 initio_reset_scsi(host, 0);2640 spin_unlock_irq(cmnd->device->host->host_lock);2641 2642 return SUCCESS;2643}2644 2645/**2646 * i91u_biosparam - return the "logical geometry2647 * @sdev: SCSI device2648 * @dev: Matching block device2649 * @capacity: Sector size of drive2650 * @info_array: Return space for BIOS geometry2651 *2652 * Map the device geometry in a manner compatible with the host2653 * controller BIOS behaviour.2654 *2655 * FIXME: limited to 2^32 sector devices.2656 */2657 2658static int i91u_biosparam(struct scsi_device *sdev, struct block_device *dev,2659 sector_t capacity, int *info_array)2660{2661 struct initio_host *host; /* Point to Host adapter control block */2662 struct target_control *tc;2663 2664 host = (struct initio_host *) sdev->host->hostdata;2665 tc = &host->targets[sdev->id];2666 2667 if (tc->heads) {2668 info_array[0] = tc->heads;2669 info_array[1] = tc->sectors;2670 info_array[2] = (unsigned long)capacity / tc->heads / tc->sectors;2671 } else {2672 if (tc->drv_flags & TCF_DRV_255_63) {2673 info_array[0] = 255;2674 info_array[1] = 63;2675 info_array[2] = (unsigned long)capacity / 255 / 63;2676 } else {2677 info_array[0] = 64;2678 info_array[1] = 32;2679 info_array[2] = (unsigned long)capacity >> 11;2680 }2681 }2682 2683#if defined(DEBUG_BIOSPARAM)2684 if (i91u_debug & debug_biosparam) {2685 printk("bios geometry: head=%d, sec=%d, cyl=%d\n",2686 info_array[0], info_array[1], info_array[2]);2687 printk("WARNING: check, if the bios geometry is correct.\n");2688 }2689#endif2690 2691 return 0;2692}2693 2694/**2695 * i91u_unmap_scb - Unmap a command2696 * @pci_dev: PCI device the command is for2697 * @cmnd: The command itself2698 *2699 * Unmap any PCI mapping/IOMMU resources allocated when the command2700 * was mapped originally as part of initio_build_scb2701 */2702 2703static void i91u_unmap_scb(struct pci_dev *pci_dev, struct scsi_cmnd *cmnd)2704{2705 /* auto sense buffer */2706 if (initio_priv(cmnd)->sense_dma_addr) {2707 dma_unmap_single(&pci_dev->dev,2708 initio_priv(cmnd)->sense_dma_addr,2709 SENSE_SIZE, DMA_FROM_DEVICE);2710 initio_priv(cmnd)->sense_dma_addr = 0;2711 }2712 2713 /* request buffer */2714 if (scsi_sg_count(cmnd)) {2715 dma_unmap_single(&pci_dev->dev,2716 initio_priv(cmnd)->sglist_dma_addr,2717 sizeof(struct sg_entry) * TOTAL_SG_ENTRY,2718 DMA_BIDIRECTIONAL);2719 2720 scsi_dma_unmap(cmnd);2721 }2722}2723 2724/*2725 * i91uSCBPost - SCSI callback2726 *2727 * This is callback routine be called when tulip finish one2728 * SCSI command.2729 */2730 2731static void i91uSCBPost(u8 * host_mem, u8 * cblk_mem)2732{2733 struct scsi_cmnd *cmnd; /* Pointer to SCSI request block */2734 struct initio_host *host;2735 struct scsi_ctrl_blk *cblk;2736 2737 host = (struct initio_host *) host_mem;2738 cblk = (struct scsi_ctrl_blk *) cblk_mem;2739 if ((cmnd = cblk->srb) == NULL) {2740 printk(KERN_ERR "i91uSCBPost: SRB pointer is empty\n");2741 WARN_ON(1);2742 initio_release_scb(host, cblk); /* Release SCB for current channel */2743 return;2744 }2745 2746 /*2747 * Remap the firmware error status into a mid layer one2748 */2749 switch (cblk->hastat) {2750 case 0x0:2751 case 0xa: /* Linked command complete without error and linked normally */2752 case 0xb: /* Linked command complete without error interrupt generated */2753 cblk->hastat = 0;2754 break;2755 2756 case 0x11: /* Selection time out-The initiator selection or target2757 reselection was not complete within the SCSI Time out period */2758 cblk->hastat = DID_TIME_OUT;2759 break;2760 2761 case 0x14: /* Target bus phase sequence failure-An invalid bus phase or bus2762 phase sequence was requested by the target. The host adapter2763 will generate a SCSI Reset Condition, notifying the host with2764 a SCRD interrupt */2765 cblk->hastat = DID_RESET;2766 break;2767 2768 case 0x1a: /* SCB Aborted. 07/21/98 */2769 cblk->hastat = DID_ABORT;2770 break;2771 2772 case 0x12: /* Data overrun/underrun-The target attempted to transfer more data2773 than was allocated by the Data Length field or the sum of the2774 Scatter / Gather Data Length fields. */2775 case 0x13: /* Unexpected bus free-The target dropped the SCSI BSY at an unexpected time. */2776 case 0x16: /* Invalid SCB Operation Code. */2777 2778 default:2779 printk("ini9100u: %x %x\n", cblk->hastat, cblk->tastat);2780 cblk->hastat = DID_ERROR; /* Couldn't find any better */2781 break;2782 }2783 2784 cmnd->result = cblk->tastat | (cblk->hastat << 16);2785 i91u_unmap_scb(host->pci_dev, cmnd);2786 scsi_done(cmnd); /* Notify system DONE */2787 initio_release_scb(host, cblk); /* Release SCB for current channel */2788}2789 2790static const struct scsi_host_template initio_template = {2791 .proc_name = "INI9100U",2792 .name = "Initio INI-9X00U/UW SCSI device driver",2793 .queuecommand = i91u_queuecommand,2794 .eh_bus_reset_handler = i91u_bus_reset,2795 .bios_param = i91u_biosparam,2796 .can_queue = MAX_TARGETS * i91u_MAXQUEUE,2797 .this_id = 1,2798 .sg_tablesize = SG_ALL,2799 .cmd_size = sizeof(struct initio_cmd_priv),2800};2801 2802static int initio_probe_one(struct pci_dev *pdev,2803 const struct pci_device_id *id)2804{2805 struct Scsi_Host *shost;2806 struct initio_host *host;2807 u32 reg;2808 u16 bios_seg;2809 struct scsi_ctrl_blk *scb, *tmp, *prev = NULL /* silence gcc */;2810 int num_scb, i, error;2811 2812 error = pci_enable_device(pdev);2813 if (error)2814 return error;2815 2816 pci_read_config_dword(pdev, 0x44, (u32 *) & reg);2817 bios_seg = (u16) (reg & 0xFF);2818 if (((reg & 0xFF00) >> 8) == 0xFF)2819 reg = 0;2820 bios_seg = (bios_seg << 8) + ((u16) ((reg & 0xFF00) >> 8));2821 2822 if (dma_set_mask(&pdev->dev, DMA_BIT_MASK(32))) {2823 printk(KERN_WARNING "i91u: Could not set 32 bit DMA mask\n");2824 error = -ENODEV;2825 goto out_disable_device;2826 }2827 shost = scsi_host_alloc(&initio_template, sizeof(struct initio_host));2828 if (!shost) {2829 printk(KERN_WARNING "initio: Could not allocate host structure.\n");2830 error = -ENOMEM;2831 goto out_disable_device;2832 }2833 host = (struct initio_host *)shost->hostdata;2834 memset(host, 0, sizeof(struct initio_host));2835 host->addr = pci_resource_start(pdev, 0);2836 host->bios_addr = bios_seg;2837 2838 if (!request_region(host->addr, 256, "i91u")) {2839 printk(KERN_WARNING "initio: I/O port range 0x%x is busy.\n", host->addr);2840 error = -ENODEV;2841 goto out_host_put;2842 }2843 2844 if (initio_tag_enable) /* 1.01i */2845 num_scb = MAX_TARGETS * i91u_MAXQUEUE;2846 else2847 num_scb = MAX_TARGETS + 3; /* 1-tape, 1-CD_ROM, 1- extra */2848 2849 for (; num_scb >= MAX_TARGETS + 3; num_scb--) {2850 i = num_scb * sizeof(struct scsi_ctrl_blk);2851 scb = kzalloc(i, GFP_KERNEL);2852 if (scb)2853 break;2854 }2855 2856 if (!scb) {2857 printk(KERN_WARNING "initio: Cannot allocate SCB array.\n");2858 error = -ENOMEM;2859 goto out_release_region;2860 }2861 2862 host->pci_dev = pdev;2863 2864 host->semaph = 1;2865 spin_lock_init(&host->semaph_lock);2866 host->num_scbs = num_scb;2867 host->scb = scb;2868 host->next_pending = scb;2869 host->next_avail = scb;2870 for (i = 0, tmp = scb; i < num_scb; i++, tmp++) {2871 tmp->tagid = i;2872 if (i != 0)2873 prev->next = tmp;2874 prev = tmp;2875 }2876 prev->next = NULL;2877 host->scb_end = tmp;2878 host->first_avail = scb;2879 host->last_avail = prev;2880 spin_lock_init(&host->avail_lock);2881 2882 initio_init(host, phys_to_virt(((u32)bios_seg << 4)));2883 2884 host->jsstatus0 = 0;2885 2886 shost->io_port = host->addr;2887 shost->n_io_port = 0xff;2888 shost->can_queue = num_scb; /* 03/05/98 */2889 shost->unique_id = host->addr;2890 shost->max_id = host->max_tar;2891 shost->max_lun = 32; /* 10/21/97 */2892 shost->irq = pdev->irq;2893 shost->this_id = host->scsi_id; /* Assign HCS index */2894 shost->base = host->addr;2895 shost->sg_tablesize = TOTAL_SG_ENTRY;2896 2897 error = request_irq(pdev->irq, i91u_intr, IRQF_SHARED, "i91u", shost);2898 if (error < 0) {2899 printk(KERN_WARNING "initio: Unable to request IRQ %d\n", pdev->irq);2900 goto out_free_scbs;2901 }2902 2903 pci_set_drvdata(pdev, shost);2904 2905 error = scsi_add_host(shost, &pdev->dev);2906 if (error)2907 goto out_free_irq;2908 scsi_scan_host(shost);2909 return 0;2910out_free_irq:2911 free_irq(pdev->irq, shost);2912out_free_scbs:2913 kfree(host->scb);2914out_release_region:2915 release_region(host->addr, 256);2916out_host_put:2917 scsi_host_put(shost);2918out_disable_device:2919 pci_disable_device(pdev);2920 return error;2921}2922 2923/**2924 * initio_remove_one - control shutdown2925 * @pdev: PCI device being released2926 *2927 * Release the resources assigned to this adapter after it has2928 * finished being used.2929 */2930 2931static void initio_remove_one(struct pci_dev *pdev)2932{2933 struct Scsi_Host *host = pci_get_drvdata(pdev);2934 struct initio_host *s = (struct initio_host *)host->hostdata;2935 scsi_remove_host(host);2936 free_irq(pdev->irq, host);2937 release_region(s->addr, 256);2938 scsi_host_put(host);2939 pci_disable_device(pdev);2940}2941 2942MODULE_LICENSE("GPL");2943 2944static struct pci_device_id initio_pci_tbl[] = {2945 {PCI_VENDOR_ID_INIT, 0x9500, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},2946 {PCI_VENDOR_ID_INIT, 0x9400, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},2947 {PCI_VENDOR_ID_INIT, 0x9401, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},2948 {PCI_VENDOR_ID_INIT, 0x0002, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},2949 {PCI_VENDOR_ID_DOMEX, 0x0002, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},2950 {0,}2951};2952MODULE_DEVICE_TABLE(pci, initio_pci_tbl);2953 2954static struct pci_driver initio_pci_driver = {2955 .name = "initio",2956 .id_table = initio_pci_tbl,2957 .probe = initio_probe_one,2958 .remove = initio_remove_one,2959};2960module_pci_driver(initio_pci_driver);2961 2962MODULE_DESCRIPTION("Initio INI-9X00U/UW SCSI device driver");2963MODULE_AUTHOR("Initio Corporation");2964MODULE_LICENSE("GPL");2965