Annotation of src/sys/dev/isa/seagate.c, Revision 1.65.6.1
1.65.6.1! skrll 1: /* $NetBSD: seagate.c,v 1.67 2009/03/16 09:34:17 cegger 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)
1.57 perry 8: * Copyright 1994, Robert Knier (rknier@qgraph.com)
1.1 mycroft 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
1.57 perry 42: * rknier 940331 Added fast transfer code
43: * rknier 940407 Added assembler coded data transfers
1.1 mycroft 44: */
45:
46: /*
47: * What should really be done:
1.57 perry 48: *
1.1 mycroft 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: */
1.57 perry 66:
1.43 lukem 67: #include <sys/cdefs.h>
1.65.6.1! skrll 68: __KERNEL_RCSID(0, "$NetBSD: seagate.c,v 1.67 2009/03/16 09:34:17 cegger 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.63 ad 82: #include <sys/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:
1.57 perry 174: /* scsi control block used to keep info about a scsi command */
1.1 mycroft 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.62 christos 197: void * maddr; /* Base address for card */
198: void * maddr_cr_sr; /* Address of control and status reg */
199: void * 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 {
1.58 christos 233: const char *signature;
1.1 mycroft 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.56 perry 278: int seaintr(void *);
279: void sea_scsipi_request(struct scsipi_channel *, scsipi_adapter_req_t, void *);
280: void sea_timeout(void *);
281: void sea_done(struct sea_softc *, struct sea_scb *);
282: struct sea_scb *sea_get_scb(struct sea_softc *, int);
283: void sea_free_scb(struct sea_softc *, struct sea_scb *, int);
284: static void sea_main(void);
285: static void sea_information_transfer(struct sea_softc *);
286: int sea_poll(struct sea_softc *, struct scsipi_xfer *, int);
287: void sea_init(struct sea_softc *);
288: void sea_send_scb(struct sea_softc *sea, struct sea_scb *scb);
289: void sea_reselect(struct sea_softc *sea);
290: int sea_select(struct sea_softc *sea, struct sea_scb *scb);
291: int sea_transfer_pio(struct sea_softc *sea, u_char *phase,
292: int *count, u_char **data);
293: int sea_abort(struct sea_softc *, struct sea_scb *scb);
1.1 mycroft 294:
1.56 perry 295: void sea_grow_scb(struct sea_softc *);
1.1 mycroft 296:
1.56 perry 297: int seaprobe(struct device *, struct cfdata *, void *);
298: void seaattach(struct device *, struct device *, void *);
1.1 mycroft 299:
1.51 thorpej 300: CFATTACH_DECL(sea, sizeof(struct sea_softc),
1.52 thorpej 301: seaprobe, seaattach, NULL, NULL);
1.14 thorpej 302:
1.25 thorpej 303: extern struct cfdriver sea_cd;
1.1 mycroft 304:
305: #ifdef SEA_DEBUGQUEUE
306: void
1.65.6.1! skrll 307: sea_queue_length(struct sea_softc *sea)
1.1 mycroft 308: {
309: struct sea_scb *scb;
310: int connected, issued, disconnected;
311:
1.3 mycroft 312: connected = sea->nexus ? 1 : 0;
313: for (scb = sea->ready_list.tqh_first, issued = 0; scb;
1.1 mycroft 314: scb = scb->chain.tqe_next, issued++);
1.3 mycroft 315: for (scb = sea->nexus_list.tqh_first, disconnected = 0; scb;
1.1 mycroft 316: scb = scb->chain.tqe_next, disconnected++);
1.64 cegger 317: printf("%s: length: %d/%d/%d\n", device_xname(&sea->sc_dev), connected,
1.1 mycroft 318: issued, disconnected);
319: }
320: #endif
321:
322: /*
323: * Check if the device can be found at the port given and if so, detect the
324: * type the type of board. Set it up ready for further work. Takes the isa_dev
325: * structure from autoconf as an argument.
326: * Returns 1 if card recognized, 0 if errors.
327: */
328: int
1.61 christos 329: seaprobe(struct device *parent, struct cfdata *match,
1.60 christos 330: void *aux)
1.1 mycroft 331: {
332: struct isa_attach_args *ia = aux;
1.26 drochner 333: int i, type = 0;
1.62 christos 334: void *maddr;
1.1 mycroft 335:
1.45 thorpej 336: if (ia->ia_niomem < 1)
337: return (0);
338: if (ia->ia_nirq < 1)
339: return (0);
340:
341: if (ISA_DIRECT_CONFIG(ia))
342: return (0);
343:
1.55 drochner 344: if (ia->ia_iomem[0].ir_addr == ISA_UNKNOWN_IOMEM)
1.45 thorpej 345: return (0);
1.55 drochner 346: if (ia->ia_irq[0].ir_irq == ISA_UNKNOWN_IRQ)
1.45 thorpej 347: return (0);
348:
349: /* XXX XXX XXX */
350: maddr = ISA_HOLE_VADDR(ia->ia_iomem[0].ir_addr);
1.1 mycroft 351:
1.26 drochner 352: /* check board type */ /* No way to define this through config */
353: for (i = 0; i < nsignatures; i++)
1.62 christos 354: if (!memcmp((char *)maddr + signatures[i].offset,
1.26 drochner 355: signatures[i].signature, signatures[i].length)) {
356: type = signatures[i].type;
357: break;
358: }
359:
360: /* Find controller and data memory addresses */
361: switch (type) {
362: case SEAGATE:
363: case FDOMAIN840:
364: case FDOMAIN:
365: break;
366: default:
1.54 christos 367: #ifdef SEA_DEBUG
1.48 sommerfe 368: printf("seaprobe: board type unknown at address %p\n", maddr);
1.26 drochner 369: #endif
370: return 0;
371: }
372:
1.45 thorpej 373: ia->ia_niomem = 1;
374: ia->ia_iomem[0].ir_size = 0x2000;
375:
376: ia->ia_nirq = 1;
377:
378: ia->ia_nio = 0;
379: ia->ia_ndrq = 0;
380:
1.26 drochner 381: return 1;
382: }
383:
384: /*
385: * Attach all sub-devices we can find
386: */
387: void
1.61 christos 388: seaattach(struct device *parent, struct device *self, void *aux)
1.26 drochner 389: {
390: struct isa_attach_args *ia = aux;
391: struct sea_softc *sea = (void *)self;
1.40 bouyer 392: struct scsipi_adapter *adapt = &sea->sc_adapter;
393: struct scsipi_channel *chan = &sea->sc_channel;
1.26 drochner 394: int i;
395:
1.45 thorpej 396: /* XXX XXX XXX */
397: sea->maddr = ISA_HOLE_VADDR(ia->ia_iomem[0].ir_addr);
1.57 perry 398:
1.1 mycroft 399: /* check board type */ /* No way to define this through config */
400: for (i = 0; i < nsignatures; i++)
1.62 christos 401: if (!memcmp((char *)sea->maddr + signatures[i].offset,
1.1 mycroft 402: signatures[i].signature, signatures[i].length)) {
403: sea->type = signatures[i].type;
404: break;
405: }
406:
407: /* Find controller and data memory addresses */
408: switch (sea->type) {
409: case SEAGATE:
1.3 mycroft 410: case FDOMAIN840:
1.1 mycroft 411: sea->maddr_cr_sr =
412: (void *) (((u_char *)sea->maddr) + 0x1a00);
413: sea->maddr_dr =
414: (void *) (((u_char *)sea->maddr) + 0x1c00);
415: break;
416: case FDOMAIN:
417: sea->maddr_cr_sr =
418: (void *) (((u_char *)sea->maddr) + 0x1c00);
419: sea->maddr_dr =
420: (void *) (((u_char *)sea->maddr) + 0x1e00);
421: break;
422: default:
1.22 mikel 423: #ifdef DEBUG
1.48 sommerfe 424: printf("%s: board type unknown at address %p\n",
1.64 cegger 425: device_xname(&sea->sc_dev), sea->maddr);
1.10 mycroft 426: #endif
1.26 drochner 427: return;
1.1 mycroft 428: }
429:
430: /* Test controller RAM (works the same way on future domain cards?) */
431: *((u_char *)sea->maddr + SEA_RAMOFFSET) = 0xa5;
432: *((u_char *)sea->maddr + SEA_RAMOFFSET + 1) = 0x5a;
433:
434: if ((*((u_char *)sea->maddr + SEA_RAMOFFSET) != 0xa5) ||
435: (*((u_char *)sea->maddr + SEA_RAMOFFSET + 1) != 0x5a)) {
1.64 cegger 436: aprint_error_dev(&sea->sc_dev, "board RAM failure\n");
1.26 drochner 437: return;
1.1 mycroft 438: }
439:
440: sea_init(sea);
441:
442: /*
1.40 bouyer 443: * Fill in the scsipi_adapter.
1.30 thorpej 444: */
1.40 bouyer 445: memset(adapt, 0, sizeof(*adapt));
446: adapt->adapt_dev = &sea->sc_dev;
447: adapt->adapt_nchannels = 1;
448: adapt->adapt_openings = sea->numscbs;
449: adapt->adapt_max_periph = 1;
450: adapt->adapt_request = sea_scsipi_request;
451: adapt->adapt_minphys = minphys;
1.30 thorpej 452:
453: /*
1.40 bouyer 454: * Fill in the scsipi_channel.
1.1 mycroft 455: */
1.40 bouyer 456: memset(chan, 0, sizeof(*chan));
457: chan->chan_adapter = adapt;
458: chan->chan_bustype = &scsi_bustype;
459: chan->chan_channel = 0;
460: chan->chan_ntargets = 8;
461: chan->chan_nluns = 8;
462: chan->chan_id = sea->our_id;
463: chan->chan_flags = SCSIPI_CHAN_CANGROW;
1.57 perry 464:
1.21 christos 465: printf("\n");
1.1 mycroft 466:
1.45 thorpej 467: sea->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq[0].ir_irq,
468: IST_EDGE, IPL_BIO, seaintr, sea);
1.1 mycroft 469:
470: /*
471: * ask the adapter what subunits are present
472: */
1.40 bouyer 473: config_found(self, &sea->sc_channel, scsiprint);
1.1 mycroft 474: }
475:
476: /*
477: * Catch an interrupt from the adaptor
478: */
479: int
1.65.6.1! skrll 480: seaintr(void *arg)
1.1 mycroft 481: {
1.8 cgd 482: struct sea_softc *sea = arg;
1.1 mycroft 483:
484: #ifdef DEBUG /* extra overhead, and only needed for intr debugging */
485: if ((STATUS & STAT_PARITY) == 0 &&
486: (STATUS & (STAT_SEL | STAT_IO)) != (STAT_SEL | STAT_IO))
487: return 0;
488: #endif
489:
490: loop:
491: /* dispatch to appropriate routine if found and done=0 */
492: /* should check to see that this card really caused the interrupt */
493:
494: if (STATUS & STAT_PARITY) {
495: /* Parity error interrupt */
1.64 cegger 496: aprint_error_dev(&sea->sc_dev, "parity error\n");
1.1 mycroft 497: return 1;
498: }
499:
500: if ((STATUS & (STAT_SEL | STAT_IO)) == (STAT_SEL | STAT_IO)) {
501: /* Reselect interrupt */
502: sea_reselect(sea);
503: if (!main_running)
504: sea_main();
505: goto loop;
506: }
507:
508: return 1;
509: }
510:
511: /*
512: * Setup data structures, and reset the board and the SCSI bus.
513: */
514: void
1.65.6.1! skrll 515: sea_init(struct sea_softc *sea)
1.1 mycroft 516: {
517: int i;
1.57 perry 518:
1.1 mycroft 519: /* Reset the scsi bus (I don't know if this is needed */
520: CONTROL = BASE_CMD | CMD_DRVR_ENABLE | CMD_RST;
521: delay(25); /* hold reset for at least 25 microseconds */
522: CONTROL = BASE_CMD;
523: delay(10); /* wait a Bus Clear Delay (800 ns + bus free delay (800 ns) */
524:
525: /* Set our id (don't know anything about this) */
526: switch (sea->type) {
527: case SEAGATE:
528: sea->our_id = 7;
529: break;
530: case FDOMAIN:
1.3 mycroft 531: case FDOMAIN840:
1.1 mycroft 532: sea->our_id = 6;
533: break;
534: }
535: sea->our_id_mask = 1 << sea->our_id;
536:
537: /* init fields used by our routines */
1.3 mycroft 538: sea->nexus = 0;
539: TAILQ_INIT(&sea->ready_list);
540: TAILQ_INIT(&sea->nexus_list);
541: TAILQ_INIT(&sea->free_list);
1.1 mycroft 542: for (i = 0; i < 8; i++)
543: sea->busy[i] = 0x00;
544:
545: /* link up the free list of scbs */
546: sea->numscbs = SCB_TABLE_SIZE;
547: for (i = 0; i < SCB_TABLE_SIZE; i++) {
1.3 mycroft 548: TAILQ_INSERT_TAIL(&sea->free_list, &sea->scb[i], chain);
1.1 mycroft 549: }
550: }
551:
552: /*
553: * start a scsi operation given the command and the data address. Also needs
554: * the unit, target and lu.
555: */
1.40 bouyer 556: void
1.65.6.1! skrll 557: sea_scsipi_request(struct scsipi_channel *chan, scsipi_adapter_req_t req, void *arg)
1.40 bouyer 558: {
1.23 bouyer 559: struct scsipi_xfer *xs;
1.40 bouyer 560: struct scsipi_periph *periph;
561: struct sea_softc *sea = (void *)chan->chan_adapter->adapt_dev;
1.1 mycroft 562: struct sea_scb *scb;
563: int flags;
1.3 mycroft 564: int s;
1.1 mycroft 565:
1.40 bouyer 566: switch (req) {
567: case ADAPTER_REQ_RUN_XFER:
568: xs = arg;
569: periph = xs->xs_periph;
570: flags = xs->xs_control;
571:
572: SC_DEBUG(periph, SCSIPI_DB2, ("sea_scsipi_requeset\n"));
573:
574: /* XXX Reset not implemented. */
575: if (flags & XS_CTL_RESET) {
1.64 cegger 576: printf("%s: resetting\n", device_xname(&sea->sc_dev));
1.40 bouyer 577: xs->error = XS_DRIVER_STUFFUP;
578: scsipi_done(xs);
579: return;
580: }
1.1 mycroft 581:
1.40 bouyer 582: /* Get an SCB to use. */
583: scb = sea_get_scb(sea, flags);
584: #ifdef DIAGNOSTIC
585: /*
586: * This should never happen as we track the resources
587: * in the mid-layer.
588: */
589: if (scb == NULL) {
590: scsipi_printaddr(periph);
591: printf("unable to allocate scb\n");
592: panic("sea_scsipi_request");
593: }
594: #endif
595:
596: scb->flags = SCB_ACTIVE;
597: scb->xs = xs;
1.1 mycroft 598:
599: /*
1.40 bouyer 600: * Put all the arguments for the xfer in the scb
1.1 mycroft 601: */
1.40 bouyer 602: scb->datalen = xs->datalen;
603: scb->data = xs->data;
1.1 mycroft 604:
605: #ifdef SEA_DEBUGQUEUE
1.40 bouyer 606: sea_queue_length(sea);
1.1 mycroft 607: #endif
608:
1.40 bouyer 609: s = splbio();
1.3 mycroft 610:
1.40 bouyer 611: sea_send_scb(sea, scb);
612:
613: if ((flags & XS_CTL_POLL) == 0) {
614: callout_reset(&scb->xs->xs_callout,
1.49 bouyer 615: mstohz(xs->timeout), sea_timeout, scb);
1.40 bouyer 616: splx(s);
617: return;
618: }
1.3 mycroft 619:
1.1 mycroft 620: splx(s);
621:
1.40 bouyer 622: /*
623: * If we can't use interrupts, poll on completion
624: */
625: if (sea_poll(sea, xs, xs->timeout)) {
626: sea_timeout(scb);
627: if (sea_poll(sea, xs, 2000))
628: sea_timeout(scb);
629: }
630: return;
631:
632: case ADAPTER_REQ_GROW_RESOURCES:
633: sea_grow_scb(sea);
634: return;
635:
636: case ADAPTER_REQ_SET_XFER_MODE:
637: {
638: struct scsipi_xfer_mode *xm = arg;
1.3 mycroft 639:
1.40 bouyer 640: /*
641: * We don't support sync or wide or tagged queueing,
642: * so announce that now.
643: */
644: xm->xm_mode = 0;
645: xm->xm_period = 0;
646: xm->xm_offset = 0;
647: scsipi_async_event(chan, ASYNC_EVENT_XFER_MODE, xm);
648: return;
649: }
1.3 mycroft 650: }
1.1 mycroft 651: }
652:
653: /*
654: * Get a free scb. If there are none, see if we can allocate a new one. If so,
655: * put it in the hash table too; otherwise return an error or sleep.
656: */
657: struct sea_scb *
1.61 christos 658: sea_get_scb(struct sea_softc *sea, int flags)
1.1 mycroft 659: {
660: int s;
661: struct sea_scb *scb;
662:
1.3 mycroft 663: s = splbio();
1.40 bouyer 664: if ((scb = TAILQ_FIRST(&sea->free_list)) != NULL)
665: TAILQ_REMOVE(&sea->free_list, scb, chain);
666: splx(s);
1.1 mycroft 667:
1.40 bouyer 668: return (scb);
1.1 mycroft 669: }
670:
671: /*
672: * Try to send this command to the board. Because this board does not use any
673: * mailboxes, this routine simply adds the command to the queue held by the
674: * sea_softc structure.
675: * A check is done to see if the command contains a REQUEST_SENSE command, and
676: * if so the command is put first in the queue, otherwise the command is added
677: * to the end of the queue. ?? Not correct ??
678: */
679: void
1.65.6.1! skrll 680: sea_send_scb(struct sea_softc *sea, struct sea_scb *scb)
1.1 mycroft 681: {
682:
1.3 mycroft 683: TAILQ_INSERT_TAIL(&sea->ready_list, scb, chain);
684: /* Try to do some work on the card. */
1.1 mycroft 685: if (!main_running)
686: sea_main();
687: }
688:
689: /*
690: * Coroutine that runs as long as more work can be done on the seagate host
691: * adapter in a system. Both sea_scsi_cmd and sea_intr will try to start it in
692: * case it is not running.
693: */
1.40 bouyer 694:
1.1 mycroft 695: void
1.65.6.1! skrll 696: sea_main(void)
1.1 mycroft 697: {
698: struct sea_softc *sea;
699: struct sea_scb *scb;
700: int done;
701: int unit;
702: int s;
703:
704: main_running = 1;
705:
706: /*
707: * This should not be run with interrupts disabled, but use the splx
708: * code instead.
709: */
710: loop:
711: done = 1;
1.14 thorpej 712: for (unit = 0; unit < sea_cd.cd_ndevs; unit++) {
1.65 tsutsui 713: sea = device_lookup_private(&sea_cd, unit);
1.1 mycroft 714: if (!sea)
715: continue;
716: s = splbio();
1.3 mycroft 717: if (!sea->nexus) {
1.1 mycroft 718: /*
1.3 mycroft 719: * Search through the ready_list for a command
1.1 mycroft 720: * destined for a target that's not busy.
721: */
1.3 mycroft 722: for (scb = sea->ready_list.tqh_first; scb;
1.1 mycroft 723: scb = scb->chain.tqe_next) {
1.40 bouyer 724: if (!(sea->busy[scb->xs->xs_periph->periph_target] &
725: (1 << scb->xs->xs_periph->periph_lun))) {
1.3 mycroft 726: TAILQ_REMOVE(&sea->ready_list, scb,
1.1 mycroft 727: chain);
1.57 perry 728:
1.1 mycroft 729: /* Re-enable interrupts. */
730: splx(s);
731:
732: /*
733: * Attempt to establish an I_T_L nexus.
1.3 mycroft 734: * On success, sea->nexus is set.
1.1 mycroft 735: * On failure, we must add the command
736: * back to the issue queue so we can
737: * keep trying.
738: */
739:
740: /*
741: * REQUEST_SENSE commands are issued
742: * without tagged queueing, even on
743: * SCSI-II devices because the
744: * contingent alligence condition
745: * exists for the entire unit.
746: */
747:
748: /*
749: * First check that if any device has
750: * tried a reconnect while we have done
751: * other things with interrupts
752: * disabled.
753: */
754:
755: if ((STATUS & (STAT_SEL | STAT_IO)) ==
756: (STAT_SEL | STAT_IO)) {
757: sea_reselect(sea);
758: break;
759: }
760: if (sea_select(sea, scb)) {
761: s = splbio();
1.3 mycroft 762: TAILQ_INSERT_HEAD(&sea->ready_list,
1.1 mycroft 763: scb, chain);
764: splx(s);
765: } else
766: break;
767: } /* if target/lun is not busy */
768: } /* for scb */
1.3 mycroft 769: if (!sea->nexus) {
770: /* check for reselection phase */
771: if ((STATUS & (STAT_SEL | STAT_IO)) ==
772: (STAT_SEL | STAT_IO)) {
773: sea_reselect(sea);
774: }
775: }
776: } /* if (!sea->nexus) */
1.57 perry 777:
1.1 mycroft 778: splx(s);
1.3 mycroft 779: if (sea->nexus) { /* we are connected. Do the task */
1.1 mycroft 780: sea_information_transfer(sea);
781: done = 0;
782: } else
783: break;
784: } /* for instance */
785:
786: if (!done)
787: goto loop;
788:
789: main_running = 0;
790: }
791:
1.40 bouyer 792: /*
793: * Allocate an scb and add it to the free list.
794: * We are called at splbio.
795: */
796: void
1.65.6.1! skrll 797: sea_grow_scb(struct sea_softc *sea)
1.40 bouyer 798: {
799: struct sea_scb *scb;
800:
801: if (sea->numscbs == SEA_SCB_MAX) {
802: sea->sc_channel.chan_flags &= ~SCSIPI_CHAN_CANGROW;
803: return;
804: }
805:
1.46 tsutsui 806: scb = malloc(sizeof(struct sea_scb), M_DEVBUF, M_NOWAIT|M_ZERO);
1.40 bouyer 807: if (scb == NULL)
808: return;
809:
810: TAILQ_INSERT_TAIL(&sea->free_list, scb, chain);
811: sea->numscbs++;
812: sea->sc_adapter.adapt_openings++;
813: }
1.1 mycroft 814: void
1.61 christos 815: sea_free_scb(struct sea_softc *sea, struct sea_scb *scb, int flags)
1.1 mycroft 816: {
817: int s;
818:
1.3 mycroft 819: s = splbio();
1.1 mycroft 820: scb->flags = SCB_FREE;
1.3 mycroft 821: TAILQ_INSERT_HEAD(&sea->free_list, scb, chain);
822: splx(s);
1.1 mycroft 823: }
824:
825: void
1.65.6.1! skrll 826: sea_timeout(void *arg)
1.1 mycroft 827: {
828: struct sea_scb *scb = arg;
1.23 bouyer 829: struct scsipi_xfer *xs = scb->xs;
1.40 bouyer 830: struct scsipi_periph *periph = xs->xs_periph;
831: struct sea_softc *sea =
832: (void *)periph->periph_channel->chan_adapter->adapt_dev;
1.3 mycroft 833: int s;
1.1 mycroft 834:
1.40 bouyer 835: scsipi_printaddr(periph);
1.21 christos 836: printf("timed out");
1.1 mycroft 837:
1.3 mycroft 838: s = splbio();
839:
1.1 mycroft 840: /*
841: * If it has been through before, then
842: * a previous abort has failed, don't
843: * try abort again
844: */
845: if (scb->flags & SCB_ABORTED) {
1.3 mycroft 846: /* abort timed out */
1.21 christos 847: printf(" AGAIN\n");
1.40 bouyer 848: scb->xs->xs_retries = 0;
1.1 mycroft 849: scb->flags |= SCB_ABORTED;
850: sea_done(sea, scb);
851: } else {
1.3 mycroft 852: /* abort the operation that has timed out */
1.21 christos 853: printf("\n");
1.3 mycroft 854: scb->flags |= SCB_ABORTED;
1.1 mycroft 855: sea_abort(sea, scb);
1.3 mycroft 856: /* 2 secs for the abort */
1.34 thorpej 857: if ((xs->xs_control & XS_CTL_POLL) == 0)
1.35 thorpej 858: callout_reset(&scb->xs->xs_callout, 2 * hz,
859: sea_timeout, scb);
1.1 mycroft 860: }
1.3 mycroft 861:
1.1 mycroft 862: splx(s);
863: }
1.57 perry 864:
1.1 mycroft 865: void
1.65.6.1! skrll 866: sea_reselect(struct sea_softc *sea)
1.1 mycroft 867: {
868: u_char target_mask;
869: int i;
870: u_char lun, phase;
871: u_char msg[3];
1.3 mycroft 872: int len;
1.1 mycroft 873: u_char *data;
874: struct sea_scb *scb;
875: int abort = 0;
1.57 perry 876:
1.1 mycroft 877: if (!((target_mask = STATUS) & STAT_SEL)) {
1.64 cegger 878: printf("%s: wrong state 0x%x\n", device_xname(&sea->sc_dev),
1.1 mycroft 879: target_mask);
880: return;
881: }
882:
883: /* wait for a device to win the reselection phase */
884: /* signals this by asserting the I/O signal */
885: for (i = 10; i && (STATUS & (STAT_SEL | STAT_IO | STAT_BSY)) !=
886: (STAT_SEL | STAT_IO | 0); i--);
887: /* !! Check for timeout here */
888: /* the data bus contains original initiator id ORed with target id */
889: target_mask = DATA;
890: /* see that we really are the initiator */
891: if (!(target_mask & sea->our_id_mask)) {
1.21 christos 892: printf("%s: polled reselection was not for me: 0x%x\n",
1.64 cegger 893: device_xname(&sea->sc_dev), target_mask);
1.1 mycroft 894: return;
895: }
896: /* find target who won */
897: target_mask &= ~sea->our_id_mask;
898: /* host responds by asserting the BSY signal */
899: CONTROL = BASE_CMD | CMD_DRVR_ENABLE | CMD_BSY;
900: /* target should respond by deasserting the SEL signal */
901: for (i = 50000; i && (STATUS & STAT_SEL); i++);
902: /* remove the busy status */
903: CONTROL = BASE_CMD | CMD_DRVR_ENABLE;
904: /* we are connected. Now we wait for the MSGIN condition */
905: for (i = 50000; i && !(STATUS & STAT_REQ); i--);
906: /* !! Add timeout check here */
907: /* hope we get an IDENTIFY message */
908: len = 3;
909: data = msg;
1.3 mycroft 910: phase = PH_MSGIN;
1.57 perry 911: sea_transfer_pio(sea, &phase, &len, &data);
1.1 mycroft 912:
1.39 bouyer 913: if (!MSG_ISIDENTIFY(msg[0])) {
1.21 christos 914: printf("%s: expecting IDENTIFY message, got 0x%x\n",
1.64 cegger 915: device_xname(&sea->sc_dev), msg[0]);
1.1 mycroft 916: abort = 1;
1.16 christos 917: scb = NULL;
1.1 mycroft 918: } else {
919: lun = msg[0] & 0x07;
920:
921: /*
922: * Find the command corresponding to the I_T_L or I_T_L_Q nexus
923: * we just reestablished, and remove it from the disconnected
924: * queue.
925: */
1.3 mycroft 926: for (scb = sea->nexus_list.tqh_first; scb;
1.1 mycroft 927: scb = scb->chain.tqe_next)
1.40 bouyer 928: if (target_mask == (1 << scb->xs->xs_periph->periph_target) &&
929: lun == scb->xs->xs_periph->periph_lun) {
1.3 mycroft 930: TAILQ_REMOVE(&sea->nexus_list, scb,
1.1 mycroft 931: chain);
932: break;
933: }
934: if (!scb) {
1.21 christos 935: printf("%s: target %02x lun %d not disconnected\n",
1.64 cegger 936: device_xname(&sea->sc_dev), target_mask, lun);
1.1 mycroft 937: /*
938: * Since we have an established nexus that we can't do
939: * anything with, we must abort it.
940: */
941: abort = 1;
942: }
943: }
944:
945: if (abort) {
946: msg[0] = MSG_ABORT;
947: len = 1;
948: data = msg;
1.3 mycroft 949: phase = PH_MSGOUT;
1.1 mycroft 950: CONTROL = BASE_CMD | CMD_ATTN;
951: sea_transfer_pio(sea, &phase, &len, &data);
952: } else
1.3 mycroft 953: sea->nexus = scb;
1.1 mycroft 954:
955: return;
956: }
957:
958: /*
959: * Transfer data in given phase using polled I/O.
960: */
961: int
1.65.6.1! skrll 962: sea_transfer_pio(struct sea_softc *sea, u_char *phase, int *count, u_char **data)
1.1 mycroft 963: {
1.36 augustss 964: u_char p = *phase, tmp;
965: int c = *count;
966: u_char *d = *data;
1.1 mycroft 967: int timeout;
968:
969: do {
970: /*
971: * Wait for assertion of REQ, after which the phase bits will
972: * be valid.
973: */
1.3 mycroft 974: for (timeout = 0; timeout < 50000; timeout++)
1.1 mycroft 975: if ((tmp = STATUS) & STAT_REQ)
976: break;
977: if (!(tmp & STAT_REQ)) {
1.21 christos 978: printf("%s: timeout waiting for STAT_REQ\n",
1.64 cegger 979: device_xname(&sea->sc_dev));
1.1 mycroft 980: break;
981: }
982:
983: /*
984: * Check for phase mismatch. Reached if the target decides
985: * that it has finished the transfer.
986: */
1.3 mycroft 987: if (sea->type == FDOMAIN840)
988: tmp = ((tmp & 0x08) >> 2) |
989: ((tmp & 0x02) << 2) |
990: (tmp & 0xf5);
991: if ((tmp & PH_MASK) != p)
1.1 mycroft 992: break;
993:
994: /* Do actual transfer from SCSI bus to/from memory. */
995: if (!(p & STAT_IO))
996: DATA = *d;
997: else
998: *d = DATA;
999: ++d;
1000:
1001: /*
1002: * The SCSI standard suggests that in MSGOUT phase, the
1003: * initiator should drop ATN on the last byte of the message
1004: * phase after REQ has been asserted for the handshake but
1005: * before the initiator raises ACK.
1006: * Don't know how to accomplish this on the ST01/02.
1007: */
1008:
1009: #if 0
1010: /*
1011: * XXX
1012: * The st01 code doesn't wait for STAT_REQ to be deasserted.
1013: * Is this ok?
1014: */
1015: for (timeout = 0; timeout < 200000L; timeout++)
1016: if (!(STATUS & STAT_REQ))
1017: break;
1018: if (STATUS & STAT_REQ)
1.21 christos 1019: printf("%s: timeout on wait for !STAT_REQ",
1.64 cegger 1020: device_xname(&sea->sc_dev));
1.1 mycroft 1021: #endif
1022: } while (--c);
1023:
1024: *count = c;
1025: *data = d;
1026: tmp = STATUS;
1027: if (tmp & STAT_REQ)
1.3 mycroft 1028: *phase = tmp & PH_MASK;
1.1 mycroft 1029: else
1.3 mycroft 1030: *phase = PH_INVALID;
1.1 mycroft 1031:
1032: if (c && (*phase != p))
1033: return -1;
1034: return 0;
1035: }
1036:
1037: /*
1038: * Establish I_T_L or I_T_L_Q nexus for new or existing command including
1039: * ARBITRATION, SELECTION, and initial message out for IDENTIFY and queue
1040: * messages. Return -1 if selection could not execute for some reason, 0 if
1041: * selection succeded or failed because the target did not respond.
1042: */
1043: int
1.65.6.1! skrll 1044: sea_select(struct sea_softc *sea, struct sea_scb *scb)
1.1 mycroft 1045: {
1046: u_char msg[3], phase;
1047: u_char *data;
1.3 mycroft 1048: int len;
1.1 mycroft 1049: int timeout;
1050:
1051: CONTROL = BASE_CMD;
1052: DATA = sea->our_id_mask;
1053: CONTROL = (BASE_CMD & ~CMD_INTR) | CMD_START_ARB;
1054:
1055: /* wait for arbitration to complete */
1056: for (timeout = 0; timeout < 3000000L; timeout++)
1057: if (STATUS & STAT_ARB_CMPL)
1058: break;
1059: if (!(STATUS & STAT_ARB_CMPL)) {
1060: if (STATUS & STAT_SEL) {
1.64 cegger 1061: printf("%s: arbitration lost\n", device_xname(&sea->sc_dev));
1.1 mycroft 1062: scb->flags |= SCB_ERROR;
1063: } else {
1.21 christos 1064: printf("%s: arbitration timeout\n",
1.64 cegger 1065: device_xname(&sea->sc_dev));
1.1 mycroft 1066: scb->flags |= SCB_TIMEOUT;
1067: }
1068: CONTROL = BASE_CMD;
1069: return -1;
1070: }
1071:
1072: delay(2);
1.40 bouyer 1073: DATA = (u_char)((1 << scb->xs->xs_periph->periph_target) |
1.23 bouyer 1074: sea->our_id_mask);
1.1 mycroft 1075: CONTROL =
1076: #ifdef SEA_NOMSGS
1077: (BASE_CMD & ~CMD_INTR) | CMD_DRVR_ENABLE | CMD_SEL;
1078: #else
1079: (BASE_CMD & ~CMD_INTR) | CMD_DRVR_ENABLE | CMD_SEL | CMD_ATTN;
1080: #endif
1.57 perry 1081: delay(1);
1.1 mycroft 1082:
1083: /* wait for a bsy from target */
1084: for (timeout = 0; timeout < 2000000L; timeout++)
1085: if (STATUS & STAT_BSY)
1086: break;
1087: if (!(STATUS & STAT_BSY)) {
1088: /* should return some error to the higher level driver */
1089: CONTROL = BASE_CMD;
1090: scb->flags |= SCB_TIMEOUT;
1091: return 0;
1092: }
1093:
1094: /* Try to make the target to take a message from us */
1095: #ifdef SEA_NOMSGS
1096: CONTROL = (BASE_CMD & ~CMD_INTR) | CMD_DRVR_ENABLE;
1097: #else
1098: CONTROL = (BASE_CMD & ~CMD_INTR) | CMD_DRVR_ENABLE | CMD_ATTN;
1099: #endif
1100: delay(1);
1.57 perry 1101:
1.1 mycroft 1102: /* should start a msg_out phase */
1103: for (timeout = 0; timeout < 2000000L; timeout++)
1104: if (STATUS & STAT_REQ)
1105: break;
1.3 mycroft 1106: /* Remove ATN. */
1.1 mycroft 1107: CONTROL = BASE_CMD | CMD_DRVR_ENABLE;
1108: if (!(STATUS & STAT_REQ)) {
1109: /*
1110: * This should not be taken as an error, but more like an
1111: * unsupported feature! Should set a flag indicating that the
1112: * target don't support messages, and continue without failure.
1113: * (THIS IS NOT AN ERROR!)
1114: */
1115: } else {
1.40 bouyer 1116: msg[0] = MSG_IDENTIFY(scb->xs->xs_periph->periph_lun, 1);
1.1 mycroft 1117: len = 1;
1118: data = msg;
1.3 mycroft 1119: phase = PH_MSGOUT;
1.1 mycroft 1120: /* Should do test on result of sea_transfer_pio(). */
1121: sea_transfer_pio(sea, &phase, &len, &data);
1122: }
1123: if (!(STATUS & STAT_BSY))
1.21 christos 1124: printf("%s: after successful arbitrate: no STAT_BSY!\n",
1.64 cegger 1125: device_xname(&sea->sc_dev));
1.57 perry 1126:
1.3 mycroft 1127: sea->nexus = scb;
1.40 bouyer 1128: sea->busy[scb->xs->xs_periph->periph_target] |=
1129: 1 << scb->xs->xs_periph->periph_lun;
1.1 mycroft 1130: /* This assignment should depend on possibility to send a message to target. */
1131: CONTROL = BASE_CMD | CMD_DRVR_ENABLE;
1132: /* XXX Reset pointer in command? */
1133: return 0;
1134: }
1135:
1136: /*
1137: * Send an abort to the target. Return 1 success, 0 on failure.
1138: */
1139: int
1.65.6.1! skrll 1140: sea_abort(struct sea_softc *sea, struct sea_scb *scb)
1.1 mycroft 1141: {
1142: struct sea_scb *tmp;
1143: u_char msg, phase, *msgptr;
1.3 mycroft 1144: int len;
1.1 mycroft 1145:
1146: /*
1147: * If the command hasn't been issued yet, we simply remove it from the
1148: * issue queue
1149: * XXX Could avoid this loop.
1150: */
1.3 mycroft 1151: for (tmp = sea->ready_list.tqh_first; tmp; tmp = tmp->chain.tqe_next)
1.1 mycroft 1152: if (scb == tmp) {
1.3 mycroft 1153: TAILQ_REMOVE(&sea->ready_list, scb, chain);
1.1 mycroft 1154: /* XXX Set some type of error result for operation. */
1155: return 1;
1156: }
1157:
1158: /*
1159: * If any commands are connected, we're going to fail the abort and let
1160: * the high level SCSI driver retry at a later time or issue a reset.
1161: */
1.3 mycroft 1162: if (sea->nexus)
1.1 mycroft 1163: return 0;
1164:
1165: /*
1166: * If the command is currently disconnected from the bus, and there are
1167: * no connected commands, we reconnect the I_T_L or I_T_L_Q nexus
1168: * associated with it, go into message out, and send an abort message.
1169: */
1.3 mycroft 1170: for (tmp = sea->nexus_list.tqh_first; tmp;
1.1 mycroft 1171: tmp = tmp->chain.tqe_next)
1172: if (scb == tmp) {
1173: if (sea_select(sea, scb))
1174: return 0;
1175:
1176: msg = MSG_ABORT;
1177: msgptr = &msg;
1178: len = 1;
1.3 mycroft 1179: phase = PH_MSGOUT;
1.1 mycroft 1180: CONTROL = BASE_CMD | CMD_ATTN;
1181: sea_transfer_pio(sea, &phase, &len, &msgptr);
1182:
1.3 mycroft 1183: for (tmp = sea->nexus_list.tqh_first; tmp;
1.1 mycroft 1184: tmp = tmp->chain.tqe_next)
1185: if (scb == tmp) {
1.3 mycroft 1186: TAILQ_REMOVE(&sea->nexus_list,
1.1 mycroft 1187: scb, chain);
1188: /* XXX Set some type of error result
1189: for the operation. */
1190: return 1;
1191: }
1192: }
1193:
1194: /* Command not found in any queue; race condition? */
1195: return 1;
1196: }
1197:
1198: void
1.65.6.1! skrll 1199: sea_done(struct sea_softc *sea, struct sea_scb *scb)
1.1 mycroft 1200: {
1.23 bouyer 1201: struct scsipi_xfer *xs = scb->xs;
1.1 mycroft 1202:
1.35 thorpej 1203: callout_stop(&scb->xs->xs_callout);
1.1 mycroft 1204:
1205: xs->resid = scb->datalen;
1206:
1.3 mycroft 1207: /* XXXX need to get status */
1208: if (scb->flags == SCB_ACTIVE) {
1.1 mycroft 1209: xs->resid = 0;
1210: } else {
1.3 mycroft 1211: if (scb->flags & (SCB_TIMEOUT | SCB_ABORTED))
1212: xs->error = XS_TIMEOUT;
1213: if (scb->flags & SCB_ERROR)
1.1 mycroft 1214: xs->error = XS_DRIVER_STUFFUP;
1215: }
1.34 thorpej 1216: sea_free_scb(sea, scb, xs->xs_control);
1.23 bouyer 1217: scsipi_done(xs);
1.1 mycroft 1218: }
1219:
1220: /*
1221: * Wait for completion of command in polled mode.
1222: */
1223: int
1.61 christos 1224: sea_poll(struct sea_softc *sea, struct scsipi_xfer *xs, int count)
1.1 mycroft 1225: {
1226: int s;
1227:
1228: while (count) {
1229: /* try to do something */
1230: s = splbio();
1231: if (!main_running)
1232: sea_main();
1233: splx(s);
1.34 thorpej 1234: if (xs->xs_status & XS_STS_DONE)
1.3 mycroft 1235: return 0;
1236: delay(1000);
1.1 mycroft 1237: count--;
1238: }
1.3 mycroft 1239: return 1;
1.1 mycroft 1240: }
1241:
1242: /*
1243: * Do the transfer. We know we are connected. Update the flags, and call
1244: * sea_done() when task accomplished. Dialog controlled by the target.
1245: */
1246: void
1.65.6.1! skrll 1247: sea_information_transfer(struct sea_softc *sea)
1.1 mycroft 1248: {
1249: int timeout;
1.3 mycroft 1250: u_char msgout = MSG_NOOP;
1251: int len;
1.1 mycroft 1252: int s;
1253: u_char *data;
1.3 mycroft 1254: u_char phase, tmp, old_phase = PH_INVALID;
1255: struct sea_scb *scb = sea->nexus;
1.1 mycroft 1256: int loop;
1257:
1258: for (timeout = 0; timeout < 10000000L; timeout++) {
1259: tmp = STATUS;
1.3 mycroft 1260: if (tmp & STAT_PARITY)
1.21 christos 1261: printf("%s: parity error detected\n",
1.64 cegger 1262: device_xname(&sea->sc_dev));
1.1 mycroft 1263: if (!(tmp & STAT_BSY)) {
1264: for (loop = 0; loop < 20; loop++)
1265: if ((tmp = STATUS) & STAT_BSY)
1266: break;
1267: if (!(tmp & STAT_BSY)) {
1.21 christos 1268: printf("%s: !STAT_BSY unit in data transfer!\n",
1.64 cegger 1269: device_xname(&sea->sc_dev));
1.1 mycroft 1270: s = splbio();
1.3 mycroft 1271: sea->nexus = NULL;
1.1 mycroft 1272: scb->flags = SCB_ERROR;
1273: splx(s);
1274: sea_done(sea, scb);
1275: return;
1276: }
1277: }
1278:
1279: /* we only have a valid SCSI phase when REQ is asserted */
1280: if (!(tmp & STAT_REQ))
1281: continue;
1282:
1.3 mycroft 1283: if (sea->type == FDOMAIN840)
1284: tmp = ((tmp & 0x08) >> 2) |
1285: ((tmp & 0x02) << 2) |
1286: (tmp & 0xf5);
1287: phase = tmp & PH_MASK;
1.1 mycroft 1288: if (phase != old_phase)
1289: old_phase = phase;
1290:
1291: switch (phase) {
1.3 mycroft 1292: case PH_DATAOUT:
1.1 mycroft 1293: #ifdef SEA_NODATAOUT
1.21 christos 1294: printf("%s: SEA_NODATAOUT set, attempted DATAOUT aborted\n",
1.64 cegger 1295: device_xname(&sea->sc_dev));
1.1 mycroft 1296: msgout = MSG_ABORT;
1297: CONTROL = BASE_CMD | CMD_ATTN;
1298: break;
1299: #endif
1.3 mycroft 1300: case PH_DATAIN:
1.1 mycroft 1301: if (!scb->data)
1.21 christos 1302: printf("no data address!\n");
1.1 mycroft 1303: #ifdef SEA_BLINDTRANSFER
1304: if (scb->datalen && !(scb->datalen % BLOCK_SIZE)) {
1305: while (scb->datalen) {
1.3 mycroft 1306: for (loop = 0; loop < 50000; loop++)
1.1 mycroft 1307: if ((tmp = STATUS) & STAT_REQ)
1308: break;
1309: if (!(tmp & STAT_REQ)) {
1.21 christos 1310: printf("%s: timeout waiting for STAT_REQ\n",
1.64 cegger 1311: device_xname(&sea->sc_dev));
1.1 mycroft 1312: /* XXX Do something? */
1313: }
1.3 mycroft 1314: if (sea->type == FDOMAIN840)
1315: tmp = ((tmp & 0x08) >> 2) |
1316: ((tmp & 0x02) << 2) |
1317: (tmp & 0xf5);
1318: if ((tmp & PH_MASK) != phase)
1.1 mycroft 1319: break;
1320: if (!(phase & STAT_IO)) {
1321: #ifdef SEA_ASSEMBLER
1.62 christos 1322: void *junk;
1.53 perry 1323: __asm("cld\n\t\
1.1 mycroft 1324: rep\n\t\
1325: movsl" :
1.37 mycroft 1326: "=S" (scb->data),
1327: "=c" (len),
1328: "=D" (junk) :
1.1 mycroft 1329: "0" (scb->data),
1.37 mycroft 1330: "1" (BLOCK_SIZE >> 2),
1331: "2" (sea->maddr_dr));
1.1 mycroft 1332: #else
1.37 mycroft 1333: for (len = BLOCK_SIZE;
1334: len; len--)
1.1 mycroft 1335: DATA = *(scb->data++);
1336: #endif
1337: } else {
1338: #ifdef SEA_ASSEMBLER
1.62 christos 1339: void *junk;
1.53 perry 1340: __asm("cld\n\t\
1.1 mycroft 1341: rep\n\t\
1342: movsl" :
1.37 mycroft 1343: "=D" (scb->data),
1344: "=c" (len),
1345: "=S" (junk) :
1.1 mycroft 1346: "0" (scb->data),
1.37 mycroft 1347: "1" (BLOCK_SIZE >> 2),
1348: "2" (sea->maddr_dr));
1.1 mycroft 1349: #else
1.37 mycroft 1350: for (len = BLOCK_SIZE;
1351: len; len--)
1.1 mycroft 1352: *(scb->data++) = DATA;
1353: #endif
1354: }
1355: scb->datalen -= BLOCK_SIZE;
1356: }
1357: }
1.57 perry 1358: #endif
1.1 mycroft 1359: if (scb->datalen)
1360: sea_transfer_pio(sea, &phase, &scb->datalen,
1361: &scb->data);
1362: break;
1.3 mycroft 1363: case PH_MSGIN:
1.1 mycroft 1364: /* Multibyte messages should not be present here. */
1365: len = 1;
1366: data = &tmp;
1367: sea_transfer_pio(sea, &phase, &len, &data);
1368: /* scb->MessageIn = tmp; */
1369:
1370: switch (tmp) {
1371: case MSG_ABORT:
1372: scb->flags = SCB_ABORTED;
1.21 christos 1373: printf("sea: command aborted by target\n");
1.1 mycroft 1374: CONTROL = BASE_CMD;
1375: sea_done(sea, scb);
1376: return;
1.3 mycroft 1377: case MSG_CMDCOMPLETE:
1.1 mycroft 1378: s = splbio();
1.3 mycroft 1379: sea->nexus = NULL;
1.1 mycroft 1380: splx(s);
1.57 perry 1381: sea->busy[scb->xs->xs_periph->periph_target] &=
1.40 bouyer 1382: ~(1 << scb->xs->xs_periph->periph_lun);
1.1 mycroft 1383: CONTROL = BASE_CMD;
1384: sea_done(sea, scb);
1385: return;
1386: case MSG_MESSAGE_REJECT:
1.41 wiz 1387: printf("%s: message_reject received\n",
1.64 cegger 1388: device_xname(&sea->sc_dev));
1.1 mycroft 1389: break;
1390: case MSG_DISCONNECT:
1391: s = splbio();
1.3 mycroft 1392: TAILQ_INSERT_TAIL(&sea->nexus_list,
1.1 mycroft 1393: scb, chain);
1.3 mycroft 1394: sea->nexus = NULL;
1.1 mycroft 1395: CONTROL = BASE_CMD;
1396: splx(s);
1397: return;
1.3 mycroft 1398: case MSG_SAVEDATAPOINTER:
1399: case MSG_RESTOREPOINTERS:
1.1 mycroft 1400: /* save/restore of pointers are ignored */
1401: break;
1402: default:
1403: /*
1404: * This should be handled in the pio data
1405: * transfer phase, as the ATN should be raised
1406: * before ACK goes false when rejecting a
1407: * message.
1408: */
1.21 christos 1409: printf("%s: unknown message in: %x\n",
1.64 cegger 1410: device_xname(&sea->sc_dev), tmp);
1.1 mycroft 1411: break;
1412: } /* switch (tmp) */
1413: break;
1.3 mycroft 1414: case PH_MSGOUT:
1.1 mycroft 1415: len = 1;
1416: data = &msgout;
1417: /* sea->last_message = msgout; */
1418: sea_transfer_pio(sea, &phase, &len, &data);
1419: if (msgout == MSG_ABORT) {
1.21 christos 1420: printf("%s: sent message abort to target\n",
1.64 cegger 1421: device_xname(&sea->sc_dev));
1.1 mycroft 1422: s = splbio();
1.57 perry 1423: sea->busy[scb->xs->xs_periph->periph_target] &=
1.40 bouyer 1424: ~(1 << scb->xs->xs_periph->periph_lun);
1.3 mycroft 1425: sea->nexus = NULL;
1.1 mycroft 1426: scb->flags = SCB_ABORTED;
1.57 perry 1427: splx(s);
1.1 mycroft 1428: /* enable interrupt from scsi */
1429: sea_done(sea, scb);
1430: return;
1431: }
1.3 mycroft 1432: msgout = MSG_NOOP;
1.1 mycroft 1433: break;
1.3 mycroft 1434: case PH_CMD:
1435: len = scb->xs->cmdlen;
1436: data = (char *) scb->xs->cmd;
1.1 mycroft 1437: sea_transfer_pio(sea, &phase, &len, &data);
1438: break;
1.3 mycroft 1439: case PH_STAT:
1.1 mycroft 1440: len = 1;
1441: data = &tmp;
1442: sea_transfer_pio(sea, &phase, &len, &data);
1.3 mycroft 1443: scb->xs->status = tmp;
1.1 mycroft 1444: break;
1445: default:
1.21 christos 1446: printf("sea: unknown phase\n");
1.1 mycroft 1447: } /* switch (phase) */
1448: } /* for (...) */
1449:
1450: /* If we get here we have got a timeout! */
1.64 cegger 1451: printf("%s: timeout in data transfer\n", device_xname(&sea->sc_dev));
1.1 mycroft 1452: scb->flags = SCB_TIMEOUT;
1453: /* XXX Should I clear scsi-bus state? */
1454: sea_done(sea, scb);
1455: }
CVSweb <webmaster@jp.NetBSD.org>