Expand PMF_FN_* macros.
[netbsd-mini2440.git] / sys / arch / acorn32 / podulebus / sbic.c
blob2c7ddbd0029751118fbd4d160557ea0a1a4a539b
1 /* $NetBSD: sbic.c,v 1.14 2009/03/18 10:22:22 cegger Exp $ */
3 /*
4 * Copyright (c) 2001 Richard Earnshaw
5 * All rights reserved.
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * 3. The name of the company nor the name of the author may be used to
13 * endorse or promote products derived from this software without specific
14 * prior written permission.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
20 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * POSSIBILITY OF SUCH DAMAGE.
28 * Copyright (c) 1990 The Regents of the University of California.
29 * All rights reserved.
31 * This code is derived from software contributed to Berkeley by
32 * Van Jacobson of Lawrence Berkeley Laboratory.
34 * Redistribution and use in source and binary forms, with or without
35 * modification, are permitted provided that the following conditions
36 * are met:
37 * 1. Redistributions of source code must retain the above copyright
38 * notice, this list of conditions and the following disclaimer.
39 * 2. Redistributions in binary form must reproduce the above copyright
40 * notice, this list of conditions and the following disclaimer in the
41 * documentation and/or other materials provided with the distribution.
42 * 3. Neither the name of the University nor the names of its contributors
43 * may be used to endorse or promote products derived from this software
44 * without specific prior written permission.
46 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
47 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
48 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
49 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
50 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
51 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
52 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
53 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
54 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
55 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
56 * SUCH DAMAGE.
58 * Copyright (c) 1994 Christian E. Hopps
60 * This code is derived from software contributed to Berkeley by
61 * Van Jacobson of Lawrence Berkeley Laboratory.
63 * Redistribution and use in source and binary forms, with or without
64 * modification, are permitted provided that the following conditions
65 * are met:
66 * 1. Redistributions of source code must retain the above copyright
67 * notice, this list of conditions and the following disclaimer.
68 * 2. Redistributions in binary form must reproduce the above copyright
69 * notice, this list of conditions and the following disclaimer in the
70 * documentation and/or other materials provided with the distribution.
71 * 3. All advertising materials mentioning features or use of this software
72 * must display the following acknowledgement:
73 * This product includes software developed by the University of
74 * California, Berkeley and its contributors.
75 * 4. Neither the name of the University nor the names of its contributors
76 * may be used to endorse or promote products derived from this software
77 * without specific prior written permission.
79 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
80 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
81 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
82 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
83 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
84 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
85 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
86 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
87 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
88 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
89 * SUCH DAMAGE.
91 * from: sbic.c,v 1.21 1996/01/07 22:01:54
95 * WD 33C93 scsi adaptor driver
98 #if 0
100 * The UPROTECTED_CSR code is bogus. It can read the csr (SCSI Status
101 * register) at times when an interrupt may be pending. Doing this will
102 * clear the interrupt, so we won't see it at times when we really need
103 * to.
105 #define UNPROTECTED_CSR
106 #endif
108 #ifndef DEBUG
109 #define DEBUG
110 #endif
111 /* #define SBIC_DEBUG(a) a */
113 #include "opt_ddb.h"
115 #include <sys/param.h>
117 __KERNEL_RCSID(0, "$NetBSD: sbic.c,v 1.14 2009/03/18 10:22:22 cegger Exp $");
119 #include <sys/systm.h>
120 #include <sys/callout.h>
121 #include <sys/kernel.h> /* For hz */
122 #include <sys/device.h>
123 #include <sys/buf.h>
125 #include <uvm/uvm_extern.h>
127 #include <machine/bus.h>
128 #include <machine/intr.h>
130 #include <dev/scsipi/scsi_all.h>
131 #include <dev/scsipi/scsipi_all.h>
132 #include <dev/scsipi/scsiconf.h>
134 #include <acorn32/podulebus/sbicreg.h>
135 #include <acorn32/podulebus/sbicvar.h>
138 * SCSI delays
139 * In u-seconds, primarily for state changes on the SPC.
141 #define SBIC_CMD_WAIT 50000 /* wait per step of 'immediate' cmds */
142 #define SBIC_DATA_WAIT 50000 /* wait per data in/out step */
143 #define SBIC_INIT_WAIT 50000 /* wait per step (both) during init */
145 #define SBIC_WAIT(regs, until, timeo) sbicwait(regs, until, timeo, __LINE__)
147 static int sbicicmd (struct sbic_softc *, int, int,
148 struct sbic_acb *);
149 static int sbicgo (struct sbic_softc *, struct scsipi_xfer *);
150 static int sbicwait (sbic_regmap_p, char, int , int);
151 static int sbicselectbus (struct sbic_softc *, sbic_regmap_p, u_char,
152 u_char, u_char);
153 static int sbicxfstart (sbic_regmap_p, int, u_char, int);
154 static int sbicxfout (sbic_regmap_p regs, int, void *, int);
155 static int sbicfromscsiperiod (struct sbic_softc *, sbic_regmap_p, int);
156 static int sbictoscsiperiod (struct sbic_softc *, sbic_regmap_p, int);
157 static int sbicpoll (struct sbic_softc *);
158 static int sbicnextstate (struct sbic_softc *, u_char, u_char);
159 static int sbicmsgin (struct sbic_softc *);
160 static int sbicxfin (sbic_regmap_p regs, int, void *);
161 static int sbicabort (struct sbic_softc *, sbic_regmap_p, const char *);
162 static void sbicxfdone (struct sbic_softc *, sbic_regmap_p, int);
163 static void sbicerror (struct sbic_softc *, sbic_regmap_p, u_char);
164 static void sbicreset (struct sbic_softc *);
165 static void sbic_scsidone (struct sbic_acb *, int);
166 static void sbic_sched (struct sbic_softc *);
167 static void sbic_save_ptrs (struct sbic_softc *, sbic_regmap_p);
170 * Synch xfer parameters, and timing conversions
172 int sbic_min_period = SBIC_SYN_MIN_PERIOD; /* in cycles = f(ICLK,FSn) */
173 int sbic_max_offset = SBIC_SYN_MAX_OFFSET; /* pure number */
175 int sbic_cmd_wait = SBIC_CMD_WAIT;
176 int sbic_data_wait = SBIC_DATA_WAIT;
177 int sbic_init_wait = SBIC_INIT_WAIT;
180 * was broken before.. now if you want this you get it for all drives
181 * on sbic controllers.
183 u_char sbic_inhibit_sync[8];
184 int sbic_enable_reselect = 1;
185 int sbic_clock_override = 0;
186 int sbic_no_dma = 1; /* was 0 */
187 int sbic_parallel_operations = 1;
189 #ifdef DEBUG
190 sbic_regmap_p debug_sbic_regs;
191 int sbicdma_ops = 0; /* total DMA operations */
192 int sbicdma_saves = 0;
193 #define QPRINTF(a) if (sbic_debug > 1) printf a
194 #define DBGPRINTF(x,p) if (p) printf x
195 #define DBG(x) x
196 int sbic_debug = 0;
197 int sync_debug = 0;
198 int sbic_dma_debug = 0;
199 int reselect_debug = 0;
200 int data_pointer_debug = 0;
201 u_char debug_asr, debug_csr, routine;
203 void sbicdumpstate (void);
204 void sbictimeout (struct sbic_softc *);
205 void sbic_dump (struct sbic_softc *);
206 void sbic_dump_acb (struct sbic_acb *);
208 #define CSR_TRACE_SIZE 32
209 #if CSR_TRACE_SIZE
210 #define CSR_TRACE(w,c,a,x) do { \
211 int _s = splbio(); \
212 csr_trace[csr_traceptr].whr = (w); csr_trace[csr_traceptr].csr = (c); \
213 csr_trace[csr_traceptr].asr = (a); csr_trace[csr_traceptr].xtn = (x); \
214 csr_traceptr = (csr_traceptr + 1) & (CSR_TRACE_SIZE - 1); \
215 splx(_s); \
216 } while (0)
217 int csr_traceptr;
218 int csr_tracesize = CSR_TRACE_SIZE;
219 struct {
220 u_char whr;
221 u_char csr;
222 u_char asr;
223 u_char xtn;
224 } csr_trace[CSR_TRACE_SIZE];
225 #else
226 #define CSR_TRACE
227 #endif
229 #define SBIC_TRACE_SIZE 0
230 #if SBIC_TRACE_SIZE
231 #define SBIC_TRACE(dev) do { \
232 int s = splbio(); \
233 sbic_trace[sbic_traceptr].sp = &s; \
234 sbic_trace[sbic_traceptr].line = __LINE__; \
235 sbic_trace[sbic_traceptr].sr = s; \
236 sbic_trace[sbic_traceptr].csr = csr_traceptr; \
237 sbic_traceptr = (sbic_traceptr + 1) & (SBIC_TRACE_SIZE - 1); \
238 splx(s); \
239 } while (0)
240 int sbic_traceptr;
241 int sbic_tracesize = SBIC_TRACE_SIZE;
242 struct {
243 void *sp;
244 u_short line;
245 u_short sr;
246 int csr;
247 } sbic_trace[SBIC_TRACE_SIZE];
248 #else
249 #define SBIC_TRACE(dev)
250 #endif
252 #else
253 #define QPRINTF(a)
254 #define DBGPRINTF(x,p)
255 #define DBG(x)
256 #define CSR_TRACE
257 #define SBIC_TRACE
258 #endif
260 #ifndef SBIC_DEBUG
261 #define SBIC_DEBUG(x)
262 #endif
265 * default minphys routine for sbic based controllers
267 void
268 sbic_minphys(struct buf *bp)
271 * No max transfer at this level.
273 minphys(bp);
277 * Save DMA pointers. Take into account partial transfer. Shut down DMA.
279 static void
280 sbic_save_ptrs(struct sbic_softc *dev, sbic_regmap_p regs)
282 int count, asr, s;
283 struct sbic_acb* acb;
285 SBIC_TRACE(dev);
286 if (!(dev->sc_flags & SBICF_INDMA))
287 return; /* DMA not active */
289 s = splbio();
291 acb = dev->sc_nexus;
292 if (acb == NULL) {
293 splx(s);
294 return;
296 count = -1;
297 do {
298 GET_SBIC_asr(regs, asr);
299 if (asr & SBIC_ASR_DBR) {
300 printf("sbic_save_ptrs: asr %02x canceled!\n", asr);
301 splx(s);
302 SBIC_TRACE(dev);
303 return;
305 } while (asr & (SBIC_ASR_BSY | SBIC_ASR_CIP));
307 /* Save important state */
308 /* must be done before dmastop */
309 SBIC_TC_GET(regs, count);
311 /* Shut down DMA ====CAREFUL==== */
312 dev->sc_dmastop(dev->sc_dmah, dev->sc_dmat, acb);
313 dev->sc_flags &= ~SBICF_INDMA;
314 #ifdef DIAGNOSTIC
316 int count2;
318 SBIC_TC_GET(regs, count2);
319 if (count2 != count)
320 panic("sbic_save_ptrs: DMA was still active(%d,%d)",
321 count, count2);
323 #endif
324 /* Note where we got to before stopping. We need this to resume
325 later. */
326 acb->offset += acb->sc_tcnt - count;
327 SBIC_TC_PUT(regs, 0);
329 DBGPRINTF(("SBIC saving tgt %d data pointers: Offset now %d ASR:%02x",
330 dev->target, acb->offset, asr), data_pointer_debug >= 1);
332 acb->sc_tcnt = 0;
334 DBG(sbicdma_saves++);
335 splx(s);
336 SBIC_TRACE(dev);
340 * used by specific sbic controller
342 * it appears that the higher level code does nothing with LUN's
343 * so I will too. I could plug it in, however so could they
344 * in scsi_scsi_cmd().
346 void
347 sbic_scsi_request(struct scsipi_channel *chan,
348 scsipi_adapter_req_t req, void *arg)
350 struct scsipi_xfer *xs;
351 struct sbic_acb *acb;
352 struct sbic_softc *dev = (void *)chan->chan_adapter->adapt_dev;
353 struct scsipi_periph *periph;
354 int flags, s, stat;
356 switch (req) {
357 case ADAPTER_REQ_RUN_XFER:
358 xs = arg;
359 periph = xs->xs_periph;
360 SBIC_TRACE(dev);
361 flags = xs->xs_control;
363 if (flags & XS_CTL_DATA_UIO)
364 panic("sbic: scsi data uio requested");
366 if (dev->sc_nexus && (flags & XS_CTL_POLL))
367 panic("sbic_scsicmd: busy");
369 s = splbio();
370 acb = dev->free_list.tqh_first;
371 if (acb)
372 TAILQ_REMOVE(&dev->free_list, acb, chain);
373 splx(s);
375 if (acb == NULL) {
376 DBG(printf("sbic_scsicmd: unable to queue request for "
377 "target %d\n", periph->periph_target));
378 #if defined(DDB) && defined(DEBUG)
379 Debugger();
380 #endif
381 xs->error = XS_RESOURCE_SHORTAGE;
382 SBIC_TRACE(dev);
383 scsipi_done(xs);
384 return;
387 acb->flags = ACB_ACTIVE;
388 if (flags & XS_CTL_DATA_IN)
389 acb->flags |= ACB_DATAIN;
390 acb->xs = xs;
391 memcpy(&acb->cmd, xs->cmd, xs->cmdlen);
392 acb->clen = xs->cmdlen;
393 acb->data = xs->data;
394 acb->datalen = xs->datalen;
396 QPRINTF(("sbic_scsi_request: Cmd %02x (len %d), Data %p(%d)\n",
397 (unsigned) acb->cmd.opcode, acb->clen, xs->data,
398 xs->datalen));
399 if (flags & XS_CTL_POLL) {
400 s = splbio();
402 * This has major side effects -- it locks up the
403 * machine.
406 dev->sc_flags |= SBICF_ICMD;
407 do {
408 while (dev->sc_nexus)
409 sbicpoll(dev);
410 dev->sc_nexus = acb;
411 dev->sc_stat[0] = -1;
412 dev->target = periph->periph_target;
413 dev->lun = periph->periph_lun;
414 stat = sbicicmd(dev, periph->periph_target,
415 periph->periph_lun, acb);
416 } while (dev->sc_nexus != acb);
418 sbic_scsidone(acb, stat);
419 splx(s);
420 SBIC_TRACE(dev);
421 return;
424 s = splbio();
425 TAILQ_INSERT_TAIL(&dev->ready_list, acb, chain);
427 if (dev->sc_nexus) {
428 splx(s);
429 SBIC_TRACE(dev);
430 return;
434 * Nothing is active, try to start it now.
436 sbic_sched(dev);
437 splx(s);
439 SBIC_TRACE(dev);
440 /* TODO: add sbic_poll to do XS_CTL_POLL operations */
441 return;
443 case ADAPTER_REQ_GROW_RESOURCES:
444 case ADAPTER_REQ_SET_XFER_MODE:
445 /* XXX Not supported. */
446 return;
451 * attempt to start the next available command
453 static void
454 sbic_sched(struct sbic_softc *dev)
456 struct scsipi_xfer *xs;
457 struct scsipi_periph *periph;
458 struct sbic_acb *acb;
459 int flags, /*phase,*/ stat, i;
461 SBIC_TRACE(dev);
462 if (dev->sc_nexus)
463 return; /* a command is current active */
465 SBIC_TRACE(dev);
466 for (acb = dev->ready_list.tqh_first; acb; acb = acb->chain.tqe_next) {
467 periph = acb->xs->xs_periph;
468 i = periph->periph_target;
469 if (!(dev->sc_tinfo[i].lubusy & (1 << periph->periph_lun))) {
470 struct sbic_tinfo *ti = &dev->sc_tinfo[i];
472 TAILQ_REMOVE(&dev->ready_list, acb, chain);
473 dev->sc_nexus = acb;
474 periph = acb->xs->xs_periph;
475 ti = &dev->sc_tinfo[periph->periph_target];
476 ti->lubusy |= (1 << periph->periph_lun);
477 break;
481 SBIC_TRACE(dev);
482 if (acb == NULL)
483 return; /* did not find an available command */
485 xs = acb->xs;
486 periph = xs->xs_periph;
487 flags = xs->xs_control;
489 if (flags & XS_CTL_RESET)
490 sbicreset(dev);
492 DBGPRINTF(("sbic_sched(%d,%d)\n", periph->periph_target,
493 periph->periph_lun), data_pointer_debug > 1);
494 DBG(if (data_pointer_debug > 1) sbic_dump_acb(acb));
495 dev->sc_stat[0] = -1;
496 dev->target = periph->periph_target;
497 dev->lun = periph->periph_lun;
499 /* Decide if we can use DMA for this transfer. */
500 if ((flags & XS_CTL_POLL) == 0
501 && !sbic_no_dma
502 && dev->sc_dmaok(dev->sc_dmah, dev->sc_dmat, acb))
503 acb->flags |= ACB_DMA;
505 if ((flags & XS_CTL_POLL) ||
506 (!sbic_parallel_operations && (acb->flags & ACB_DMA) == 0))
507 stat = sbicicmd(dev, periph->periph_target,
508 periph->periph_lun, acb);
509 else if (sbicgo(dev, xs) == 0 && xs->error != XS_SELTIMEOUT) {
510 SBIC_TRACE(dev);
511 return;
512 } else
513 stat = dev->sc_stat[0];
515 sbic_scsidone(acb, stat);
516 SBIC_TRACE(dev);
519 static void
520 sbic_scsidone(struct sbic_acb *acb, int stat)
522 struct scsipi_xfer *xs;
523 struct scsipi_periph *periph;
524 struct sbic_softc *dev;
525 /* int s;*/
526 int dosched = 0;
528 xs = acb->xs;
529 periph = xs->xs_periph;
530 dev = (void *)periph->periph_channel->chan_adapter->adapt_dev;
531 SBIC_TRACE(dev);
532 #ifdef DIAGNOSTIC
533 if (acb == NULL || xs == NULL) {
534 printf("sbic_scsidone -- (%d,%d) no scsipi_xfer\n",
535 dev->target, dev->lun);
536 #ifdef DDB
537 Debugger();
538 #endif
539 return;
541 #endif
543 DBGPRINTF(("scsidone: (%d,%d)->(%d,%d)%02x acbfl=%x\n",
544 periph->periph_target, periph->periph_lun,
545 dev->target, dev->lun, stat, acb->flags),
546 data_pointer_debug > 1);
547 DBG(if (xs->xs_periph->periph_target == dev->sc_channel.chan_id)
548 panic("target == hostid"));
550 xs->status = stat;
551 xs->resid = 0;
552 if (xs->error == XS_NOERROR) {
553 if (stat == SCSI_CHECK || stat == SCSI_BUSY)
554 xs->error = XS_BUSY;
558 * Remove the ACB from whatever queue it's on. We have to do a bit of
559 * a hack to figure out which queue it's on. Note that it is *not*
560 * necessary to cdr down the ready queue, but we must cdr down the
561 * nexus queue and see if it's there, so we can mark the unit as no
562 * longer busy. This code is sickening, but it works.
564 if (acb == dev->sc_nexus) {
565 dev->sc_nexus = NULL;
566 dev->sc_tinfo[periph->periph_target].lubusy &=
567 ~(1 << periph->periph_lun);
568 if (dev->ready_list.tqh_first)
569 dosched = 1; /* start next command */
570 } else if (dev->ready_list.tqh_last == &acb->chain.tqe_next) {
571 TAILQ_REMOVE(&dev->ready_list, acb, chain);
572 } else {
573 register struct sbic_acb *acb2;
574 for (acb2 = dev->nexus_list.tqh_first; acb2;
575 acb2 = acb2->chain.tqe_next) {
576 if (acb2 == acb) {
577 TAILQ_REMOVE(&dev->nexus_list, acb, chain);
578 dev->sc_tinfo[periph->periph_target].lubusy
579 &= ~(1 << periph->periph_lun);
580 break;
583 if (acb2)
585 else if (acb->chain.tqe_next) {
586 TAILQ_REMOVE(&dev->ready_list, acb, chain);
587 } else {
588 printf("%s: can't find matching acb\n",
589 device_xname(&dev->sc_dev));
590 #ifdef DDB
591 Debugger();
592 #endif
595 /* Put it on the free list. */
596 acb->flags = ACB_FREE;
597 TAILQ_INSERT_HEAD(&dev->free_list, acb, chain);
599 dev->sc_tinfo[periph->periph_target].cmds++;
601 scsipi_done(xs);
603 if (dosched)
604 sbic_sched(dev);
605 SBIC_TRACE(dev);
608 static int
609 sbicwait(sbic_regmap_p regs, char until, int timeo, int line)
611 u_char val;
612 int csr;
614 SBIC_TRACE((struct sbic_softc *)0);
615 if (timeo == 0)
616 timeo = 1000000; /* some large value.. */
618 GET_SBIC_asr(regs,val);
619 while ((val & until) == 0) {
620 if (timeo-- == 0) {
621 GET_SBIC_csr(regs, csr);
622 printf("sbicwait TIMEO @%d with asr=x%x csr=x%x\n",
623 line, val, csr);
624 #if defined(DDB) && defined(DEBUG)
625 Debugger();
626 #endif
627 return val; /* Maybe I should abort */
628 break;
630 DELAY(1);
631 GET_SBIC_asr(regs,val);
633 SBIC_TRACE((struct sbic_softc *)0);
634 return val;
637 static int
638 sbicabort(struct sbic_softc *dev, sbic_regmap_p regs, const char *where)
640 u_char csr, asr;
642 GET_SBIC_asr(regs, asr);
643 GET_SBIC_csr(regs, csr);
645 printf ("%s: abort %s: csr = 0x%02x, asr = 0x%02x\n",
646 device_xname(&dev->sc_dev), where, csr, asr);
649 #if 0
650 /* Clean up running command */
651 if (dev->sc_nexus != NULL) {
652 dev->sc_nexus->xs->error = XS_DRIVER_STUFFUP;
653 sbic_scsidone(dev->sc_nexus, dev->sc_stat[0]);
655 while (acb = dev->nexus_list.tqh_first) {
656 acb->xs->error = XS_DRIVER_STUFFUP;
657 sbic_scsidone(acb, -1 /*acb->stat[0]*/);
659 #endif
661 /* Clean up chip itself */
662 if (dev->sc_flags & SBICF_SELECTED) {
663 while (asr & SBIC_ASR_DBR) {
664 /* sbic is jammed w/data. need to clear it */
665 /* But we don't know what direction it needs to go */
666 GET_SBIC_data(regs, asr);
667 printf("%s: abort %s: clearing data buffer 0x%02x\n",
668 device_xname(&dev->sc_dev), where, asr);
669 GET_SBIC_asr(regs, asr);
670 /* Not the read direction, then */
671 if (asr & SBIC_ASR_DBR)
672 SET_SBIC_data(regs, asr);
673 GET_SBIC_asr(regs, asr);
675 WAIT_CIP(regs);
676 printf("%s: sbicabort - sending ABORT command\n",
677 device_xname(&dev->sc_dev));
678 SET_SBIC_cmd(regs, SBIC_CMD_ABORT);
679 WAIT_CIP(regs);
681 GET_SBIC_asr(regs, asr);
682 if (asr & (SBIC_ASR_BSY | SBIC_ASR_LCI)) {
683 /* ok, get more drastic.. */
685 printf("%s: sbicabort - asr %x, trying to reset\n",
686 device_xname(&dev->sc_dev), asr);
687 sbicreset(dev);
688 dev->sc_flags &= ~SBICF_SELECTED;
689 return -1;
691 printf("%s: sbicabort - sending DISC command\n",
692 device_xname(&dev->sc_dev));
693 SET_SBIC_cmd(regs, SBIC_CMD_DISC);
695 do {
696 asr = SBIC_WAIT (regs, SBIC_ASR_INT, 0);
697 GET_SBIC_csr (regs, csr);
698 CSR_TRACE('a',csr,asr,0);
699 } while ((csr != SBIC_CSR_DISC) && (csr != SBIC_CSR_DISC_1)
700 && (csr != SBIC_CSR_CMD_INVALID));
702 /* lets just hope it worked.. */
703 dev->sc_flags &= ~SBICF_SELECTED;
705 return -1;
710 * Initialize driver-private structures
714 sbicinit(struct sbic_softc *dev)
716 sbic_regmap_p regs;
717 u_int i;
718 /* u_int my_id, s;*/
719 /* u_char csr;*/
720 struct sbic_acb *acb;
721 u_int inhibit_sync;
723 extern u_long scsi_nosync;
724 extern int shift_nosync;
726 SBIC_DEBUG(printf("sbicinit:\n"));
728 regs = &dev->sc_sbicp;
730 if ((dev->sc_flags & SBICF_ALIVE) == 0) {
731 TAILQ_INIT(&dev->ready_list);
732 TAILQ_INIT(&dev->nexus_list);
733 TAILQ_INIT(&dev->free_list);
734 callout_init(&dev->sc_timo_ch, 0);
735 dev->sc_nexus = NULL;
736 acb = dev->sc_acb;
737 memset(acb, 0, sizeof(dev->sc_acb));
739 SBIC_DEBUG(printf("sbicinit: %d\n", __LINE__));
741 for (i = 0; i < sizeof(dev->sc_acb) / sizeof(*acb); i++) {
742 TAILQ_INSERT_TAIL(&dev->free_list, acb, chain);
743 acb++;
745 memset(dev->sc_tinfo, 0, sizeof(dev->sc_tinfo));
746 /* make sure timeout is really not needed */
747 DBG(callout_reset(&dev->sc_timo_ch, 30 * hz,
748 (void *)sbictimeout, dev));
749 } else
750 panic("sbic: reinitializing driver!");
752 SBIC_DEBUG(printf("sbicinit: %d\n", __LINE__));
754 dev->sc_flags |= SBICF_ALIVE;
755 dev->sc_flags &= ~SBICF_SELECTED;
757 /* initialize inhibit array */
758 if (scsi_nosync) {
760 SBIC_DEBUG(printf("sbicinit: %d\n", __LINE__));
762 inhibit_sync = (scsi_nosync >> shift_nosync) & 0xff;
763 shift_nosync += 8;
765 DBGPRINTF(("%s: Inhibiting synchronous transfer %02x\n",
766 device_xname(&dev->sc_dev), inhibit_sync), inhibit_sync);
768 for (i = 0; i < 8; ++i)
769 if (inhibit_sync & (1 << i))
770 sbic_inhibit_sync[i] = 1;
773 SBIC_DEBUG(printf("sbicinit: %d\n", __LINE__));
775 sbicreset(dev);
776 return 0;
779 static void
780 sbicreset(struct sbic_softc *dev)
782 sbic_regmap_p regs;
783 u_int my_id, s;
784 /* u_int i;*/
785 u_char csr;
786 /* struct sbic_acb *acb;*/
788 SBIC_DEBUG(printf("sbicreset: %d\n", __LINE__));
790 regs = &dev->sc_sbicp;
792 SBIC_DEBUG(printf("sbicreset: regs = %08x\n", regs));
794 #if 0
795 if (dev->sc_flags & SBICF_ALIVE) {
796 SET_SBIC_cmd(regs, SBIC_CMD_ABORT);
797 WAIT_CIP(regs);
799 #else
800 SET_SBIC_cmd(regs, SBIC_CMD_ABORT);
802 SBIC_DEBUG(printf("sbicreset: %d\n", __LINE__));
804 WAIT_CIP(regs);
806 SBIC_DEBUG(printf("sbicreset: %d\n", __LINE__));
807 #endif
808 s = splbio();
809 my_id = dev->sc_channel.chan_id & SBIC_ID_MASK;
811 /* Enable advanced mode */
812 my_id |= SBIC_ID_EAF /*| SBIC_ID_EHP*/ ;
813 SET_SBIC_myid(regs, my_id);
815 SBIC_DEBUG(printf("sbicreset: %d\n", __LINE__));
818 * Disable interrupts (in dmainit) then reset the chip
820 SET_SBIC_cmd(regs, SBIC_CMD_RESET);
821 DELAY(25);
822 SBIC_WAIT(regs, SBIC_ASR_INT, 0);
823 GET_SBIC_csr(regs, csr); /* clears interrupt also */
825 if (dev->sc_clkfreq < 110)
826 my_id |= SBIC_ID_FS_8_10;
827 else if (dev->sc_clkfreq < 160)
828 my_id |= SBIC_ID_FS_12_15;
829 else if (dev->sc_clkfreq < 210)
830 my_id |= SBIC_ID_FS_16_20;
832 SET_SBIC_myid(regs, my_id);
834 SBIC_DEBUG(printf("sbicreset: %d\n", __LINE__));
837 * Set up various chip parameters
839 SET_SBIC_control(regs, SBIC_CTL_EDI | SBIC_CTL_IDI /* | SBIC_CTL_HSP */
840 | dev->sc_dmamode);
842 * don't allow (re)selection (SBIC_RID_ES)
843 * until we can handle target mode!!
845 SET_SBIC_rselid(regs, SBIC_RID_ER);
846 SET_SBIC_syn(regs, 0); /* asynch for now */
849 * anything else was zeroed by reset
851 splx(s);
853 #if 0
854 if ((dev->sc_flags & SBICF_ALIVE) == 0) {
855 TAILQ_INIT(&dev->ready_list);
856 TAILQ_INIT(&dev->nexus_list);
857 TAILQ_INIT(&dev->free_list);
858 dev->sc_nexus = NULL;
859 acb = dev->sc_acb;
860 memset(acb, 0, sizeof(dev->sc_acb));
861 for (i = 0; i < sizeof(dev->sc_acb) / sizeof(*acb); i++) {
862 TAILQ_INSERT_TAIL(&dev->free_list, acb, chain);
863 acb++;
865 memset(dev->sc_tinfo, 0, sizeof(dev->sc_tinfo));
866 } else {
867 if (dev->sc_nexus != NULL) {
868 dev->sc_nexus->xs->error = XS_DRIVER_STUFFUP;
869 sbic_scsidone(dev->sc_nexus, dev->sc_stat[0]);
871 while (acb = dev->nexus_list.tqh_first) {
872 acb->xs->error = XS_DRIVER_STUFFUP;
873 sbic_scsidone(acb, -1 /*acb->stat[0]*/);
877 dev->sc_flags |= SBICF_ALIVE;
878 #endif
879 dev->sc_flags &= ~SBICF_SELECTED;
882 static void
883 sbicerror(struct sbic_softc *dev, sbic_regmap_p regs, u_char csr)
885 #ifdef DIAGNOSTIC
886 if (dev->sc_nexus == NULL)
887 panic("sbicerror");
888 #endif
889 if (dev->sc_nexus->xs->xs_control & XS_CTL_SILENT)
890 return;
892 printf("%s: ", device_xname(&dev->sc_dev));
893 printf("csr == 0x%02x\n", csr); /* XXX */
897 * select the bus, return when selected or error.
899 static int
900 sbicselectbus(struct sbic_softc *dev, sbic_regmap_p regs, u_char target,
901 u_char lun, u_char our_addr)
903 u_char asr, csr, id;
905 SBIC_TRACE(dev);
906 QPRINTF(("sbicselectbus %d\n", target));
909 * if we're already selected, return (XXXX panic maybe?)
911 if (dev->sc_flags & SBICF_SELECTED) {
912 SBIC_TRACE(dev);
913 return 1;
917 * issue select
919 SBIC_TC_PUT(regs, 0);
920 SET_SBIC_selid(regs, target);
921 SET_SBIC_timeo(regs, SBIC_TIMEOUT(250,dev->sc_clkfreq));
924 * set sync or async
926 if (dev->sc_sync[target].state == SYNC_DONE)
927 SET_SBIC_syn(regs, SBIC_SYN (dev->sc_sync[target].offset,
928 dev->sc_sync[target].period));
929 else
930 SET_SBIC_syn(regs, SBIC_SYN (0, sbic_min_period));
932 GET_SBIC_asr(regs, asr);
933 if (asr & (SBIC_ASR_INT | SBIC_ASR_BSY)) {
934 /* This means we got ourselves reselected upon */
935 /* printf("sbicselectbus: INT/BSY asr %02x\n", asr);*/
936 #ifdef DDB
937 /* Debugger();*/
938 #endif
939 SBIC_TRACE(dev);
940 return 1;
943 SET_SBIC_cmd(regs, SBIC_CMD_SEL_ATN);
946 * wait for select (merged from separate function may need
947 * cleanup)
949 WAIT_CIP(regs);
950 do {
951 asr = SBIC_WAIT(regs, SBIC_ASR_INT | SBIC_ASR_LCI, 0);
952 if (asr & SBIC_ASR_LCI) {
954 DBGPRINTF(("sbicselectbus: late LCI asr %02x\n", asr),
955 reselect_debug);
957 SBIC_TRACE(dev);
958 return 1;
960 GET_SBIC_csr (regs, csr);
961 CSR_TRACE('s',csr,asr,target);
962 QPRINTF(("%02x ", csr));
963 if (csr == SBIC_CSR_RSLT_NI || csr == SBIC_CSR_RSLT_IFY) {
965 DBGPRINTF(("sbicselectbus: reselected asr %02x\n",
966 asr), reselect_debug);
968 /* We need to handle this now so we don't lock
969 up later */
970 sbicnextstate(dev, csr, asr);
971 SBIC_TRACE(dev);
972 return 1;
974 if (csr == SBIC_CSR_SLT || csr == SBIC_CSR_SLT_ATN) {
975 panic("sbicselectbus: target issued select!");
976 return 1;
978 } while (csr != (SBIC_CSR_MIS_2 | MESG_OUT_PHASE) &&
979 csr != (SBIC_CSR_MIS_2 | CMD_PHASE) &&
980 csr != SBIC_CSR_SEL_TIMEO);
982 /* Enable (or not) reselection */
983 if (!sbic_enable_reselect && dev->nexus_list.tqh_first == NULL)
984 SET_SBIC_rselid (regs, 0);
985 else
986 SET_SBIC_rselid (regs, SBIC_RID_ER);
988 if (csr == (SBIC_CSR_MIS_2 | CMD_PHASE)) {
989 dev->sc_flags |= SBICF_SELECTED; /* device ignored ATN */
990 GET_SBIC_selid(regs, id);
991 dev->target = id;
992 GET_SBIC_tlun(regs,dev->lun);
993 if (dev->lun & SBIC_TLUN_VALID)
994 dev->lun &= SBIC_TLUN_MASK;
995 else
996 dev->lun = lun;
997 } else if (csr == (SBIC_CSR_MIS_2 | MESG_OUT_PHASE)) {
999 * Send identify message
1000 * (SCSI-2 requires an identify msg (?))
1002 GET_SBIC_selid(regs, id);
1003 dev->target = id;
1004 GET_SBIC_tlun(regs,dev->lun);
1005 if (dev->lun & SBIC_TLUN_VALID)
1006 dev->lun &= SBIC_TLUN_MASK;
1007 else
1008 dev->lun = lun;
1010 * handle drives that don't want to be asked
1011 * whether to go sync at all.
1013 if (sbic_inhibit_sync[id]
1014 && dev->sc_sync[id].state == SYNC_START) {
1015 DBGPRINTF(("Forcing target %d asynchronous.\n", id),
1016 sync_debug);
1018 dev->sc_sync[id].offset = 0;
1019 dev->sc_sync[id].period = sbic_min_period;
1020 dev->sc_sync[id].state = SYNC_DONE;
1024 if (dev->sc_sync[id].state != SYNC_START){
1025 if ((dev->sc_nexus->xs->xs_control & XS_CTL_POLL)
1026 || (dev->sc_flags & SBICF_ICMD)
1027 || !sbic_enable_reselect)
1028 SEND_BYTE(regs, MSG_IDENTIFY | lun);
1029 else
1030 SEND_BYTE(regs, MSG_IDENTIFY_DR | lun);
1031 } else {
1033 * try to initiate a sync transfer.
1034 * So compose the sync message we're going
1035 * to send to the target
1038 DBGPRINTF(("Sending sync request to target %d ... ",
1039 id), sync_debug);
1042 * setup scsi message sync message request
1044 dev->sc_msg[0] = MSG_IDENTIFY | lun;
1045 dev->sc_msg[1] = MSG_EXT_MESSAGE;
1046 dev->sc_msg[2] = 3;
1047 dev->sc_msg[3] = MSG_SYNC_REQ;
1048 dev->sc_msg[4] = sbictoscsiperiod(dev, regs,
1049 sbic_min_period);
1050 dev->sc_msg[5] = sbic_max_offset;
1052 if (sbicxfstart(regs, 6, MESG_OUT_PHASE,
1053 sbic_cmd_wait))
1054 sbicxfout(regs, 6, dev->sc_msg,
1055 MESG_OUT_PHASE);
1057 dev->sc_sync[id].state = SYNC_SENT;
1059 DBGPRINTF(("sent\n"), sync_debug);
1062 asr = SBIC_WAIT (regs, SBIC_ASR_INT, 0);
1063 GET_SBIC_csr (regs, csr);
1064 CSR_TRACE('y',csr,asr,target);
1065 QPRINTF(("[%02x]", csr));
1067 DBGPRINTF(("csr-result of last msgout: 0x%x\n", csr),
1068 sync_debug && dev->sc_sync[id].state == SYNC_SENT);
1070 if (csr != SBIC_CSR_SEL_TIMEO)
1071 dev->sc_flags |= SBICF_SELECTED;
1073 if (csr == SBIC_CSR_SEL_TIMEO)
1074 dev->sc_nexus->xs->error = XS_SELTIMEOUT;
1076 QPRINTF(("\n"));
1078 SBIC_TRACE(dev);
1079 return csr == SBIC_CSR_SEL_TIMEO;
1082 static int
1083 sbicxfstart(sbic_regmap_p regs, int len, u_char phase, int wait)
1085 u_char id;
1087 switch (phase) {
1088 case DATA_IN_PHASE:
1089 case MESG_IN_PHASE:
1090 GET_SBIC_selid (regs, id);
1091 id |= SBIC_SID_FROM_SCSI;
1092 SET_SBIC_selid (regs, id);
1093 SBIC_TC_PUT (regs, (unsigned)len);
1094 break;
1095 case DATA_OUT_PHASE:
1096 case MESG_OUT_PHASE:
1097 case CMD_PHASE:
1098 GET_SBIC_selid (regs, id);
1099 id &= ~SBIC_SID_FROM_SCSI;
1100 SET_SBIC_selid (regs, id);
1101 SBIC_TC_PUT (regs, (unsigned)len);
1102 break;
1103 default:
1104 SBIC_TC_PUT (regs, 0);
1106 QPRINTF(("sbicxfstart %d, %d, %d\n", len, phase, wait));
1108 return 1;
1111 static int
1112 sbicxfout(sbic_regmap_p regs, int len, void *bp, int phase)
1114 #ifdef UNPROTECTED_CSR
1115 u_char orig_csr
1116 #endif
1117 u_char asr, *buf;
1118 /* u_char csr;*/
1119 int wait;
1121 buf = bp;
1122 wait = sbic_data_wait;
1124 QPRINTF(("sbicxfout {%d} %02x %02x %02x %02x %02x "
1125 "%02x %02x %02x %02x %02x\n", len, buf[0], buf[1], buf[2],
1126 buf[3], buf[4], buf[5], buf[6], buf[7], buf[8], buf[9]));
1128 #ifdef UNPROTECTED_CSR
1129 GET_SBIC_csr (regs, orig_csr);
1130 CSR_TRACE('>',orig_csr,0,0);
1131 #endif
1134 * sigh.. WD-PROTO strikes again.. sending the command in one go
1135 * causes the chip to lock up if talking to certain (misbehaving?)
1136 * targets. Anyway, this procedure should work for all targets, but
1137 * it's slightly slower due to the overhead
1139 WAIT_CIP (regs);
1140 SET_SBIC_cmd (regs, SBIC_CMD_XFER_INFO);
1141 for (;len > 0; len--) {
1142 GET_SBIC_asr (regs, asr);
1143 while ((asr & SBIC_ASR_DBR) == 0) {
1144 if ((asr & SBIC_ASR_INT) || --wait < 0) {
1146 DBGPRINTF(("sbicxfout fail: l%d i%x w%d\n",
1147 len, asr, wait), sbic_debug);
1149 return len;
1151 /* DELAY(1);*/
1152 GET_SBIC_asr (regs, asr);
1155 SET_SBIC_data (regs, *buf);
1156 buf++;
1158 SBIC_TC_GET(regs, len);
1159 QPRINTF(("sbicxfout done %d bytes\n", len));
1161 * this leaves with one csr to be read
1163 return 0;
1166 /* returns # bytes left to read */
1167 static int
1168 sbicxfin(sbic_regmap_p regs, int len, void *bp)
1170 int wait;
1171 /* int read;*/
1172 u_char *obp, *buf;
1173 #ifdef UNPROTECTED_CSR
1174 u_char orig_csr, csr;
1175 #endif
1176 u_char asr;
1178 wait = sbic_data_wait;
1179 obp = bp;
1180 buf = bp;
1182 #ifdef UNPROTECTED_CSR
1183 GET_SBIC_csr (regs, orig_csr);
1184 CSR_TRACE('<',orig_csr,0,0);
1186 QPRINTF(("sbicxfin %d, csr=%02x\n", len, orig_csr));
1187 #endif
1189 WAIT_CIP (regs);
1190 SET_SBIC_cmd (regs, SBIC_CMD_XFER_INFO);
1191 for (;len > 0; len--) {
1192 GET_SBIC_asr (regs, asr);
1193 if ((asr & SBIC_ASR_PE)) {
1194 DBG(printf("sbicxfin parity error: l%d i%x w%d\n",
1195 len, asr, wait));
1196 #if defined(DDB) && defined(DEBUG)
1197 Debugger();
1198 #endif
1199 DBG(return ((unsigned long)buf - (unsigned long)bp));
1201 while ((asr & SBIC_ASR_DBR) == 0) {
1202 if ((asr & SBIC_ASR_INT) || --wait < 0) {
1204 DBG(if (sbic_debug) {
1205 QPRINTF(("sbicxfin fail:{%d} %02x %02x %02x %02x %02x %02x "
1206 "%02x %02x %02x %02x\n", len, obp[0], obp[1], obp[2],
1207 obp[3], obp[4], obp[5], obp[6], obp[7], obp[8], obp[9]));
1208 printf("sbicxfin fail: l%d i%x w%d\n", len, asr, wait); });
1210 return len;
1213 #ifdef UNPROTECTED_CSR
1214 if (!(asr & SBIC_ASR_BSY)) {
1215 GET_SBIC_csr(regs, csr);
1216 CSR_TRACE('<',csr,asr,len);
1217 QPRINTF(("[CSR%02xASR%02x]", csr, asr));
1219 #endif
1221 /* DELAY(1);*/
1222 GET_SBIC_asr (regs, asr);
1225 GET_SBIC_data (regs, *buf);
1226 /* QPRINTF(("asr=%02x, csr=%02x, data=%02x\n", asr, csr, *buf));*/
1227 buf++;
1230 QPRINTF(("sbicxfin {%d} %02x %02x %02x %02x %02x %02x "
1231 "%02x %02x %02x %02x\n", len, obp[0], obp[1], obp[2],
1232 obp[3], obp[4], obp[5], obp[6], obp[7], obp[8], obp[9]));
1234 /* this leaves with one csr to be read */
1235 return len;
1239 * SCSI 'immediate' command: issue a command to some SCSI device
1240 * and get back an 'immediate' response (i.e., do programmed xfer
1241 * to get the response data). 'cbuf' is a buffer containing a scsi
1242 * command of length clen bytes. 'buf' is a buffer of length 'len'
1243 * bytes for data. The transfer direction is determined by the device
1244 * (i.e., by the scsi bus data xfer phase). If 'len' is zero, the
1245 * command must supply no data.
1247 static int
1248 sbicicmd(struct sbic_softc *dev, int target, int lun, struct sbic_acb *acb)
1250 sbic_regmap_p regs;
1251 u_char phase, csr, asr;
1252 int wait;
1253 /* int newtarget, cmd_sent, parity_err;*/
1255 /* int discon;*/
1256 int i;
1258 void *cbuf, *buf;
1259 int clen, len;
1261 #define CSR_LOG_BUF_SIZE 0
1262 #if CSR_LOG_BUF_SIZE
1263 int bufptr;
1264 int csrbuf[CSR_LOG_BUF_SIZE];
1265 bufptr = 0;
1266 #endif
1268 cbuf = &acb->cmd;
1269 clen = acb->clen;
1270 buf = acb->data;
1271 len = acb->datalen;
1273 SBIC_TRACE(dev);
1274 regs = &dev->sc_sbicp;
1276 acb->sc_tcnt = 0;
1278 DBG(routine = 3);
1279 DBG(debug_sbic_regs = regs); /* store this to allow debug calls */
1280 DBGPRINTF(("sbicicmd(%d,%d):%d\n", target, lun, len),
1281 data_pointer_debug > 1);
1284 * set the sbic into non-DMA mode
1286 SET_SBIC_control(regs, SBIC_CTL_EDI | SBIC_CTL_IDI /*| SBIC_CTL_HSP*/);
1288 dev->sc_stat[0] = 0xff;
1289 dev->sc_msg[0] = 0xff;
1290 i = 1; /* pre-load */
1292 /* We're stealing the SCSI bus */
1293 dev->sc_flags |= SBICF_ICMD;
1295 do {
1297 * select the SCSI bus (it's an error if bus isn't free)
1299 if (!(dev->sc_flags & SBICF_SELECTED)
1300 && sbicselectbus(dev, regs, target, lun,
1301 dev->sc_scsiaddr)) {
1302 /*printf("sbicicmd trying to select busy bus!\n");*/
1303 dev->sc_flags &= ~SBICF_ICMD;
1304 return -1;
1308 * Wait for a phase change (or error) then let the
1309 * device sequence us through the various SCSI phases.
1312 wait = sbic_cmd_wait;
1314 GET_SBIC_asr (regs, asr);
1315 GET_SBIC_csr (regs, csr);
1316 CSR_TRACE('I',csr,asr,target);
1317 QPRINTF((">ASR:%02xCSR:%02x<", asr, csr));
1319 #if CSR_LOG_BUF_SIZE
1320 csrbuf[bufptr++] = csr;
1321 #endif
1324 switch (csr) {
1325 case SBIC_CSR_S_XFERRED:
1326 case SBIC_CSR_DISC:
1327 case SBIC_CSR_DISC_1:
1328 dev->sc_flags &= ~SBICF_SELECTED;
1329 GET_SBIC_cmd_phase (regs, phase);
1330 if (phase == 0x60) {
1331 GET_SBIC_tlun (regs, dev->sc_stat[0]);
1332 i = 0; /* done */
1333 /* break;*/ /* Bypass all the state gobldygook */
1334 } else {
1335 DBGPRINTF(("sbicicmd: handling disconnect\n"),
1336 reselect_debug > 1);
1338 i = SBIC_STATE_DISCONNECT;
1340 break;
1342 case SBIC_CSR_XFERRED | CMD_PHASE:
1343 case SBIC_CSR_MIS | CMD_PHASE:
1344 case SBIC_CSR_MIS_1 | CMD_PHASE:
1345 case SBIC_CSR_MIS_2 | CMD_PHASE:
1346 if (sbicxfstart(regs, clen, CMD_PHASE, sbic_cmd_wait))
1347 if (sbicxfout(regs, clen,
1348 cbuf, CMD_PHASE))
1349 i = sbicabort(dev, regs,
1350 "icmd sending cmd");
1351 #if 0
1352 GET_SBIC_csr(regs, csr); /* Lets us reload tcount */
1353 WAIT_CIP(regs);
1354 GET_SBIC_asr(regs, asr);
1355 CSR_TRACE('I',csr,asr,target);
1356 if (asr & (SBIC_ASR_BSY | SBIC_ASR_LCI | SBIC_ASR_CIP))
1357 printf("next: cmd sent asr %02x, csr %02x\n",
1358 asr, csr);
1359 #endif
1360 break;
1362 #if 0
1363 case SBIC_CSR_XFERRED | DATA_OUT_PHASE:
1364 case SBIC_CSR_XFERRED | DATA_IN_PHASE:
1365 case SBIC_CSR_MIS | DATA_OUT_PHASE:
1366 case SBIC_CSR_MIS | DATA_IN_PHASE:
1367 case SBIC_CSR_MIS_1 | DATA_OUT_PHASE:
1368 case SBIC_CSR_MIS_1 | DATA_IN_PHASE:
1369 case SBIC_CSR_MIS_2 | DATA_OUT_PHASE:
1370 case SBIC_CSR_MIS_2 | DATA_IN_PHASE:
1371 if (acb->datalen <= 0)
1372 i = sbicabort(dev, regs, "icmd out of data");
1373 else {
1374 wait = sbic_data_wait;
1375 if (sbicxfstart(regs, acb->datalen,
1376 SBIC_PHASE(csr), wait))
1377 if (csr & 0x01)
1378 /* data in? */
1379 i = sbicxfin(regs, acb->datalen, acb->data);
1380 else
1381 i = sbicxfout(regs, acb->datalen, acb->data,
1382 SBIC_PHASE(csr));
1383 acb->data += acb->datalen - i;
1384 acb->datalen = i;
1385 i = 1;
1387 break;
1389 #endif
1390 case SBIC_CSR_XFERRED | STATUS_PHASE:
1391 case SBIC_CSR_MIS | STATUS_PHASE:
1392 case SBIC_CSR_MIS_1 | STATUS_PHASE:
1393 case SBIC_CSR_MIS_2 | STATUS_PHASE:
1395 * the sbic does the status/cmd-complete reading ok,
1396 * so do this with its hi-level commands.
1398 DBGPRINTF(("SBICICMD status phase\n"), sbic_debug);
1400 SBIC_TC_PUT(regs, 0);
1401 SET_SBIC_cmd_phase(regs, 0x46);
1402 SET_SBIC_cmd(regs, SBIC_CMD_SEL_ATN_XFER);
1403 break;
1405 #if THIS_IS_A_RESERVED_STATE
1406 case BUS_FREE_PHASE: /* This is not legal */
1407 if (dev->sc_stat[0] != 0xff)
1408 goto out;
1409 break;
1410 #endif
1412 default:
1413 i = sbicnextstate(dev, csr, asr);
1417 * make sure the last command was taken,
1418 * ie. we're not hunting after an ignored command..
1420 GET_SBIC_asr(regs, asr);
1422 /* tapes may take a loooong time.. */
1423 while (asr & SBIC_ASR_BSY){
1424 if (asr & SBIC_ASR_DBR) {
1425 printf("sbicicmd: Waiting while sbic is "
1426 "jammed, CSR:%02x,ASR:%02x\n",
1427 csr, asr);
1428 #ifdef DDB
1429 Debugger();
1430 #endif
1431 /* SBIC is jammed */
1432 /* DUNNO which direction */
1433 /* Try old direction */
1434 GET_SBIC_data(regs,i);
1435 GET_SBIC_asr(regs, asr);
1436 if (asr & SBIC_ASR_DBR) /* Wants us to write */
1437 SET_SBIC_data(regs,i);
1439 GET_SBIC_asr(regs, asr);
1443 * wait for last command to complete
1445 if (asr & SBIC_ASR_LCI) {
1446 printf("sbicicmd: last command ignored\n");
1448 else if (i == 1) /* Bsy */
1449 SBIC_WAIT(regs, SBIC_ASR_INT, wait);
1452 * do it again
1454 } while (i > 0 && dev->sc_stat[0] == 0xff);
1456 /* Sometimes we need to do an extra read of the CSR */
1457 GET_SBIC_csr(regs, csr);
1458 CSR_TRACE('I',csr,asr,0xff);
1460 #if CSR_LOG_BUF_SIZE
1461 if (reselect_debug > 1)
1462 for (i = 0; i < bufptr; i++)
1463 printf("CSR:%02x", csrbuf[i]);
1464 #endif
1466 DBGPRINTF(("sbicicmd done(%d,%d):%d =%d=\n",
1467 dev->target, lun,
1468 acb->datalen,
1469 dev->sc_stat[0]),
1470 data_pointer_debug > 1);
1472 QPRINTF(("=STS:%02x=", dev->sc_stat[0]));
1473 dev->sc_flags &= ~SBICF_ICMD;
1475 SBIC_TRACE(dev);
1476 return dev->sc_stat[0];
1480 * Finish SCSI xfer command: After the completion interrupt from
1481 * a read/write operation, sequence through the final phases in
1482 * programmed i/o. This routine is a lot like sbicicmd except we
1483 * skip (and don't allow) the select, cmd out and data in/out phases.
1485 static void
1486 sbicxfdone(struct sbic_softc *dev, sbic_regmap_p regs, int target)
1488 u_char phase, asr, csr;
1489 int s;
1491 SBIC_TRACE(dev);
1492 QPRINTF(("{"));
1493 s = splbio();
1496 * have the sbic complete on its own
1498 SBIC_TC_PUT(regs, 0);
1499 SET_SBIC_cmd_phase(regs, 0x46);
1500 SET_SBIC_cmd(regs, SBIC_CMD_SEL_ATN_XFER);
1502 do {
1503 asr = SBIC_WAIT (regs, SBIC_ASR_INT, 0);
1504 GET_SBIC_csr (regs, csr);
1505 CSR_TRACE('f',csr,asr,target);
1506 QPRINTF(("%02x:", csr));
1507 } while ((csr != SBIC_CSR_DISC) && (csr != SBIC_CSR_DISC_1)
1508 && (csr != SBIC_CSR_S_XFERRED));
1510 dev->sc_flags &= ~SBICF_SELECTED;
1512 GET_SBIC_cmd_phase (regs, phase);
1513 QPRINTF(("}%02x", phase));
1514 if (phase == 0x60)
1515 GET_SBIC_tlun(regs, dev->sc_stat[0]);
1516 else
1517 sbicerror(dev, regs, csr);
1519 QPRINTF(("=STS:%02x=\n", dev->sc_stat[0]));
1520 splx(s);
1521 SBIC_TRACE(dev);
1525 * No DMA chains
1528 static int
1529 sbicgo(struct sbic_softc *dev, struct scsipi_xfer *xs)
1531 int i, usedma;
1532 /* int dmaflags, count; */
1533 /* int wait;*/
1534 /* u_char cmd;*/
1535 u_char asr = 0, csr = 0;
1536 /* u_char *addr; */
1537 sbic_regmap_p regs;
1538 struct sbic_acb *acb;
1540 SBIC_TRACE(dev);
1541 dev->target = xs->xs_periph->periph_target;
1542 dev->lun = xs->xs_periph->periph_lun;
1543 acb = dev->sc_nexus;
1544 regs = &dev->sc_sbicp;
1546 usedma = acb->flags & ACB_DMA;
1548 DBG(routine = 1);
1549 DBG(debug_sbic_regs = regs); /* store this to allow debug calls */
1550 DBGPRINTF(("sbicgo(%d,%d)\n", dev->target, dev->lun),
1551 data_pointer_debug > 1);
1554 * set the sbic into DMA mode
1556 if (usedma)
1557 SET_SBIC_control(regs,
1558 SBIC_CTL_EDI | SBIC_CTL_IDI | dev->sc_dmamode);
1559 else
1560 SET_SBIC_control(regs, SBIC_CTL_EDI | SBIC_CTL_IDI);
1564 * select the SCSI bus (it's an error if bus isn't free)
1566 if (sbicselectbus(dev, regs, dev->target, dev->lun,
1567 dev->sc_scsiaddr)) {
1568 /* printf("sbicgo: Trying to select busy bus!\n"); */
1569 SBIC_TRACE(dev);
1570 /* Not done: may need to be rescheduled */
1571 return 0;
1573 dev->sc_stat[0] = 0xff;
1576 * Allocate the DMA chain
1579 /* Mark end of segment */
1580 acb->sc_tcnt = 0;
1582 SBIC_TRACE(dev);
1583 /* Enable interrupts */
1584 dev->sc_enintr(dev);
1585 if (usedma) {
1586 int tcnt;
1588 acb->offset = 0;
1589 acb->sc_tcnt = 0;
1590 /* Note, this does not start DMA */
1591 tcnt = dev->sc_dmasetup(dev->sc_dmah, dev->sc_dmat, acb,
1592 (acb->flags & ACB_DATAIN) != 0);
1594 DBG(dev->sc_dmatimo = tcnt ? 1 : 0);
1595 DBG(++sbicdma_ops); /* count total DMA operations */
1598 SBIC_TRACE(dev);
1601 * enintr() also enables interrupts for the sbic
1603 DBG(debug_asr = asr);
1604 DBG(debug_csr = csr);
1607 * Lets cycle a while then let the interrupt handler take over
1610 GET_SBIC_asr(regs, asr);
1611 do {
1612 GET_SBIC_csr(regs, csr);
1613 CSR_TRACE('g', csr, asr, dev->target);
1615 DBG(debug_csr = csr);
1616 DBG(routine = 1);
1618 QPRINTF(("go[0x%x]", csr));
1620 i = sbicnextstate(dev, csr, asr);
1622 WAIT_CIP(regs);
1623 GET_SBIC_asr(regs, asr);
1625 DBG(debug_asr = asr);
1627 if (asr & SBIC_ASR_LCI)
1628 printf("sbicgo: LCI asr:%02x csr:%02x\n", asr, csr);
1629 } while (i == SBIC_STATE_RUNNING &&
1630 (asr & (SBIC_ASR_INT | SBIC_ASR_LCI)));
1632 CSR_TRACE('g',csr,asr,i<<4);
1633 SBIC_TRACE(dev);
1634 if (i == SBIC_STATE_DONE && dev->sc_stat[0] == 0xff)
1635 printf("sbicgo: done & stat = 0xff\n");
1636 if (i == SBIC_STATE_DONE && dev->sc_stat[0] != 0xff) {
1637 /* if (i == SBIC_STATE_DONE && dev->sc_stat[0]) { */
1638 /* Did we really finish that fast? */
1639 return 1;
1641 return 0;
1646 sbicintr(struct sbic_softc *dev)
1648 sbic_regmap_p regs;
1649 u_char asr, csr;
1650 /* u_char *tmpaddr;*/
1651 /* struct sbic_acb *acb;*/
1652 int i;
1653 /* int newtarget, newlun;*/
1654 /* unsigned tcnt;*/
1656 regs = &dev->sc_sbicp;
1659 * pending interrupt?
1661 GET_SBIC_asr (regs, asr);
1662 if ((asr & SBIC_ASR_INT) == 0)
1663 return 0;
1665 SBIC_TRACE(dev);
1666 do {
1667 GET_SBIC_csr(regs, csr);
1668 CSR_TRACE('i',csr,asr,dev->target);
1670 DBG(debug_csr = csr);
1671 DBG(routine = 2);
1673 QPRINTF(("intr[0x%x]", csr));
1675 i = sbicnextstate(dev, csr, asr);
1677 WAIT_CIP(regs);
1678 GET_SBIC_asr(regs, asr);
1680 DBG(debug_asr = asr);
1682 #if 0
1683 if (asr & SBIC_ASR_LCI)
1684 printf("sbicintr: LCI asr:%02x csr:%02x\n", asr, csr);
1685 #endif
1686 } while (i == SBIC_STATE_RUNNING &&
1687 (asr & (SBIC_ASR_INT | SBIC_ASR_LCI)));
1688 CSR_TRACE('i', csr, asr, i << 4);
1689 SBIC_TRACE(dev);
1690 return 1;
1694 * Run commands and wait for disconnect
1696 static int
1697 sbicpoll(struct sbic_softc *dev)
1699 sbic_regmap_p regs;
1700 u_char asr, csr;
1701 /* struct sbic_pending* pendp;*/
1702 int i;
1703 /* unsigned tcnt;*/
1705 SBIC_TRACE(dev);
1706 regs = &dev->sc_sbicp;
1708 do {
1709 GET_SBIC_asr (regs, asr);
1711 DBG(debug_asr = asr);
1713 GET_SBIC_csr(regs, csr);
1714 CSR_TRACE('p', csr, asr, dev->target);
1716 DBG(debug_csr = csr);
1717 DBG(routine = 2);
1719 QPRINTF(("poll[0x%x]", csr));
1721 i = sbicnextstate(dev, csr, asr);
1723 WAIT_CIP(regs);
1724 GET_SBIC_asr(regs, asr);
1725 /* tapes may take a loooong time.. */
1726 while (asr & SBIC_ASR_BSY){
1727 if (asr & SBIC_ASR_DBR) {
1728 printf("sbipoll: Waiting while sbic is "
1729 "jammed, CSR:%02x,ASR:%02x\n",
1730 csr, asr);
1731 #ifdef DDB
1732 Debugger();
1733 #endif
1734 /* SBIC is jammed */
1735 /* DUNNO which direction */
1736 /* Try old direction */
1737 GET_SBIC_data(regs,i);
1738 GET_SBIC_asr(regs, asr);
1739 if (asr & SBIC_ASR_DBR) /* Wants us to write */
1740 SET_SBIC_data(regs,i);
1742 GET_SBIC_asr(regs, asr);
1745 if (asr & SBIC_ASR_LCI)
1746 printf("sbicpoll: LCI asr:%02x csr:%02x\n", asr, csr);
1747 else if (i == 1) /* BSY */
1748 SBIC_WAIT(regs, SBIC_ASR_INT, sbic_cmd_wait);
1749 } while (i == SBIC_STATE_RUNNING);
1750 CSR_TRACE('p', csr, asr, i << 4);
1751 SBIC_TRACE(dev);
1752 return 1;
1756 * Handle a single msgin
1759 static int
1760 sbicmsgin(struct sbic_softc *dev)
1762 sbic_regmap_p regs;
1763 int recvlen;
1764 u_char asr, csr, *tmpaddr;
1766 regs = &dev->sc_sbicp;
1768 dev->sc_msg[0] = 0xff;
1769 dev->sc_msg[1] = 0xff;
1771 GET_SBIC_asr(regs, asr);
1773 DBGPRINTF(("sbicmsgin asr=%02x\n", asr), reselect_debug > 1);
1775 sbic_save_ptrs(dev, regs);
1777 GET_SBIC_selid (regs, csr);
1778 SET_SBIC_selid (regs, csr | SBIC_SID_FROM_SCSI);
1780 SBIC_TC_PUT(regs, 0);
1781 tmpaddr = dev->sc_msg;
1782 recvlen = 1;
1783 do {
1784 while (recvlen--) {
1785 GET_SBIC_asr(regs, asr);
1786 GET_SBIC_csr(regs, csr);
1787 QPRINTF(("sbicmsgin ready to go (csr,asr)=(%02x,%02x)\n",
1788 csr, asr));
1790 RECV_BYTE(regs, *tmpaddr);
1791 CSR_TRACE('m', csr, asr, *tmpaddr);
1792 #if 1
1794 * get the command completion interrupt, or we
1795 * can't send a new command (LCI)
1797 SBIC_WAIT(regs, SBIC_ASR_INT, 0);
1798 GET_SBIC_csr(regs, csr);
1799 CSR_TRACE('X', csr, asr, dev->target);
1800 #else
1801 WAIT_CIP(regs);
1802 do {
1803 GET_SBIC_asr(regs, asr);
1804 csr = 0xff;
1805 GET_SBIC_csr(regs, csr);
1806 CSR_TRACE('X', csr, asr, dev->target);
1807 if (csr == 0xff)
1808 printf("sbicmsgin waiting: csr %02x "
1809 "asr %02x\n", csr, asr);
1810 } while (csr == 0xff);
1811 #endif
1813 DBGPRINTF(("sbicmsgin: got %02x csr %02x asr %02x\n",
1814 *tmpaddr, csr, asr), reselect_debug > 1);
1816 #if do_parity_check
1817 if (asr & SBIC_ASR_PE) {
1818 printf("Parity error");
1819 /* This code simply does not work. */
1820 WAIT_CIP(regs);
1821 SET_SBIC_cmd(regs, SBIC_CMD_SET_ATN);
1822 WAIT_CIP(regs);
1823 GET_SBIC_asr(regs, asr);
1824 WAIT_CIP(regs);
1825 SET_SBIC_cmd(regs, SBIC_CMD_CLR_ACK);
1826 WAIT_CIP(regs);
1827 if (!(asr & SBIC_ASR_LCI))
1828 /* Target wants to send garbled msg*/
1829 continue;
1830 printf("--fixing\n");
1831 /* loop until a msgout phase occurs on
1832 target */
1833 while ((csr & 0x07) != MESG_OUT_PHASE) {
1834 while ((asr & SBIC_ASR_BSY) &&
1835 !(asr &
1836 (SBIC_ASR_DBR | SBIC_ASR_INT)))
1837 GET_SBIC_asr(regs, asr);
1838 if (asr & SBIC_ASR_DBR)
1839 panic("msgin: jammed again!");
1840 GET_SBIC_csr(regs, csr);
1841 CSR_TRACE('e', csr, asr, dev->target);
1842 if ((csr & 0x07) != MESG_OUT_PHASE) {
1843 sbicnextstate(dev, csr, asr);
1844 sbic_save_ptrs(dev, regs);
1847 /* Should be msg out by now */
1848 SEND_BYTE(regs, MSG_PARITY_ERROR);
1850 else
1851 #endif
1852 tmpaddr++;
1854 if (recvlen) {
1855 /* Clear ACK */
1856 WAIT_CIP(regs);
1857 GET_SBIC_asr(regs, asr);
1858 GET_SBIC_csr(regs, csr);
1859 CSR_TRACE('X',csr,asr,dev->target);
1860 QPRINTF(("sbicmsgin pre byte CLR_ACK (csr,asr)=(%02x,%02x)\n",
1861 csr, asr));
1862 SET_SBIC_cmd(regs, SBIC_CMD_CLR_ACK);
1863 SBIC_WAIT(regs, SBIC_ASR_INT, 0);
1868 if (dev->sc_msg[0] == 0xff) {
1869 printf("sbicmsgin: sbic swallowed our message\n");
1870 break;
1873 DBGPRINTF(("msgin done csr 0x%x asr 0x%x msg 0x%x\n",
1874 csr, asr, dev->sc_msg[0]), sync_debug);
1877 * test whether this is a reply to our sync
1878 * request
1880 if (MSG_ISIDENTIFY(dev->sc_msg[0])) {
1881 QPRINTF(("IFFY"));
1882 /* Got IFFY msg -- ack it */
1883 } else if (dev->sc_msg[0] == MSG_REJECT
1884 && dev->sc_sync[dev->target].state == SYNC_SENT) {
1885 QPRINTF(("REJECT of SYN"));
1887 DBGPRINTF(("target %d rejected sync, going async\n",
1888 dev->target), sync_debug);
1890 dev->sc_sync[dev->target].period = sbic_min_period;
1891 dev->sc_sync[dev->target].offset = 0;
1892 dev->sc_sync[dev->target].state = SYNC_DONE;
1893 SET_SBIC_syn(regs,
1894 SBIC_SYN(dev->sc_sync[dev->target].offset,
1895 dev->sc_sync[dev->target].period));
1896 } else if ((dev->sc_msg[0] == MSG_REJECT)) {
1897 QPRINTF(("REJECT"));
1899 * we'll never REJECt a REJECT message..
1901 } else if ((dev->sc_msg[0] == MSG_SAVE_DATA_PTR)) {
1902 QPRINTF(("MSG_SAVE_DATA_PTR"));
1904 * don't reject this either.
1906 } else if ((dev->sc_msg[0] == MSG_DISCONNECT)) {
1907 QPRINTF(("DISCONNECT"));
1909 DBGPRINTF(("sbicmsgin: got disconnect msg %s\n",
1910 (dev->sc_flags & SBICF_ICMD) ? "rejecting" : ""),
1911 reselect_debug > 1 &&
1912 dev->sc_msg[0] == MSG_DISCONNECT);
1914 if (dev->sc_flags & SBICF_ICMD) {
1915 /* We're in immediate mode. Prevent
1916 disconnects. */
1917 /* prepare to reject the message, NACK */
1918 SET_SBIC_cmd(regs, SBIC_CMD_SET_ATN);
1919 WAIT_CIP(regs);
1921 } else if (dev->sc_msg[0] == MSG_CMD_COMPLETE) {
1922 QPRINTF(("CMD_COMPLETE"));
1923 /* !! KLUDGE ALERT !! quite a few drives don't seem to
1924 * really like the current way of sending the
1925 * sync-handshake together with the ident-message, and
1926 * they react by sending command-complete and
1927 * disconnecting right after returning the valid sync
1928 * handshake. So, all I can do is reselect the drive,
1929 * and hope it won't disconnect again. I don't think
1930 * this is valid behavior, but I can't help fixing a
1931 * problem that apparently exists.
1933 * Note: we should not get here on `normal' command
1934 * completion, as that condition is handled by the
1935 * high-level sel&xfer resume command used to walk
1936 * thru status/cc-phase.
1939 DBGPRINTF(("GOT MSG %d! target %d acting weird.."
1940 " waiting for disconnect...\n",
1941 dev->sc_msg[0], dev->target), sync_debug);
1943 /* Check to see if sbic is handling this */
1944 GET_SBIC_asr(regs, asr);
1945 if (asr & SBIC_ASR_BSY)
1946 return SBIC_STATE_RUNNING;
1948 /* Let's try this: Assume it works and set
1949 status to 00 */
1950 dev->sc_stat[0] = 0;
1951 } else if (dev->sc_msg[0] == MSG_EXT_MESSAGE
1952 && tmpaddr == &dev->sc_msg[1]) {
1953 QPRINTF(("ExtMSG\n"));
1954 /* Read in whole extended message */
1955 SET_SBIC_cmd(regs, SBIC_CMD_CLR_ACK);
1956 SBIC_WAIT(regs, SBIC_ASR_INT, 0);
1957 GET_SBIC_asr(regs, asr);
1958 GET_SBIC_csr(regs, csr);
1959 QPRINTF(("CLR ACK asr %02x, csr %02x\n", asr, csr));
1960 RECV_BYTE(regs, *tmpaddr);
1961 CSR_TRACE('x',csr,asr,*tmpaddr);
1962 /* Wait for command completion IRQ */
1963 SBIC_WAIT(regs, SBIC_ASR_INT, 0);
1964 recvlen = *tmpaddr++;
1965 QPRINTF(("Recving ext msg, asr %02x csr %02x len %02x\n",
1966 asr, csr, recvlen));
1967 } else if (dev->sc_msg[0] == MSG_EXT_MESSAGE &&
1968 dev->sc_msg[1] == 3 &&
1969 dev->sc_msg[2] == MSG_SYNC_REQ) {
1970 QPRINTF(("SYN"));
1971 dev->sc_sync[dev->target].period =
1972 sbicfromscsiperiod(dev,
1973 regs, dev->sc_msg[3]);
1974 dev->sc_sync[dev->target].offset = dev->sc_msg[4];
1975 dev->sc_sync[dev->target].state = SYNC_DONE;
1976 SET_SBIC_syn(regs,
1977 SBIC_SYN(dev->sc_sync[dev->target].offset,
1978 dev->sc_sync[dev->target].period));
1979 printf("%s: target %d now synchronous,"
1980 " period=%dns, offset=%d.\n",
1981 device_xname(&dev->sc_dev), dev->target,
1982 dev->sc_msg[3] * 4, dev->sc_msg[4]);
1983 } else {
1985 DBGPRINTF(("sbicmsgin: Rejecting message 0x%02x\n",
1986 dev->sc_msg[0]), sbic_debug || sync_debug);
1988 /* prepare to reject the message, NACK */
1989 SET_SBIC_cmd(regs, SBIC_CMD_SET_ATN);
1990 WAIT_CIP(regs);
1992 /* Clear ACK */
1993 WAIT_CIP(regs);
1994 GET_SBIC_asr(regs, asr);
1995 GET_SBIC_csr(regs, csr);
1996 CSR_TRACE('X',csr,asr,dev->target);
1997 QPRINTF(("sbicmsgin pre CLR_ACK (csr,asr)=(%02x,%02x)%d\n",
1998 csr, asr, recvlen));
1999 SET_SBIC_cmd(regs, SBIC_CMD_CLR_ACK);
2000 SBIC_WAIT(regs, SBIC_ASR_INT, 0);
2002 #if 0
2003 while ((csr == SBIC_CSR_MSGIN_W_ACK) ||
2004 (SBIC_PHASE(csr) == MESG_IN_PHASE));
2005 #else
2006 while (recvlen > 0);
2007 #endif
2009 QPRINTF(("sbicmsgin finished: csr %02x, asr %02x\n",csr, asr));
2011 /* Should still have one CSR to read */
2012 return SBIC_STATE_RUNNING;
2017 * sbicnextstate()
2018 * return:
2019 * 0 == done
2020 * 1 == working
2021 * 2 == disconnected
2022 * -1 == error
2024 static int
2025 sbicnextstate(struct sbic_softc *dev, u_char csr, u_char asr)
2027 sbic_regmap_p regs;
2028 struct sbic_acb *acb;
2029 /* int i;*/
2030 int newtarget, newlun, wait;
2031 /* unsigned tcnt;*/
2033 SBIC_TRACE(dev);
2034 regs = &dev->sc_sbicp;
2035 acb = dev->sc_nexus;
2037 QPRINTF(("next[%02x,%02x]",asr,csr));
2039 switch (csr) {
2040 case SBIC_CSR_XFERRED | CMD_PHASE:
2041 case SBIC_CSR_MIS | CMD_PHASE:
2042 case SBIC_CSR_MIS_1 | CMD_PHASE:
2043 case SBIC_CSR_MIS_2 | CMD_PHASE:
2044 sbic_save_ptrs(dev, regs);
2045 if (sbicxfstart(regs, acb->clen, CMD_PHASE, sbic_cmd_wait))
2046 if (sbicxfout(regs, acb->clen,
2047 &acb->cmd, CMD_PHASE))
2048 goto abort;
2049 break;
2051 case SBIC_CSR_XFERRED | STATUS_PHASE:
2052 case SBIC_CSR_MIS | STATUS_PHASE:
2053 case SBIC_CSR_MIS_1 | STATUS_PHASE:
2054 case SBIC_CSR_MIS_2 | STATUS_PHASE:
2056 * this should be the normal i/o completion case.
2057 * get the status & cmd complete msg then let the
2058 * device driver look at what happened.
2060 sbicxfdone(dev,regs,dev->target);
2062 if (acb->flags & ACB_DMA) {
2063 DBG(dev->sc_dmatimo = 0);
2065 dev->sc_dmafinish(dev->sc_dmah, dev->sc_dmat, acb);
2067 dev->sc_flags &= ~SBICF_INDMA;
2069 sbic_scsidone(acb, dev->sc_stat[0]);
2070 SBIC_TRACE(dev);
2071 return SBIC_STATE_DONE;
2073 case SBIC_CSR_XFERRED | DATA_OUT_PHASE:
2074 case SBIC_CSR_XFERRED | DATA_IN_PHASE:
2075 case SBIC_CSR_MIS | DATA_OUT_PHASE:
2076 case SBIC_CSR_MIS | DATA_IN_PHASE:
2077 case SBIC_CSR_MIS_1 | DATA_OUT_PHASE:
2078 case SBIC_CSR_MIS_1 | DATA_IN_PHASE:
2079 case SBIC_CSR_MIS_2 | DATA_OUT_PHASE:
2080 case SBIC_CSR_MIS_2 | DATA_IN_PHASE:
2082 int i = 0;
2084 if ((acb->xs->xs_control & XS_CTL_POLL) ||
2085 (dev->sc_flags & SBICF_ICMD) ||
2086 (acb->flags & ACB_DMA) == 0) {
2087 /* Do PIO */
2088 SET_SBIC_control(regs, SBIC_CTL_EDI | SBIC_CTL_IDI);
2089 if (acb->datalen <= 0) {
2090 printf("sbicnextstate:xfer count %d asr%x csr%x\n",
2091 acb->datalen, asr, csr);
2092 goto abort;
2094 wait = sbic_data_wait;
2095 if (sbicxfstart(regs, acb->datalen,
2096 SBIC_PHASE(csr), wait)) {
2097 if (SBIC_PHASE(csr) == DATA_IN_PHASE)
2098 /* data in? */
2099 i = sbicxfin(regs, acb->datalen,
2100 acb->data);
2101 else
2102 i = sbicxfout(regs, acb->datalen,
2103 acb->data, SBIC_PHASE(csr));
2105 acb->data += acb->datalen - i;
2106 acb->datalen = i;
2107 } else {
2108 /* Transfer = using DMA */
2110 * do scatter-gather dma
2111 * hacking the controller chip, ouch..
2113 SET_SBIC_control(regs,
2114 SBIC_CTL_EDI | SBIC_CTL_IDI | dev->sc_dmamode);
2116 * set next dma addr and dec count
2118 sbic_save_ptrs(dev, regs);
2120 if (acb->offset >= acb->datalen) {
2121 printf("sbicnextstate:xfer offset %d asr%x csr%x\n",
2122 acb->offset, asr, csr);
2123 goto abort;
2125 DBGPRINTF(("next dmanext: %d(offset %d)\n",
2126 dev->target, acb->offset),
2127 data_pointer_debug > 1);
2128 DBG(dev->sc_dmatimo = 1);
2130 acb->sc_tcnt =
2131 dev->sc_dmanext(dev->sc_dmah, dev->sc_dmat,
2132 acb, acb->offset);
2133 DBGPRINTF(("dmanext transfering %ld bytes\n",
2134 acb->sc_tcnt), data_pointer_debug);
2135 SBIC_TC_PUT(regs, (unsigned)acb->sc_tcnt);
2136 SET_SBIC_cmd(regs, SBIC_CMD_XFER_INFO);
2137 dev->sc_flags |= SBICF_INDMA;
2139 break;
2141 case SBIC_CSR_XFERRED | MESG_IN_PHASE:
2142 case SBIC_CSR_MIS | MESG_IN_PHASE:
2143 case SBIC_CSR_MIS_1 | MESG_IN_PHASE:
2144 case SBIC_CSR_MIS_2 | MESG_IN_PHASE:
2145 SBIC_TRACE(dev);
2146 return sbicmsgin(dev);
2148 case SBIC_CSR_MSGIN_W_ACK:
2149 /* Dunno what I'm ACKing */
2150 SET_SBIC_cmd(regs, SBIC_CMD_CLR_ACK);
2151 printf("Acking unknown msgin CSR:%02x",csr);
2152 break;
2154 case SBIC_CSR_XFERRED | MESG_OUT_PHASE:
2155 case SBIC_CSR_MIS | MESG_OUT_PHASE:
2156 case SBIC_CSR_MIS_1 | MESG_OUT_PHASE:
2157 case SBIC_CSR_MIS_2 | MESG_OUT_PHASE:
2159 DBGPRINTF(("sending REJECT msg to last msg.\n"), sync_debug);
2161 sbic_save_ptrs(dev, regs);
2163 * Should only get here on reject, since it's always
2164 * US that initiate a sync transfer.
2166 SEND_BYTE(regs, MSG_REJECT);
2167 WAIT_CIP(regs);
2168 if (asr & (SBIC_ASR_BSY | SBIC_ASR_LCI | SBIC_ASR_CIP))
2169 printf("next: REJECT sent asr %02x\n", asr);
2170 SBIC_TRACE(dev);
2171 return SBIC_STATE_RUNNING;
2173 case SBIC_CSR_DISC:
2174 case SBIC_CSR_DISC_1:
2175 dev->sc_flags &= ~(SBICF_INDMA | SBICF_SELECTED);
2177 /* Try to schedule another target */
2178 DBGPRINTF(("sbicnext target %d disconnected\n", dev->target),
2179 reselect_debug > 1);
2181 TAILQ_INSERT_HEAD(&dev->nexus_list, acb, chain);
2182 ++dev->sc_tinfo[dev->target].dconns;
2183 dev->sc_nexus = NULL;
2185 if ((acb->xs->xs_control & XS_CTL_POLL)
2186 || (dev->sc_flags & SBICF_ICMD)
2187 || (!sbic_parallel_operations)) {
2188 SBIC_TRACE(dev);
2189 return SBIC_STATE_DISCONNECT;
2191 sbic_sched(dev);
2192 SBIC_TRACE(dev);
2193 return SBIC_STATE_DISCONNECT;
2195 case SBIC_CSR_RSLT_NI:
2196 case SBIC_CSR_RSLT_IFY:
2197 GET_SBIC_rselid(regs, newtarget);
2198 /* check SBIC_RID_SIV? */
2199 newtarget &= SBIC_RID_MASK;
2200 if (csr == SBIC_CSR_RSLT_IFY) {
2201 /* Read IFY msg to avoid lockup */
2202 GET_SBIC_data(regs, newlun);
2203 WAIT_CIP(regs);
2204 newlun &= SBIC_TLUN_MASK;
2205 CSR_TRACE('r',csr,asr,newtarget);
2206 } else {
2207 /* Need to get IFY message */
2208 for (newlun = 256; newlun; --newlun) {
2209 GET_SBIC_asr(regs, asr);
2210 if (asr & SBIC_ASR_INT)
2211 break;
2212 delay(1);
2214 newlun = 0; /* XXXX */
2215 if ((asr & SBIC_ASR_INT) == 0) {
2217 DBGPRINTF(("RSLT_NI - no IFFY message? asr %x\n",
2218 asr), reselect_debug);
2220 } else {
2221 GET_SBIC_csr(regs,csr);
2222 CSR_TRACE('n',csr,asr,newtarget);
2223 if ((csr == (SBIC_CSR_MIS | MESG_IN_PHASE)) ||
2224 (csr == (SBIC_CSR_MIS_1 | MESG_IN_PHASE)) ||
2225 (csr == (SBIC_CSR_MIS_2 | MESG_IN_PHASE))) {
2226 sbicmsgin(dev);
2227 newlun = dev->sc_msg[0] & 7;
2228 } else {
2229 printf("RSLT_NI - not MESG_IN_PHASE %x\n",
2230 csr);
2235 DBGPRINTF(("sbicnext: reselect %s from targ %d lun %d\n",
2236 csr == SBIC_CSR_RSLT_NI ? "NI" : "IFY",
2237 newtarget, newlun),
2238 reselect_debug > 1 ||
2239 (reselect_debug && csr == SBIC_CSR_RSLT_NI));
2241 if (dev->sc_nexus) {
2242 DBGPRINTF(("%s: reselect %s with active command\n",
2243 device_xname(&dev->sc_dev),
2244 csr == SBIC_CSR_RSLT_NI ? "NI" : "IFY"),
2245 reselect_debug > 1);
2246 #if defined(DDB) && defined (DEBUG)
2247 /* Debugger();*/
2248 #endif
2250 TAILQ_INSERT_HEAD(&dev->ready_list, dev->sc_nexus,
2251 chain);
2252 dev->sc_tinfo[dev->target].lubusy &= ~(1 << dev->lun);
2253 dev->sc_nexus = NULL;
2255 /* Reload sync values for this target */
2256 if (dev->sc_sync[newtarget].state == SYNC_DONE)
2257 SET_SBIC_syn(regs,
2258 SBIC_SYN(dev->sc_sync[newtarget].offset,
2259 dev->sc_sync[newtarget].period));
2260 else
2261 SET_SBIC_syn(regs, SBIC_SYN (0, sbic_min_period));
2262 for (acb = dev->nexus_list.tqh_first; acb;
2263 acb = acb->chain.tqe_next) {
2264 if (acb->xs->xs_periph->periph_target != newtarget ||
2265 acb->xs->xs_periph->periph_lun != newlun)
2266 continue;
2267 TAILQ_REMOVE(&dev->nexus_list, acb, chain);
2268 dev->sc_nexus = acb;
2269 dev->sc_flags |= SBICF_SELECTED;
2270 dev->target = newtarget;
2271 dev->lun = newlun;
2272 break;
2274 if (acb == NULL) {
2275 printf("%s: reselect %s targ %d not in nexus_list %p\n",
2276 device_xname(&dev->sc_dev),
2277 csr == SBIC_CSR_RSLT_NI ? "NI" : "IFY", newtarget,
2278 &dev->nexus_list.tqh_first);
2279 panic("bad reselect in sbic");
2281 if (csr == SBIC_CSR_RSLT_IFY)
2282 SET_SBIC_cmd(regs, SBIC_CMD_CLR_ACK);
2283 break;
2285 default:
2286 abort:
2288 * Something unexpected happened -- deal with it.
2290 printf("sbicnextstate: aborting csr %02x asr %02x\n", csr,
2291 asr);
2292 #ifdef DDB
2293 Debugger();
2294 #endif
2295 DBG(dev->sc_dmatimo = 0);
2297 if (dev->sc_flags & SBICF_INDMA) {
2298 dev->sc_dmafinish(dev->sc_dmah, dev->sc_dmat, acb);
2299 dev->sc_flags &= ~SBICF_INDMA;
2300 DBG(dev->sc_dmatimo = 0);
2302 SET_SBIC_control(regs, SBIC_CTL_EDI | SBIC_CTL_IDI);
2303 sbicerror(dev, regs, csr);
2304 sbicabort(dev, regs, "next");
2305 sbic_scsidone(acb, -1);
2306 SBIC_TRACE(dev);
2307 return SBIC_STATE_ERROR;
2310 SBIC_TRACE(dev);
2311 return SBIC_STATE_RUNNING;
2314 static int
2315 sbictoscsiperiod(struct sbic_softc *dev, sbic_regmap_p regs, int a)
2317 unsigned int fs;
2320 * cycle = DIV / (2*CLK)
2321 * DIV = FS+2
2322 * best we can do is 200ns at 20 MHz, 2 cycles
2325 GET_SBIC_myid(regs,fs);
2326 fs = (fs >> 6) + 2; /* DIV */
2327 fs = (fs * 10000) / (dev->sc_clkfreq << 1); /* Cycle, in ns */
2328 if (a < 2)
2329 a = 8; /* map to Cycles */
2330 return (fs * a) >> 2; /* in 4 ns units */
2333 static int
2334 sbicfromscsiperiod(struct sbic_softc *dev, sbic_regmap_p regs, int p)
2336 register unsigned int fs, ret;
2338 /* Just the inverse of the above */
2340 GET_SBIC_myid(regs, fs);
2341 fs = (fs >> 6) + 2; /* DIV */
2342 fs = (fs * 10000) / (dev->sc_clkfreq << 1); /* Cycle, in ns */
2344 ret = p << 2; /* in ns units */
2345 ret = ret / fs; /* in Cycles */
2346 if (ret < sbic_min_period)
2347 return sbic_min_period;
2349 /* verify rounding */
2350 if (sbictoscsiperiod(dev, regs, ret) < p)
2351 ret++;
2352 return (ret >= 8) ? 0 : ret;
2355 #ifdef DEBUG
2357 void
2358 sbicdumpstate(void)
2360 u_char csr, asr;
2362 GET_SBIC_asr(debug_sbic_regs,asr);
2363 GET_SBIC_csr(debug_sbic_regs,csr);
2364 printf("%s: asr:csr(%02x:%02x)->(%02x:%02x)\n",
2365 (routine == 1) ? "sbicgo" :
2366 (routine == 2) ? "sbicintr" :
2367 (routine == 3) ? "sbicicmd" :
2368 (routine == 4) ? "sbicnext" : "unknown",
2369 debug_asr, debug_csr, asr, csr);
2373 void
2374 sbictimeout(struct sbic_softc *dev)
2376 int s, asr;
2378 s = splbio();
2379 if (dev->sc_dmatimo) {
2380 if (dev->sc_dmatimo > 1) {
2381 printf("%s: DMA timeout #%d\n",
2382 device_xname(&dev->sc_dev), dev->sc_dmatimo - 1);
2383 GET_SBIC_asr(&dev->sc_sbicp, asr);
2384 if (asr & SBIC_ASR_INT) {
2385 /* We need to service a missed IRQ */
2386 printf("Servicing a missed int:(%02x,%02x)->(%02x,?)\n",
2387 debug_asr, debug_csr, asr);
2388 sbicintr(dev);
2390 sbicdumpstate();
2392 dev->sc_dmatimo++;
2394 splx(s);
2395 callout_reset(&dev->sc_timo_ch, 30 * hz,
2396 (void *)sbictimeout, dev);
2399 void
2400 sbic_dump_acb(struct sbic_acb *acb)
2402 u_char *b = (u_char *) &acb->cmd;
2403 int i;
2405 printf("acb@%p ", acb);
2406 if (acb->xs == NULL) {
2407 printf("<unused>\n");
2408 return;
2410 printf("(%d:%d) flags %2x clen %2d cmd ",
2411 acb->xs->xs_periph->periph_target,
2412 acb->xs->xs_periph->periph_lun, acb->flags, acb->clen);
2413 for (i = acb->clen; i; --i)
2414 printf(" %02x", *b++);
2415 printf("\n");
2416 printf(" xs: %8p data %8p:%04x ", acb->xs, acb->xs->data,
2417 acb->xs->datalen);
2418 printf("tcnt %lx\n", acb->sc_tcnt);
2421 void
2422 sbic_dump(struct sbic_softc *dev)
2424 sbic_regmap_p regs;
2425 u_char csr, asr;
2426 struct sbic_acb *acb;
2427 int s;
2428 int i;
2430 s = splbio();
2431 regs = &dev->sc_sbicp;
2432 #if CSR_TRACE_SIZE
2433 printf("csr trace: ");
2434 i = csr_traceptr;
2435 do {
2436 printf("%c%02x%02x%02x ", csr_trace[i].whr,
2437 csr_trace[i].csr, csr_trace[i].asr, csr_trace[i].xtn);
2438 switch(csr_trace[i].whr) {
2439 case 'g':
2440 printf("go "); break;
2441 case 's':
2442 printf("select "); break;
2443 case 'y':
2444 printf("select+ "); break;
2445 case 'i':
2446 printf("intr "); break;
2447 case 'f':
2448 printf("finish "); break;
2449 case '>':
2450 printf("out "); break;
2451 case '<':
2452 printf("in "); break;
2453 case 'm':
2454 printf("msgin "); break;
2455 case 'x':
2456 printf("msginx "); break;
2457 case 'X':
2458 printf("msginX "); break;
2459 case 'r':
2460 printf("reselect "); break;
2461 case 'I':
2462 printf("icmd "); break;
2463 case 'a':
2464 printf("abort "); break;
2465 default:
2466 printf("? ");
2468 switch(csr_trace[i].csr) {
2469 case 0x11:
2470 printf("INITIATOR"); break;
2471 case 0x16:
2472 printf("S_XFERRED"); break;
2473 case 0x20:
2474 printf("MSGIN_ACK"); break;
2475 case 0x41:
2476 printf("DISC"); break;
2477 case 0x42:
2478 printf("SEL_TIMEO"); break;
2479 case 0x80:
2480 printf("RSLT_NI"); break;
2481 case 0x81:
2482 printf("RSLT_IFY"); break;
2483 case 0x85:
2484 printf("DISC_1"); break;
2485 case 0x18: case 0x19: case 0x1a:
2486 case 0x1b: case 0x1e: case 0x1f:
2487 case 0x28: case 0x29: case 0x2a:
2488 case 0x2b: case 0x2e: case 0x2f:
2489 case 0x48: case 0x49: case 0x4a:
2490 case 0x4b: case 0x4e: case 0x4f:
2491 case 0x88: case 0x89: case 0x8a:
2492 case 0x8b: case 0x8e: case 0x8f:
2493 switch(csr_trace[i].csr & 0xf0) {
2494 case 0x10:
2495 printf("DONE_"); break;
2496 case 0x20:
2497 printf("STOP_"); break;
2498 case 0x40:
2499 printf("ERR_"); break;
2500 case 0x80:
2501 printf("REQ_"); break;
2503 switch(csr_trace[i].csr & 7) {
2504 case 0:
2505 printf("DATA_OUT"); break;
2506 case 1:
2507 printf("DATA_IN"); break;
2508 case 2:
2509 printf("CMD"); break;
2510 case 3:
2511 printf("STATUS"); break;
2512 case 6:
2513 printf("MSG_OUT"); break;
2514 case 7:
2515 printf("MSG_IN"); break;
2516 default:
2517 printf("invld phs");
2519 break;
2520 default: printf("****"); break;
2522 if (csr_trace[i].asr & SBIC_ASR_INT)
2523 printf(" ASR_INT");
2524 if (csr_trace[i].asr & SBIC_ASR_LCI)
2525 printf(" ASR_LCI");
2526 if (csr_trace[i].asr & SBIC_ASR_BSY)
2527 printf(" ASR_BSY");
2528 if (csr_trace[i].asr & SBIC_ASR_CIP)
2529 printf(" ASR_CIP");
2530 printf("\n");
2531 i = (i + 1) & (CSR_TRACE_SIZE - 1);
2532 } while (i != csr_traceptr);
2533 #endif
2534 GET_SBIC_asr(regs, asr);
2535 if ((asr & SBIC_ASR_INT) == 0)
2536 GET_SBIC_csr(regs, csr);
2537 else
2538 csr = 0;
2539 printf("%s@%p regs %p asr %x csr %x\n", device_xname(&dev->sc_dev),
2540 dev, regs, asr, csr);
2541 if ((acb = dev->free_list.tqh_first)) {
2542 printf("Free list:\n");
2543 while (acb) {
2544 sbic_dump_acb(acb);
2545 acb = acb->chain.tqe_next;
2548 if ((acb = dev->ready_list.tqh_first)) {
2549 printf("Ready list:\n");
2550 while (acb) {
2551 sbic_dump_acb(acb);
2552 acb = acb->chain.tqe_next;
2555 if ((acb = dev->nexus_list.tqh_first)) {
2556 printf("Nexus list:\n");
2557 while (acb) {
2558 sbic_dump_acb(acb);
2559 acb = acb->chain.tqe_next;
2562 if (dev->sc_nexus) {
2563 printf("nexus:\n");
2564 sbic_dump_acb(dev->sc_nexus);
2566 printf("targ %d lun %d flags %x\n",
2567 dev->target, dev->lun, dev->sc_flags);
2568 for (i = 0; i < 8; ++i) {
2569 if (dev->sc_tinfo[i].cmds > 2) {
2570 printf("tgt %d: cmds %d disc %d lubusy %x\n",
2571 i, dev->sc_tinfo[i].cmds,
2572 dev->sc_tinfo[i].dconns,
2573 dev->sc_tinfo[i].lubusy);
2576 splx(s);
2579 #endif