3039 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * linux/drivers/acorn/scsi/fas216.c4 *5 * Copyright (C) 1997-2003 Russell King6 *7 * Based on information in qlogicfas.c by Tom Zerucha, Michael Griffith, and8 * other sources, including:9 * the AMD Am53CF94 data sheet10 * the AMD Am53C94 data sheet11 *12 * This is a generic driver. To use it, have a look at cumana_2.c. You13 * should define your own structure that overlays FAS216_Info, eg:14 * struct my_host_data {15 * FAS216_Info info;16 * ... my host specific data ...17 * };18 *19 * Changelog:20 * 30-08-1997 RMK Created21 * 14-09-1997 RMK Started disconnect support22 * 08-02-1998 RMK Corrected real DMA support23 * 15-02-1998 RMK Started sync xfer support24 * 06-04-1998 RMK Tightened conditions for printing incomplete25 * transfers26 * 02-05-1998 RMK Added extra checks in fas216_reset27 * 24-05-1998 RMK Fixed synchronous transfers with period >= 200ns28 * 27-06-1998 RMK Changed asm/delay.h to linux/delay.h29 * 26-08-1998 RMK Improved message support wrt MESSAGE_REJECT30 * 02-04-2000 RMK Converted to use the new error handling, and31 * automatically request sense data upon check32 * condition status from targets.33 */34#include <linux/module.h>35#include <linux/blkdev.h>36#include <linux/kernel.h>37#include <linux/string.h>38#include <linux/ioport.h>39#include <linux/proc_fs.h>40#include <linux/delay.h>41#include <linux/bitops.h>42#include <linux/init.h>43#include <linux/interrupt.h>44 45#include <asm/dma.h>46#include <asm/io.h>47#include <asm/irq.h>48#include <asm/ecard.h>49 50#include <scsi/scsi.h>51#include <scsi/scsi_cmnd.h>52#include <scsi/scsi_dbg.h>53#include <scsi/scsi_device.h>54#include <scsi/scsi_eh.h>55#include <scsi/scsi_host.h>56#include <scsi/scsi_tcq.h>57#include "fas216.h"58#include "arm_scsi.h"59 60/* NOTE: SCSI2 Synchronous transfers *require* DMA according to61 * the data sheet. This restriction is crazy, especially when62 * you only want to send 16 bytes! What were the guys who63 * designed this chip on at that time? Did they read the SCSI264 * spec at all? The following sections are taken from the SCSI265 * standard (s2r10) concerning this:66 *67 * > IMPLEMENTORS NOTES:68 * > (1) Re-negotiation at every selection is not recommended, since a69 * > significant performance impact is likely.70 *71 * > The implied synchronous agreement shall remain in effect until a BUS DEVICE72 * > RESET message is received, until a hard reset condition occurs, or until one73 * > of the two SCSI devices elects to modify the agreement. The default data74 * > transfer mode is asynchronous data transfer mode. The default data transfer75 * > mode is entered at power on, after a BUS DEVICE RESET message, or after a hard76 * > reset condition.77 *78 * In total, this means that once you have elected to use synchronous79 * transfers, you must always use DMA.80 *81 * I was thinking that this was a good chip until I found this restriction ;(82 */83#define SCSI2_SYNC84 85#undef DEBUG_CONNECT86#undef DEBUG_MESSAGES87 88#undef CHECK_STRUCTURE89 90#define LOG_CONNECT (1 << 0)91#define LOG_BUSSERVICE (1 << 1)92#define LOG_FUNCTIONDONE (1 << 2)93#define LOG_MESSAGES (1 << 3)94#define LOG_BUFFER (1 << 4)95#define LOG_ERROR (1 << 8)96 97static int level_mask = LOG_ERROR;98 99module_param(level_mask, int, 0644);100 101#ifndef MODULE102static int __init fas216_log_setup(char *str)103{104 char *s;105 106 level_mask = 0;107 108 while ((s = strsep(&str, ",")) != NULL) {109 switch (s[0]) {110 case 'a':111 if (strcmp(s, "all") == 0)112 level_mask |= -1;113 break;114 case 'b':115 if (strncmp(s, "bus", 3) == 0)116 level_mask |= LOG_BUSSERVICE;117 if (strncmp(s, "buf", 3) == 0)118 level_mask |= LOG_BUFFER;119 break;120 case 'c':121 level_mask |= LOG_CONNECT;122 break;123 case 'e':124 level_mask |= LOG_ERROR;125 break;126 case 'm':127 level_mask |= LOG_MESSAGES;128 break;129 case 'n':130 if (strcmp(s, "none") == 0)131 level_mask = 0;132 break;133 case 's':134 level_mask |= LOG_FUNCTIONDONE;135 break;136 }137 }138 return 1;139}140 141__setup("fas216_logging=", fas216_log_setup);142#endif143 144static inline unsigned char fas216_readb(FAS216_Info *info, unsigned int reg)145{146 unsigned int off = reg << info->scsi.io_shift;147 return readb(info->scsi.io_base + off);148}149 150static inline void fas216_writeb(FAS216_Info *info, unsigned int reg, unsigned int val)151{152 unsigned int off = reg << info->scsi.io_shift;153 writeb(val, info->scsi.io_base + off);154}155 156static void fas216_dumpstate(FAS216_Info *info)157{158 unsigned char is, stat, inst;159 160 is = fas216_readb(info, REG_IS);161 stat = fas216_readb(info, REG_STAT);162 inst = fas216_readb(info, REG_INST);163 164 printk("FAS216: CTCL=%02X CTCM=%02X CMD=%02X STAT=%02X"165 " INST=%02X IS=%02X CFIS=%02X",166 fas216_readb(info, REG_CTCL),167 fas216_readb(info, REG_CTCM),168 fas216_readb(info, REG_CMD), stat, inst, is,169 fas216_readb(info, REG_CFIS));170 printk(" CNTL1=%02X CNTL2=%02X CNTL3=%02X CTCH=%02X\n",171 fas216_readb(info, REG_CNTL1),172 fas216_readb(info, REG_CNTL2),173 fas216_readb(info, REG_CNTL3),174 fas216_readb(info, REG_CTCH));175}176 177static void print_SCp(struct scsi_pointer *SCp, const char *prefix, const char *suffix)178{179 printk("%sptr %p this_residual 0x%x buffer %p buffers_residual 0x%x%s",180 prefix, SCp->ptr, SCp->this_residual, SCp->buffer,181 SCp->buffers_residual, suffix);182}183 184#ifdef CHECK_STRUCTURE185static void fas216_dumpinfo(FAS216_Info *info)186{187 static int used = 0;188 int i;189 190 if (used++)191 return;192 193 printk("FAS216_Info=\n");194 printk(" { magic_start=%lX host=%p SCpnt=%p origSCpnt=%p\n",195 info->magic_start, info->host, info->SCpnt,196 info->origSCpnt);197 printk(" scsi={ io_shift=%X irq=%X cfg={ %X %X %X %X }\n",198 info->scsi.io_shift, info->scsi.irq,199 info->scsi.cfg[0], info->scsi.cfg[1], info->scsi.cfg[2],200 info->scsi.cfg[3]);201 printk(" type=%p phase=%X\n",202 info->scsi.type, info->scsi.phase);203 print_SCp(&info->scsi.SCp, " SCp={ ", " }\n");204 printk(" msgs async_stp=%X disconnectable=%d aborting=%d }\n",205 info->scsi.async_stp,206 info->scsi.disconnectable, info->scsi.aborting);207 printk(" stats={ queues=%X removes=%X fins=%X reads=%X writes=%X miscs=%X\n"208 " disconnects=%X aborts=%X bus_resets=%X host_resets=%X}\n",209 info->stats.queues, info->stats.removes, info->stats.fins,210 info->stats.reads, info->stats.writes, info->stats.miscs,211 info->stats.disconnects, info->stats.aborts, info->stats.bus_resets,212 info->stats.host_resets);213 printk(" ifcfg={ clockrate=%X select_timeout=%X asyncperiod=%X sync_max_depth=%X }\n",214 info->ifcfg.clockrate, info->ifcfg.select_timeout,215 info->ifcfg.asyncperiod, info->ifcfg.sync_max_depth);216 for (i = 0; i < 8; i++) {217 printk(" busyluns[%d]=%08lx dev[%d]={ disconnect_ok=%d stp=%X sof=%X sync_state=%X }\n",218 i, info->busyluns[i], i,219 info->device[i].disconnect_ok, info->device[i].stp,220 info->device[i].sof, info->device[i].sync_state);221 }222 printk(" dma={ transfer_type=%X setup=%p pseudo=%p stop=%p }\n",223 info->dma.transfer_type, info->dma.setup,224 info->dma.pseudo, info->dma.stop);225 printk(" internal_done=%X magic_end=%lX }\n",226 info->internal_done, info->magic_end);227}228 229static void __fas216_checkmagic(FAS216_Info *info, const char *func)230{231 int corruption = 0;232 if (info->magic_start != MAGIC) {233 printk(KERN_CRIT "FAS216 Error: magic at start corrupted\n");234 corruption++;235 }236 if (info->magic_end != MAGIC) {237 printk(KERN_CRIT "FAS216 Error: magic at end corrupted\n");238 corruption++;239 }240 if (corruption) {241 fas216_dumpinfo(info);242 panic("scsi memory space corrupted in %s", func);243 }244}245#define fas216_checkmagic(info) __fas216_checkmagic((info), __func__)246#else247#define fas216_checkmagic(info)248#endif249 250static const char *fas216_bus_phase(int stat)251{252 static const char *phases[] = {253 "DATA OUT", "DATA IN",254 "COMMAND", "STATUS",255 "MISC OUT", "MISC IN",256 "MESG OUT", "MESG IN"257 };258 259 return phases[stat & STAT_BUSMASK];260}261 262static const char *fas216_drv_phase(FAS216_Info *info)263{264 static const char *phases[] = {265 [PHASE_IDLE] = "idle",266 [PHASE_SELECTION] = "selection",267 [PHASE_COMMAND] = "command",268 [PHASE_DATAOUT] = "data out",269 [PHASE_DATAIN] = "data in",270 [PHASE_MSGIN] = "message in",271 [PHASE_MSGIN_DISCONNECT]= "disconnect",272 [PHASE_MSGOUT_EXPECT] = "expect message out",273 [PHASE_MSGOUT] = "message out",274 [PHASE_STATUS] = "status",275 [PHASE_DONE] = "done",276 };277 278 if (info->scsi.phase < ARRAY_SIZE(phases) &&279 phases[info->scsi.phase])280 return phases[info->scsi.phase];281 return "???";282}283 284static char fas216_target(FAS216_Info *info)285{286 if (info->SCpnt)287 return '0' + info->SCpnt->device->id;288 else289 return 'H';290}291 292static void293fas216_do_log(FAS216_Info *info, char target, char *fmt, va_list ap)294{295 static char buf[1024];296 297 vsnprintf(buf, sizeof(buf), fmt, ap);298 printk("scsi%d.%c: %s", info->host->host_no, target, buf);299}300 301static void fas216_log_command(FAS216_Info *info, int level,302 struct scsi_cmnd *SCpnt, char *fmt, ...)303{304 va_list args;305 306 if (level != 0 && !(level & level_mask))307 return;308 309 va_start(args, fmt);310 fas216_do_log(info, '0' + SCpnt->device->id, fmt, args);311 va_end(args);312 313 scsi_print_command(SCpnt);314}315 316static void317fas216_log_target(FAS216_Info *info, int level, int target, char *fmt, ...)318{319 va_list args;320 321 if (level != 0 && !(level & level_mask))322 return;323 324 if (target < 0)325 target = 'H';326 else327 target += '0';328 329 va_start(args, fmt);330 fas216_do_log(info, target, fmt, args);331 va_end(args);332 333 printk("\n");334}335 336static void fas216_log(FAS216_Info *info, int level, char *fmt, ...)337{338 va_list args;339 340 if (level != 0 && !(level & level_mask))341 return;342 343 va_start(args, fmt);344 fas216_do_log(info, fas216_target(info), fmt, args);345 va_end(args);346 347 printk("\n");348}349 350#define PH_SIZE 32351 352static struct { int stat, ssr, isr, ph; } ph_list[PH_SIZE];353static int ph_ptr;354 355static void add_debug_list(int stat, int ssr, int isr, int ph)356{357 ph_list[ph_ptr].stat = stat;358 ph_list[ph_ptr].ssr = ssr;359 ph_list[ph_ptr].isr = isr;360 ph_list[ph_ptr].ph = ph;361 362 ph_ptr = (ph_ptr + 1) & (PH_SIZE-1);363}364 365static struct { int command; void *from; } cmd_list[8];366static int cmd_ptr;367 368static void fas216_cmd(FAS216_Info *info, unsigned int command)369{370 cmd_list[cmd_ptr].command = command;371 cmd_list[cmd_ptr].from = __builtin_return_address(0);372 373 cmd_ptr = (cmd_ptr + 1) & 7;374 375 fas216_writeb(info, REG_CMD, command);376}377 378static void print_debug_list(void)379{380 int i;381 382 i = ph_ptr;383 384 printk(KERN_ERR "SCSI IRQ trail\n");385 do {386 printk(" %02x:%02x:%02x:%1x",387 ph_list[i].stat, ph_list[i].ssr,388 ph_list[i].isr, ph_list[i].ph);389 i = (i + 1) & (PH_SIZE - 1);390 if (((i ^ ph_ptr) & 7) == 0)391 printk("\n");392 } while (i != ph_ptr);393 if ((i ^ ph_ptr) & 7)394 printk("\n");395 396 i = cmd_ptr;397 printk(KERN_ERR "FAS216 commands: ");398 do {399 printk("%02x:%p ", cmd_list[i].command, cmd_list[i].from);400 i = (i + 1) & 7;401 } while (i != cmd_ptr);402 printk("\n");403}404 405static void fas216_done(FAS216_Info *info, unsigned int result);406 407/**408 * fas216_get_last_msg - retrive last message from the list409 * @info: interface to search410 * @pos: current fifo position411 *412 * Retrieve a last message from the list, using position in fifo.413 */414static inline unsigned short415fas216_get_last_msg(FAS216_Info *info, int pos)416{417 unsigned short packed_msg = NOP;418 struct message *msg;419 int msgnr = 0;420 421 while ((msg = msgqueue_getmsg(&info->scsi.msgs, msgnr++)) != NULL) {422 if (pos >= msg->fifo)423 break;424 }425 426 if (msg) {427 if (msg->msg[0] == EXTENDED_MESSAGE)428 packed_msg = EXTENDED_MESSAGE | msg->msg[2] << 8;429 else430 packed_msg = msg->msg[0];431 }432 433 fas216_log(info, LOG_MESSAGES,434 "Message: %04x found at position %02x\n", packed_msg, pos);435 436 return packed_msg;437}438 439/**440 * fas216_syncperiod - calculate STP register value441 * @info: state structure for interface connected to device442 * @ns: period in ns (between subsequent bytes)443 *444 * Calculate value to be loaded into the STP register for a given period445 * in ns. Returns a value suitable for REG_STP.446 */447static int fas216_syncperiod(FAS216_Info *info, int ns)448{449 int value = (info->ifcfg.clockrate * ns) / 1000;450 451 fas216_checkmagic(info);452 453 if (value < 4)454 value = 4;455 else if (value > 35)456 value = 35;457 458 return value & 31;459}460 461/**462 * fas216_set_sync - setup FAS216 chip for specified transfer period.463 * @info: state structure for interface connected to device464 * @target: target465 *466 * Correctly setup FAS216 chip for specified transfer period.467 * Notes : we need to switch the chip out of FASTSCSI mode if we have468 * a transfer period >= 200ns - otherwise the chip will violate469 * the SCSI timings.470 */471static void fas216_set_sync(FAS216_Info *info, int target)472{473 unsigned int cntl3;474 475 fas216_writeb(info, REG_SOF, info->device[target].sof);476 fas216_writeb(info, REG_STP, info->device[target].stp);477 478 cntl3 = info->scsi.cfg[2];479 if (info->device[target].period >= (200 / 4))480 cntl3 = cntl3 & ~CNTL3_FASTSCSI;481 482 fas216_writeb(info, REG_CNTL3, cntl3);483}484 485/* Synchronous transfer support486 *487 * Note: The SCSI II r10 spec says (5.6.12):488 *489 * (2) Due to historical problems with early host adapters that could490 * not accept an SDTR message, some targets may not initiate synchronous491 * negotiation after a power cycle as required by this standard. Host492 * adapters that support synchronous mode may avoid the ensuing failure493 * modes when the target is independently power cycled by initiating a494 * synchronous negotiation on each REQUEST SENSE and INQUIRY command.495 * This approach increases the SCSI bus overhead and is not recommended496 * for new implementations. The correct method is to respond to an497 * SDTR message with a MESSAGE REJECT message if the either the498 * initiator or target devices does not support synchronous transfers499 * or does not want to negotiate for synchronous transfers at the time.500 * Using the correct method assures compatibility with wide data501 * transfers and future enhancements.502 *503 * We will always initiate a synchronous transfer negotiation request on504 * every INQUIRY or REQUEST SENSE message, unless the target itself has505 * at some point performed a synchronous transfer negotiation request, or506 * we have synchronous transfers disabled for this device.507 */508 509/**510 * fas216_handlesync - Handle a synchronous transfer message511 * @info: state structure for interface512 * @msg: message from target513 *514 * Handle a synchronous transfer message from the target515 */516static void fas216_handlesync(FAS216_Info *info, char *msg)517{518 struct fas216_device *dev = &info->device[info->SCpnt->device->id];519 enum { sync, async, none, reject } res = none;520 521#ifdef SCSI2_SYNC522 switch (msg[0]) {523 case MESSAGE_REJECT:524 /* Synchronous transfer request failed.525 * Note: SCSI II r10:526 *527 * SCSI devices that are capable of synchronous528 * data transfers shall not respond to an SDTR529 * message with a MESSAGE REJECT message.530 *531 * Hence, if we get this condition, we disable532 * negotiation for this device.533 */534 if (dev->sync_state == neg_inprogress) {535 dev->sync_state = neg_invalid;536 res = async;537 }538 break;539 540 case EXTENDED_MESSAGE:541 switch (dev->sync_state) {542 /* We don't accept synchronous transfer requests.543 * Respond with a MESSAGE_REJECT to prevent a544 * synchronous transfer agreement from being reached.545 */546 case neg_invalid:547 res = reject;548 break;549 550 /* We were not negotiating a synchronous transfer,551 * but the device sent us a negotiation request.552 * Honour the request by sending back a SDTR553 * message containing our capability, limited by554 * the targets capability.555 */556 default:557 fas216_cmd(info, CMD_SETATN);558 if (msg[4] > info->ifcfg.sync_max_depth)559 msg[4] = info->ifcfg.sync_max_depth;560 if (msg[3] < 1000 / info->ifcfg.clockrate)561 msg[3] = 1000 / info->ifcfg.clockrate;562 563 msgqueue_flush(&info->scsi.msgs);564 msgqueue_addmsg(&info->scsi.msgs, 5,565 EXTENDED_MESSAGE, 3, EXTENDED_SDTR,566 msg[3], msg[4]);567 info->scsi.phase = PHASE_MSGOUT_EXPECT;568 569 /* This is wrong. The agreement is not in effect570 * until this message is accepted by the device571 */572 dev->sync_state = neg_targcomplete;573 res = sync;574 break;575 576 /* We initiated the synchronous transfer negotiation,577 * and have successfully received a response from the578 * target. The synchronous transfer agreement has been579 * reached. Note: if the values returned are out of our580 * bounds, we must reject the message.581 */582 case neg_inprogress:583 res = reject;584 if (msg[4] <= info->ifcfg.sync_max_depth &&585 msg[3] >= 1000 / info->ifcfg.clockrate) {586 dev->sync_state = neg_complete;587 res = sync;588 }589 break;590 }591 }592#else593 res = reject;594#endif595 596 switch (res) {597 case sync:598 dev->period = msg[3];599 dev->sof = msg[4];600 dev->stp = fas216_syncperiod(info, msg[3] * 4);601 fas216_set_sync(info, info->SCpnt->device->id);602 break;603 604 case reject:605 fas216_cmd(info, CMD_SETATN);606 msgqueue_flush(&info->scsi.msgs);607 msgqueue_addmsg(&info->scsi.msgs, 1, MESSAGE_REJECT);608 info->scsi.phase = PHASE_MSGOUT_EXPECT;609 fallthrough;610 611 case async:612 dev->period = info->ifcfg.asyncperiod / 4;613 dev->sof = 0;614 dev->stp = info->scsi.async_stp;615 fas216_set_sync(info, info->SCpnt->device->id);616 break;617 618 case none:619 break;620 }621}622 623/**624 * fas216_updateptrs - update data pointers after transfer suspended/paused625 * @info: interface's local pointer to update626 * @bytes_transferred: number of bytes transferred627 *628 * Update data pointers after transfer suspended/paused629 */630static void fas216_updateptrs(FAS216_Info *info, int bytes_transferred)631{632 struct scsi_pointer *SCp = &info->scsi.SCp;633 634 fas216_checkmagic(info);635 636 BUG_ON(bytes_transferred < 0);637 638 SCp->phase -= bytes_transferred;639 640 while (bytes_transferred != 0) {641 if (SCp->this_residual > bytes_transferred)642 break;643 /*644 * We have used up this buffer. Move on to the645 * next buffer.646 */647 bytes_transferred -= SCp->this_residual;648 if (!next_SCp(SCp) && bytes_transferred) {649 printk(KERN_WARNING "scsi%d.%c: out of buffers\n",650 info->host->host_no, '0' + info->SCpnt->device->id);651 return;652 }653 }654 655 SCp->this_residual -= bytes_transferred;656 if (SCp->this_residual)657 SCp->ptr += bytes_transferred;658 else659 SCp->ptr = NULL;660}661 662/**663 * fas216_pio - transfer data off of/on to card using programmed IO664 * @info: interface to transfer data to/from665 * @direction: direction to transfer data (DMA_OUT/DMA_IN)666 *667 * Transfer data off of/on to card using programmed IO.668 * Notes: this is incredibly slow.669 */670static void fas216_pio(FAS216_Info *info, fasdmadir_t direction)671{672 struct scsi_pointer *SCp = &info->scsi.SCp;673 674 fas216_checkmagic(info);675 676 if (direction == DMA_OUT)677 fas216_writeb(info, REG_FF, get_next_SCp_byte(SCp));678 else679 put_next_SCp_byte(SCp, fas216_readb(info, REG_FF));680 681 if (SCp->this_residual == 0)682 next_SCp(SCp);683}684 685static void fas216_set_stc(FAS216_Info *info, unsigned int length)686{687 fas216_writeb(info, REG_STCL, length);688 fas216_writeb(info, REG_STCM, length >> 8);689 fas216_writeb(info, REG_STCH, length >> 16);690}691 692static unsigned int fas216_get_ctc(FAS216_Info *info)693{694 return fas216_readb(info, REG_CTCL) +695 (fas216_readb(info, REG_CTCM) << 8) +696 (fas216_readb(info, REG_CTCH) << 16);697}698 699/**700 * fas216_cleanuptransfer - clean up after a transfer has completed.701 * @info: interface to clean up702 *703 * Update the data pointers according to the number of bytes transferred704 * on the SCSI bus.705 */706static void fas216_cleanuptransfer(FAS216_Info *info)707{708 unsigned long total, residual, fifo;709 fasdmatype_t dmatype = info->dma.transfer_type;710 711 info->dma.transfer_type = fasdma_none;712 713 /*714 * PIO transfers do not need to be cleaned up.715 */716 if (dmatype == fasdma_pio || dmatype == fasdma_none)717 return;718 719 if (dmatype == fasdma_real_all)720 total = info->scsi.SCp.phase;721 else722 total = info->scsi.SCp.this_residual;723 724 residual = fas216_get_ctc(info);725 726 fifo = fas216_readb(info, REG_CFIS) & CFIS_CF;727 728 fas216_log(info, LOG_BUFFER, "cleaning up from previous "729 "transfer: length 0x%06x, residual 0x%x, fifo %d",730 total, residual, fifo);731 732 /*733 * If we were performing Data-Out, the transfer counter734 * counts down each time a byte is transferred by the735 * host to the FIFO. This means we must include the736 * bytes left in the FIFO from the transfer counter.737 */738 if (info->scsi.phase == PHASE_DATAOUT)739 residual += fifo;740 741 fas216_updateptrs(info, total - residual);742}743 744/**745 * fas216_transfer - Perform a DMA/PIO transfer off of/on to card746 * @info: interface from which device disconnected from747 *748 * Start a DMA/PIO transfer off of/on to card749 */750static void fas216_transfer(FAS216_Info *info)751{752 fasdmadir_t direction;753 fasdmatype_t dmatype;754 755 fas216_log(info, LOG_BUFFER,756 "starttransfer: buffer %p length 0x%06x reqlen 0x%06x",757 info->scsi.SCp.ptr, info->scsi.SCp.this_residual,758 info->scsi.SCp.phase);759 760 if (!info->scsi.SCp.ptr) {761 fas216_log(info, LOG_ERROR, "null buffer passed to "762 "fas216_starttransfer");763 print_SCp(&info->scsi.SCp, "SCp: ", "\n");764 print_SCp(arm_scsi_pointer(info->SCpnt), "Cmnd SCp: ", "\n");765 return;766 }767 768 /*769 * If we have a synchronous transfer agreement in effect, we must770 * use DMA mode. If we are using asynchronous transfers, we may771 * use DMA mode or PIO mode.772 */773 if (info->device[info->SCpnt->device->id].sof)774 dmatype = fasdma_real_all;775 else776 dmatype = fasdma_pio;777 778 if (info->scsi.phase == PHASE_DATAOUT)779 direction = DMA_OUT;780 else781 direction = DMA_IN;782 783 if (info->dma.setup)784 dmatype = info->dma.setup(info->host, &info->scsi.SCp,785 direction, dmatype);786 info->dma.transfer_type = dmatype;787 788 if (dmatype == fasdma_real_all)789 fas216_set_stc(info, info->scsi.SCp.phase);790 else791 fas216_set_stc(info, info->scsi.SCp.this_residual);792 793 switch (dmatype) {794 case fasdma_pio:795 fas216_log(info, LOG_BUFFER, "PIO transfer");796 fas216_writeb(info, REG_SOF, 0);797 fas216_writeb(info, REG_STP, info->scsi.async_stp);798 fas216_cmd(info, CMD_TRANSFERINFO);799 fas216_pio(info, direction);800 break;801 802 case fasdma_pseudo:803 fas216_log(info, LOG_BUFFER, "pseudo transfer");804 fas216_cmd(info, CMD_TRANSFERINFO | CMD_WITHDMA);805 info->dma.pseudo(info->host, &info->scsi.SCp,806 direction, info->SCpnt->transfersize);807 break;808 809 case fasdma_real_block:810 fas216_log(info, LOG_BUFFER, "block dma transfer");811 fas216_cmd(info, CMD_TRANSFERINFO | CMD_WITHDMA);812 break;813 814 case fasdma_real_all:815 fas216_log(info, LOG_BUFFER, "total dma transfer");816 fas216_cmd(info, CMD_TRANSFERINFO | CMD_WITHDMA);817 break;818 819 default:820 fas216_log(info, LOG_BUFFER | LOG_ERROR,821 "invalid FAS216 DMA type");822 break;823 }824}825 826/**827 * fas216_stoptransfer - Stop a DMA transfer onto / off of the card828 * @info: interface from which device disconnected from829 *830 * Called when we switch away from DATA IN or DATA OUT phases.831 */832static void fas216_stoptransfer(FAS216_Info *info)833{834 fas216_checkmagic(info);835 836 if (info->dma.transfer_type == fasdma_real_all ||837 info->dma.transfer_type == fasdma_real_block)838 info->dma.stop(info->host, &info->scsi.SCp);839 840 fas216_cleanuptransfer(info);841 842 if (info->scsi.phase == PHASE_DATAIN) {843 unsigned int fifo;844 845 /*846 * If we were performing Data-In, then the FIFO counter847 * contains the number of bytes not transferred via DMA848 * from the on-board FIFO. Read them manually.849 */850 fifo = fas216_readb(info, REG_CFIS) & CFIS_CF;851 while (fifo && info->scsi.SCp.ptr) {852 *info->scsi.SCp.ptr = fas216_readb(info, REG_FF);853 fas216_updateptrs(info, 1);854 fifo--;855 }856 } else {857 /*858 * After a Data-Out phase, there may be unsent859 * bytes left in the FIFO. Flush them out.860 */861 fas216_cmd(info, CMD_FLUSHFIFO);862 }863}864 865static void fas216_aborttransfer(FAS216_Info *info)866{867 fas216_checkmagic(info);868 869 if (info->dma.transfer_type == fasdma_real_all ||870 info->dma.transfer_type == fasdma_real_block)871 info->dma.stop(info->host, &info->scsi.SCp);872 873 info->dma.transfer_type = fasdma_none;874 fas216_cmd(info, CMD_FLUSHFIFO);875}876 877static void fas216_kick(FAS216_Info *info);878 879/**880 * fas216_disconnected_intr - handle device disconnection881 * @info: interface from which device disconnected from882 *883 * Handle device disconnection884 */885static void fas216_disconnect_intr(FAS216_Info *info)886{887 unsigned long flags;888 889 fas216_checkmagic(info);890 891 fas216_log(info, LOG_CONNECT, "disconnect phase=%02x",892 info->scsi.phase);893 894 msgqueue_flush(&info->scsi.msgs);895 896 switch (info->scsi.phase) {897 case PHASE_SELECTION: /* while selecting - no target */898 case PHASE_SELSTEPS:899 fas216_done(info, DID_NO_CONNECT);900 break;901 902 case PHASE_MSGIN_DISCONNECT: /* message in - disconnecting */903 info->scsi.disconnectable = 1;904 info->scsi.phase = PHASE_IDLE;905 info->stats.disconnects += 1;906 spin_lock_irqsave(&info->host_lock, flags);907 if (info->scsi.phase == PHASE_IDLE)908 fas216_kick(info);909 spin_unlock_irqrestore(&info->host_lock, flags);910 break;911 912 case PHASE_DONE: /* at end of command - complete */913 fas216_done(info, DID_OK);914 break;915 916 case PHASE_MSGOUT: /* message out - possible ABORT message */917 if (fas216_get_last_msg(info, info->scsi.msgin_fifo) == ABORT) {918 info->scsi.aborting = 0;919 fas216_done(info, DID_ABORT);920 break;921 }922 fallthrough;923 924 default: /* huh? */925 printk(KERN_ERR "scsi%d.%c: unexpected disconnect in phase %s\n",926 info->host->host_no, fas216_target(info), fas216_drv_phase(info));927 print_debug_list();928 fas216_stoptransfer(info);929 fas216_done(info, DID_ERROR);930 break;931 }932}933 934/**935 * fas216_reselected_intr - start reconnection of a device936 * @info: interface which was reselected937 *938 * Start reconnection of a device939 */940static void941fas216_reselected_intr(FAS216_Info *info)942{943 unsigned int cfis, i;944 unsigned char msg[4];945 unsigned char target, lun, tag;946 947 fas216_checkmagic(info);948 949 WARN_ON(info->scsi.phase == PHASE_SELECTION ||950 info->scsi.phase == PHASE_SELSTEPS);951 952 cfis = fas216_readb(info, REG_CFIS);953 954 fas216_log(info, LOG_CONNECT, "reconnect phase=%02x cfis=%02x",955 info->scsi.phase, cfis);956 957 cfis &= CFIS_CF;958 959 if (cfis < 2 || cfis > 4) {960 printk(KERN_ERR "scsi%d.H: incorrect number of bytes after reselect\n",961 info->host->host_no);962 goto bad_message;963 }964 965 for (i = 0; i < cfis; i++)966 msg[i] = fas216_readb(info, REG_FF);967 968 if (!(msg[0] & (1 << info->host->this_id)) ||969 !(msg[1] & 0x80))970 goto initiator_error;971 972 target = msg[0] & ~(1 << info->host->this_id);973 target = ffs(target) - 1;974 lun = msg[1] & 7;975 tag = 0;976 977 if (cfis >= 3) {978 if (msg[2] != SIMPLE_QUEUE_TAG)979 goto initiator_error;980 981 tag = msg[3];982 }983 984 /* set up for synchronous transfers */985 fas216_writeb(info, REG_SDID, target);986 fas216_set_sync(info, target);987 msgqueue_flush(&info->scsi.msgs);988 989 fas216_log(info, LOG_CONNECT, "Reconnected: target %1x lun %1x tag %02x",990 target, lun, tag);991 992 if (info->scsi.disconnectable && info->SCpnt) {993 info->scsi.disconnectable = 0;994 if (info->SCpnt->device->id == target &&995 info->SCpnt->device->lun == lun &&996 scsi_cmd_to_rq(info->SCpnt)->tag == tag) {997 fas216_log(info, LOG_CONNECT, "reconnected previously executing command");998 } else {999 queue_add_cmd_tail(&info->queues.disconnected, info->SCpnt);1000 fas216_log(info, LOG_CONNECT, "had to move command to disconnected queue");1001 info->SCpnt = NULL;1002 }1003 }1004 if (!info->SCpnt) {1005 info->SCpnt = queue_remove_tgtluntag(&info->queues.disconnected,1006 target, lun, tag);1007 fas216_log(info, LOG_CONNECT, "had to get command");1008 }1009 1010 if (info->SCpnt) {1011 /*1012 * Restore data pointer from SAVED data pointer1013 */1014 info->scsi.SCp = *arm_scsi_pointer(info->SCpnt);1015 1016 fas216_log(info, LOG_CONNECT, "data pointers: [%p, %X]",1017 info->scsi.SCp.ptr, info->scsi.SCp.this_residual);1018 info->scsi.phase = PHASE_MSGIN;1019 } else {1020 /*1021 * Our command structure not found - abort the1022 * command on the target. Since we have no1023 * record of this command, we can't send1024 * an INITIATOR DETECTED ERROR message.1025 */1026 fas216_cmd(info, CMD_SETATN);1027 1028#if 01029 if (tag)1030 msgqueue_addmsg(&info->scsi.msgs, 2, ABORT_TAG, tag);1031 else1032#endif1033 msgqueue_addmsg(&info->scsi.msgs, 1, ABORT);1034 info->scsi.phase = PHASE_MSGOUT_EXPECT;1035 info->scsi.aborting = 1;1036 }1037 1038 fas216_cmd(info, CMD_MSGACCEPTED);1039 return;1040 1041 initiator_error:1042 printk(KERN_ERR "scsi%d.H: error during reselection: bytes",1043 info->host->host_no);1044 for (i = 0; i < cfis; i++)1045 printk(" %02x", msg[i]);1046 printk("\n");1047 bad_message:1048 fas216_cmd(info, CMD_SETATN);1049 msgqueue_flush(&info->scsi.msgs);1050 msgqueue_addmsg(&info->scsi.msgs, 1, INITIATOR_ERROR);1051 info->scsi.phase = PHASE_MSGOUT_EXPECT;1052 fas216_cmd(info, CMD_MSGACCEPTED);1053}1054 1055static void fas216_parse_message(FAS216_Info *info, unsigned char *message, int msglen)1056{1057 struct scsi_pointer *scsi_pointer;1058 int i;1059 1060 switch (message[0]) {1061 case COMMAND_COMPLETE:1062 if (msglen != 1)1063 goto unrecognised;1064 1065 printk(KERN_ERR "scsi%d.%c: command complete with no "1066 "status in MESSAGE_IN?\n",1067 info->host->host_no, fas216_target(info));1068 break;1069 1070 case SAVE_POINTERS:1071 if (msglen != 1)1072 goto unrecognised;1073 1074 /*1075 * Save current data pointer to SAVED data pointer1076 * SCSI II standard says that we must not acknowledge1077 * this until we have really saved pointers.1078 * NOTE: we DO NOT save the command nor status pointers1079 * as required by the SCSI II standard. These always1080 * point to the start of their respective areas.1081 */1082 scsi_pointer = arm_scsi_pointer(info->SCpnt);1083 *scsi_pointer = info->scsi.SCp;1084 scsi_pointer->sent_command = 0;1085 fas216_log(info, LOG_CONNECT | LOG_MESSAGES | LOG_BUFFER,1086 "save data pointers: [%p, %X]",1087 info->scsi.SCp.ptr, info->scsi.SCp.this_residual);1088 break;1089 1090 case RESTORE_POINTERS:1091 if (msglen != 1)1092 goto unrecognised;1093 1094 /*1095 * Restore current data pointer from SAVED data pointer1096 */1097 info->scsi.SCp = *arm_scsi_pointer(info->SCpnt);1098 fas216_log(info, LOG_CONNECT | LOG_MESSAGES | LOG_BUFFER,1099 "restore data pointers: [%p, 0x%x]",1100 info->scsi.SCp.ptr, info->scsi.SCp.this_residual);1101 break;1102 1103 case DISCONNECT:1104 if (msglen != 1)1105 goto unrecognised;1106 1107 info->scsi.phase = PHASE_MSGIN_DISCONNECT;1108 break;1109 1110 case MESSAGE_REJECT:1111 if (msglen != 1)1112 goto unrecognised;1113 1114 switch (fas216_get_last_msg(info, info->scsi.msgin_fifo)) {1115 case EXTENDED_MESSAGE | EXTENDED_SDTR << 8:1116 fas216_handlesync(info, message);1117 break;1118 1119 default:1120 fas216_log(info, 0, "reject, last message 0x%04x",1121 fas216_get_last_msg(info, info->scsi.msgin_fifo));1122 }1123 break;1124 1125 case NOP:1126 break;1127 1128 case EXTENDED_MESSAGE:1129 if (msglen < 3)1130 goto unrecognised;1131 1132 switch (message[2]) {1133 case EXTENDED_SDTR: /* Sync transfer negotiation request/reply */1134 fas216_handlesync(info, message);1135 break;1136 1137 default:1138 goto unrecognised;1139 }1140 break;1141 1142 default:1143 goto unrecognised;1144 }1145 return;1146 1147unrecognised:1148 fas216_log(info, 0, "unrecognised message, rejecting");1149 printk("scsi%d.%c: message was", info->host->host_no, fas216_target(info));1150 for (i = 0; i < msglen; i++)1151 printk("%s%02X", i & 31 ? " " : "\n ", message[i]);1152 printk("\n");1153 1154 /*1155 * Something strange seems to be happening here -1156 * I can't use SETATN since the chip gives me an1157 * invalid command interrupt when I do. Weird.1158 */1159fas216_cmd(info, CMD_NOP);1160fas216_dumpstate(info);1161 fas216_cmd(info, CMD_SETATN);1162 msgqueue_flush(&info->scsi.msgs);1163 msgqueue_addmsg(&info->scsi.msgs, 1, MESSAGE_REJECT);1164 info->scsi.phase = PHASE_MSGOUT_EXPECT;1165fas216_dumpstate(info);1166}1167 1168static int fas216_wait_cmd(FAS216_Info *info, int cmd)1169{1170 int tout;1171 int stat;1172 1173 fas216_cmd(info, cmd);1174 1175 for (tout = 1000; tout; tout -= 1) {1176 stat = fas216_readb(info, REG_STAT);1177 if (stat & (STAT_INT|STAT_PARITYERROR))1178 break;1179 udelay(1);1180 }1181 1182 return stat;1183}1184 1185static int fas216_get_msg_byte(FAS216_Info *info)1186{1187 unsigned int stat = fas216_wait_cmd(info, CMD_MSGACCEPTED);1188 1189 if ((stat & STAT_INT) == 0)1190 goto timedout;1191 1192 if ((stat & STAT_BUSMASK) != STAT_MESGIN)1193 goto unexpected_phase_change;1194 1195 fas216_readb(info, REG_INST);1196 1197 stat = fas216_wait_cmd(info, CMD_TRANSFERINFO);1198 1199 if ((stat & STAT_INT) == 0)1200 goto timedout;1201 1202 if (stat & STAT_PARITYERROR)1203 goto parity_error;1204 1205 if ((stat & STAT_BUSMASK) != STAT_MESGIN)1206 goto unexpected_phase_change;1207 1208 fas216_readb(info, REG_INST);1209 1210 return fas216_readb(info, REG_FF);1211 1212timedout:1213 fas216_log(info, LOG_ERROR, "timed out waiting for message byte");1214 return -1;1215 1216unexpected_phase_change:1217 fas216_log(info, LOG_ERROR, "unexpected phase change: status = %02x", stat);1218 return -2;1219 1220parity_error:1221 fas216_log(info, LOG_ERROR, "parity error during message in phase");1222 return -3;1223}1224 1225/**1226 * fas216_message - handle a function done interrupt from FAS216 chip1227 * @info: interface which caused function done interrupt1228 *1229 * Handle a function done interrupt from FAS216 chip1230 */1231static void fas216_message(FAS216_Info *info)1232{1233 unsigned char *message = info->scsi.message;1234 unsigned int msglen = 1;1235 int msgbyte = 0;1236 1237 fas216_checkmagic(info);1238 1239 message[0] = fas216_readb(info, REG_FF);1240 1241 if (message[0] == EXTENDED_MESSAGE) {1242 msgbyte = fas216_get_msg_byte(info);1243 1244 if (msgbyte >= 0) {1245 message[1] = msgbyte;1246 1247 for (msglen = 2; msglen < message[1] + 2; msglen++) {1248 msgbyte = fas216_get_msg_byte(info);1249 1250 if (msgbyte >= 0)1251 message[msglen] = msgbyte;1252 else1253 break;1254 }1255 }1256 }1257 1258 if (msgbyte == -3)1259 goto parity_error;1260 1261#ifdef DEBUG_MESSAGES1262 {1263 int i;1264 1265 printk("scsi%d.%c: message in: ",1266 info->host->host_no, fas216_target(info));1267 for (i = 0; i < msglen; i++)1268 printk("%02X ", message[i]);1269 printk("\n");1270 }1271#endif1272 1273 fas216_parse_message(info, message, msglen);1274 fas216_cmd(info, CMD_MSGACCEPTED);1275 return;1276 1277parity_error:1278 fas216_cmd(info, CMD_SETATN);1279 msgqueue_flush(&info->scsi.msgs);1280 msgqueue_addmsg(&info->scsi.msgs, 1, MSG_PARITY_ERROR);1281 info->scsi.phase = PHASE_MSGOUT_EXPECT;1282 fas216_cmd(info, CMD_MSGACCEPTED);1283 return;1284}1285 1286/**1287 * fas216_send_command - send command after all message bytes have been sent1288 * @info: interface which caused bus service1289 *1290 * Send a command to a target after all message bytes have been sent1291 */1292static void fas216_send_command(FAS216_Info *info)1293{1294 int i;1295 1296 fas216_checkmagic(info);1297 1298 fas216_cmd(info, CMD_NOP|CMD_WITHDMA);1299 fas216_cmd(info, CMD_FLUSHFIFO);1300 1301 /* load command */1302 for (i = info->scsi.SCp.sent_command; i < info->SCpnt->cmd_len; i++)1303 fas216_writeb(info, REG_FF, info->SCpnt->cmnd[i]);1304 1305 fas216_cmd(info, CMD_TRANSFERINFO);1306 1307 info->scsi.phase = PHASE_COMMAND;1308}1309 1310/**1311 * fas216_send_messageout - handle bus service to send a message1312 * @info: interface which caused bus service1313 *1314 * Handle bus service to send a message.1315 * Note: We do not allow the device to change the data direction!1316 */1317static void fas216_send_messageout(FAS216_Info *info, int start)1318{1319 unsigned int tot_msglen = msgqueue_msglength(&info->scsi.msgs);1320 1321 fas216_checkmagic(info);1322 1323 fas216_cmd(info, CMD_FLUSHFIFO);1324 1325 if (tot_msglen) {1326 struct message *msg;1327 int msgnr = 0;1328 1329 while ((msg = msgqueue_getmsg(&info->scsi.msgs, msgnr++)) != NULL) {1330 int i;1331 1332 for (i = start; i < msg->length; i++)1333 fas216_writeb(info, REG_FF, msg->msg[i]);1334 1335 msg->fifo = tot_msglen - (fas216_readb(info, REG_CFIS) & CFIS_CF);1336 start = 0;1337 }1338 } else1339 fas216_writeb(info, REG_FF, NOP);1340 1341 fas216_cmd(info, CMD_TRANSFERINFO);1342 1343 info->scsi.phase = PHASE_MSGOUT;1344}1345 1346/**1347 * fas216_busservice_intr - handle bus service interrupt from FAS216 chip1348 * @info: interface which caused bus service interrupt1349 * @stat: Status register contents1350 * @is: SCSI Status register contents1351 *1352 * Handle a bus service interrupt from FAS216 chip1353 */1354static void fas216_busservice_intr(FAS216_Info *info, unsigned int stat, unsigned int is)1355{1356 fas216_checkmagic(info);1357 1358 fas216_log(info, LOG_BUSSERVICE,1359 "bus service: stat=%02x is=%02x phase=%02x",1360 stat, is, info->scsi.phase);1361 1362 switch (info->scsi.phase) {1363 case PHASE_SELECTION:1364 if ((is & IS_BITS) != IS_MSGBYTESENT)1365 goto bad_is;1366 break;1367 1368 case PHASE_SELSTEPS:1369 switch (is & IS_BITS) {1370 case IS_SELARB:1371 case IS_MSGBYTESENT:1372 goto bad_is;1373 1374 case IS_NOTCOMMAND:1375 case IS_EARLYPHASE:1376 if ((stat & STAT_BUSMASK) == STAT_MESGIN)1377 break;1378 goto bad_is;1379 1380 case IS_COMPLETE:1381 break;1382 }1383 break;1384 1385 default:1386 break;1387 }1388 1389 fas216_cmd(info, CMD_NOP);1390 1391#define STATE(st,ph) ((ph) << 3 | (st))1392 /* This table describes the legal SCSI state transitions,1393 * as described by the SCSI II spec.1394 */1395 switch (STATE(stat & STAT_BUSMASK, info->scsi.phase)) {1396 case STATE(STAT_DATAIN, PHASE_SELSTEPS):/* Sel w/ steps -> Data In */1397 case STATE(STAT_DATAIN, PHASE_MSGOUT): /* Message Out -> Data In */1398 case STATE(STAT_DATAIN, PHASE_COMMAND): /* Command -> Data In */1399 case STATE(STAT_DATAIN, PHASE_MSGIN): /* Message In -> Data In */1400 info->scsi.phase = PHASE_DATAIN;1401 fas216_transfer(info);1402 return;1403 1404 case STATE(STAT_DATAIN, PHASE_DATAIN): /* Data In -> Data In */1405 case STATE(STAT_DATAOUT, PHASE_DATAOUT):/* Data Out -> Data Out */1406 fas216_cleanuptransfer(info);1407 fas216_transfer(info);1408 return;1409 1410 case STATE(STAT_DATAOUT, PHASE_SELSTEPS):/* Sel w/ steps-> Data Out */1411 case STATE(STAT_DATAOUT, PHASE_MSGOUT): /* Message Out -> Data Out */1412 case STATE(STAT_DATAOUT, PHASE_COMMAND):/* Command -> Data Out */1413 case STATE(STAT_DATAOUT, PHASE_MSGIN): /* Message In -> Data Out */1414 fas216_cmd(info, CMD_FLUSHFIFO);1415 info->scsi.phase = PHASE_DATAOUT;1416 fas216_transfer(info);1417 return;1418 1419 case STATE(STAT_STATUS, PHASE_DATAOUT): /* Data Out -> Status */1420 case STATE(STAT_STATUS, PHASE_DATAIN): /* Data In -> Status */1421 fas216_stoptransfer(info);1422 fallthrough;1423 1424 case STATE(STAT_STATUS, PHASE_SELSTEPS):/* Sel w/ steps -> Status */1425 case STATE(STAT_STATUS, PHASE_MSGOUT): /* Message Out -> Status */1426 case STATE(STAT_STATUS, PHASE_COMMAND): /* Command -> Status */1427 case STATE(STAT_STATUS, PHASE_MSGIN): /* Message In -> Status */1428 fas216_cmd(info, CMD_INITCMDCOMPLETE);1429 info->scsi.phase = PHASE_STATUS;1430 return;1431 1432 case STATE(STAT_MESGIN, PHASE_DATAOUT): /* Data Out -> Message In */1433 case STATE(STAT_MESGIN, PHASE_DATAIN): /* Data In -> Message In */1434 fas216_stoptransfer(info);1435 fallthrough;1436 1437 case STATE(STAT_MESGIN, PHASE_COMMAND): /* Command -> Message In */1438 case STATE(STAT_MESGIN, PHASE_SELSTEPS):/* Sel w/ steps -> Message In */1439 case STATE(STAT_MESGIN, PHASE_MSGOUT): /* Message Out -> Message In */1440 info->scsi.msgin_fifo = fas216_readb(info, REG_CFIS) & CFIS_CF;1441 fas216_cmd(info, CMD_FLUSHFIFO);1442 fas216_cmd(info, CMD_TRANSFERINFO);1443 info->scsi.phase = PHASE_MSGIN;1444 return;1445 1446 case STATE(STAT_MESGIN, PHASE_MSGIN):1447 info->scsi.msgin_fifo = fas216_readb(info, REG_CFIS) & CFIS_CF;1448 fas216_cmd(info, CMD_TRANSFERINFO);1449 return;1450 1451 case STATE(STAT_COMMAND, PHASE_MSGOUT): /* Message Out -> Command */1452 case STATE(STAT_COMMAND, PHASE_MSGIN): /* Message In -> Command */1453 fas216_send_command(info);1454 info->scsi.phase = PHASE_COMMAND;1455 return;1456 1457 1458 /*1459 * Selection -> Message Out1460 */1461 case STATE(STAT_MESGOUT, PHASE_SELECTION):1462 fas216_send_messageout(info, 1);1463 return;1464 1465 /*1466 * Message Out -> Message Out1467 */1468 case STATE(STAT_MESGOUT, PHASE_SELSTEPS):1469 case STATE(STAT_MESGOUT, PHASE_MSGOUT):1470 /*1471 * If we get another message out phase, this usually1472 * means some parity error occurred. Resend complete1473 * set of messages. If we have more than one byte to1474 * send, we need to assert ATN again.1475 */1476 if (info->device[info->SCpnt->device->id].parity_check) {1477 /*1478 * We were testing... good, the device1479 * supports parity checking.1480 */1481 info->device[info->SCpnt->device->id].parity_check = 0;1482 info->device[info->SCpnt->device->id].parity_enabled = 1;1483 fas216_writeb(info, REG_CNTL1, info->scsi.cfg[0]);1484 }1485 1486 if (msgqueue_msglength(&info->scsi.msgs) > 1)1487 fas216_cmd(info, CMD_SETATN);1488 fallthrough;1489 1490 /*1491 * Any -> Message Out1492 */1493 case STATE(STAT_MESGOUT, PHASE_MSGOUT_EXPECT):1494 fas216_send_messageout(info, 0);1495 return;1496 1497 /* Error recovery rules.1498 * These either attempt to abort or retry the operation.1499 * TODO: we need more of these1500 */1501 case STATE(STAT_COMMAND, PHASE_COMMAND):/* Command -> Command */1502 /* error - we've sent out all the command bytes1503 * we have.1504 * NOTE: we need SAVE DATA POINTERS/RESTORE DATA POINTERS1505 * to include the command bytes sent for this to work1506 * correctly.1507 */1508 printk(KERN_ERR "scsi%d.%c: "1509 "target trying to receive more command bytes\n",1510 info->host->host_no, fas216_target(info));1511 fas216_cmd(info, CMD_SETATN);1512 fas216_set_stc(info, 15);1513 fas216_cmd(info, CMD_PADBYTES | CMD_WITHDMA);1514 msgqueue_flush(&info->scsi.msgs);1515 msgqueue_addmsg(&info->scsi.msgs, 1, INITIATOR_ERROR);1516 info->scsi.phase = PHASE_MSGOUT_EXPECT;1517 return;1518 }1519 1520 if (info->scsi.phase == PHASE_MSGIN_DISCONNECT) {1521 printk(KERN_ERR "scsi%d.%c: disconnect message received, but bus service %s?\n",1522 info->host->host_no, fas216_target(info),1523 fas216_bus_phase(stat));1524 msgqueue_flush(&info->scsi.msgs);1525 fas216_cmd(info, CMD_SETATN);1526 msgqueue_addmsg(&info->scsi.msgs, 1, INITIATOR_ERROR);1527 info->scsi.phase = PHASE_MSGOUT_EXPECT;1528 info->scsi.aborting = 1;1529 fas216_cmd(info, CMD_TRANSFERINFO);1530 return;1531 }1532 printk(KERN_ERR "scsi%d.%c: bus phase %s after %s?\n",1533 info->host->host_no, fas216_target(info),1534 fas216_bus_phase(stat),1535 fas216_drv_phase(info));1536 print_debug_list();1537 return;1538 1539bad_is:1540 fas216_log(info, 0, "bus service at step %d?", is & IS_BITS);1541 fas216_dumpstate(info);1542 print_debug_list();1543 1544 fas216_done(info, DID_ERROR);1545}1546 1547/**1548 * fas216_funcdone_intr - handle a function done interrupt from FAS216 chip1549 * @info: interface which caused function done interrupt1550 * @stat: Status register contents1551 * @is: SCSI Status register contents1552 *1553 * Handle a function done interrupt from FAS216 chip1554 */1555static void fas216_funcdone_intr(FAS216_Info *info, unsigned int stat, unsigned int is)1556{1557 unsigned int fifo_len = fas216_readb(info, REG_CFIS) & CFIS_CF;1558 1559 fas216_checkmagic(info);1560 1561 fas216_log(info, LOG_FUNCTIONDONE,1562 "function done: stat=%02x is=%02x phase=%02x",1563 stat, is, info->scsi.phase);1564 1565 switch (info->scsi.phase) {1566 case PHASE_STATUS: /* status phase - read status and msg */1567 if (fifo_len != 2) {1568 fas216_log(info, 0, "odd number of bytes in FIFO: %d", fifo_len);1569 }1570 /*1571 * Read status then message byte.1572 */1573 info->scsi.SCp.Status = fas216_readb(info, REG_FF);1574 info->scsi.SCp.Message = fas216_readb(info, REG_FF);1575 info->scsi.phase = PHASE_DONE;1576 fas216_cmd(info, CMD_MSGACCEPTED);1577 break;1578 1579 case PHASE_IDLE:1580 case PHASE_SELECTION:1581 case PHASE_SELSTEPS:1582 break;1583 1584 case PHASE_MSGIN: /* message in phase */1585 if ((stat & STAT_BUSMASK) == STAT_MESGIN) {1586 info->scsi.msgin_fifo = fifo_len;1587 fas216_message(info);1588 break;1589 }1590 fallthrough;1591 1592 default:1593 fas216_log(info, 0, "internal phase %s for function done?"1594 " What do I do with this?",1595 fas216_target(info), fas216_drv_phase(info));1596 }1597}1598 1599static void fas216_bus_reset(FAS216_Info *info)1600{1601 neg_t sync_state;1602 int i;1603 1604 msgqueue_flush(&info->scsi.msgs);1605 1606 sync_state = neg_invalid;1607 1608#ifdef SCSI2_SYNC1609 if (info->ifcfg.capabilities & (FASCAP_DMA|FASCAP_PSEUDODMA))1610 sync_state = neg_wait;1611#endif1612 1613 info->scsi.phase = PHASE_IDLE;1614 info->SCpnt = NULL; /* bug! */1615 memset(&info->scsi.SCp, 0, sizeof(info->scsi.SCp));1616 1617 for (i = 0; i < 8; i++) {1618 info->device[i].disconnect_ok = info->ifcfg.disconnect_ok;1619 info->device[i].sync_state = sync_state;1620 info->device[i].period = info->ifcfg.asyncperiod / 4;1621 info->device[i].stp = info->scsi.async_stp;1622 info->device[i].sof = 0;1623 info->device[i].wide_xfer = 0;1624 }1625 1626 info->rst_bus_status = 1;1627 wake_up(&info->eh_wait);1628}1629 1630/**1631 * fas216_intr - handle interrupts to progress a command1632 * @info: interface to service1633 *1634 * Handle interrupts from the interface to progress a command1635 */1636irqreturn_t fas216_intr(FAS216_Info *info)1637{1638 unsigned char inst, is, stat;1639 int handled = IRQ_NONE;1640 1641 fas216_checkmagic(info);1642 1643 stat = fas216_readb(info, REG_STAT);1644 is = fas216_readb(info, REG_IS);1645 inst = fas216_readb(info, REG_INST);1646 1647 add_debug_list(stat, is, inst, info->scsi.phase);1648 1649 if (stat & STAT_INT) {1650 if (inst & INST_BUSRESET) {1651 fas216_log(info, 0, "bus reset detected");1652 fas216_bus_reset(info);1653 scsi_report_bus_reset(info->host, 0);1654 } else if (inst & INST_ILLEGALCMD) {1655 fas216_log(info, LOG_ERROR, "illegal command given\n");1656 fas216_dumpstate(info);1657 print_debug_list();1658 } else if (inst & INST_DISCONNECT)1659 fas216_disconnect_intr(info);1660 else if (inst & INST_RESELECTED) /* reselected */1661 fas216_reselected_intr(info);1662 else if (inst & INST_BUSSERVICE) /* bus service request */1663 fas216_busservice_intr(info, stat, is);1664 else if (inst & INST_FUNCDONE) /* function done */1665 fas216_funcdone_intr(info, stat, is);1666 else1667 fas216_log(info, 0, "unknown interrupt received:"1668 " phase %s inst %02X is %02X stat %02X",1669 fas216_drv_phase(info), inst, is, stat);1670 handled = IRQ_HANDLED;1671 }1672 return handled;1673}1674 1675static void __fas216_start_command(FAS216_Info *info, struct scsi_cmnd *SCpnt)1676{1677 int tot_msglen;1678 1679 /* following what the ESP driver says */1680 fas216_set_stc(info, 0);1681 fas216_cmd(info, CMD_NOP | CMD_WITHDMA);1682 1683 /* flush FIFO */1684 fas216_cmd(info, CMD_FLUSHFIFO);1685 1686 /* load bus-id and timeout */1687 fas216_writeb(info, REG_SDID, BUSID(SCpnt->device->id));1688 fas216_writeb(info, REG_STIM, info->ifcfg.select_timeout);1689 1690 /* synchronous transfers */1691 fas216_set_sync(info, SCpnt->device->id);1692 1693 tot_msglen = msgqueue_msglength(&info->scsi.msgs);1694 1695#ifdef DEBUG_MESSAGES1696 {1697 struct message *msg;1698 int msgnr = 0, i;1699 1700 printk("scsi%d.%c: message out: ",1701 info->host->host_no, '0' + SCpnt->device->id);1702 while ((msg = msgqueue_getmsg(&info->scsi.msgs, msgnr++)) != NULL) {1703 printk("{ ");1704 for (i = 0; i < msg->length; i++)1705 printk("%02x ", msg->msg[i]);1706 printk("} ");1707 }1708 printk("\n");1709 }1710#endif1711 1712 if (tot_msglen == 1 || tot_msglen == 3) {1713 /*1714 * We have an easy message length to send...1715 */1716 struct message *msg;1717 int msgnr = 0, i;1718 1719 info->scsi.phase = PHASE_SELSTEPS;1720 1721 /* load message bytes */1722 while ((msg = msgqueue_getmsg(&info->scsi.msgs, msgnr++)) != NULL) {1723 for (i = 0; i < msg->length; i++)1724 fas216_writeb(info, REG_FF, msg->msg[i]);1725 msg->fifo = tot_msglen - (fas216_readb(info, REG_CFIS) & CFIS_CF);1726 }1727 1728 /* load command */1729 for (i = 0; i < SCpnt->cmd_len; i++)1730 fas216_writeb(info, REG_FF, SCpnt->cmnd[i]);1731 1732 if (tot_msglen == 1)1733 fas216_cmd(info, CMD_SELECTATN);1734 else1735 fas216_cmd(info, CMD_SELECTATN3);1736 } else {1737 /*1738 * We have an unusual number of message bytes to send.1739 * Load first byte into fifo, and issue SELECT with ATN and1740 * stop steps.1741 */1742 struct message *msg = msgqueue_getmsg(&info->scsi.msgs, 0);1743 1744 fas216_writeb(info, REG_FF, msg->msg[0]);1745 msg->fifo = 1;1746 1747 fas216_cmd(info, CMD_SELECTATNSTOP);1748 }1749}1750 1751/*1752 * Decide whether we need to perform a parity test on this device.1753 * Can also be used to force parity error conditions during initial1754 * information transfer phase (message out) for test purposes.1755 */1756static int parity_test(FAS216_Info *info, int target)1757{1758#if 01759 if (target == 3) {1760 info->device[target].parity_check = 0;1761 return 1;1762 }1763#endif1764 return info->device[target].parity_check;1765}1766 1767static void fas216_start_command(FAS216_Info *info, struct scsi_cmnd *SCpnt)1768{1769 int disconnect_ok;1770 1771 /*1772 * claim host busy1773 */1774 info->scsi.phase = PHASE_SELECTION;1775 info->scsi.SCp = *arm_scsi_pointer(SCpnt);1776 info->SCpnt = SCpnt;1777 info->dma.transfer_type = fasdma_none;1778 1779 if (parity_test(info, SCpnt->device->id))1780 fas216_writeb(info, REG_CNTL1, info->scsi.cfg[0] | CNTL1_PTE);1781 else1782 fas216_writeb(info, REG_CNTL1, info->scsi.cfg[0]);1783 1784 /*1785 * Don't allow request sense commands to disconnect.1786 */1787 disconnect_ok = SCpnt->cmnd[0] != REQUEST_SENSE &&1788 info->device[SCpnt->device->id].disconnect_ok;1789 1790 /*1791 * build outgoing message bytes1792 */1793 msgqueue_flush(&info->scsi.msgs);1794 msgqueue_addmsg(&info->scsi.msgs, 1, IDENTIFY(disconnect_ok, SCpnt->device->lun));1795 1796 /*1797 * add tag message if required1798 */1799 if (SCpnt->device->simple_tags)1800 msgqueue_addmsg(&info->scsi.msgs, 2, SIMPLE_QUEUE_TAG,1801 scsi_cmd_to_rq(SCpnt)->tag);1802 1803 do {1804#ifdef SCSI2_SYNC1805 if ((info->device[SCpnt->device->id].sync_state == neg_wait ||1806 info->device[SCpnt->device->id].sync_state == neg_complete) &&1807 (SCpnt->cmnd[0] == REQUEST_SENSE ||1808 SCpnt->cmnd[0] == INQUIRY)) {1809 info->device[SCpnt->device->id].sync_state = neg_inprogress;1810 msgqueue_addmsg(&info->scsi.msgs, 5,1811 EXTENDED_MESSAGE, 3, EXTENDED_SDTR,1812 1000 / info->ifcfg.clockrate,1813 info->ifcfg.sync_max_depth);1814 break;1815 }1816#endif1817 } while (0);1818 1819 __fas216_start_command(info, SCpnt);1820}1821 1822static void fas216_allocate_tag(FAS216_Info *info, struct scsi_cmnd *SCpnt)1823{1824 set_bit(SCpnt->device->id * 8 +1825 (u8)(SCpnt->device->lun & 0x7), info->busyluns);1826 1827 info->stats.removes += 1;1828 switch (SCpnt->cmnd[0]) {1829 case WRITE_6:1830 case WRITE_10:1831 case WRITE_12:1832 info->stats.writes += 1;1833 break;1834 case READ_6:1835 case READ_10:1836 case READ_12:1837 info->stats.reads += 1;1838 break;1839 default:1840 info->stats.miscs += 1;1841 break;1842 }1843}1844 1845static void fas216_do_bus_device_reset(FAS216_Info *info,1846 struct scsi_cmnd *SCpnt)1847{1848 struct message *msg;1849 1850 /*1851 * claim host busy1852 */1853 info->scsi.phase = PHASE_SELECTION;1854 info->scsi.SCp = *arm_scsi_pointer(SCpnt);1855 info->SCpnt = SCpnt;1856 info->dma.transfer_type = fasdma_none;1857 1858 fas216_log(info, LOG_ERROR, "sending bus device reset");1859 1860 msgqueue_flush(&info->scsi.msgs);1861 msgqueue_addmsg(&info->scsi.msgs, 1, BUS_DEVICE_RESET);1862 1863 /* following what the ESP driver says */1864 fas216_set_stc(info, 0);1865 fas216_cmd(info, CMD_NOP | CMD_WITHDMA);1866 1867 /* flush FIFO */1868 fas216_cmd(info, CMD_FLUSHFIFO);1869 1870 /* load bus-id and timeout */1871 fas216_writeb(info, REG_SDID, BUSID(SCpnt->device->id));1872 fas216_writeb(info, REG_STIM, info->ifcfg.select_timeout);1873 1874 /* synchronous transfers */1875 fas216_set_sync(info, SCpnt->device->id);1876 1877 msg = msgqueue_getmsg(&info->scsi.msgs, 0);1878 1879 fas216_writeb(info, REG_FF, BUS_DEVICE_RESET);1880 msg->fifo = 1;1881 1882 fas216_cmd(info, CMD_SELECTATNSTOP);1883}1884 1885/**1886 * fas216_kick - kick a command to the interface1887 * @info: our host interface to kick1888 *1889 * Kick a command to the interface, interface should be idle.1890 * Notes: Interrupts are always disabled!1891 */1892static void fas216_kick(FAS216_Info *info)1893{1894 struct scsi_cmnd *SCpnt = NULL;1895#define TYPE_OTHER 01896#define TYPE_RESET 11897#define TYPE_QUEUE 21898 int where_from = TYPE_OTHER;1899 1900 fas216_checkmagic(info);1901 1902 /*1903 * Obtain the next command to process.1904 */1905 do {1906 if (info->rstSCpnt) {1907 SCpnt = info->rstSCpnt;1908 /* don't remove it */1909 where_from = TYPE_RESET;1910 break;1911 }1912 1913 if (info->reqSCpnt) {1914 SCpnt = info->reqSCpnt;1915 info->reqSCpnt = NULL;1916 break;1917 }1918 1919 if (info->origSCpnt) {1920 SCpnt = info->origSCpnt;1921 info->origSCpnt = NULL;1922 break;1923 }1924 1925 /* retrieve next command */1926 if (!SCpnt) {1927 SCpnt = queue_remove_exclude(&info->queues.issue,1928 info->busyluns);1929 where_from = TYPE_QUEUE;1930 break;1931 }1932 } while (0);1933 1934 if (!SCpnt) {1935 /*1936 * no command pending, so enable reselection.1937 */1938 fas216_cmd(info, CMD_ENABLESEL);1939 return;1940 }1941 1942 /*1943 * We're going to start a command, so disable reselection1944 */1945 fas216_cmd(info, CMD_DISABLESEL);1946 1947 if (info->scsi.disconnectable && info->SCpnt) {1948 fas216_log(info, LOG_CONNECT,1949 "moved command for %d to disconnected queue",1950 info->SCpnt->device->id);1951 queue_add_cmd_tail(&info->queues.disconnected, info->SCpnt);1952 info->scsi.disconnectable = 0;1953 info->SCpnt = NULL;1954 }1955 1956 fas216_log_command(info, LOG_CONNECT | LOG_MESSAGES, SCpnt,1957 "starting");1958 1959 switch (where_from) {1960 case TYPE_QUEUE:1961 fas216_allocate_tag(info, SCpnt);1962 fallthrough;1963 case TYPE_OTHER:1964 fas216_start_command(info, SCpnt);1965 break;1966 case TYPE_RESET:1967 fas216_do_bus_device_reset(info, SCpnt);1968 break;1969 }1970 1971 fas216_log(info, LOG_CONNECT, "select: data pointers [%p, %X]",1972 info->scsi.SCp.ptr, info->scsi.SCp.this_residual);1973 1974 /*1975 * should now get either DISCONNECT or1976 * (FUNCTION DONE with BUS SERVICE) interrupt1977 */1978}1979 1980/*1981 * Clean up from issuing a BUS DEVICE RESET message to a device.1982 */1983static void fas216_devicereset_done(FAS216_Info *info, struct scsi_cmnd *SCpnt,1984 unsigned int result)1985{1986 fas216_log(info, LOG_ERROR, "fas216 device reset complete");1987 1988 info->rstSCpnt = NULL;1989 info->rst_dev_status = 1;1990 wake_up(&info->eh_wait);1991}1992 1993/**1994 * fas216_rq_sns_done - Finish processing automatic request sense command1995 * @info: interface that completed1996 * @SCpnt: command that completed1997 * @result: driver byte of result1998 *1999 * Finish processing automatic request sense command2000 */2001static void fas216_rq_sns_done(FAS216_Info *info, struct scsi_cmnd *SCpnt,2002 unsigned int result)2003{2004 struct scsi_pointer *scsi_pointer = arm_scsi_pointer(SCpnt);2005 2006 fas216_log_target(info, LOG_CONNECT, SCpnt->device->id,2007 "request sense complete, result=0x%04x%02x%02x",2008 result, scsi_pointer->Message, scsi_pointer->Status);2009 2010 if (result != DID_OK || scsi_pointer->Status != SAM_STAT_GOOD)2011 /*2012 * Something went wrong. Make sure that we don't2013 * have valid data in the sense buffer that could2014 * confuse the higher levels.2015 */2016 memset(SCpnt->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE);2017//printk("scsi%d.%c: sense buffer: ", info->host->host_no, '0' + SCpnt->device->id);2018//{ int i; for (i = 0; i < 32; i++) printk("%02x ", SCpnt->sense_buffer[i]); printk("\n"); }2019 /*2020 * Note that we don't set SCpnt->result, since that should2021 * reflect the status of the command that we were asked by2022 * the upper layers to process. This would have been set2023 * correctly by fas216_std_done.2024 */2025 scsi_eh_restore_cmnd(SCpnt, &info->ses);2026 fas216_cmd_priv(SCpnt)->scsi_done(SCpnt);2027}2028 2029/**2030 * fas216_std_done - finish processing of standard command2031 * @info: interface that completed2032 * @SCpnt: command that completed2033 * @result: driver byte of result2034 *2035 * Finish processing of standard command2036 */2037static void2038fas216_std_done(FAS216_Info *info, struct scsi_cmnd *SCpnt, unsigned int result)2039{2040 struct scsi_pointer *scsi_pointer = arm_scsi_pointer(SCpnt);2041 2042 info->stats.fins += 1;2043 2044 set_host_byte(SCpnt, result);2045 if (result == DID_OK)2046 scsi_msg_to_host_byte(SCpnt, info->scsi.SCp.Message);2047 set_status_byte(SCpnt, info->scsi.SCp.Status);2048 2049 fas216_log_command(info, LOG_CONNECT, SCpnt,2050 "command complete, result=0x%08x", SCpnt->result);2051 2052 /*2053 * If the driver detected an error, we're all done.2054 */2055 if (get_host_byte(SCpnt) != DID_OK)2056 goto done;2057 2058 /*2059 * If the command returned CHECK_CONDITION or COMMAND_TERMINATED2060 * status, request the sense information.2061 */2062 if (get_status_byte(SCpnt) == SAM_STAT_CHECK_CONDITION ||2063 get_status_byte(SCpnt) == SAM_STAT_COMMAND_TERMINATED)2064 goto request_sense;2065 2066 /*2067 * If the command did not complete with GOOD status,2068 * we are all done here.2069 */2070 if (get_status_byte(SCpnt) != SAM_STAT_GOOD)2071 goto done;2072 2073 /*2074 * We have successfully completed a command. Make sure that2075 * we do not have any buffers left to transfer. The world2076 * is not perfect, and we seem to occasionally hit this.2077 * It can be indicative of a buggy driver, target or the upper2078 * levels of the SCSI code.2079 */2080 if (info->scsi.SCp.ptr) {2081 switch (SCpnt->cmnd[0]) {2082 case INQUIRY:2083 case START_STOP:2084 case MODE_SENSE:2085 break;2086 2087 default:2088 scmd_printk(KERN_ERR, SCpnt,2089 "incomplete data transfer detected: res=%08X ptr=%p len=%X\n",2090 SCpnt->result, info->scsi.SCp.ptr,2091 info->scsi.SCp.this_residual);2092 scsi_print_command(SCpnt);2093 set_host_byte(SCpnt, DID_ERROR);2094 goto request_sense;2095 }2096 }2097 2098done:2099 if (fas216_cmd_priv(SCpnt)->scsi_done) {2100 fas216_cmd_priv(SCpnt)->scsi_done(SCpnt);2101 return;2102 }2103 2104 panic("scsi%d.H: null scsi_done function in fas216_done",2105 info->host->host_no);2106 2107 2108request_sense:2109 if (SCpnt->cmnd[0] == REQUEST_SENSE)2110 goto done;2111 2112 scsi_eh_prep_cmnd(SCpnt, &info->ses, NULL, 0, ~0);2113 fas216_log_target(info, LOG_CONNECT, SCpnt->device->id,2114 "requesting sense");2115 init_SCp(SCpnt);2116 scsi_pointer->Message = 0;2117 scsi_pointer->Status = 0;2118 SCpnt->host_scribble = (void *)fas216_rq_sns_done;2119 2120 /*2121 * Place this command into the high priority "request2122 * sense" slot. This will be the very next command2123 * executed, unless a target connects to us.2124 */2125 if (info->reqSCpnt)2126 printk(KERN_WARNING "scsi%d.%c: losing request command\n",2127 info->host->host_no, '0' + SCpnt->device->id);2128 info->reqSCpnt = SCpnt;2129}2130 2131/**2132 * fas216_done - complete processing for current command2133 * @info: interface that completed2134 * @result: driver byte of result2135 *2136 * Complete processing for current command2137 */2138static void fas216_done(FAS216_Info *info, unsigned int result)2139{2140 void (*fn)(FAS216_Info *, struct scsi_cmnd *, unsigned int);2141 struct scsi_cmnd *SCpnt;2142 unsigned long flags;2143 2144 fas216_checkmagic(info);2145 2146 if (!info->SCpnt)2147 goto no_command;2148 2149 SCpnt = info->SCpnt;2150 info->SCpnt = NULL;2151 info->scsi.phase = PHASE_IDLE;2152 2153 if (info->scsi.aborting) {2154 fas216_log(info, 0, "uncaught abort - returning DID_ABORT");2155 result = DID_ABORT;2156 info->scsi.aborting = 0;2157 }2158 2159 /*2160 * Sanity check the completion - if we have zero bytes left2161 * to transfer, we should not have a valid pointer.2162 */2163 if (info->scsi.SCp.ptr && info->scsi.SCp.this_residual == 0) {2164 scmd_printk(KERN_INFO, SCpnt,2165 "zero bytes left to transfer, but buffer pointer still valid: ptr=%p len=%08x\n",2166 info->scsi.SCp.ptr, info->scsi.SCp.this_residual);2167 info->scsi.SCp.ptr = NULL;2168 scsi_print_command(SCpnt);2169 }2170 2171 /*2172 * Clear down this command as completed. If we need to request2173 * the sense information, fas216_kick will re-assert the busy2174 * status.2175 */2176 info->device[SCpnt->device->id].parity_check = 0;2177 clear_bit(SCpnt->device->id * 8 +2178 (u8)(SCpnt->device->lun & 0x7), info->busyluns);2179 2180 fn = (void (*)(FAS216_Info *, struct scsi_cmnd *, unsigned int))SCpnt->host_scribble;2181 fn(info, SCpnt, result);2182 2183 if (info->scsi.irq) {2184 spin_lock_irqsave(&info->host_lock, flags);2185 if (info->scsi.phase == PHASE_IDLE)2186 fas216_kick(info);2187 spin_unlock_irqrestore(&info->host_lock, flags);2188 }2189 return;2190 2191no_command:2192 panic("scsi%d.H: null command in fas216_done",2193 info->host->host_no);2194}2195 2196/**2197 * fas216_queue_command_internal - queue a command for the adapter to process2198 * @SCpnt: Command to queue2199 * @done: done function to call once command is complete2200 *2201 * Queue a command for adapter to process.2202 * Returns: 0 on success, else error.2203 * Notes: io_request_lock is held, interrupts are disabled.2204 */2205static int fas216_queue_command_internal(struct scsi_cmnd *SCpnt,2206 void (*done)(struct scsi_cmnd *))2207{2208 FAS216_Info *info = (FAS216_Info *)SCpnt->device->host->hostdata;2209 int result;2210 2211 fas216_checkmagic(info);2212 2213 fas216_log_command(info, LOG_CONNECT, SCpnt,2214 "received command (%p)", SCpnt);2215 2216 fas216_cmd_priv(SCpnt)->scsi_done = done;2217 SCpnt->host_scribble = (void *)fas216_std_done;2218 SCpnt->result = 0;2219 2220 init_SCp(SCpnt);2221 2222 info->stats.queues += 1;2223 2224 spin_lock(&info->host_lock);2225 2226 /*2227 * Add command into execute queue and let it complete under2228 * whatever scheme we're using.2229 */2230 result = !queue_add_cmd_ordered(&info->queues.issue, SCpnt);2231 2232 /*2233 * If we successfully added the command,2234 * kick the interface to get it moving.2235 */2236 if (result == 0 && info->scsi.phase == PHASE_IDLE)2237 fas216_kick(info);2238 spin_unlock(&info->host_lock);2239 2240 fas216_log_target(info, LOG_CONNECT, -1, "queue %s",2241 result ? "failure" : "success");2242 2243 return result;2244}2245 2246static int fas216_queue_command_lck(struct scsi_cmnd *SCpnt)2247{2248 return fas216_queue_command_internal(SCpnt, scsi_done);2249}2250 2251DEF_SCSI_QCMD(fas216_queue_command)2252 2253/**2254 * fas216_internal_done - trigger restart of a waiting thread in fas216_noqueue_command2255 * @SCpnt: Command to wake2256 *2257 * Trigger restart of a waiting thread in fas216_command2258 */2259static void fas216_internal_done(struct scsi_cmnd *SCpnt)2260{2261 FAS216_Info *info = (FAS216_Info *)SCpnt->device->host->hostdata;2262 2263 fas216_checkmagic(info);2264 2265 info->internal_done = 1;2266}2267 2268/**2269 * fas216_noqueue_command - process a command for the adapter.2270 * @SCpnt: Command to queue2271 *2272 * Queue a command for adapter to process.2273 * Returns: scsi result code.2274 * Notes: io_request_lock is held, interrupts are disabled.2275 */2276static int fas216_noqueue_command_lck(struct scsi_cmnd *SCpnt)2277{2278 FAS216_Info *info = (FAS216_Info *)SCpnt->device->host->hostdata;2279 2280 fas216_checkmagic(info);2281 2282 /*2283 * We should only be using this if we don't have an interrupt.2284 * Provide some "incentive" to use the queueing code.2285 */2286 BUG_ON(info->scsi.irq);2287 2288 info->internal_done = 0;2289 fas216_queue_command_internal(SCpnt, fas216_internal_done);2290 2291 /*2292 * This wastes time, since we can't return until the command is2293 * complete. We can't sleep either since we may get re-entered!2294 * However, we must re-enable interrupts, or else we'll be2295 * waiting forever.2296 */2297 spin_unlock_irq(info->host->host_lock);2298 2299 while (!info->internal_done) {2300 /*2301 * If we don't have an IRQ, then we must poll the card for2302 * it's interrupt, and use that to call this driver's2303 * interrupt routine. That way, we keep the command2304 * progressing. Maybe we can add some intelligence here2305 * and go to sleep if we know that the device is going2306 * to be some time (eg, disconnected).2307 */2308 if (fas216_readb(info, REG_STAT) & STAT_INT) {2309 spin_lock_irq(info->host->host_lock);2310 fas216_intr(info);2311 spin_unlock_irq(info->host->host_lock);2312 }2313 }2314 2315 spin_lock_irq(info->host->host_lock);2316 2317 scsi_done(SCpnt);2318 2319 return 0;2320}2321 2322DEF_SCSI_QCMD(fas216_noqueue_command)2323 2324/*2325 * Error handler timeout function. Indicate that we timed out,2326 * and wake up any error handler process so it can continue.2327 */2328static void fas216_eh_timer(struct timer_list *t)2329{2330 FAS216_Info *info = from_timer(info, t, eh_timer);2331 2332 fas216_log(info, LOG_ERROR, "error handling timed out\n");2333 2334 del_timer(&info->eh_timer);2335 2336 if (info->rst_bus_status == 0)2337 info->rst_bus_status = -1;2338 if (info->rst_dev_status == 0)2339 info->rst_dev_status = -1;2340 2341 wake_up(&info->eh_wait);2342}2343 2344enum res_find {2345 res_failed, /* not found */2346 res_success, /* command on issue queue */2347 res_hw_abort /* command on disconnected dev */2348};2349 2350/**2351 * fas216_do_abort - decide how to abort a command2352 * @SCpnt: command to abort2353 *2354 * Decide how to abort a command.2355 * Returns: abort status2356 */2357static enum res_find fas216_find_command(FAS216_Info *info,2358 struct scsi_cmnd *SCpnt)2359{2360 enum res_find res = res_failed;2361 2362 if (queue_remove_cmd(&info->queues.issue, SCpnt)) {2363 /*2364 * The command was on the issue queue, and has not been2365 * issued yet. We can remove the command from the queue,2366 * and acknowledge the abort. Neither the device nor the2367 * interface know about the command.2368 */2369 printk("on issue queue ");2370 2371 res = res_success;2372 } else if (queue_remove_cmd(&info->queues.disconnected, SCpnt)) {2373 /*2374 * The command was on the disconnected queue. We must2375 * reconnect with the device if possible, and send it2376 * an abort message.2377 */2378 printk("on disconnected queue ");2379 2380 res = res_hw_abort;2381 } else if (info->SCpnt == SCpnt) {2382 printk("executing ");2383 2384 switch (info->scsi.phase) {2385 /*2386 * If the interface is idle, and the command is 'disconnectable',2387 * then it is the same as on the disconnected queue.2388 */2389 case PHASE_IDLE:2390 if (info->scsi.disconnectable) {2391 info->scsi.disconnectable = 0;2392 info->SCpnt = NULL;2393 res = res_hw_abort;2394 }2395 break;2396 2397 default:2398 break;2399 }2400 } else if (info->origSCpnt == SCpnt) {2401 /*2402 * The command will be executed next, but a command2403 * is currently using the interface. This is similar to2404 * being on the issue queue, except the busylun bit has2405 * been set.2406 */2407 info->origSCpnt = NULL;2408 clear_bit(SCpnt->device->id * 8 +2409 (u8)(SCpnt->device->lun & 0x7), info->busyluns);2410 printk("waiting for execution ");2411 res = res_success;2412 } else2413 printk("unknown ");2414 2415 return res;2416}2417 2418/**2419 * fas216_eh_abort - abort this command2420 * @SCpnt: command to abort2421 *2422 * Abort this command.2423 * Returns: FAILED if unable to abort2424 * Notes: io_request_lock is taken, and irqs are disabled2425 */2426int fas216_eh_abort(struct scsi_cmnd *SCpnt)2427{2428 FAS216_Info *info = (FAS216_Info *)SCpnt->device->host->hostdata;2429 int result = FAILED;2430 2431 fas216_checkmagic(info);2432 2433 info->stats.aborts += 1;2434 2435 scmd_printk(KERN_WARNING, SCpnt, "abort command\n");2436 2437 print_debug_list();2438 fas216_dumpstate(info);2439 2440 switch (fas216_find_command(info, SCpnt)) {2441 /*2442 * We found the command, and cleared it out. Either2443 * the command is still known to be executing on the2444 * target, or the busylun bit is not set.2445 */2446 case res_success:2447 scmd_printk(KERN_WARNING, SCpnt, "abort %p success\n", SCpnt);2448 result = SUCCESS;2449 break;2450 2451 /*2452 * We need to reconnect to the target and send it an2453 * ABORT or ABORT_TAG message. We can only do this2454 * if the bus is free.2455 */2456 case res_hw_abort:2457 2458 /*2459 * We are unable to abort the command for some reason.2460 */2461 default:2462 case res_failed:2463 scmd_printk(KERN_WARNING, SCpnt, "abort %p failed\n", SCpnt);2464 break;2465 }2466 2467 return result;2468}2469 2470/**2471 * fas216_eh_device_reset - Reset the device associated with this command2472 * @SCpnt: command specifing device to reset2473 *2474 * Reset the device associated with this command.2475 * Returns: FAILED if unable to reset.2476 * Notes: We won't be re-entered, so we'll only have one device2477 * reset on the go at one time.2478 */2479int fas216_eh_device_reset(struct scsi_cmnd *SCpnt)2480{2481 FAS216_Info *info = (FAS216_Info *)SCpnt->device->host->hostdata;2482 unsigned long flags;2483 int i, res = FAILED, target = SCpnt->device->id;2484 2485 fas216_log(info, LOG_ERROR, "device reset for target %d", target);2486 2487 spin_lock_irqsave(&info->host_lock, flags);2488 2489 do {2490 /*2491 * If we are currently connected to a device, and2492 * it is the device we want to reset, there is2493 * nothing we can do here. Chances are it is stuck,2494 * and we need a bus reset.2495 */2496 if (info->SCpnt && !info->scsi.disconnectable &&2497 info->SCpnt->device->id == SCpnt->device->id)2498 break;2499 2500 /*2501 * We're going to be resetting this device. Remove2502 * all pending commands from the driver. By doing2503 * so, we guarantee that we won't touch the command2504 * structures except to process the reset request.2505 */2506 queue_remove_all_target(&info->queues.issue, target);2507 queue_remove_all_target(&info->queues.disconnected, target);2508 if (info->origSCpnt && info->origSCpnt->device->id == target)2509 info->origSCpnt = NULL;2510 if (info->reqSCpnt && info->reqSCpnt->device->id == target)2511 info->reqSCpnt = NULL;2512 for (i = 0; i < 8; i++)2513 clear_bit(target * 8 + i, info->busyluns);2514 2515 /*2516 * Hijack this SCSI command structure to send2517 * a bus device reset message to this device.2518 */2519 SCpnt->host_scribble = (void *)fas216_devicereset_done;2520 2521 info->rst_dev_status = 0;2522 info->rstSCpnt = SCpnt;2523 2524 if (info->scsi.phase == PHASE_IDLE)2525 fas216_kick(info);2526 2527 mod_timer(&info->eh_timer, jiffies + 30 * HZ);2528 spin_unlock_irqrestore(&info->host_lock, flags);2529 2530 /*2531 * Wait up to 30 seconds for the reset to complete.2532 */2533 wait_event(info->eh_wait, info->rst_dev_status);2534 2535 del_timer_sync(&info->eh_timer);2536 spin_lock_irqsave(&info->host_lock, flags);2537 info->rstSCpnt = NULL;2538 2539 if (info->rst_dev_status == 1)2540 res = SUCCESS;2541 } while (0);2542 2543 SCpnt->host_scribble = NULL;2544 spin_unlock_irqrestore(&info->host_lock, flags);2545 2546 fas216_log(info, LOG_ERROR, "device reset complete: %s\n",2547 res == SUCCESS ? "success" : "failed");2548 2549 return res;2550}2551 2552/**2553 * fas216_eh_bus_reset - Reset the bus associated with the command2554 * @SCpnt: command specifing bus to reset2555 *2556 * Reset the bus associated with the command.2557 * Returns: FAILED if unable to reset.2558 * Notes: Further commands are blocked.2559 */2560int fas216_eh_bus_reset(struct scsi_cmnd *SCpnt)2561{2562 FAS216_Info *info = (FAS216_Info *)SCpnt->device->host->hostdata;2563 unsigned long flags;2564 struct scsi_device *SDpnt;2565 2566 fas216_checkmagic(info);2567 fas216_log(info, LOG_ERROR, "resetting bus");2568 2569 info->stats.bus_resets += 1;2570 2571 spin_lock_irqsave(&info->host_lock, flags);2572 2573 /*2574 * Stop all activity on this interface.2575 */2576 fas216_aborttransfer(info);2577 fas216_writeb(info, REG_CNTL3, info->scsi.cfg[2]);2578 2579 /*2580 * Clear any pending interrupts.2581 */2582 while (fas216_readb(info, REG_STAT) & STAT_INT)2583 fas216_readb(info, REG_INST);2584 2585 info->rst_bus_status = 0;2586 2587 /*2588 * For each attached hard-reset device, clear out2589 * all command structures. Leave the running2590 * command in place.2591 */2592 shost_for_each_device(SDpnt, info->host) {2593 int i;2594 2595 if (SDpnt->soft_reset)2596 continue;2597 2598 queue_remove_all_target(&info->queues.issue, SDpnt->id);2599 queue_remove_all_target(&info->queues.disconnected, SDpnt->id);2600 if (info->origSCpnt && info->origSCpnt->device->id == SDpnt->id)2601 info->origSCpnt = NULL;2602 if (info->reqSCpnt && info->reqSCpnt->device->id == SDpnt->id)2603 info->reqSCpnt = NULL;2604 info->SCpnt = NULL;2605 2606 for (i = 0; i < 8; i++)2607 clear_bit(SDpnt->id * 8 + i, info->busyluns);2608 }2609 2610 info->scsi.phase = PHASE_IDLE;2611 2612 /*2613 * Reset the SCSI bus. Device cleanup happens in2614 * the interrupt handler.2615 */2616 fas216_cmd(info, CMD_RESETSCSI);2617 2618 mod_timer(&info->eh_timer, jiffies + HZ);2619 spin_unlock_irqrestore(&info->host_lock, flags);2620 2621 /*2622 * Wait one second for the interrupt.2623 */2624 wait_event(info->eh_wait, info->rst_bus_status);2625 del_timer_sync(&info->eh_timer);2626 2627 fas216_log(info, LOG_ERROR, "bus reset complete: %s\n",2628 info->rst_bus_status == 1 ? "success" : "failed");2629 2630 return info->rst_bus_status == 1 ? SUCCESS : FAILED;2631}2632 2633/**2634 * fas216_init_chip - Initialise FAS216 state after reset2635 * @info: state structure for interface2636 *2637 * Initialise FAS216 state after reset2638 */2639static void fas216_init_chip(FAS216_Info *info)2640{2641 unsigned int clock = ((info->ifcfg.clockrate - 1) / 5 + 1) & 7;2642 fas216_writeb(info, REG_CLKF, clock);2643 fas216_writeb(info, REG_CNTL1, info->scsi.cfg[0]);2644 fas216_writeb(info, REG_CNTL2, info->scsi.cfg[1]);2645 fas216_writeb(info, REG_CNTL3, info->scsi.cfg[2]);2646 fas216_writeb(info, REG_STIM, info->ifcfg.select_timeout);2647 fas216_writeb(info, REG_SOF, 0);2648 fas216_writeb(info, REG_STP, info->scsi.async_stp);2649 fas216_writeb(info, REG_CNTL1, info->scsi.cfg[0]);2650}2651 2652/**2653 * fas216_eh_host_reset - Reset the host associated with this command2654 * @SCpnt: command specifing host to reset2655 *2656 * Reset the host associated with this command.2657 * Returns: FAILED if unable to reset.2658 * Notes: io_request_lock is taken, and irqs are disabled2659 */2660int fas216_eh_host_reset(struct scsi_cmnd *SCpnt)2661{2662 FAS216_Info *info = (FAS216_Info *)SCpnt->device->host->hostdata;2663 2664 spin_lock_irq(info->host->host_lock);2665 2666 fas216_checkmagic(info);2667 2668 fas216_log(info, LOG_ERROR, "resetting host");2669 2670 /*2671 * Reset the SCSI chip.2672 */2673 fas216_cmd(info, CMD_RESETCHIP);2674 2675 /*2676 * Ugly ugly ugly!2677 * We need to release the host_lock and enable2678 * IRQs if we sleep, but we must relock and disable2679 * IRQs after the sleep.2680 */2681 spin_unlock_irq(info->host->host_lock);2682 msleep(50 * 1000/100);2683 spin_lock_irq(info->host->host_lock);2684 2685 /*2686 * Release the SCSI reset.2687 */2688 fas216_cmd(info, CMD_NOP);2689 2690 fas216_init_chip(info);2691 2692 spin_unlock_irq(info->host->host_lock);2693 return SUCCESS;2694}2695 2696#define TYPE_UNKNOWN 02697#define TYPE_NCR53C90 12698#define TYPE_NCR53C90A 22699#define TYPE_NCR53C9x 32700#define TYPE_Am53CF94 42701#define TYPE_EmFAS216 52702#define TYPE_QLFAS216 62703 2704static char *chip_types[] = {2705 "unknown",2706 "NS NCR53C90",2707 "NS NCR53C90A",2708 "NS NCR53C9x",2709 "AMD Am53CF94",2710 "Emulex FAS216",2711 "QLogic FAS216"2712};2713 2714static int fas216_detect_type(FAS216_Info *info)2715{2716 int family, rev;2717 2718 /*2719 * Reset the chip.2720 */2721 fas216_writeb(info, REG_CMD, CMD_RESETCHIP);2722 udelay(50);2723 fas216_writeb(info, REG_CMD, CMD_NOP);2724 2725 /*2726 * Check to see if control reg 2 is present.2727 */2728 fas216_writeb(info, REG_CNTL3, 0);2729 fas216_writeb(info, REG_CNTL2, CNTL2_S2FE);2730 2731 /*2732 * If we are unable to read back control reg 22733 * correctly, it is not present, and we have a2734 * NCR53C90.2735 */2736 if ((fas216_readb(info, REG_CNTL2) & (~0xe0)) != CNTL2_S2FE)2737 return TYPE_NCR53C90;2738 2739 /*2740 * Now, check control register 32741 */2742 fas216_writeb(info, REG_CNTL2, 0);2743 fas216_writeb(info, REG_CNTL3, 0);2744 fas216_writeb(info, REG_CNTL3, 5);2745 2746 /*2747 * If we are unable to read the register back2748 * correctly, we have a NCR53C90A2749 */2750 if (fas216_readb(info, REG_CNTL3) != 5)2751 return TYPE_NCR53C90A;2752 2753 /*2754 * Now read the ID from the chip.2755 */2756 fas216_writeb(info, REG_CNTL3, 0);2757 2758 fas216_writeb(info, REG_CNTL3, CNTL3_ADIDCHK);2759 fas216_writeb(info, REG_CNTL3, 0);2760 2761 fas216_writeb(info, REG_CMD, CMD_RESETCHIP);2762 udelay(50);2763 fas216_writeb(info, REG_CMD, CMD_WITHDMA | CMD_NOP);2764 2765 fas216_writeb(info, REG_CNTL2, CNTL2_ENF);2766 fas216_writeb(info, REG_CMD, CMD_RESETCHIP);2767 udelay(50);2768 fas216_writeb(info, REG_CMD, CMD_NOP);2769 2770 rev = fas216_readb(info, REG_ID);2771 family = rev >> 3;2772 rev &= 7;2773 2774 switch (family) {2775 case 0x01:2776 if (rev == 4)2777 return TYPE_Am53CF94;2778 break;2779 2780 case 0x02:2781 switch (rev) {2782 case 2:2783 return TYPE_EmFAS216;2784 case 3:2785 return TYPE_QLFAS216;2786 }2787 break;2788 2789 default:2790 break;2791 }2792 printk("family %x rev %x\n", family, rev);2793 return TYPE_NCR53C9x;2794}2795 2796/**2797 * fas216_reset_state - Initialise driver internal state2798 * @info: state to initialise2799 *2800 * Initialise driver internal state2801 */2802static void fas216_reset_state(FAS216_Info *info)2803{2804 int i;2805 2806 fas216_checkmagic(info);2807 2808 fas216_bus_reset(info);2809 2810 /*2811 * Clear out all stale info in our state structure2812 */2813 memset(info->busyluns, 0, sizeof(info->busyluns));2814 info->scsi.disconnectable = 0;2815 info->scsi.aborting = 0;2816 2817 for (i = 0; i < 8; i++) {2818 info->device[i].parity_enabled = 0;2819 info->device[i].parity_check = 1;2820 }2821 2822 /*2823 * Drain all commands on disconnected queue2824 */2825 while (queue_remove(&info->queues.disconnected) != NULL);2826 2827 /*2828 * Remove executing commands.2829 */2830 info->SCpnt = NULL;2831 info->reqSCpnt = NULL;2832 info->rstSCpnt = NULL;2833 info->origSCpnt = NULL;2834}2835 2836/**2837 * fas216_init - initialise FAS/NCR/AMD SCSI structures.2838 * @host: a driver-specific filled-out structure2839 *2840 * Initialise FAS/NCR/AMD SCSI structures.2841 * Returns: 0 on success2842 */2843int fas216_init(struct Scsi_Host *host)2844{2845 FAS216_Info *info = (FAS216_Info *)host->hostdata;2846 2847 info->magic_start = MAGIC;2848 info->magic_end = MAGIC;2849 info->host = host;2850 info->scsi.cfg[0] = host->this_id | CNTL1_PERE;2851 info->scsi.cfg[1] = CNTL2_ENF | CNTL2_S2FE;2852 info->scsi.cfg[2] = info->ifcfg.cntl3 |2853 CNTL3_ADIDCHK | CNTL3_QTAG | CNTL3_G2CB | CNTL3_LBTM;2854 info->scsi.async_stp = fas216_syncperiod(info, info->ifcfg.asyncperiod);2855 2856 info->rst_dev_status = -1;2857 info->rst_bus_status = -1;2858 init_waitqueue_head(&info->eh_wait);2859 timer_setup(&info->eh_timer, fas216_eh_timer, 0);2860 2861 spin_lock_init(&info->host_lock);2862 2863 memset(&info->stats, 0, sizeof(info->stats));2864 2865 msgqueue_initialise(&info->scsi.msgs);2866 2867 if (!queue_initialise(&info->queues.issue))2868 return -ENOMEM;2869 2870 if (!queue_initialise(&info->queues.disconnected)) {2871 queue_free(&info->queues.issue);2872 return -ENOMEM;2873 }2874 2875 return 0;2876}2877 2878/**2879 * fas216_add - initialise FAS/NCR/AMD SCSI ic.2880 * @host: a driver-specific filled-out structure2881 * @dev: parent device2882 *2883 * Initialise FAS/NCR/AMD SCSI ic.2884 * Returns: 0 on success2885 */2886int fas216_add(struct Scsi_Host *host, struct device *dev)2887{2888 FAS216_Info *info = (FAS216_Info *)host->hostdata;2889 int type, ret;2890 2891 if (info->ifcfg.clockrate <= 10 || info->ifcfg.clockrate > 40) {2892 printk(KERN_CRIT "fas216: invalid clock rate %u MHz\n",2893 info->ifcfg.clockrate);2894 return -EINVAL;2895 }2896 2897 fas216_reset_state(info);2898 type = fas216_detect_type(info);2899 info->scsi.type = chip_types[type];2900 2901 udelay(300);2902 2903 /*2904 * Initialise the chip correctly.2905 */2906 fas216_init_chip(info);2907 2908 /*2909 * Reset the SCSI bus. We don't want to see2910 * the resulting reset interrupt, so mask it2911 * out.2912 */2913 fas216_writeb(info, REG_CNTL1, info->scsi.cfg[0] | CNTL1_DISR);2914 fas216_writeb(info, REG_CMD, CMD_RESETSCSI);2915 2916 /*2917 * scsi standard says wait 250ms2918 */2919 spin_unlock_irq(info->host->host_lock);2920 msleep(100*1000/100);2921 spin_lock_irq(info->host->host_lock);2922 2923 fas216_writeb(info, REG_CNTL1, info->scsi.cfg[0]);2924 fas216_readb(info, REG_INST);2925 2926 fas216_checkmagic(info);2927 2928 ret = scsi_add_host(host, dev);2929 if (ret)2930 fas216_writeb(info, REG_CMD, CMD_RESETCHIP);2931 else2932 scsi_scan_host(host);2933 2934 return ret;2935}2936 2937void fas216_remove(struct Scsi_Host *host)2938{2939 FAS216_Info *info = (FAS216_Info *)host->hostdata;2940 2941 fas216_checkmagic(info);2942 scsi_remove_host(host);2943 2944 fas216_writeb(info, REG_CMD, CMD_RESETCHIP);2945 scsi_host_put(host);2946}2947 2948/**2949 * fas216_release - release all resources for FAS/NCR/AMD SCSI ic.2950 * @host: a driver-specific filled-out structure2951 *2952 * release all resources and put everything to bed for FAS/NCR/AMD SCSI ic.2953 */2954void fas216_release(struct Scsi_Host *host)2955{2956 FAS216_Info *info = (FAS216_Info *)host->hostdata;2957 2958 queue_free(&info->queues.disconnected);2959 queue_free(&info->queues.issue);2960}2961 2962void fas216_print_host(FAS216_Info *info, struct seq_file *m)2963{2964 seq_printf(m,2965 "\n"2966 "Chip : %s\n"2967 " Address: 0x%p\n"2968 " IRQ : %d\n"2969 " DMA : %d\n",2970 info->scsi.type, info->scsi.io_base,2971 info->scsi.irq, info->scsi.dma);2972}2973 2974void fas216_print_stats(FAS216_Info *info, struct seq_file *m)2975{2976 seq_printf(m, "\n"2977 "Command Statistics:\n"2978 " Queued : %u\n"2979 " Issued : %u\n"2980 " Completed : %u\n"2981 " Reads : %u\n"2982 " Writes : %u\n"2983 " Others : %u\n"2984 " Disconnects: %u\n"2985 " Aborts : %u\n"2986 " Bus resets : %u\n"2987 " Host resets: %u\n",2988 info->stats.queues, info->stats.removes,2989 info->stats.fins, info->stats.reads,2990 info->stats.writes, info->stats.miscs,2991 info->stats.disconnects, info->stats.aborts,2992 info->stats.bus_resets, info->stats.host_resets);2993}2994 2995void fas216_print_devices(FAS216_Info *info, struct seq_file *m)2996{2997 struct fas216_device *dev;2998 struct scsi_device *scd;2999 3000 seq_puts(m, "Device/Lun TaggedQ Parity Sync\n");3001 3002 shost_for_each_device(scd, info->host) {3003 dev = &info->device[scd->id];3004 seq_printf(m, " %d/%llu ", scd->id, scd->lun);3005 if (scd->tagged_supported)3006 seq_printf(m, "%3sabled ",3007 scd->simple_tags ? "en" : "dis");3008 else3009 seq_puts(m, "unsupported ");3010 3011 seq_printf(m, "%3sabled ", dev->parity_enabled ? "en" : "dis");3012 3013 if (dev->sof)3014 seq_printf(m, "offset %d, %d ns\n",3015 dev->sof, dev->period * 4);3016 else3017 seq_puts(m, "async\n");3018 }3019}3020 3021EXPORT_SYMBOL(fas216_init);3022EXPORT_SYMBOL(fas216_add);3023EXPORT_SYMBOL(fas216_queue_command);3024EXPORT_SYMBOL(fas216_noqueue_command);3025EXPORT_SYMBOL(fas216_intr);3026EXPORT_SYMBOL(fas216_remove);3027EXPORT_SYMBOL(fas216_release);3028EXPORT_SYMBOL(fas216_eh_abort);3029EXPORT_SYMBOL(fas216_eh_device_reset);3030EXPORT_SYMBOL(fas216_eh_bus_reset);3031EXPORT_SYMBOL(fas216_eh_host_reset);3032EXPORT_SYMBOL(fas216_print_host);3033EXPORT_SYMBOL(fas216_print_stats);3034EXPORT_SYMBOL(fas216_print_devices);3035 3036MODULE_AUTHOR("Russell King");3037MODULE_DESCRIPTION("Generic FAS216/NCR53C9x driver core");3038MODULE_LICENSE("GPL");3039