si.c revision 1.1 1 /*
2 * Copyright (C) 1994 Adam Glass
3 * Copyright (C) 1993 Allen K. Briggs, Chris P. Caputo,
4 * Michael L. Finch, Bradley A. Grantham, and
5 * Lawrence A. Kesteloot
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed by the Alice Group.
19 * 4. The names of the Alice Group or any of its members may not be used
20 * to endorse or promote products derived from this software without
21 * specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE ALICE GROUP ``AS IS'' AND ANY EXPRESS OR
24 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
25 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26 * IN NO EVENT SHALL THE ALICE GROUP BE LIABLE FOR ANY DIRECT, INDIRECT,
27 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
28 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
32 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 *
34 * $Id: si.c,v 1.1 1994/02/23 08:28:56 glass Exp $
35 *
36 */
37
38 #define PSEUDO_DMA 1
39
40 static int pdebug=0;
41
42 #include <sys/types.h>
43 #include <sys/malloc.h>
44 #include <sys/param.h>
45 #include <sys/systm.h>
46 #include <sys/errno.h>
47 #include <sys/buf.h>
48 #include <sys/proc.h>
49 #include <sys/user.h>
50 #include <sys/device.h>
51
52 #include <machine/autoconf.h>
53 #include <machine/isr.h>
54 #include <machine/mtpr.h>
55 #include <machine/obio.h>
56
57 #include "../scsi/scsi_all.h"
58 #include "../scsi/scsi_debug.h"
59 #include "../scsi/scsiconf.h"
60 #include "scsi_defs.h"
61 #include "scsi_5380.h"
62
63 #define SCI_PHASE_DISC 0 /* sort of ... */
64 #define SCI_CLR_INTR(regs) {register int temp = regs->sci_iack;}
65 #define SCI_ACK(ptr,phase) (ptr)->sci_tcmd = (phase)
66 #define SCSI_TIMEOUT_VAL 10000000
67 #define WAIT_FOR_NOT_REQ(ptr) { \
68 int scsi_timeout = SCSI_TIMEOUT_VAL; \
69 while ( ((ptr)->sci_bus_csr & SCI_BUS_REQ) && \
70 ((ptr)->sci_bus_csr & SCI_BUS_REQ) && \
71 ((ptr)->sci_bus_csr & SCI_BUS_REQ) && \
72 (--scsi_timeout) ); \
73 if (!scsi_timeout) { \
74 printf("scsi timeout--WAIT_FOR_NOT_REQ---scsi.c, line %d.\n", __LINE__); \
75 goto scsi_timeout_error; \
76 } \
77 }
78 #define WAIT_FOR_REQ(ptr) { \
79 int scsi_timeout = SCSI_TIMEOUT_VAL; \
80 while ( (((ptr)->sci_bus_csr & SCI_BUS_REQ) == 0) && \
81 (((ptr)->sci_bus_csr & SCI_BUS_REQ) == 0) && \
82 (((ptr)->sci_bus_csr & SCI_BUS_REQ) == 0) && \
83 (--scsi_timeout) ); \
84 if (!scsi_timeout) { \
85 printf("scsi timeout--WAIT_FOR_REQ---scsi.c, line %d.\n", __LINE__); \
86 goto scsi_timeout_error; \
87 } \
88 }
89 #define WAIT_FOR_BSY(ptr) { \
90 int scsi_timeout = SCSI_TIMEOUT_VAL; \
91 while ( (((ptr)->sci_bus_csr & SCI_BUS_BSY) == 0) && \
92 (((ptr)->sci_bus_csr & SCI_BUS_BSY) == 0) && \
93 (((ptr)->sci_bus_csr & SCI_BUS_BSY) == 0) && \
94 (--scsi_timeout) ); \
95 if (!scsi_timeout) { \
96 printf("scsi timeout--WAIT_FOR_BSY---scsi.c, line %d.\n", __LINE__); \
97 goto scsi_timeout_error; \
98 } \
99 }
100
101 #ifdef DDB
102 int Debugger();
103 #else
104 #define Debugger() panic("Should call Debugger here (sun3/dev/scsi.c).")
105 #endif
106
107 struct ncr5380_softc {
108 struct device sc_dev;
109 void *sc_regs;
110 int sc_adapter_target;
111 struct scsi_link sc_link;
112 };
113
114 #if 0
115 In your dreams dude...
116 /* From Guide to Mac II family hardware, p. 137 */
117 static volatile sci_padded_regmap_t *ncr = (sci_regmap_t *) 0x50F10000;
118 static volatile long *sci_4byte_addr= (long *) 0x50F06000;
119 static volatile u_char *sci_1byte_addr=(u_char *) 0x50F12000;
120 #endif
121
122 static unsigned int ncr5380_adapter_info(struct ncr5380_softc *ncr5380);
123 static void ncr5380_minphys(struct buf *bp);
124 static int ncr5380_scsi_cmd(struct scsi_xfer *xs);
125
126 static int ncr5380_show_scsi_cmd(struct scsi_xfer *xs);
127 static int ncr5380_reset_target(int adapter, int target);
128 static int ncr5380_poll(int adapter, int timeout);
129 static int ncr5380_send_cmd(struct scsi_xfer *xs);
130
131 extern void ncr5380_intr(int adapter);
132 extern void spinwait(int);
133
134 static void delay(int);
135
136 static int scsi_gen(int adapter, int id, int lun,
137 struct scsi_generic *cmd, int cmdlen,
138 void *databuf, int datalen);
139 static int scsi_group0(int adapter, int id, int lun,
140 int opcode, int addr, int len,
141 int flags, caddr_t databuf, int datalen);
142
143 static char scsi_name[] = "si";
144
145 struct scsi_adapter ncr5380_switch = {
146 ncr5380_scsi_cmd, /* scsi_cmd() */
147 ncr5380_minphys, /* scsi_minphys() */
148 0, /* open_target_lu() */
149 0, /* close_target_lu() */
150 ncr5380_adapter_info, /* adapter_info() */
151 scsi_name, /* name */
152 {0, 0} /* spare[3] */
153 };
154
155 /* This is copied from julian's bt driver */
156 /* "so we have a default dev struct for our link struct." */
157 struct scsi_device ncr_dev = {
158 NULL, /* Use default error handler. */
159 NULL, /* have a queue, served by this (?) */
160 NULL, /* have no async handler. */
161 NULL, /* Use default "done" routine. */
162 "si",
163 0,
164 0, 0
165 };
166
167 extern int matchbyname();
168 static int ncrprobe();
169 static void ncrattach();
170
171 struct cfdriver ncrcd =
172 { NULL, "si", ncrprobe, ncrattach,
173 DV_DULL, sizeof(struct ncr5380_softc), NULL, 0 };
174
175 static int
176 ncr_print(aux, name)
177 void *aux;
178 char *name;
179 {
180 /* printf("%s: (sc_link = 0x%x)", name, (int) aux);
181 return UNCONF;*/
182 }
183
184 static int
185 ncrprobe(parent, cf, aux)
186 struct device *parent;
187 struct cfdata *cf;
188 void *aux;
189 {
190 caddr_t si_addr;
191 struct obio_cf_loc *obio_loc = (struct obio_cf_loc *) CFDATA_LOC(cf);
192
193 si_addr = OBIO_DEFAULT_PARAM(caddr_t, obio_loc->obio_addr, OBIO_NCR_SCSI);
194 return /* !obio_probe_byte(si_addr)*/ 1;
195 }
196
197 static void
198 ncrattach(parent, self, aux)
199 struct device *parent, *self;
200 void *aux;
201 {
202 caddr_t dvma_malloc(), si_addr;
203 int level, ncr_intr(), unit = DEVICE_UNIT(self);
204 struct ncr5380_softc *ncr5380 = (struct ncr5380_softc *) self;
205 struct obio_cf_loc *obio_loc = OBIO_LOC(self);
206
207 si_addr = OBIO_DEFAULT_PARAM(caddr_t, obio_loc->obio_addr, OBIO_NCR_SCSI);
208 ncr5380->sc_regs = (sci_regmap_t *)
209 obio_alloc(si_addr, OBIO_AMD_ETHER_SIZE, OBIO_WRITE);
210
211 level = OBIO_DEFAULT_PARAM(int, obio_loc->obio_level, 3);
212
213 ncr5380->sc_link.scsibus = unit;
214 ncr5380->sc_link.adapter_targ = 7;
215 ncr5380->sc_link.adapter = &ncr5380_switch;
216 ncr5380->sc_link.device = &ncr_dev;
217
218 obio_print(si_addr, level);
219 printf("\n");
220
221 config_found(self, &(ncr5380->sc_link), ncr_print);
222 }
223
224 static unsigned int
225 ncr5380_adapter_info(struct ncr5380_softc *ncr5380)
226 {
227 return 1;
228 }
229
230 #define MIN_PHYS 65536 /*BARF!!!!*/
231 static void
232 ncr5380_minphys(struct buf *bp)
233 {
234 if (bp->b_bcount > MIN_PHYS) {
235 printf("Uh-oh... ncr5380_minphys setting bp->b_bcount = %x.\n", MIN_PHYS);
236 bp->b_bcount = MIN_PHYS;
237 }
238 }
239 #undef MIN_PHYS
240
241 static int
242 ncr5380_scsi_cmd(struct scsi_xfer *xs)
243 {
244 int flags, s, r;
245
246 flags = xs->flags;
247 if (xs->bp) flags |= (SCSI_NOSLEEP);
248 if ( flags & ITSDONE ) {
249 printf("Already done?");
250 xs->flags &= ~ITSDONE;
251 }
252 if ( ! ( flags & INUSE ) ) {
253 printf("Not in use?");
254 xs->flags |= INUSE;
255 }
256
257 if ( flags & SCSI_RESET ) {
258 printf("flags & SCSIRESET.\n");
259 if ( ! ( flags & SCSI_NOSLEEP ) ) {
260 s = splbio();
261 ncr5380_reset_target(xs->sc_link->scsibus, xs->sc_link->target);
262 splx(s);
263 return(SUCCESSFULLY_QUEUED);
264 } else {
265 ncr5380_reset_target(xs->sc_link->scsibus, xs->sc_link->target);
266 if (ncr5380_poll(xs->sc_link->scsibus, xs->timeout)) {
267 return (HAD_ERROR);
268 }
269 return (COMPLETE);
270 }
271 }
272 /*
273 * OK. Now that that's over with, let's pack up that
274 * SCSI puppy and send it off. If we can, we'll just
275 * queue and go; otherwise, we'll wait for the command
276 * to finish.
277 if ( ! ( flags & SCSI_NOSLEEP ) ) {
278 s = splbio();
279 ncr5380_send_cmd(xs);
280 splx(s);
281 return(SUCCESSFULLY_QUEUED);
282 }
283 */
284
285 r = ncr5380_send_cmd(xs);
286 xs->flags |= ITSDONE;
287 scsi_done(xs);
288 switch(r) {
289 case COMPLETE: case SUCCESSFULLY_QUEUED:
290 r = SUCCESSFULLY_QUEUED;
291 if (xs->flags&SCSI_NOMASK)
292 r = COMPLETE;
293 break;
294 default:
295 break;
296 }
297 return r;
298 /*
299 do {
300 if (ncr5380_poll(xs->sc_link->scsibus, xs->timeout)) {
301 if ( ! ( xs->flags & SCSI_SILENT ) )
302 printf("cmd fail.\n");
303 cmd_cleanup
304 xs->error = XS_DRIVER_STUFFUP;
305 splx(s);
306 }
307 } while ( ! ( xs->flags & ITSDONE ) );
308 */
309 }
310
311 static int
312 ncr5380_show_scsi_cmd(struct scsi_xfer *xs)
313 {
314 u_char *b = (u_char *) xs->cmd;
315 int i = 0;
316
317 if ( ! ( xs->flags & SCSI_RESET ) ) {
318 printf("si(%d:%d:%d)-",
319 xs->sc_link->scsibus, xs->sc_link->target, xs->sc_link->lun);
320 while (i < xs->cmdlen) {
321 if (i) printf(",");
322 printf("%x",b[i++]);
323 }
324 printf("-\n");
325 } else {
326 printf("si(%d:%d:%d)-RESET-\n",
327 xs->sc_link->scsibus, xs->sc_link->target, xs->sc_link->lun);
328 }
329 }
330
331 /*
332 * Actual chip control.
333 */
334
335 static void
336 delay(int timeo)
337 {
338 int len;
339 for (len=0;len<timeo*2;len++);
340 }
341
342 extern void
343 spinwait(int ms)
344 {
345 while (ms--)
346 delay(500);
347 }
348
349 extern void
350 ncr5380_intr(int adapter)
351 {
352 register struct ncr5380_softc *ncr5380 = ncrcd.cd_devs[adapter];
353 register volatile sci_regmap_t *regs = ncr5380->sc_regs;
354
355 SCI_CLR_INTR(regs);
356 regs->sci_mode = 0x00;
357 }
358
359 #if 0
360 extern int
361 scsi_irq_intr(void)
362 {
363 register volatile sci_regmap_t *regs = ncr;
364
365 /* if (regs->sci_csr != SCI_CSR_PHASE_MATCH)
366 printf("scsi_irq_intr called (not just phase match -- "
367 "csr = 0x%x, bus_csr = 0x%x).\n",
368 regs->sci_csr, regs->sci_bus_csr);
369 ncr5380_intr(0); */
370 return 1;
371 }
372 #endif
373
374 #if 0
375 extern int
376 scsi_drq_intr(void)
377 {
378 /* printf("scsi_drq_intr called.\n"); */
379 /* ncr5380_intr(0); */
380 return 1;
381 }
382 #endif
383
384 static int
385 ncr5380_reset_target(int adapter, int target)
386 {
387 register struct ncr5380_softc *ncr5380 = ncrcd.cd_devs[adapter];
388 register volatile sci_regmap_t *regs = ncr5380->sc_regs;
389 int dummy;
390
391 regs->sci_icmd = SCI_ICMD_TEST;
392 regs->sci_icmd = SCI_ICMD_TEST | SCI_ICMD_RST;
393 delay(2500);
394 regs->sci_icmd = 0;
395
396 regs->sci_mode = 0;
397 regs->sci_tcmd = SCI_PHASE_DISC;
398 regs->sci_sel_enb = 0;
399
400 SCI_CLR_INTR(regs);
401 SCI_CLR_INTR(regs);
402 }
403
404 static int
405 ncr5380_poll(int adapter, int timeout)
406 {
407 }
408
409 static int
410 ncr5380_send_cmd(struct scsi_xfer *xs)
411 {
412 int s;
413 int sense;
414
415 /* ncr5380_show_scsi_cmd(xs); */
416 s = splbio();
417 sense = scsi_gen( xs->sc_link->scsibus, xs->sc_link->target,
418 xs->sc_link->lun, xs->cmd, xs->cmdlen,
419 xs->data, xs->datalen );
420 splx(s);
421 if (sense) {
422 switch (sense) {
423 case 0x02: /* Check condition */
424 /* printf("check cond. target %d.\n", xs->targ);*/
425 s = splbio();
426 scsi_group0(xs->sc_link->scsibus,
427 xs->sc_link->target,
428 xs->sc_link->lun,
429 0x3, 0x0,
430 sizeof(struct scsi_sense_data),
431 0, (caddr_t) &(xs->sense),
432 sizeof(struct scsi_sense_data));
433 splx(s);
434 xs->error = XS_SENSE;
435 return HAD_ERROR;
436 case 0x08: /* Busy */
437 xs->error = XS_BUSY;
438 return HAD_ERROR;
439 default:
440 xs->error = XS_DRIVER_STUFFUP;
441 return HAD_ERROR;
442 }
443 }
444 xs->error = XS_NOERROR;
445 return (COMPLETE);
446 }
447
448 static int
449 select_target(register volatile sci_regmap_t *regs,
450 u_char myid, u_char tid, int with_atn)
451 {
452 register u_char bid, icmd;
453 int ret = SCSI_RET_RETRY;
454
455 if ((regs->sci_bus_csr & (SCI_BUS_BSY|SCI_BUS_SEL)) &&
456 (regs->sci_bus_csr & (SCI_BUS_BSY|SCI_BUS_SEL)) &&
457 (regs->sci_bus_csr & (SCI_BUS_BSY|SCI_BUS_SEL)))
458 return ret;
459
460 /* for our purposes.. */
461 myid = 1 << myid;
462 tid = 1 << tid;
463
464 regs->sci_sel_enb = 0; /*myid; we don't want any interrupts. */
465
466 regs->sci_odata = myid;
467 regs->sci_mode = SCI_MODE_ARB;
468 /* regs->sci_mode |= SCI_MODE_ARB; */
469 /* AIP might not set if BSY went true after we checked */
470 for (bid = 0; bid < 20; bid++) /* 20usec circa */
471 if (regs->sci_icmd & SCI_ICMD_AIP)
472 break;
473 if ((regs->sci_icmd & SCI_ICMD_AIP) == 0) {
474 goto lost;
475 }
476
477 spinwait(2); /* 2.2us arb delay */
478
479 if (regs->sci_icmd & SCI_ICMD_LST) {
480 goto lost;
481 }
482
483 regs->sci_mode &= ~SCI_MODE_PAR_CHK;
484 bid = regs->sci_data;
485
486 if ((bid & ~myid) > myid) {
487 goto lost;
488 }
489 if (regs->sci_icmd & SCI_ICMD_LST) {
490 goto lost;
491 }
492
493 /* Won arbitration, enter selection phase now */
494 icmd = regs->sci_icmd & ~(SCI_ICMD_DIFF|SCI_ICMD_TEST);
495 icmd |= (with_atn ? (SCI_ICMD_SEL|SCI_ICMD_ATN) : SCI_ICMD_SEL);
496 icmd |= SCI_ICMD_BSY;
497 regs->sci_icmd = icmd;
498
499 if (regs->sci_icmd & SCI_ICMD_LST) {
500 goto nosel;
501 }
502
503 /* XXX a target that violates specs might still drive the bus XXX */
504 /* XXX should put our id out, and after the delay check nothi XXX */
505 /* XXX ng else is out there. XXX */
506
507 delay(0);
508
509 regs->sci_tcmd = 0;
510 regs->sci_odata = myid | tid;
511 regs->sci_sel_enb = 0;
512
513 /* regs->sci_mode &= ~SCI_MODE_ARB; 2 deskew delays, too */
514 regs->sci_mode = 0; /* 2 deskew delays, too */
515
516 icmd |= SCI_ICMD_DATA;
517 icmd &= ~(SCI_ICMD_BSY);
518
519 regs->sci_icmd = icmd;
520
521 /* bus settle delay, 400ns */
522 delay(2); /* too much (was 2) ? */
523
524 /* regs->sci_mode |= SCI_MODE_PAR_CHK; */
525
526 {
527 register int timeo = 2500;/* 250 msecs in 100 usecs chunks */
528 while ((regs->sci_bus_csr & SCI_BUS_BSY) == 0) {
529 if (--timeo > 0) {
530 delay(100);
531 } else {
532 goto nodev;
533 }
534 }
535 }
536
537 icmd &= ~(SCI_ICMD_DATA|SCI_ICMD_SEL);
538 regs->sci_icmd = icmd;
539 /* regs->sci_sel_enb = myid;*/ /* looks like we should NOT have it */
540 return SCSI_RET_SUCCESS;
541 nodev:
542 ret = SCSI_RET_DEVICE_DOWN;
543 regs->sci_sel_enb = myid;
544 nosel:
545 icmd &= ~(SCI_ICMD_DATA|SCI_ICMD_SEL|SCI_ICMD_ATN);
546 regs->sci_icmd = icmd;
547 lost:
548 regs->sci_mode = 0;
549
550 return ret;
551 }
552
553 sci_data_out(regs, phase, count, data)
554 register sci_regmap_t *regs;
555 unsigned char *data;
556 {
557 register unsigned char icmd;
558 register int cnt=0;
559
560 /* ..checks.. */
561
562 icmd = regs->sci_icmd & ~(SCI_ICMD_DIFF|SCI_ICMD_TEST);
563 loop:
564 if (SCI_CUR_PHASE(regs->sci_bus_csr) != phase)
565 return cnt;
566
567 WAIT_FOR_REQ(regs);
568 icmd |= SCI_ICMD_DATA;
569 regs->sci_icmd = icmd;
570 regs->sci_odata = *data++;
571 icmd |= SCI_ICMD_ACK;
572 regs->sci_icmd = icmd;
573
574 icmd &= ~(SCI_ICMD_DATA|SCI_ICMD_ACK);
575 WAIT_FOR_NOT_REQ(regs);
576 regs->sci_icmd = icmd;
577 ++cnt;
578 if (--count > 0)
579 goto loop;
580 scsi_timeout_error:
581 return cnt;
582 }
583
584 sci_data_in(regs, phase, count, data)
585 register sci_regmap_t *regs;
586 unsigned char *data;
587 {
588 register unsigned char icmd;
589 register int cnt=0;
590
591 /* ..checks.. */
592
593 icmd = regs->sci_icmd & ~(SCI_ICMD_DIFF|SCI_ICMD_TEST);
594
595 loop:
596 if (SCI_CUR_PHASE(regs->sci_bus_csr) != phase)
597 return cnt;
598
599 WAIT_FOR_REQ(regs);
600 *data++ = regs->sci_data;
601 icmd |= SCI_ICMD_ACK;
602 regs->sci_icmd = icmd;
603
604 icmd &= ~SCI_ICMD_ACK;
605 WAIT_FOR_NOT_REQ(regs);
606 regs->sci_icmd = icmd;
607 ++cnt;
608 if (--count > 0)
609 goto loop;
610
611 scsi_timeout_error:
612 return cnt;
613 }
614
615 static int
616 command_transfer(register volatile sci_regmap_t *regs,
617 int maxlen, u_char *data, u_char *status, u_char *msg)
618 {
619 int xfer=0, phase;
620
621 /* printf("command_transfer called for 0x%x.\n", *data); */
622
623 regs->sci_icmd = 0;
624
625 while (1) {
626
627 WAIT_FOR_REQ(regs);
628
629 phase = SCI_CUR_PHASE(regs->sci_bus_csr);
630
631 switch (phase) {
632 case SCSI_PHASE_CMD:
633 SCI_ACK(regs,SCSI_PHASE_CMD);
634 xfer += sci_data_out(regs, SCSI_PHASE_CMD,
635 maxlen, data);
636 return xfer;
637 case SCSI_PHASE_DATA_IN:
638 printf("Data in phase in command_transfer?\n");
639 return 0;
640 case SCSI_PHASE_DATA_OUT:
641 printf("Data out phase in command_transfer?\n");
642 return 0;
643 case SCSI_PHASE_STATUS:
644 SCI_ACK(regs,SCSI_PHASE_STATUS);
645 printf("status in command_transfer.\n");
646 sci_data_in(regs, SCSI_PHASE_STATUS,
647 1, status);
648 break;
649 case SCSI_PHASE_MESSAGE_IN:
650 SCI_ACK(regs,SCSI_PHASE_MESSAGE_IN);
651 printf("msgin in command_transfer.\n");
652 sci_data_in(regs, SCSI_PHASE_MESSAGE_IN,
653 1, msg);
654 break;
655 case SCSI_PHASE_MESSAGE_OUT:
656 SCI_ACK(regs,SCSI_PHASE_MESSAGE_OUT);
657 sci_data_out(regs, SCSI_PHASE_MESSAGE_OUT,
658 1, msg);
659 break;
660 default:
661 printf("Unexpected phase 0x%x in "
662 "command_transfer().\n", phase);
663 scsi_timeout_error:
664 return xfer;
665 break;
666 }
667 }
668 }
669
670 static int
671 data_transfer(register volatile sci_regmap_t *regs,
672 int maxlen, u_char *data, u_char *status, u_char *msg)
673 {
674 int retlen = 0, xfer, phase;
675
676 regs->sci_icmd = 0;
677
678 *status = 0;
679
680 while (1) {
681
682 WAIT_FOR_REQ(regs);
683
684 phase = SCI_CUR_PHASE(regs->sci_bus_csr);
685
686 switch (phase) {
687 case SCSI_PHASE_CMD:
688 printf("Command phase in data_transfer().\n");
689 return retlen;
690 case SCSI_PHASE_DATA_IN:
691 SCI_ACK(regs,SCSI_PHASE_DATA_IN);
692 #if PSEUDO_DMA
693 xfer = sci_pdma_in(regs, SCSI_PHASE_DATA_IN,
694 maxlen, data);
695 #else
696 xfer = sci_data_in(regs, SCSI_PHASE_DATA_IN,
697 maxlen, data);
698 #endif
699 retlen += xfer;
700 maxlen -= xfer;
701 break;
702 case SCSI_PHASE_DATA_OUT:
703 SCI_ACK(regs,SCSI_PHASE_DATA_OUT);
704 #if PSEUDO_DMA
705 xfer = sci_pdma_out(regs, SCSI_PHASE_DATA_OUT,
706 maxlen, data);
707 #else
708 xfer = sci_data_out(regs, SCSI_PHASE_DATA_OUT,
709 maxlen, data);
710 #endif
711 retlen += xfer;
712 maxlen -= xfer;
713 break;
714 case SCSI_PHASE_STATUS:
715 SCI_ACK(regs,SCSI_PHASE_STATUS);
716 sci_data_in(regs, SCSI_PHASE_STATUS,
717 1, status);
718 break;
719 case SCSI_PHASE_MESSAGE_IN:
720 SCI_ACK(regs,SCSI_PHASE_MESSAGE_IN);
721 sci_data_in(regs, SCSI_PHASE_MESSAGE_IN,
722 1, msg);
723 if (*msg == 0) {
724 return retlen;
725 } else {
726 printf( "message 0x%x in "
727 "data_transfer.\n", *msg);
728 }
729 break;
730 case SCSI_PHASE_MESSAGE_OUT:
731 SCI_ACK(regs,SCSI_PHASE_MESSAGE_OUT);
732 sci_data_out(regs, SCSI_PHASE_MESSAGE_OUT,
733 1, msg);
734 break;
735 default:
736 printf( "Unexpected phase 0x%x in "
737 "data_transfer().\n", phase);
738 scsi_timeout_error:
739 return retlen;
740 break;
741 }
742 }
743 }
744
745 static int
746 scsi_request(register volatile sci_regmap_t *regs,
747 int target, int lun, u_char *cmd, int cmdlen,
748 char *databuf, int datalen, int *sent, int *ret)
749 {
750 /* Returns 0 on success, -1 on internal error, or the status byte */
751 int cmd_bytes_sent, r;
752 u_char stat, msg, c;
753
754 *sent = 0;
755
756 if ( ( r = select_target(regs, 7, target, 1) ) != SCSI_RET_SUCCESS) {
757 *ret = r;
758 SCI_CLR_INTR(regs);
759 switch (r) {
760 case SCSI_RET_RETRY:
761 return 0x08;
762 default:
763 printf("select_target(target %d, lun %d) failed(%d).\n",
764 target, lun, r);
765 case SCSI_RET_DEVICE_DOWN:
766 return -1;
767 }
768 }
769
770 c = 0x80 | lun;
771
772 if ((cmd_bytes_sent = command_transfer(regs, cmdlen,
773 (u_char *) cmd, &stat, &c))
774 != cmdlen) {
775 SCI_CLR_INTR(regs);
776 *ret = SCSI_RET_COMMAND_FAIL;
777 printf("Data underrun sending CCB (%d bytes of %d, sent).\n",
778 cmd_bytes_sent, cmdlen);
779 return -1;
780 }
781
782 *sent=data_transfer(regs, datalen, (u_char *)databuf,
783 &stat, &msg);
784
785 *ret = 0;
786
787 return stat;
788 }
789
790 static int
791 scsi_gen(int adapter, int id, int lun, struct scsi_generic *cmd,
792 int cmdlen, void *databuf, int datalen)
793 {
794 register struct ncr5380_softc *ncr5380 = ncrcd.cd_devs[adapter];
795 register volatile sci_regmap_t *regs = ncr5380->sc_regs;
796 int i,j,sent,ret;
797
798 cmd->bytes[0] = ((u_char) lun << 5);
799
800 i = scsi_request(regs, id, lun, (u_char *) cmd, cmdlen,
801 databuf, datalen, &sent, &ret);
802
803 return i;
804 }
805
806 static int
807 scsi_group0(int adapter, int id, int lun, int opcode, int addr, int len,
808 int flags, caddr_t databuf, int datalen)
809 {
810 register struct ncr5380_softc *ncr5380 = ncrcd.cd_devs[adapter];
811 register volatile sci_regmap_t *regs = ncr5380->sc_regs;
812 unsigned char cmd[6];
813 int i,j,sent,ret;
814
815 cmd[0] = opcode; /* Operation code */
816 cmd[1] = (lun << 5) | ((addr >> 16) & 0x1F); /* Lun & MSB of addr */
817 cmd[2] = (addr >> 8) & 0xFF; /* addr */
818 cmd[3] = addr & 0xFF; /* LSB of addr */
819 cmd[4] = len; /* Allocation length */
820 cmd[5] = flags; /* Link/Flag */
821
822 i = scsi_request(regs, id, lun, cmd, 6, databuf, datalen, &sent, &ret);
823
824 return i;
825 }
826
827 /* pseudo-dma action */
828
829 #if PSEUDO_DMA
830
831 #define TIMEOUT 1000000
832 #define READY(poll) \
833 i = TIMEOUT; \
834 while ((regs->sci_csr & (SCI_CSR_DREQ|SCI_CSR_PHASE_MATCH)) \
835 !=(SCI_CSR_DREQ|SCI_CSR_PHASE_MATCH)) \
836 if ( !(regs->sci_csr & SCI_CSR_PHASE_MATCH) \
837 || !(regs->sci_bus_csr & SCI_BUS_BSY) \
838 || (i-- < 0) ) { \
839 printf("scsi.c: timeout counter = %d, len = %d count=%d (count-len %d).\n", \
840 i, len,count,count-len); \
841 printf("pdebug = %d, 1=out, 2=in",pdebug); \
842 /*dump_regs();*/ \
843 if (poll && !(regs->sci_csr & SCI_CSR_PHASE_MATCH)) { \
844 regs->sci_icmd &= ~SCI_ICMD_DATA; \
845 len--; \
846 } else { \
847 regs->sci_mode &= ~SCI_MODE_DMA; \
848 } \
849 return count-len; \
850 }
851
852 #define W1 *byte_data = *data++
853 #define W4 W1; W1; W1; W1;
854 /*#define W4 *long_data = *((long*)data)++*/
855
856 sci_pdma_out(regs, phase, count, data)
857 register volatile sci_regmap_t *regs;
858 int phase;
859 int count;
860 u_char *data;
861 {
862 register volatile u_char *byte_data = (u_char *)®s->sci_data;
863 register int len = count, i;
864
865 pdebug=1;
866
867 if (count < 128)
868 return sci_data_out(regs, phase, count, data);
869
870 WAIT_FOR_BSY(regs);
871 regs->sci_mode |= SCI_MODE_DMA;
872 regs->sci_icmd |= SCI_ICMD_DATA;
873 regs->sci_dma_send = 0;
874
875 while ( len >= 64 ) {
876 READY(1); W1; READY(1); W1; READY(1); W1; READY(1); W1;
877 READY(1);
878 W4;W4;W4; W4;W4;W4;W4; W4;W4;W4;W4; W4;W4;W4;W4;
879 len -= 64;
880 }
881 while (len) {
882 READY(1);
883 W1;
884 len--;
885 }
886 i = TIMEOUT;
887 while ( ((regs->sci_csr & (SCI_CSR_DREQ|SCI_CSR_PHASE_MATCH))
888 == SCI_CSR_PHASE_MATCH) && --i);
889 if (!i)
890 printf("scsi.c:%d: timeout waiting for SCI_CSR_DREQ.\n", __LINE__);
891 *byte_data = 0;
892 scsi_timeout_error:
893 regs->sci_mode &= ~SCI_MODE_DMA;
894 return count-len;
895 }
896
897 #undef W1
898 #undef W4
899
900
901 #define R1 *data++ = *byte_data
902 #define R4 R1; R1; R1; R1;
903 /*#define R4 (*((long *)data)++ = *long_data*/
904 sci_pdma_in(regs, phase, count, data)
905 register volatile sci_regmap_t *regs;
906 int phase;
907 int count;
908 u_char *data;
909 {
910 register volatile u_char *byte_data = (u_char *) ®s->sci_data;
911 register int len = count, i;
912
913 pdebug=2;
914 if (count < 128)
915 return sci_data_in(regs, phase, count, data);
916
917 /* printf("Called sci_pdma_in(0x%x, 0x%x, %d, 0x%x.\n", regs, phase, count, data); */
918
919 WAIT_FOR_BSY(regs);
920 regs->sci_mode |= SCI_MODE_DMA;
921 regs->sci_icmd |= SCI_ICMD_DATA;
922 regs->sci_irecv = 0;
923
924 while (len >= 1024) {
925 READY(0);
926 R4;R4;R4;R4; R4;R4;R4;R4; R4;R4;R4;R4; R4;R4;R4;R4;
927 R4;R4;R4;R4; R4;R4;R4;R4; R4;R4;R4;R4; R4;R4;R4;R4; /* 128 */
928 READY(0);
929 R4;R4;R4;R4; R4;R4;R4;R4; R4;R4;R4;R4; R4;R4;R4;R4;
930 R4;R4;R4;R4; R4;R4;R4;R4; R4;R4;R4;R4; R4;R4;R4;R4; /* 256 */
931 READY(0);
932 R4;R4;R4;R4; R4;R4;R4;R4; R4;R4;R4;R4; R4;R4;R4;R4;
933 R4;R4;R4;R4; R4;R4;R4;R4; R4;R4;R4;R4; R4;R4;R4;R4; /* 384 */
934 READY(0);
935 R4;R4;R4;R4; R4;R4;R4;R4; R4;R4;R4;R4; R4;R4;R4;R4;
936 R4;R4;R4;R4; R4;R4;R4;R4; R4;R4;R4;R4; R4;R4;R4;R4; /* 512 */
937 READY(0);
938 R4;R4;R4;R4; R4;R4;R4;R4; R4;R4;R4;R4; R4;R4;R4;R4;
939 R4;R4;R4;R4; R4;R4;R4;R4; R4;R4;R4;R4; R4;R4;R4;R4; /* 640 */
940 READY(0);
941 R4;R4;R4;R4; R4;R4;R4;R4; R4;R4;R4;R4; R4;R4;R4;R4;
942 R4;R4;R4;R4; R4;R4;R4;R4; R4;R4;R4;R4; R4;R4;R4;R4; /* 768 */
943 READY(0);
944 R4;R4;R4;R4; R4;R4;R4;R4; R4;R4;R4;R4; R4;R4;R4;R4;
945 R4;R4;R4;R4; R4;R4;R4;R4; R4;R4;R4;R4; R4;R4;R4;R4; /* 896 */
946 READY(0);
947 R4;R4;R4;R4; R4;R4;R4;R4; R4;R4;R4;R4; R4;R4;R4;R4;
948 R4;R4;R4;R4; R4;R4;R4;R4; R4;R4;R4;R4; R4;R4;R4;R4; /*1024 */
949 len -= 1024;
950 }
951 while (len >= 128) {
952 READY(0);
953 R4;R4;R4;R4; R4;R4;R4;R4; R4;R4;R4;R4; R4;R4;R4;R4;
954 R4;R4;R4;R4; R4;R4;R4;R4; R4;R4;R4;R4; R4;R4;R4;R4; /* 128 */
955 len -= 128;
956 }
957 while (len) {
958 READY(0);
959 R1;
960 len--;
961 }
962 scsi_timeout_error:
963 regs->sci_mode &= ~SCI_MODE_DMA;
964 return count - len;
965 }
966 #undef R4
967 #undef R1
968 #endif
969