Annotation of src/sys/arch/mac68k/dev/ncr5380.c, Revision 1.38.10.1
1.38.10.1! thorpej 1: /* $NetBSD: ncr5380.c,v 1.39 1997/08/27 11:23:50 bouyer Exp $ */
1.1 briggs 2:
3: /*
4: * Copyright (c) 1995 Leo Weppelman.
5: * All rights reserved.
6: *
7: * Redistribution and use in source and binary forms, with or without
8: * modification, are permitted provided that the following conditions
9: * are met:
10: * 1. Redistributions of source code must retain the above copyright
11: * notice, this list of conditions and the following disclaimer.
12: * 2. Redistributions in binary form must reproduce the above copyright
13: * notice, this list of conditions and the following disclaimer in the
14: * documentation and/or other materials provided with the distribution.
15: * 3. All advertising materials mentioning features or use of this software
16: * must display the following acknowledgement:
17: * This product includes software developed by Leo Weppelman.
18: * 4. The name of the author may not be used to endorse or promote products
19: * derived from this software without specific prior written permission
20: *
21: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31: */
32:
33: /*
34: * Bit mask of targets you want debugging to be shown
35: */
36: u_char dbg_target_mask = 0x7f;
37:
38: /*
39: * Set bit for target when parity checking must be disabled.
40: * My (LWP) Maxtor 7245S seems to generate parity errors on about 50%
41: * of all transfers while the data is correct!?
42: */
43: u_char ncr5380_no_parchk = 0xff;
44:
1.14 briggs 45: #ifdef AUTO_SENSE
46:
47: /*
48: * Bit masks of targets that accept linked commands, and those
1.21 briggs 49: * that we've already checked out. Some devices will report
50: * that they support linked commands when they have problems with
51: * them. By default, don't try them on any devices. Allow an
52: * option to override.
1.14 briggs 53: */
54: u_char ncr_will_link = 0x00;
1.21 briggs 55: #ifdef TRY_SCSI_LINKED_COMMANDS
56: u_char ncr_test_link = ((~TRY_SCSI_LINKED_COMMANDS) & 0x7f);
57: #else
58: u_char ncr_test_link = 0x7f;
59: #endif
1.14 briggs 60:
61: #endif /* AUTO_SENSE */
62:
1.1 briggs 63: /*
64: * This is the default sense-command we send.
65: */
66: static u_char sense_cmd[] = {
1.38.10.1! thorpej 67: REQUEST_SENSE, 0, 0, 0, sizeof(struct scsipi_sense_data), 0
1.1 briggs 68: };
69:
70: /*
71: * True if the main co-routine is running
72: */
73: static volatile int main_running = 0;
74:
75: /*
76: * Mask of targets selected
77: */
78: static u_char busy;
79:
1.28 briggs 80: static void ncr5380_minphys __P((struct buf *bp));
1.38.10.1! thorpej 81: static int ncr5380_scsi_cmd __P((struct scsipi_xfer *xs));
! 82: static void ncr5380_show_scsi_cmd __P((struct scsipi_xfer *xs));
1.1 briggs 83:
1.38.10.1! thorpej 84: struct scsipi_adapter ncr5380_switch = {
1.1 briggs 85: ncr5380_scsi_cmd, /* scsi_cmd() */
86: ncr5380_minphys, /* scsi_minphys() */
87: 0, /* open_target_lu() */
88: 0 /* close_target_lu() */
89: };
90:
1.38.10.1! thorpej 91: struct scsipi_device ncr5380_dev = {
1.1 briggs 92: NULL, /* use default error handler */
93: NULL, /* do not have a start functio */
94: NULL, /* have no async handler */
95: NULL /* Use default done routine */
96: };
97:
98:
99: static SC_REQ req_queue[NREQ];
100: static SC_REQ *free_head = NULL; /* Free request structures */
101:
102:
103: /*
104: * Inline functions:
105: */
106:
107: /*
108: * Determine the size of a SCSI command.
109: */
1.28 briggs 110: extern __inline__ int command_size(opcode)
111: u_char opcode;
1.1 briggs 112: {
113: switch ((opcode >> 4) & 0xf) {
114: case 0:
115: case 1:
116: return (6);
117: case 2:
118: case 3:
119: return (10);
120: }
121: return (12);
122: }
123:
124:
125: /*
126: * Wait for request-line to become active. When it doesn't return 0.
127: * Otherwise return != 0.
128: * The timeouts in the 'wait_req_*' functions are arbitrary and rather
129: * large. In 99% of the invocations nearly no timeout is needed but in
130: * some cases (especially when using my tapedrive, a Tandberg 3600) the
131: * device is busy internally and the first SCSI-phase will be delayed.
1.31 briggs 132: *
133: * -- A sleeping Fujitsu M2512 is even worse; try 2.5 sec -hf 20 Jun
1.1 briggs 134: */
135: extern __inline__ int wait_req_true(void)
136: {
1.30 briggs 137: int timeout = 2500000;
1.1 briggs 138:
139: while (!(GET_5380_REG(NCR5380_IDSTAT) & SC_S_REQ) && --timeout)
140: delay(1);
141: return (GET_5380_REG(NCR5380_IDSTAT) & SC_S_REQ);
142: }
143:
144: /*
145: * Wait for request-line to become inactive. When it doesn't return 0.
146: * Otherwise return != 0.
147: */
148: extern __inline__ int wait_req_false(void)
149: {
1.30 briggs 150: int timeout = 2500000;
1.1 briggs 151:
152: while ((GET_5380_REG(NCR5380_IDSTAT) & SC_S_REQ) && --timeout)
153: delay(1);
154: return (!(GET_5380_REG(NCR5380_IDSTAT) & SC_S_REQ));
155: }
156:
1.3 briggs 157: extern __inline__ void ack_message()
158: {
159: SET_5380_REG(NCR5380_ICOM, 0);
160: }
161:
1.9 briggs 162: extern __inline__ void nack_message(SC_REQ *reqp, u_char msg)
1.3 briggs 163: {
164: SET_5380_REG(NCR5380_ICOM, SC_A_ATN);
1.9 briggs 165: reqp->msgout = msg;
1.3 briggs 166: }
167:
1.1 briggs 168: extern __inline__ void finish_req(SC_REQ *reqp)
169: {
170: int sps;
1.38.10.1! thorpej 171: struct scsipi_xfer *xs = reqp->xs;
1.1 briggs 172:
173: #ifdef REAL_DMA
174: /*
175: * If we bounced, free the bounce buffer
176: */
177: if (reqp->dr_flag & DRIVER_BOUNCING)
178: free_bounceb(reqp->bounceb);
179: #endif /* REAL_DMA */
180: #ifdef DBG_REQ
181: if (dbg_target_mask & (1 << reqp->targ_id))
182: show_request(reqp, "DONE");
183: #endif
184: #ifdef DBG_ERR_RET
185: if (reqp->xs->error != 0)
186: show_request(reqp, "ERR_RET");
187: #endif
188: /*
189: * Return request to free-q
190: */
191: sps = splbio();
192: reqp->next = free_head;
193: free_head = reqp;
194: splx(sps);
195:
196: xs->flags |= ITSDONE;
1.14 briggs 197: if (!(reqp->dr_flag & DRIVER_LINKCHK))
1.38.10.1! thorpej 198: scsipi_done(xs);
1.1 briggs 199: }
200:
201: /*
202: * Auto config stuff....
203: */
204: void ncr_attach __P((struct device *, struct device *, void *));
1.37 scottr 205: int ncr_match __P((struct device *, struct cfdata *, void *));
1.1 briggs 206:
207: /*
208: * Tricks to make driver-name configurable
209: */
1.23 thorpej 210: #define CFNAME(n) __CONCAT(n,_cd)
211: #define CANAME(n) __CONCAT(n,_ca)
1.1 briggs 212: #define CFSTRING(n) __STRING(n)
213:
1.23 thorpej 214: struct cfattach CANAME(DRNAME) = {
215: sizeof(struct ncr_softc), ncr_match, ncr_attach
216: };
217:
1.1 briggs 218: struct cfdriver CFNAME(DRNAME) = {
1.24 scottr 219: NULL, CFSTRING(DRNAME), DV_DULL
1.23 thorpej 220: };
1.1 briggs 221:
222: int
1.37 scottr 223: ncr_match(parent, cf, aux)
224: struct device *parent;
225: struct cfdata *cf;
1.38 scottr 226: void *aux;
1.1 briggs 227: {
1.38 scottr 228: return (machine_match(parent, cf, aux, &CFNAME(DRNAME)));
1.1 briggs 229: }
230:
231: void
232: ncr_attach(pdp, dp, auxp)
233: struct device *pdp, *dp;
234: void *auxp;
235: {
236: struct ncr_softc *sc;
237: int i;
238:
239: sc = (struct ncr_softc *)dp;
240:
1.38.10.1! thorpej 241: sc->sc_link.scsipi_scsi.channel = SCSI_CHANNEL_ONLY_ONE;
1.1 briggs 242: sc->sc_link.adapter_softc = sc;
1.38.10.1! thorpej 243: sc->sc_link.scsipi_scsi.adapter_target = 7;
1.1 briggs 244: sc->sc_link.adapter = &ncr5380_switch;
245: sc->sc_link.device = &ncr5380_dev;
246: sc->sc_link.openings = NREQ - 1;
1.38.10.1! thorpej 247: sc->sc_link.scsipi_scsi.max_target = 7;
! 248: sc->sc_link.type = BUS_SCSI;
1.1 briggs 249:
250: /*
1.5 briggs 251: * bitmasks
252: */
253: sc->sc_noselatn = 0;
254: sc->sc_selected = 0;
255:
256: /*
1.1 briggs 257: * Initialize machine-type specific things...
258: */
259: scsi_mach_init(sc);
1.35 christos 260: printf("\n");
1.1 briggs 261:
262: /*
263: * Initialize request queue freelist.
264: */
265: for (i = 0; i < NREQ; i++) {
266: req_queue[i].next = free_head;
267: free_head = &req_queue[i];
268: }
269:
270: /*
271: * Initialize the host adapter
272: */
273: scsi_idisable();
274: ENABLE_NCR5380(sc);
275: SET_5380_REG(NCR5380_ICOM, 0);
276: SET_5380_REG(NCR5380_MODE, IMODE_BASE);
277: SET_5380_REG(NCR5380_TCOM, 0);
278: SET_5380_REG(NCR5380_IDSTAT, 0);
279: scsi_ienable();
280:
281: /*
282: * attach all scsi units on us
283: */
1.33 cgd 284: config_found(dp, &sc->sc_link, scsiprint);
1.1 briggs 285: }
286:
287: /*
288: * End of auto config stuff....
289: */
290:
291: /*
292: * Carry out a request from the high level driver.
293: */
294: static int
1.38.10.1! thorpej 295: ncr5380_scsi_cmd(struct scsipi_xfer *xs)
1.1 briggs 296: {
297: int sps;
1.14 briggs 298: SC_REQ *reqp, *link, *tmp;
1.1 briggs 299: int flags = xs->flags;
300:
301: /*
302: * We do not queue RESET commands
303: */
304: if (flags & SCSI_RESET) {
1.20 briggs 305: scsi_reset_verbose(xs->sc_link->adapter_softc,
306: "Got reset-command");
1.1 briggs 307: return (COMPLETE);
308: }
309:
310: /*
311: * Get a request block
312: */
313: sps = splbio();
314: if ((reqp = free_head) == 0) {
315: splx(sps);
316: return (TRY_AGAIN_LATER);
317: }
318: free_head = reqp->next;
319: reqp->next = NULL;
320: splx(sps);
321:
322: /*
323: * Initialize our private fields
324: */
325: reqp->dr_flag = (flags & SCSI_POLL) ? DRIVER_NOINT : 0;
326: reqp->phase = NR_PHASE;
327: reqp->msgout = MSG_NOOP;
328: reqp->status = SCSGOOD;
1.19 briggs 329: reqp->message = 0xff;
1.1 briggs 330: reqp->link = NULL;
331: reqp->xs = xs;
1.38.10.1! thorpej 332: reqp->targ_id = xs->sc_link->scsipi_scsi.target;
! 333: reqp->targ_lun = xs->sc_link->scsipi_scsi.lun;
1.1 briggs 334: reqp->xdata_ptr = (u_char*)xs->data;
335: reqp->xdata_len = xs->datalen;
336: memcpy(&reqp->xcmd, xs->cmd, sizeof(struct scsi_generic));
337: reqp->xcmd.bytes[0] |= reqp->targ_lun << 5;
338:
339: /*
340: * Sanity check on flags...
341: */
342: if (flags & ITSDONE) {
343: ncr_tprint(reqp, "scsi_cmd: command already done.....\n");
344: xs->flags &= ~ITSDONE;
345: }
346: if (!(flags & INUSE)) {
347: ncr_tprint(reqp, "scsi_cmd: command not in use.....\n");
1.25 briggs 348: xs->flags |= INUSE;
1.1 briggs 349: }
350:
351: #ifdef REAL_DMA
352: /*
353: * Check if DMA can be used on this request
354: */
355: if (scsi_dmaok(reqp))
356: reqp->dr_flag |= DRIVER_DMAOK;
357: #endif /* REAL_DMA */
358:
359: /*
360: * Insert the command into the issue queue. Note that 'REQUEST SENSE'
361: * commands are inserted at the head of the queue since any command
362: * will clear the existing contingent allegience condition and the sense
363: * data is only valid while the condition exists.
364: * When possible, link the command to a previous command to the same
365: * target. This is not very sensible when AUTO_SENSE is not defined!
366: * Interrupts are disabled while we are fiddling with the issue-queue.
367: */
368: sps = splbio();
1.14 briggs 369: link = NULL;
1.1 briggs 370: if ((issue_q == NULL) || (reqp->xcmd.opcode == REQUEST_SENSE)) {
371: reqp->next = issue_q;
372: issue_q = reqp;
373: }
374: else {
375: tmp = issue_q;
376: do {
377: if (!link && (tmp->targ_id == reqp->targ_id) && !tmp->link)
378: link = tmp;
379: } while (tmp->next && (tmp = tmp->next));
380: tmp->next = reqp;
381: #ifdef AUTO_SENSE
1.14 briggs 382: if (link && (ncr_will_link & (1<<reqp->targ_id))) {
1.1 briggs 383: link->link = reqp;
1.13 briggs 384: link->xcmd.bytes[link->xs->cmdlen-2] |= 1;
1.14 briggs 385: }
1.13 briggs 386: #endif
1.14 briggs 387: }
388: #ifdef AUTO_SENSE
389: /*
390: * If we haven't already, check the target for link support.
391: * Do this by prefixing the current command with a dummy
392: * Request_Sense command, link the dummy to the current
393: * command, and insert the dummy command at the head of the
394: * issue queue. Set the DRIVER_LINKCHK flag so that we'll
395: * ignore the results of the dummy command, since we only
396: * care about whether it was accepted or not.
397: */
398: if (!link && !(ncr_test_link & (1<<reqp->targ_id)) &&
399: (tmp = free_head) && !(reqp->dr_flag & DRIVER_NOINT)) {
400: free_head = tmp->next;
401: tmp->dr_flag = (reqp->dr_flag & ~DRIVER_DMAOK) | DRIVER_LINKCHK;
402: tmp->phase = NR_PHASE;
403: tmp->msgout = MSG_NOOP;
404: tmp->status = SCSGOOD;
405: tmp->xs = reqp->xs;
406: tmp->targ_id = reqp->targ_id;
407: tmp->targ_lun = reqp->targ_lun;
408: bcopy(sense_cmd, &tmp->xcmd, sizeof(sense_cmd));
1.38.10.1! thorpej 409: tmp->xdata_ptr = (u_char *)&tmp->xs->sense.scsi_sense;
! 410: tmp->xdata_len = sizeof(tmp->xs->sense.scsi_sense);
1.14 briggs 411: ncr_test_link |= 1<<tmp->targ_id;
412: tmp->link = reqp;
413: tmp->xcmd.bytes[sizeof(sense_cmd)-2] |= 1;
414: tmp->next = issue_q;
415: issue_q = tmp;
416: #ifdef DBG_REQ
417: if (dbg_target_mask & (1 << tmp->targ_id))
418: show_request(tmp, "LINKCHK");
1.1 briggs 419: #endif
420: }
1.14 briggs 421: #endif
1.1 briggs 422: splx(sps);
423:
424: #ifdef DBG_REQ
425: if (dbg_target_mask & (1 << reqp->targ_id))
426: show_request(reqp, (reqp->xcmd.opcode == REQUEST_SENSE) ?
427: "HEAD":"TAIL");
428: #endif
429:
430: run_main(xs->sc_link->adapter_softc);
431:
1.11 briggs 432: if (xs->flags & (SCSI_POLL|ITSDONE))
433: return (COMPLETE); /* We're booting or run_main has completed */
1.1 briggs 434: return (SUCCESSFULLY_QUEUED);
435: }
436:
437: static void
438: ncr5380_minphys(struct buf *bp)
439: {
440: if (bp->b_bcount > MIN_PHYS)
441: bp->b_bcount = MIN_PHYS;
442: minphys(bp);
443: }
444: #undef MIN_PHYS
445:
1.28 briggs 446: static void
1.38.10.1! thorpej 447: ncr5380_show_scsi_cmd(struct scsipi_xfer *xs)
1.1 briggs 448: {
449: u_char *b = (u_char *) xs->cmd;
450: int i = 0;
451:
452: if (!(xs->flags & SCSI_RESET)) {
1.38.10.1! thorpej 453: printf("(%d:%d:%d,0x%x)-", xs->sc_link->scsipi_scsi.scsibus,
! 454: xs->sc_link->scsipi_scsi.target, xs->sc_link->scsipi_scsi.lun,
! 455: xs->sc_link->flags);
1.1 briggs 456: while (i < xs->cmdlen) {
457: if (i)
1.35 christos 458: printf(",");
459: printf("%x",b[i++]);
1.1 briggs 460: }
1.35 christos 461: printf("-\n");
1.1 briggs 462: }
463: else {
1.35 christos 464: printf("(%d:%d:%d)-RESET-\n",
1.38.10.1! thorpej 465: xs->sc_link->scsipi_scsi.scsibus,xs->sc_link->scsipi_scsi.target,
! 466: xs->sc_link->scsipi_scsi.lun);
1.1 briggs 467: }
468: }
469:
470: /*
471: * The body of the driver.
472: */
473: static void
474: scsi_main(sc)
475: struct ncr_softc *sc;
476: {
477: SC_REQ *req, *prev;
478: int itype;
479: int sps;
480:
481: /*
482: * While running in the driver SCSI-interrupts are disabled.
483: */
484: scsi_idisable();
485: ENABLE_NCR5380(sc);
486:
487: PID("scsi_main1");
488: for (;;) {
489: sps = splbio();
490: if (!connected) {
491: /*
492: * Check if it is fair keep any exclusive access to DMA
493: * claimed. If not, stop queueing new jobs so the discon_q
494: * will be eventually drained and DMA can be given up.
495: */
496: if (!fair_to_keep_dma())
497: goto main_exit;
498:
499: /*
500: * Search through the issue-queue for a command
501: * destined for a target that isn't busy.
502: */
503: prev = NULL;
504: for (req=issue_q; req != NULL; prev = req, req = req->next) {
505: if (!(busy & (1 << req->targ_id))) {
506: /*
507: * Found one, remove it from the issue queue
508: */
509: if (prev == NULL)
510: issue_q = req->next;
511: else prev->next = req->next;
512: req->next = NULL;
513: break;
514: }
515: }
516:
517: /*
518: * When a request has just ended, we get here before an other
519: * device detects that the bus is free and that it can
520: * reconnect. The problem is that when this happens, we always
521: * baffle the device because our (initiator) id is higher. This
522: * can cause a sort of starvation on slow devices. So we check
523: * for a pending reselection here.
524: * Note that 'connected' will be non-null if the reselection
525: * succeeds.
526: */
527: if ((GET_5380_REG(NCR5380_IDSTAT) & (SC_S_SEL|SC_S_IO))
528: == (SC_S_SEL|SC_S_IO)){
529: if (req != NULL) {
530: req->next = issue_q;
531: issue_q = req;
532: }
533: splx(sps);
534:
535: reselect(sc);
536: scsi_clr_ipend();
537: goto connected;
538: }
539:
540: /*
541: * The host is not connected and there is no request
542: * pending, exit.
543: */
544: if (req == NULL) {
545: PID("scsi_main2");
546: goto main_exit;
547: }
548:
549: /*
550: * Re-enable interrupts before handling the request.
551: */
552: splx(sps);
553:
554: #ifdef DBG_REQ
555: if (dbg_target_mask & (1 << req->targ_id))
556: show_request(req, "TARGET");
557: #endif
558: /*
559: * We found a request. Try to connect to the target. If the
560: * initiator fails arbitration, the command is put back in the
561: * issue queue.
562: */
563: if (scsi_select(req, 0)) {
564: sps = splbio();
565: req->next = issue_q;
566: issue_q = req;
567: splx(sps);
568: #ifdef DBG_REQ
569: if (dbg_target_mask & (1 << req->targ_id))
570: ncr_tprint(req, "Select failed\n");
571: #endif
572: }
573: }
574: else splx(sps);
575: connected:
576: if (connected) {
577: /*
578: * If the host is currently connected but a 'real-dma' transfer
579: * is in progress, the 'end-of-dma' interrupt restarts main.
580: * So quit.
581: */
582: sps = splbio();
583: if (connected && (connected->dr_flag & DRIVER_IN_DMA)) {
584: PID("scsi_main3");
585: goto main_exit;
586: }
587: splx(sps);
588:
589: /*
590: * Let the target guide us through the bus-phases
591: */
1.20 briggs 592: while (information_transfer(sc) == -1)
1.1 briggs 593: ;
594: }
595: }
596: /* NEVER TO REACH HERE */
597: panic("ncr5380-SCSI: not designed to come here");
598:
599: main_exit:
600: /*
601: * We enter here with interrupts disabled. We are about to exit main
602: * so interrupts should be re-enabled. Because interrupts are edge
603: * triggered, we could already have missed the interrupt. Therefore
604: * we check the IRQ-line here and re-enter when we really missed a
605: * valid interrupt.
606: */
607: PID("scsi_main4");
608: scsi_ienable();
1.20 briggs 609:
610: /*
611: * If we're not currently connected, enable reselection
612: * interrupts.
613: */
614: if (!connected)
615: SET_5380_REG(NCR5380_IDSTAT, SC_HOST_ID);
616:
617: if (scsi_ipending()) {
1.1 briggs 618: if ((itype = check_intr(sc)) != INTR_SPURIOUS) {
619: scsi_idisable();
620: splx(sps);
621:
622: if (itype == INTR_RESEL)
623: reselect(sc);
624: #ifdef REAL_DMA
625: else dma_ready();
626: #else
627: else {
1.20 briggs 628: if (pdma_ready())
629: goto connected;
630: panic("Got DMA interrupt without DMA");
1.1 briggs 631: }
632: #endif
633: scsi_clr_ipend();
634: goto connected;
635: }
636: }
637: reconsider_dma();
638:
639: main_running = 0;
640: splx(sps);
641: PID("scsi_main5");
642: }
643:
644: #ifdef REAL_DMA
645: /*
646: * The SCSI-DMA interrupt.
647: * This interrupt can only be triggered when running in non-polled DMA
648: * mode. When DMA is not active, it will be silently ignored, it is usually
649: * to late because the EOP interrupt of the controller happens just a tiny
650: * bit earlier. It might become usefull when scatter/gather is implemented,
651: * because in that case only part of the DATAIN/DATAOUT transfer is taken
652: * out of a single buffer.
653: */
654: static void
655: ncr_dma_intr(sc)
656: struct ncr_softc *sc;
657: {
658: SC_REQ *reqp;
659: int dma_done;
660:
661: PID("ncr_dma_intr");
662: if ((reqp = connected) && (reqp->dr_flag & DRIVER_IN_DMA)) {
663: scsi_idisable();
664: if (!(dma_done = dma_ready())) {
665: transfer_dma(reqp, reqp->phase, 0);
666: return;
667: }
668: run_main(sc);
669: }
670: }
671: #endif /* REAL_DMA */
672:
673: /*
674: * The SCSI-controller interrupt. This interrupt occurs on reselections and
675: * at the end of non-polled DMA-interrupts. It is assumed to be called from
676: * the machine-dependent hardware interrupt.
677: */
678: static void
679: ncr_ctrl_intr(sc)
680: struct ncr_softc *sc;
681: {
682: int itype;
683:
1.20 briggs 684: while (scsi_ipending()) {
1.1 briggs 685: scsi_idisable();
686: if ((itype = check_intr(sc)) != INTR_SPURIOUS) {
687: if (itype == INTR_RESEL)
688: reselect(sc);
689: else {
690: #ifdef REAL_DMA
1.28 briggs 691: int dma_done;
1.1 briggs 692: if (!(dma_done = dma_ready())) {
693: transfer_dma(connected, connected->phase, 0);
694: return;
695: }
696: #else
1.20 briggs 697: if (pdma_ready())
698: return;
699: panic("Got DMA interrupt without DMA\n");
1.1 briggs 700: #endif
701: }
702: scsi_clr_ipend();
703: }
704: run_main(sc);
705: return;
706: }
707: PID("ncr_ctrl_intr1");
708: }
709:
710: /*
711: * Initiate a connection path between the host and the target. The function
712: * first goes into arbitration for the SCSI-bus. When this succeeds, the target
713: * is selected and an 'IDENTIFY' message is send.
714: * Returns -1 when the arbitration failed. Otherwise 0 is returned. When
715: * the target does not respond (to either selection or 'MESSAGE OUT') the
716: * 'done' function is executed.
717: * The result code given by the driver can be influenced by setting 'code'
718: * to a non-zero value. This is the case when 'select' is called by abort.
719: */
720: static int
721: scsi_select(reqp, code)
722: SC_REQ *reqp;
1.28 briggs 723: int code;
1.1 briggs 724: {
725: u_char tmp[1];
726: u_char phase;
727: u_long cnt;
728: int sps;
1.5 briggs 729: u_int8_t atn_flag;
730: u_int8_t targ_bit;
1.1 briggs 731: struct ncr_softc *sc;
732:
733: sc = reqp->xs->sc_link->adapter_softc;
734: DBG_SELPRINT ("Starting arbitration\n", 0);
735: PID("scsi_select1");
736:
737: sps = splbio();
738:
739: /*
740: * Prevent a race condition here. If a reslection interrupt occurred
741: * between the decision to pick a new request and the call to select,
742: * we abort the selection.
743: * Interrupts are lowered when the 5380 is setup to arbitrate for the
744: * bus.
745: */
1.10 briggs 746: if (connected) {
1.1 briggs 747: splx(sps);
748: PID("scsi_select2");
749: return (-1);
750: }
751:
752: /*
753: * Set phase bits to 0, otherwise the 5380 won't drive the bus during
754: * selection.
755: */
756: SET_5380_REG(NCR5380_TCOM, 0);
757: SET_5380_REG(NCR5380_ICOM, 0);
758:
759: /*
760: * Arbitrate for the bus.
761: */
762: SET_5380_REG(NCR5380_DATA, SC_HOST_ID);
763: SET_5380_REG(NCR5380_MODE, SC_ARBIT);
764:
765: splx(sps);
766:
1.10 briggs 767: cnt = 10;
1.1 briggs 768: while (!(GET_5380_REG(NCR5380_ICOM) & SC_AIP) && --cnt)
769: delay(1);
770:
771: if (!(GET_5380_REG(NCR5380_ICOM) & SC_AIP)) {
772: SET_5380_REG(NCR5380_MODE, IMODE_BASE);
1.10 briggs 773: SET_5380_REG(NCR5380_ICOM, 0);
774: DBG_SELPRINT ("Arbitration lost, bus not free\n",0);
1.1 briggs 775: PID("scsi_select3");
776: return (-1);
777: }
778:
779: /* The arbitration delay is 2.2 usecs */
780: delay(3);
781:
782: /*
783: * Check the result of the arbitration. If we failed, return -1.
784: */
785: if (GET_5380_REG(NCR5380_ICOM) & SC_LA) {
1.10 briggs 786: SET_5380_REG(NCR5380_MODE, IMODE_BASE);
787: SET_5380_REG(NCR5380_ICOM, 0);
788: PID("scsi_select4");
789: return (-1);
790: }
791:
792: /*
793: * The spec requires that we should read the data register to
794: * check for higher id's and check the SC_LA again.
795: */
796: tmp[0] = GET_5380_REG(NCR5380_DATA);
797: if (tmp[0] & ~((SC_HOST_ID << 1) - 1)) {
798: SET_5380_REG(NCR5380_MODE, IMODE_BASE);
799: SET_5380_REG(NCR5380_ICOM, 0);
800: DBG_SELPRINT ("Arbitration lost, higher id present\n",0);
801: PID("scsi_select5");
802: return (-1);
803: }
804: if (GET_5380_REG(NCR5380_ICOM) & SC_LA) {
805: SET_5380_REG(NCR5380_MODE, IMODE_BASE);
806: SET_5380_REG(NCR5380_ICOM, 0);
807: DBG_SELPRINT ("Arbitration lost,deassert SC_ARBIT\n",0);
808: PID("scsi_select6");
809: return (-1);
1.1 briggs 810: }
811: SET_5380_REG(NCR5380_ICOM, SC_A_SEL | SC_A_BSY);
812: if (GET_5380_REG(NCR5380_ICOM) & SC_LA) {
813: SET_5380_REG(NCR5380_MODE, IMODE_BASE);
814: SET_5380_REG(NCR5380_ICOM, 0);
815: DBG_SELPRINT ("Arbitration lost, deassert SC_A_SEL\n", 0);
1.10 briggs 816: PID("scsi_select7");
1.1 briggs 817: return (-1);
818: }
819: /* Bus settle delay + Bus clear delay = 1.2 usecs */
820: delay(2);
821: DBG_SELPRINT ("Arbitration complete\n", 0);
822:
823: /*
824: * Now that we won the arbitration, start the selection.
825: */
1.10 briggs 826: targ_bit = 1 << reqp->targ_id;
1.5 briggs 827: SET_5380_REG(NCR5380_DATA, SC_HOST_ID | targ_bit);
828:
829: if (sc->sc_noselatn & targ_bit)
830: atn_flag = 0;
831: else
832: atn_flag = SC_A_ATN;
1.1 briggs 833:
834: /*
835: * Raise ATN while SEL is true before BSY goes false from arbitration,
836: * since this is the only way to guarantee that we'll get a MESSAGE OUT
837: * phase immediately after the selection.
838: */
1.5 briggs 839: SET_5380_REG(NCR5380_ICOM, SC_A_BSY | SC_A_SEL | atn_flag | SC_ADTB);
1.1 briggs 840: SET_5380_REG(NCR5380_MODE, IMODE_BASE);
841:
842: /*
843: * Turn off reselection interrupts
844: */
845: SET_5380_REG(NCR5380_IDSTAT, 0);
846:
847: /*
848: * Reset BSY. The delay following it, surpresses a glitch in the
849: * 5380 which causes us to see our own BSY signal instead of that of
850: * the target.
851: */
1.6 briggs 852: SET_5380_REG(NCR5380_ICOM, SC_A_SEL | atn_flag | SC_ADTB);
1.1 briggs 853: delay(1);
854:
855: /*
856: * Wait for the target to react, the specs call for a timeout of
857: * 250 ms.
858: */
1.10 briggs 859: cnt = 25000;
1.1 briggs 860: while (!(GET_5380_REG(NCR5380_IDSTAT) & SC_S_BSY) && --cnt)
861: delay(10);
862:
863: if (!(GET_5380_REG(NCR5380_IDSTAT) & SC_S_BSY)) {
864: /*
865: * There is no reaction from the target, start the selection
866: * timeout procedure. We release the databus but keep SEL
867: * asserted. After that we wait a 'selection abort time' (200
868: * usecs) and 2 deskew delays (90 ns) and check BSY again.
869: * When BSY is asserted, we assume the selection succeeded,
870: * otherwise we release the bus.
871: */
1.10 briggs 872: SET_5380_REG(NCR5380_ICOM, SC_A_SEL | atn_flag);
1.1 briggs 873: delay(201);
874: if (!(GET_5380_REG(NCR5380_IDSTAT) & SC_S_BSY)) {
875: SET_5380_REG(NCR5380_ICOM, 0);
876: reqp->xs->error = code ? code : XS_SELTIMEOUT;
877: DBG_SELPRINT ("Target %d not responding to sel\n",
878: reqp->targ_id);
1.14 briggs 879: if (reqp->dr_flag & DRIVER_LINKCHK)
880: ncr_test_link &= ~(1<<reqp->targ_id);
1.1 briggs 881: finish_req(reqp);
1.10 briggs 882: PID("scsi_select8");
1.1 briggs 883: return (0);
884: }
885: }
1.6 briggs 886: SET_5380_REG(NCR5380_ICOM, atn_flag);
1.1 briggs 887:
888: DBG_SELPRINT ("Target %d responding to select.\n", reqp->targ_id);
889:
890: /*
891: * The SCSI-interrupts are disabled while a request is being handled.
892: */
893: scsi_idisable();
894:
895: /*
1.5 briggs 896: * If we did not request ATN, then don't try to send IDENTIFY.
897: */
898: if (atn_flag == 0) {
899: reqp->phase = PH_CMD;
900: goto identify_failed;
901: }
902:
903: /*
904: * Here we prepare to send an 'IDENTIFY' message.
905: * Allow disconnect only when interrups are allowed.
906: */
907: tmp[0] = MSG_IDENTIFY(reqp->targ_lun,
908: (reqp->dr_flag & DRIVER_NOINT) ? 0 : 1);
909: cnt = 1;
910: phase = PH_MSGOUT;
1.7 briggs 911:
1.5 briggs 912: /*
1.1 briggs 913: * Since we followed the SCSI-spec and raised ATN while SEL was true
914: * but before BSY was false during the selection, a 'MESSAGE OUT'
1.4 briggs 915: * phase should follow. Unfortunately, this does not happen on
916: * all targets (Asante ethernet devices, for example), so we must
1.5 briggs 917: * check the actual mode if the message transfer fails--if the
918: * new phase is PH_CMD and has never been successfully selected
919: * w/ATN in the past, then we assume that it is an old device
920: * that doesn't support select w/ATN.
1.4 briggs 921: */
1.5 briggs 922: if (transfer_pio(&phase, tmp, &cnt, 0) || cnt) {
1.4 briggs 923:
1.5 briggs 924: if ((phase == PH_CMD) && !(sc->sc_selected & targ_bit)) {
925: DBG_SELPRINT ("Target %d: not responding to ATN.\n",
926: reqp->targ_id);
927: sc->sc_noselatn |= targ_bit;
928: reqp->phase = PH_CMD;
929: goto identify_failed;
930: }
931:
932: DBG_SELPRINT ("Target %d: failed to send identify\n",
933: reqp->targ_id);
934: /*
935: * Try to disconnect from the target. We cannot leave
936: * it just hanging here.
937: */
938: if (!reach_msg_out(sc, sizeof(struct scsi_generic))) {
939: u_long len = 1;
940: u_char phase = PH_MSGOUT;
941: u_char msg = MSG_ABORT;
1.4 briggs 942:
1.5 briggs 943: transfer_pio(&phase, &msg, &len, 0);
1.1 briggs 944: }
1.20 briggs 945: else scsi_reset_verbose(sc, "Connected to unidentified target");
1.5 briggs 946:
947: SET_5380_REG(NCR5380_ICOM, 0);
948: reqp->xs->error = code ? code : XS_DRIVER_STUFFUP;
949: finish_req(reqp);
1.10 briggs 950: PID("scsi_select9");
1.5 briggs 951: return (0);
1.1 briggs 952: }
1.5 briggs 953: reqp->phase = PH_MSGOUT;
954:
955: identify_failed:
956: sc->sc_selected |= targ_bit;
1.1 briggs 957:
958: #ifdef notyet /* LWP: Do we need timeouts in the driver? */
959: /*
960: * Command is connected, start timer ticking.
961: */
962: ccb_p->xtimeout = ccb_p->timeout + Lbolt;
963: #endif
964:
965: connected = reqp;
1.5 briggs 966: busy |= targ_bit;
1.10 briggs 967: PID("scsi_select10");
1.1 briggs 968: return (0);
969: }
970:
971: /*
972: * Return codes:
1.20 briggs 973: * 0: Job has finished or disconnected, find something else
974: * -1: keep on calling information_transfer() from scsi_main()
1.1 briggs 975: */
976: static int
1.20 briggs 977: information_transfer(sc)
978: struct ncr_softc *sc;
1.1 briggs 979: {
980: SC_REQ *reqp = connected;
981: u_char tmp, phase;
982: u_long len;
983:
984: PID("info_transf1");
985: /*
986: * Clear pending interrupts from 5380-chip.
987: */
988: scsi_clr_ipend();
989:
990: /*
1.20 briggs 991: * The SCSI-spec requires BSY to be true while connected to a target,
992: * loosing it means we lost the target...
993: * Also REQ needs to be asserted here to indicate that the bus-phase
994: * is valid. When the target does not supply REQ within a 'reasonable'
995: * amount of time, it's probably lost in it's own maze of twisting
996: * passages, we have to reset the bus to free it.
1.1 briggs 997: */
1.20 briggs 998: if (GET_5380_REG(NCR5380_IDSTAT) & SC_S_BSY)
999: wait_req_true();
1.1 briggs 1000: tmp = GET_5380_REG(NCR5380_IDSTAT);
1001:
1.20 briggs 1002:
1003: if ((tmp & (SC_S_BSY|SC_S_REQ)) != (SC_S_BSY|SC_S_REQ)) {
1.1 briggs 1004: busy &= ~(1 << reqp->targ_id);
1005: connected = NULL;
1.20 briggs 1006: reqp->xs->error = XS_TIMEOUT;
1.1 briggs 1007: finish_req(reqp);
1.20 briggs 1008: if (!(tmp & SC_S_REQ))
1009: scsi_reset_verbose(sc,
1010: "Timeout waiting for phase-change");
1.1 briggs 1011: PID("info_transf2");
1012: return (0);
1013: }
1014:
1.20 briggs 1015: phase = (tmp >> 2) & 7;
1016: if (phase != reqp->phase) {
1017: reqp->phase = phase;
1018: DBG_INFPRINT(show_phase, reqp, phase);
1.1 briggs 1019: }
1.27 briggs 1020: else {
1021: /*
1022: * Same data-phase. If same error give up
1023: */
1024: if ((reqp->msgout == MSG_ABORT)
1025: && ((phase == PH_DATAOUT) || (phase == PH_DATAIN))) {
1026: busy &= ~(1 << reqp->targ_id);
1027: connected = NULL;
1028: finish_req(reqp);
1029: scsi_reset_verbose(sc, "Failure to abort command");
1030: return (0);
1031: }
1032: }
1.1 briggs 1033:
1034: switch (phase) {
1035: case PH_DATAOUT:
1036: #ifdef DBG_NOWRITE
1037: ncr_tprint(reqp, "NOWRITE set -- write attempt aborted.");
1038: reqp->msgout = MSG_ABORT;
1039: SET_5380_REG(NCR5380_ICOM, SC_A_ATN);
1040: return (-1);
1041: #endif /* DBG_NOWRITE */
1042: /*
1043: * If this is the first write using DMA, fill
1044: * the bounce buffer.
1045: */
1046: if (reqp->xdata_ptr == reqp->xs->data) { /* XXX */
1047: if (reqp->dr_flag & DRIVER_BOUNCING)
1048: bcopy(reqp->xdata_ptr, reqp->bounceb, reqp->xdata_len);
1049: }
1050:
1051: case PH_DATAIN:
1.27 briggs 1052: if (reqp->xdata_len <= 0) {
1053: /*
1054: * Target keeps requesting data. Try to get into
1055: * message-out phase by feeding/taking 100 byte.
1056: */
1057: ncr_tprint(reqp, "Target requests too much data\n");
1058: reqp->msgout = MSG_ABORT;
1059: SET_5380_REG(NCR5380_ICOM, SC_A_ATN);
1060: reach_msg_out(sc, 100);
1061: return (-1);
1062: }
1.1 briggs 1063: #ifdef REAL_DMA
1064: if (reqp->dr_flag & DRIVER_DMAOK) {
1065: int poll = REAL_DMA_POLL|(reqp->dr_flag & DRIVER_NOINT);
1066: transfer_dma(reqp, phase, poll);
1067: if (!poll)
1068: return (0);
1069: }
1070: else
1071: #endif
1072: {
1073: PID("info_transf3");
1074: len = reqp->xdata_len;
1075: #ifdef USE_PDMA
1076: if (transfer_pdma(&phase, reqp->xdata_ptr, &len) == 0)
1.7 briggs 1077: return (0);
1.1 briggs 1078: #else
1.3 briggs 1079: transfer_pio(&phase, reqp->xdata_ptr, &len, 0);
1.1 briggs 1080: #endif
1081: reqp->xdata_ptr += reqp->xdata_len - len;
1082: reqp->xdata_len = len;
1083: }
1084: return (-1);
1085: case PH_MSGIN:
1086: /*
1087: * We only expect single byte messages here.
1088: */
1089: len = 1;
1.3 briggs 1090: transfer_pio(&phase, &tmp, &len, 1);
1.1 briggs 1091: reqp->message = tmp;
1092: return (handle_message(reqp, tmp));
1093: case PH_MSGOUT:
1094: len = 1;
1.3 briggs 1095: transfer_pio(&phase, &reqp->msgout, &len, 0);
1.1 briggs 1096: if (reqp->msgout == MSG_ABORT) {
1097: busy &= ~(1 << reqp->targ_id);
1098: connected = NULL;
1.27 briggs 1099: if (!reqp->xs->error)
1100: reqp->xs->error = XS_DRIVER_STUFFUP;
1.1 briggs 1101: finish_req(reqp);
1102: PID("info_transf4");
1103: return (0);
1104: }
1105: reqp->msgout = MSG_NOOP;
1106: return (-1);
1107: case PH_CMD :
1108: len = command_size(reqp->xcmd.opcode);
1.3 briggs 1109: transfer_pio(&phase, (u_char *)&reqp->xcmd, &len, 0);
1.1 briggs 1110: PID("info_transf5");
1111: return (-1);
1112: case PH_STATUS:
1113: len = 1;
1.3 briggs 1114: transfer_pio(&phase, &tmp, &len, 0);
1.1 briggs 1115: reqp->status = tmp;
1116: PID("info_transf6");
1117: return (-1);
1118: default :
1119: ncr_tprint(reqp, "Unknown phase\n");
1120: }
1121: PID("info_transf7");
1122: return (-1);
1123: }
1124:
1125: /*
1126: * Handle the message 'msg' send to us by the target.
1127: * Return values:
1128: * 0 : The current command has completed.
1129: * -1 : Get on to the next phase.
1130: */
1131: static int
1132: handle_message(reqp, msg)
1133: SC_REQ *reqp;
1134: u_int msg;
1135: {
1136: int sps;
1.11 briggs 1137: SC_REQ *prev, *req;
1.1 briggs 1138:
1139: PID("hmessage1");
1140: switch (msg) {
1141: /*
1142: * Linking lets us reduce the time required to get
1143: * the next command to the device, skipping the arbitration
1144: * and selection time. In the current implementation,
1145: * we merely have to start the next command pointed
1146: * to by 'next_link'.
1147: */
1148: case MSG_LINK_CMD_COMPLETE:
1149: case MSG_LINK_CMD_COMPLETEF:
1150: if (reqp->link == NULL) {
1151: ncr_tprint(reqp, "No link for linked command");
1.9 briggs 1152: nack_message(reqp, MSG_ABORT);
1.1 briggs 1153: PID("hmessage2");
1154: return (-1);
1155: }
1.3 briggs 1156: ack_message();
1.11 briggs 1157: if (!(reqp->dr_flag & DRIVER_AUTOSEN)) {
1158: reqp->xs->resid = reqp->xdata_len;
1159: reqp->xs->error = 0;
1160: }
1.1 briggs 1161:
1162: #ifdef AUTO_SENSE
1.11 briggs 1163: if (check_autosense(reqp, 1) == -1)
1.1 briggs 1164: return (-1);
1165: #endif /* AUTO_SENSE */
1166:
1167: #ifdef DBG_REQ
1168: if (dbg_target_mask & (1 << reqp->targ_id))
1169: show_request(reqp->link, "LINK");
1170: #endif
1171: connected = reqp->link;
1.11 briggs 1172:
1173: /*
1174: * Unlink the 'linked' request from the issue_q
1175: */
1176: sps = splbio();
1177: prev = NULL;
1178: req = issue_q;
1179: for (; req != NULL; prev = req, req = req->next) {
1180: if (req == connected)
1181: break;
1182: }
1183: if (req == NULL)
1184: panic("Inconsistent issue_q");
1185: if (prev == NULL)
1186: issue_q = req->next;
1187: else prev->next = req->next;
1188: req->next = NULL;
1189: splx(sps);
1190:
1.1 briggs 1191: finish_req(reqp);
1192: PID("hmessage3");
1193: return (-1);
1194: case MSG_ABORT:
1195: case MSG_CMDCOMPLETE:
1.3 briggs 1196: ack_message();
1.1 briggs 1197: connected = NULL;
1198: busy &= ~(1 << reqp->targ_id);
1199: if (!(reqp->dr_flag & DRIVER_AUTOSEN)) {
1200: reqp->xs->resid = reqp->xdata_len;
1201: reqp->xs->error = 0;
1202: }
1203:
1204: #ifdef AUTO_SENSE
1205: if (check_autosense(reqp, 0) == -1) {
1206: PID("hmessage4");
1207: return (0);
1208: }
1209: #endif /* AUTO_SENSE */
1210:
1211: finish_req(reqp);
1212: PID("hmessage5");
1213: return (0);
1214: case MSG_MESSAGE_REJECT:
1.3 briggs 1215: ack_message();
1.1 briggs 1216: PID("hmessage6");
1217: return (-1);
1218: case MSG_DISCONNECT:
1.3 briggs 1219: ack_message();
1.1 briggs 1220: #ifdef DBG_REQ
1221: if (dbg_target_mask & (1 << reqp->targ_id))
1222: show_request(reqp, "DISCON");
1223: #endif
1224: sps = splbio();
1225: connected = NULL;
1226: reqp->next = discon_q;
1227: discon_q = reqp;
1228: splx(sps);
1229: PID("hmessage7");
1230: return (0);
1231: case MSG_SAVEDATAPOINTER:
1232: case MSG_RESTOREPOINTERS:
1233: /*
1234: * We save pointers implicitely at disconnect.
1235: * So we can ignore these messages.
1236: */
1.3 briggs 1237: ack_message();
1.1 briggs 1238: PID("hmessage8");
1239: return (-1);
1.3 briggs 1240: case MSG_EXTENDED:
1.9 briggs 1241: nack_message(reqp, MSG_MESSAGE_REJECT);
1.3 briggs 1242: PID("hmessage9");
1243: return (-1);
1.1 briggs 1244: default:
1.22 briggs 1245: if ((msg & 0x80) && !(msg & 0x18)) { /* IDENTIFY */
1.21 briggs 1246: PID("hmessage10");
1247: ack_message();
1248: return (0);
1249: } else {
1250: ncr_tprint(reqp,
1251: "Unknown message %x. Rejecting.\n",
1252: msg);
1253: nack_message(reqp, MSG_MESSAGE_REJECT);
1254: }
1.1 briggs 1255: return (-1);
1256: }
1.21 briggs 1257: PID("hmessage11");
1.1 briggs 1258: return (-1);
1259: }
1260:
1261: /*
1262: * Handle reselection. If a valid reconnection occurs, connected
1263: * points at the reconnected command. The command is removed from the
1264: * disconnected queue.
1265: */
1266: static void
1267: reselect(sc)
1268: struct ncr_softc *sc;
1269: {
1270: u_char phase;
1271: u_long len;
1272: u_char msg;
1273: u_char target_mask;
1274: int abort = 0;
1275: SC_REQ *tmp, *prev;
1276:
1277: PID("reselect1");
1278: target_mask = GET_5380_REG(NCR5380_DATA) & ~SC_HOST_ID;
1279:
1280: /*
1281: * At this point, we have detected that our SCSI-id is on the bus,
1282: * SEL is true and BSY was false for at least one bus settle
1283: * delay (400 ns.).
1284: * We must assert BSY ourselves, until the target drops the SEL signal.
1.3 briggs 1285: * The SCSI-spec specifies no maximum time for this, so we have to
1286: * choose something long enough to suit all targets.
1.1 briggs 1287: */
1288: SET_5380_REG(NCR5380_ICOM, SC_A_BSY);
1.11 briggs 1289: len = 250000;
1.2 briggs 1290: while ((GET_5380_REG(NCR5380_IDSTAT) & SC_S_SEL) && (len > 0)) {
1291: delay(1);
1292: len--;
1293: }
1294: if (GET_5380_REG(NCR5380_IDSTAT) & SC_S_SEL) {
1295: /* Damn SEL isn't dropping */
1.20 briggs 1296: scsi_reset_verbose(sc, "Target won't drop SEL during Reselect");
1.2 briggs 1297: return;
1298: }
1.7 briggs 1299:
1.1 briggs 1300: SET_5380_REG(NCR5380_ICOM, 0);
1301:
1302: /*
1.11 briggs 1303: * Check if the reselection is still valid. Check twice because
1304: * of possible line glitches - cheaper than delay(1) and we need
1305: * only a few nanoseconds.
1306: */
1307: if (!(GET_5380_REG(NCR5380_IDSTAT) & SC_S_BSY)) {
1308: if (!(GET_5380_REG(NCR5380_IDSTAT) & SC_S_BSY)) {
1309: ncr_aprint(sc, "Stepped into the reselection timeout\n");
1310: return;
1311: }
1312: }
1313:
1314: /*
1.1 briggs 1315: * Get the expected identify message.
1316: */
1317: phase = PH_MSGIN;
1318: len = 1;
1.3 briggs 1319: transfer_pio(&phase, &msg, &len, 0);
1.1 briggs 1320: if (len || !MSG_ISIDENTIFY(msg)) {
1321: ncr_aprint(sc, "Expecting IDENTIFY, got 0x%x\n", msg);
1322: abort = 1;
1.27 briggs 1323: tmp = NULL;
1.1 briggs 1324: }
1325: else {
1326: /*
1327: * Find the command reconnecting
1328: */
1329: for (tmp = discon_q, prev = NULL; tmp; prev = tmp, tmp = tmp->next){
1330: if (target_mask == (1 << tmp->targ_id)) {
1331: if (prev)
1332: prev->next = tmp->next;
1333: else discon_q = tmp->next;
1334: tmp->next = NULL;
1335: break;
1336: }
1337: }
1338: if (tmp == NULL) {
1339: ncr_aprint(sc, "No disconnected job for targetmask %x\n",
1340: target_mask);
1341: abort = 1;
1342: }
1343: }
1344: if (abort) {
1345: msg = MSG_ABORT;
1346: len = 1;
1347: phase = PH_MSGOUT;
1348:
1349: SET_5380_REG(NCR5380_ICOM, SC_A_ATN);
1.16 briggs 1350: if (transfer_pio(&phase, &msg, &len, 0) || len)
1.20 briggs 1351: scsi_reset_verbose(sc, "Failure to abort reselection");
1.1 briggs 1352: }
1353: else {
1354: connected = tmp;
1355: #ifdef DBG_REQ
1356: if (dbg_target_mask & (1 << tmp->targ_id))
1357: show_request(tmp, "RECON");
1358: #endif
1359: }
1360: PID("reselect2");
1361: }
1362:
1363: /*
1364: * Transfer data in a given phase using programmed I/O.
1365: * Returns -1 when a different phase is entered without transferring the
1.3 briggs 1366: * maximum number of bytes, 0 if all bytes transferred or exit is in the same
1.1 briggs 1367: * phase.
1368: */
1369: static int
1.3 briggs 1370: transfer_pio(phase, data, len, dont_drop_ack)
1.1 briggs 1371: u_char *phase;
1372: u_char *data;
1373: u_long *len;
1.3 briggs 1374: int dont_drop_ack;
1.1 briggs 1375: {
1376: u_int cnt = *len;
1377: u_char ph = *phase;
1.3 briggs 1378: u_char tmp, new_icom;
1.1 briggs 1379:
1380: DBG_PIOPRINT ("SCSI: transfer_pio start: phase: %d, len: %d\n", ph,cnt);
1381: PID("tpio1");
1382: SET_5380_REG(NCR5380_TCOM, ph);
1383: do {
1384: if (!wait_req_true()) {
1385: DBG_PIOPRINT ("SCSI: transfer_pio: missing REQ\n", 0, 0);
1386: break;
1387: }
1388: if (((GET_5380_REG(NCR5380_IDSTAT) >> 2) & 7) != ph) {
1389: DBG_PIOPRINT ("SCSI: transfer_pio: phase mismatch\n", 0, 0);
1390: break;
1391: }
1392: if (PH_IN(ph)) {
1393: *data++ = GET_5380_REG(NCR5380_DATA);
1394: SET_5380_REG(NCR5380_ICOM, SC_A_ACK);
1.3 briggs 1395: if ((cnt == 1) && dont_drop_ack)
1396: new_icom = SC_A_ACK;
1397: else new_icom = 0;
1.1 briggs 1398: }
1399: else {
1400: SET_5380_REG(NCR5380_DATA, *data++);
1401:
1402: /*
1403: * The SCSI-standard suggests that in the 'MESSAGE OUT' phase,
1404: * the initiator should drop ATN on the last byte of the
1405: * message phase after REQ has been asserted for the handshake
1406: * but before the initiator raises ACK.
1407: */
1408: if (!( (ph == PH_MSGOUT) && (cnt > 1) )) {
1409: SET_5380_REG(NCR5380_ICOM, SC_ADTB);
1410: SET_5380_REG(NCR5380_ICOM, SC_ADTB | SC_A_ACK);
1.3 briggs 1411: new_icom = 0;
1.1 briggs 1412: }
1413: else {
1414: SET_5380_REG(NCR5380_ICOM, SC_ADTB | SC_A_ATN);
1415: SET_5380_REG(NCR5380_ICOM, SC_ADTB|SC_A_ATN|SC_A_ACK);
1.3 briggs 1416: new_icom = SC_A_ATN;
1.1 briggs 1417: }
1418: }
1419: if (!wait_req_false()) {
1420: DBG_PIOPRINT ("SCSI: transfer_pio - REQ not dropping\n", 0, 0);
1421: break;
1422: }
1.3 briggs 1423: SET_5380_REG(NCR5380_ICOM, new_icom);
1.1 briggs 1424:
1425: } while (--cnt);
1426:
1427: if ((tmp = GET_5380_REG(NCR5380_IDSTAT)) & SC_S_REQ)
1428: *phase = (tmp >> 2) & 7;
1429: else *phase = NR_PHASE;
1430: *len = cnt;
1431: DBG_PIOPRINT ("SCSI: transfer_pio done: phase: %d, len: %d\n",
1432: *phase, cnt);
1433: PID("tpio2");
1434: if (!cnt || (*phase == ph))
1435: return (0);
1436: return (-1);
1437: }
1438:
1439: #ifdef REAL_DMA
1440: /*
1441: * Start a DMA-transfer on the device using the current pointers.
1442: * If 'poll' is true, the function busy-waits until DMA has completed.
1443: */
1444: static void
1445: transfer_dma(reqp, phase, poll)
1446: SC_REQ *reqp;
1447: u_int phase;
1448: int poll;
1449: {
1450: int dma_done;
1451: u_char mbase = 0;
1452: int sps;
1453:
1454: again:
1455: PID("tdma1");
1456:
1457: /*
1458: * We should be in phase, otherwise we are not allowed to
1459: * drive the bus.
1460: */
1461: SET_5380_REG(NCR5380_TCOM, phase);
1462:
1463: /*
1464: * Defer interrupts until DMA is fully running.
1465: */
1466: sps = splbio();
1467:
1468: /*
1469: * Clear pending interrupts and parity errors.
1470: */
1471: scsi_clr_ipend();
1472:
1473: if (!poll) {
1474: /*
1475: * Enable SCSI interrupts and set IN_DMA flag, set 'mbase'
1476: * to the interrupts we want enabled.
1477: */
1478: scsi_ienable();
1479: reqp->dr_flag |= DRIVER_IN_DMA;
1480: mbase = SC_E_EOPI | SC_MON_BSY;
1481: }
1482: else scsi_idisable();
1483: mbase |= IMODE_BASE | SC_M_DMA;
1484: scsi_dma_setup(reqp, phase, mbase);
1485:
1486: splx(sps);
1487:
1488: if (poll) {
1489: /*
1490: * On polled-dma transfers, we wait here until the
1491: * 'end-of-dma' condition occurs.
1492: */
1493: poll_edma(reqp);
1494: if (!(dma_done = dma_ready()))
1495: goto again;
1496: }
1497: PID("tdma2");
1498: }
1499:
1500: /*
1501: * Check results of a DMA data-transfer.
1502: */
1503: static int
1504: dma_ready()
1505: {
1506: SC_REQ *reqp = connected;
1507: int dmstat, is_edma;
1508: long bytes_left, bytes_done;
1509:
1510: is_edma = get_dma_result(reqp, &bytes_left);
1511: dmstat = GET_5380_REG(NCR5380_DMSTAT);
1512:
1513: /*
1514: * Check if the call is sensible and not caused by any spurious
1515: * interrupt.
1516: */
1517: if (!is_edma && !(dmstat & (SC_END_DMA|SC_BSY_ERR))
1518: && (dmstat & SC_PHS_MTCH) ) {
1.17 briggs 1519: ncr_tprint(reqp, "dma_ready: spurious call "
1.1 briggs 1520: "(dm:%x,last_hit: %s)\n",
1521: #ifdef DBG_PID
1.17 briggs 1522: dmstat, last_hit[DBG_PID-1]);
1.1 briggs 1523: #else
1.17 briggs 1524: dmstat, "unknown");
1.1 briggs 1525: #endif
1526: return (0);
1527: }
1528:
1529: /*
1530: * Clear all (pending) interrupts.
1531: */
1532: scsi_clr_ipend();
1533:
1534: /*
1535: * Update various transfer-pointers/lengths
1536: */
1537: bytes_done = reqp->dm_cur->dm_count - bytes_left;
1538:
1539: if ((reqp->dr_flag & DRIVER_BOUNCING) && (PH_IN(reqp->phase))) {
1540: /*
1541: * Copy the bytes read until now from the bounce buffer
1542: * to the 'real' destination. Flush the data-cache
1543: * before copying.
1544: */
1545: PCIA();
1546: bcopy(reqp->bouncerp, reqp->xdata_ptr, bytes_done);
1547: reqp->bouncerp += bytes_done;
1548: }
1549:
1550: reqp->xdata_ptr = &reqp->xdata_ptr[bytes_done]; /* XXX */
1551: reqp->xdata_len -= bytes_done; /* XXX */
1552: if ((reqp->dm_cur->dm_count -= bytes_done) == 0)
1553: reqp->dm_cur++;
1554: else reqp->dm_cur->dm_addr += bytes_done;
1555:
1556: if (PH_IN(reqp->phase) && (dmstat & SC_PAR_ERR)) {
1.27 briggs 1557: if (!(ncr5380_no_parchk & (1 << reqp->targ_id))) {
1558: ncr_tprint(reqp, "parity error in data-phase\n");
1559: reqp->xs->error = XS_TIMEOUT;
1560: }
1.1 briggs 1561: }
1562:
1563: /*
1564: * DMA mode should always be reset even when we will continue with the
1.10 briggs 1565: * next chain. It is also essential to clear the MON_BUSY because
1566: * when LOST_BUSY is unexpectedly set, we will not be able to drive
1567: * the bus....
1.1 briggs 1568: */
1.10 briggs 1569: SET_5380_REG(NCR5380_MODE, IMODE_BASE);
1.1 briggs 1570:
1571:
1572: if ((dmstat & SC_BSY_ERR) || !(dmstat & SC_PHS_MTCH)
1573: || (reqp->dm_cur > reqp->dm_last) || (reqp->xs->error)) {
1574:
1575: /*
1576: * Tell interrupt functions DMA mode has ended.
1577: */
1578: reqp->dr_flag &= ~DRIVER_IN_DMA;
1579:
1580: /*
1581: * Clear mode and icom
1582: */
1583: SET_5380_REG(NCR5380_MODE, IMODE_BASE);
1584: SET_5380_REG(NCR5380_ICOM, 0);
1585:
1586: if (dmstat & SC_BSY_ERR) {
1587: if (!reqp->xs->error)
1.27 briggs 1588: reqp->xs->error = XS_TIMEOUT;
1.1 briggs 1589: finish_req(reqp);
1590: PID("dma_ready1");
1591: return (1);
1592: }
1593:
1594: if (reqp->xs->error != 0) {
1595: ncr_tprint(reqp, "dma-ready: code = %d\n", reqp->xs->error); /* LWP */
1596: reqp->msgout = MSG_ABORT;
1597: SET_5380_REG(NCR5380_ICOM, SC_A_ATN);
1598: }
1599: PID("dma_ready2");
1600: return (1);
1601: }
1602: return (0);
1603: }
1604: #endif /* REAL_DMA */
1605:
1606: static int
1607: check_autosense(reqp, linked)
1608: SC_REQ *reqp;
1609: int linked;
1610: {
1611: int sps;
1612:
1613: /*
1.14 briggs 1614: * If this is the driver's Link Check for this target, ignore
1615: * the results of the command. All we care about is whether we
1616: * got here from a LINK_CMD_COMPLETE or CMD_COMPLETE message.
1617: */
1618: PID("linkcheck");
1619: if (reqp->dr_flag & DRIVER_LINKCHK) {
1620: if (linked)
1621: ncr_will_link |= 1<<reqp->targ_id;
1.16 briggs 1622: else ncr_tprint(reqp, "Does not support linked commands\n");
1.14 briggs 1623: return (0);
1624: }
1625: /*
1.1 briggs 1626: * If we not executing an auto-sense and the status code
1627: * is request-sense, we automatically issue a request
1628: * sense command.
1629: */
1630: PID("cautos1");
1631: if (!(reqp->dr_flag & DRIVER_AUTOSEN)) {
1.11 briggs 1632: switch (reqp->status & SCSMASK) {
1633: case SCSCHKC:
1634: bcopy(sense_cmd, &reqp->xcmd, sizeof(sense_cmd));
1.38.10.1! thorpej 1635: reqp->xdata_ptr = (u_char *)&reqp->xs->sense.scsi_sense;
! 1636: reqp->xdata_len = sizeof(reqp->xs->sense.scsi_sense);
1.1 briggs 1637: reqp->dr_flag |= DRIVER_AUTOSEN;
1638: reqp->dr_flag &= ~DRIVER_DMAOK;
1639: if (!linked) {
1640: sps = splbio();
1641: reqp->next = issue_q;
1642: issue_q = reqp;
1643: splx(sps);
1644: }
1.14 briggs 1645: else reqp->xcmd.bytes[sizeof(sense_cmd)-2] |= 1;
1.1 briggs 1646:
1647: #ifdef DBG_REQ
1648: bzero(reqp->xdata_ptr, reqp->xdata_len);
1649: if (dbg_target_mask & (1 << reqp->targ_id))
1650: show_request(reqp, "AUTO-SENSE");
1651: #endif
1652: PID("cautos2");
1653: return (-1);
1.11 briggs 1654: case SCSBUSY:
1655: reqp->xs->error = XS_BUSY;
1656: return (0);
1.1 briggs 1657: }
1658: }
1659: else {
1660: /*
1661: * An auto-sense has finished
1662: */
1663: if ((reqp->status & SCSMASK) != SCSGOOD)
1664: reqp->xs->error = XS_DRIVER_STUFFUP; /* SC_E_AUTOSEN; */
1665: else reqp->xs->error = XS_SENSE;
1666: reqp->status = SCSCHKC;
1667: }
1668: PID("cautos3");
1669: return (0);
1670: }
1671:
1672: static int
1673: reach_msg_out(sc, len)
1674: struct ncr_softc *sc;
1675: u_long len;
1676: {
1677: u_char phase;
1678: u_char data;
1.27 briggs 1679: u_long n = len;
1.1 briggs 1680:
1681: ncr_aprint(sc, "Trying to reach Message-out phase\n");
1682: if ((phase = GET_5380_REG(NCR5380_IDSTAT)) & SC_S_REQ)
1683: phase = (phase >> 2) & 7;
1684: else return (-1);
1685: ncr_aprint(sc, "Trying to reach Message-out phase, now: %d\n", phase);
1686: if (phase == PH_MSGOUT)
1687: return (0);
1688:
1689: SET_5380_REG(NCR5380_TCOM, phase);
1690:
1691: do {
1692: if (!wait_req_true())
1693: break;
1694: if (((GET_5380_REG(NCR5380_IDSTAT) >> 2) & 7) != phase)
1695: break;
1696: if (PH_IN(phase)) {
1697: data = GET_5380_REG(NCR5380_DATA);
1698: SET_5380_REG(NCR5380_ICOM, SC_A_ACK | SC_A_ATN);
1699: }
1700: else {
1701: SET_5380_REG(NCR5380_DATA, 0);
1702: SET_5380_REG(NCR5380_ICOM, SC_ADTB|SC_A_ACK|SC_A_ATN);
1703: }
1704: if (!wait_req_false())
1705: break;
1706: SET_5380_REG(NCR5380_ICOM, SC_A_ATN);
1.27 briggs 1707: } while (--n);
1.1 briggs 1708:
1709: if ((phase = GET_5380_REG(NCR5380_IDSTAT)) & SC_S_REQ) {
1710: phase = (phase >> 2) & 7;
1711: if (phase == PH_MSGOUT) {
1.27 briggs 1712: ncr_aprint(sc, "Message-out phase reached after "
1713: "%ld bytes.\n", len - n);
1.1 briggs 1714: return (0);
1715: }
1716: }
1717: return (-1);
1718: }
1719:
1.28 briggs 1720: void
1.20 briggs 1721: scsi_reset()
1.1 briggs 1722: {
1723: SC_REQ *tmp, *next;
1724: int sps;
1725:
1726: PID("scsi_reset1");
1727: sps = splbio();
1728: SET_5380_REG(NCR5380_ICOM, SC_A_RST);
1.20 briggs 1729: delay(100);
1.1 briggs 1730: SET_5380_REG(NCR5380_ICOM, 0);
1.20 briggs 1731: scsi_clr_ipend();
1.1 briggs 1732:
1733: /*
1734: * None of the jobs in the discon_q will ever be reconnected,
1735: * notify this to the higher level code.
1736: */
1737: for (tmp = discon_q; tmp ;) {
1738: next = tmp->next;
1739: tmp->next = NULL;
1740: tmp->xs->error = XS_TIMEOUT;
1741: busy &= ~(1 << tmp->targ_id);
1742: finish_req(tmp);
1743: tmp = next;
1744: }
1745: discon_q = NULL;
1746:
1747: /*
1748: * The current job will never finish either.
1749: * The problem is that we can't finish the job because an instance
1750: * of main is running on it. Our best guess is that the job is currently
1751: * doing REAL-DMA. In that case 'dma_ready()' should correctly finish
1752: * the job because it detects BSY-loss.
1753: */
1.27 briggs 1754: if ((tmp = connected) != NULL) {
1.1 briggs 1755: if (tmp->dr_flag & DRIVER_IN_DMA) {
1756: tmp->xs->error = XS_DRIVER_STUFFUP;
1757: #ifdef REAL_DMA
1758: dma_ready();
1759: #endif
1760: }
1761: }
1762: splx(sps);
1763: PID("scsi_reset2");
1.20 briggs 1764:
1765: /*
1766: * Give the attached devices some time to handle the reset. This
1767: * value is arbitrary but should be relatively long.
1768: */
1769: delay(100000);
1770: }
1771:
1772: static void
1773: scsi_reset_verbose(sc, why)
1774: struct ncr_softc *sc;
1775: const char *why;
1776: {
1777: ncr_aprint(sc, "Resetting SCSI-bus (%s)\n", why);
1778:
1779: scsi_reset();
1.1 briggs 1780: }
1781:
1782: /*
1783: * Check validity of the IRQ set by the 5380. If the interrupt is valid,
1784: * the appropriate action is carried out (reselection or DMA ready) and
1785: * INTR_RESEL or INTR_DMA is returned. Otherwise a console notice is written
1786: * and INTR_SPURIOUS is returned.
1787: */
1788: static int
1789: check_intr(sc)
1790: struct ncr_softc *sc;
1791: {
1792: SC_REQ *reqp;
1793:
1794: if ((GET_5380_REG(NCR5380_IDSTAT) & (SC_S_SEL|SC_S_IO))
1795: ==(SC_S_SEL|SC_S_IO))
1796: return (INTR_RESEL);
1797: else {
1798: if ((reqp = connected) && (reqp->dr_flag & DRIVER_IN_DMA)){
1799: reqp->dr_flag &= ~DRIVER_IN_DMA;
1800: return (INTR_DMA);
1801: }
1802: }
1803: scsi_clr_ipend();
1.35 christos 1804: printf("-->");
1.1 briggs 1805: scsi_show();
1806: ncr_aprint(sc, "Spurious interrupt.\n");
1807: return (INTR_SPURIOUS);
1808: }
1809:
1810: #ifdef REAL_DMA
1811: /*
1812: * Check if DMA can be used for this request. This function also builds
1813: * the dma-chain.
1814: */
1815: static int
1816: scsi_dmaok(reqp)
1817: SC_REQ *reqp;
1818: {
1819: u_long phy_buf;
1820: u_long phy_len;
1821: void *req_addr;
1822: u_long req_len;
1823: struct dma_chain *dm;
1824:
1825: /*
1826: * Initialize locals and requests' DMA-chain.
1827: */
1828: req_len = reqp->xdata_len;
1829: req_addr = (void*)reqp->xdata_ptr;
1830: dm = reqp->dm_cur = reqp->dm_last = reqp->dm_chain;
1831: dm->dm_count = dm->dm_addr = 0;
1832: reqp->dr_flag &= ~DRIVER_BOUNCING;
1833:
1834: /*
1835: * Do not accept zero length DMA.
1836: */
1837: if (req_len == 0)
1838: return (0);
1839:
1840: /*
1841: * LWP: I think that this restriction is not strictly nessecary.
1842: */
1843: if ((req_len & 0x1) || ((u_int)req_addr & 0x3))
1844: return (0);
1845:
1846: /*
1847: * Build the DMA-chain.
1848: */
1849: dm->dm_addr = phy_buf = kvtop(req_addr);
1850: while (req_len) {
1851: if (req_len < (phy_len = NBPG - ((u_long)req_addr & PGOFSET)))
1852: phy_len = req_len;
1853:
1854: req_addr += phy_len;
1855: req_len -= phy_len;
1856: dm->dm_count += phy_len;
1857:
1858: if (req_len) {
1859: u_long tmp = kvtop(req_addr);
1860:
1861: if ((phy_buf + phy_len) != tmp) {
1862: if (wrong_dma_range(reqp, dm)) {
1863: if (reqp->dr_flag & DRIVER_BOUNCING)
1864: goto bounceit;
1865: return (0);
1866: }
1867:
1868: if (++dm >= &reqp->dm_chain[MAXDMAIO]) {
1869: ncr_tprint(reqp,"dmaok: DMA chain too long!\n");
1870: return (0);
1871: }
1872: dm->dm_count = 0;
1873: dm->dm_addr = tmp;
1874: }
1875: phy_buf = tmp;
1876: }
1877: }
1878: if (wrong_dma_range(reqp, dm)) {
1879: if (reqp->dr_flag & DRIVER_BOUNCING)
1880: goto bounceit;
1881: return (0);
1882: }
1883: reqp->dm_last = dm;
1884: return (1);
1885:
1886: bounceit:
1887: if ((reqp->bounceb = alloc_bounceb(reqp->xdata_len)) == NULL) {
1888: /*
1889: * If we can't get a bounce buffer, forget DMA
1890: */
1891: reqp->dr_flag &= ~DRIVER_BOUNCING;
1892: return(0);
1893: }
1894: /*
1895: * Initialize a single DMA-range containing the bounced request
1896: */
1897: dm = reqp->dm_cur = reqp->dm_last = reqp->dm_chain;
1898: dm->dm_addr = kvtop(reqp->bounceb);
1899: dm->dm_count = reqp->xdata_len;
1900: reqp->bouncerp = reqp->bounceb;
1901:
1902: return (1);
1903: }
1904: #endif /* REAL_DMA */
1905:
1906: static void
1907: run_main(sc)
1908: struct ncr_softc *sc;
1909: {
1910: int sps = splbio();
1911:
1912: if (!main_running) {
1913: /*
1914: * If shared resources are required, claim them
1915: * before entering 'scsi_main'. If we can't get them
1916: * now, assume 'run_main' will be called when the resource
1917: * becomes available.
1918: */
1919: if (!claimed_dma()) {
1920: splx(sps);
1921: return;
1922: }
1923: main_running = 1;
1924: splx(sps);
1925: scsi_main(sc);
1926: }
1927: else splx(sps);
1928: }
1929:
1930: /*
1931: * Prefix message with full target info.
1932: */
1933: static void
1934: ncr_tprint(SC_REQ *reqp, char *fmt, ...)
1935: {
1936: va_list ap;
1937:
1938: va_start(ap, fmt);
1.38.10.1! thorpej 1939: scsi_print_addr(reqp->xs->sc_link);
1.35 christos 1940: printf("%:", fmt, ap);
1.1 briggs 1941: va_end(ap);
1942: }
1943:
1944: /*
1945: * Prefix message with adapter info.
1946: */
1947: static void
1948: ncr_aprint(struct ncr_softc *sc, char *fmt, ...)
1949: {
1950: va_list ap;
1951:
1952: va_start(ap, fmt);
1.35 christos 1953: printf("%s: %:", sc->sc_dev.dv_xname, fmt, ap);
1.1 briggs 1954: va_end(ap);
1955: }
1956: /****************************************************************************
1957: * Start Debugging Functions *
1958: ****************************************************************************/
1959: static void
1.28 briggs 1960: show_data_sense(xs)
1.38.10.1! thorpej 1961: struct scsipi_xfer *xs;
1.1 briggs 1962: {
1963: u_char *p1, *p2;
1964: int i;
1965: int sz;
1966:
1967: p1 = (u_char *) xs->cmd;
1.38.10.1! thorpej 1968: p2 = (u_char *)&xs->sense.scsi_sense;
1.1 briggs 1969: if(*p2 == 0)
1970: return; /* No(n)sense */
1.35 christos 1971: printf("cmd[%d,%d]: ", xs->cmdlen, sz = command_size(*p1));
1.1 briggs 1972: for (i = 0; i < sz; i++)
1.35 christos 1973: printf("%x ", p1[i]);
1974: printf("\nsense: ");
1.38.10.1! thorpej 1975: for (i = 0; i < sizeof(xs->sense.scsi_sense); i++)
1.35 christos 1976: printf("%x ", p2[i]);
1977: printf("\n");
1.1 briggs 1978: }
1979:
1980: static void
1981: show_request(reqp, qtxt)
1982: SC_REQ *reqp;
1983: char *qtxt;
1984: {
1.35 christos 1985: printf("REQ-%s: %d %p[%ld] cmd[0]=%x S=%x M=%x R=%x resid=%d dr_flag=%x %s\n",
1.1 briggs 1986: qtxt, reqp->targ_id, reqp->xdata_ptr, reqp->xdata_len,
1987: reqp->xcmd.opcode, reqp->status, reqp->message,
1.16 briggs 1988: reqp->xs->error, reqp->xs->resid, reqp->dr_flag,
1989: reqp->link ? "L":"");
1.1 briggs 1990: if (reqp->status == SCSCHKC)
1991: show_data_sense(reqp->xs);
1992: }
1993:
1.3 briggs 1994: static char *sig_names[] = {
1995: "PAR", "SEL", "I/O", "C/D", "MSG", "REQ", "BSY", "RST",
1996: "ACK", "ATN", "LBSY", "PMATCH", "IRQ", "EPAR", "DREQ", "EDMA"
1997: };
1998:
1999: static void
2000: show_signals(dmstat, idstat)
2001: u_char dmstat, idstat;
2002: {
2003: u_short tmp, mask;
1.27 briggs 2004: int j, need_pipe;
1.3 briggs 2005:
2006: tmp = idstat | ((dmstat & 3) << 8);
1.35 christos 2007: printf("Bus signals (%02x/%02x): ", idstat, dmstat & 3);
1.3 briggs 2008: for (mask = 1, j = need_pipe = 0; mask <= tmp; mask <<= 1, j++) {
2009: if (tmp & mask)
1.35 christos 2010: printf("%s%s", need_pipe++ ? "|" : "", sig_names[j]);
1.3 briggs 2011: }
1.35 christos 2012: printf("\nDma status (%02x): ", dmstat);
1.3 briggs 2013: for (mask = 4, j = 10, need_pipe = 0; mask <= dmstat; mask <<= 1, j++) {
2014: if (dmstat & mask)
1.35 christos 2015: printf("%s%s", need_pipe++ ? "|" : "", sig_names[j]);
1.3 briggs 2016: }
1.35 christos 2017: printf("\n");
1.3 briggs 2018: }
2019:
1.27 briggs 2020: void
1.1 briggs 2021: scsi_show()
2022: {
2023: SC_REQ *tmp;
2024: int sps = splhigh();
1.3 briggs 2025: u_char idstat, dmstat;
1.29 briggs 2026: #ifdef DBG_PID
1.16 briggs 2027: int i;
1.29 briggs 2028: #endif
1.1 briggs 2029:
1.35 christos 2030: printf("scsi_show: scsi_main is%s running\n",
1.28 briggs 2031: main_running ? "" : " not");
1.1 briggs 2032: for (tmp = issue_q; tmp; tmp = tmp->next)
2033: show_request(tmp, "ISSUED");
2034: for (tmp = discon_q; tmp; tmp = tmp->next)
2035: show_request(tmp, "DISCONNECTED");
2036: if (connected)
2037: show_request(connected, "CONNECTED");
1.3 briggs 2038: idstat = GET_5380_REG(NCR5380_IDSTAT);
2039: dmstat = GET_5380_REG(NCR5380_DMSTAT);
2040: show_signals(dmstat, idstat);
1.1 briggs 2041: if (connected)
1.35 christos 2042: printf("phase = %d, ", connected->phase);
2043: printf("busy:%x, spl:%04x\n", busy, sps);
1.16 briggs 2044: #ifdef DBG_PID
1.17 briggs 2045: for (i=0; i<DBG_PID; i++)
1.35 christos 2046: printf("\t%d\t%s\n", i, last_hit[i]);
1.16 briggs 2047: #endif
1.1 briggs 2048:
2049: splx(sps);
2050: }
CVSweb <webmaster@jp.NetBSD.org>