* added 0.99 linux version
[mascara-docs.git] / i386 / linux / linux-2.3.21 / drivers / acorn / scsi / fas216.c
blobb54080ead9a09a3eeaef8796e0d280e837be66e4
1 /*
2 * linux/arch/arm/drivers/scsi/fas216.c
4 * Copyright (C) 1997 Russell King
6 * Based on information in qlogicfas.c by Tom Zerucha, Michael Griffith, and
7 * other sources, including:
8 * the AMD Am53CF94 data sheet
10 * This is a generic driver. To use it, have a look at cumana_2.c. You
11 * should define your own structure that overlays FAS216_Info, eg:
12 * struct my_host_data {
13 * FAS216_Info info;
14 * ... my host specific data ...
15 * };
17 * Changelog:
18 * 30-08-1997 RMK Created
19 * 14-09-1997 RMK Started disconnect support
20 * 08-02-1998 RMK Corrected real DMA support
21 * 15-02-1998 RMK Started sync xfer support
22 * 06-04-1998 RMK Tightened conditions for printing incomplete
23 * transfers
24 * 02-05-1998 RMK Added extra checks in fas216_reset
25 * 24-05-1998 RMK Fixed synchronous transfers with period >= 200ns
26 * 27-06-1998 RMK Changed asm/delay.h to linux/delay.h
27 * 26-08-1998 RMK Improved message support wrt MESSAGE_REJECT
29 * Todo:
30 * - allow individual devices to enable sync xfers.
33 #include <linux/module.h>
34 #include <linux/blk.h>
35 #include <linux/kernel.h>
36 #include <linux/string.h>
37 #include <linux/ioport.h>
38 #include <linux/sched.h>
39 #include <linux/proc_fs.h>
40 #include <linux/unistd.h>
41 #include <linux/stat.h>
42 #include <linux/delay.h>
44 #include <asm/dma.h>
45 #include <asm/io.h>
46 #include <asm/irq.h>
47 #include <asm/ecard.h>
49 #define FAS216_C
51 #include "../../scsi/scsi.h"
52 #include "../../scsi/hosts.h"
53 #include "fas216.h"
55 MODULE_AUTHOR("Russell King");
56 MODULE_DESCRIPTION("Generic FAS216/NCR53C9x driver");
58 #define VER_MAJOR 0
59 #define VER_MINOR 0
60 #define VER_PATCH 5
62 #define SCSI2_TAG
64 /* NOTE: SCSI2 Synchronous transfers *require* DMA according to
65 * the data sheet. This restriction is crazy, especially when
66 * you only want to send 16 bytes! What were the guys who
67 * designed this chip on at that time? Did they read the SCSI2
68 * spec at all? The following sections are taken from the SCSI2
69 * standard (s2r10) concerning this:
71 * > IMPLEMENTORS NOTES:
72 * > (1) Re-negotiation at every selection is not recommended, since a
73 * > significant performance impact is likely.
75 * > The implied synchronous agreement shall remain in effect until a BUS DEVICE
76 * > RESET message is received, until a hard reset condition occurs, or until one
77 * > of the two SCSI devices elects to modify the agreement. The default data
78 * > transfer mode is asynchronous data transfer mode. The default data transfer
79 * > mode is entered at power on, after a BUS DEVICE RESET message, or after a hard
80 * > reset condition.
82 * In total, this means that once you have elected to use synchronous
83 * transfers, you must always use DMA.
85 * I was thinking that this was a good chip until I found this restriction ;(
87 #define SCSI2_SYNC
89 #define SCSI2_WIDE
91 #undef DEBUG_CONNECT
92 #undef DEBUG_BUSSERVICE
93 #undef DEBUG_FUNCTIONDONE
94 #undef DEBUG_MESSAGES
96 #undef CHECK_STRUCTURE
98 static struct { int stat, ssr, isr, ph; } list[8];
99 static int ptr;
101 static void fas216_dumpstate(FAS216_Info *info)
103 unsigned char is, stat, inst;
105 is = inb(REG_IS(info));
106 stat = inb(REG_STAT(info));
107 inst = inb(REG_INST(info));
109 printk("FAS216: CTCL=%02X CTCM=%02X CMD=%02X STAT=%02X"
110 " INST=%02X IS=%02X CFIS=%02X",
111 inb(REG_CTCL(info)), inb(REG_CTCM(info)),
112 inb(REG_CMD(info)), stat, inst, is,
113 inb(REG_CFIS(info)));
114 printk(" CNTL1=%02X CNTL2=%02X CNTL3=%02X CTCH=%02X\n",
115 inb(REG_CNTL1(info)), inb(REG_CNTL2(info)),
116 inb(REG_CNTL3(info)), inb(REG_CTCH(info)));
119 static void fas216_dumpinfo(FAS216_Info *info)
121 static int used = 0;
122 int i;
124 if (used++)
125 return;
127 printk("FAS216_Info=\n");
128 printk(" { magic_start=%lX host=%p SCpnt=%p origSCpnt=%p\n",
129 info->magic_start, info->host, info->SCpnt,
130 info->origSCpnt);
131 printk(" scsi={ io_port=%X io_shift=%X irq=%X cfg={ %X %X %X %X }\n",
132 info->scsi.io_port, info->scsi.io_shift, info->scsi.irq,
133 info->scsi.cfg[0], info->scsi.cfg[1], info->scsi.cfg[2],
134 info->scsi.cfg[3]);
135 printk(" type=%p phase=%X reconnected={ target=%d lun=%d tag=%d }\n",
136 info->scsi.type, info->scsi.phase,
137 info->scsi.reconnected.target,
138 info->scsi.reconnected.lun, info->scsi.reconnected.tag);
139 printk(" SCp={ ptr=%p this_residual=%X buffer=%p buffers_residual=%X }\n",
140 info->scsi.SCp.ptr, info->scsi.SCp.this_residual,
141 info->scsi.SCp.buffer, info->scsi.SCp.buffers_residual);
142 printk(" msgs async_stp=%X disconnectable=%d aborting=%d }\n",
143 info->scsi.async_stp,
144 info->scsi.disconnectable, info->scsi.aborting);
145 printk(" stats={ queues=%X removes=%X fins=%X reads=%X writes=%X miscs=%X\n"
146 " disconnects=%X aborts=%X resets=%X }\n",
147 info->stats.queues, info->stats.removes, info->stats.fins,
148 info->stats.reads, info->stats.writes, info->stats.miscs,
149 info->stats.disconnects, info->stats.aborts, info->stats.resets);
150 printk(" ifcfg={ clockrate=%X select_timeout=%X asyncperiod=%X sync_max_depth=%X }\n",
151 info->ifcfg.clockrate, info->ifcfg.select_timeout,
152 info->ifcfg.asyncperiod, info->ifcfg.sync_max_depth);
153 for (i = 0; i < 8; i++) {
154 printk(" busyluns[%d]=%X dev[%d]={ disconnect_ok=%d stp=%X sof=%X sync_state=%X }\n",
155 i, info->busyluns[i], i,
156 info->device[i].disconnect_ok, info->device[i].stp,
157 info->device[i].sof, info->device[i].sync_state);
159 printk(" dma={ transfer_type=%X setup=%p pseudo=%p stop=%p }\n",
160 info->dma.transfer_type, info->dma.setup,
161 info->dma.pseudo, info->dma.stop);
162 printk(" internal_done=%X magic_end=%lX }\n",
163 info->internal_done, info->magic_end);
166 #ifdef CHECK_STRUCTURE
167 static void fas216_checkmagic(FAS216_Info *info, const char *func)
169 int corruption = 0;
170 if (info->magic_start != MAGIC) {
171 printk(KERN_CRIT "FAS216 Error: magic at start corrupted\n");
172 corruption++;
174 if (info->magic_end != MAGIC) {
175 printk(KERN_CRIT "FAS216 Error: magic at end corrupted\n");
176 corruption++;
178 if (corruption) {
179 fas216_dumpinfo(info);
180 panic("scsi memory space corrupted in %s", func);
183 #else
184 #define fas216_checkmagic(info,func)
185 #endif
187 static const char *fas216_bus_phase(int stat)
189 static const char *phases[] = {
190 "DATA OUT", "DATA IN",
191 "COMMAND", "STATUS",
192 "MISC OUT", "MISC IN",
193 "MESG OUT", "MESG IN"
196 return phases[stat & STAT_BUSMASK];
199 static const char *fas216_drv_phase(FAS216_Info *info)
201 switch (info->scsi.phase) {
202 case PHASE_IDLE: return "idle";
203 case PHASE_SELECTION: return "selection";
204 case PHASE_COMMAND: return "command";
205 case PHASE_RECONNECTED: return "reconnected";
206 case PHASE_DATAOUT: return "data out";
207 case PHASE_DATAIN: return "data in";
208 case PHASE_MSGIN: return "message in";
209 case PHASE_MSGIN_DISCONNECT: return "disconnect";
210 case PHASE_MSGOUT_EXPECT: return "expect message out";
211 case PHASE_MSGOUT: return "message out";
212 case PHASE_STATUS: return "status";
213 case PHASE_DONE: return "done";
214 default: return "???";
218 static char fas216_target(FAS216_Info *info)
220 if (info->SCpnt)
221 return '0' + info->SCpnt->target;
222 else
223 return 'H';
226 static void add_debug_list(int stat, int ssr, int isr, int ph)
228 list[ptr].stat = stat;
229 list[ptr].ssr = ssr;
230 list[ptr].isr = isr;
231 list[ptr].ph = ph;
233 ptr = (ptr + 1) & 7;
236 static void print_debug_list(void)
238 int i;
240 i = ptr;
242 printk(KERN_ERR "SCSI IRQ trail: ");
243 do {
244 printk("%02X:%02X:%02X:%1X ",
245 list[i].stat, list[i].ssr,
246 list[i].isr, list[i].ph);
247 i = (i + 1) & 7;
248 } while (i != ptr);
249 printk("\n");
252 static void fas216_done(FAS216_Info *info, unsigned int result);
254 /* Function: int fas216_clockrate(unsigned int clock)
255 * Purpose : calculate correct value to be written into clock conversion
256 * factor register.
257 * Params : clock - clock speed in MHz
258 * Returns : CLKF_ value
260 static int fas216_clockrate(int clock)
262 if (clock <= 10 || clock > 40) {
263 printk(KERN_CRIT
264 "fas216: invalid clock rate: check your driver!\n");
265 clock = -1;
266 } else
267 clock = ((clock - 1) / 5 + 1) & 7;
269 return clock;
272 /* Function: unsigned short fas216_get_last_msg(FAS216_Info *info, int pos)
273 * Purpose : retrieve a last message from the list, using position in fifo
274 * Params : info - interface to search
275 * : pos - current fifo position
277 static inline unsigned short
278 fas216_get_last_msg(FAS216_Info *info, int pos)
280 unsigned short packed_msg = NOP;
281 struct message *msg;
282 int msgnr = 0;
284 while ((msg = msgqueue_getmsg(&info->scsi.msgs, msgnr++)) != NULL) {
285 if (pos >= msg->fifo)
286 break;
289 if (msg) {
290 if (msg->msg[0] == EXTENDED_MESSAGE)
291 packed_msg = EXTENDED_MESSAGE | msg->msg[2] << 8;
292 else
293 packed_msg = msg->msg[0];
296 #ifdef DEBUG_MESSAGES
297 printk("Message: %04X found at position %02X\n",
298 packed_msg, pos);
299 #endif
300 return packed_msg;
303 /* Function: int fas216_syncperiod(FAS216_Info *info, int ns)
304 * Purpose : Calculate value to be loaded into the STP register
305 * for a given period in ns
306 * Params : info - state structure for interface connected to device
307 * : ns - period in ns (between subsequent bytes)
308 * Returns : Value suitable for REG_STP
310 static int
311 fas216_syncperiod(FAS216_Info *info, int ns)
313 int value = (info->ifcfg.clockrate * ns) / 1000;
315 fas216_checkmagic(info, "fas216_syncperiod");
317 if (value < 4)
318 value = 4;
319 else if (value > 35)
320 value = 35;
322 return value & 31;
325 /* Function: void fas216_set_sync(FAS216_Info *info, int target)
326 * Purpose : Correctly setup FAS216 chip for specified transfer period.
327 * Params : info - state structure for interface
328 * : target - target
329 * Notes : we need to switch the chip out of FASTSCSI mode if we have
330 * a transfer period >= 200ns - otherwise the chip will violate
331 * the SCSI timings.
333 static void
334 fas216_set_sync(FAS216_Info *info, int target)
336 outb(info->device[target].sof, REG_SOF(info));
337 outb(info->device[target].stp, REG_STP(info));
338 if (info->device[target].period >= (200 / 4))
339 outb(info->scsi.cfg[2] & ~CNTL3_FASTSCSI, REG_CNTL3(info));
340 else
341 outb(info->scsi.cfg[2], REG_CNTL3(info));
344 /* Synchronous transfer support
346 * Note: The SCSI II r10 spec says (5.6.12):
348 * (2) Due to historical problems with early host adapters that could
349 * not accept an SDTR message, some targets may not initiate synchronous
350 * negotiation after a power cycle as required by this standard. Host
351 * adapters that support synchronous mode may avoid the ensuing failure
352 * modes when the target is independently power cycled by initiating a
353 * synchronous negotiation on each REQUEST SENSE and INQUIRY command.
354 * This approach increases the SCSI bus overhead and is not recommended
355 * for new implementations. The correct method is to respond to an
356 * SDTR message with a MESSAGE REJECT message if the either the
357 * initiator or target devices does not support synchronous transfers
358 * or does not want to negotiate for synchronous transfers at the time.
359 * Using the correct method assures compatibility with wide data
360 * transfers and future enhancements.
362 * We will always initiate a synchronous transfer negociation request on
363 * every INQUIRY or REQUEST SENSE message, unless the target itself has
364 * at some point performed a synchronous transfer negociation request, or
365 * we have synchronous transfers disabled for this device.
368 /* Function: void fas216_handlesync(FAS216_Info *info, char *msg)
369 * Purpose : Handle a synchronous transfer message from the target
370 * Params : info - state structure for interface
371 * : msg - message from target
373 static void
374 fas216_handlesync(FAS216_Info *info, char *msg)
376 struct fas216_device *dev = &info->device[info->SCpnt->target];
377 enum { sync, async, none, reject } res = none;
379 #ifdef SCSI2_SYNC
380 switch (msg[0]) {
381 case MESSAGE_REJECT:
382 /* Synchronous transfer request failed.
383 * Note: SCSI II r10:
385 * SCSI devices that are capable of synchronous
386 * data transfers shall not respond to an SDTR
387 * message with a MESSAGE REJECT message.
389 * Hence, if we get this condition, we disable
390 * negociation for this device.
392 if (dev->sync_state == neg_inprogress) {
393 dev->sync_state = neg_invalid;
394 res = async;
396 break;
398 case EXTENDED_MESSAGE:
399 switch (dev->sync_state) {
400 /* We don't accept synchronous transfer requests.
401 * Respond with a MESSAGE_REJECT to prevent a
402 * synchronous transfer agreement from being reached.
404 case neg_invalid:
405 res = reject;
406 break;
408 /* We were not negociating a synchronous transfer,
409 * but the device sent us a negociation request.
410 * Honour the request by sending back a SDTR
411 * message containing our capability, limited by
412 * the targets capability.
414 default:
415 outb(CMD_SETATN, REG_CMD(info));
416 if (msg[4] > info->ifcfg.sync_max_depth)
417 msg[4] = info->ifcfg.sync_max_depth;
418 if (msg[3] < 1000 / info->ifcfg.clockrate)
419 msg[3] = 1000 / info->ifcfg.clockrate;
421 msgqueue_flush(&info->scsi.msgs);
422 msgqueue_addmsg(&info->scsi.msgs, 5,
423 EXTENDED_MESSAGE, 3, EXTENDED_SDTR,
424 msg[3], msg[4]);
425 info->scsi.phase = PHASE_MSGOUT_EXPECT;
427 /* This is wrong. The agreement is not in effect
428 * until this message is accepted by the device
430 dev->sync_state = neg_targcomplete;
431 res = sync;
432 break;
434 /* We initiated the synchronous transfer negociation,
435 * and have successfully received a response from the
436 * target. The synchronous transfer agreement has been
437 * reached. Note: if the values returned are out of our
438 * bounds, we must reject the message.
440 case neg_inprogress:
441 res = reject;
442 if (msg[4] <= info->ifcfg.sync_max_depth &&
443 msg[3] >= 1000 / info->ifcfg.clockrate) {
444 dev->sync_state = neg_complete;
445 res = sync;
447 break;
450 #else
451 res = reject;
452 #endif
454 switch (res) {
455 case sync:
456 dev->period = msg[3];
457 dev->sof = msg[4];
458 dev->stp = fas216_syncperiod(info, msg[3] * 4);
459 fas216_set_sync(info, info->SCpnt->target);
460 break;
462 case reject:
463 outb(CMD_SETATN, REG_CMD(info));
464 msgqueue_flush(&info->scsi.msgs);
465 msgqueue_addmsg(&info->scsi.msgs, 1, MESSAGE_REJECT);
466 info->scsi.phase = PHASE_MSGOUT_EXPECT;
468 case async:
469 dev->period = info->ifcfg.asyncperiod / 4;
470 dev->sof = 0;
471 dev->stp = info->scsi.async_stp;
472 fas216_set_sync(info, info->SCpnt->target);
473 break;
475 case none:
476 break;
480 /* Function: void fas216_handlewide(FAS216_Info *info, char *msg)
481 * Purpose : Handle a wide transfer message from the target
482 * Params : info - state structure for interface
483 * : msg - message from target
485 static void
486 fas216_handlewide(FAS216_Info *info, char *msg)
488 struct fas216_device *dev = &info->device[info->SCpnt->target];
489 enum { wide, bit8, none, reject } res = none;
491 #ifdef SCSI2_WIDE
492 switch (msg[0]) {
493 case MESSAGE_REJECT:
494 /* Wide transfer request failed.
495 * Note: SCSI II r10:
497 * SCSI devices that are capable of wide
498 * data transfers shall not respond to a
499 * WDTR message with a MESSAGE REJECT message.
501 * Hence, if we get this condition, we never
502 * reattempt negociation for this device.
504 if (dev->wide_state == neg_inprogress) {
505 dev->wide_state = neg_invalid;
506 res = bit8;
508 break;
510 case EXTENDED_MESSAGE:
511 switch (dev->wide_state) {
512 /* We don't accept wide data transfer requests.
513 * Respond with a MESSAGE REJECT to prevent a
514 * wide data transfer agreement from being reached.
516 case neg_invalid:
517 res = reject;
518 break;
520 /* We were not negociating a wide data transfer,
521 * but the device sent is a negociation request.
522 * Honour the request by sending back a WDTR
523 * message containing our capability, limited by
524 * the targets capability.
526 default:
527 outb(CMD_SETATN, REG_CMD(info));
528 if (msg[3] > info->ifcfg.wide_max_size)
529 msg[3] = info->ifcfg.wide_max_size;
531 msgqueue_flush(&info->scsi.msgs);
532 msgqueue_addmsg(&info->scsi.msgs, 4,
533 EXTENDED_MESSAGE, 2, EXTENDED_WDTR,
534 msg[3]);
535 info->scsi.phase = PHASE_MSGOUT_EXPECT;
536 res = wide;
537 break;
539 /* We initiated the wide data transfer negociation,
540 * and have successfully received a response from the
541 * target. The synchronous transfer agreement has been
542 * reached. Note: if the values returned are out of our
543 * bounds, we must reject the message.
545 case neg_inprogress:
546 res = reject;
547 if (msg[3] <= info->ifcfg.wide_max_size) {
548 dev->wide_state = neg_complete;
549 res = wide;
551 break;
554 #else
555 res = reject;
556 #endif
558 switch (res) {
559 case wide:
560 dev->wide_xfer = msg[3];
561 break;
563 case reject:
564 outb(CMD_SETATN, REG_CMD(info));
565 msgqueue_flush(&info->scsi.msgs);
566 msgqueue_addmsg(&info->scsi.msgs, 1, MESSAGE_REJECT);
567 info->scsi.phase = PHASE_MSGOUT_EXPECT;
569 case bit8:
570 dev->wide_xfer = 0;
571 break;
573 case none:
574 break;
578 /* Function: void fas216_updateptrs(FAS216_Info *info, int bytes_transferred)
579 * Purpose : update data pointers after transfer suspended/paused
580 * Params : info - interface's local pointer to update
581 * bytes_transferred - number of bytes transferred
583 static void
584 fas216_updateptrs(FAS216_Info *info, int bytes_transferred)
586 unsigned char *ptr;
587 unsigned int residual;
589 fas216_checkmagic(info, "fas216_updateptrs");
591 ptr = info->scsi.SCp.ptr;
592 residual = info->scsi.SCp.this_residual;
594 info->SCpnt->request_bufflen -= bytes_transferred;
596 while (residual <= bytes_transferred && bytes_transferred) {
597 /* We have used up this buffer */
598 bytes_transferred -= residual;
599 if (info->scsi.SCp.buffers_residual) {
600 info->scsi.SCp.buffer++;
601 info->scsi.SCp.buffers_residual--;
602 ptr = (unsigned char *)info->scsi.SCp.buffer->address;
603 residual = info->scsi.SCp.buffer->length;
604 } else {
605 ptr = NULL;
606 residual = 0;
610 residual -= bytes_transferred;
611 ptr += bytes_transferred;
613 if (residual == 0)
614 ptr = NULL;
616 info->scsi.SCp.ptr = ptr;
617 info->scsi.SCp.this_residual = residual;
620 /* Function: void fas216_pio(FAS216_Info *info, fasdmadir_t direction)
621 * Purpose : transfer data off of/on to card using programmed IO
622 * Params : info - interface to transfer data to/from
623 * direction - direction to transfer data (DMA_OUT/DMA_IN)
624 * Notes : this is incredibly slow
626 static void
627 fas216_pio(FAS216_Info *info, fasdmadir_t direction)
629 unsigned int residual;
630 char *ptr;
632 fas216_checkmagic(info, "fas216_pio");
634 residual = info->scsi.SCp.this_residual;
635 ptr = info->scsi.SCp.ptr;
637 if (direction == DMA_OUT)
638 outb(*ptr++, REG_FF(info));
639 else
640 *ptr++ = inb(REG_FF(info));
642 residual -= 1;
644 if (residual == 0) {
645 if (info->scsi.SCp.buffers_residual) {
646 info->scsi.SCp.buffer++;
647 info->scsi.SCp.buffers_residual--;
648 ptr = (unsigned char *)info->scsi.SCp.buffer->address;
649 residual = info->scsi.SCp.buffer->length;
650 } else {
651 ptr = NULL;
652 residual = 0;
656 info->scsi.SCp.ptr = ptr;
657 info->scsi.SCp.this_residual = residual;
660 /* Function: void fas216_starttransfer(FAS216_Info *info,
661 * fasdmadir_t direction)
662 * Purpose : Start a DMA/PIO transfer off of/on to card
663 * Params : info - interface from which device disconnected from
664 * direction - transfer direction (DMA_OUT/DMA_IN)
666 static void
667 fas216_starttransfer(FAS216_Info *info, fasdmadir_t direction, int flush_fifo)
669 fasdmatype_t dmatype;
671 fas216_checkmagic(info, "fas216_starttransfer");
673 info->scsi.phase = (direction == DMA_OUT) ?
674 PHASE_DATAOUT : PHASE_DATAIN;
676 if (info->dma.transfer_type != fasdma_none &&
677 info->dma.transfer_type != fasdma_pio) {
678 unsigned long total, residual;
680 if (info->dma.transfer_type == fasdma_real_all)
681 total = info->SCpnt->request_bufflen;
682 else
683 total = info->scsi.SCp.this_residual;
685 residual = (inb(REG_CFIS(info)) & CFIS_CF) +
686 inb(REG_CTCL(info)) +
687 (inb(REG_CTCM(info)) << 8) +
688 (inb(REG_CTCH(info)) << 16);
689 fas216_updateptrs(info, total - residual);
691 info->dma.transfer_type = fasdma_none;
693 if (!info->scsi.SCp.ptr) {
694 printk("scsi%d.%c: null buffer passed to "
695 "fas216_starttransfer\n", info->host->host_no,
696 fas216_target(info));
697 return;
700 /* flush FIFO */
701 if (flush_fifo)
702 outb(CMD_FLUSHFIFO, REG_CMD(info));
705 * Default to PIO mode or DMA mode if we have a synchronous
706 * transfer agreement.
708 if (info->device[info->SCpnt->target].sof && info->dma.setup)
709 dmatype = fasdma_real_all;
710 else
711 dmatype = fasdma_pio;
713 if (info->dma.setup)
714 dmatype = info->dma.setup(info->host, &info->scsi.SCp,
715 direction, dmatype);
716 info->dma.transfer_type = dmatype;
718 switch (dmatype) {
719 case fasdma_pio:
720 outb(0, REG_SOF(info));
721 outb(info->scsi.async_stp, REG_STP(info));
722 outb(info->scsi.SCp.this_residual, REG_STCL(info));
723 outb(info->scsi.SCp.this_residual >> 8, REG_STCM(info));
724 outb(info->scsi.SCp.this_residual >> 16, REG_STCH(info));
725 outb(CMD_TRANSFERINFO, REG_CMD(info));
726 fas216_pio(info, direction);
727 break;
729 case fasdma_pseudo:
730 outb(info->scsi.SCp.this_residual, REG_STCL(info));
731 outb(info->scsi.SCp.this_residual >> 8, REG_STCM(info));
732 outb(info->scsi.SCp.this_residual >> 16, REG_STCH(info));
733 outb(CMD_TRANSFERINFO | CMD_WITHDMA, REG_CMD(info));
734 info->dma.pseudo(info->host, &info->scsi.SCp,
735 direction, info->SCpnt->transfersize);
736 break;
738 case fasdma_real_block:
739 outb(info->scsi.SCp.this_residual, REG_STCL(info));
740 outb(info->scsi.SCp.this_residual >> 8, REG_STCM(info));
741 outb(info->scsi.SCp.this_residual >> 16, REG_STCH(info));
742 outb(CMD_TRANSFERINFO | CMD_WITHDMA, REG_CMD(info));
743 break;
745 case fasdma_real_all:
746 outb(info->SCpnt->request_bufflen, REG_STCL(info));
747 outb(info->SCpnt->request_bufflen >> 8, REG_STCM(info));
748 outb(info->SCpnt->request_bufflen >> 16, REG_STCH(info));
749 outb(CMD_TRANSFERINFO | CMD_WITHDMA, REG_CMD(info));
750 break;
752 default:
753 printk(KERN_ERR "scsi%d.%d: invalid FAS216 DMA type\n",
754 info->host->host_no, fas216_target(info));
755 break;
759 /* Function: void fas216_stoptransfer(FAS216_Info *info)
760 * Purpose : Stop a DMA transfer onto / off of the card
761 * Params : info - interface from which device disconnected from
763 static void
764 fas216_stoptransfer(FAS216_Info *info)
766 fas216_checkmagic(info, "fas216_stoptransfer");
768 if (info->dma.transfer_type != fasdma_none &&
769 info->dma.transfer_type != fasdma_pio) {
770 unsigned long total, residual;
772 if ((info->dma.transfer_type == fasdma_real_all ||
773 info->dma.transfer_type == fasdma_real_block) &&
774 info->dma.stop)
775 info->dma.stop(info->host, &info->scsi.SCp);
777 if (info->dma.transfer_type == fasdma_real_all)
778 total = info->SCpnt->request_bufflen;
779 else
780 total = info->scsi.SCp.this_residual;
782 residual = (inb(REG_CFIS(info)) & CFIS_CF) +
783 inb(REG_CTCL(info)) +
784 (inb(REG_CTCM(info)) << 8) +
785 (inb(REG_CTCH(info)) << 16);
786 fas216_updateptrs(info, total - residual);
787 info->dma.transfer_type = fasdma_none;
789 if (info->scsi.phase == PHASE_DATAOUT)
790 outb(CMD_FLUSHFIFO, REG_CMD(info));
793 /* Function: void fas216_disconnected_intr(FAS216_Info *info)
794 * Purpose : handle device disconnection
795 * Params : info - interface from which device disconnected from
797 static void
798 fas216_disconnect_intr(FAS216_Info *info)
800 fas216_checkmagic(info, "fas216_disconnected_intr");
802 #ifdef DEBUG_CONNECT
803 printk("scsi%d.%c: disconnect phase=%02X\n", info->host->host_no,
804 fas216_target(info), info->scsi.phase);
805 #endif
806 msgqueue_flush(&info->scsi.msgs);
808 switch (info->scsi.phase) {
809 case PHASE_SELECTION: /* while selecting - no target */
810 case PHASE_SELSTEPS:
811 fas216_done(info, DID_NO_CONNECT);
812 break;
814 case PHASE_MSGIN_DISCONNECT: /* message in - disconnecting */
815 outb(CMD_ENABLESEL, REG_CMD(info));
816 info->scsi.disconnectable = 1;
817 info->scsi.reconnected.tag = 0;
818 info->scsi.phase = PHASE_IDLE;
819 info->stats.disconnects += 1;
820 break;
822 case PHASE_DONE: /* at end of command - complete */
823 fas216_done(info, DID_OK);
824 break;
826 case PHASE_MSGOUT: /* message out - possible ABORT message */
827 if (fas216_get_last_msg(info, info->scsi.msgin_fifo) == ABORT) {
828 info->scsi.aborting = 0;
829 fas216_done(info, DID_ABORT);
830 break;
833 default: /* huh? */
834 printk(KERN_ERR "scsi%d.%c: unexpected disconnect in phase %s\n",
835 info->host->host_no, fas216_target(info), fas216_drv_phase(info));
836 print_debug_list();
837 fas216_stoptransfer(info);
838 fas216_done(info, DID_ERROR);
839 break;
843 /* Function: void fas216_reselected_intr(FAS216_Info *info)
844 * Purpose : Start reconnection of a device
845 * Params : info - interface which was reselected
847 static void
848 fas216_reselected_intr(FAS216_Info *info)
850 unsigned char target, identify_msg, ok;
852 fas216_checkmagic(info, "fas216_reselected_intr");
854 if ((info->scsi.phase == PHASE_SELECTION ||
855 info->scsi.phase == PHASE_SELSTEPS) && info->SCpnt) {
856 Scsi_Cmnd *SCpnt = info->SCpnt;
858 info->origSCpnt = SCpnt;
859 info->SCpnt = NULL;
861 if (info->device[SCpnt->target].wide_state == neg_inprogress)
862 info->device[SCpnt->target].wide_state = neg_wait;
863 if (info->device[SCpnt->target].sync_state == neg_inprogress)
864 info->device[SCpnt->target].sync_state = neg_wait;
867 #ifdef DEBUG_CONNECT
868 printk("scsi%d.%c: reconnect phase=%02X\n", info->host->host_no,
869 fas216_target(info), info->scsi.phase);
870 #endif
872 if ((inb(REG_CFIS(info)) & CFIS_CF) != 2) {
873 printk(KERN_ERR "scsi%d.H: incorrect number of bytes after reselect\n",
874 info->host->host_no);
875 outb(CMD_SETATN, REG_CMD(info));
876 outb(CMD_MSGACCEPTED, REG_CMD(info));
877 msgqueue_flush(&info->scsi.msgs);
878 msgqueue_addmsg(&info->scsi.msgs, 1, INITIATOR_ERROR);
879 info->scsi.phase = PHASE_MSGOUT_EXPECT;
880 return;
883 target = inb(REG_FF(info));
884 identify_msg = inb(REG_FF(info));
886 ok = 1;
887 if (!(target & (1 << info->host->this_id))) {
888 printk(KERN_ERR "scsi%d.H: invalid host id on reselect\n", info->host->host_no);
889 ok = 0;
892 if (!(identify_msg & 0x80)) {
893 printk(KERN_ERR "scsi%d.H: no IDENTIFY message on reselect, got msg %02X\n",
894 info->host->host_no, identify_msg);
895 ok = 0;
898 if (!ok) {
900 * Something went wrong - send an initiator error to
901 * the target.
903 outb(CMD_SETATN, REG_CMD(info));
904 outb(CMD_MSGACCEPTED, REG_CMD(info));
905 msgqueue_flush(&info->scsi.msgs);
906 msgqueue_addmsg(&info->scsi.msgs, 1, INITIATOR_ERROR);
907 info->scsi.phase = PHASE_MSGOUT_EXPECT;
908 return;
911 target &= ~(1 << info->host->this_id);
912 switch (target) {
913 case 1: target = 0; break;
914 case 2: target = 1; break;
915 case 4: target = 2; break;
916 case 8: target = 3; break;
917 case 16: target = 4; break;
918 case 32: target = 5; break;
919 case 64: target = 6; break;
920 case 128: target = 7; break;
921 default: target = info->host->this_id; break;
924 identify_msg &= 7;
925 info->scsi.reconnected.target = target;
926 info->scsi.reconnected.lun = identify_msg;
927 info->scsi.reconnected.tag = 0;
929 ok = 0;
930 if (info->scsi.disconnectable && info->SCpnt &&
931 info->SCpnt->target == target && info->SCpnt->lun == identify_msg)
932 ok = 1;
934 if (!ok && queue_probetgtlun(&info->queues.disconnected, target, identify_msg))
935 ok = 1;
937 msgqueue_flush(&info->scsi.msgs);
938 if (ok) {
939 info->scsi.phase = PHASE_RECONNECTED;
940 outb(target, REG_SDID(info));
941 } else {
943 * Our command structure not found - abort the
944 * command on the target. Since we have no
945 * record of this command, we can't send
946 * an INITIATOR DETECTED ERROR message.
948 outb(CMD_SETATN, REG_CMD(info));
949 msgqueue_addmsg(&info->scsi.msgs, 1, ABORT);
950 info->scsi.phase = PHASE_MSGOUT_EXPECT;
952 outb(CMD_MSGACCEPTED, REG_CMD(info));
955 /* Function: void fas216_finish_reconnect(FAS216_Info *info)
956 * Purpose : finish reconnection sequence for device
957 * Params : info - interface which caused function done interrupt
959 static void
960 fas216_finish_reconnect(FAS216_Info *info)
962 fas216_checkmagic(info, "fas216_reconnect");
964 #ifdef DEBUG_CONNECT
965 printk("Connected: %1X %1X %02X, reconnected: %1X %1X %02X\n",
966 info->SCpnt->target, info->SCpnt->lun, info->SCpnt->tag,
967 info->scsi.reconnected.target, info->scsi.reconnected.lun,
968 info->scsi.reconnected.tag);
969 #endif
971 if (info->scsi.disconnectable && info->SCpnt) {
972 info->scsi.disconnectable = 0;
973 if (info->SCpnt->target == info->scsi.reconnected.target &&
974 info->SCpnt->lun == info->scsi.reconnected.lun &&
975 info->SCpnt->tag == info->scsi.reconnected.tag) {
976 #ifdef DEBUG_CONNECT
977 printk("scsi%d.%c: reconnected",
978 info->host->host_no, fas216_target(info));
979 #endif
980 } else {
981 queue_add_cmd_tail(&info->queues.disconnected, info->SCpnt);
982 #ifdef DEBUG_CONNECT
983 printk("scsi%d.%c: had to move command to disconnected queue\n",
984 info->host->host_no, fas216_target(info));
985 #endif
986 info->SCpnt = NULL;
989 if (!info->SCpnt) {
990 info->SCpnt = queue_remove_tgtluntag(&info->queues.disconnected,
991 info->scsi.reconnected.target,
992 info->scsi.reconnected.lun,
993 info->scsi.reconnected.tag);
994 #ifdef DEBUG_CONNECT
995 printk("scsi%d.%c: had to get command",
996 info->host->host_no, fas216_target(info));
997 #endif
999 if (!info->SCpnt) {
1000 outb(CMD_SETATN, REG_CMD(info));
1001 msgqueue_flush(&info->scsi.msgs);
1002 #if 0
1003 if (info->scsi.reconnected.tag)
1004 msgqueue_addmsg(&info->scsi.msgs, 2, ABORT_TAG, info->scsi.reconnected.tag);
1005 else
1006 #endif
1007 msgqueue_addmsg(&info->scsi.msgs, 1, ABORT);
1008 info->scsi.phase = PHASE_MSGOUT_EXPECT;
1009 info->scsi.aborting = 1;
1010 } else {
1012 * Restore data pointer from SAVED data pointer
1014 info->scsi.SCp = info->SCpnt->SCp;
1015 #ifdef DEBUG_CONNECT
1016 printk(", data pointers: [%p, %X]",
1017 info->scsi.SCp.ptr, info->scsi.SCp.this_residual);
1018 #endif
1020 #ifdef DEBUG_CONNECT
1021 printk("\n");
1022 #endif
1025 static int fas216_wait_cmd(FAS216_Info *info, int cmd)
1027 int tout;
1028 int stat;
1030 outb(cmd, REG_CMD(info));
1032 for (tout = 1000; tout; tout -= 1) {
1033 stat = inb(REG_STAT(info));
1034 if (stat & STAT_INT)
1035 break;
1036 udelay(1);
1039 return stat;
1042 static int fas216_get_msg_byte(FAS216_Info *info)
1044 int stat;
1046 stat = fas216_wait_cmd(info, CMD_MSGACCEPTED);
1048 if ((stat & STAT_INT) == 0)
1049 goto timedout;
1051 if ((stat & STAT_BUSMASK) != STAT_MESGIN)
1052 goto unexpected_phase_change;
1054 inb(REG_INST(info));
1056 stat = fas216_wait_cmd(info, CMD_TRANSFERINFO);
1058 if ((stat & STAT_INT) == 0)
1059 goto timedout;
1061 if ((stat & STAT_BUSMASK) != STAT_MESGIN)
1062 goto unexpected_phase_change;
1064 inb(REG_INST(info));
1066 return inb(REG_FF(info));
1068 timedout:
1069 printk("scsi%d.%c: timed out waiting for message byte\n",
1070 info->host->host_no, fas216_target(info));
1071 return -1;
1073 unexpected_phase_change:
1074 printk("scsi%d.%c: unexpected phase change: status = %02X\n",
1075 info->host->host_no, fas216_target(info), stat);
1077 return -2;
1080 /* Function: void fas216_message(FAS216_Info *info)
1081 * Purpose : handle a function done interrupt from FAS216 chip
1082 * Params : info - interface which caused function done interrupt
1084 static void fas216_message(FAS216_Info *info)
1086 unsigned char *message = info->scsi.message;
1087 unsigned int msglen = 1, i;
1088 int msgbyte = 0;
1090 fas216_checkmagic(info, "fas216_message");
1092 message[0] = inb(REG_FF(info));
1094 if (message[0] == EXTENDED_MESSAGE) {
1095 msgbyte = fas216_get_msg_byte(info);
1097 if (msgbyte >= 0) {
1098 message[1] = msgbyte;
1100 for (msglen = 2; msglen < message[1] + 2; msglen++) {
1101 msgbyte = fas216_get_msg_byte(info);
1103 if (msgbyte >= 0)
1104 message[msglen] = msgbyte;
1105 else
1106 break;
1111 info->scsi.msglen = msglen;
1113 #ifdef DEBUG_MESSAGES
1115 int i;
1117 printk("scsi%d.%c: message in: ",
1118 info->host->host_no, fas216_target(info));
1119 for (i = 0; i < msglen; i++)
1120 printk("%02X ", message[i]);
1121 printk("\n");
1123 #endif
1125 if (info->scsi.phase == PHASE_RECONNECTED) {
1126 if (message[0] == SIMPLE_QUEUE_TAG)
1127 info->scsi.reconnected.tag = message[1];
1128 fas216_finish_reconnect(info);
1129 info->scsi.phase = PHASE_MSGIN;
1132 switch (message[0]) {
1133 case COMMAND_COMPLETE:
1134 if (msglen != 1)
1135 goto unrecognised;
1137 printk(KERN_ERR "scsi%d.%c: command complete with no "
1138 "status in MESSAGE_IN?\n",
1139 info->host->host_no, fas216_target(info));
1140 break;
1142 case SAVE_POINTERS:
1143 if (msglen != 1)
1144 goto unrecognised;
1147 * Save current data pointer to SAVED data pointer
1148 * SCSI II standard says that we must not acknowledge
1149 * this until we have really saved pointers.
1150 * NOTE: we DO NOT save the command nor status pointers
1151 * as required by the SCSI II standard. These always
1152 * point to the start of their respective areas.
1154 info->SCpnt->SCp = info->scsi.SCp;
1155 info->SCpnt->SCp.sent_command = 0;
1156 #if defined (DEBUG_MESSAGES) || defined (DEBUG_CONNECT)
1157 printk("scsi%d.%c: save data pointers: [%p, %X]\n",
1158 info->host->host_no, fas216_target(info),
1159 info->scsi.SCp.ptr, info->scsi.SCp.this_residual);
1160 #endif
1161 break;
1163 case RESTORE_POINTERS:
1164 if (msglen != 1)
1165 goto unrecognised;
1168 * Restore current data pointer from SAVED data pointer
1170 info->scsi.SCp = info->SCpnt->SCp;
1171 #if defined (DEBUG_MESSAGES) || defined (DEBUG_CONNECT)
1172 printk("scsi%d.%c: restore data pointers: [%p, %X]\n",
1173 info->host->host_no, fas216_target(info),
1174 info->scsi.SCp.ptr, info->scsi.SCp.this_residual);
1175 #endif
1176 break;
1178 case DISCONNECT:
1179 if (msglen != 1)
1180 goto unrecognised;
1182 info->scsi.phase = PHASE_MSGIN_DISCONNECT;
1183 break;
1185 case MESSAGE_REJECT:
1186 if (msglen != 1)
1187 goto unrecognised;
1189 switch (fas216_get_last_msg(info, info->scsi.msgin_fifo)) {
1190 case EXTENDED_MESSAGE | EXTENDED_SDTR << 8:
1191 fas216_handlesync(info, message);
1192 break;
1194 case EXTENDED_MESSAGE | EXTENDED_WDTR << 8:
1195 fas216_handlewide(info, message);
1196 break;
1198 default:
1199 printk("scsi%d.%c: reject, last message %04X\n",
1200 info->host->host_no, fas216_target(info),
1201 fas216_get_last_msg(info, info->scsi.msgin_fifo));
1203 break;
1205 case NOP:
1206 break;
1208 case SIMPLE_QUEUE_TAG:
1209 if (msglen < 2)
1210 goto unrecognised;
1212 /* handled above - print a warning since this is untested */
1213 printk("scsi%d.%c: reconnect queue tag %02X\n",
1214 info->host->host_no, fas216_target(info),
1215 message[1]);
1216 break;
1218 case EXTENDED_MESSAGE:
1219 if (msglen < 3)
1220 goto unrecognised;
1222 switch (message[2]) {
1223 case EXTENDED_SDTR: /* Sync transfer negociation request/reply */
1224 fas216_handlesync(info, message);
1225 break;
1227 case EXTENDED_WDTR: /* Wide transfer negociation request/reply */
1228 fas216_handlewide(info, message);
1229 break;
1231 default:
1232 goto unrecognised;
1234 break;
1236 default:
1237 goto unrecognised;
1239 outb(CMD_MSGACCEPTED, REG_CMD(info));
1240 return;
1242 unrecognised:
1243 printk("scsi%d.%c: unrecognised message, rejecting\n",
1244 info->host->host_no, fas216_target(info));
1245 printk("scsi%d.%c: message was", info->host->host_no, fas216_target(info));
1246 for (i = 0; i < msglen; i++)
1247 printk("%s%02X", i & 31 ? " " : "\n ", message[i]);
1248 printk("\n");
1250 reject_message:
1252 * Something strange seems to be happening here -
1253 * I can't use SETATN since the chip gives me an
1254 * invalid command interrupt when I do. Weird.
1256 outb(CMD_NOP, REG_CMD(info));
1257 fas216_dumpstate(info);
1258 outb(CMD_SETATN, REG_CMD(info));
1259 msgqueue_flush(&info->scsi.msgs);
1260 msgqueue_addmsg(&info->scsi.msgs, 1, MESSAGE_REJECT);
1261 info->scsi.phase = PHASE_MSGOUT_EXPECT;
1262 fas216_dumpstate(info);
1263 outb(CMD_MSGACCEPTED, REG_CMD(info));
1266 /* Function: void fas216_send_command(FAS216_Info *info)
1267 * Purpose : send a command to a target after all message bytes have been sent
1268 * Params : info - interface which caused bus service
1270 static void fas216_send_command(FAS216_Info *info)
1272 int i;
1274 fas216_checkmagic(info, "fas216_send_command");
1276 outb(CMD_NOP|CMD_WITHDMA, REG_CMD(info));
1277 outb(CMD_FLUSHFIFO, REG_CMD(info));
1279 /* load command */
1280 for (i = info->scsi.SCp.sent_command; i < info->SCpnt->cmd_len; i++)
1281 outb(info->SCpnt->cmnd[i], REG_FF(info));
1283 outb(CMD_TRANSFERINFO, REG_CMD(info));
1285 info->scsi.phase = PHASE_COMMAND;
1288 /* Function: void fas216_send_messageout(FAS216_Info *info, int start)
1289 * Purpose : handle bus service to send a message
1290 * Params : info - interface which caused bus service
1291 * Note : We do not allow the device to change the data direction!
1293 static void fas216_send_messageout(FAS216_Info *info, int start)
1295 unsigned int tot_msglen = msgqueue_msglength(&info->scsi.msgs);
1297 fas216_checkmagic(info, "fas216_send_messageout");
1299 outb(CMD_FLUSHFIFO, REG_CMD(info));
1301 if (tot_msglen) {
1302 struct message *msg;
1303 int msgnr = 0;
1305 while ((msg = msgqueue_getmsg(&info->scsi.msgs, msgnr++)) != NULL) {
1306 int i;
1308 for (i = start; i < msg->length; i++)
1309 outb(msg->msg[i], REG_FF(info));
1311 msg->fifo = tot_msglen - (inb(REG_CFIS(info)) & CFIS_CF);
1312 start = 0;
1314 } else
1315 outb(NOP, REG_FF(info));
1317 outb(CMD_TRANSFERINFO, REG_CMD(info));
1319 info->scsi.phase = PHASE_MSGOUT;
1322 /* Function: void fas216_busservice_intr(FAS216_Info *info, unsigned int stat, unsigned int ssr)
1323 * Purpose : handle a bus service interrupt from FAS216 chip
1324 * Params : info - interface which caused bus service interrupt
1325 * stat - Status register contents
1326 * ssr - SCSI Status register contents
1328 static void fas216_busservice_intr(FAS216_Info *info, unsigned int stat, unsigned int ssr)
1330 fas216_checkmagic(info, "fas216_busservice_intr");
1332 #ifdef DEBUG_BUSSERVICE
1333 printk("scsi%d.%c: bus service: stat=%02X ssr=%02X phase=%02X\n",
1334 info->host->host_no, fas216_target(info), stat, ssr, info->scsi.phase);
1335 #endif
1337 switch (info->scsi.phase) {
1338 case PHASE_SELECTION:
1339 if ((ssr & IS_BITS) != 1)
1340 goto bad_is;
1341 break;
1343 case PHASE_SELSTEPS:
1344 switch (ssr & IS_BITS) {
1345 case IS_SELARB:
1346 case IS_MSGBYTESENT:
1347 goto bad_is;
1349 case IS_NOTCOMMAND:
1350 case IS_EARLYPHASE:
1351 if ((stat & STAT_BUSMASK) == STAT_MESGIN)
1352 break;
1353 goto bad_is;
1355 case IS_COMPLETE:
1356 break;
1359 default:
1360 break;
1363 outb(CMD_NOP, REG_CMD(info));
1365 #define STATE(st,ph) ((ph) << 3 | (st))
1366 /* This table describes the legal SCSI state transitions,
1367 * as described by the SCSI II spec.
1369 switch (STATE(stat & STAT_BUSMASK, info->scsi.phase)) {
1370 /* Reselmsgin -> Data In */
1371 case STATE(STAT_DATAIN, PHASE_RECONNECTED):
1372 fas216_finish_reconnect(info);
1373 case STATE(STAT_DATAIN, PHASE_SELSTEPS):/* Sel w/ steps -> Data In */
1374 case STATE(STAT_DATAIN, PHASE_DATAIN): /* Data In -> Data In */
1375 case STATE(STAT_DATAIN, PHASE_MSGOUT): /* Message Out -> Data In */
1376 case STATE(STAT_DATAIN, PHASE_COMMAND): /* Command -> Data In */
1377 case STATE(STAT_DATAIN, PHASE_MSGIN): /* Message In -> Data In */
1378 fas216_starttransfer(info, DMA_IN, 0);
1379 return;
1381 case STATE(STAT_DATAOUT, PHASE_DATAOUT):/* Data Out -> Data Out */
1382 fas216_starttransfer(info, DMA_OUT, 0);
1383 return;
1385 /* Reselmsgin -> Data Out */
1386 case STATE(STAT_DATAOUT, PHASE_RECONNECTED):
1387 fas216_finish_reconnect(info);
1388 case STATE(STAT_DATAOUT, PHASE_SELSTEPS):/* Sel w/ steps-> Data Out */
1389 case STATE(STAT_DATAOUT, PHASE_MSGOUT): /* Message Out -> Data Out */
1390 case STATE(STAT_DATAOUT, PHASE_COMMAND):/* Command -> Data Out */
1391 case STATE(STAT_DATAOUT, PHASE_MSGIN): /* Message In -> Data Out */
1392 fas216_starttransfer(info, DMA_OUT, 1);
1393 return;
1395 /* Reselmsgin -> Status */
1396 case STATE(STAT_STATUS, PHASE_RECONNECTED):
1397 fas216_finish_reconnect(info);
1398 goto status;
1399 case STATE(STAT_STATUS, PHASE_DATAOUT): /* Data Out -> Status */
1400 case STATE(STAT_STATUS, PHASE_DATAIN): /* Data In -> Status */
1401 fas216_stoptransfer(info);
1402 case STATE(STAT_STATUS, PHASE_SELSTEPS):/* Sel w/ steps -> Status */
1403 case STATE(STAT_STATUS, PHASE_MSGOUT): /* Message Out -> Status */
1404 case STATE(STAT_STATUS, PHASE_COMMAND): /* Command -> Status */
1405 case STATE(STAT_STATUS, PHASE_MSGIN): /* Message In -> Status */
1406 status:
1407 outb(CMD_INITCMDCOMPLETE, REG_CMD(info));
1408 info->scsi.phase = PHASE_STATUS;
1409 return;
1411 case STATE(STAT_MESGIN, PHASE_DATAOUT): /* Data Out -> Message In */
1412 case STATE(STAT_MESGIN, PHASE_DATAIN): /* Data In -> Message In */
1413 fas216_stoptransfer(info);
1414 case STATE(STAT_MESGIN, PHASE_SELSTEPS):/* Sel w/ steps -> Message In */
1415 case STATE(STAT_MESGIN, PHASE_MSGOUT): /* Message Out -> Message In */
1416 info->scsi.msgin_fifo = inb(REG_CFIS(info)) & CFIS_CF;
1417 outb(CMD_FLUSHFIFO, REG_CMD(info));
1418 outb(CMD_TRANSFERINFO, REG_CMD(info));
1419 info->scsi.phase = PHASE_MSGIN;
1420 return;
1422 /* Reselmsgin -> Message In */
1423 case STATE(STAT_MESGIN, PHASE_RECONNECTED):
1424 case STATE(STAT_MESGIN, PHASE_MSGIN):
1425 info->scsi.msgin_fifo = inb(REG_CFIS(info)) & CFIS_CF;
1426 outb(CMD_TRANSFERINFO, REG_CMD(info));
1427 return;
1429 /* Reselmsgin -> Command */
1430 case STATE(STAT_COMMAND, PHASE_RECONNECTED):
1431 fas216_finish_reconnect(info);
1432 case STATE(STAT_COMMAND, PHASE_MSGOUT): /* Message Out -> Command */
1433 case STATE(STAT_COMMAND, PHASE_MSGIN): /* Message In -> Command */
1434 fas216_send_command(info);
1435 info->scsi.phase = PHASE_COMMAND;
1436 return;
1437 /* Selection -> Message Out */
1438 case STATE(STAT_MESGOUT, PHASE_SELECTION):
1439 fas216_send_messageout(info, 1);
1440 return;
1441 /* Any -> Message Out */
1442 case STATE(STAT_MESGOUT, PHASE_MSGOUT_EXPECT):
1443 fas216_send_messageout(info, 0);
1444 return;
1446 /* Error recovery rules.
1447 * These either attempt to abort or retry the operation.
1448 * TODO: we need more of these
1450 case STATE(STAT_COMMAND, PHASE_COMMAND):/* Command -> Command */
1451 /* error - we've sent out all the command bytes
1452 * we have.
1453 * NOTE: we need SAVE DATA POINTERS/RESTORE DATA POINTERS
1454 * to include the command bytes sent for this to work
1455 * correctly.
1457 printk(KERN_ERR "scsi%d.%c: "
1458 "target trying to receive more command bytes\n",
1459 info->host->host_no, fas216_target(info));
1460 outb(CMD_SETATN, REG_CMD(info));
1461 outb(15, REG_STCL(info));
1462 outb(0, REG_STCM(info));
1463 outb(0, REG_STCH(info));
1464 outb(CMD_PADBYTES | CMD_WITHDMA, REG_CMD(info));
1465 msgqueue_flush(&info->scsi.msgs);
1466 msgqueue_addmsg(&info->scsi.msgs, 1, INITIATOR_ERROR);
1467 info->scsi.phase = PHASE_MSGOUT_EXPECT;
1468 return;
1470 /* Selection -> Message Out */
1471 case STATE(STAT_MESGOUT, PHASE_SELSTEPS):
1472 case STATE(STAT_MESGOUT, PHASE_MSGOUT): /* Message Out -> Message Out */
1473 /* If we get another message out phase, this
1474 * usually means some parity error occurred.
1475 * Resend complete set of messages. If we have
1476 * more than 1 byte to send, we need to assert
1477 * ATN again.
1479 if (msgqueue_msglength(&info->scsi.msgs) > 1)
1480 outb(CMD_SETATN, REG_CMD(info));
1482 fas216_send_messageout(info, 0);
1483 return;
1486 if (info->scsi.phase == PHASE_MSGIN_DISCONNECT) {
1487 printk(KERN_ERR "scsi%d.%c: disconnect message received, but bus service %s?\n",
1488 info->host->host_no, fas216_target(info),
1489 fas216_bus_phase(stat));
1490 msgqueue_flush(&info->scsi.msgs);
1491 outb(CMD_SETATN, REG_CMD(info));
1492 msgqueue_addmsg(&info->scsi.msgs, 1, INITIATOR_ERROR);
1493 info->scsi.phase = PHASE_MSGOUT_EXPECT;
1494 info->scsi.aborting = 1;
1495 outb(CMD_TRANSFERINFO, REG_CMD(info));
1496 return;
1498 printk(KERN_ERR "scsi%d.%c: bus phase %s after %s?\n",
1499 info->host->host_no, fas216_target(info),
1500 fas216_bus_phase(stat),
1501 fas216_drv_phase(info));
1502 print_debug_list();
1503 return;
1505 bad_is:
1506 printk("scsi%d.%c: bus service at step %d?\n",
1507 info->host->host_no, fas216_target(info),
1508 ssr & IS_BITS);
1509 print_debug_list();
1511 fas216_done(info, DID_ERROR);
1514 /* Function: void fas216_funcdone_intr(FAS216_Info *info, unsigned int stat, unsigned int ssr)
1515 * Purpose : handle a function done interrupt from FAS216 chip
1516 * Params : info - interface which caused function done interrupt
1517 * stat - Status register contents
1518 * ssr - SCSI Status register contents
1520 static void fas216_funcdone_intr(FAS216_Info *info, unsigned int stat, unsigned int ssr)
1522 int status, message;
1524 fas216_checkmagic(info, "fas216_funcdone_intr");
1526 #ifdef DEBUG_FUNCTIONDONE
1527 printk("scsi%d.%c: function done: stat=%X ssr=%X phase=%02X\n",
1528 info->host->host_no, fas216_target(info), stat, ssr, info->scsi.phase);
1529 #endif
1530 switch (info->scsi.phase) {
1531 case PHASE_STATUS: /* status phase - read status and msg */
1532 status = inb(REG_FF(info));
1533 message = inb(REG_FF(info));
1534 info->scsi.SCp.Message = message;
1535 info->scsi.SCp.Status = status;
1536 info->scsi.phase = PHASE_DONE;
1537 outb(CMD_MSGACCEPTED, REG_CMD(info));
1538 break;
1540 case PHASE_IDLE: /* reselected? */
1541 case PHASE_MSGIN: /* message in phase */
1542 case PHASE_RECONNECTED: /* reconnected command */
1543 if ((stat & STAT_BUSMASK) == STAT_MESGIN) {
1544 info->scsi.msgin_fifo = inb(REG_CFIS(info)) & CFIS_CF;
1545 fas216_message(info);
1546 break;
1549 default:
1550 printk("scsi%d.%c: internal phase %s for function done?"
1551 " What do I do with this?\n",
1552 info->host->host_no, fas216_target(info),
1553 fas216_drv_phase(info));
1557 /* Function: void fas216_intr(struct Scsi_Host *instance)
1558 * Purpose : handle interrupts from the interface to progress a command
1559 * Params : instance - interface to service
1561 void fas216_intr(struct Scsi_Host *instance)
1563 FAS216_Info *info = (FAS216_Info *)instance->hostdata;
1564 unsigned char isr, ssr, stat;
1566 fas216_checkmagic(info, "fas216_intr");
1568 stat = inb(REG_STAT(info));
1569 ssr = inb(REG_IS(info));
1570 isr = inb(REG_INST(info));
1572 add_debug_list(stat, ssr, isr, info->scsi.phase);
1574 if (stat & STAT_INT) {
1575 if (isr & INST_BUSRESET)
1576 printk(KERN_DEBUG "scsi%d.H: bus reset detected\n", instance->host_no);
1577 else if (isr & INST_ILLEGALCMD) {
1578 printk(KERN_CRIT "scsi%d.H: illegal command given\n", instance->host_no);
1579 fas216_dumpstate(info);
1580 } else if (isr & INST_DISCONNECT)
1581 fas216_disconnect_intr(info);
1582 else if (isr & INST_RESELECTED) /* reselected */
1583 fas216_reselected_intr(info);
1584 else if (isr & INST_BUSSERVICE) /* bus service request */
1585 fas216_busservice_intr(info, stat, ssr);
1586 else if (isr & INST_FUNCDONE) /* function done */
1587 fas216_funcdone_intr(info, stat, ssr);
1588 else
1589 printk("scsi%d.%c: unknown interrupt received:"
1590 " phase %s isr %02X ssr %02X stat %02X\n",
1591 instance->host_no, fas216_target(info),
1592 fas216_drv_phase(info), isr, ssr, stat);
1596 /* Function: void fas216_kick(FAS216_Info *info)
1597 * Purpose : kick a command to the interface - interface should be idle
1598 * Params : info - our host interface to kick
1599 * Notes : Interrupts are always disabled!
1601 static void fas216_kick(FAS216_Info *info)
1603 Scsi_Cmnd *SCpnt;
1604 int tot_msglen, from_queue = 0;
1606 fas216_checkmagic(info, "fas216_kick");
1608 if (info->origSCpnt) {
1609 SCpnt = info->origSCpnt;
1610 info->origSCpnt = NULL;
1611 } else
1612 SCpnt = NULL;
1614 /* retrieve next command */
1615 if (!SCpnt) {
1616 SCpnt = queue_remove_exclude(&info->queues.issue, info->busyluns);
1617 from_queue = 1;
1620 if (!SCpnt) /* no command pending - just exit */
1621 return;
1623 if (info->scsi.disconnectable && info->SCpnt) {
1624 queue_add_cmd_tail(&info->queues.disconnected, info->SCpnt);
1625 info->scsi.disconnectable = 0;
1626 info->SCpnt = NULL;
1627 printk("scsi%d.%c: moved command to disconnected queue\n",
1628 info->host->host_no, fas216_target(info));
1632 * tagged queuing - allocate a new tag to this command
1634 if (SCpnt->device->tagged_queue && SCpnt->cmnd[0] != REQUEST_SENSE) {
1635 SCpnt->device->current_tag += 1;
1636 if (SCpnt->device->current_tag == 0)
1637 SCpnt->device->current_tag = 1;
1638 SCpnt->tag = SCpnt->device->current_tag;
1642 * claim host busy
1644 info->scsi.phase = PHASE_SELECTION;
1645 info->SCpnt = SCpnt;
1646 info->scsi.SCp = SCpnt->SCp;
1647 info->dma.transfer_type = fasdma_none;
1649 #ifdef DEBUG_CONNECT
1650 printk("scsi%d.%c: starting cmd %02X",
1651 info->host->host_no, '0' + SCpnt->target,
1652 SCpnt->cmnd[0]);
1653 #endif
1655 if (from_queue) {
1656 #ifdef SCSI2_TAG
1657 if (SCpnt->device->tagged_queue && SCpnt->cmnd[0] != REQUEST_SENSE &&
1658 SCpnt->cmnd[0] != INQUIRY) {
1659 SCpnt->device->current_tag += 1;
1660 if (SCpnt->device->current_tag == 0)
1661 SCpnt->device->current_tag = 1;
1662 SCpnt->tag = SCpnt->device->current_tag;
1663 } else
1664 #endif
1665 set_bit(SCpnt->target * 8 + SCpnt->lun, info->busyluns);
1667 info->stats.removes += 1;
1668 switch (SCpnt->cmnd[0]) {
1669 case WRITE_6:
1670 case WRITE_10:
1671 case WRITE_12:
1672 info->stats.writes += 1;
1673 break;
1674 case READ_6:
1675 case READ_10:
1676 case READ_12:
1677 info->stats.reads += 1;
1678 break;
1679 default:
1680 info->stats.miscs += 1;
1681 break;
1685 /* build outgoing message bytes */
1686 msgqueue_flush(&info->scsi.msgs);
1688 if (info->device[SCpnt->target].disconnect_ok)
1689 msgqueue_addmsg(&info->scsi.msgs, 1, IDENTIFY(1, SCpnt->lun));
1690 else
1691 msgqueue_addmsg(&info->scsi.msgs, 1, IDENTIFY(0, SCpnt->lun));
1693 /* add tag message if required */
1694 if (SCpnt->tag)
1695 msgqueue_addmsg(&info->scsi.msgs, 2, SIMPLE_QUEUE_TAG, SCpnt->tag);
1697 #ifdef SCSI2_WIDE
1698 if (info->device[SCpnt->target].wide_state == neg_wait) {
1699 info->device[SCpnt->target].wide_state = neg_inprogress;
1700 msgqueue_addmsg(&info->scsi.msgs, 4,
1701 EXTENDED_MESSAGE, 2, EXTENDED_WDTR,
1702 info->ifcfg.wide_max_size);
1704 #ifdef SCSI2_SYNC
1705 else
1706 #endif
1707 #endif
1708 #ifdef SCSI2_SYNC
1709 if ((info->device[SCpnt->target].sync_state == neg_wait ||
1710 info->device[SCpnt->target].sync_state == neg_complete) &&
1711 (SCpnt->cmnd[0] == REQUEST_SENSE ||
1712 SCpnt->cmnd[0] == INQUIRY)) {
1713 info->device[SCpnt->target].sync_state = neg_inprogress;
1714 msgqueue_addmsg(&info->scsi.msgs, 5,
1715 EXTENDED_MESSAGE, 3, EXTENDED_SDTR,
1716 1000 / info->ifcfg.clockrate,
1717 info->ifcfg.sync_max_depth);
1719 #endif
1721 /* following what the ESP driver says */
1722 outb(0, REG_STCL(info));
1723 outb(0, REG_STCM(info));
1724 outb(0, REG_STCH(info));
1725 outb(CMD_NOP | CMD_WITHDMA, REG_CMD(info));
1727 /* flush FIFO */
1728 outb(CMD_FLUSHFIFO, REG_CMD(info));
1730 /* load bus-id and timeout */
1731 outb(BUSID(SCpnt->target), REG_SDID(info));
1732 outb(info->ifcfg.select_timeout, REG_STIM(info));
1734 /* synchronous transfers */
1735 fas216_set_sync(info, SCpnt->target);
1737 tot_msglen = msgqueue_msglength(&info->scsi.msgs);
1739 if (tot_msglen == 1 || tot_msglen == 3) {
1741 * We have an easy message length to send...
1743 struct message *msg;
1744 int msgnr = 0, i;
1746 info->scsi.phase = PHASE_SELSTEPS;
1748 /* load message bytes */
1749 while ((msg = msgqueue_getmsg(&info->scsi.msgs, msgnr++)) != NULL) {
1750 for (i = 0; i < msg->length; i++)
1751 outb(msg->msg[i], REG_FF(info));
1752 msg->fifo = tot_msglen - (inb(REG_CFIS(info)) & CFIS_CF);
1755 /* load command */
1756 for (i = 0; i < SCpnt->cmd_len; i++)
1757 outb(SCpnt->cmnd[i], REG_FF(info));
1759 if (tot_msglen == 1)
1760 outb(CMD_SELECTATN, REG_CMD(info));
1761 else
1762 outb(CMD_SELECTATN3, REG_CMD(info));
1763 } else {
1765 * We have an unusual number of message bytes to send.
1766 * Load first byte into fifo, and issue SELECT with ATN and
1767 * stop steps.
1769 struct message *msg = msgqueue_getmsg(&info->scsi.msgs, 0);
1771 outb(msg->msg[0], REG_FF(info));
1772 msg->fifo = 1;
1774 outb(CMD_SELECTATNSTOP, REG_CMD(info));
1777 #ifdef DEBUG_CONNECT
1778 printk(", data pointers [%p, %X]\n",
1779 info->scsi.SCp.ptr, info->scsi.SCp.this_residual);
1780 #endif
1781 /* should now get either DISCONNECT or (FUNCTION DONE with BUS SERVICE) intr */
1784 /* Function: void fas216_done(FAS216_Info *info, unsigned int result)
1785 * Purpose : complete processing for command
1786 * Params : info - interface that completed
1787 * result - driver byte of result
1789 static void fas216_done(FAS216_Info *info, unsigned int result)
1791 Scsi_Cmnd *SCpnt;
1793 fas216_checkmagic(info, "fas216_done");
1795 SCpnt = info->SCpnt;
1797 if (info->scsi.aborting) {
1798 printk("scsi%d.%c: uncaught abort - returning DID_ABORT\n",
1799 info->host->host_no, fas216_target(info));
1800 result = DID_ABORT;
1801 info->scsi.aborting = 0;
1804 info->stats.fins += 1;
1806 if (SCpnt) {
1807 info->scsi.phase = PHASE_IDLE;
1808 info->SCpnt = NULL;
1810 SCpnt->result = result << 16 | info->scsi.SCp.Message << 8 |
1811 info->scsi.SCp.Status;
1814 * In theory, this should not happen, but just in case it does.
1816 if (info->scsi.SCp.ptr &&
1817 info->scsi.SCp.this_residual &&
1818 result == DID_OK) {
1819 switch (SCpnt->cmnd[0]) {
1820 case INQUIRY:
1821 case START_STOP:
1822 case READ_CAPACITY:
1823 case TEST_UNIT_READY:
1824 case MODE_SENSE:
1825 break;
1827 default:
1828 switch (status_byte(SCpnt->result)) {
1829 case CHECK_CONDITION:
1830 case COMMAND_TERMINATED:
1831 case BUSY:
1832 case QUEUE_FULL:
1833 case RESERVATION_CONFLICT:
1834 break;
1836 default:
1837 printk(KERN_ERR "scsi%d.H: incomplete data transfer "
1838 "detected: res=%08X ptr=%p len=%X command=",
1839 info->host->host_no, SCpnt->result,
1840 info->scsi.SCp.ptr, info->scsi.SCp.this_residual);
1841 print_command(SCpnt->cmnd);
1845 #ifdef DEBUG_CONNECT
1846 printk("scsi%d.%c: scsi command (%p) complete, result=%08X\n",
1847 info->host->host_no, fas216_target(info),
1848 SCpnt, SCpnt->result);
1849 #endif
1851 if (!SCpnt->scsi_done)
1852 panic("scsi%d.H: null scsi_done function in "
1853 "fas216_done", info->host->host_no);
1855 clear_bit(SCpnt->target * 8 + SCpnt->lun, info->busyluns);
1857 SCpnt->scsi_done(SCpnt);
1858 } else
1859 panic("scsi%d.H: null command in fas216_done", info->host->host_no);
1861 if (info->scsi.irq != NO_IRQ)
1862 fas216_kick(info);
1865 /* Function: int fas216_queue_command(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
1866 * Purpose : queue a command for adapter to process.
1867 * Params : SCpnt - Command to queue
1868 * done - done function to call once command is complete
1869 * Returns : 0 - success, else error
1871 int fas216_queue_command(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
1873 FAS216_Info *info = (FAS216_Info *)SCpnt->host->hostdata;
1874 unsigned long flags;
1876 fas216_checkmagic(info, "fas216_queue_command");
1878 #ifdef DEBUG_CONNECT
1879 printk("scsi%d.%c: received queuable command (%p) %02X\n",
1880 SCpnt->host->host_no, '0' + SCpnt->target,
1881 SCpnt, SCpnt->cmnd[0]);
1882 #endif
1884 SCpnt->scsi_done = done;
1885 SCpnt->host_scribble = NULL;
1886 SCpnt->result = 0;
1887 SCpnt->SCp.Message = 0;
1888 SCpnt->SCp.Status = 0;
1890 if (SCpnt->use_sg) {
1891 unsigned long len = 0;
1892 int buf;
1894 SCpnt->SCp.buffer = (struct scatterlist *) SCpnt->buffer;
1895 SCpnt->SCp.buffers_residual = SCpnt->use_sg - 1;
1896 SCpnt->SCp.ptr = (char *) SCpnt->SCp.buffer->address;
1897 SCpnt->SCp.this_residual = SCpnt->SCp.buffer->length;
1899 * Calculate correct buffer length
1901 for (buf = 0; buf <= SCpnt->SCp.buffers_residual; buf++)
1902 len += SCpnt->SCp.buffer[buf].length;
1903 SCpnt->request_bufflen = len;
1904 } else {
1905 SCpnt->SCp.buffer = NULL;
1906 SCpnt->SCp.buffers_residual = 0;
1907 SCpnt->SCp.ptr = (unsigned char *)SCpnt->request_buffer;
1908 SCpnt->SCp.this_residual = SCpnt->request_bufflen;
1911 info->stats.queues += 1;
1912 SCpnt->tag = 0;
1914 /* add command into execute queue and let it complete under
1915 * whatever scheme we're using.
1917 if (!queue_add_cmd_ordered(&info->queues.issue, SCpnt)) {
1918 SCpnt->result = DID_ERROR << 16;
1919 done(SCpnt);
1921 save_flags_cli(flags);
1922 if (!info->SCpnt || info->scsi.disconnectable)
1923 fas216_kick(info);
1924 restore_flags(flags);
1926 return 0;
1929 /* Function: void fas216_internal_done(Scsi_Cmnd *SCpnt)
1930 * Purpose : trigger restart of a waiting thread in fas216_command
1931 * Params : SCpnt - Command to wake
1933 static void fas216_internal_done(Scsi_Cmnd *SCpnt)
1935 FAS216_Info *info = (FAS216_Info *)SCpnt->host->hostdata;
1937 fas216_checkmagic(info, "fas216_internal_done");
1939 info->internal_done = 1;
1942 /* Function: int fas216_command(Scsi_Cmnd *SCpnt)
1943 * Purpose : queue a command for adapter to process.
1944 * Params : SCpnt - Command to queue
1945 * Returns : scsi result code
1947 int fas216_command(Scsi_Cmnd *SCpnt)
1949 FAS216_Info *info = (FAS216_Info *)SCpnt->host->hostdata;
1950 unsigned long flags;
1952 fas216_checkmagic(info, "fas216_command");
1954 info->internal_done = 0;
1955 fas216_queue_command(SCpnt, fas216_internal_done);
1958 * This wastes time, since we can't return until the command is
1959 * complete. We can't sleep either since we may get re-entered!
1960 * However, we must re-enable interrupts, or else we'll be
1961 * waiting forever.
1963 save_flags(flags);
1964 sti();
1966 while (!info->internal_done) {
1968 * If we don't have an IRQ, then we must
1969 * poll the card for it's interrupt, and
1970 * use that to call this driver's interrupt
1971 * routine. That way, we keep the command
1972 * progressing.
1974 if (info->scsi.irq == NO_IRQ) {
1975 sti();
1976 while (!(inb(REG_STAT(info)) & STAT_INT));
1977 cli();
1978 fas216_intr(info->host);
1982 restore_flags(flags);
1984 return SCpnt->result;
1987 /* Prototype: void fas216_reportstatus(Scsi_Cmnd **SCpntp1,
1988 * Scsi_Cmnd **SCpntp2, int result, int no_report)
1989 * Purpose : pass a result to *SCpntp1, and check if *SCpntp1 = *SCpntp2
1990 * Params : SCpntp1 - pointer to command to return
1991 * SCpntp2 - pointer to command to check
1992 * result - result to pass back to mid-level done function
1993 * Returns : *SCpntp2 = NULL if *SCpntp1 is the same command
1994 * structure as *SCpntp2.
1996 static void fas216_reportstatus(Scsi_Cmnd **SCpntp1, Scsi_Cmnd **SCpntp2,
1997 int result, int no_report)
1999 Scsi_Cmnd *SCpnt = *SCpntp1;
2001 if (SCpnt) {
2002 *SCpntp1 = NULL;
2004 SCpnt->result = result;
2005 if (!no_report || SCpnt != *SCpntp2)
2006 SCpnt->scsi_done(SCpnt);
2009 if (SCpnt == *SCpntp2)
2010 *SCpntp2 = NULL;
2013 /* Function: int fas216_eh_abort(Scsi_Cmnd *SCpnt)
2014 * Purpose : abort this command
2015 * Params : SCpnt - command to abort
2016 * Returns : FAILED if unable to abort
2018 int fas216_eh_abort(Scsi_Cmnd *SCpnt)
2020 return FAILED;
2023 /* Function: int fas216_eh_device_reset(Scsi_Cmnd *SCpnt)
2024 * Purpose : Reset the device associated with this command
2025 * Params : SCpnt - command specifing device to reset
2026 * Returns : FAILED if unable to reset
2028 int fas216_eh_device_reset(Scsi_Cmnd *SCpnt)
2030 return FAILED;
2033 /* Function: int fas216_eh_bus_reset(Scsi_Cmnd *SCpnt)
2034 * Purpose : Reset the complete bus associated with this command
2035 * Params : SCpnt - command specifing bus to reset
2036 * Returns : FAILED if unable to reset
2038 int fas216_eh_bus_reset(Scsi_Cmnd *SCpnt)
2040 return FAILED;
2043 /* Function: int fas216_eh_host_reset(Scsi_Cmnd *SCpnt)
2044 * Purpose : Reset the host associated with this command
2045 * Params : SCpnt - command specifing host to reset
2046 * Returns : FAILED if unable to reset
2048 int fas216_eh_host_reset(Scsi_Cmnd *SCpnt)
2050 return FAILED;
2053 enum res_abort { res_not_running, res_success, res_success_clear, res_snooze };
2056 * Prototype: enum res_abort fas216_do_abort(FAS216_Info *info, Scsi_Cmnd *SCpnt)
2057 * Purpose : abort a command on this host
2058 * Params : SCpnt - command to abort
2059 * Returns : abort status
2061 static enum res_abort
2062 fas216_do_abort(FAS216_Info *info, Scsi_Cmnd *SCpnt)
2064 enum res_abort res = res_not_running;
2066 if (queue_removecmd(&info->queues.issue, SCpnt)) {
2068 * The command was on the issue queue, and has not been
2069 * issued yet. We can remove the command from the queue,
2070 * and acknowledge the abort. Neither the devices nor the
2071 * interface know about the command.
2073 printk("on issue queue ");
2075 res = res_success;
2076 } else if (queue_removecmd(&info->queues.disconnected, SCpnt)) {
2078 * The command was on the disconnected queue. Simply
2079 * acknowledge the abort condition, and when the target
2080 * reconnects, we will give it an ABORT message. The
2081 * target should then disconnect, and we will clear
2082 * the busylun bit.
2084 printk("on disconnected queue ");
2086 res = res_success;
2087 } else if (info->SCpnt == SCpnt) {
2088 unsigned long flags;
2090 printk("executing ");
2092 save_flags(flags);
2093 cli();
2094 switch (info->scsi.phase) {
2096 * If the interface is idle, and the command is 'disconnectable',
2097 * then it is the same as on the disconnected queue. We simply
2098 * remove all traces of the command. When the target reconnects,
2099 * we will give it an ABORT message since the command could not
2100 * be found. When the target finally disconnects, we will clear
2101 * the busylun bit.
2103 case PHASE_IDLE:
2104 if (info->scsi.disconnectable) {
2105 info->scsi.disconnectable = 0;
2106 info->SCpnt = NULL;
2107 res = res_success;
2109 break;
2112 * If the command has connected and done nothing futher,
2113 * simply force a disconnect. We also need to clear the
2114 * busylun bit.
2116 case PHASE_SELECTION:
2117 // info->SCpnt = NULL;
2118 // res = res_success_clear;
2119 // break;
2121 default:
2122 res = res_snooze;
2123 break;
2125 restore_flags(flags);
2126 } else if (info->origSCpnt == SCpnt) {
2128 * The command will be executed next, but a command
2129 * is currently using the interface. This is similar to
2130 * being on the issue queue, except the busylun bit has
2131 * been set.
2133 info->origSCpnt = NULL;
2134 printk("waiting for execution ");
2135 res = res_success_clear;
2136 } else
2137 printk("unknown ");
2139 return res;
2142 /* Function: int fas216_abort(Scsi_Cmnd *SCpnt)
2143 * Purpose : abort a command if something horrible happens.
2144 * Params : SCpnt - Command that is believed to be causing a problem.
2145 * Returns : one of SCSI_ABORT_ macros.
2147 int fas216_abort(Scsi_Cmnd *SCpnt)
2149 FAS216_Info *info = (FAS216_Info *)SCpnt->host->hostdata;
2150 int result = SCSI_ABORT_SNOOZE;
2152 fas216_checkmagic(info, "fas216_abort");
2154 info->stats.aborts += 1;
2156 print_debug_list();
2157 fas216_dumpstate(info);
2158 fas216_dumpinfo(info);
2160 printk(KERN_WARNING "scsi%d: abort ", info->host->host_no);
2162 switch (fas216_do_abort(info, SCpnt)) {
2164 * We managed to find the command and cleared it out.
2165 * We do not expect the command to be executing on the
2166 * target, but we have set the busylun bit.
2168 case res_success_clear:
2169 printk("clear ");
2170 clear_bit(SCpnt->target * 8 + SCpnt->lun, info->busyluns);
2173 * We found the command, and cleared it out. Either
2174 * the command is still known to be executing on the
2175 * target, or the busylun bit is not set.
2177 case res_success:
2178 printk("success\n");
2179 SCpnt->result = DID_ABORT << 16;
2180 SCpnt->scsi_done(SCpnt);
2181 result = SCSI_ABORT_SUCCESS;
2182 break;
2185 * We did find the command, but unfortunately we couldn't
2186 * unhook it from ourselves. Wait some more, and if it
2187 * still doesn't complete, reset the interface.
2189 case res_snooze:
2190 printk("snooze\n");
2191 result = SCSI_ABORT_SNOOZE;
2192 break;
2195 * The command could not be found (either because it completed,
2196 * or it got dropped.
2198 default:
2199 case res_not_running:
2200 result = SCSI_ABORT_SNOOZE;
2201 printk("not running\n");
2202 break;
2205 return result;
2208 /* Function: void fas216_reset_state(FAS216_Info *info)
2209 * Purpose : Initialise driver internal state
2210 * Params : info - state to initialise
2212 static void fas216_reset_state(FAS216_Info *info)
2214 neg_t sync_state, wide_state;
2215 int i;
2217 fas216_checkmagic(info, "fas216_reset_state");
2220 * Clear out all stale info in our state structure
2222 memset(info->busyluns, 0, sizeof(info->busyluns));
2223 msgqueue_flush(&info->scsi.msgs);
2224 info->scsi.reconnected.target = 0;
2225 info->scsi.reconnected.lun = 0;
2226 info->scsi.reconnected.tag = 0;
2227 info->scsi.disconnectable = 0;
2228 info->scsi.aborting = 0;
2229 info->scsi.phase = PHASE_IDLE;
2230 info->scsi.async_stp =
2231 fas216_syncperiod(info, info->ifcfg.asyncperiod);
2233 if (info->ifcfg.wide_max_size == 0)
2234 wide_state = neg_invalid;
2235 else
2236 #ifdef SCSI2_WIDE
2237 wide_state = neg_wait;
2238 #else
2239 wide_state = neg_invalid;
2240 #endif
2242 if (info->host->dma_channel == NO_DMA || !info->dma.setup)
2243 sync_state = neg_invalid;
2244 else
2245 #ifdef SCSI2_SYNC
2246 sync_state = neg_wait;
2247 #else
2248 sync_state = neg_invalid;
2249 #endif
2251 for (i = 0; i < 8; i++) {
2252 info->device[i].disconnect_ok = info->ifcfg.disconnect_ok;
2253 info->device[i].sync_state = sync_state;
2254 info->device[i].wide_state = wide_state;
2255 info->device[i].period = info->ifcfg.asyncperiod / 4;
2256 info->device[i].stp = info->scsi.async_stp;
2257 info->device[i].sof = 0;
2258 info->device[i].wide_xfer = 0;
2262 /* Function: void fas216_init_chip(FAS216_Info *info)
2263 * Purpose : Initialise FAS216 state after reset
2264 * Params : info - state structure for interface
2266 static void fas216_init_chip(FAS216_Info *info)
2268 fas216_checkmagic(info, "fas216_init_chip");
2270 outb(fas216_clockrate(info->ifcfg.clockrate), REG_CLKF(info));
2271 outb(info->scsi.cfg[0], REG_CNTL1(info));
2272 outb(info->scsi.cfg[1], REG_CNTL2(info));
2273 outb(info->scsi.cfg[2], REG_CNTL3(info));
2274 outb(info->ifcfg.select_timeout, REG_STIM(info));
2275 outb(0, REG_SOF(info));
2276 outb(info->scsi.async_stp, REG_STP(info));
2277 outb(info->scsi.cfg[0], REG_CNTL1(info));
2280 /* Function: int fas216_reset(Scsi_Cmnd *SCpnt, unsigned int reset_flags)
2281 * Purpose : resets the adapter if something horrible happens.
2282 * Params : SCpnt - Command that is believed to be causing a problem.
2283 * reset_flags - flags indicating reset type that is believed
2284 * to be required.
2285 * Returns : one of SCSI_RESET_ macros, or'd with the SCSI_RESET_*_RESET
2286 * macros.
2288 int fas216_reset(Scsi_Cmnd *SCpnt, unsigned int reset_flags)
2290 FAS216_Info *info = (FAS216_Info *)SCpnt->host->hostdata;
2291 Scsi_Cmnd *SCptr;
2292 int result = 0;
2293 int synchronous = reset_flags & SCSI_RESET_SYNCHRONOUS;
2295 fas216_checkmagic(info, "fas216_reset");
2298 * Validate that command is actually on one of our queues if we're doing
2299 * an asynchronous reset
2301 if (reset_flags & SCSI_RESET_ASYNCHRONOUS &&
2302 SCpnt &&
2303 info->SCpnt != SCpnt &&
2304 info->origSCpnt != SCpnt &&
2305 !queue_cmdonqueue(&info->queues.disconnected, SCpnt) &&
2306 !queue_cmdonqueue(&info->queues.issue, SCpnt)) {
2307 printk("scsi%d: fas216_reset: asynchronous reset for unknown command\n",
2308 info->host->host_no);
2309 return SCSI_RESET_NOT_RUNNING;
2312 info->stats.resets += 1;
2314 print_debug_list();
2315 printk(KERN_WARNING "scsi%d: reset ", info->host->host_no);
2316 if (SCpnt)
2317 printk("for target %d ", SCpnt->target);
2319 printk("\n");
2321 outb(info->scsi.cfg[3], REG_CNTL3(info));
2323 fas216_stoptransfer(info);
2325 switch (reset_flags & (SCSI_RESET_SUGGEST_BUS_RESET | SCSI_RESET_SUGGEST_HOST_RESET)) {
2326 case SCSI_RESET_SUGGEST_BUS_RESET:
2327 outb(CMD_RESETSCSI, REG_CMD(info));
2328 outb(CMD_NOP, REG_CMD(info));
2329 result |= SCSI_RESET_BUS_RESET;
2330 break;
2332 case SCSI_RESET_SUGGEST_HOST_RESET:
2333 outb(CMD_RESETCHIP, REG_CMD(info));
2334 outb(CMD_NOP, REG_CMD(info));
2335 result |= SCSI_RESET_HOST_RESET;
2336 break;
2338 default:
2339 outb(CMD_RESETCHIP, REG_CMD(info));
2340 outb(CMD_NOP, REG_CMD(info));
2341 outb(CMD_RESETSCSI, REG_CMD(info));
2342 result |= SCSI_RESET_HOST_RESET | SCSI_RESET_BUS_RESET;
2343 break;
2346 udelay(300);
2347 fas216_reset_state(info);
2348 fas216_init_chip(info);
2351 * Signal all commands in progress have been reset
2353 fas216_reportstatus(&info->SCpnt, &SCpnt, DID_RESET << 16, synchronous);
2355 while ((SCptr = queue_remove(&info->queues.disconnected)) != NULL)
2356 fas216_reportstatus(&SCptr, &SCpnt, DID_RESET << 16, synchronous);
2358 if (SCpnt) {
2360 * Command not found on disconnected queue, nor currently
2361 * executing command - check pending commands
2363 if (info->origSCpnt == SCpnt)
2364 info->origSCpnt = NULL;
2366 queue_removecmd(&info->queues.issue, SCpnt);
2368 SCpnt->result = DID_RESET << 16;
2369 if (!synchronous)
2370 SCpnt->scsi_done(SCpnt);
2373 return result | SCSI_RESET_SUCCESS;
2376 /* Function: int fas216_init(struct Scsi_Host *instance)
2377 * Purpose : initialise FAS/NCR/AMD SCSI ic.
2378 * Params : instance - a driver-specific filled-out structure
2379 * Returns : 0 on success
2381 int fas216_init(struct Scsi_Host *instance)
2383 FAS216_Info *info = (FAS216_Info *)instance->hostdata;
2384 unsigned long flags;
2385 int target_jiffies;
2387 info->magic_start = MAGIC;
2388 info->magic_end = MAGIC;
2390 info->host = instance;
2391 info->scsi.cfg[0] = instance->this_id;
2392 info->scsi.cfg[1] = CNTL2_ENF | CNTL2_S2FE;
2393 info->scsi.cfg[2] = info->ifcfg.cntl3 | CNTL3_ADIDCHK | CNTL3_G2CB;
2394 info->scsi.type = "unknown";
2395 info->SCpnt = NULL;
2396 fas216_reset_state(info);
2398 memset(&info->stats, 0, sizeof(info->stats));
2400 msgqueue_initialise(&info->scsi.msgs);
2402 if (!queue_initialise(&info->queues.issue))
2403 return 1;
2405 if (!queue_initialise(&info->queues.disconnected)) {
2406 queue_free(&info->queues.issue);
2407 return 1;
2410 outb(CMD_RESETCHIP, REG_CMD(info));
2412 outb(0, REG_CNTL3(info));
2413 outb(CNTL2_S2FE, REG_CNTL2(info));
2415 if ((inb(REG_CNTL2(info)) & (~0xe0)) != CNTL2_S2FE) {
2416 info->scsi.type = "NCR53C90";
2417 } else {
2418 outb(0, REG_CNTL2(info));
2419 outb(0, REG_CNTL3(info));
2420 outb(5, REG_CNTL3(info));
2421 if (inb(REG_CNTL3(info)) != 5) {
2422 info->scsi.type = "NCR53C90A";
2423 } else {
2424 outb(0, REG_CNTL3(info));
2425 info->scsi.type = "NCR53C9x";
2430 outb(CNTL3_ADIDCHK, REG_CNTL3(info));
2431 outb(0, REG_CNTL3(info));
2433 outb(CMD_RESETCHIP, REG_CMD(info));
2434 outb(CMD_WITHDMA | CMD_NOP, REG_CMD(info));
2435 outb(CNTL2_ENF, REG_CNTL2(info));
2436 outb(CMD_RESETCHIP, REG_CMD(info));
2437 switch (inb(REG1_ID(info))) {
2438 case 12:
2439 info->scsi.type = "Am53CF94";
2440 break;
2441 default:
2442 break;
2445 udelay(300);
2446 /* now for the real initialisation */
2447 fas216_init_chip(info);
2449 outb(info->scsi.cfg[0] | CNTL1_DISR, REG_CNTL1(info));
2450 outb(CMD_RESETSCSI, REG_CMD(info));
2452 /* scsi standard says 250ms */
2453 target_jiffies = jiffies + (25 * HZ) / 100;
2454 save_flags(flags);
2455 sti();
2457 while (time_before(jiffies, target_jiffies)) barrier();
2459 restore_flags(flags);
2461 outb(info->scsi.cfg[0], REG_CNTL1(info));
2462 inb(REG_INST(info));
2464 /* now for the real initialisation */
2465 fas216_init_chip(info);
2467 fas216_checkmagic(info, "fas216_init");
2469 return 0;
2472 /* Function: int fas216_release(struct Scsi_Host *instance)
2473 * Purpose : release all resources and put everything to bed for
2474 * FAS/NCR/AMD SCSI ic.
2475 * Params : instance - a driver-specific filled-out structure
2476 * Returns : 0 on success
2478 int fas216_release(struct Scsi_Host *instance)
2480 FAS216_Info *info = (FAS216_Info *)instance->hostdata;
2482 fas216_checkmagic(info, "fas216_release");
2484 outb(CMD_RESETCHIP, REG_CMD(info));
2485 queue_free(&info->queues.disconnected);
2486 queue_free(&info->queues.issue);
2488 return 0;
2491 int fas216_print_stats(FAS216_Info *info, char *buffer)
2493 return sprintf(buffer,
2494 "Queued commands: %-10u Issued commands: %-10u\n"
2495 "Done commands : %-10u Reads : %-10u\n"
2496 "Writes : %-10u Others : %-10u\n"
2497 "Disconnects : %-10u Aborts : %-10u\n"
2498 "Resets : %-10u\n",
2499 info->stats.queues, info->stats.removes,
2500 info->stats.fins, info->stats.reads,
2501 info->stats.writes, info->stats.miscs,
2502 info->stats.disconnects, info->stats.aborts,
2503 info->stats.resets);
2506 int fas216_print_device(FAS216_Info *info, Scsi_Device *scd, char *buffer)
2508 struct fas216_device *dev = &info->device[scd->id];
2509 int len = 0;
2510 char *p;
2512 proc_print_scsidevice(scd, buffer, &len, 0);
2513 p = buffer + len;
2515 p += sprintf(p, " Extensions: ");
2517 if (scd->tagged_supported)
2518 p += sprintf(p, "TAG %sabled [%d] ",
2519 scd->tagged_queue ? "en" : "dis",
2520 scd->current_tag);
2522 p += sprintf(p, "\n Transfers : %d-bit ",
2523 8 << dev->wide_xfer);
2525 if (dev->sof)
2526 p += sprintf(p, "sync offset %d, %d ns\n",
2527 dev->sof, dev->period * 4);
2528 else
2529 p += sprintf(p, "async\n");
2531 return p - buffer;
2534 EXPORT_SYMBOL(fas216_init);
2535 EXPORT_SYMBOL(fas216_abort);
2536 EXPORT_SYMBOL(fas216_reset);
2537 EXPORT_SYMBOL(fas216_queue_command);
2538 EXPORT_SYMBOL(fas216_command);
2539 EXPORT_SYMBOL(fas216_intr);
2540 EXPORT_SYMBOL(fas216_release);
2541 EXPORT_SYMBOL(fas216_eh_abort);
2542 EXPORT_SYMBOL(fas216_eh_device_reset);
2543 EXPORT_SYMBOL(fas216_eh_bus_reset);
2544 EXPORT_SYMBOL(fas216_eh_host_reset);
2545 EXPORT_SYMBOL(fas216_print_stats);
2546 EXPORT_SYMBOL(fas216_print_device);
2548 #ifdef MODULE
2549 int init_module(void)
2551 return 0;
2554 void cleanup_module(void)
2557 #endif