sci.c revision 1.28 1 /* $NetBSD: sci.c,v 1.28 2003/06/18 08:58:36 drochner Exp $ */
2
3 /*
4 * Copyright (c) 1994 Michael L. Hitch
5 * Copyright (c) 1990 The Regents of the University of California.
6 * All rights reserved.
7 *
8 * This code is derived from software contributed to Berkeley by
9 * Van Jacobson of Lawrence Berkeley Laboratory.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. All advertising materials mentioning features or use of this software
20 * must display the following acknowledgement:
21 * This product includes software developed by the University of
22 * California, Berkeley and its contributors.
23 * 4. Neither the name of the University nor the names of its contributors
24 * may be used to endorse or promote products derived from this software
25 * without specific prior written permission.
26 *
27 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
28 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
31 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
32 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
33 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
34 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
35 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
36 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
37 * SUCH DAMAGE.
38 *
39 * @(#)scsi.c 7.5 (Berkeley) 5/4/91
40 */
41
42 /*
43 * AMIGA NCR 5380 scsi adaptor driver
44 */
45
46 #include <sys/cdefs.h>
47 __KERNEL_RCSID(0, "$NetBSD: sci.c,v 1.28 2003/06/18 08:58:36 drochner Exp $");
48
49 #include <sys/param.h>
50 #include <sys/systm.h>
51 #include <sys/device.h>
52 #include <sys/disklabel.h>
53 #include <sys/buf.h>
54 #include <dev/scsipi/scsi_all.h>
55 #include <dev/scsipi/scsipi_all.h>
56 #include <dev/scsipi/scsiconf.h>
57 #include <uvm/uvm_extern.h>
58 #include <machine/pmap.h>
59 #include <machine/cpu.h>
60 #include <amiga/amiga/device.h>
61 #include <amiga/amiga/custom.h>
62 #include <amiga/amiga/isr.h>
63 #include <amiga/dev/scireg.h>
64 #include <amiga/dev/scivar.h>
65
66 /*
67 * SCSI delays
68 * In u-seconds, primarily for state changes on the SPC.
69 */
70 #define SCI_CMD_WAIT 50000 /* wait per step of 'immediate' cmds */
71 #define SCI_DATA_WAIT 50000 /* wait per data in/out step */
72 #define SCI_INIT_WAIT 50000 /* wait per step (both) during init */
73
74 int sciicmd(struct sci_softc *, int, void *, int, void *, int,u_char);
75 int scigo(struct sci_softc *, struct scsipi_xfer *);
76 int sciselectbus(struct sci_softc *, u_char, u_char);
77 void sciabort(struct sci_softc *, char *);
78 void scierror(struct sci_softc *, u_char);
79 void scisetdelay(int);
80 void sci_scsidone(struct sci_softc *, int);
81 void sci_donextcmd(struct sci_softc *);
82 int sci_ixfer_out(struct sci_softc *, int, register u_char *, int);
83 void sci_ixfer_in(struct sci_softc *, int, register u_char *, int);
84
85 int sci_cmd_wait = SCI_CMD_WAIT;
86 int sci_data_wait = SCI_DATA_WAIT;
87 int sci_init_wait = SCI_INIT_WAIT;
88
89 int sci_no_dma = 0;
90
91 #ifdef DEBUG
92 #define QPRINTF(a) if (sci_debug > 1) printf a
93 int sci_debug = 0;
94 #else
95 #define QPRINTF(a)
96 #endif
97
98 /*
99 * default minphys routine for sci based controllers
100 */
101 void
102 sci_minphys(struct buf *bp)
103 {
104
105 /*
106 * No max transfer at this level.
107 */
108 minphys(bp);
109 }
110
111 /*
112 * used by specific sci controller
113 *
114 * it appears that the higher level code does nothing with LUN's
115 * so I will too. I could plug it in, however so could they
116 * in scsi_scsipi_cmd().
117 */
118 void
119 sci_scsipi_request(struct scsipi_channel *chan, scsipi_adapter_req_t req,
120 void *arg)
121 {
122 struct scsipi_xfer *xs;
123 struct scsipi_periph *periph;
124 struct sci_softc *dev = (void *)chan->chan_adapter->adapt_dev;
125 int flags, s;
126
127 switch (req) {
128 case ADAPTER_REQ_RUN_XFER:
129 xs = arg;
130 periph = xs->xs_periph;
131 flags = xs->xs_control;
132
133 if (flags & XS_CTL_DATA_UIO)
134 panic("sci: scsi data uio requested");
135
136 if (dev->sc_xs && flags & XS_CTL_POLL)
137 panic("sci_scsicmd: busy");
138
139 #ifdef DIAGNOSTIC
140 /*
141 * This should never happen as we track the resources
142 * in the mid-layer.
143 */
144 if (dev->sc_xs) {
145 scsipi_printaddr(periph);
146 printf("unable to allocate scb\n");
147 panic("sea_scsipi_request");
148 }
149 #endif
150
151 dev->sc_xs = xs;
152 splx(s);
153
154 /*
155 * nothing is pending do it now.
156 */
157 sci_donextcmd(dev);
158
159 return;
160
161 case ADAPTER_REQ_GROW_RESOURCES:
162 return;
163
164 case ADAPTER_REQ_SET_XFER_MODE:
165 return;
166 }
167 }
168
169 /*
170 * entered with dev->sc_xs pointing to the next xfer to perform
171 */
172 void
173 sci_donextcmd(struct sci_softc *dev)
174 {
175 struct scsipi_xfer *xs;
176 struct scsipi_periph *periph;
177 int flags, phase, stat;
178
179 xs = dev->sc_xs;
180 periph = xs->xs_periph;
181 flags = xs->xs_control;
182
183 if (flags & XS_CTL_DATA_IN)
184 phase = DATA_IN_PHASE;
185 else if (flags & XS_CTL_DATA_OUT)
186 phase = DATA_OUT_PHASE;
187 else
188 phase = STATUS_PHASE;
189
190 if (flags & XS_CTL_RESET)
191 scireset(dev);
192
193 dev->sc_stat[0] = -1;
194 xs->cmd->bytes[0] |= periph->periph_lun << 5;
195 if (phase == STATUS_PHASE || flags & XS_CTL_POLL)
196 stat = sciicmd(dev, periph->periph_target, xs->cmd, xs->cmdlen,
197 xs->data, xs->datalen, phase);
198 else if (scigo(dev, xs) == 0)
199 return;
200 else
201 stat = dev->sc_stat[0];
202
203 sci_scsidone(dev, stat);
204 }
205
206 void
207 sci_scsidone(struct sci_softc *dev, int stat)
208 {
209 struct scsipi_xfer *xs;
210
211 xs = dev->sc_xs;
212 #ifdef DIAGNOSTIC
213 if (xs == NULL)
214 panic("sci_scsidone");
215 #endif
216 xs->status = stat;
217 if (stat == 0)
218 xs->resid = 0;
219 else {
220 switch(stat) {
221 case SCSI_CHECK:
222 xs->resid = 0;
223 /* FALLTHOUGH */
224 case SCSI_BUSY:
225 xs->error = XS_BUSY;
226 break;
227 default:
228 xs->error = XS_DRIVER_STUFFUP;
229 QPRINTF(("sci_scsicmd() bad %x\n", stat));
230 break;
231 }
232 }
233
234 scsipi_done(xs);
235
236 }
237
238 void
239 sciabort(struct sci_softc *dev, char *where)
240 {
241 printf ("%s: abort %s: csr = 0x%02x, bus = 0x%02x\n",
242 dev->sc_dev.dv_xname, where, *dev->sci_csr, *dev->sci_bus_csr);
243
244 if (dev->sc_flags & SCI_SELECTED) {
245
246 /* lets just hope it worked.. */
247 dev->sc_flags &= ~SCI_SELECTED;
248 /* XXX */
249 scireset (dev);
250 }
251 }
252
253 /*
254 * XXX Set/reset long delays.
255 *
256 * if delay == 0, reset default delays
257 * if delay < 0, set both delays to default long initialization values
258 * if delay > 0, set both delays to this value
259 *
260 * Used when a devices is expected to respond slowly (e.g. during
261 * initialization).
262 */
263 void
264 scisetdelay(int del)
265 {
266 static int saved_cmd_wait, saved_data_wait;
267
268 if (del) {
269 saved_cmd_wait = sci_cmd_wait;
270 saved_data_wait = sci_data_wait;
271 if (del > 0)
272 sci_cmd_wait = sci_data_wait = del;
273 else
274 sci_cmd_wait = sci_data_wait = sci_init_wait;
275 } else {
276 sci_cmd_wait = saved_cmd_wait;
277 sci_data_wait = saved_data_wait;
278 }
279 }
280
281 void
282 scireset(struct sci_softc *dev)
283 {
284 u_int s;
285 u_char my_id;
286
287 dev->sc_flags &= ~SCI_SELECTED;
288 if (dev->sc_flags & SCI_ALIVE)
289 sciabort(dev, "reset");
290
291 printf("%s: ", dev->sc_dev.dv_xname);
292
293 s = splbio();
294 /* preserve our ID for now */
295 my_id = 7;
296
297 /*
298 * Reset the chip
299 */
300 *dev->sci_icmd = SCI_ICMD_TEST;
301 *dev->sci_icmd = SCI_ICMD_TEST | SCI_ICMD_RST;
302 delay (25);
303 *dev->sci_icmd = 0;
304
305 /*
306 * Set up various chip parameters
307 */
308 *dev->sci_icmd = 0;
309 *dev->sci_tcmd = 0;
310 *dev->sci_sel_enb = 0;
311
312 /* anything else was zeroed by reset */
313
314 splx (s);
315
316 printf("sci id %d\n", my_id);
317 dev->sc_flags |= SCI_ALIVE;
318 }
319
320 void
321 scierror(struct sci_softc *dev, u_char csr)
322 {
323 struct scsipi_xfer *xs;
324
325 xs = dev->sc_xs;
326
327 #ifdef DIAGNOSTIC
328 if (xs == NULL)
329 panic("scierror");
330 #endif
331 if (xs->xs_control & XS_CTL_SILENT)
332 return;
333
334 printf("%s: ", dev->sc_dev.dv_xname);
335 printf("csr == 0x%02i\n", csr); /* XXX */
336 }
337
338 /*
339 * select the bus, return when selected or error.
340 */
341 int
342 sciselectbus(struct sci_softc *dev, u_char target, u_char our_addr)
343 {
344 register int timeo = 2500;
345
346 QPRINTF (("sciselectbus %d\n", target));
347
348 /* if we're already selected, return */
349 if (dev->sc_flags & SCI_SELECTED) /* XXXX */
350 return 1;
351
352 if ((*dev->sci_bus_csr & (SCI_BUS_BSY|SCI_BUS_SEL)) &&
353 (*dev->sci_bus_csr & (SCI_BUS_BSY|SCI_BUS_SEL)) &&
354 (*dev->sci_bus_csr & (SCI_BUS_BSY|SCI_BUS_SEL)))
355 return 1;
356
357 *dev->sci_tcmd = 0;
358 *dev->sci_odata = 0x80 + (1 << target);
359 *dev->sci_icmd = SCI_ICMD_DATA|SCI_ICMD_SEL;
360 while ((*dev->sci_bus_csr & SCI_BUS_BSY) == 0) {
361 if (--timeo > 0) {
362 delay(100);
363 } else {
364 break;
365 }
366 }
367 if (timeo) {
368 *dev->sci_icmd = 0;
369 dev->sc_flags |= SCI_SELECTED;
370 return (0);
371 }
372 *dev->sci_icmd = 0;
373 return (1);
374 }
375
376 int
377 sci_ixfer_out(register struct sci_softc *dev, int len, register u_char *buf,
378 int phase)
379 {
380 register int wait = sci_data_wait;
381 u_char csr;
382
383 QPRINTF(("sci_ixfer_out {%d} %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
384 len, buf[0], buf[1], buf[2], buf[3], buf[4], buf[5],
385 buf[6], buf[7], buf[8], buf[9]));
386
387 *dev->sci_tcmd = phase;
388 *dev->sci_icmd = SCI_ICMD_DATA;
389 for (;len > 0; len--) {
390 csr = *dev->sci_bus_csr;
391 while (!(csr & SCI_BUS_REQ)) {
392 if ((csr & SCI_BUS_BSY) == 0 || --wait < 0) {
393 #ifdef DEBUG
394 if (sci_debug)
395 printf("sci_ixfer_out fail: l%d i%x w%d\n",
396 len, csr, wait);
397 #endif
398 return (len);
399 }
400 delay(1);
401 csr = *dev->sci_bus_csr;
402 }
403
404 if (!(*dev->sci_csr & SCI_CSR_PHASE_MATCH))
405 break;
406 *dev->sci_odata = *buf;
407 *dev->sci_icmd = SCI_ICMD_DATA|SCI_ICMD_ACK;
408 buf++;
409 while (*dev->sci_bus_csr & SCI_BUS_REQ);
410 *dev->sci_icmd = SCI_ICMD_DATA;
411 }
412
413 QPRINTF(("sci_ixfer_out done\n"));
414 return (0);
415 }
416
417 void
418 sci_ixfer_in(struct sci_softc *dev, int len, register u_char *buf, int phase)
419 {
420 int wait = sci_data_wait;
421 u_char csr;
422 volatile register u_char *sci_bus_csr = dev->sci_bus_csr;
423 volatile register u_char *sci_data = dev->sci_data;
424 volatile register u_char *sci_icmd = dev->sci_icmd;
425 #ifdef DEBUG
426 u_char *obp = buf;
427 #endif
428
429 csr = *sci_bus_csr;
430
431 QPRINTF(("sci_ixfer_in %d, csr=%02x\n", len, csr));
432
433 *dev->sci_tcmd = phase;
434 *sci_icmd = 0;
435 for (;len > 0; len--) {
436 csr = *sci_bus_csr;
437 while (!(csr & SCI_BUS_REQ)) {
438 if (!(csr & SCI_BUS_BSY) || --wait < 0) {
439 #ifdef DEBUG
440 if (sci_debug)
441 printf("sci_ixfer_in fail: l%d i%x w%d\n",
442 len, csr, wait);
443 #endif
444 return;
445 }
446
447 delay(1);
448 csr = *sci_bus_csr;
449 }
450
451 if (!(*dev->sci_csr & SCI_CSR_PHASE_MATCH))
452 break;
453 *buf = *sci_data;
454 *sci_icmd = SCI_ICMD_ACK;
455 buf++;
456 while (*sci_bus_csr & SCI_BUS_REQ);
457 *sci_icmd = 0;
458 }
459
460 QPRINTF(("sci_ixfer_in {%d} %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
461 len, obp[0], obp[1], obp[2], obp[3], obp[4], obp[5],
462 obp[6], obp[7], obp[8], obp[9]));
463 }
464
465 /*
466 * SCSI 'immediate' command: issue a command to some SCSI device
467 * and get back an 'immediate' response (i.e., do programmed xfer
468 * to get the response data). 'cbuf' is a buffer containing a scsi
469 * command of length clen bytes. 'buf' is a buffer of length 'len'
470 * bytes for data. The transfer direction is determined by the device
471 * (i.e., by the scsi bus data xfer phase). If 'len' is zero, the
472 * command must supply no data. 'xferphase' is the bus phase the
473 * caller expects to happen after the command is issued. It should
474 * be one of DATA_IN_PHASE, DATA_OUT_PHASE or STATUS_PHASE.
475 */
476 int
477 sciicmd(struct sci_softc *dev, int target, void *cbuf, int clen, void *buf,
478 int len, u_char xferphase)
479 {
480 u_char phase;
481 register int wait;
482
483 /* select the SCSI bus (it's an error if bus isn't free) */
484 if (sciselectbus (dev, target, dev->sc_scsi_addr))
485 return -1;
486 /*
487 * Wait for a phase change (or error) then let the device
488 * sequence us through the various SCSI phases.
489 */
490 dev->sc_stat[0] = 0xff;
491 dev->sc_msg[0] = 0xff;
492 phase = CMD_PHASE;
493 while (1) {
494 wait = sci_cmd_wait;
495
496 while ((*dev->sci_bus_csr & (SCI_BUS_REQ|SCI_BUS_BSY)) == SCI_BUS_BSY);
497
498 QPRINTF((">CSR:%02x<", *dev->sci_bus_csr));
499 if ((*dev->sci_bus_csr & SCI_BUS_REQ) == 0) {
500 return -1;
501 }
502 phase = SCI_PHASE(*dev->sci_bus_csr);
503
504 switch (phase) {
505 case CMD_PHASE:
506 if (sci_ixfer_out (dev, clen, cbuf, phase))
507 goto abort;
508 phase = xferphase;
509 break;
510
511 case DATA_IN_PHASE:
512 if (len <= 0)
513 goto abort;
514 wait = sci_data_wait;
515 sci_ixfer_in (dev, len, buf, phase);
516 phase = STATUS_PHASE;
517 break;
518
519 case DATA_OUT_PHASE:
520 if (len <= 0)
521 goto abort;
522 wait = sci_data_wait;
523 if (sci_ixfer_out (dev, len, buf, phase))
524 goto abort;
525 phase = STATUS_PHASE;
526 break;
527
528 case MESG_IN_PHASE:
529 dev->sc_msg[0] = 0xff;
530 sci_ixfer_in (dev, 1, dev->sc_msg,phase);
531 dev->sc_flags &= ~SCI_SELECTED;
532 while (*dev->sci_bus_csr & SCI_BUS_BSY);
533 goto out;
534 break;
535
536 case MESG_OUT_PHASE:
537 phase = STATUS_PHASE;
538 break;
539
540 case STATUS_PHASE:
541 sci_ixfer_in (dev, 1, dev->sc_stat, phase);
542 phase = MESG_IN_PHASE;
543 break;
544
545 case BUS_FREE_PHASE:
546 goto out;
547
548 default:
549 printf("sci: unexpected phase %d in icmd from %d\n",
550 phase, target);
551 goto abort;
552 }
553 #if 0
554 if (wait <= 0)
555 goto abort;
556 #endif
557 }
558
559 abort:
560 sciabort(dev, "icmd");
561 out:
562 QPRINTF(("=STS:%02x=", dev->sc_stat[0]));
563 return (dev->sc_stat[0]);
564 }
565
566 int
567 scigo(struct sci_softc *dev, struct scsipi_xfer *xs)
568 {
569 int count, target;
570 u_char phase, *addr;
571
572 target = xs->xs_periph->periph_target;
573 count = xs->datalen;
574 addr = xs->data;
575
576 if (sci_no_dma) {
577 sciicmd (dev, target, (u_char *) xs->cmd, xs->cmdlen,
578 addr, count,
579 xs->xs_control & XS_CTL_DATA_IN ? DATA_IN_PHASE : DATA_OUT_PHASE);
580
581 return (1);
582 }
583
584 /* select the SCSI bus (it's an error if bus isn't free) */
585 if (sciselectbus (dev, target, dev->sc_scsi_addr))
586 return -1;
587 /*
588 * Wait for a phase change (or error) then let the device
589 * sequence us through the various SCSI phases.
590 */
591 dev->sc_stat[0] = 0xff;
592 dev->sc_msg[0] = 0xff;
593 phase = CMD_PHASE;
594 while (1) {
595 while ((*dev->sci_bus_csr & (SCI_BUS_REQ|SCI_BUS_BSY)) ==
596 SCI_BUS_BSY);
597
598 QPRINTF((">CSR:%02x<", *dev->sci_bus_csr));
599 if ((*dev->sci_bus_csr & SCI_BUS_REQ) == 0) {
600 goto abort;
601 }
602 phase = SCI_PHASE(*dev->sci_bus_csr);
603
604 switch (phase) {
605 case CMD_PHASE:
606 if (sci_ixfer_out (dev, xs->cmdlen, (u_char *) xs->cmd, phase))
607 goto abort;
608 phase = xs->xs_control & XS_CTL_DATA_IN ? DATA_IN_PHASE : DATA_OUT_PHASE;
609 break;
610
611 case DATA_IN_PHASE:
612 if (count <= 0)
613 goto abort;
614 /* XXX use psuedo DMA if available */
615 if (count >= 128 && dev->dma_xfer_in)
616 (*dev->dma_xfer_in)(dev, count, addr, phase);
617 else
618 sci_ixfer_in (dev, count, addr, phase);
619 phase = STATUS_PHASE;
620 break;
621
622 case DATA_OUT_PHASE:
623 if (count <= 0)
624 goto abort;
625 /* XXX use psuedo DMA if available */
626 if (count >= 128 && dev->dma_xfer_out)
627 (*dev->dma_xfer_out)(dev, count, addr, phase);
628 else
629 if (sci_ixfer_out (dev, count, addr, phase))
630 goto abort;
631 phase = STATUS_PHASE;
632 break;
633
634 case MESG_IN_PHASE:
635 dev->sc_msg[0] = 0xff;
636 sci_ixfer_in (dev, 1, dev->sc_msg,phase);
637 dev->sc_flags &= ~SCI_SELECTED;
638 while (*dev->sci_bus_csr & SCI_BUS_BSY);
639 goto out;
640 break;
641
642 case MESG_OUT_PHASE:
643 phase = STATUS_PHASE;
644 break;
645
646 case STATUS_PHASE:
647 sci_ixfer_in (dev, 1, dev->sc_stat, phase);
648 phase = MESG_IN_PHASE;
649 break;
650
651 case BUS_FREE_PHASE:
652 goto out;
653
654 default:
655 printf("sci: unexpected phase %d in icmd from %d\n",
656 phase, target);
657 goto abort;
658 }
659 }
660
661 abort:
662 sciabort(dev, "go");
663 out:
664 QPRINTF(("=STS:%02x=", dev->sc_stat[0]));
665 return (1);
666 }
667