1 /*        $NetBSD: sbc.c,v 1.69 2025/03/10 11:32:24 nat Exp $         */
2 
3 /*
4  * Copyright (C) 1996 Scott Reynolds.  All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  * 3. The name of the author may not be used to endorse or promote products
15  *    derived from this software without specific prior written permission
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 /*
30  * This file contains only the machine-dependent parts of the mac68k
31  * NCR 5380 SCSI driver.  (Autoconfig stuff and PDMA functions.)
32  * The machine-independent parts are in ncr5380sbc.c
33  *
34  * Supported hardware includes:
35  * Macintosh II family 5380-based controller
36  *
37  * Credits, history:
38  *
39  * Scott Reynolds wrote this module, based on work by Allen Briggs
40  * (mac68k), Gordon W. Ross and David Jones (sun3), and Leo Weppelman
41  * (atari).  Thanks to Allen for supplying crucial interpretation of the
42  * NetBSD/mac68k 1.1 'ncrscsi' driver.  Also, Allen, Gordon, and Jason
43  * Thorpe all helped to refine this code, and were considerable sources
44  * of moral support.
45  */
46 
47 #include <sys/cdefs.h>
48 __KERNEL_RCSID(0, "$NetBSD: sbc.c,v 1.69 2025/03/10 11:32:24 nat Exp $");
49 
50 #include "opt_ddb.h"
51 
52 #include <sys/types.h>
53 #include <sys/param.h>
54 #include <sys/systm.h>
55 #include <sys/kernel.h>
56 #include <sys/errno.h>
57 #include <sys/device.h>
58 #include <sys/buf.h>
59 #include <sys/proc.h>
60 
61 #include <dev/scsipi/scsi_all.h>
62 #include <dev/scsipi/scsipi_all.h>
63 #include <dev/scsipi/scsipi_debug.h>
64 #include <dev/scsipi/scsiconf.h>
65 
66 #include <dev/ic/ncr5380reg.h>
67 #include <dev/ic/ncr5380var.h>
68 
69 #include <machine/cpu.h>
70 #include <machine/viareg.h>
71 
72 #include <mac68k/dev/sbcreg.h>
73 #include <mac68k/dev/sbcvar.h>
74 
75 /* SBC_DEBUG --  relies on DDB */
76 #ifdef SBC_DEBUG
77 # define  SBC_DB_INTR         0x01
78 # define  SBC_DB_DMA          0x02
79 # define  SBC_DB_REG          0x04
80 # define  SBC_DB_BREAK        0x08
81 # ifndef DDB
82 #  define Debugger()          printf("Debug: sbc.c:%d\n", __LINE__)
83 # endif
84 # define  SBC_BREAK \
85                     do { if (sbc_debug & SBC_DB_BREAK) Debugger(); } while (0)
86 #else
87 # define  SBC_BREAK
88 #endif
89 
90 
91 int       sbc_debug = 0 /* | SBC_DB_INTR | SBC_DB_DMA */;
92 int       sbc_link_flags = 0 /* | SDEV_DB2 */;
93 int       sbc_options = 0 /* | SBC_PDMA */;
94 
95 extern label_t      *nofault;
96 extern void *       m68k_fault_addr;
97 
98 static    int       sbc_wait_busy(struct ncr5380_softc *);
99 static    int       sbc_ready(struct ncr5380_softc *);
100 static    int       sbc_wait_dreq(struct ncr5380_softc *);
101 
102 
103 /***
104  * General support for Mac-specific SCSI logic.
105  ***/
106 
107 /* These are used in the following inline functions. */
108 int sbc_wait_busy_timo = 1000 * 5000;   /* X2 = 10 S. */
109 int sbc_ready_timo = 1000 * 5000;       /* X2 = 10 S. */
110 int sbc_wait_dreq_timo = 1000 * 5000;   /* X2 = 10 S. */
111 
112 /* Return zero on success. */
113 static inline int
sbc_wait_busy(struct ncr5380_softc * sc)114 sbc_wait_busy(struct ncr5380_softc *sc)
115 {
116           int timo = sbc_wait_busy_timo;
117           for (;;) {
118                     if (SCI_BUSY(sc)) {
119                               timo = 0; /* return 0 */
120                               break;
121                     }
122                     if (--timo < 0)
123                               break;    /* return -1 */
124                     delay(2);
125           }
126           return (timo);
127 }
128 
129 static inline int
sbc_ready(struct ncr5380_softc * sc)130 sbc_ready(struct ncr5380_softc *sc)
131 {
132           int timo = sbc_ready_timo;
133 
134           for (;;) {
135                     if ((*sc->sci_csr & (SCI_CSR_DREQ|SCI_CSR_PHASE_MATCH))
136                         == (SCI_CSR_DREQ|SCI_CSR_PHASE_MATCH)) {
137                               timo = 0;
138                               break;
139                     }
140                     if (((*sc->sci_csr & SCI_CSR_PHASE_MATCH) == 0)
141                         || (SCI_BUSY(sc) == 0)) {
142                               timo = -1;
143                               break;
144                     }
145                     if (--timo < 0)
146                               break;    /* return -1 */
147                     delay(2);
148           }
149           return (timo);
150 }
151 
152 static inline int
sbc_wait_dreq(struct ncr5380_softc * sc)153 sbc_wait_dreq(struct ncr5380_softc *sc)
154 {
155           int timo = sbc_wait_dreq_timo;
156 
157           for (;;) {
158                     if ((*sc->sci_csr & (SCI_CSR_DREQ|SCI_CSR_PHASE_MATCH))
159                         == (SCI_CSR_DREQ|SCI_CSR_PHASE_MATCH)) {
160                               timo = 0;
161                               break;
162                     }
163                     if (--timo < 0)
164                               break;    /* return -1 */
165                     delay(2);
166           }
167           return (timo);
168 }
169 
170 void
sbc_irq_intr(void * p)171 sbc_irq_intr(void *p)
172 {
173           struct ncr5380_softc *ncr_sc = p;
174           struct sbc_softc *sc = (struct sbc_softc *)ncr_sc;
175           int claimed = 0;
176 
177           /* How we ever arrive here without IRQ set is a mystery... */
178           if (*ncr_sc->sci_csr & SCI_CSR_INT) {
179 #ifdef SBC_DEBUG
180                     if (sbc_debug & SBC_DB_INTR)
181                               decode_5380_intr(ncr_sc);
182 #endif
183                     if (!cold)
184                               claimed = ncr5380_intr(ncr_sc);
185                     if (!claimed) {
186                               if (((*ncr_sc->sci_csr & ~SCI_CSR_PHASE_MATCH) == SCI_CSR_INT)
187                                   && ((*ncr_sc->sci_bus_csr & ~SCI_BUS_RST) == 0)) {
188                                         SCI_CLR_INTR(ncr_sc);         /* RST interrupt */
189                                         if (sc->sc_clrintr)
190                                                   (*sc->sc_clrintr)(ncr_sc);
191                               }
192 #ifdef SBC_DEBUG
193                               else {
194                                         printf("%s: spurious intr\n",
195                                             device_xname(ncr_sc->sc_dev));
196                                         SBC_BREAK;
197                               }
198 #endif
199                     }
200           }
201 }
202 
203 #ifdef SBC_DEBUG
204 void
decode_5380_intr(struct ncr5380_softc * ncr_sc)205 decode_5380_intr(struct ncr5380_softc *ncr_sc)
206 {
207           u_int8_t csr = *ncr_sc->sci_csr;
208           u_int8_t bus_csr = *ncr_sc->sci_bus_csr;
209 
210           if (((csr & ~(SCI_CSR_PHASE_MATCH | SCI_CSR_ATN)) == SCI_CSR_INT) &&
211               ((bus_csr & ~(SCI_BUS_MSG | SCI_BUS_CD | SCI_BUS_IO | SCI_BUS_DBP)) == SCI_BUS_SEL)) {
212                     if (csr & SCI_BUS_IO)
213                               printf("%s: reselect\n", device_xname(ncr_sc->sc_dev));
214                     else
215                               printf("%s: select\n", device_xname(ncr_sc->sc_dev));
216           } else if (((csr & ~SCI_CSR_ACK) == (SCI_CSR_DONE | SCI_CSR_INT)) &&
217               ((bus_csr & (SCI_BUS_RST | SCI_BUS_BSY | SCI_BUS_SEL)) == SCI_BUS_BSY))
218                     printf("%s: DMA eop\n", device_xname(ncr_sc->sc_dev));
219           else if (((csr & ~SCI_CSR_PHASE_MATCH) == SCI_CSR_INT) &&
220               ((bus_csr & ~SCI_BUS_RST) == 0))
221                     printf("%s: bus reset\n", device_xname(ncr_sc->sc_dev));
222           else if (((csr & ~(SCI_CSR_DREQ | SCI_CSR_ATN | SCI_CSR_ACK)) == (SCI_CSR_PERR | SCI_CSR_INT | SCI_CSR_PHASE_MATCH)) &&
223               ((bus_csr & (SCI_BUS_RST | SCI_BUS_BSY | SCI_BUS_SEL)) == SCI_BUS_BSY))
224                     printf("%s: parity error\n", device_xname(ncr_sc->sc_dev));
225           else if (((csr & ~SCI_CSR_ATN) == SCI_CSR_INT) &&
226               ((bus_csr & (SCI_BUS_RST | SCI_BUS_BSY | SCI_BUS_REQ | SCI_BUS_SEL)) == (SCI_BUS_BSY | SCI_BUS_REQ)))
227                     printf("%s: phase mismatch\n", device_xname(ncr_sc->sc_dev));
228           else if (((csr & ~SCI_CSR_PHASE_MATCH) == (SCI_CSR_INT | SCI_CSR_DISC)) &&
229               (bus_csr == 0))
230                     printf("%s: disconnect\n", device_xname(ncr_sc->sc_dev));
231           else
232                     printf("%s: unknown intr: csr=%x, bus_csr=%x\n",
233                         device_xname(ncr_sc->sc_dev), csr, bus_csr);
234 }
235 #endif
236 
237 
238 /***
239  * The following code implements polled PDMA.
240  ***/
241 
242 int
sbc_pdma_in(struct ncr5380_softc * ncr_sc,int phase,int datalen,u_char * data)243 sbc_pdma_in(struct ncr5380_softc *ncr_sc, int phase, int datalen, u_char *data)
244 {
245           struct sbc_softc *sc = (struct sbc_softc *)ncr_sc;
246           volatile u_int32_t *long_data = (u_int32_t *)sc->sc_drq_addr;
247           volatile u_int8_t *byte_data = (u_int8_t *)sc->sc_nodrq_addr;
248           label_t faultbuf;
249           int resid, s;
250 
251           if (datalen < ncr_sc->sc_min_dma_len ||
252               (sc->sc_options & SBC_PDMA) == 0 ||
253               (ncr_sc->sc_current != NULL &&
254               (ncr_sc->sc_current->sr_xs->xs_control & XS_CTL_POLL)))
255                     return ncr5380_pio_in(ncr_sc, phase, datalen, data);
256 
257           mutex_enter(&sc->sc_drq_lock);
258           s = splbio();
259           if (sbc_wait_busy(ncr_sc)) {
260                     splx(s);
261                     mutex_exit(&sc->sc_drq_lock);
262 
263                     return 0;
264           }
265 
266           *ncr_sc->sci_mode |= SCI_MODE_DMA;
267           *ncr_sc->sci_irecv = 0;
268 
269           resid = datalen;
270 
271           /*
272            * Setup for a possible bus error caused by SCSI controller
273            * switching out of DATA OUT before we're done with the
274            * current transfer.  (See comment before sbc_drq_intr().)
275            */
276           nofault = &faultbuf;
277           if (setjmp(nofault)) {
278                     goto interrupt;
279           }
280 
281 #define R4          *(u_int32_t *)data = *long_data, data += 4;
282           for (; resid >= 128; resid -= 128) {
283                     if (sbc_ready(ncr_sc))
284                               goto interrupt;
285                     R4; R4; R4; R4; R4; R4; R4; R4;
286                     R4; R4; R4; R4; R4; R4; R4; R4;
287                     R4; R4; R4; R4; R4; R4; R4; R4;
288                     R4; R4; R4; R4; R4; R4; R4; R4;                   /* 128 */
289           }
290           while (resid) {
291                     if (sbc_ready(ncr_sc))
292                               goto interrupt;
293                     *(u_int8_t *)data = *byte_data, data += 1;
294                     resid--;
295           }
296 #undef R4
297 
298 interrupt:
299           nofault = NULL;
300           SCI_CLR_INTR(ncr_sc);
301           *ncr_sc->sci_mode &= ~SCI_MODE_DMA;
302           *ncr_sc->sci_icmd = 0;
303           splx(s);
304           mutex_exit(&sc->sc_drq_lock);
305 
306           return (datalen - resid);
307 }
308 
309 int
sbc_pdma_out(struct ncr5380_softc * ncr_sc,int phase,int datalen,u_char * data)310 sbc_pdma_out(struct ncr5380_softc *ncr_sc, int phase, int datalen, u_char *data)
311 {
312           struct sbc_softc *sc = (struct sbc_softc *)ncr_sc;
313           volatile u_int32_t *long_data = (u_int32_t *)sc->sc_drq_addr;
314           volatile u_int8_t *byte_data = (u_int8_t *)sc->sc_nodrq_addr;
315           label_t faultbuf;
316           int resid, s;
317           u_int8_t icmd;
318 
319 #if 1
320           /* Work around lame gcc initialization bug */
321           (void)&data;
322 #endif
323 
324           if (datalen < ncr_sc->sc_min_dma_len ||
325               (sc->sc_options & SBC_PDMA) == 0 ||
326               (sc->sc_options & SBC_PDMA_NO_WRITE) ||
327               (ncr_sc->sc_current != NULL &&
328               (ncr_sc->sc_current->sr_xs->xs_control & XS_CTL_POLL)))
329                     return ncr5380_pio_out(ncr_sc, phase, datalen, data);
330 
331           mutex_enter(&sc->sc_drq_lock);
332           s = splbio();
333           if (sbc_wait_busy(ncr_sc)) {
334                     splx(s);
335                     mutex_exit(&sc->sc_drq_lock);
336 
337                     return 0;
338           }
339 
340           icmd = *(ncr_sc->sci_icmd) & SCI_ICMD_RMASK;
341           *ncr_sc->sci_icmd = icmd | SCI_ICMD_DATA;
342           *ncr_sc->sci_mode |= SCI_MODE_DMA;
343           *ncr_sc->sci_dma_send = 0;
344 
345           /*
346            * Setup for a possible bus error caused by SCSI controller
347            * switching out of DATA OUT before we're done with the
348            * current transfer.  (See comment before sbc_drq_intr().)
349            */
350           nofault = &faultbuf;
351 
352           if (setjmp(nofault)) {
353                     printf("buf = 0x%lx, fault = 0x%lx\n",
354                         (u_long)sc->sc_drq_addr, (u_long)m68k_fault_addr);
355                     panic("Unexpected bus error in sbc_pdma_out()");
356           }
357 
358 #define W1          *byte_data = *(u_int8_t *)data, data += 1
359 #define W4          *long_data = *(u_int32_t *)data, data += 4
360           for (resid = datalen; resid >= 64; resid -= 64) {
361                     if (sbc_ready(ncr_sc))
362                               goto interrupt;
363                     W1;
364                     if (sbc_ready(ncr_sc))
365                               goto interrupt;
366                     W1;
367                     if (sbc_ready(ncr_sc))
368                               goto interrupt;
369                     W1;
370                     if (sbc_ready(ncr_sc))
371                               goto interrupt;
372                     W1;
373                     if (sbc_ready(ncr_sc))
374                               goto interrupt;
375                     W4; W4; W4; W4;
376                     W4; W4; W4; W4;
377                     W4; W4; W4; W4;
378                     W4; W4; W4;
379           }
380           while (resid) {
381                     if (sbc_ready(ncr_sc))
382                               goto interrupt;
383                     W1;
384                     resid--;
385           }
386 #undef  W1
387 #undef  W4
388           if (sbc_wait_dreq(ncr_sc))
389                     printf("%s: timeout waiting for DREQ.\n",
390                         device_xname(ncr_sc->sc_dev));
391 
392           *byte_data = 0;
393           goto done;
394 
395 interrupt:
396           if ((*ncr_sc->sci_csr & SCI_CSR_PHASE_MATCH) == 0) {
397                     *ncr_sc->sci_icmd = icmd & ~SCI_ICMD_DATA;
398                     --resid;
399           }
400 
401 done:
402           SCI_CLR_INTR(ncr_sc);
403           *ncr_sc->sci_mode &= ~SCI_MODE_DMA;
404           *ncr_sc->sci_icmd = icmd;
405           splx(s);
406           mutex_exit(&sc->sc_drq_lock);
407 
408           return (datalen - resid);
409 }
410 
411 
412 /***
413  * The following code implements interrupt-driven PDMA.
414  ***/
415 
416 /*
417  * This is the meat of the PDMA transfer.
418  * When we get here, we shove data as fast as the mac can take it.
419  * We depend on several things:
420  *   * All macs after the Mac Plus that have a 5380 chip should have a general
421  *     logic IC that handshakes data for blind transfers.
422  *   * If the SCSI controller finishes sending/receiving data before we do,
423  *     the same general logic IC will generate a /BERR for us in short order.
424  *   * The fault address for said /BERR minus the base address for the
425  *     transfer will be the amount of data that was actually written.
426  *
427  * We use the nofault flag and the setjmp/longjmp in locore.s so we can
428  * detect and handle the bus error for early termination of a command.
429  * This is usually caused by a disconnecting target.
430  */
431 void
sbc_drq_intr(void * p)432 sbc_drq_intr(void *p)
433 {
434           struct sbc_softc *sc = (struct sbc_softc *)p;
435           struct ncr5380_softc *ncr_sc = (struct ncr5380_softc *)p;
436           struct sci_req *sr = ncr_sc->sc_current;
437           struct sbc_pdma_handle *dh = sr->sr_dma_hand;
438           label_t faultbuf;
439           volatile u_int32_t *long_drq;
440           u_int32_t *long_data;
441           volatile u_int8_t *drq = 0;   /* XXX gcc4 -Wuninitialized */
442           u_int8_t *data;
443           int count, dcount, s;
444 
445           /*
446            * If we're not ready to xfer data, or have no more, just return.
447            */
448           if (sbc_ready(ncr_sc) || dh->dh_len == 0)
449                     return;
450 
451 #ifdef SBC_DEBUG
452           if (sbc_debug & SBC_DB_INTR)
453                     printf("%s: drq intr, dh_len=0x%x, dh_flags=0x%x\n",
454                         device_xname(ncr_sc->sc_dev), dh->dh_len, dh->dh_flags);
455 #endif
456           mutex_enter(&sc->sc_drq_lock);
457           s = splbio();
458 
459           /*
460            * Setup for a possible bus error caused by SCSI controller
461            * switching out of DATA-IN/OUT before we're done with the
462            * current transfer.
463            */
464           nofault = &faultbuf;
465 
466           m68k_fault_addr = 0;
467           if (setjmp(nofault)) {
468                     nofault = (label_t *)0;
469                     if ((dh->dh_flags & SBC_DH_DONE) == 0) {
470                               count = ((  (u_long)m68k_fault_addr
471                                           - (u_long)sc->sc_drq_addr));
472 
473                               if ((count < 0) || (count > dh->dh_len)) {
474                                         printf("%s: complete=0x%x (pending 0x%x)\n",
475                                             device_xname(ncr_sc->sc_dev), count,
476                                             dh->dh_len);
477                                         panic("something is wrong");
478                               }
479 
480                               dh->dh_addr += count;
481                               dh->dh_len -= count;
482                     } else
483                               count = 0;
484 
485 #ifdef SBC_DEBUG
486                     if (sbc_debug & SBC_DB_INTR)
487                               printf("%s: drq /berr, complete=0x%x (pending 0x%x)\n",
488                                  device_xname(ncr_sc->sc_dev), count, dh->dh_len);
489 #endif
490                     m68k_fault_addr = 0;
491 
492                     splx(s);
493 
494                     mutex_exit(&sc->sc_drq_lock);
495 
496                     return;
497           }
498 
499           if (dh->dh_flags & SBC_DH_OUT) { /* Data Out */
500                     dcount = 0;
501 
502                     /*
503                      * Get the source address aligned.
504                      */
505                     dcount =
506                         count = uimin(dh->dh_len, 4 - (((int)dh->dh_addr) & 0x3));
507                     if (count && count < 4) {
508                               drq = (volatile u_int8_t *)sc->sc_drq_addr;
509                               data = (u_int8_t *)dh->dh_addr;
510 
511 #define W1                    *drq++ = *data++
512                               while (count) {
513                                         W1; count--;
514                               }
515 #undef W1
516                               dh->dh_addr += dcount;
517                               dh->dh_len -= dcount;
518                     }
519 
520                     /*
521                      * Start the transfer.
522                      */
523                     while (dh->dh_len) {
524 #define W4                    *long_drq++ = *long_data++; count -= 4
525 
526                               dcount = count = uimin(dh->dh_len, MAX_DMA_LEN);
527                               long_drq = (volatile u_int32_t *)sc->sc_drq_addr;
528                               long_data = (u_int32_t *)dh->dh_addr;
529 
530                               while (count >= 64) {
531                                         W4; W4; W4; W4; W4; W4; W4; W4;
532                                         W4; W4; W4; W4; W4; W4; W4; W4; /*  64 */
533                               }
534                               while (count >= 4) {
535                                         W4;
536                               }
537 #undef W4
538                               data = (u_int8_t *)long_data;
539                               drq = (volatile u_int8_t *)long_drq;
540 
541 #define W1                    *drq++ = *data++
542                               while (count) {
543                                         W1; count--;
544                               }
545 #undef W1
546                               dh->dh_len -= dcount;
547                               dh->dh_addr += dcount;
548                     }
549                     dh->dh_flags |= SBC_DH_DONE;
550                     if (dcount >= MAX_DMA_LEN)
551                               drq = (volatile u_int8_t *)sc->sc_drq_addr;
552                     /*
553                      * Write an extra byte to handle last ack.
554                      * From NCR5380 Interface manual.
555                      */
556                     if (*ncr_sc->sci_csr & SCI_CSR_ACK)
557                               *drq = 0;
558 
559                     /*
560                      * XXX -- Read a byte from the SBC to trigger a /BERR.
561                      * This seems to be necessary for us to notice that
562                      * the target has disconnected.  Ick.  06 jun 1996 (sr)
563                      * Unsure if this is still necessary - See comment above.
564                      */
565                     (void)*drq;
566           } else {  /* Data In */
567                     /*
568                      * Get the dest address aligned.
569                      */
570                     dcount =
571                         count = uimin(dh->dh_len, 4 - (((int)dh->dh_addr) & 0x3));
572                     if (count && count < 4) {
573                               data = (u_int8_t *)dh->dh_addr;
574                               drq = (volatile u_int8_t *)sc->sc_drq_addr;
575                               while (count) {
576                                         *data++ = *drq++;
577                                         count--;
578                               }
579                               dh->dh_addr += dcount;
580                               dh->dh_len -= dcount;
581                     }
582 
583                     /*
584                      * Start the transfer.
585                      */
586                     while (dh->dh_len) {
587                               dcount = count = uimin(dh->dh_len, MAX_DMA_LEN);
588                               long_data = (u_int32_t *)dh->dh_addr;
589                               long_drq = (volatile u_int32_t *)sc->sc_drq_addr;
590 
591 #define R4                    *long_data++ = *long_drq++; count -= 4
592                               while (count >= 64) {
593                                         R4; R4; R4; R4; R4; R4; R4; R4;
594                                         R4; R4; R4; R4; R4; R4; R4; R4;         /* 64 */
595                               }
596                               while (count >= 4) {
597                                         R4;
598                               }
599 #undef R4
600                               data = (u_int8_t *)long_data;
601                               drq = (volatile u_int8_t *)long_drq;
602                               while (count) {
603                                         *data++ = *drq++;
604                                         count--;
605                               }
606                               dh->dh_len -= dcount;
607                               dh->dh_addr += dcount;
608                     }
609                     dh->dh_flags |= SBC_DH_DONE;
610           }
611 
612           /*
613            * OK.  No bus error occurred above.  Clear the nofault flag
614            * so we no longer short-circuit bus errors.
615            */
616           nofault = (label_t *)0;
617 
618           splx(s);
619 
620           mutex_exit(&sc->sc_drq_lock);
621 
622 #ifdef SBC_DEBUG
623           if (sbc_debug & (SBC_DB_REG | SBC_DB_INTR))
624                     printf("%s: drq intr complete: csr=0x%x, bus_csr=0x%x\n",
625                         device_xname(ncr_sc->sc_dev), *ncr_sc->sci_csr,
626                         *ncr_sc->sci_bus_csr);
627 #endif
628 }
629 
630 void
sbc_dma_alloc(struct ncr5380_softc * ncr_sc)631 sbc_dma_alloc(struct ncr5380_softc *ncr_sc)
632 {
633           struct sbc_softc *sc = (struct sbc_softc *)ncr_sc;
634           struct sci_req *sr = ncr_sc->sc_current;
635           struct scsipi_xfer *xs = sr->sr_xs;
636           struct sbc_pdma_handle *dh;
637           int                 i, xlen;
638 
639 #ifdef DIAGNOSTIC
640           if (sr->sr_dma_hand != NULL)
641                     panic("sbc_dma_alloc: already have PDMA handle");
642 #endif
643 
644           /* Polled transfers shouldn't allocate a PDMA handle. */
645           if (sr->sr_flags & SR_IMMED)
646                     return;
647 
648           xlen = ncr_sc->sc_datalen;
649 
650           /* Make sure our caller checked sc_min_dma_len. */
651           if (xlen < MIN_DMA_LEN)
652                     panic("sbc_dma_alloc: len=0x%x", xlen);
653 
654           /*
655            * Find free PDMA handle.  Guaranteed to find one since we
656            * have as many PDMA handles as the driver has processes.
657            * (instances?)
658            */
659            for (i = 0; i < SCI_OPENINGS; i++) {
660                     if ((sc->sc_pdma[i].dh_flags & SBC_DH_BUSY) == 0)
661                               goto found;
662           }
663           panic("sbc: no free PDMA handles");
664 found:
665           dh = &sc->sc_pdma[i];
666           dh->dh_flags = SBC_DH_BUSY;
667           dh->dh_addr = ncr_sc->sc_dataptr;
668           dh->dh_len = xlen;
669 
670           /* Copy the 'write' flag for convenience. */
671           if (xs->xs_control & XS_CTL_DATA_OUT)
672                     dh->dh_flags |= SBC_DH_OUT;
673 
674           sr->sr_dma_hand = dh;
675 }
676 
677 void
sbc_dma_free(struct ncr5380_softc * ncr_sc)678 sbc_dma_free(struct ncr5380_softc *ncr_sc)
679 {
680           struct sci_req *sr = ncr_sc->sc_current;
681           struct sbc_pdma_handle *dh = sr->sr_dma_hand;
682 
683 #ifdef DIAGNOSTIC
684           if (sr->sr_dma_hand == NULL)
685                     panic("sbc_dma_free: no DMA handle");
686 #endif
687 
688           if (ncr_sc->sc_state & NCR_DOINGDMA)
689                     panic("sbc_dma_free: free while in progress");
690 
691           if (dh->dh_flags & SBC_DH_BUSY) {
692                     dh->dh_flags = 0;
693                     dh->dh_addr = NULL;
694                     dh->dh_len = 0;
695           }
696           sr->sr_dma_hand = NULL;
697 }
698 
699 void
sbc_dma_poll(struct ncr5380_softc * ncr_sc)700 sbc_dma_poll(struct ncr5380_softc *ncr_sc)
701 {
702           struct sci_req *sr = ncr_sc->sc_current;
703 
704           /*
705            * We shouldn't arrive here; if SR_IMMED is set, then
706            * dma_alloc() should have refused to allocate a handle
707            * for the transfer.  This forces the polled PDMA code
708            * to handle the request...
709            */
710 #ifdef SBC_DEBUG
711           if (sbc_debug & SBC_DB_DMA)
712                     printf("%s: lost DRQ interrupt?\n",
713                         device_xname(ncr_sc->sc_dev));
714 #endif
715           sr->sr_flags |= SR_OVERDUE;
716 }
717 
718 void
sbc_dma_setup(struct ncr5380_softc * ncr_sc)719 sbc_dma_setup(struct ncr5380_softc *ncr_sc)
720 {
721           /* Not needed; we don't have real DMA */
722 }
723 
724 void
sbc_dma_start(struct ncr5380_softc * ncr_sc)725 sbc_dma_start(struct ncr5380_softc *ncr_sc)
726 {
727           struct sbc_softc *sc = (struct sbc_softc *)ncr_sc;
728           struct sci_req *sr = ncr_sc->sc_current;
729           struct sbc_pdma_handle *dh = sr->sr_dma_hand;
730 
731           /*
732            * Match bus phase, clear pending interrupts, set DMA mode, and
733            * assert data bus (for writing only), then start the transfer.
734            */
735           if (dh->dh_flags & SBC_DH_OUT) {
736                     *ncr_sc->sci_tcmd = PHASE_DATA_OUT;
737                     SCI_CLR_INTR(ncr_sc);
738                     if (sc->sc_clrintr)
739                               (*sc->sc_clrintr)(ncr_sc);
740                     *ncr_sc->sci_mode |= SCI_MODE_DMA;
741                     *ncr_sc->sci_icmd = SCI_ICMD_DATA;
742                     *ncr_sc->sci_dma_send = 0;
743           } else {
744                     *ncr_sc->sci_tcmd = PHASE_DATA_IN;
745                     SCI_CLR_INTR(ncr_sc);
746                     if (sc->sc_clrintr)
747                               (*sc->sc_clrintr)(ncr_sc);
748                     *ncr_sc->sci_mode |= SCI_MODE_DMA;
749                     *ncr_sc->sci_icmd = 0;
750                     *ncr_sc->sci_irecv = 0;
751           }
752           ncr_sc->sc_state |= NCR_DOINGDMA;
753 
754 #ifdef SBC_DEBUG
755           if (sbc_debug & SBC_DB_DMA)
756                     printf("%s: PDMA started, va=%p, len=0x%x\n",
757                         device_xname(ncr_sc->sc_dev), dh->dh_addr, dh->dh_len);
758 #endif
759 }
760 
761 void
sbc_dma_eop(struct ncr5380_softc * ncr_sc)762 sbc_dma_eop(struct ncr5380_softc *ncr_sc)
763 {
764           /* Not used; the EOP pin is wired high (GMFH, pp. 389-390) */
765 }
766 
767 void
sbc_dma_stop(struct ncr5380_softc * ncr_sc)768 sbc_dma_stop(struct ncr5380_softc *ncr_sc)
769 {
770           struct sbc_softc *sc = (struct sbc_softc *)ncr_sc;
771           struct sci_req *sr = ncr_sc->sc_current;
772           struct sbc_pdma_handle *dh = sr->sr_dma_hand;
773           int ntrans;
774 
775           if ((ncr_sc->sc_state & NCR_DOINGDMA) == 0) {
776 #ifdef SBC_DEBUG
777                     if (sbc_debug & SBC_DB_DMA)
778                               printf("%s: dma_stop: DMA not running\n",
779                                   device_xname(ncr_sc->sc_dev));
780 #endif
781                     return;
782           }
783           ncr_sc->sc_state &= ~NCR_DOINGDMA;
784 
785           if ((ncr_sc->sc_state & NCR_ABORTING) == 0) {
786                     ntrans = ncr_sc->sc_datalen - dh->dh_len;
787 
788 #ifdef SBC_DEBUG
789                     if (sbc_debug & SBC_DB_DMA)
790                               printf("%s: dma_stop: ntrans=0x%x\n",
791                                   device_xname(ncr_sc->sc_dev), ntrans);
792 #endif
793 
794                     if (ntrans > ncr_sc->sc_datalen)
795                               panic("sbc_dma_stop: excess transfer");
796 
797                     /* Adjust data pointer */
798                     ncr_sc->sc_dataptr += ntrans;
799                     ncr_sc->sc_datalen -= ntrans;
800 
801                     /* Clear any pending interrupts. */
802                     SCI_CLR_INTR(ncr_sc);
803                     if (sc->sc_clrintr)
804                               (*sc->sc_clrintr)(ncr_sc);
805           }
806 
807           /* Put SBIC back into PIO mode. */
808           *ncr_sc->sci_mode &= ~SCI_MODE_DMA;
809           *ncr_sc->sci_icmd = 0;
810 
811 #ifdef SBC_DEBUG
812           if (sbc_debug & SBC_DB_REG)
813                     printf("%s: dma_stop: csr=0x%x, bus_csr=0x%x\n",
814                         device_xname(ncr_sc->sc_dev), *ncr_sc->sci_csr,
815                         *ncr_sc->sci_bus_csr);
816 #endif
817 }
818