si.c revision 1.2 1 /*
2 * Copyright (C) 1994 Adam Glass, Gordon W. Ross
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.2 1994/05/13 15:01:39 gwr Exp $
35 */
36
37 #define DEBUG
38
39 #ifdef DEBUG
40 #define STATIC /* let DDB see the symbols */
41 #else
42 #define STATIC static
43 #endif
44
45 /* XXX - Need to add support for real DMA. -gwr */
46 /* #define PSEUDO_DMA 1 (broken) */
47
48 STATIC int si_debug=0;
49
50 #include <sys/types.h>
51 #include <sys/malloc.h>
52 #include <sys/param.h>
53 #include <sys/systm.h>
54 #include <sys/errno.h>
55 #include <sys/buf.h>
56 #include <sys/proc.h>
57 #include <sys/user.h>
58 #include <sys/device.h>
59
60 #include <machine/autoconf.h>
61 #include <machine/isr.h>
62 #include <machine/mtpr.h>
63 #include <machine/obio.h>
64
65 #include <scsi/scsi_all.h>
66 #include <scsi/scsi_debug.h>
67 #include <scsi/scsiconf.h>
68
69 #include "scsi_defs.h"
70 #include "scsi_5380.h"
71
72 #define SCI_PHASE_DISC 0 /* sort of ... */
73 #define SCI_CLR_INTR(regs) {register int temp = regs->sci_iack;}
74 #define SCI_ACK(ptr,phase) (ptr)->sci_tcmd = (phase)
75 #define SCSI_TIMEOUT_VAL 10000000
76 #define WAIT_FOR_NOT_REQ(ptr) { \
77 int scsi_timeout = SCSI_TIMEOUT_VAL; \
78 while ( ((ptr)->sci_bus_csr & SCI_BUS_REQ) && \
79 ((ptr)->sci_bus_csr & SCI_BUS_REQ) && \
80 ((ptr)->sci_bus_csr & SCI_BUS_REQ) && \
81 (--scsi_timeout) ); \
82 if (!scsi_timeout) { \
83 printf("scsi timeout--WAIT_FOR_NOT_REQ---%s, line %d.\n", \
84 __FILE__, __LINE__); \
85 goto scsi_timeout_error; \
86 } \
87 }
88 #define WAIT_FOR_REQ(ptr) { \
89 int scsi_timeout = SCSI_TIMEOUT_VAL; \
90 while ( (((ptr)->sci_bus_csr & SCI_BUS_REQ) == 0) && \
91 (((ptr)->sci_bus_csr & SCI_BUS_REQ) == 0) && \
92 (((ptr)->sci_bus_csr & SCI_BUS_REQ) == 0) && \
93 (--scsi_timeout) ); \
94 if (!scsi_timeout) { \
95 printf("scsi timeout--WAIT_FOR_REQ---%s, line %d.\n", \
96 __FILE__, __LINE__); \
97 goto scsi_timeout_error; \
98 } \
99 }
100 #define WAIT_FOR_BSY(ptr) { \
101 int scsi_timeout = SCSI_TIMEOUT_VAL; \
102 while ( (((ptr)->sci_bus_csr & SCI_BUS_BSY) == 0) && \
103 (((ptr)->sci_bus_csr & SCI_BUS_BSY) == 0) && \
104 (((ptr)->sci_bus_csr & SCI_BUS_BSY) == 0) && \
105 (--scsi_timeout) ); \
106 if (!scsi_timeout) { \
107 printf("scsi timeout--WAIT_FOR_BSY---%s, line %d.\n", \
108 __FILE__, __LINE__); \
109 goto scsi_timeout_error; \
110 } \
111 }
112
113 #ifdef DDB
114 int Debugger();
115 #else
116 #define Debugger() panic("Should call Debugger here %s:%d", \
117 __FILE__, __LINE__)
118 #endif
119
120 struct ncr5380_softc {
121 struct device sc_dev;
122 void *sc_regs;
123 int sc_adapter_target;
124 struct scsi_link sc_link;
125 };
126
127 STATIC u_int ncr5380_adapter_info(struct ncr5380_softc *ncr5380);
128 STATIC void ncr5380_minphys(struct buf *bp);
129 STATIC int ncr5380_scsi_cmd(struct scsi_xfer *xs);
130
131 STATIC int ncr5380_show_scsi_cmd(struct scsi_xfer *xs);
132 STATIC int ncr5380_reset_target(int adapter, int target);
133 STATIC int ncr5380_poll(int adapter, int timeout);
134 STATIC int ncr5380_send_cmd(struct scsi_xfer *xs);
135
136 void ncr5380_intr(int adapter);
137
138 STATIC int si_generic(int adapter, int id, int lun,
139 struct scsi_generic *cmd, int cmdlen,
140 void *databuf, int datalen);
141 STATIC int si_group0(int adapter, int id, int lun,
142 int opcode, int addr, int len,
143 int flags, caddr_t databuf, int datalen);
144
145 static char scsi_name[] = "si";
146
147 struct scsi_adapter ncr5380_switch = {
148 ncr5380_scsi_cmd, /* scsi_cmd() */
149 ncr5380_minphys, /* scsi_minphys() */
150 0, /* open_target_lu() */
151 0, /* close_target_lu() */
152 ncr5380_adapter_info, /* adapter_info() */
153 scsi_name, /* name */
154 0, 0 /* spare[2] */
155 };
156
157 /* This is copied from julian's bt driver */
158 /* "so we have a default dev struct for our link struct." */
159 struct scsi_device ncr_dev = {
160 NULL, /* Use default error handler. */
161 NULL, /* Use default start handler. */
162 NULL, /* Use default async handler. */
163 NULL, /* Use default "done" routine. */
164 "si", /* name of device type */
165 0, /* device type dependent flags */
166 0, 0 /* spare[2] */
167 };
168
169 extern int matchbyname();
170 STATIC int si_match();
171 STATIC void si_attach();
172
173 struct cfdriver sicd = {
174 NULL, "si", si_match, si_attach, DV_DULL,
175 sizeof(struct ncr5380_softc), NULL, 0,
176 };
177
178 STATIC int
179 si_print(aux, name)
180 void *aux;
181 char *name;
182 {
183 if (name)
184 printf("%s: (sc_link = 0x%x)", name, (int) aux);
185 return UNCONF;
186 }
187
188 STATIC int
189 si_match(parent, cf, aux)
190 struct device *parent;
191 struct cfdata *cf;
192 void *aux;
193 {
194 caddr_t si_addr;
195 struct obio_cf_loc *obio_loc = (struct obio_cf_loc *) CFDATA_LOC(cf);
196
197 si_addr = OBIO_DEFAULT_PARAM(caddr_t, obio_loc->obio_addr, OBIO_NCR_SCSI);
198 return !obio_probe_byte(si_addr);
199 }
200
201 STATIC void
202 si_attach(parent, self, aux)
203 struct device *parent, *self;
204 void *aux;
205 {
206 caddr_t dvma_malloc(), si_addr;
207 int level, ncr_intr(), unit = DEVICE_UNIT(self);
208 struct ncr5380_softc *ncr5380 = (struct ncr5380_softc *) self;
209 struct obio_cf_loc *obio_loc = OBIO_LOC(self);
210 struct cfdata *new_match;
211
212 si_addr = OBIO_DEFAULT_PARAM(caddr_t, obio_loc->obio_addr, OBIO_NCR_SCSI);
213 ncr5380->sc_regs = (sci_regmap_t *)
214 obio_alloc(si_addr, OBIO_NCR_SCSI_SIZE, OBIO_WRITE);
215
216 level = OBIO_DEFAULT_PARAM(int, obio_loc->obio_level, 2);
217
218 ncr5380->sc_link.scsibus = unit; /* needed? */
219 ncr5380->sc_link.adapter_softc = ncr5380;
220 ncr5380->sc_link.adapter_targ = 7;
221 ncr5380->sc_link.adapter = &ncr5380_switch;
222 ncr5380->sc_link.device = &ncr_dev;
223
224 obio_print(si_addr, level);
225 printf("\n");
226
227 Debugger(); /* XXX */
228 config_found(self, &(ncr5380->sc_link), si_print);
229 }
230
231 STATIC u_int
232 ncr5380_adapter_info(struct ncr5380_softc *ncr5380)
233 {
234 return 1;
235 }
236
237 #define MIN_PHYS 65536 /*BARF!!!!*/
238 STATIC void
239 ncr5380_minphys(struct buf *bp)
240 {
241 if (bp->b_bcount > MIN_PHYS) {
242 printf("Uh-oh... ncr5380_minphys setting bp->b_bcount = %x.\n", MIN_PHYS);
243 bp->b_bcount = MIN_PHYS;
244 }
245 }
246 #undef MIN_PHYS
247
248 STATIC int /* si_attach+0x190 */
249 ncr5380_scsi_cmd(struct scsi_xfer *xs)
250 {
251 int flags, s, r;
252
253 flags = xs->flags;
254 if (xs->bp) flags |= (SCSI_NOSLEEP);
255 if ( flags & ITSDONE ) {
256 printf("Already done?");
257 xs->flags &= ~ITSDONE;
258 }
259 if ( ! ( flags & INUSE ) ) {
260 printf("Not in use?");
261 xs->flags |= INUSE;
262 }
263
264 if ( flags & SCSI_RESET ) {
265 printf("flags & SCSIRESET.\n");
266 if ( ! ( flags & SCSI_NOSLEEP ) ) {
267 s = splbio();
268 ncr5380_reset_target(xs->sc_link->scsibus, xs->sc_link->target);
269 splx(s);
270 return(SUCCESSFULLY_QUEUED);
271 } else {
272 ncr5380_reset_target(xs->sc_link->scsibus, xs->sc_link->target);
273 if (ncr5380_poll(xs->sc_link->scsibus, xs->timeout)) {
274 return (HAD_ERROR);
275 }
276 return (COMPLETE);
277 }
278 }
279 #if 0
280 /*
281 * OK. Now that that's over with, let's pack up that
282 * SCSI puppy and send it off. If we can, we'll just
283 * queue and go; otherwise, we'll wait for the command
284 * to finish.
285 */
286 if ( ! ( flags & SCSI_NOSLEEP ) ) {
287 s = splbio();
288 ncr5380_send_cmd(xs);
289 splx(s);
290 return(SUCCESSFULLY_QUEUED);
291 }
292 #endif
293
294 r = ncr5380_send_cmd(xs);
295 xs->flags |= ITSDONE;
296 scsi_done(xs);
297 switch(r) {
298 case COMPLETE:
299 case SUCCESSFULLY_QUEUED:
300 r = SUCCESSFULLY_QUEUED;
301 if (xs->flags&SCSI_NOMASK)
302 r = COMPLETE;
303 break;
304 default:
305 break;
306 }
307 return r;
308 #if 0
309 do {
310 if (ncr5380_poll(xs->sc_link->scsibus, xs->timeout)) {
311 if ( ! ( xs->flags & SCSI_SILENT ) )
312 printf("cmd fail.\n");
313 cmd_cleanup
314 xs->error = XS_DRIVER_STUFFUP;
315 splx(s);
316 }
317 } while ( ! ( xs->flags & ITSDONE ) );
318 #endif
319 }
320
321 STATIC int
322 ncr5380_show_scsi_cmd(struct scsi_xfer *xs)
323 {
324 u_char *b = (u_char *) xs->cmd;
325 int i = 0;
326
327 if ( ! ( xs->flags & SCSI_RESET ) ) {
328 printf("si(%d:%d:%d)-",
329 xs->sc_link->scsibus,
330 xs->sc_link->target,
331 xs->sc_link->lun);
332 while (i < xs->cmdlen) {
333 if (i) printf(",");
334 printf("%x",b[i++]);
335 }
336 printf("-\n");
337 } else {
338 printf("si(%d:%d:%d)-RESET-\n",
339 xs->sc_link->scsibus,
340 xs->sc_link->target,
341 xs->sc_link->lun);
342 }
343 }
344
345 /*
346 * Actual chip control.
347 */
348
349 void
350 ncr5380_intr(int adapter)
351 {
352 register struct ncr5380_softc *ncr5380 = sicd.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 #ifdef DEBUG
358 printf ("ncr_intr\n");
359 #endif
360 }
361
362 int
363 scsi_irq_intr(void)
364 {
365 #if 0 /* XXX - no way to get regs */
366 register volatile sci_regmap_t *regs = ncr;
367 if (regs->sci_csr != SCI_CSR_PHASE_MATCH)
368 printf("scsi_irq_intr called (not just phase match -- "
369 "csr = 0x%x, bus_csr = 0x%x).\n",
370 regs->sci_csr, regs->sci_bus_csr);
371 ncr5380_intr(0);
372 #endif
373 return 1;
374 }
375
376 int
377 scsi_drq_intr(void)
378 {
379 #if 0
380 printf("scsi_drq_intr called.\n");
381 ncr5380_intr(0);
382 #endif
383 return 1;
384 }
385
386 STATIC int
387 ncr5380_reset_target(int adapter, int target)
388 {
389 register struct ncr5380_softc *ncr5380 = sicd.cd_devs[adapter];
390 register volatile sci_regmap_t *regs = ncr5380->sc_regs;
391 int dummy;
392
393 regs->sci_icmd = SCI_ICMD_TEST;
394 regs->sci_icmd = SCI_ICMD_TEST | SCI_ICMD_RST;
395 delay(2500);
396 regs->sci_icmd = 0;
397
398 regs->sci_mode = 0;
399 regs->sci_tcmd = SCI_PHASE_DISC;
400 regs->sci_sel_enb = 0;
401
402 SCI_CLR_INTR(regs);
403 SCI_CLR_INTR(regs);
404 }
405
406 STATIC int
407 ncr5380_poll(int adapter, int timeout)
408 {
409 }
410
411 STATIC int
412 ncr5380_send_cmd(struct scsi_xfer *xs)
413 {
414 int s;
415 int sense;
416
417 /* ncr5380_show_scsi_cmd(xs); */
418 s = splbio();
419 sense = si_generic( xs->sc_link->scsibus, xs->sc_link->target,
420 xs->sc_link->lun, xs->cmd, xs->cmdlen,
421 xs->data, xs->datalen );
422 splx(s);
423 if (sense) {
424 switch (sense) {
425 case 0x02: /* Check condition */
426 #ifdef DEBUG
427 printf("check cond. target %d.\n",
428 xs->sc_link->target);
429 #endif
430 s = splbio();
431 si_group0(xs->sc_link->scsibus,
432 xs->sc_link->target,
433 xs->sc_link->lun,
434 0x3, 0x0,
435 sizeof(struct scsi_sense_data),
436 0, (caddr_t) &(xs->sense),
437 sizeof(struct scsi_sense_data));
438 splx(s);
439 xs->error = XS_SENSE;
440 return HAD_ERROR;
441 case 0x08: /* Busy */
442 xs->error = XS_BUSY;
443 return HAD_ERROR;
444 default:
445 xs->error = XS_DRIVER_STUFFUP;
446 return HAD_ERROR;
447 }
448 }
449 xs->error = XS_NOERROR;
450 return (COMPLETE);
451 }
452
453 STATIC int
454 si_select_target(register volatile sci_regmap_t *regs,
455 u_char myid, u_char tid, int with_atn)
456 {
457 register u_char bid, icmd;
458 int ret = SCSI_RET_RETRY;
459
460 if ((regs->sci_bus_csr & (SCI_BUS_BSY|SCI_BUS_SEL)) &&
461 (regs->sci_bus_csr & (SCI_BUS_BSY|SCI_BUS_SEL)) &&
462 (regs->sci_bus_csr & (SCI_BUS_BSY|SCI_BUS_SEL)))
463 return ret;
464
465 /* for our purposes.. */
466 myid = 1 << myid;
467 tid = 1 << tid;
468
469 regs->sci_sel_enb = 0; /* we don't want any interrupts. */
470 regs->sci_tcmd = 0; /* get into a harmless state */
471 regs->sci_mode = 0; /* get into a harmless state */
472
473 regs->sci_odata = myid;
474 regs->sci_mode = SCI_MODE_ARB;
475 /* regs->sci_mode |= SCI_MODE_ARB; XXX? */
476 /* AIP might not set if BSY went true after we checked */
477 for (bid = 0; bid < 20; bid++) /* 20usec circa */
478 if (regs->sci_icmd & SCI_ICMD_AIP)
479 break;
480 if ((regs->sci_icmd & SCI_ICMD_AIP) == 0) {
481 goto lost;
482 }
483
484 delay(2200); /* 2.2 millisecond arbitration delay */
485
486 if (regs->sci_icmd & SCI_ICMD_LST) {
487 #ifdef DEBUG
488 printf ("lost 1\n");
489 #endif
490 goto lost;
491 }
492
493 regs->sci_mode &= ~SCI_MODE_PAR_CHK;
494 bid = regs->sci_data;
495
496 if ((bid & ~myid) > myid) {
497 #ifdef DEBUG
498 printf ("lost 2\n");
499 #endif
500 goto lost;
501 }
502 if (regs->sci_icmd & SCI_ICMD_LST) {
503 #ifdef DEBUG
504 printf ("lost 3\n");
505 #endif
506 goto lost;
507 }
508
509 /* Won arbitration, enter selection phase now */
510 icmd = regs->sci_icmd & ~(SCI_ICMD_DIFF|SCI_ICMD_TEST);
511 icmd |= (with_atn ? (SCI_ICMD_SEL|SCI_ICMD_ATN) : SCI_ICMD_SEL);
512 icmd |= SCI_ICMD_BSY;
513 regs->sci_icmd = icmd;
514
515 if (regs->sci_icmd & SCI_ICMD_LST) {
516 #ifdef DEBUG
517 printf ("nosel\n");
518 #endif
519 goto nosel;
520 }
521
522 /* XXX a target that violates specs might still drive the bus XXX */
523 /* XXX should put our id out, and after the delay check nothi XXX */
524 /* XXX ng else is out there. XXX */
525
526 delay2us();
527
528 regs->sci_tcmd = 0;
529 regs->sci_odata = myid | tid;
530 regs->sci_sel_enb = 0;
531
532 /* regs->sci_mode &= ~SCI_MODE_ARB; 2 deskew delays, too */
533 regs->sci_mode = 0; /* 2 deskew delays, too */
534
535 icmd |= SCI_ICMD_DATA;
536 icmd &= ~(SCI_ICMD_BSY);
537
538 regs->sci_icmd = icmd;
539
540 /* bus settle delay, 400ns */
541 delay2us(); /* too much (was 2) ? */
542
543 /* regs->sci_mode |= SCI_MODE_PAR_CHK; */
544
545 {
546 register int timeo = 2500;/* 250 msecs in 100 usecs chunks */
547 while ((regs->sci_bus_csr & SCI_BUS_BSY) == 0) {
548 if (--timeo > 0) {
549 delay(100);
550 } else {
551 goto nodev;
552 }
553 }
554 }
555
556 icmd &= ~(SCI_ICMD_DATA|SCI_ICMD_SEL);
557 regs->sci_icmd = icmd;
558 /* regs->sci_sel_enb = myid;*/ /* looks like we should NOT have it */
559 return SCSI_RET_SUCCESS;
560 nodev:
561 ret = SCSI_RET_DEVICE_DOWN;
562 regs->sci_sel_enb = myid;
563 nosel:
564 icmd &= ~(SCI_ICMD_DATA|SCI_ICMD_SEL|SCI_ICMD_ATN);
565 regs->sci_icmd = icmd;
566 lost:
567 regs->sci_mode = 0;
568
569 return ret;
570 }
571
572 sci_data_out(regs, phase, count, data)
573 register volatile sci_regmap_t *regs;
574 unsigned char *data;
575 {
576 register unsigned char icmd;
577 register int cnt=0;
578
579 /* ..checks.. */
580
581 icmd = regs->sci_icmd & ~(SCI_ICMD_DIFF|SCI_ICMD_TEST);
582 loop:
583 if (SCI_CUR_PHASE(regs->sci_bus_csr) != phase)
584 return cnt;
585
586 WAIT_FOR_REQ(regs);
587 icmd |= SCI_ICMD_DATA;
588 regs->sci_icmd = icmd;
589 regs->sci_odata = *data++;
590 icmd |= SCI_ICMD_ACK;
591 regs->sci_icmd = icmd;
592
593 icmd &= ~(SCI_ICMD_DATA|SCI_ICMD_ACK);
594 WAIT_FOR_NOT_REQ(regs);
595 regs->sci_icmd = icmd;
596 ++cnt;
597 if (--count > 0)
598 goto loop;
599 scsi_timeout_error:
600 return cnt;
601 }
602
603 sci_data_in(regs, phase, count, data)
604 register volatile sci_regmap_t *regs;
605 unsigned char *data;
606 {
607 register unsigned char icmd;
608 register int cnt=0;
609
610 /* ..checks.. */
611
612 icmd = regs->sci_icmd & ~(SCI_ICMD_DIFF|SCI_ICMD_TEST);
613
614 loop:
615 if (SCI_CUR_PHASE(regs->sci_bus_csr) != phase)
616 return cnt;
617
618 WAIT_FOR_REQ(regs);
619 *data++ = regs->sci_data;
620 icmd |= SCI_ICMD_ACK;
621 regs->sci_icmd = icmd;
622
623 icmd &= ~SCI_ICMD_ACK;
624 WAIT_FOR_NOT_REQ(regs);
625 regs->sci_icmd = icmd;
626 ++cnt;
627 if (--count > 0)
628 goto loop;
629
630 scsi_timeout_error:
631 return cnt;
632 }
633
634 STATIC int
635 si_command_transfer(register volatile sci_regmap_t *regs,
636 int maxlen, u_char *data, u_char *status, u_char *msg)
637 {
638 int xfer=0, phase;
639
640 /* printf("command_transfer called for 0x%x.\n", *data); */
641
642 regs->sci_icmd = 0;
643
644 while (1) {
645
646 WAIT_FOR_REQ(regs);
647
648 phase = SCI_CUR_PHASE(regs->sci_bus_csr);
649
650 switch (phase) {
651 case SCSI_PHASE_CMD:
652 SCI_ACK(regs,SCSI_PHASE_CMD);
653 xfer += sci_data_out(regs, SCSI_PHASE_CMD,
654 maxlen, data);
655 return xfer;
656 case SCSI_PHASE_DATA_IN:
657 printf("Data in phase in command_transfer?\n");
658 return 0;
659 case SCSI_PHASE_DATA_OUT:
660 printf("Data out phase in command_transfer?\n");
661 return 0;
662 case SCSI_PHASE_STATUS:
663 SCI_ACK(regs,SCSI_PHASE_STATUS);
664 printf("status in command_transfer.\n");
665 sci_data_in(regs, SCSI_PHASE_STATUS,
666 1, status);
667 break;
668 case SCSI_PHASE_MESSAGE_IN:
669 SCI_ACK(regs,SCSI_PHASE_MESSAGE_IN);
670 printf("msgin in command_transfer.\n");
671 sci_data_in(regs, SCSI_PHASE_MESSAGE_IN,
672 1, msg);
673 break;
674 case SCSI_PHASE_MESSAGE_OUT:
675 SCI_ACK(regs,SCSI_PHASE_MESSAGE_OUT);
676 sci_data_out(regs, SCSI_PHASE_MESSAGE_OUT,
677 1, msg);
678 break;
679 default:
680 printf("Unexpected phase 0x%x in "
681 "command_transfer().\n", phase);
682 scsi_timeout_error:
683 return xfer;
684 break;
685 }
686 }
687 }
688
689 STATIC int
690 si_data_transfer(register volatile sci_regmap_t *regs,
691 int maxlen, u_char *data, u_char *status, u_char *msg)
692 {
693 int retlen = 0, xfer, phase;
694
695 regs->sci_icmd = 0;
696
697 *status = 0;
698
699 while (1) {
700
701 WAIT_FOR_REQ(regs);
702
703 phase = SCI_CUR_PHASE(regs->sci_bus_csr);
704
705 switch (phase) {
706 case SCSI_PHASE_CMD:
707 printf("Command phase in data_transfer().\n");
708 return retlen;
709 case SCSI_PHASE_DATA_IN:
710 SCI_ACK(regs,SCSI_PHASE_DATA_IN);
711 #if PSEUDO_DMA
712 xfer = sci_pdma_in(regs, SCSI_PHASE_DATA_IN,
713 maxlen, data);
714 #else
715 xfer = sci_data_in(regs, SCSI_PHASE_DATA_IN,
716 maxlen, data);
717 #endif
718 retlen += xfer;
719 maxlen -= xfer;
720 break;
721 case SCSI_PHASE_DATA_OUT:
722 SCI_ACK(regs,SCSI_PHASE_DATA_OUT);
723 #if PSEUDO_DMA
724 xfer = sci_pdma_out(regs, SCSI_PHASE_DATA_OUT,
725 maxlen, data);
726 #else
727 xfer = sci_data_out(regs, SCSI_PHASE_DATA_OUT,
728 maxlen, data);
729 #endif
730 retlen += xfer;
731 maxlen -= xfer;
732 break;
733 case SCSI_PHASE_STATUS:
734 SCI_ACK(regs,SCSI_PHASE_STATUS);
735 sci_data_in(regs, SCSI_PHASE_STATUS,
736 1, status);
737 break;
738 case SCSI_PHASE_MESSAGE_IN:
739 SCI_ACK(regs,SCSI_PHASE_MESSAGE_IN);
740 sci_data_in(regs, SCSI_PHASE_MESSAGE_IN,
741 1, msg);
742 if (*msg == 0) {
743 return retlen;
744 } else {
745 printf( "message 0x%x in "
746 "data_transfer.\n", *msg);
747 }
748 break;
749 case SCSI_PHASE_MESSAGE_OUT:
750 SCI_ACK(regs,SCSI_PHASE_MESSAGE_OUT);
751 sci_data_out(regs, SCSI_PHASE_MESSAGE_OUT,
752 1, msg);
753 break;
754 default:
755 printf( "Unexpected phase 0x%x in "
756 "data_transfer().\n", phase);
757 scsi_timeout_error:
758 return retlen;
759 break;
760 }
761 }
762 }
763
764 STATIC int
765 si_dorequest(register volatile sci_regmap_t *regs,
766 int target, int lun, u_char *cmd, int cmdlen,
767 char *databuf, int datalen, int *sent, int *ret)
768 {
769 /* Returns 0 on success, -1 on internal error, or the status byte */
770 int cmd_bytes_sent, r;
771 u_char stat, msg, c;
772
773 *sent = 0;
774
775 if ( ( r = si_select_target(regs, 7, target, 1) ) != SCSI_RET_SUCCESS) {
776 *ret = r;
777 SCI_CLR_INTR(regs);
778 switch (r) {
779 case SCSI_RET_RETRY:
780 return 0x08;
781 default:
782 printf("si_select_target(target %d, lun %d) failed(%d).\n",
783 target, lun, r);
784 case SCSI_RET_DEVICE_DOWN:
785 return -1;
786 }
787 }
788
789 c = 0x80 | lun;
790
791 if ((cmd_bytes_sent = si_command_transfer(regs, cmdlen,
792 (u_char *) cmd, &stat, &c))
793 != cmdlen) {
794 SCI_CLR_INTR(regs);
795 *ret = SCSI_RET_COMMAND_FAIL;
796 printf("Data underrun sending CCB (%d bytes of %d, sent).\n",
797 cmd_bytes_sent, cmdlen);
798 return -1;
799 }
800
801 *sent=si_data_transfer(regs, datalen, (u_char *)databuf,
802 &stat, &msg);
803
804 *ret = 0;
805 return stat;
806 }
807
808 STATIC int
809 si_generic(int adapter, int id, int lun, struct scsi_generic *cmd,
810 int cmdlen, void *databuf, int datalen)
811 {
812 register struct ncr5380_softc *ncr5380 = sicd.cd_devs[adapter];
813 register volatile sci_regmap_t *regs = ncr5380->sc_regs;
814 int i,j,sent,ret;
815
816 if (cmd->opcode == TEST_UNIT_READY) /* XXX */
817 cmd->bytes[0] = ((u_char) lun << 5);
818
819 i = si_dorequest(regs, id, lun, (u_char *) cmd, cmdlen,
820 databuf, datalen, &sent, &ret);
821
822 return i;
823 }
824
825 STATIC int
826 si_group0(int adapter, int id, int lun, int opcode, int addr, int len,
827 int flags, caddr_t databuf, int datalen)
828 {
829 register struct ncr5380_softc *ncr5380 = sicd.cd_devs[adapter];
830 register volatile sci_regmap_t *regs = ncr5380->sc_regs;
831 unsigned char cmd[6];
832 int i,j,sent,ret;
833
834 cmd[0] = opcode; /* Operation code */
835 cmd[1] = (lun << 5) | ((addr >> 16) & 0x1F); /* Lun & MSB of addr */
836 cmd[2] = (addr >> 8) & 0xFF; /* addr */
837 cmd[3] = addr & 0xFF; /* LSB of addr */
838 cmd[4] = len; /* Allocation length */
839 cmd[5] = flags; /* Link/Flag */
840
841 i = si_dorequest(regs, id, lun, cmd, 6, databuf, datalen, &sent, &ret);
842
843 return i;
844 }
845