Annotation of src/sys/dev/isa/seagate.c, Revision 1.52
1.52 ! thorpej 1: /* $NetBSD: seagate.c,v 1.51 2002/10/02 02:09:20 thorpej Exp $ */
1.24 perry 2:
1.1 mycroft 3: /*
4: * ST01/02, Future Domain TMC-885, TMC-950 SCSI driver
5: *
1.28 mycroft 6: * Copyright 1994, Charles M. Hannum (mycroft@ai.mit.edu)
1.1 mycroft 7: * Copyright 1994, Kent Palmkvist (kentp@isy.liu.se)
8: * Copyright 1994, Robert Knier (rknier@qgraph.com)
9: * Copyright 1992, 1994 Drew Eckhardt (drew@colorado.edu)
10: * Copyright 1994, Julian Elischer (julian@tfs.com)
11: *
12: * Others that has contributed by example code is
13: * Glen Overby (overby@cray.com)
14: * Tatu Yllnen
15: * Brian E Litzinger
16: *
17: * Redistribution and use in source and binary forms, with or without
18: * modification, are permitted provided that the following conditions
19: * are met:
20: * 1. Redistributions of source code must retain the above copyright
21: * notice, this list of conditions and the following disclaimer.
22: * 2. Redistributions in binary form must reproduce the above copyright
23: * notice, this list of conditions and the following disclaimer in the
24: * documentation and/or other materials provided with the distribution.
25: *
26: * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND
27: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29: * ARE DISCLAIMED. IN NO EVENT SHALL THE DEVELOPERS BE LIABLE
30: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36: * SUCH DAMAGE.
37: */
38:
39: /*
40: * kentp 940307 alpha version based on newscsi-03 version of Julians SCSI-code
41: * kentp 940314 Added possibility to not use messages
42: * rknier 940331 Added fast transfer code
43: * rknier 940407 Added assembler coded data transfers
44: */
45:
46: /*
47: * What should really be done:
48: *
49: * Add missing tests for timeouts
50: * Restructure interrupt enable/disable code (runs to long with int disabled)
51: * Find bug? giving problem with tape status
52: * Add code to handle Future Domain 840, 841, 880 and 881
53: * adjust timeouts (startup is very slow)
54: * add code to use tagged commands in SCSI2
55: * Add code to handle slow devices better (sleep if device not disconnecting)
56: * Fix unnecessary interrupts
57: */
58:
59: /*
60: * Note to users trying to share a disk between DOS and unix:
61: * The ST01/02 is a translating host-adapter. It is not giving DOS
62: * the same number of heads/tracks/sectors as specified by the disk.
63: * It is therefore important to look at what numbers DOS thinks the
64: * disk has. Use these to disklabel your disk in an appropriate manner
65: */
66:
1.43 lukem 67: #include <sys/cdefs.h>
1.52 ! thorpej 68: __KERNEL_RCSID(0, "$NetBSD: seagate.c,v 1.51 2002/10/02 02:09:20 thorpej Exp $");
1.43 lukem 69:
1.1 mycroft 70: #include <sys/param.h>
71: #include <sys/systm.h>
72: #include <sys/kernel.h>
73: #include <sys/errno.h>
74: #include <sys/ioctl.h>
1.3 mycroft 75: #include <sys/device.h>
1.1 mycroft 76: #include <sys/buf.h>
77: #include <sys/proc.h>
78: #include <sys/user.h>
1.3 mycroft 79: #include <sys/queue.h>
80: #include <sys/malloc.h>
1.1 mycroft 81:
1.17 mycroft 82: #include <machine/intr.h>
1.1 mycroft 83: #include <machine/pio.h>
84:
1.23 bouyer 85: #include <dev/scsipi/scsi_all.h>
86: #include <dev/scsipi/scsipi_all.h>
87: #include <dev/scsipi/scsi_message.h>
88: #include <dev/scsipi/scsiconf.h>
1.1 mycroft 89:
1.8 cgd 90: #include <dev/isa/isareg.h>
1.33 cgd 91: #include <dev/isa/isavar.h> /* XXX USES ISA HOLE DIRECTLY */
1.3 mycroft 92:
1.1 mycroft 93: #define SEA_SCB_MAX 32 /* allow maximally 8 scsi control blocks */
94: #define SCB_TABLE_SIZE 8 /* start with 8 scb entries in table */
95: #define BLOCK_SIZE 512 /* size of READ/WRITE areas on SCSI card */
96:
97: /*
98: * defining SEA_BLINDTRANSFER will make DATA IN and DATA OUT to be done with
99: * blind transfers, i.e. no check is done for scsi phase changes. This will
100: * result in data loss if the scsi device does not send its data using
101: * BLOCK_SIZE bytes at a time.
102: * If SEA_BLINDTRANSFER defined and SEA_ASSEMBLER also defined will result in
103: * the use of blind transfers coded in assembler. SEA_ASSEMBLER is no good
104: * without SEA_BLINDTRANSFER defined.
105: */
106: #define SEA_BLINDTRANSFER /* do blind transfers */
107: #define SEA_ASSEMBLER /* Use assembly code for fast transfers */
108:
109: /*
110: * defining SEA_NOMSGS causes messages not to be used (thereby disabling
111: * disconnects)
112: */
113: #undef SEA_NOMSGS
114:
115: /*
116: * defining SEA_NODATAOUT makes dataout phase being aborted
117: */
118: #undef SEA_NODATAOUT
119:
120: /* Debugging definitions. Should not be used unless you want a lot of
121: printouts even under normal conditions */
122:
123: #undef SEA_DEBUGQUEUE /* Display info about queue-lengths */
124:
125: /******************************* board definitions **************************/
126: /*
127: * CONTROL defines
128: */
129: #define CMD_RST 0x01 /* scsi reset */
130: #define CMD_SEL 0x02 /* scsi select */
131: #define CMD_BSY 0x04 /* scsi busy */
132: #define CMD_ATTN 0x08 /* scsi attention */
133: #define CMD_START_ARB 0x10 /* start arbitration bit */
134: #define CMD_EN_PARITY 0x20 /* enable scsi parity generation */
135: #define CMD_INTR 0x40 /* enable scsi interrupts */
136: #define CMD_DRVR_ENABLE 0x80 /* scsi enable */
137:
138: /*
139: * STATUS
140: */
141: #define STAT_BSY 0x01 /* scsi busy */
142: #define STAT_MSG 0x02 /* scsi msg */
143: #define STAT_IO 0x04 /* scsi I/O */
144: #define STAT_CD 0x08 /* scsi C/D */
145: #define STAT_REQ 0x10 /* scsi req */
146: #define STAT_SEL 0x20 /* scsi select */
147: #define STAT_PARITY 0x40 /* parity error bit */
148: #define STAT_ARB_CMPL 0x80 /* arbitration complete bit */
149:
150: /*
151: * REQUESTS
152: */
1.3 mycroft 153: #define PH_DATAOUT (0)
154: #define PH_DATAIN (STAT_IO)
155: #define PH_CMD (STAT_CD)
156: #define PH_STAT (STAT_CD | STAT_IO)
157: #define PH_MSGOUT (STAT_MSG | STAT_CD)
158: #define PH_MSGIN (STAT_MSG | STAT_CD | STAT_IO)
159:
160: #define PH_MASK (STAT_MSG | STAT_CD | STAT_IO)
1.1 mycroft 161:
1.3 mycroft 162: #define PH_INVALID 0xff
1.1 mycroft 163:
164: #define SEA_RAMOFFSET 0x00001800
165:
166: #define BASE_CMD (CMD_INTR | CMD_EN_PARITY)
167:
1.3 mycroft 168: #define SEAGATE 1 /* Seagate ST0[12] */
169: #define FDOMAIN 2 /* Future Domain TMC-{885,950} */
170: #define FDOMAIN840 3 /* Future Domain TMC-{84[01],88[01]} */
1.1 mycroft 171:
172: /******************************************************************************/
173:
174: /* scsi control block used to keep info about a scsi command */
175: struct sea_scb {
176: u_char *data; /* position in data buffer so far */
1.3 mycroft 177: int datalen; /* bytes remaining to transfer */
1.1 mycroft 178: TAILQ_ENTRY(sea_scb) chain;
1.23 bouyer 179: struct scsipi_xfer *xs; /* the scsipi_xfer for this cmd */
1.1 mycroft 180: int flags; /* status of the instruction */
181: #define SCB_FREE 0
182: #define SCB_ACTIVE 1
183: #define SCB_ABORTED 2
184: #define SCB_TIMEOUT 4
185: #define SCB_ERROR 8
186: };
187:
188: /*
189: * data structure describing current status of the scsi bus. One for each
190: * controller card.
191: */
192: struct sea_softc {
193: struct device sc_dev;
1.8 cgd 194: void *sc_ih;
1.1 mycroft 195:
1.3 mycroft 196: int type; /* board type */
1.1 mycroft 197: caddr_t maddr; /* Base address for card */
198: caddr_t maddr_cr_sr; /* Address of control and status reg */
199: caddr_t maddr_dr; /* Address of data register */
1.3 mycroft 200:
1.30 thorpej 201: struct scsipi_adapter sc_adapter;
1.40 bouyer 202: struct scsipi_channel sc_channel;
203:
1.3 mycroft 204: TAILQ_HEAD(, sea_scb) free_list, ready_list, nexus_list;
205: struct sea_scb *nexus; /* currently connected command */
206: int numscbs; /* number of scsi control blocks */
207: struct sea_scb scb[SCB_TABLE_SIZE];
208:
1.1 mycroft 209: int our_id; /* our scsi id */
210: u_char our_id_mask;
211: volatile u_char busy[8]; /* index=target, bit=lun, Keep track of
212: busy luns at device target */
213: };
214:
215: /* flag showing if main routine is running. */
216: static volatile int main_running = 0;
217:
218: #define STATUS (*(volatile u_char *)sea->maddr_cr_sr)
219: #define CONTROL STATUS
220: #define DATA (*(volatile u_char *)sea->maddr_dr)
221:
222: /*
223: * These are "special" values for the tag parameter passed to sea_select
224: * Not implemented right now.
225: */
226: #define TAG_NEXT -1 /* Use next free tag */
227: #define TAG_NONE -2 /*
228: * Establish I_T_L nexus instead of I_T_L_Q
229: * even on SCSI-II devices.
230: */
231:
232: typedef struct {
233: char *signature;
234: int offset, length;
235: int type;
236: } BiosSignature;
237:
238: /*
239: * Signatures for automatic recognition of board type
240: */
241: static const BiosSignature signatures[] = {
242: {"ST01 v1.7 (C) Copyright 1987 Seagate", 15, 37, SEAGATE},
243: {"SCSI BIOS 2.00 (C) Copyright 1987 Seagate", 15, 40, SEAGATE},
244:
245: /*
246: * The following two lines are NOT mistakes. One detects ROM revision
247: * 3.0.0, the other 3.2. Since seagate has only one type of SCSI adapter,
248: * and this is not going to change, the "SEAGATE" and "SCSI" together
249: * are probably "good enough"
250: */
251: {"SEAGATE SCSI BIOS ", 16, 17, SEAGATE},
252: {"SEAGATE SCSI BIOS ", 17, 17, SEAGATE},
253:
254: /*
255: * However, future domain makes several incompatible SCSI boards, so specific
256: * signatures must be used.
257: */
258: {"FUTURE DOMAIN CORP. (C) 1986-1989 V5.0C2/14/89", 5, 45, FDOMAIN},
259: {"FUTURE DOMAIN CORP. (C) 1986-1989 V6.0A7/28/89", 5, 46, FDOMAIN},
260: {"FUTURE DOMAIN CORP. (C) 1986-1990 V6.0105/31/90",5, 47, FDOMAIN},
261: {"FUTURE DOMAIN CORP. (C) 1986-1990 V6.0209/18/90",5, 47, FDOMAIN},
262: {"FUTURE DOMAIN CORP. (C) 1986-1990 V7.009/18/90", 5, 46, FDOMAIN},
263: {"FUTURE DOMAIN CORP. (C) 1992 V8.00.004/02/92", 5, 44, FDOMAIN},
264: {"FUTURE DOMAIN TMC-950", 5, 21, FDOMAIN},
265: };
266:
267: #define nsignatures (sizeof(signatures) / sizeof(signatures[0]))
268:
1.16 christos 269: #ifdef notdef
1.1 mycroft 270: static const char *bases[] = {
271: (char *) 0xc8000, (char *) 0xca000, (char *) 0xcc000,
272: (char *) 0xce000, (char *) 0xdc000, (char *) 0xde000
273: };
274:
275: #define nbases (sizeof(bases) / sizeof(bases[0]))
1.16 christos 276: #endif
1.1 mycroft 277:
1.8 cgd 278: int seaintr __P((void *));
1.40 bouyer 279: void sea_scsipi_request __P((struct scsipi_channel *,
280: scsipi_adapter_req_t, void *));
1.1 mycroft 281: void sea_timeout __P((void *));
282: void sea_done __P((struct sea_softc *, struct sea_scb *));
283: struct sea_scb *sea_get_scb __P((struct sea_softc *, int));
284: void sea_free_scb __P((struct sea_softc *, struct sea_scb *, int));
285: static void sea_main __P((void));
286: static void sea_information_transfer __P((struct sea_softc *));
1.23 bouyer 287: int sea_poll __P((struct sea_softc *, struct scsipi_xfer *, int));
1.1 mycroft 288: void sea_init __P((struct sea_softc *));
289: void sea_send_scb __P((struct sea_softc *sea, struct sea_scb *scb));
290: void sea_reselect __P((struct sea_softc *sea));
291: int sea_select __P((struct sea_softc *sea, struct sea_scb *scb));
292: int sea_transfer_pio __P((struct sea_softc *sea, u_char *phase,
1.3 mycroft 293: int *count, u_char **data));
1.1 mycroft 294: int sea_abort __P((struct sea_softc *, struct sea_scb *scb));
295:
1.40 bouyer 296: void sea_grow_scb __P((struct sea_softc *));
1.1 mycroft 297:
1.26 drochner 298: int seaprobe __P((struct device *, struct cfdata *, void *));
1.11 pk 299: void seaattach __P((struct device *, struct device *, void *));
1.1 mycroft 300:
1.51 thorpej 301: CFATTACH_DECL(sea, sizeof(struct sea_softc),
1.52 ! thorpej 302: seaprobe, seaattach, NULL, NULL);
1.14 thorpej 303:
1.25 thorpej 304: extern struct cfdriver sea_cd;
1.1 mycroft 305:
306: #ifdef SEA_DEBUGQUEUE
307: void
308: sea_queue_length(sea)
309: struct sea_softc *sea;
310: {
311: struct sea_scb *scb;
312: int connected, issued, disconnected;
313:
1.3 mycroft 314: connected = sea->nexus ? 1 : 0;
315: for (scb = sea->ready_list.tqh_first, issued = 0; scb;
1.1 mycroft 316: scb = scb->chain.tqe_next, issued++);
1.3 mycroft 317: for (scb = sea->nexus_list.tqh_first, disconnected = 0; scb;
1.1 mycroft 318: scb = scb->chain.tqe_next, disconnected++);
1.21 christos 319: printf("%s: length: %d/%d/%d\n", sea->sc_dev.dv_xname, connected,
1.1 mycroft 320: issued, disconnected);
321: }
322: #endif
323:
324: /*
325: * Check if the device can be found at the port given and if so, detect the
326: * type the type of board. Set it up ready for further work. Takes the isa_dev
327: * structure from autoconf as an argument.
328: * Returns 1 if card recognized, 0 if errors.
329: */
330: int
1.2 mycroft 331: seaprobe(parent, match, aux)
332: struct device *parent;
1.26 drochner 333: struct cfdata *match;
334: void *aux;
1.1 mycroft 335: {
336: struct isa_attach_args *ia = aux;
1.26 drochner 337: int i, type = 0;
338: caddr_t maddr;
1.1 mycroft 339:
1.45 thorpej 340: if (ia->ia_niomem < 1)
341: return (0);
342: if (ia->ia_nirq < 1)
343: return (0);
344:
345: if (ISA_DIRECT_CONFIG(ia))
346: return (0);
347:
348: if (ia->ia_iomem[0].ir_addr == ISACF_IOMEM_DEFAULT)
349: return (0);
350: if (ia->ia_irq[0].ir_irq == ISACF_IRQ_DEFAULT)
351: return (0);
352:
353: /* XXX XXX XXX */
354: maddr = ISA_HOLE_VADDR(ia->ia_iomem[0].ir_addr);
1.1 mycroft 355:
1.26 drochner 356: /* check board type */ /* No way to define this through config */
357: for (i = 0; i < nsignatures; i++)
1.42 thorpej 358: if (!memcmp(maddr + signatures[i].offset,
1.26 drochner 359: signatures[i].signature, signatures[i].length)) {
360: type = signatures[i].type;
361: break;
362: }
363:
364: /* Find controller and data memory addresses */
365: switch (type) {
366: case SEAGATE:
367: case FDOMAIN840:
368: case FDOMAIN:
369: break;
370: default:
371: #ifdef DEBUG
1.48 sommerfe 372: printf("seaprobe: board type unknown at address %p\n", maddr);
1.26 drochner 373: #endif
374: return 0;
375: }
376:
1.45 thorpej 377: ia->ia_niomem = 1;
378: ia->ia_iomem[0].ir_size = 0x2000;
379:
380: ia->ia_nirq = 1;
381:
382: ia->ia_nio = 0;
383: ia->ia_ndrq = 0;
384:
1.26 drochner 385: return 1;
386: }
387:
388: /*
389: * Attach all sub-devices we can find
390: */
391: void
392: seaattach(parent, self, aux)
393: struct device *parent, *self;
394: void *aux;
395: {
396: struct isa_attach_args *ia = aux;
397: struct sea_softc *sea = (void *)self;
1.40 bouyer 398: struct scsipi_adapter *adapt = &sea->sc_adapter;
399: struct scsipi_channel *chan = &sea->sc_channel;
1.26 drochner 400: int i;
401:
1.45 thorpej 402: /* XXX XXX XXX */
403: sea->maddr = ISA_HOLE_VADDR(ia->ia_iomem[0].ir_addr);
1.1 mycroft 404:
405: /* check board type */ /* No way to define this through config */
406: for (i = 0; i < nsignatures; i++)
1.42 thorpej 407: if (!memcmp(sea->maddr + signatures[i].offset,
1.1 mycroft 408: signatures[i].signature, signatures[i].length)) {
409: sea->type = signatures[i].type;
410: break;
411: }
412:
413: /* Find controller and data memory addresses */
414: switch (sea->type) {
415: case SEAGATE:
1.3 mycroft 416: case FDOMAIN840:
1.1 mycroft 417: sea->maddr_cr_sr =
418: (void *) (((u_char *)sea->maddr) + 0x1a00);
419: sea->maddr_dr =
420: (void *) (((u_char *)sea->maddr) + 0x1c00);
421: break;
422: case FDOMAIN:
423: sea->maddr_cr_sr =
424: (void *) (((u_char *)sea->maddr) + 0x1c00);
425: sea->maddr_dr =
426: (void *) (((u_char *)sea->maddr) + 0x1e00);
427: break;
428: default:
1.22 mikel 429: #ifdef DEBUG
1.48 sommerfe 430: printf("%s: board type unknown at address %p\n",
1.47 sommerfe 431: sea->sc_dev.dv_xname, sea->maddr);
1.10 mycroft 432: #endif
1.26 drochner 433: return;
1.1 mycroft 434: }
435:
436: /* Test controller RAM (works the same way on future domain cards?) */
437: *((u_char *)sea->maddr + SEA_RAMOFFSET) = 0xa5;
438: *((u_char *)sea->maddr + SEA_RAMOFFSET + 1) = 0x5a;
439:
440: if ((*((u_char *)sea->maddr + SEA_RAMOFFSET) != 0xa5) ||
441: (*((u_char *)sea->maddr + SEA_RAMOFFSET + 1) != 0x5a)) {
1.21 christos 442: printf("%s: board RAM failure\n", sea->sc_dev.dv_xname);
1.26 drochner 443: return;
1.1 mycroft 444: }
445:
446: sea_init(sea);
447:
448: /*
1.40 bouyer 449: * Fill in the scsipi_adapter.
1.30 thorpej 450: */
1.40 bouyer 451: memset(adapt, 0, sizeof(*adapt));
452: adapt->adapt_dev = &sea->sc_dev;
453: adapt->adapt_nchannels = 1;
454: adapt->adapt_openings = sea->numscbs;
455: adapt->adapt_max_periph = 1;
456: adapt->adapt_request = sea_scsipi_request;
457: adapt->adapt_minphys = minphys;
1.30 thorpej 458:
459: /*
1.40 bouyer 460: * Fill in the scsipi_channel.
1.1 mycroft 461: */
1.40 bouyer 462: memset(chan, 0, sizeof(*chan));
463: chan->chan_adapter = adapt;
464: chan->chan_bustype = &scsi_bustype;
465: chan->chan_channel = 0;
466: chan->chan_ntargets = 8;
467: chan->chan_nluns = 8;
468: chan->chan_id = sea->our_id;
469: chan->chan_flags = SCSIPI_CHAN_CANGROW;
1.1 mycroft 470:
1.21 christos 471: printf("\n");
1.1 mycroft 472:
1.45 thorpej 473: sea->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq[0].ir_irq,
474: IST_EDGE, IPL_BIO, seaintr, sea);
1.1 mycroft 475:
476: /*
477: * ask the adapter what subunits are present
478: */
1.40 bouyer 479: config_found(self, &sea->sc_channel, scsiprint);
1.1 mycroft 480: }
481:
482: /*
483: * Catch an interrupt from the adaptor
484: */
485: int
1.8 cgd 486: seaintr(arg)
487: void *arg;
1.1 mycroft 488: {
1.8 cgd 489: struct sea_softc *sea = arg;
1.1 mycroft 490:
491: #ifdef DEBUG /* extra overhead, and only needed for intr debugging */
492: if ((STATUS & STAT_PARITY) == 0 &&
493: (STATUS & (STAT_SEL | STAT_IO)) != (STAT_SEL | STAT_IO))
494: return 0;
495: #endif
496:
497: loop:
498: /* dispatch to appropriate routine if found and done=0 */
499: /* should check to see that this card really caused the interrupt */
500:
501: if (STATUS & STAT_PARITY) {
502: /* Parity error interrupt */
1.21 christos 503: printf("%s: parity error\n", sea->sc_dev.dv_xname);
1.1 mycroft 504: return 1;
505: }
506:
507: if ((STATUS & (STAT_SEL | STAT_IO)) == (STAT_SEL | STAT_IO)) {
508: /* Reselect interrupt */
509: sea_reselect(sea);
510: if (!main_running)
511: sea_main();
512: goto loop;
513: }
514:
515: return 1;
516: }
517:
518: /*
519: * Setup data structures, and reset the board and the SCSI bus.
520: */
521: void
522: sea_init(sea)
523: struct sea_softc *sea;
524: {
525: int i;
526:
527: /* Reset the scsi bus (I don't know if this is needed */
528: CONTROL = BASE_CMD | CMD_DRVR_ENABLE | CMD_RST;
529: delay(25); /* hold reset for at least 25 microseconds */
530: CONTROL = BASE_CMD;
531: delay(10); /* wait a Bus Clear Delay (800 ns + bus free delay (800 ns) */
532:
533: /* Set our id (don't know anything about this) */
534: switch (sea->type) {
535: case SEAGATE:
536: sea->our_id = 7;
537: break;
538: case FDOMAIN:
1.3 mycroft 539: case FDOMAIN840:
1.1 mycroft 540: sea->our_id = 6;
541: break;
542: }
543: sea->our_id_mask = 1 << sea->our_id;
544:
545: /* init fields used by our routines */
1.3 mycroft 546: sea->nexus = 0;
547: TAILQ_INIT(&sea->ready_list);
548: TAILQ_INIT(&sea->nexus_list);
549: TAILQ_INIT(&sea->free_list);
1.1 mycroft 550: for (i = 0; i < 8; i++)
551: sea->busy[i] = 0x00;
552:
553: /* link up the free list of scbs */
554: sea->numscbs = SCB_TABLE_SIZE;
555: for (i = 0; i < SCB_TABLE_SIZE; i++) {
1.3 mycroft 556: TAILQ_INSERT_TAIL(&sea->free_list, &sea->scb[i], chain);
1.1 mycroft 557: }
558: }
559:
560: /*
561: * start a scsi operation given the command and the data address. Also needs
562: * the unit, target and lu.
563: */
1.40 bouyer 564: void
565: sea_scsipi_request(chan, req, arg)
566: struct scsipi_channel *chan;
567: scsipi_adapter_req_t req;
568: void *arg;
569: {
1.23 bouyer 570: struct scsipi_xfer *xs;
1.40 bouyer 571: struct scsipi_periph *periph;
572: struct sea_softc *sea = (void *)chan->chan_adapter->adapt_dev;
1.1 mycroft 573: struct sea_scb *scb;
574: int flags;
1.3 mycroft 575: int s;
1.1 mycroft 576:
1.40 bouyer 577: switch (req) {
578: case ADAPTER_REQ_RUN_XFER:
579: xs = arg;
580: periph = xs->xs_periph;
581: flags = xs->xs_control;
582:
583: SC_DEBUG(periph, SCSIPI_DB2, ("sea_scsipi_requeset\n"));
584:
585: /* XXX Reset not implemented. */
586: if (flags & XS_CTL_RESET) {
587: printf("%s: resetting\n", sea->sc_dev.dv_xname);
588: xs->error = XS_DRIVER_STUFFUP;
589: scsipi_done(xs);
590: return;
591: }
1.1 mycroft 592:
1.40 bouyer 593: /* Get an SCB to use. */
594: scb = sea_get_scb(sea, flags);
595: #ifdef DIAGNOSTIC
596: /*
597: * This should never happen as we track the resources
598: * in the mid-layer.
599: */
600: if (scb == NULL) {
601: scsipi_printaddr(periph);
602: printf("unable to allocate scb\n");
603: panic("sea_scsipi_request");
604: }
605: #endif
606:
607: scb->flags = SCB_ACTIVE;
608: scb->xs = xs;
1.1 mycroft 609:
610: /*
1.40 bouyer 611: * Put all the arguments for the xfer in the scb
1.1 mycroft 612: */
1.40 bouyer 613: scb->datalen = xs->datalen;
614: scb->data = xs->data;
1.1 mycroft 615:
616: #ifdef SEA_DEBUGQUEUE
1.40 bouyer 617: sea_queue_length(sea);
1.1 mycroft 618: #endif
619:
1.40 bouyer 620: s = splbio();
1.3 mycroft 621:
1.40 bouyer 622: sea_send_scb(sea, scb);
623:
624: if ((flags & XS_CTL_POLL) == 0) {
625: callout_reset(&scb->xs->xs_callout,
1.49 bouyer 626: mstohz(xs->timeout), sea_timeout, scb);
1.40 bouyer 627: splx(s);
628: return;
629: }
1.3 mycroft 630:
1.1 mycroft 631: splx(s);
632:
1.40 bouyer 633: /*
634: * If we can't use interrupts, poll on completion
635: */
636: if (sea_poll(sea, xs, xs->timeout)) {
637: sea_timeout(scb);
638: if (sea_poll(sea, xs, 2000))
639: sea_timeout(scb);
640: }
641: return;
642:
643: case ADAPTER_REQ_GROW_RESOURCES:
644: sea_grow_scb(sea);
645: return;
646:
647: case ADAPTER_REQ_SET_XFER_MODE:
648: {
649: struct scsipi_xfer_mode *xm = arg;
1.3 mycroft 650:
1.40 bouyer 651: /*
652: * We don't support sync or wide or tagged queueing,
653: * so announce that now.
654: */
655: xm->xm_mode = 0;
656: xm->xm_period = 0;
657: xm->xm_offset = 0;
658: scsipi_async_event(chan, ASYNC_EVENT_XFER_MODE, xm);
659: return;
660: }
1.3 mycroft 661: }
1.1 mycroft 662: }
663:
664: /*
665: * Get a free scb. If there are none, see if we can allocate a new one. If so,
666: * put it in the hash table too; otherwise return an error or sleep.
667: */
668: struct sea_scb *
669: sea_get_scb(sea, flags)
670: struct sea_softc *sea;
671: int flags;
672: {
673: int s;
674: struct sea_scb *scb;
675:
1.3 mycroft 676: s = splbio();
1.40 bouyer 677: if ((scb = TAILQ_FIRST(&sea->free_list)) != NULL)
678: TAILQ_REMOVE(&sea->free_list, scb, chain);
679: splx(s);
1.1 mycroft 680:
1.40 bouyer 681: return (scb);
1.1 mycroft 682: }
683:
684: /*
685: * Try to send this command to the board. Because this board does not use any
686: * mailboxes, this routine simply adds the command to the queue held by the
687: * sea_softc structure.
688: * A check is done to see if the command contains a REQUEST_SENSE command, and
689: * if so the command is put first in the queue, otherwise the command is added
690: * to the end of the queue. ?? Not correct ??
691: */
692: void
693: sea_send_scb(sea, scb)
694: struct sea_softc *sea;
695: struct sea_scb *scb;
696: {
697:
1.3 mycroft 698: TAILQ_INSERT_TAIL(&sea->ready_list, scb, chain);
699: /* Try to do some work on the card. */
1.1 mycroft 700: if (!main_running)
701: sea_main();
702: }
703:
704: /*
705: * Coroutine that runs as long as more work can be done on the seagate host
706: * adapter in a system. Both sea_scsi_cmd and sea_intr will try to start it in
707: * case it is not running.
708: */
1.40 bouyer 709:
1.1 mycroft 710: void
711: sea_main()
712: {
713: struct sea_softc *sea;
714: struct sea_scb *scb;
715: int done;
716: int unit;
717: int s;
718:
719: main_running = 1;
720:
721: /*
722: * This should not be run with interrupts disabled, but use the splx
723: * code instead.
724: */
725: loop:
726: done = 1;
1.14 thorpej 727: for (unit = 0; unit < sea_cd.cd_ndevs; unit++) {
1.38 thorpej 728: sea = device_lookup(&sea_cd, unit);
1.1 mycroft 729: if (!sea)
730: continue;
731: s = splbio();
1.3 mycroft 732: if (!sea->nexus) {
1.1 mycroft 733: /*
1.3 mycroft 734: * Search through the ready_list for a command
1.1 mycroft 735: * destined for a target that's not busy.
736: */
1.3 mycroft 737: for (scb = sea->ready_list.tqh_first; scb;
1.1 mycroft 738: scb = scb->chain.tqe_next) {
1.40 bouyer 739: if (!(sea->busy[scb->xs->xs_periph->periph_target] &
740: (1 << scb->xs->xs_periph->periph_lun))) {
1.3 mycroft 741: TAILQ_REMOVE(&sea->ready_list, scb,
1.1 mycroft 742: chain);
743:
744: /* Re-enable interrupts. */
745: splx(s);
746:
747: /*
748: * Attempt to establish an I_T_L nexus.
1.3 mycroft 749: * On success, sea->nexus is set.
1.1 mycroft 750: * On failure, we must add the command
751: * back to the issue queue so we can
752: * keep trying.
753: */
754:
755: /*
756: * REQUEST_SENSE commands are issued
757: * without tagged queueing, even on
758: * SCSI-II devices because the
759: * contingent alligence condition
760: * exists for the entire unit.
761: */
762:
763: /*
764: * First check that if any device has
765: * tried a reconnect while we have done
766: * other things with interrupts
767: * disabled.
768: */
769:
770: if ((STATUS & (STAT_SEL | STAT_IO)) ==
771: (STAT_SEL | STAT_IO)) {
772: sea_reselect(sea);
773: break;
774: }
775: if (sea_select(sea, scb)) {
776: s = splbio();
1.3 mycroft 777: TAILQ_INSERT_HEAD(&sea->ready_list,
1.1 mycroft 778: scb, chain);
779: splx(s);
780: } else
781: break;
782: } /* if target/lun is not busy */
783: } /* for scb */
1.3 mycroft 784: if (!sea->nexus) {
785: /* check for reselection phase */
786: if ((STATUS & (STAT_SEL | STAT_IO)) ==
787: (STAT_SEL | STAT_IO)) {
788: sea_reselect(sea);
789: }
790: }
791: } /* if (!sea->nexus) */
1.1 mycroft 792:
793: splx(s);
1.3 mycroft 794: if (sea->nexus) { /* we are connected. Do the task */
1.1 mycroft 795: sea_information_transfer(sea);
796: done = 0;
797: } else
798: break;
799: } /* for instance */
800:
801: if (!done)
802: goto loop;
803:
804: main_running = 0;
805: }
806:
1.40 bouyer 807: /*
808: * Allocate an scb and add it to the free list.
809: * We are called at splbio.
810: */
811: void
812: sea_grow_scb(sea)
813: struct sea_softc *sea;
814: {
815: struct sea_scb *scb;
816:
817: if (sea->numscbs == SEA_SCB_MAX) {
818: sea->sc_channel.chan_flags &= ~SCSIPI_CHAN_CANGROW;
819: return;
820: }
821:
1.46 tsutsui 822: scb = malloc(sizeof(struct sea_scb), M_DEVBUF, M_NOWAIT|M_ZERO);
1.40 bouyer 823: if (scb == NULL)
824: return;
825:
826: TAILQ_INSERT_TAIL(&sea->free_list, scb, chain);
827: sea->numscbs++;
828: sea->sc_adapter.adapt_openings++;
829: }
1.1 mycroft 830: void
831: sea_free_scb(sea, scb, flags)
832: struct sea_softc *sea;
833: struct sea_scb *scb;
834: int flags;
835: {
836: int s;
837:
1.3 mycroft 838: s = splbio();
1.1 mycroft 839: scb->flags = SCB_FREE;
1.3 mycroft 840: TAILQ_INSERT_HEAD(&sea->free_list, scb, chain);
841: splx(s);
1.1 mycroft 842: }
843:
844: void
845: sea_timeout(arg)
846: void *arg;
847: {
848: struct sea_scb *scb = arg;
1.23 bouyer 849: struct scsipi_xfer *xs = scb->xs;
1.40 bouyer 850: struct scsipi_periph *periph = xs->xs_periph;
851: struct sea_softc *sea =
852: (void *)periph->periph_channel->chan_adapter->adapt_dev;
1.3 mycroft 853: int s;
1.1 mycroft 854:
1.40 bouyer 855: scsipi_printaddr(periph);
1.21 christos 856: printf("timed out");
1.1 mycroft 857:
1.3 mycroft 858: s = splbio();
859:
1.1 mycroft 860: /*
861: * If it has been through before, then
862: * a previous abort has failed, don't
863: * try abort again
864: */
865: if (scb->flags & SCB_ABORTED) {
1.3 mycroft 866: /* abort timed out */
1.21 christos 867: printf(" AGAIN\n");
1.40 bouyer 868: scb->xs->xs_retries = 0;
1.1 mycroft 869: scb->flags |= SCB_ABORTED;
870: sea_done(sea, scb);
871: } else {
1.3 mycroft 872: /* abort the operation that has timed out */
1.21 christos 873: printf("\n");
1.3 mycroft 874: scb->flags |= SCB_ABORTED;
1.1 mycroft 875: sea_abort(sea, scb);
1.3 mycroft 876: /* 2 secs for the abort */
1.34 thorpej 877: if ((xs->xs_control & XS_CTL_POLL) == 0)
1.35 thorpej 878: callout_reset(&scb->xs->xs_callout, 2 * hz,
879: sea_timeout, scb);
1.1 mycroft 880: }
1.3 mycroft 881:
1.1 mycroft 882: splx(s);
883: }
884:
885: void
886: sea_reselect(sea)
887: struct sea_softc *sea;
888: {
889: u_char target_mask;
890: int i;
891: u_char lun, phase;
892: u_char msg[3];
1.3 mycroft 893: int len;
1.1 mycroft 894: u_char *data;
895: struct sea_scb *scb;
896: int abort = 0;
897:
898: if (!((target_mask = STATUS) & STAT_SEL)) {
1.21 christos 899: printf("%s: wrong state 0x%x\n", sea->sc_dev.dv_xname,
1.1 mycroft 900: target_mask);
901: return;
902: }
903:
904: /* wait for a device to win the reselection phase */
905: /* signals this by asserting the I/O signal */
906: for (i = 10; i && (STATUS & (STAT_SEL | STAT_IO | STAT_BSY)) !=
907: (STAT_SEL | STAT_IO | 0); i--);
908: /* !! Check for timeout here */
909: /* the data bus contains original initiator id ORed with target id */
910: target_mask = DATA;
911: /* see that we really are the initiator */
912: if (!(target_mask & sea->our_id_mask)) {
1.21 christos 913: printf("%s: polled reselection was not for me: 0x%x\n",
1.1 mycroft 914: sea->sc_dev.dv_xname, target_mask);
915: return;
916: }
917: /* find target who won */
918: target_mask &= ~sea->our_id_mask;
919: /* host responds by asserting the BSY signal */
920: CONTROL = BASE_CMD | CMD_DRVR_ENABLE | CMD_BSY;
921: /* target should respond by deasserting the SEL signal */
922: for (i = 50000; i && (STATUS & STAT_SEL); i++);
923: /* remove the busy status */
924: CONTROL = BASE_CMD | CMD_DRVR_ENABLE;
925: /* we are connected. Now we wait for the MSGIN condition */
926: for (i = 50000; i && !(STATUS & STAT_REQ); i--);
927: /* !! Add timeout check here */
928: /* hope we get an IDENTIFY message */
929: len = 3;
930: data = msg;
1.3 mycroft 931: phase = PH_MSGIN;
1.1 mycroft 932: sea_transfer_pio(sea, &phase, &len, &data);
933:
1.39 bouyer 934: if (!MSG_ISIDENTIFY(msg[0])) {
1.21 christos 935: printf("%s: expecting IDENTIFY message, got 0x%x\n",
1.1 mycroft 936: sea->sc_dev.dv_xname, msg[0]);
937: abort = 1;
1.16 christos 938: scb = NULL;
1.1 mycroft 939: } else {
940: lun = msg[0] & 0x07;
941:
942: /*
943: * Find the command corresponding to the I_T_L or I_T_L_Q nexus
944: * we just reestablished, and remove it from the disconnected
945: * queue.
946: */
1.3 mycroft 947: for (scb = sea->nexus_list.tqh_first; scb;
1.1 mycroft 948: scb = scb->chain.tqe_next)
1.40 bouyer 949: if (target_mask == (1 << scb->xs->xs_periph->periph_target) &&
950: lun == scb->xs->xs_periph->periph_lun) {
1.3 mycroft 951: TAILQ_REMOVE(&sea->nexus_list, scb,
1.1 mycroft 952: chain);
953: break;
954: }
955: if (!scb) {
1.21 christos 956: printf("%s: target %02x lun %d not disconnected\n",
1.1 mycroft 957: sea->sc_dev.dv_xname, target_mask, lun);
958: /*
959: * Since we have an established nexus that we can't do
960: * anything with, we must abort it.
961: */
962: abort = 1;
963: }
964: }
965:
966: if (abort) {
967: msg[0] = MSG_ABORT;
968: len = 1;
969: data = msg;
1.3 mycroft 970: phase = PH_MSGOUT;
1.1 mycroft 971: CONTROL = BASE_CMD | CMD_ATTN;
972: sea_transfer_pio(sea, &phase, &len, &data);
973: } else
1.3 mycroft 974: sea->nexus = scb;
1.1 mycroft 975:
976: return;
977: }
978:
979: /*
980: * Transfer data in given phase using polled I/O.
981: */
982: int
983: sea_transfer_pio(sea, phase, count, data)
984: struct sea_softc *sea;
985: u_char *phase;
1.3 mycroft 986: int *count;
1.1 mycroft 987: u_char **data;
988: {
1.36 augustss 989: u_char p = *phase, tmp;
990: int c = *count;
991: u_char *d = *data;
1.1 mycroft 992: int timeout;
993:
994: do {
995: /*
996: * Wait for assertion of REQ, after which the phase bits will
997: * be valid.
998: */
1.3 mycroft 999: for (timeout = 0; timeout < 50000; timeout++)
1.1 mycroft 1000: if ((tmp = STATUS) & STAT_REQ)
1001: break;
1002: if (!(tmp & STAT_REQ)) {
1.21 christos 1003: printf("%s: timeout waiting for STAT_REQ\n",
1.1 mycroft 1004: sea->sc_dev.dv_xname);
1005: break;
1006: }
1007:
1008: /*
1009: * Check for phase mismatch. Reached if the target decides
1010: * that it has finished the transfer.
1011: */
1.3 mycroft 1012: if (sea->type == FDOMAIN840)
1013: tmp = ((tmp & 0x08) >> 2) |
1014: ((tmp & 0x02) << 2) |
1015: (tmp & 0xf5);
1016: if ((tmp & PH_MASK) != p)
1.1 mycroft 1017: break;
1018:
1019: /* Do actual transfer from SCSI bus to/from memory. */
1020: if (!(p & STAT_IO))
1021: DATA = *d;
1022: else
1023: *d = DATA;
1024: ++d;
1025:
1026: /*
1027: * The SCSI standard suggests that in MSGOUT phase, the
1028: * initiator should drop ATN on the last byte of the message
1029: * phase after REQ has been asserted for the handshake but
1030: * before the initiator raises ACK.
1031: * Don't know how to accomplish this on the ST01/02.
1032: */
1033:
1034: #if 0
1035: /*
1036: * XXX
1037: * The st01 code doesn't wait for STAT_REQ to be deasserted.
1038: * Is this ok?
1039: */
1040: for (timeout = 0; timeout < 200000L; timeout++)
1041: if (!(STATUS & STAT_REQ))
1042: break;
1043: if (STATUS & STAT_REQ)
1.21 christos 1044: printf("%s: timeout on wait for !STAT_REQ",
1.1 mycroft 1045: sea->sc_dev.dv_xname);
1046: #endif
1047: } while (--c);
1048:
1049: *count = c;
1050: *data = d;
1051: tmp = STATUS;
1052: if (tmp & STAT_REQ)
1.3 mycroft 1053: *phase = tmp & PH_MASK;
1.1 mycroft 1054: else
1.3 mycroft 1055: *phase = PH_INVALID;
1.1 mycroft 1056:
1057: if (c && (*phase != p))
1058: return -1;
1059: return 0;
1060: }
1061:
1062: /*
1063: * Establish I_T_L or I_T_L_Q nexus for new or existing command including
1064: * ARBITRATION, SELECTION, and initial message out for IDENTIFY and queue
1065: * messages. Return -1 if selection could not execute for some reason, 0 if
1066: * selection succeded or failed because the target did not respond.
1067: */
1068: int
1069: sea_select(sea, scb)
1070: struct sea_softc *sea;
1071: struct sea_scb *scb;
1072: {
1073: u_char msg[3], phase;
1074: u_char *data;
1.3 mycroft 1075: int len;
1.1 mycroft 1076: int timeout;
1077:
1078: CONTROL = BASE_CMD;
1079: DATA = sea->our_id_mask;
1080: CONTROL = (BASE_CMD & ~CMD_INTR) | CMD_START_ARB;
1081:
1082: /* wait for arbitration to complete */
1083: for (timeout = 0; timeout < 3000000L; timeout++)
1084: if (STATUS & STAT_ARB_CMPL)
1085: break;
1086: if (!(STATUS & STAT_ARB_CMPL)) {
1087: if (STATUS & STAT_SEL) {
1.21 christos 1088: printf("%s: arbitration lost\n", sea->sc_dev.dv_xname);
1.1 mycroft 1089: scb->flags |= SCB_ERROR;
1090: } else {
1.21 christos 1091: printf("%s: arbitration timeout\n",
1.1 mycroft 1092: sea->sc_dev.dv_xname);
1093: scb->flags |= SCB_TIMEOUT;
1094: }
1095: CONTROL = BASE_CMD;
1096: return -1;
1097: }
1098:
1099: delay(2);
1.40 bouyer 1100: DATA = (u_char)((1 << scb->xs->xs_periph->periph_target) |
1.23 bouyer 1101: sea->our_id_mask);
1.1 mycroft 1102: CONTROL =
1103: #ifdef SEA_NOMSGS
1104: (BASE_CMD & ~CMD_INTR) | CMD_DRVR_ENABLE | CMD_SEL;
1105: #else
1106: (BASE_CMD & ~CMD_INTR) | CMD_DRVR_ENABLE | CMD_SEL | CMD_ATTN;
1107: #endif
1108: delay(1);
1109:
1110: /* wait for a bsy from target */
1111: for (timeout = 0; timeout < 2000000L; timeout++)
1112: if (STATUS & STAT_BSY)
1113: break;
1114: if (!(STATUS & STAT_BSY)) {
1115: /* should return some error to the higher level driver */
1116: CONTROL = BASE_CMD;
1117: scb->flags |= SCB_TIMEOUT;
1118: return 0;
1119: }
1120:
1121: /* Try to make the target to take a message from us */
1122: #ifdef SEA_NOMSGS
1123: CONTROL = (BASE_CMD & ~CMD_INTR) | CMD_DRVR_ENABLE;
1124: #else
1125: CONTROL = (BASE_CMD & ~CMD_INTR) | CMD_DRVR_ENABLE | CMD_ATTN;
1126: #endif
1127: delay(1);
1128:
1129: /* should start a msg_out phase */
1130: for (timeout = 0; timeout < 2000000L; timeout++)
1131: if (STATUS & STAT_REQ)
1132: break;
1.3 mycroft 1133: /* Remove ATN. */
1.1 mycroft 1134: CONTROL = BASE_CMD | CMD_DRVR_ENABLE;
1135: if (!(STATUS & STAT_REQ)) {
1136: /*
1137: * This should not be taken as an error, but more like an
1138: * unsupported feature! Should set a flag indicating that the
1139: * target don't support messages, and continue without failure.
1140: * (THIS IS NOT AN ERROR!)
1141: */
1142: } else {
1.40 bouyer 1143: msg[0] = MSG_IDENTIFY(scb->xs->xs_periph->periph_lun, 1);
1.1 mycroft 1144: len = 1;
1145: data = msg;
1.3 mycroft 1146: phase = PH_MSGOUT;
1.1 mycroft 1147: /* Should do test on result of sea_transfer_pio(). */
1148: sea_transfer_pio(sea, &phase, &len, &data);
1149: }
1150: if (!(STATUS & STAT_BSY))
1.21 christos 1151: printf("%s: after successful arbitrate: no STAT_BSY!\n",
1.1 mycroft 1152: sea->sc_dev.dv_xname);
1153:
1.3 mycroft 1154: sea->nexus = scb;
1.40 bouyer 1155: sea->busy[scb->xs->xs_periph->periph_target] |=
1156: 1 << scb->xs->xs_periph->periph_lun;
1.1 mycroft 1157: /* This assignment should depend on possibility to send a message to target. */
1158: CONTROL = BASE_CMD | CMD_DRVR_ENABLE;
1159: /* XXX Reset pointer in command? */
1160: return 0;
1161: }
1162:
1163: /*
1164: * Send an abort to the target. Return 1 success, 0 on failure.
1165: */
1166: int
1167: sea_abort(sea, scb)
1168: struct sea_softc *sea;
1169: struct sea_scb *scb;
1170: {
1171: struct sea_scb *tmp;
1172: u_char msg, phase, *msgptr;
1.3 mycroft 1173: int len;
1.1 mycroft 1174:
1175: /*
1176: * If the command hasn't been issued yet, we simply remove it from the
1177: * issue queue
1178: * XXX Could avoid this loop.
1179: */
1.3 mycroft 1180: for (tmp = sea->ready_list.tqh_first; tmp; tmp = tmp->chain.tqe_next)
1.1 mycroft 1181: if (scb == tmp) {
1.3 mycroft 1182: TAILQ_REMOVE(&sea->ready_list, scb, chain);
1.1 mycroft 1183: /* XXX Set some type of error result for operation. */
1184: return 1;
1185: }
1186:
1187: /*
1188: * If any commands are connected, we're going to fail the abort and let
1189: * the high level SCSI driver retry at a later time or issue a reset.
1190: */
1.3 mycroft 1191: if (sea->nexus)
1.1 mycroft 1192: return 0;
1193:
1194: /*
1195: * If the command is currently disconnected from the bus, and there are
1196: * no connected commands, we reconnect the I_T_L or I_T_L_Q nexus
1197: * associated with it, go into message out, and send an abort message.
1198: */
1.3 mycroft 1199: for (tmp = sea->nexus_list.tqh_first; tmp;
1.1 mycroft 1200: tmp = tmp->chain.tqe_next)
1201: if (scb == tmp) {
1202: if (sea_select(sea, scb))
1203: return 0;
1204:
1205: msg = MSG_ABORT;
1206: msgptr = &msg;
1207: len = 1;
1.3 mycroft 1208: phase = PH_MSGOUT;
1.1 mycroft 1209: CONTROL = BASE_CMD | CMD_ATTN;
1210: sea_transfer_pio(sea, &phase, &len, &msgptr);
1211:
1.3 mycroft 1212: for (tmp = sea->nexus_list.tqh_first; tmp;
1.1 mycroft 1213: tmp = tmp->chain.tqe_next)
1214: if (scb == tmp) {
1.3 mycroft 1215: TAILQ_REMOVE(&sea->nexus_list,
1.1 mycroft 1216: scb, chain);
1217: /* XXX Set some type of error result
1218: for the operation. */
1219: return 1;
1220: }
1221: }
1222:
1223: /* Command not found in any queue; race condition? */
1224: return 1;
1225: }
1226:
1227: void
1228: sea_done(sea, scb)
1229: struct sea_softc *sea;
1230: struct sea_scb *scb;
1231: {
1.23 bouyer 1232: struct scsipi_xfer *xs = scb->xs;
1.1 mycroft 1233:
1.35 thorpej 1234: callout_stop(&scb->xs->xs_callout);
1.1 mycroft 1235:
1236: xs->resid = scb->datalen;
1237:
1.3 mycroft 1238: /* XXXX need to get status */
1239: if (scb->flags == SCB_ACTIVE) {
1.1 mycroft 1240: xs->resid = 0;
1241: } else {
1.3 mycroft 1242: if (scb->flags & (SCB_TIMEOUT | SCB_ABORTED))
1243: xs->error = XS_TIMEOUT;
1244: if (scb->flags & SCB_ERROR)
1.1 mycroft 1245: xs->error = XS_DRIVER_STUFFUP;
1246: }
1.34 thorpej 1247: sea_free_scb(sea, scb, xs->xs_control);
1.23 bouyer 1248: scsipi_done(xs);
1.1 mycroft 1249: }
1250:
1251: /*
1252: * Wait for completion of command in polled mode.
1253: */
1254: int
1.3 mycroft 1255: sea_poll(sea, xs, count)
1.1 mycroft 1256: struct sea_softc *sea;
1.23 bouyer 1257: struct scsipi_xfer *xs;
1.3 mycroft 1258: int count;
1.1 mycroft 1259: {
1260: int s;
1261:
1262: while (count) {
1263: /* try to do something */
1264: s = splbio();
1265: if (!main_running)
1266: sea_main();
1267: splx(s);
1.34 thorpej 1268: if (xs->xs_status & XS_STS_DONE)
1.3 mycroft 1269: return 0;
1270: delay(1000);
1.1 mycroft 1271: count--;
1272: }
1.3 mycroft 1273: return 1;
1.1 mycroft 1274: }
1275:
1276: /*
1277: * Do the transfer. We know we are connected. Update the flags, and call
1278: * sea_done() when task accomplished. Dialog controlled by the target.
1279: */
1280: void
1281: sea_information_transfer(sea)
1282: struct sea_softc *sea;
1283: {
1284: int timeout;
1.3 mycroft 1285: u_char msgout = MSG_NOOP;
1286: int len;
1.1 mycroft 1287: int s;
1288: u_char *data;
1.3 mycroft 1289: u_char phase, tmp, old_phase = PH_INVALID;
1290: struct sea_scb *scb = sea->nexus;
1.1 mycroft 1291: int loop;
1292:
1293: for (timeout = 0; timeout < 10000000L; timeout++) {
1294: tmp = STATUS;
1.3 mycroft 1295: if (tmp & STAT_PARITY)
1.21 christos 1296: printf("%s: parity error detected\n",
1.3 mycroft 1297: sea->sc_dev.dv_xname);
1.1 mycroft 1298: if (!(tmp & STAT_BSY)) {
1299: for (loop = 0; loop < 20; loop++)
1300: if ((tmp = STATUS) & STAT_BSY)
1301: break;
1302: if (!(tmp & STAT_BSY)) {
1.21 christos 1303: printf("%s: !STAT_BSY unit in data transfer!\n",
1.1 mycroft 1304: sea->sc_dev.dv_xname);
1305: s = splbio();
1.3 mycroft 1306: sea->nexus = NULL;
1.1 mycroft 1307: scb->flags = SCB_ERROR;
1308: splx(s);
1309: sea_done(sea, scb);
1310: return;
1311: }
1312: }
1313:
1314: /* we only have a valid SCSI phase when REQ is asserted */
1315: if (!(tmp & STAT_REQ))
1316: continue;
1317:
1.3 mycroft 1318: if (sea->type == FDOMAIN840)
1319: tmp = ((tmp & 0x08) >> 2) |
1320: ((tmp & 0x02) << 2) |
1321: (tmp & 0xf5);
1322: phase = tmp & PH_MASK;
1.1 mycroft 1323: if (phase != old_phase)
1324: old_phase = phase;
1325:
1326: switch (phase) {
1.3 mycroft 1327: case PH_DATAOUT:
1.1 mycroft 1328: #ifdef SEA_NODATAOUT
1.21 christos 1329: printf("%s: SEA_NODATAOUT set, attempted DATAOUT aborted\n",
1.1 mycroft 1330: sea->sc_dev.dv_xname);
1331: msgout = MSG_ABORT;
1332: CONTROL = BASE_CMD | CMD_ATTN;
1333: break;
1334: #endif
1.3 mycroft 1335: case PH_DATAIN:
1.1 mycroft 1336: if (!scb->data)
1.21 christos 1337: printf("no data address!\n");
1.1 mycroft 1338: #ifdef SEA_BLINDTRANSFER
1339: if (scb->datalen && !(scb->datalen % BLOCK_SIZE)) {
1340: while (scb->datalen) {
1.3 mycroft 1341: for (loop = 0; loop < 50000; loop++)
1.1 mycroft 1342: if ((tmp = STATUS) & STAT_REQ)
1343: break;
1344: if (!(tmp & STAT_REQ)) {
1.21 christos 1345: printf("%s: timeout waiting for STAT_REQ\n",
1.1 mycroft 1346: sea->sc_dev.dv_xname);
1347: /* XXX Do something? */
1348: }
1.3 mycroft 1349: if (sea->type == FDOMAIN840)
1350: tmp = ((tmp & 0x08) >> 2) |
1351: ((tmp & 0x02) << 2) |
1352: (tmp & 0xf5);
1353: if ((tmp & PH_MASK) != phase)
1.1 mycroft 1354: break;
1355: if (!(phase & STAT_IO)) {
1356: #ifdef SEA_ASSEMBLER
1.37 mycroft 1357: caddr_t junk;
1358: asm("cld\n\t\
1.1 mycroft 1359: rep\n\t\
1360: movsl" :
1.37 mycroft 1361: "=S" (scb->data),
1362: "=c" (len),
1363: "=D" (junk) :
1.1 mycroft 1364: "0" (scb->data),
1.37 mycroft 1365: "1" (BLOCK_SIZE >> 2),
1366: "2" (sea->maddr_dr));
1.1 mycroft 1367: #else
1.37 mycroft 1368: for (len = BLOCK_SIZE;
1369: len; len--)
1.1 mycroft 1370: DATA = *(scb->data++);
1371: #endif
1372: } else {
1373: #ifdef SEA_ASSEMBLER
1.37 mycroft 1374: caddr_t junk;
1375: asm("cld\n\t\
1.1 mycroft 1376: rep\n\t\
1377: movsl" :
1.37 mycroft 1378: "=D" (scb->data),
1379: "=c" (len),
1380: "=S" (junk) :
1.1 mycroft 1381: "0" (scb->data),
1.37 mycroft 1382: "1" (BLOCK_SIZE >> 2),
1383: "2" (sea->maddr_dr));
1.1 mycroft 1384: #else
1.37 mycroft 1385: for (len = BLOCK_SIZE;
1386: len; len--)
1.1 mycroft 1387: *(scb->data++) = DATA;
1388: #endif
1389: }
1390: scb->datalen -= BLOCK_SIZE;
1391: }
1392: }
1393: #endif
1394: if (scb->datalen)
1395: sea_transfer_pio(sea, &phase, &scb->datalen,
1396: &scb->data);
1397: break;
1.3 mycroft 1398: case PH_MSGIN:
1.1 mycroft 1399: /* Multibyte messages should not be present here. */
1400: len = 1;
1401: data = &tmp;
1402: sea_transfer_pio(sea, &phase, &len, &data);
1403: /* scb->MessageIn = tmp; */
1404:
1405: switch (tmp) {
1406: case MSG_ABORT:
1407: scb->flags = SCB_ABORTED;
1.21 christos 1408: printf("sea: command aborted by target\n");
1.1 mycroft 1409: CONTROL = BASE_CMD;
1410: sea_done(sea, scb);
1411: return;
1.3 mycroft 1412: case MSG_CMDCOMPLETE:
1.1 mycroft 1413: s = splbio();
1.3 mycroft 1414: sea->nexus = NULL;
1.1 mycroft 1415: splx(s);
1.40 bouyer 1416: sea->busy[scb->xs->xs_periph->periph_target] &=
1417: ~(1 << scb->xs->xs_periph->periph_lun);
1.1 mycroft 1418: CONTROL = BASE_CMD;
1419: sea_done(sea, scb);
1420: return;
1421: case MSG_MESSAGE_REJECT:
1.41 wiz 1422: printf("%s: message_reject received\n",
1.1 mycroft 1423: sea->sc_dev.dv_xname);
1424: break;
1425: case MSG_DISCONNECT:
1426: s = splbio();
1.3 mycroft 1427: TAILQ_INSERT_TAIL(&sea->nexus_list,
1.1 mycroft 1428: scb, chain);
1.3 mycroft 1429: sea->nexus = NULL;
1.1 mycroft 1430: CONTROL = BASE_CMD;
1431: splx(s);
1432: return;
1.3 mycroft 1433: case MSG_SAVEDATAPOINTER:
1434: case MSG_RESTOREPOINTERS:
1.1 mycroft 1435: /* save/restore of pointers are ignored */
1436: break;
1437: default:
1438: /*
1439: * This should be handled in the pio data
1440: * transfer phase, as the ATN should be raised
1441: * before ACK goes false when rejecting a
1442: * message.
1443: */
1.21 christos 1444: printf("%s: unknown message in: %x\n",
1.1 mycroft 1445: sea->sc_dev.dv_xname, tmp);
1446: break;
1447: } /* switch (tmp) */
1448: break;
1.3 mycroft 1449: case PH_MSGOUT:
1.1 mycroft 1450: len = 1;
1451: data = &msgout;
1452: /* sea->last_message = msgout; */
1453: sea_transfer_pio(sea, &phase, &len, &data);
1454: if (msgout == MSG_ABORT) {
1.21 christos 1455: printf("%s: sent message abort to target\n",
1.1 mycroft 1456: sea->sc_dev.dv_xname);
1457: s = splbio();
1.40 bouyer 1458: sea->busy[scb->xs->xs_periph->periph_target] &=
1459: ~(1 << scb->xs->xs_periph->periph_lun);
1.3 mycroft 1460: sea->nexus = NULL;
1.1 mycroft 1461: scb->flags = SCB_ABORTED;
1462: splx(s);
1463: /* enable interrupt from scsi */
1464: sea_done(sea, scb);
1465: return;
1466: }
1.3 mycroft 1467: msgout = MSG_NOOP;
1.1 mycroft 1468: break;
1.3 mycroft 1469: case PH_CMD:
1470: len = scb->xs->cmdlen;
1471: data = (char *) scb->xs->cmd;
1.1 mycroft 1472: sea_transfer_pio(sea, &phase, &len, &data);
1473: break;
1.3 mycroft 1474: case PH_STAT:
1.1 mycroft 1475: len = 1;
1476: data = &tmp;
1477: sea_transfer_pio(sea, &phase, &len, &data);
1.3 mycroft 1478: scb->xs->status = tmp;
1.1 mycroft 1479: break;
1480: default:
1.21 christos 1481: printf("sea: unknown phase\n");
1.1 mycroft 1482: } /* switch (phase) */
1483: } /* for (...) */
1484:
1485: /* If we get here we have got a timeout! */
1.21 christos 1486: printf("%s: timeout in data transfer\n", sea->sc_dev.dv_xname);
1.1 mycroft 1487: scb->flags = SCB_TIMEOUT;
1488: /* XXX Should I clear scsi-bus state? */
1489: sea_done(sea, scb);
1490: }
CVSweb <webmaster@jp.NetBSD.org>