This commit was manufactured by cvs2svn to create tag 'FreeBSD-release/1.0'.
[unix-history] / sys / i386 / isa / bt742a.c
CommitLineData
15637ed4
RG
1/*
2 * Written by Julian Elischer (julian@tfs.com)
3 * for TRW Financial Systems for use under the MACH(2.5) operating system.
4 *
5 * TRW Financial Systems, in accordance with their agreement with Carnegie
6 * Mellon University, makes this software available to CMU to distribute
7 * or use in any manner that they see fit as long as this message is kept with
8 * the software. For this reason TFS also grants any other persons or
9 * organisations permission to use or modify this software.
10 *
11 * TFS supplies this software to be publicly redistributed
12 * on the understanding that TFS is not responsible for the correct
13 * functioning of this software in any circumstances.
14 *
78ed81a3 15 * $Id: bt742a.c,v 1.7 1993/08/28 03:07:42 rgrimes Exp $
15637ed4
RG
16 */
17
18/*
78ed81a3 19 * bt742a SCSI driver
15637ed4
RG
20 */
21
22#include <sys/types.h>
23#include <bt.h>
24
25#include <sys/param.h>
26#include <sys/systm.h>
27#include <sys/errno.h>
28#include <sys/ioctl.h>
29#include <sys/buf.h>
30#include <sys/proc.h>
31#include <sys/user.h>
32
33#ifdef MACH /* EITHER CMU OR OSF */
34#include <i386/ipl.h>
35#include <i386at/scsi.h>
36#include <i386at/scsiconf.h>
37
38#ifdef OSF /* OSF ONLY */
39#include <sys/table.h>
40#include <i386/handler.h>
41#include <i386/dispatcher.h>
42#include <i386/AT386/atbus.h>
43
44#else OSF /* CMU ONLY */
45#include <i386at/atbus.h>
46#include <i386/pio.h>
47#endif OSF
48#endif MACH /* end of MACH specific */
49
50#ifdef __386BSD__ /* 386BSD specific */
51#define isa_dev isa_device
52#define dev_unit id_unit
53#define dev_addr id_iobase
54
55#include <i386/isa/isa_device.h>
56#include <scsi/scsi_all.h>
57#include <scsi/scsiconf.h>
58#endif __386BSD__
59
60
61#ifdef __386BSD__
62#include "ddb.h"
63#if NDDB > 0
64int Debugger();
65#else NDDB
78ed81a3 66#define Debugger() panic("should call debugger here (bt742a.c)")
15637ed4
RG
67#endif NDDB
68#endif __386BSD__
69
70#ifdef MACH
71int Debugger();
72#endif MACH
73
78ed81a3 74extern int hz;
15637ed4
RG
75extern int delaycount; /* from clock setup code */
76typedef unsigned long int physaddr;
77
78/*
79 * I/O Port Interface
80 */
81
82#define BT_BASE bt_base[unit]
83#define BT_CTRL_STAT_PORT (BT_BASE + 0x0) /* control & status */
84#define BT_CMD_DATA_PORT (BT_BASE + 0x1) /* cmds and datas */
85#define BT_INTR_PORT (BT_BASE + 0x2) /* Intr. stat */
86
87/*
88 * BT_CTRL_STAT bits (write)
89 */
90
91#define BT_HRST 0x80 /* Hardware reset */
92#define BT_SRST 0x40 /* Software reset */
93#define BT_IRST 0x20 /* Interrupt reset */
94#define BT_SCRST 0x10 /* SCSI bus reset */
95
96/*
97 * BT_CTRL_STAT bits (read)
98 */
99
100#define BT_STST 0x80 /* Self test in Progress */
101#define BT_DIAGF 0x40 /* Diagnostic Failure */
102#define BT_INIT 0x20 /* Mbx Init required */
103#define BT_IDLE 0x10 /* Host Adapter Idle */
104#define BT_CDF 0x08 /* cmd/data out port full */
105#define BT_DF 0x04 /* Data in port full */
106#define BT_INVDCMD 0x01 /* Invalid command */
107
108/*
109 * BT_CMD_DATA bits (write)
110 */
111
112#define BT_NOP 0x00 /* No operation */
113#define BT_MBX_INIT 0x01 /* Mbx initialization */
114#define BT_START_SCSI 0x02 /* start scsi command */
115#define BT_START_BIOS 0x03 /* start bios command */
116#define BT_INQUIRE 0x04 /* Adapter Inquiry */
117#define BT_MBO_INTR_EN 0x05 /* Enable MBO available interrupt */
118#define BT_SEL_TIMEOUT_SET 0x06 /* set selection time-out */
119#define BT_BUS_ON_TIME_SET 0x07 /* set bus-on time */
120#define BT_BUS_OFF_TIME_SET 0x08 /* set bus-off time */
121#define BT_SPEED_SET 0x09 /* set transfer speed */
122#define BT_DEV_GET 0x0a /* return installed devices */
123#define BT_CONF_GET 0x0b /* return configuration data */
124#define BT_TARGET_EN 0x0c /* enable target mode */
125#define BT_SETUP_GET 0x0d /* return setup data */
126#define BT_WRITE_CH2 0x1a /* write channel 2 buffer */
127#define BT_READ_CH2 0x1b /* read channel 2 buffer */
128#define BT_WRITE_FIFO 0x1c /* write fifo buffer */
129#define BT_READ_FIFO 0x1d /* read fifo buffer */
130#define BT_ECHO 0x1e /* Echo command data */
131#define BT_MBX_INIT_EXTENDED 0x81 /* Mbx initialization */
132#define BT_INQUIRE_EXTENDED 0x8D /* Adapter Setup Inquiry */
133
78ed81a3 134/* Follows command appeared at FirmWare 3.31 */
135#define BT_ROUND_ROBIN 0x8f /* Enable/Disable(default) round robin */
136#define BT_DISABLE 0x00 /* Parameter value for Disable */
137#define BT_ENABLE 0x01 /* Parameter value for Enable */
138
15637ed4
RG
139struct bt_cmd_buf {
140 u_char byte[16];
141};
142
143/*
144 * BT_INTR_PORT bits (read)
145 */
146
78ed81a3 147#define BT_ANY_INTR 0x80 /* Any interrupt */
15637ed4
RG
148#define BT_SCRD 0x08 /* SCSI reset detected */
149#define BT_HACC 0x04 /* Command complete */
150#define BT_MBOA 0x02 /* MBX out empty */
151#define BT_MBIF 0x01 /* MBX in full */
152
153/*
154 * Mail box defs
155 */
156
78ed81a3 157#define BT_MBX_SIZE 255 /* mail box size (MAX 255 MBxs) */
158#define BT_CCB_SIZE 32 /* store up to 32CCBs at any one time */
159 /* in bt742a H/W ( Not MAX ? ) */
160
161#define bt_nextmbx( wmb, mbx, mbio ) \
162 if ( (wmb) == &((mbx)->mbio[BT_MBX_SIZE - 1 ]) ) { \
163 (wmb) = &((mbx)->mbio[0]); \
164 } else { \
165 (wmb)++; \
166 }
167
168
169typedef struct bt_mbx_out {
170 physaddr ccb_addr;
171 unsigned char dummy[3];
172 unsigned char cmd;
173} BT_MBO;
174
175typedef struct bt_mbx_in{
176 physaddr ccb_addr;
177 unsigned char btstat;
178 unsigned char sdstat;
179 unsigned char dummy;
180 unsigned char stat;
181} BT_MBI;
15637ed4
RG
182
183struct bt_mbx
184{
78ed81a3 185 BT_MBO mbo[BT_MBX_SIZE];
186 BT_MBI mbi[BT_MBX_SIZE];
187 BT_MBO *tmbo; /* Target Mail Box out */
188 BT_MBI *tmbi; /* Target Mail Box in */
15637ed4
RG
189};
190
191/*
192 * mbo.cmd values
193 */
194
195#define BT_MBO_FREE 0x0 /* MBO entry is free */
196#define BT_MBO_START 0x1 /* MBO activate entry */
197#define BT_MBO_ABORT 0x2 /* MBO abort entry */
198
199#define BT_MBI_FREE 0x0 /* MBI entry is free */
200#define BT_MBI_OK 0x1 /* completed without error */
201#define BT_MBI_ABORT 0x2 /* aborted ccb */
202#define BT_MBI_UNKNOWN 0x3 /* Tried to abort invalid CCB */
203#define BT_MBI_ERROR 0x4 /* Completed with error */
204
205extern struct bt_mbx bt_mbx[];
206
207#if defined(BIG_DMA)
208/* #define BT_NSEG 8192 /* Number of scatter gather segments - to much vm */
209#define BT_NSEG 512
210#else
211#define BT_NSEG 33
212#endif /* BIG_DMA */
213struct bt_scat_gath
214 {
215 unsigned long seg_len;
216 physaddr seg_addr;
217 };
218
219struct bt_ccb {
220 unsigned char opcode;
221 unsigned char :3,data_in:1,data_out:1,:3;
222 unsigned char scsi_cmd_length;
223 unsigned char req_sense_length;
224 /*------------------------------------longword boundary */
225 unsigned long data_length;
226 /*------------------------------------longword boundary */
227 physaddr data_addr;
228 /*------------------------------------longword boundary */
229 unsigned char dummy[2];
230 unsigned char host_stat;
231 unsigned char target_stat;
232 /*------------------------------------longword boundary */
233 unsigned char target;
234 unsigned char lun;
235 unsigned char scsi_cmd[12]; /* 12 bytes (bytes only)*/
236 unsigned char dummy2[1];
237 unsigned char link_id;
238 /*------------------------------------4 longword boundary */
239 physaddr link_addr;
240 /*------------------------------------longword boundary */
241 physaddr sense_ptr;
242 /*------------------------------------longword boundary */
243 struct scsi_sense_data scsi_sense;
244 /*------------------------------------longword boundary */
245 struct bt_scat_gath scat_gath[BT_NSEG];
246 /*------------------------------------longword boundary */
247 struct bt_ccb *next;
248 /*------------------------------------longword boundary */
249 struct scsi_xfer *xfer; /* the scsi_xfer for this cmd */
250 /*------------------------------------longword boundary */
251 struct bt_mbx_out *mbx; /* pointer to mail box */
252 /*------------------------------------longword boundary */
15637ed4
RG
253 int flags;
254#define CCB_FREE 0
255#define CCB_ACTIVE 1
256#define CCB_ABORTED 2
257};
258
15637ed4
RG
259/*
260 * opcode fields
261 */
262
263#define BT_INITIATOR_CCB 0x00 /* SCSI Initiator CCB */
264#define BT_TARGET_CCB 0x01 /* SCSI Target CCB */
265#define BT_INIT_SCAT_GATH_CCB 0x02 /* SCSI Initiator with scattter gather*/
266#define BT_RESET_CCB 0x81 /* SCSI Bus reset */
267
268
269/*
270 * bt_ccb.host_stat values
271 */
272
273#define BT_OK 0x00 /* cmd ok */
274#define BT_LINK_OK 0x0a /* Link cmd ok */
275#define BT_LINK_IT 0x0b /* Link cmd ok + int */
276#define BT_SEL_TIMEOUT 0x11 /* Selection time out */
277#define BT_OVER_UNDER 0x12 /* Data over/under run */
278#define BT_BUS_FREE 0x13 /* Bus dropped at unexpected time */
279#define BT_INV_BUS 0x14 /* Invalid bus phase/sequence */
280#define BT_BAD_MBO 0x15 /* Incorrect MBO cmd */
281#define BT_BAD_CCB 0x16 /* Incorrect ccb opcode */
282#define BT_BAD_LINK 0x17 /* Not same values of LUN for links */
283#define BT_INV_TARGET 0x18 /* Invalid target direction */
284#define BT_CCB_DUP 0x19 /* Duplicate CCB received */
285#define BT_INV_CCB 0x1a /* Invalid CCB or segment list */
286#define BT_ABORTED 42 /* pseudo value from driver */
287
78ed81a3 288struct bt_boardID
289{
290 u_char board_type;
291 u_char custom_feture;
292 char firm_revision;
293 u_char firm_version;
294};
15637ed4
RG
295
296struct bt_setup
297{
298 u_char sync_neg:1;
299 u_char parity:1;
300 u_char :6;
301 u_char speed;
302 u_char bus_on;
303 u_char bus_off;
304 u_char num_mbx;
78ed81a3 305 u_char mbx[3];
306 struct {
15637ed4
RG
307 u_char offset:4;
308 u_char period:3;
309 u_char valid:1;
310 }sync[8];
311 u_char disc_sts;
312};
313
314struct bt_config
315{
316 u_char chan;
317 u_char intr;
318 u_char scsi_dev:3;
319 u_char :5;
320};
321
322#define INT9 0x01
323#define INT10 0x02
324#define INT11 0x04
325#define INT12 0x08
326#define INT14 0x20
327#define INT15 0x40
328
329#define EISADMA 0x00
330#define CHAN0 0x01
331#define CHAN5 0x20
332#define CHAN6 0x40
333#define CHAN7 0x80
334
335
336
337
338#ifdef MACH
339extern physaddr kvtophys();
340#define PHYSTOKV(x) phystokv(x)
341#define KVTOPHYS(x) kvtophys(x)
342#endif MACH
343
344#ifdef __386BSD__
15637ed4
RG
345#define KVTOPHYS(x) vtophys(x)
346#endif __386BSD__
347
348
349
350#define PAGESIZ 4096
351#define INVALIDATE_CACHE {asm volatile( ".byte 0x0F ;.byte 0x08" ); }
352
353
354u_char bt_scratch_buf[256];
355#ifdef MACH
356caddr_t bt_base[NBT]; /* base port for each board */
357#else MACH
358short bt_base[NBT]; /* base port for each board */
359#endif MACH
360struct bt_mbx bt_mbx[NBT];
361struct bt_ccb *bt_ccb_free[NBT];
78ed81a3 362struct bt_ccb bt_ccb[NBT][BT_CCB_SIZE];
15637ed4
RG
363struct scsi_xfer bt_scsi_xfer[NBT];
364struct isa_dev *btinfo[NBT];
365struct bt_ccb *bt_get_ccb();
366int bt_int[NBT];
367int bt_dma[NBT];
368int bt_scsi_dev[NBT];
369int bt_initialized[NBT];
370#if defined(OSF)
371int bt_attached[NBT];
372#endif /* defined(OSF) */
373
374/***********debug values *************/
375#define BT_SHOWCCBS 0x01
376#define BT_SHOWINTS 0x02
377#define BT_SHOWCMDS 0x04
378#define BT_SHOWMISC 0x08
379int bt_debug = 0;
380
381
382int btprobe(), btattach();
383int btintr();
384
385#ifdef MACH
386struct isa_driver btdriver = { btprobe, 0, btattach, "bt", 0, 0, 0};
387int (*btintrs[])() = {btintr, 0};
388#endif MACH
389
390#ifdef __386BSD__
391struct isa_driver btdriver = { btprobe, btattach, "bt"};
392#endif __386BSD__
393
394static int btunit = 0;
395
15637ed4
RG
396int bt_scsi_cmd();
397int bt_timeout();
398void btminphys();
399long int bt_adapter_info();
400
401struct scsi_switch bt_switch =
402{
403 bt_scsi_cmd,
404 btminphys,
405 0,
406 0,
407 bt_adapter_info,
78ed81a3 408 "bt",
409 0,0
15637ed4
RG
410};
411#define BT_CMD_TIMEOUT_FUDGE 200 /* multiplied to get Secs */
412#define BT_RESET_TIMEOUT 1000000
413#define BT_SCSI_TIMEOUT_FUDGE 20 /* divided by for mSecs */
414
415
416/***********************************************************************\
417* bt_cmd(unit,icnt, ocnt,wait, retval, opcode, args) *
418* Activate Adapter command *
419* icnt: number of args (outbound bytes written after opcode) *
420* ocnt: number of expected returned bytes *
421* wait: number of seconds to wait for response *
422* retval: buffer where to place returned bytes *
423* opcode: opcode BT_NOP, BT_MBX_INIT, BT_START_SCSI ... *
424* args: parameters *
425* *
426* Performs an adapter command through the ports. Not to be confused *
427* with a scsi command, which is read in via the dma *
428* One of the adapter commands tells it to read in a scsi command *
429\***********************************************************************/
430bt_cmd(unit,icnt, ocnt, wait,retval, opcode, args)
431
432u_char *retval;
433unsigned opcode;
434u_char args;
435{
436 unsigned *ic = &opcode;
437 u_char oc;
438 register i;
439 int sts;
440
441 /*******************************************************\
442 * multiply the wait argument by a big constant *
443 * zero defaults to 1 *
444 \*******************************************************/
445 if(!wait)
446 wait = BT_CMD_TIMEOUT_FUDGE * delaycount;
447 else
448 wait *= BT_CMD_TIMEOUT_FUDGE * delaycount;
449 /*******************************************************\
450 * Wait for the adapter to go idle, unless it's one of *
451 * the commands which don't need this *
452 \*******************************************************/
453 if (opcode != BT_MBX_INIT && opcode != BT_START_SCSI)
454 {
455 i = BT_CMD_TIMEOUT_FUDGE * delaycount; /* 1 sec?*/
456 while (--i)
457 {
458 sts = inb(BT_CTRL_STAT_PORT);
459 if (sts & BT_IDLE)
460 {
461 break;
462 }
463 }
464 if (!i)
465 {
78ed81a3 466 printf("bt%d: bt_cmd, host not idle(0x%x)\n",unit,sts);
15637ed4
RG
467 return(ENXIO);
468 }
469 }
470 /*******************************************************\
471 * Now that it is idle, if we expect output, preflush the*
472 * queue feeding to us. *
473 \*******************************************************/
474 if (ocnt)
475 {
476 while((inb(BT_CTRL_STAT_PORT)) & BT_DF)
477 inb(BT_CMD_DATA_PORT);
478 }
479
480 /*******************************************************\
481 * Output the command and the number of arguments given *
482 * for each byte, first check the port is empty. *
483 \*******************************************************/
484 icnt++; /* include the command */
485 while (icnt--)
486 {
487 sts = inb(BT_CTRL_STAT_PORT);
488 for (i=0; i< wait; i++)
489 {
490 sts = inb(BT_CTRL_STAT_PORT);
491 if (!(sts & BT_CDF))
492 break;
493 }
494 if (i >= wait)
495 {
78ed81a3 496 printf("bt%d: bt_cmd, cmd/data port full\n",unit);
15637ed4
RG
497 outb(BT_CTRL_STAT_PORT, BT_SRST);
498 return(ENXIO);
499 }
500 outb(BT_CMD_DATA_PORT, (u_char)(*ic++));
501 }
502 /*******************************************************\
503 * If we expect input, loop that many times, each time, *
504 * looking for the data register to have valid data *
505 \*******************************************************/
506 while (ocnt--)
507 {
508 sts = inb(BT_CTRL_STAT_PORT);
509 for (i=0; i< wait; i++)
510 {
511 sts = inb(BT_CTRL_STAT_PORT);
512 if (sts & BT_DF)
513 break;
514 }
515 if (i >= wait)
516 {
78ed81a3 517 printf("bt%d: bt_cmd, cmd/data port empty %d\n",
518 unit,ocnt);
15637ed4
RG
519 return(ENXIO);
520 }
521 oc = inb(BT_CMD_DATA_PORT);
522 if (retval)
523 *retval++ = oc;
524 }
525 /*******************************************************\
526 * Wait for the board to report a finised instruction *
527 \*******************************************************/
528 i=BT_CMD_TIMEOUT_FUDGE * delaycount; /* 1 sec? */
529 while (--i)
530 {
531 sts = inb(BT_INTR_PORT);
532 if (sts & BT_HACC)
533 {
534 break;
535 }
536 }
537 if (!i)
538 {
78ed81a3 539 printf("bt%d: bt_cmd, host not finished(0x%x)\n",unit,sts);
15637ed4
RG
540 return(ENXIO);
541 }
542 outb(BT_CTRL_STAT_PORT, BT_IRST);
543 return(0);
544}
545
546/*******************************************************\
547* Check if the device can be found at the port given *
548* and if so, set it up ready for further work *
549* as an argument, takes the isa_dev structure from *
550* autoconf.c *
551\*******************************************************/
552
553btprobe(dev)
554struct isa_dev *dev;
555{
556 /***********************************************\
557 * find unit and check we have that many defined *
558 \***********************************************/
559 int unit = btunit;
560#if defined(OSF)
561 static ihandler_t bt_handler[NBT];
562 static ihandler_id_t *bt_handler_id[NBT];
563 register ihandler_t *chp = &bt_handler[unit];;
564#endif /* defined(OSF) */
565
566 dev->dev_unit = unit;
567 bt_base[unit] = dev->dev_addr;
568 if(unit >= NBT)
569 {
78ed81a3 570 printf("bt%d: unit number too high\n",unit);
15637ed4
RG
571 return(0);
572 }
573 /***********************************************\
574 * Try initialise a unit at this location *
575 * sets up dma and bus speed, loads bt_int[unit]*
576 \***********************************************/
577 if (bt_init(unit) != 0)
578 {
579 return(0);
580 }
581
582 /***********************************************\
583 * If it's there, put in it's interrupt vectors *
584 \***********************************************/
585#ifdef MACH
78ed81a3 586 dev->dev_pic = bt_int[unit];
15637ed4
RG
587#if defined(OSF) /* OSF */
588 chp->ih_level = dev->dev_pic;
589 chp->ih_handler = dev->dev_intr[0];
590 chp->ih_resolver = i386_resolver;
591 chp->ih_rdev = dev;
592 chp->ih_stats.intr_type = INTR_DEVICE;
593 chp->ih_stats.intr_cnt = 0;
594 chp->ih_hparam[0].intparam = unit;
595 if ((bt_handler_id[unit] = handler_add(chp)) != NULL)
596 handler_enable(bt_handler_id[unit]);
597 else
598 panic("Unable to add bt interrupt handler");
599#else /* CMU */
15637ed4
RG
600 take_dev_irq(dev);
601#endif /* !defined(OSF) */
602 printf("port=%x spl=%d\n", dev->dev_addr, dev->dev_spl);
603#endif MACH
604#ifdef __386BSD__ /* 386BSD */
605 dev->id_irq = (1 << bt_int[unit]);
606 dev->id_drq = bt_dma[unit];
15637ed4
RG
607#endif __386BSD__
608
609 btunit++;
610 return(1);
611}
612
613/***********************************************\
614* Attach all the sub-devices we can find *
615\***********************************************/
616btattach(dev)
617struct isa_dev *dev;
618{
619 int unit = dev->dev_unit;
620
621
15637ed4
RG
622 /***********************************************\
623 * ask the adapter what subunits are present *
624 \***********************************************/
625 scsi_attachdevs( unit, bt_scsi_dev[unit], &bt_switch);
626#if defined(OSF)
627 bt_attached[unit]=1;
628#endif /* defined(OSF) */
15637ed4
RG
629 return;
630}
631
632/***********************************************\
633* Return some information to the caller about *
634* the adapter and it's capabilities *
635\***********************************************/
636long int bt_adapter_info(unit)
637int unit;
638{
639 return(2); /* 2 outstanding requests at a time per device */
640}
641
642/***********************************************\
643* Catch an interrupt from the adaptor *
644\***********************************************/
645btintr(unit)
646{
78ed81a3 647 BT_MBI *wmbi;
648 struct bt_mbx *wmbx;
15637ed4
RG
649 struct bt_ccb *ccb;
650 unsigned char stat;
78ed81a3 651 int i,wait;
652 int found = 0;
15637ed4 653
78ed81a3 654#ifdef UTEST
15637ed4
RG
655 if(scsi_debug & PRINTROUTINES)
656 printf("btintr ");
78ed81a3 657#endif
15637ed4
RG
658 /***********************************************\
659 * First acknowlege the interrupt, Then if it's *
660 * not telling about a completed operation *
661 * just return. *
662 \***********************************************/
663 stat = inb(BT_INTR_PORT);
78ed81a3 664
665 /* Mail Box out empty ? */
666 if ( stat & BT_MBOA ) {
667 printf("bt%d: Available Free mbo post\n",unit);
668 /* Disable MBO available interrupt */
669 outb(BT_CMD_DATA_PORT,BT_MBO_INTR_EN);
670 wait = BT_CMD_TIMEOUT_FUDGE * delaycount;
671 for (i=0; i< wait; i++)
672 {
673 if (!(inb(BT_CTRL_STAT_PORT) & BT_CDF))
674 break;
675 }
676 if (i >= wait)
677 {
678 printf("bt%d: bt_intr, cmd/data port full\n",unit);
679 outb(BT_CTRL_STAT_PORT, BT_SRST);
680 return 1;
681 }
682 outb(BT_CMD_DATA_PORT, 0x00); /* Disable */
683 wakeup(&bt_mbx[unit]);
684 outb(BT_CTRL_STAT_PORT, BT_IRST);
15637ed4 685 return 1;
78ed81a3 686 }
687 if (! (stat & BT_MBIF)) {
688 outb(BT_CTRL_STAT_PORT, BT_IRST);
689 return 1;
690 }
15637ed4
RG
691#if defined(OSF)
692 if (!bt_attached[unit])
693 {
694 return(1);
695 }
696#endif /* defined(OSF) */
697 /***********************************************\
698 * If it IS then process the competed operation *
699 \***********************************************/
78ed81a3 700 wmbx = &bt_mbx[unit];
701 wmbi = wmbx->tmbi;
702AGAIN:
703 while ( wmbi->stat != BT_MBI_FREE ) {
704 found++;
705 ccb = (struct bt_ccb *)PHYSTOKV((wmbi->ccb_addr));
706 if((stat = wmbi->stat) != BT_MBI_OK)
15637ed4 707 {
78ed81a3 708 switch(stat)
15637ed4 709 {
78ed81a3 710 case BT_MBI_ABORT:
711#ifdef UTEST
712 if(bt_debug & BT_SHOWMISC)
713 printf("abort ");
714#endif
715 ccb->host_stat = BT_ABORTED;
716 break;
15637ed4 717
78ed81a3 718 case BT_MBI_UNKNOWN:
719 ccb = (struct bt_ccb *)0;
720#ifdef UTEST
721 if(bt_debug & BT_SHOWMISC)
722 printf("unknown ccb for abort");
723#endif
724 break;
15637ed4 725
78ed81a3 726 case BT_MBI_ERROR:
727 break;
15637ed4 728
78ed81a3 729 default:
730 panic("Impossible mbxi status");
15637ed4 731
15637ed4 732 }
78ed81a3 733#ifdef UTEST
734 if((bt_debug & BT_SHOWCMDS ) && ccb)
15637ed4 735 {
78ed81a3 736 u_char *cp;
737 cp = ccb->scsi_cmd;
738 printf("op=%x %x %x %x %x %x\n",
739 cp[0], cp[1], cp[2],
740 cp[3], cp[4], cp[5]);
741 printf("stat %x for mbi addr = 0x%08x\n"
742 , wmbi->stat, wmbi );
743 printf("addr = 0x%x\n", ccb);
744 }
745#endif
746 }
747 wmbi->stat = BT_MBI_FREE;
748 if(ccb)
749 {
750 untimeout(bt_timeout,ccb);
751 bt_done(unit,ccb);
752 }
753
754 /* Set the IN mail Box pointer for next */
755 bt_nextmbx( wmbi, wmbx, mbi );
756 }
757 if ( !found ) {
758 for ( i = 0; i < BT_MBX_SIZE; i++) {
759 if ( wmbi->stat != BT_MBI_FREE ) {
760 found ++;
761 break;
15637ed4 762 }
78ed81a3 763 bt_nextmbx( wmbi, wmbx, mbi );
764 }
765 if ( !found ) {
766 printf("bt%d: mbi at 0x%08x should be found, stat=%02x..resync\n",
767 unit, wmbi, stat );
768 } else {
769 found = 0;
770 goto AGAIN;
15637ed4
RG
771 }
772 }
78ed81a3 773 wmbx->tmbi = wmbi;
774 outb(BT_CTRL_STAT_PORT, BT_IRST);
15637ed4
RG
775 return(1);
776}
777
778/***********************************************\
779* A ccb (and hence a mbx-out is put onto the *
780* free list. *
781\***********************************************/
782bt_free_ccb(unit,ccb, flags)
783struct bt_ccb *ccb;
784{
785 unsigned int opri;
78ed81a3 786
787#ifdef UTEST
15637ed4
RG
788 if(scsi_debug & PRINTROUTINES)
789 printf("ccb%d(0x%x)> ",unit,flags);
78ed81a3 790#endif
15637ed4
RG
791 if (!(flags & SCSI_NOMASK))
792 opri = splbio();
793
794 ccb->next = bt_ccb_free[unit];
795 bt_ccb_free[unit] = ccb;
796 ccb->flags = CCB_FREE;
797 /***********************************************\
798 * If there were none, wake abybody waiting for *
799 * one to come free, starting with queued entries*
800 \***********************************************/
801 if (!ccb->next) {
802 wakeup(&bt_ccb_free[unit]);
803 }
804 if (!(flags & SCSI_NOMASK))
805 splx(opri);
806}
807
808/***********************************************\
78ed81a3 809* Get a free ccb *
15637ed4
RG
810\***********************************************/
811struct bt_ccb *
812bt_get_ccb(unit,flags)
813{
78ed81a3 814 unsigned opri;
15637ed4 815 struct bt_ccb *rc;
78ed81a3 816 struct bt_mbx *wmbx; /* Mail Box pointer specified unit */
817 BT_MBO *wmbo; /* Out Mail Box pointer */
15637ed4 818
78ed81a3 819#ifdef UTEST
15637ed4
RG
820 if(scsi_debug & PRINTROUTINES)
821 printf("<ccb%d(0x%x) ",unit,flags);
78ed81a3 822#endif
15637ed4
RG
823 if (!(flags & SCSI_NOMASK))
824 opri = splbio();
825 /***********************************************\
826 * If we can and have to, sleep waiting for one *
827 * to come free *
828 \***********************************************/
829 while ((!(rc = bt_ccb_free[unit])) && (!(flags & SCSI_NOSLEEP)))
830 {
831 sleep(&bt_ccb_free[unit], PRIBIO);
832 }
833 if (rc)
834 {
78ed81a3 835 /* Get CCB from from free list */
15637ed4
RG
836 bt_ccb_free[unit] = rc->next;
837 rc->flags = CCB_ACTIVE;
78ed81a3 838#ifdef HE
839 /* Get the Target OUT mail Box pointer */
840 wmbx = &bt_mbx[unit];
841 wmbo = wmbx->tmbo;
842 while ( wmbo->cmd != BT_MBO_FREE ) {
843 /* Enable MBO available interrupt */
844 outb(BT_CMD_DATA_PORT,BT_MBO_INTR_EN);
845 printf("Wait free mbo.."); /* AMURAI */
846 sleep( wmbx, PRIBIO);
847 printf("Got free mbo\n"); /* AMURAI */
848 }
849
850 /* Link CCB to the Mail Box */
851 rc->mbx = wmbo;
852 wmbo->ccb_addr = KVTOPHYS(rc);
853
854 /* Set the OUT mail Box pointer for next */
855 bt_nextmbx( wmbo, wmbx, mbo );
856 wmbx->tmbo = wmbo;
857#endif
15637ed4
RG
858 }
859 if (!(flags & SCSI_NOMASK))
860 splx(opri);
78ed81a3 861
15637ed4
RG
862 return(rc);
863}
78ed81a3 864/***********************************************\
865* Get a MBO and then Send it *
866\***********************************************/
867BT_MBO *bt_send_mbo( int unit,
868 int flags,
869 int cmd,
870 struct bt_ccb *ccb )
871{
872 unsigned opri;
873 BT_MBO *wmbo; /* Mail Box Out pointer */
874 struct bt_mbx *wmbx; /* Mail Box pointer specified unit */
875 int i, wait;
15637ed4 876
78ed81a3 877 wmbx = &bt_mbx[unit];
878
879 if (!(flags & SCSI_NOMASK))
880 opri = splbio();
881
882 /* Get the Target OUT mail Box pointer and move to Next */
883 wmbo = wmbx->tmbo;
884 wmbx->tmbo = ( wmbo == &( wmbx->mbo[BT_MBX_SIZE - 1 ] ) ?
885 &(wmbx->mbo[0]) : wmbo + 1 );
886
887 /*
888 * Check the outmail box is free or not
889 * Note: Under the normal operation, it shuld NOT happen to wait.
890 */
891 while ( wmbo->cmd != BT_MBO_FREE ) {
892
893 wait = BT_CMD_TIMEOUT_FUDGE * delaycount;
894 /* Enable MBO available interrupt */
895 outb(BT_CMD_DATA_PORT,BT_MBO_INTR_EN);
896 for (i=0; i< wait; i++)
897 {
898 if (!(inb(BT_CTRL_STAT_PORT) & BT_CDF))
899 break;
900 }
901 if (i >= wait)
902 {
903 printf("bt%d: bt_send_mbo, cmd/data port full\n",unit);
904 outb(BT_CTRL_STAT_PORT, BT_SRST);
905 return( (BT_MBO *)0 );
906 }
907 outb(BT_CMD_DATA_PORT, 0x01); /* Enable */
908 sleep( wmbx, PRIBIO);
909 }
910
911 /* Link CCB to the Mail Box */
912 wmbo->ccb_addr = KVTOPHYS(ccb);
913 ccb->mbx = wmbo;
914 wmbo->cmd = cmd;
915
916 /* Send it ! */
917 outb(BT_CMD_DATA_PORT, BT_START_SCSI);
918
919 if (!(flags & SCSI_NOMASK))
920 splx(opri);
921
922 return(wmbo);
923}
15637ed4
RG
924/***********************************************\
925* We have a ccb which has been processed by the *
926* adaptor, now we look to see how the operation *
927* went. Wake up the owner if waiting *
928\***********************************************/
929bt_done(unit,ccb)
930struct bt_ccb *ccb;
931{
932 struct scsi_sense_data *s1,*s2;
933 struct scsi_xfer *xs = ccb->xfer;
934
78ed81a3 935#ifdef UTEST
15637ed4
RG
936 if(scsi_debug & (PRINTROUTINES | TRACEINTERRUPTS))
937 printf("bt_done ");
78ed81a3 938#endif
15637ed4
RG
939 /***********************************************\
940 * Otherwise, put the results of the operation *
941 * into the xfer and call whoever started it *
942 \***********************************************/
943 if ( ( ccb->host_stat != BT_OK
944 || ccb->target_stat != SCSI_OK)
945 && (!(xs->flags & SCSI_ERR_OK)))
946 {
947
948 s1 = &(ccb->scsi_sense);
949 s2 = &(xs->sense);
950
951 if(ccb->host_stat)
952 {
953 switch(ccb->host_stat)
954 {
955 case BT_ABORTED: /* No response */
956 case BT_SEL_TIMEOUT: /* No response */
78ed81a3 957#ifdef UTEST
15637ed4
RG
958 if (bt_debug & BT_SHOWMISC)
959 {
960 printf("timeout reported back\n");
961 }
78ed81a3 962#endif
15637ed4
RG
963 xs->error = XS_TIMEOUT;
964 break;
965 default: /* Other scsi protocol messes */
966 xs->error = XS_DRIVER_STUFFUP;
78ed81a3 967#ifdef UTEST
15637ed4
RG
968 if (bt_debug & BT_SHOWMISC)
969 {
970 printf("unexpected host_stat: %x\n",
971 ccb->host_stat);
972 }
78ed81a3 973#endif
15637ed4
RG
974 }
975
976 }
977 else
978 {
979 switch(ccb->target_stat)
980 {
981 case 0x02:
982 /* structure copy!!!!!*/
983 *s2=*s1;
984 xs->error = XS_SENSE;
985 break;
986 case 0x08:
987 xs->error = XS_BUSY;
988 break;
989 default:
78ed81a3 990#ifdef UTEST
15637ed4
RG
991 if (bt_debug & BT_SHOWMISC)
992 {
993 printf("unexpected target_stat: %x\n",
994 ccb->target_stat);
995 }
78ed81a3 996#endif
15637ed4
RG
997 xs->error = XS_DRIVER_STUFFUP;
998 }
999 }
1000 }
1001 else /* All went correctly OR errors expected */
1002 {
1003 xs->resid = 0;
1004 }
1005 xs->flags |= ITSDONE;
1006 bt_free_ccb(unit,ccb, xs->flags);
1007 if(xs->when_done)
1008 (*(xs->when_done))(xs->done_arg,xs->done_arg2);
1009}
1010
1011/***********************************************\
1012* Start the board, ready for normal operation *
1013\***********************************************/
1014bt_init(unit)
1015int unit;
1016{
1017 unsigned char ad[4];
1018 volatile int i,sts;
1019 struct bt_config conf;
1020
1021 /***********************************************\
1022 * reset board, If it doesn't respond, assume *
1023 * that it's not there.. good for the probe *
1024 \***********************************************/
1025
1026 outb(BT_CTRL_STAT_PORT, BT_HRST|BT_SRST);
1027
1028 for (i=0; i < BT_RESET_TIMEOUT; i++)
1029 {
1030 sts = inb(BT_CTRL_STAT_PORT) ;
1031 if ( sts == (BT_IDLE | BT_INIT))
1032 break;
1033 }
1034 if (i >= BT_RESET_TIMEOUT)
1035 {
78ed81a3 1036#ifdef UTEST
15637ed4
RG
1037 if (bt_debug & BT_SHOWMISC)
1038 printf("bt_init: No answer from bt742a board\n");
78ed81a3 1039#endif
15637ed4
RG
1040 return(ENXIO);
1041 }
1042
1043 /***********************************************\
1044 * Assume we have a board at this stage *
1045 * setup dma channel from jumpers and save int *
1046 * level *
1047 \***********************************************/
1048#ifdef __386BSD__
78ed81a3 1049 printf("bt%d: reading board settings, ",unit);
15637ed4
RG
1050#else __386BSD__
1051 printf("bt%d:",unit);
15637ed4
RG
1052#endif __386BSD__
1053
1054 bt_cmd(unit,0, sizeof(conf), 0 ,&conf, BT_CONF_GET);
1055 switch(conf.chan)
1056 {
1057 case EISADMA:
1058 bt_dma[unit] = -1;
15637ed4
RG
1059 break;
1060 case CHAN0:
1061 outb(0x0b, 0x0c);
1062 outb(0x0a, 0x00);
1063 bt_dma[unit] = 0;
15637ed4
RG
1064 break;
1065 case CHAN5:
1066 outb(0xd6, 0xc1);
1067 outb(0xd4, 0x01);
1068 bt_dma[unit] = 5;
15637ed4
RG
1069 break;
1070 case CHAN6:
1071 outb(0xd6, 0xc2);
1072 outb(0xd4, 0x02);
1073 bt_dma[unit] = 6;
15637ed4
RG
1074 break;
1075 case CHAN7:
1076 outb(0xd6, 0xc3);
1077 outb(0xd4, 0x03);
1078 bt_dma[unit] = 7;
15637ed4
RG
1079 break;
1080 default:
1081 printf("illegal dma setting %x\n",conf.chan);
1082 return(EIO);
1083 }
78ed81a3 1084 if (bt_dma[unit] == -1)
1085 printf("eisa dma, ");
1086 else
1087 printf("dma=%d, ",bt_dma[unit]);
1088
15637ed4
RG
1089 switch(conf.intr)
1090 {
1091 case INT9:
1092 bt_int[unit] = 9;
15637ed4
RG
1093 break;
1094 case INT10:
1095 bt_int[unit] = 10;
15637ed4
RG
1096 break;
1097 case INT11:
1098 bt_int[unit] = 11;
15637ed4
RG
1099 break;
1100 case INT12:
1101 bt_int[unit] = 12;
15637ed4
RG
1102 break;
1103 case INT14:
1104 bt_int[unit] = 14;
15637ed4
RG
1105 break;
1106 case INT15:
1107 bt_int[unit] = 15;
15637ed4
RG
1108 break;
1109 default:
1110 printf("illegal int setting\n");
1111 return(EIO);
1112 }
78ed81a3 1113#ifdef __386BSD__
1114 printf("int=%d\n",bt_int[unit]);
1115#else
1116 printf("int=%d ",bt_int[unit]);
1117#endif __386BSD__
1118
15637ed4
RG
1119 /* who are we on the scsi bus */
1120 bt_scsi_dev[unit] = conf.scsi_dev;
1121 /***********************************************\
1122 * Initialize mail box *
1123 \***********************************************/
15637ed4
RG
1124 *((physaddr *)ad) = KVTOPHYS(&bt_mbx[unit]);
1125 bt_cmd(unit,5, 0, 0, 0, BT_MBX_INIT_EXTENDED
1126 , BT_MBX_SIZE
1127 , ad[0]
1128 , ad[1]
1129 , ad[2]
1130 , ad[3]);
1131
1132 /***********************************************\
78ed81a3 1133 * Set Pointer chain null for just in case *
1134 * Link the ccb's into a free-list W/O mbox *
1135 * Initilize Mail Box stat to Free *
15637ed4 1136 \***********************************************/
78ed81a3 1137 if ( bt_ccb_free[unit] != (struct bt_ccb *)0 ) {
1138 printf("bt%d: bt_ccb_free is NOT initialized but init here\n",
1139 unit);
1140 bt_ccb_free[unit] = (struct bt_ccb *)0;
1141 }
1142 for (i=0; i < BT_CCB_SIZE; i++) {
1143 bt_ccb[unit][i].next = bt_ccb_free[unit];
1144 bt_ccb_free[unit] = &bt_ccb[unit][i];
15637ed4 1145 bt_ccb_free[unit]->flags = CCB_FREE;
15637ed4 1146 }
78ed81a3 1147 for (i=0; i < BT_MBX_SIZE; i++) {
1148 bt_mbx[unit].mbo[i].cmd = BT_MBO_FREE;
1149 bt_mbx[unit].mbi[i].stat = BT_MBI_FREE;
1150 }
1151
1152 /***********************************************\
1153 * Set up Initial mail box for round-robin *
1154 \***********************************************/
1155 bt_mbx[unit].tmbo = &bt_mbx[unit].mbo[0];
1156 bt_mbx[unit].tmbi = &bt_mbx[unit].mbi[0];
1157 bt_inquire_setup_information( unit );
1158
1159 /* Enable round-robin scheme - appeared at FirmWare 3.31 */
1160 bt_cmd(unit, 1, 0, 0, 0, BT_ROUND_ROBIN, BT_ENABLE );
15637ed4
RG
1161
1162 /***********************************************\
1163 * Note that we are going and return (to probe) *
1164 \***********************************************/
1165 bt_initialized[unit]++;
1166 return( 0 );
1167}
78ed81a3 1168bt_inquire_setup_information( unit )
1169int unit;
1170{
1171 struct bt_setup setup;
1172 struct bt_boardID bID;
1173 int i;
1174
1175 /* Inquire Board ID to Bt742 for FirmWare Version */
1176 bt_cmd(unit, 0, sizeof(bID), 0, &bID, BT_INQUIRE );
1177 printf("bt%d: version %c.%c, ",
1178 unit, bID.firm_revision, bID.firm_version );
1179
1180 /* Ask setup information to Bt742 */
1181 bt_cmd(unit, 1, sizeof(setup), 0, &setup, BT_SETUP_GET, sizeof(setup) );
1182
1183 if ( setup.sync_neg ) {
1184 printf("sync, ");
1185 } else {
1186 printf("async, ");
1187 }
1188
1189 if ( setup.parity ) {
1190 printf("parity, ");
1191 } else {
1192 printf("no parity, ");
1193 }
1194
1195 printf("%d mbxs, %d ccbs\n", setup.num_mbx,
1196 sizeof(bt_ccb)/(sizeof(struct bt_ccb) * NBT) );
1197
1198 for ( i = 0; i < 8; i++ ) {
1199 if( !setup.sync[i].offset &&
1200 !setup.sync[i].period &&
1201 !setup.sync[i].valid )
1202 continue;
1203
1204 printf("bt%d: dev%02d Offset=%d,Transfer period=%d, Synchronous? %s",
1205 unit, i,
1206 setup.sync[i].offset, setup.sync[i].period,
1207 setup.sync[i].valid ? "Yes" : "No" );
1208 }
1209
1210}
15637ed4
RG
1211
1212
1213#ifndef min
1214#define min(x,y) (x < y ? x : y)
1215#endif min
1216
1217
1218void btminphys(bp)
1219struct buf *bp;
1220{
1221#ifdef MACH
1222#if !defined(OSF)
1223 bp->b_flags |= B_NPAGES; /* can support scat/gather */
1224#endif /* defined(OSF) */
1225#endif MACH
1226 if(bp->b_bcount > ((BT_NSEG-1) * PAGESIZ))
1227 {
1228 bp->b_bcount = ((BT_NSEG-1) * PAGESIZ);
1229 }
1230}
1231
1232/***********************************************\
1233* start a scsi operation given the command and *
1234* the data address. Also needs the unit, target *
1235* and lu *
1236\***********************************************/
1237int bt_scsi_cmd(xs)
1238struct scsi_xfer *xs;
1239{
1240 struct scsi_sense_data *s1,*s2;
1241 struct bt_ccb *ccb;
1242 struct bt_scat_gath *sg;
1243 int seg; /* scatter gather seg being worked on */
1244 int i = 0;
1245 int rc = 0;
1246 int thiskv;
1247 physaddr thisphys,nextphys;
1248 int unit =xs->adapter;
1249 int bytes_this_seg,bytes_this_page,datalen,flags;
1250 struct iovec *iovp;
78ed81a3 1251 BT_MBO *mbo;
15637ed4 1252
78ed81a3 1253#ifdef UTEST
15637ed4
RG
1254 if(scsi_debug & PRINTROUTINES)
1255 printf("bt_scsi_cmd ");
78ed81a3 1256#endif
15637ed4
RG
1257 /***********************************************\
1258 * get a ccb (mbox-out) to use. If the transfer *
1259 * is from a buf (possibly from interrupt time) *
1260 * then we can't allow it to sleep *
1261 \***********************************************/
1262 flags = xs->flags;
1263 if(xs->bp) flags |= (SCSI_NOSLEEP); /* just to be sure */
1264 if(flags & ITSDONE)
1265 {
78ed81a3 1266 printf("bt%d: Already done?\n",unit);
15637ed4
RG
1267 xs->flags &= ~ITSDONE;
1268 }
1269 if(!(flags & INUSE))
1270 {
78ed81a3 1271 printf("bt%d: Not in use?\n",unit);
15637ed4
RG
1272 xs->flags |= INUSE;
1273 }
1274 if (!(ccb = bt_get_ccb(unit,flags)))
1275 {
1276 xs->error = XS_DRIVER_STUFFUP;
1277 return(TRY_AGAIN_LATER);
1278 }
78ed81a3 1279#ifdef UTEST
15637ed4
RG
1280 if(bt_debug & BT_SHOWCCBS)
1281 printf("<start ccb(%x)>",ccb);
78ed81a3 1282#endif
15637ed4
RG
1283 /***********************************************\
1284 * Put all the arguments for the xfer in the ccb *
1285 \***********************************************/
1286 ccb->xfer = xs;
1287 if(flags & SCSI_RESET)
1288 {
1289 ccb->opcode = BT_RESET_CCB;
1290 }
1291 else
1292 {
1293 /* can't use S/G if zero length */
1294 ccb->opcode = (xs->datalen?
1295 BT_INIT_SCAT_GATH_CCB
1296 :BT_INITIATOR_CCB);
1297 }
1298 ccb->target = xs->targ;;
1299 ccb->data_out = 0;
1300 ccb->data_in = 0;
1301 ccb->lun = xs->lu;
1302 ccb->scsi_cmd_length = xs->cmdlen;
1303 ccb->sense_ptr = KVTOPHYS(&(ccb->scsi_sense));
1304 ccb->req_sense_length = sizeof(ccb->scsi_sense);
1305
1306 if((xs->datalen) && (!(flags & SCSI_RESET)))
1307 { /* can use S/G only if not zero length */
1308 ccb->data_addr = KVTOPHYS(ccb->scat_gath);
1309 sg = ccb->scat_gath ;
1310 seg = 0;
1311 if(flags & SCSI_DATA_UIO)
1312 {
1313 iovp = ((struct uio *)xs->data)->uio_iov;
1314 datalen = ((struct uio *)xs->data)->uio_iovcnt;
1315 xs->datalen = 0;
1316 while ((datalen) && (seg < BT_NSEG))
1317 {
1318 sg->seg_addr = (physaddr)iovp->iov_base;
1319 xs->datalen += sg->seg_len = iovp->iov_len;
78ed81a3 1320#ifdef UTEST
15637ed4
RG
1321 if(scsi_debug & SHOWSCATGATH)
1322 printf("(0x%x@0x%x)"
1323 ,iovp->iov_len
1324 ,iovp->iov_base);
78ed81a3 1325#endif
15637ed4
RG
1326 sg++;
1327 iovp++;
1328 seg++;
1329 datalen--;
1330 }
1331 }
1332 else
1333 {
1334 /***********************************************\
1335 * Set up the scatter gather block *
1336 \***********************************************/
1337
78ed81a3 1338#ifdef UTEST
15637ed4
RG
1339 if(scsi_debug & SHOWSCATGATH)
1340 printf("%d @0x%x:- ",xs->datalen,xs->data);
78ed81a3 1341#endif
15637ed4
RG
1342 datalen = xs->datalen;
1343 thiskv = (int)xs->data;
1344 thisphys = KVTOPHYS(thiskv);
1345
1346 while ((datalen) && (seg < BT_NSEG))
1347 {
1348 bytes_this_seg = 0;
1349
1350 /* put in the base address */
1351 sg->seg_addr = thisphys;
1352
78ed81a3 1353#ifdef UTEST
15637ed4
RG
1354 if(scsi_debug & SHOWSCATGATH)
1355 printf("0x%x",thisphys);
78ed81a3 1356#endif
15637ed4
RG
1357
1358 /* do it at least once */
1359 nextphys = thisphys;
1360 while ((datalen) && (thisphys == nextphys))
1361 /*********************************************\
1362 * This page is contiguous (physically) with *
1363 * the the last, just extend the length *
1364 \*********************************************/
1365 {
1366 /* how far to the end of the page */
1367 nextphys= (thisphys & (~(PAGESIZ - 1)))
1368 + PAGESIZ;
1369 bytes_this_page = nextphys - thisphys;
1370 /**** or the data ****/
1371 bytes_this_page = min(bytes_this_page
1372 ,datalen);
1373 bytes_this_seg += bytes_this_page;
1374 datalen -= bytes_this_page;
1375
1376 /* get more ready for the next page */
1377 thiskv = (thiskv & (~(PAGESIZ - 1)))
1378 + PAGESIZ;
1379 if(datalen)
1380 thisphys = KVTOPHYS(thiskv);
1381 }
1382 /********************************************\
1383 * next page isn't contiguous, finish the seg *
1384 \********************************************/
78ed81a3 1385#ifdef UTEST
15637ed4
RG
1386 if(scsi_debug & SHOWSCATGATH)
1387 printf("(0x%x)",bytes_this_seg);
78ed81a3 1388#endif
15637ed4
RG
1389 sg->seg_len = bytes_this_seg;
1390 sg++;
1391 seg++;
1392 }
1393 } /*end of iov/kv decision */
1394 ccb->data_length = seg * sizeof(struct bt_scat_gath);
78ed81a3 1395#ifdef UTEST
15637ed4
RG
1396 if(scsi_debug & SHOWSCATGATH)
1397 printf("\n");
78ed81a3 1398#endif
15637ed4
RG
1399 if (datalen)
1400 { /* there's still data, must have run out of segs! */
78ed81a3 1401 printf("bt%d: bt_scsi_cmd, more than %d DMA segs\n",
15637ed4
RG
1402 unit,BT_NSEG);
1403 xs->error = XS_DRIVER_STUFFUP;
1404 bt_free_ccb(unit,ccb,flags);
1405 return(HAD_ERROR);
1406 }
1407
1408 }
1409 else
1410 { /* No data xfer, use non S/G values */
1411 ccb->data_addr = (physaddr)0;
1412 ccb->data_length = 0;
1413 }
1414 ccb->link_id = 0;
1415 ccb->link_addr = (physaddr)0;
1416 /***********************************************\
1417 * Put the scsi command in the ccb and start it *
1418 \***********************************************/
1419 if(!(flags & SCSI_RESET))
1420 {
1421 bcopy(xs->cmd, ccb->scsi_cmd, ccb->scsi_cmd_length);
1422 }
78ed81a3 1423#ifdef UTEST
15637ed4
RG
1424 if(scsi_debug & SHOWCOMMANDS)
1425 {
1426 u_char *b = ccb->scsi_cmd;
1427 if(!(flags & SCSI_RESET))
1428 {
1429 int i = 0;
1430 printf("bt%d:%d:%d-"
1431 ,unit
1432 ,ccb->target
1433 ,ccb->lun);
1434 while(i < ccb->scsi_cmd_length )
1435 {
1436 if(i) printf(",");
1437 printf("%x",b[i++]);
1438 }
1439 printf("-\n");
1440 }
1441 else
1442 {
1443 printf("bt%d:%d:%d-RESET- "
1444 ,unit
1445 ,ccb->target
1446 ,ccb->lun
1447 );
1448 }
1449 }
78ed81a3 1450#endif
1451 if ( bt_send_mbo( unit, flags, BT_MBO_START, ccb ) == (BT_MBO *)0 )
1452 {
1453 xs->error = XS_DRIVER_STUFFUP;
1454 bt_free_ccb(unit,ccb,flags);
1455 return(TRY_AGAIN_LATER);
1456 }
15637ed4
RG
1457 /***********************************************\
1458 * Usually return SUCCESSFULLY QUEUED *
1459 \***********************************************/
78ed81a3 1460#ifdef UTEST
15637ed4
RG
1461 if(scsi_debug & TRACEINTERRUPTS)
1462 printf("cmd_sent ");
78ed81a3 1463#endif
15637ed4
RG
1464 if (!(flags & SCSI_NOMASK))
1465 {
78ed81a3 1466 timeout(bt_timeout,ccb,(xs->timeout * hz) / 1000);
15637ed4 1467 return(SUCCESSFULLY_QUEUED);
78ed81a3 1468 } else
15637ed4
RG
1469 /***********************************************\
1470 * If we can't use interrupts, poll on completion*
1471 \***********************************************/
1472 {
1473 int done = 0;
1474 int count = delaycount * xs->timeout / BT_SCSI_TIMEOUT_FUDGE;
78ed81a3 1475 struct bt_mbx *wmbx = &bt_mbx[unit];
1476 BT_MBI *wmbi = wmbx->tmbi;
1477 unsigned char stat;
1478#ifdef UTEST
15637ed4
RG
1479 if(scsi_debug & TRACEINTERRUPTS)
1480 printf("wait ");
78ed81a3 1481#endif
15637ed4
RG
1482 while((!done) && count)
1483 {
78ed81a3 1484 stat = inb(BT_INTR_PORT) & (BT_ANY_INTR | BT_MBIF );
1485 if ( !( stat & BT_ANY_INTR ) ||
1486 ( wmbi->stat == BT_MBI_FREE )||
1487 (PHYSTOKV(wmbi->ccb_addr)
1488 != (int)ccb ) ) {
1489 count--;
1490 continue;
15637ed4 1491 }
78ed81a3 1492 wmbi->stat = BT_MBI_FREE;
1493 bt_done(unit,ccb);
1494 done ++;
1495 outb(BT_CTRL_STAT_PORT, BT_IRST);
1496 /* Set the IN mail Box pointer for next */
1497 bt_nextmbx( wmbi, wmbx, mbi );
1498 wmbx->tmbi = wmbi;
15637ed4 1499 }
78ed81a3 1500 if (!count && !done)
15637ed4 1501 {
78ed81a3 1502#ifdef UTEST
15637ed4
RG
1503 if (!(xs->flags & SCSI_SILENT))
1504 printf("cmd fail\n");
78ed81a3 1505#endif
1506 bt_send_mbo( unit, flags, BT_MBO_ABORT, ccb );
15637ed4
RG
1507 count = delaycount * 2000 / BT_SCSI_TIMEOUT_FUDGE;
1508 while((!done) && count)
1509 {
78ed81a3 1510 if ( !( stat & BT_ANY_INTR ) ||
1511 ( wmbi->stat == BT_MBI_FREE )||
1512 ( PHYSTOKV(wmbi->ccb_addr )
1513 != (int)ccb ) ) {
1514 count--;
1515 continue;
15637ed4 1516 }
78ed81a3 1517 wmbi->stat = BT_MBI_FREE;
1518 bt_done(unit,ccb);
1519 done ++;
1520 outb(BT_CTRL_STAT_PORT, BT_IRST);
1521 /* Set the IN mail Box pointer for next */
1522 bt_nextmbx( wmbi, wmbx, mbi );
1523 wmbx->tmbi = wmbi;
15637ed4 1524 }
78ed81a3 1525 if(!count && !done)
15637ed4 1526 {
78ed81a3 1527 printf("bt%d: abort failed in wait\n", unit);
15637ed4
RG
1528 ccb->mbx->cmd = BT_MBO_FREE;
1529 }
1530 bt_free_ccb(unit,ccb,flags);
15637ed4
RG
1531 xs->error = XS_DRIVER_STUFFUP;
1532 return(HAD_ERROR);
1533 }
15637ed4
RG
1534 if(xs->error) return(HAD_ERROR);
1535 return(COMPLETE);
15637ed4 1536 }
15637ed4
RG
1537}
1538
1539
78ed81a3 1540bt_timeout(struct bt_ccb *ccb)
15637ed4 1541{
15637ed4
RG
1542 int unit;
1543 int s = splbio();
1544
78ed81a3 1545 unit = ccb->xfer->adapter;
1546 printf("bt%d: %d device timed out\n",unit
1547 ,ccb->xfer->targ);
1548#ifdef UTEST
1549 if(bt_debug & BT_SHOWCCBS)
1550 bt_print_active_ccbs(unit);
1551#endif
1552
1553 /***************************************\
1554 * If The ccb's mbx is not free, then *
1555 * the board has gone Far East ? *
1556 \***************************************/
1557 if((struct bt_ccb *)PHYSTOKV(ccb->mbx->ccb_addr)==ccb &&
1558 ccb->mbx->cmd != BT_MBO_FREE )
15637ed4 1559 {
78ed81a3 1560 printf("bt%d: not taking commands!\n"
1561 ,unit);
1562 Debugger();
1563 }
1564 /***************************************\
1565 * If it has been through before, then *
1566 * a previous abort has failed, don't *
1567 * try abort again *
1568 \***************************************/
1569 if(ccb->flags == CCB_ABORTED) /* abort timed out */
1570 {
1571 printf("bt%d: Abort Operation has timed out\n",unit);
1572 ccb->xfer->retries = 0; /* I MEAN IT ! */
1573 ccb->host_stat = BT_ABORTED;
1574 bt_done(unit,ccb);
1575 }
1576 else /* abort the operation that has timed out */
1577 {
1578 printf("bt%d: Try to abort\n",unit);
1579 bt_send_mbo( unit, ~SCSI_NOMASK,
1580 BT_MBO_ABORT, ccb );
1581 /* 2 secs for the abort */
1582 timeout(bt_timeout,ccb,2 * hz);
1583 ccb->flags = CCB_ABORTED;
15637ed4
RG
1584 }
1585 splx(s);
15637ed4
RG
1586}
1587
78ed81a3 1588#ifdef UTEST
1589bt_print_ccb(ccb)
15637ed4
RG
1590struct bt_ccb *ccb;
1591{
1592 printf("ccb:%x op:%x cmdlen:%d senlen:%d\n"
1593 ,ccb
1594 ,ccb->opcode
1595 ,ccb->scsi_cmd_length
1596 ,ccb->req_sense_length);
78ed81a3 1597 printf(" datlen:%d hstat:%x tstat:%x flags:%x\n"
15637ed4
RG
1598 ,ccb->data_length
1599 ,ccb->host_stat
1600 ,ccb->target_stat
15637ed4
RG
1601 ,ccb->flags);
1602}
1603
78ed81a3 1604bt_print_active_ccbs(int unit)
15637ed4
RG
1605{
1606 struct bt_ccb *ccb;
78ed81a3 1607 ccb = &(bt_ccb[unit][0]);
1608 int i = BT_CCB_SIZE;
15637ed4 1609
78ed81a3 1610 while(i--)
15637ed4 1611 {
78ed81a3 1612 if(ccb->flags != CCB_FREE)
1613 bt_print_ccb(ccb);
1614 ccb++;
15637ed4 1615 }
15637ed4 1616}
78ed81a3 1617#endif /*UTEST*/