1*d1579b2dSriastradh /* $NetBSD: oak.c,v 1.21 2018/09/03 16:29:33 riastradh Exp $ */
2c7a388d9Sbjh21
3c7a388d9Sbjh21 /*
4c7a388d9Sbjh21 * Copyright (c) 1998 The NetBSD Foundation, Inc.
5c7a388d9Sbjh21 * All rights reserved.
6c7a388d9Sbjh21 *
7c7a388d9Sbjh21 * This code is derived from software contributed to The NetBSD Foundation
8c7a388d9Sbjh21 * by Mark Brinicombe of Causality Limited.
9c7a388d9Sbjh21 *
10c7a388d9Sbjh21 * Redistribution and use in source and binary forms, with or without
11c7a388d9Sbjh21 * modification, are permitted provided that the following conditions
12c7a388d9Sbjh21 * are met:
13c7a388d9Sbjh21 * 1. Redistributions of source code must retain the above copyright
14c7a388d9Sbjh21 * notice, this list of conditions and the following disclaimer.
15c7a388d9Sbjh21 * 2. Redistributions in binary form must reproduce the above copyright
16c7a388d9Sbjh21 * notice, this list of conditions and the following disclaimer in the
17c7a388d9Sbjh21 * documentation and/or other materials provided with the distribution.
18c7a388d9Sbjh21 *
19c7a388d9Sbjh21 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20c7a388d9Sbjh21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21c7a388d9Sbjh21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22c7a388d9Sbjh21 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23c7a388d9Sbjh21 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24c7a388d9Sbjh21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25c7a388d9Sbjh21 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26c7a388d9Sbjh21 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27c7a388d9Sbjh21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28c7a388d9Sbjh21 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29c7a388d9Sbjh21 * POSSIBILITY OF SUCH DAMAGE.
30c7a388d9Sbjh21 */
31c7a388d9Sbjh21
32c7a388d9Sbjh21 /*
331208c816Sbjh21 * Oak Solutions SCSI 1 driver using the generic NCR5380 driver.
34ab063701Sbjh21 *
351208c816Sbjh21 * From <URL:http://foldoc.doc.ic.ac.uk/acorn/doc/scsi>:
361208c816Sbjh21 * --------8<--------
371208c816Sbjh21 * From: Hugo Fiennes
381208c816Sbjh21 * [...]
391208c816Sbjh21 * The oak scsi plays some other tricks to get max around 2.2Mb/sec:
401208c816Sbjh21 * it is a 16- bit interface (using their own hardware and an 8-bit
411208c816Sbjh21 * scsi controller to 'double-up' the data). What it does is: every
421208c816Sbjh21 * 128 bytes it uses a polling loop (see above) to check data is
431208c816Sbjh21 * present and the drive has reported no errors, etc. Inside each 128
441208c816Sbjh21 * byte block it just reads data as fast as it can: on a normal card
451208c816Sbjh21 * this would result in disaster if the drive wasn't fast enough to
461208c816Sbjh21 * feed the machine: on the oak card however, the hardware will not
471208c816Sbjh21 * assert IOGT (IO grant), so hanging the machine in a wait state
481208c816Sbjh21 * until data is ready. This can have problems: if the drive is to
491208c816Sbjh21 * slow (unlikely) the machine will completely stiff as the ARM3 can't
501208c816Sbjh21 * be kept in such a state for more than 10(?) us.
511208c816Sbjh21 * -------->8--------
521208c816Sbjh21 *
531208c816Sbjh21 * So far, my attempts at doing this have failed, though.
54ab063701Sbjh21 *
55ab063701Sbjh21 * This card has to be polled: it doesn't have anything connected to
56ab063701Sbjh21 * PIRQ*. This seems to be a common failing of Archimedes disc
57ab063701Sbjh21 * controllers.
58c7a388d9Sbjh21 */
59c7a388d9Sbjh21
609ab2c471Slukem #include <sys/cdefs.h>
61*d1579b2dSriastradh __KERNEL_RCSID(0, "$NetBSD: oak.c,v 1.21 2018/09/03 16:29:33 riastradh Exp $");
62ab063701Sbjh21
639ab2c471Slukem #include <sys/param.h>
64ab063701Sbjh21
65c7a388d9Sbjh21 #include <sys/systm.h>
66c7a388d9Sbjh21 #include <sys/kernel.h>
67c7a388d9Sbjh21 #include <sys/device.h>
68c7a388d9Sbjh21 #include <sys/buf.h>
69c7a388d9Sbjh21 #include <dev/scsipi/scsi_all.h>
70c7a388d9Sbjh21 #include <dev/scsipi/scsipi_all.h>
71c7a388d9Sbjh21 #include <dev/scsipi/scsiconf.h>
72c7a388d9Sbjh21
73c7a388d9Sbjh21 #include <dev/ic/ncr5380reg.h>
74c7a388d9Sbjh21 #include <dev/ic/ncr5380var.h>
75c7a388d9Sbjh21
76c7a388d9Sbjh21 #include <machine/bootconfig.h>
77c7a388d9Sbjh21
78c7a388d9Sbjh21 #include <dev/podulebus/podulebus.h>
79c7a388d9Sbjh21 #include <dev/podulebus/podules.h>
80bd4a0aaeSbjh21 #include <dev/podulebus/powerromreg.h>
81c7a388d9Sbjh21
821208c816Sbjh21 #include <dev/podulebus/oakreg.h>
831208c816Sbjh21
8451475713Stsutsui int oak_match(device_t, cfdata_t, void *);
8551475713Stsutsui void oak_attach(device_t, device_t, void *);
86c7a388d9Sbjh21
871208c816Sbjh21 #if 0
8851475713Stsutsui static int oak_pdma_in(struct ncr5380_softc *, int, int, uint8_t *);
8951475713Stsutsui static int oak_pdma_out(struct ncr5380_softc *, int, int, uint8_t *);
901208c816Sbjh21 #endif
911208c816Sbjh21
92c7a388d9Sbjh21 /*
93c7a388d9Sbjh21 * Oak SCSI 1 softc structure.
94c7a388d9Sbjh21 *
95c7a388d9Sbjh21 * Contains the generic ncr5380 device node, podule information and
96c7a388d9Sbjh21 * global information required by the driver.
97c7a388d9Sbjh21 */
98c7a388d9Sbjh21
99c7a388d9Sbjh21 struct oak_softc {
100c7a388d9Sbjh21 struct ncr5380_softc sc_ncr5380;
1011208c816Sbjh21 bus_space_tag_t sc_pdmat;
1021208c816Sbjh21 bus_space_handle_t sc_pdmah;
103c7a388d9Sbjh21 };
104c7a388d9Sbjh21
10551475713Stsutsui CFATTACH_DECL_NEW(oak, sizeof(struct oak_softc),
106b75a007dSthorpej oak_match, oak_attach, NULL, NULL);
107c7a388d9Sbjh21
108c7a388d9Sbjh21 /*
109c7a388d9Sbjh21 * Card probe function
110c7a388d9Sbjh21 *
111c7a388d9Sbjh21 * Just match the manufacturer and podule ID's
112c7a388d9Sbjh21 */
113c7a388d9Sbjh21
114c7a388d9Sbjh21 int
oak_match(device_t parent,cfdata_t cf,void * aux)11551475713Stsutsui oak_match(device_t parent, cfdata_t cf, void *aux)
116c7a388d9Sbjh21 {
117c7a388d9Sbjh21 struct podulebus_attach_args *pa = aux;
118c7a388d9Sbjh21
11920518673Sbjh21 if (pa->pa_product == PODULE_OAK_SCSI)
120e02efcb8Sbjh21 return 1;
121c7a388d9Sbjh21
122e02efcb8Sbjh21 /* PowerROM */
123e02efcb8Sbjh21 if (pa->pa_product == PODULE_ALSYSTEMS_SCSI &&
124e02efcb8Sbjh21 podulebus_initloader(pa) == 0 &&
125e02efcb8Sbjh21 podloader_callloader(pa, 0, 0) == PRID_OAK_SCSI1)
126e02efcb8Sbjh21 return 1;
127e02efcb8Sbjh21
1281e0b1b73Sbjh21 return 0;
129c7a388d9Sbjh21 }
130c7a388d9Sbjh21
131c7a388d9Sbjh21 /*
132c7a388d9Sbjh21 * Card attach function
133c7a388d9Sbjh21 *
134c7a388d9Sbjh21 */
135c7a388d9Sbjh21
136c7a388d9Sbjh21 void
oak_attach(device_t parent,device_t self,void * aux)13751475713Stsutsui oak_attach(device_t parent, device_t self, void *aux)
138c7a388d9Sbjh21 {
139838ee1e0Sthorpej struct oak_softc *sc = device_private(self);
14051475713Stsutsui struct ncr5380_softc *ncr_sc = &sc->sc_ncr5380;
141c7a388d9Sbjh21 struct podulebus_attach_args *pa = aux;
14296dda214Sbjh21 #ifndef NCR5380_USE_BUS_SPACE
14351475713Stsutsui uint8_t *iobase;
14496dda214Sbjh21 #endif
145cbab9cadSchs char hi_option[sizeof(device_xname(self)) + 8];
146c7a388d9Sbjh21
14751475713Stsutsui ncr_sc->sc_dev = self;
14851475713Stsutsui ncr_sc->sc_flags |= NCR5380_FORCE_POLLING;
14951475713Stsutsui ncr_sc->sc_min_dma_len = 0;
15051475713Stsutsui ncr_sc->sc_no_disconnect = 0xff;
15151475713Stsutsui ncr_sc->sc_parity_disable = 0;
152c7a388d9Sbjh21
15351475713Stsutsui ncr_sc->sc_dma_alloc = NULL;
15451475713Stsutsui ncr_sc->sc_dma_free = NULL;
15551475713Stsutsui ncr_sc->sc_dma_poll = NULL;
15651475713Stsutsui ncr_sc->sc_dma_setup = NULL;
15751475713Stsutsui ncr_sc->sc_dma_start = NULL;
15851475713Stsutsui ncr_sc->sc_dma_eop = NULL;
15951475713Stsutsui ncr_sc->sc_dma_stop = NULL;
16051475713Stsutsui ncr_sc->sc_intr_on = NULL;
16151475713Stsutsui ncr_sc->sc_intr_off = NULL;
162c7a388d9Sbjh21
163ab063701Sbjh21 #ifdef NCR5380_USE_BUS_SPACE
16451475713Stsutsui ncr_sc->sc_regt = pa->pa_mod_t;
16551475713Stsutsui bus_space_map(ncr_sc->sc_regt, pa->pa_mod_base, 8, 0,
16651475713Stsutsui &ncr_sc->sc_regh);
16751475713Stsutsui ncr_sc->sci_r0 = 0;
16851475713Stsutsui ncr_sc->sci_r1 = 1;
16951475713Stsutsui ncr_sc->sci_r2 = 2;
17051475713Stsutsui ncr_sc->sci_r3 = 3;
17151475713Stsutsui ncr_sc->sci_r4 = 4;
17251475713Stsutsui ncr_sc->sci_r5 = 5;
17351475713Stsutsui ncr_sc->sci_r6 = 6;
17451475713Stsutsui ncr_sc->sci_r7 = 7;
175ab063701Sbjh21 #else
17651475713Stsutsui iobase = (uint8_t *)pa->pa_mod_base;
17751475713Stsutsui ncr_sc->sci_r0 = iobase + 0;
17851475713Stsutsui ncr_sc->sci_r1 = iobase + 4;
17951475713Stsutsui ncr_sc->sci_r2 = iobase + 8;
18051475713Stsutsui ncr_sc->sci_r3 = iobase + 12;
18151475713Stsutsui ncr_sc->sci_r4 = iobase + 16;
18251475713Stsutsui ncr_sc->sci_r5 = iobase + 20;
18351475713Stsutsui ncr_sc->sci_r6 = iobase + 24;
18451475713Stsutsui ncr_sc->sci_r7 = iobase + 28;
185ab063701Sbjh21 #endif
1861208c816Sbjh21 sc->sc_pdmat = pa->pa_mod_t;
1871208c816Sbjh21 bus_space_map(sc->sc_pdmat, pa->pa_mod_base + OAK_PDMA_OFFSET, 0x20, 0,
1881208c816Sbjh21 &sc->sc_pdmah);
189c7a388d9Sbjh21
19051475713Stsutsui ncr_sc->sc_rev = NCR_VARIANT_NCR5380;
191c7a388d9Sbjh21
19251475713Stsutsui ncr_sc->sc_pio_in = ncr5380_pio_in;
19351475713Stsutsui ncr_sc->sc_pio_out = ncr5380_pio_out;
194c7a388d9Sbjh21
195c7a388d9Sbjh21 /* Provide an override for the host id */
19651475713Stsutsui ncr_sc->sc_channel.chan_id = 7;
197aca4c091Sitojun snprintf(hi_option, sizeof(hi_option), "%s.hostid",
19851475713Stsutsui device_xname(self));
199c7a388d9Sbjh21 (void)get_bootconf_option(boot_args, hi_option,
20051475713Stsutsui BOOTOPT_TYPE_INT, &ncr_sc->sc_channel.chan_id);
20151475713Stsutsui ncr_sc->sc_adapter.adapt_minphys = minphys;
202c7a388d9Sbjh21
20351475713Stsutsui aprint_normal(": host=%d, using 8 bit PIO\n",
20451475713Stsutsui ncr_sc->sc_channel.chan_id);
205c7a388d9Sbjh21
20651475713Stsutsui ncr5380_attach(ncr_sc);
207c7a388d9Sbjh21 }
2081208c816Sbjh21
2091208c816Sbjh21 /*
2101208c816Sbjh21 * XXX The code below doesn't work correctly. I probably need more
2111208c816Sbjh21 * details on how the card works. [bjh21 20011202]
2121208c816Sbjh21 */
2131208c816Sbjh21 #if 0
2141208c816Sbjh21
2151208c816Sbjh21 #ifndef OAK_TSIZE_OUT
2161208c816Sbjh21 #define OAK_TSIZE_OUT 128
2171208c816Sbjh21 #endif
2181208c816Sbjh21
2191208c816Sbjh21 #ifndef OAK_TSIZE_IN
2201208c816Sbjh21 #define OAK_TSIZE_IN 128
2211208c816Sbjh21 #endif
2221208c816Sbjh21
2231208c816Sbjh21 #define TIMEOUT 1000000
2241208c816Sbjh21
22593124077Sperry static inline int
2261208c816Sbjh21 oak_ready(struct ncr5380_softc *sc)
2271208c816Sbjh21 {
2281208c816Sbjh21 int i;
2291208c816Sbjh21 int status;
2301208c816Sbjh21
2311208c816Sbjh21 for (i = TIMEOUT; i > 0; i--) {
2321208c816Sbjh21 status = NCR5380_READ(sc, sci_csr);
2331208c816Sbjh21 if ((status & (SCI_CSR_DREQ | SCI_CSR_PHASE_MATCH)) ==
2341208c816Sbjh21 (SCI_CSR_DREQ | SCI_CSR_PHASE_MATCH))
23551475713Stsutsui return 1;
2361208c816Sbjh21
2371208c816Sbjh21 if ((status & SCI_CSR_PHASE_MATCH) == 0 ||
2381208c816Sbjh21 SCI_BUSY(sc) == 0)
23951475713Stsutsui return 0;
2401208c816Sbjh21 }
24151475713Stsutsui printf("%s: ready timeout\n", device_xname(sc->sc_dev));
24251475713Stsutsui return 0;
2431208c816Sbjh21
2441208c816Sbjh21 #if 0 /* The Linux driver does this: */
2451208c816Sbjh21 struct oak_softc *sc = (void *)ncr_sc;
2461208c816Sbjh21 bus_space_tag_t pdmat = sc->sc_pdmat;
2471208c816Sbjh21 bus_space_handle_t pdmah = sc->sc_pdmah;
2481208c816Sbjh21 int i, status;
2491208c816Sbjh21
2501208c816Sbjh21 for (i = TIMEOUT; i > 0; i--) {
2511208c816Sbjh21 status = bus_space_read_2(pdmat, pdmah, OAK_PDMA_STATUS);
2521208c816Sbjh21 if (status & 0x200)
25351475713Stsutsui return 0;
2541208c816Sbjh21 if (status & 0x100)
25551475713Stsutsui return 1;
2561208c816Sbjh21 }
25751475713Stsutsui printf("%s: ready timeout, status = 0x%x\n",
25851475713Stsutsui device_xname(ncr_sc->sc_dev), status);
25951475713Stsutsui return 0;
2601208c816Sbjh21 #endif
2611208c816Sbjh21 }
2621208c816Sbjh21
2631208c816Sbjh21
2641208c816Sbjh21
2651208c816Sbjh21 /* Return zero on success. */
26693124077Sperry static inline void oak_wait_not_req(struct ncr5380_softc *sc)
2671208c816Sbjh21 {
2681208c816Sbjh21 int timo;
2691208c816Sbjh21 for (timo = TIMEOUT; timo; timo--) {
2701208c816Sbjh21 if ((NCR5380_READ(sc, sci_bus_csr) & SCI_BUS_REQ) == 0 ||
2711208c816Sbjh21 (NCR5380_READ(sc, sci_csr) & SCI_CSR_PHASE_MATCH) == 0 ||
2721208c816Sbjh21 SCI_BUSY(sc) == 0) {
2731208c816Sbjh21 return;
2741208c816Sbjh21 }
2751208c816Sbjh21 }
27651475713Stsutsui printf("%s: pdma not_req timeout\n", device_xname(sc->sc_dev));
2771208c816Sbjh21 }
2781208c816Sbjh21
2791208c816Sbjh21 static int
2801208c816Sbjh21 oak_pdma_in(struct ncr5380_softc *ncr_sc, int phase, int datalen,
28151475713Stsutsui uint8_t *data)
2821208c816Sbjh21 {
2831208c816Sbjh21 struct oak_softc *sc = (void *)ncr_sc;
2841208c816Sbjh21 bus_space_tag_t pdmat = sc->sc_pdmat;
2851208c816Sbjh21 bus_space_handle_t pdmah = sc->sc_pdmah;
2861208c816Sbjh21 int s, resid, len;
2871208c816Sbjh21
2881208c816Sbjh21 s = splbio();
2891208c816Sbjh21
2901208c816Sbjh21 NCR5380_WRITE(ncr_sc, sci_mode,
2911208c816Sbjh21 NCR5380_READ(ncr_sc, sci_mode) | SCI_MODE_DMA);
2921208c816Sbjh21 NCR5380_WRITE(ncr_sc, sci_irecv, 0);
2931208c816Sbjh21
2941208c816Sbjh21 resid = datalen;
2951208c816Sbjh21 while (resid > 0) {
296*d1579b2dSriastradh len = uimin(resid, OAK_TSIZE_IN);
2971208c816Sbjh21 if (oak_ready(ncr_sc) == 0)
2981208c816Sbjh21 goto interrupt;
29951475713Stsutsui KASSERT(BUS_SPACE_ALIGNED_POINTER(data, uint16_t));
3001208c816Sbjh21 bus_space_read_multi_2(pdmat, pdmah, OAK_PDMA_READ,
30151475713Stsutsui (uint16_t *)data, len / 2);
3021208c816Sbjh21 data += len;
3031208c816Sbjh21 resid -= len;
3041208c816Sbjh21 }
3051208c816Sbjh21
3061208c816Sbjh21 oak_wait_not_req(ncr_sc);
3071208c816Sbjh21
3081208c816Sbjh21 interrupt:
3091208c816Sbjh21 SCI_CLR_INTR(ncr_sc);
3101208c816Sbjh21 NCR5380_WRITE(ncr_sc, sci_mode,
3111208c816Sbjh21 NCR5380_READ(ncr_sc, sci_mode) & ~SCI_MODE_DMA);
3121208c816Sbjh21 splx(s);
3131208c816Sbjh21 return datalen - resid;
3141208c816Sbjh21 }
3151208c816Sbjh21
3161208c816Sbjh21 static int
3171208c816Sbjh21 oak_pdma_out(struct ncr5380_softc *ncr_sc, int phase, int datalen,
31851475713Stsutsui uint8_t *data)
3191208c816Sbjh21 {
32051475713Stsutsui struct oak_softc *sc = (struct oak_softc *)ncr_sc;
3211208c816Sbjh21 bus_space_tag_t pdmat = sc->sc_pdmat;
3221208c816Sbjh21 bus_space_handle_t pdmah = sc->sc_pdmah;
3231208c816Sbjh21 int i, s, icmd, resid;
3241208c816Sbjh21
3251208c816Sbjh21 s = splbio();
3261208c816Sbjh21 icmd = NCR5380_READ(ncr_sc, sci_icmd) & SCI_ICMD_RMASK;
3271208c816Sbjh21 NCR5380_WRITE(ncr_sc, sci_icmd, icmd | SCI_ICMD_DATA);
3281208c816Sbjh21 NCR5380_WRITE(ncr_sc, sci_mode,
3291208c816Sbjh21 NCR5380_READ(ncr_sc, sci_mode) | SCI_MODE_DMA);
3301208c816Sbjh21 NCR5380_WRITE(ncr_sc, sci_dma_send, 0);
3311208c816Sbjh21
3321208c816Sbjh21 resid = datalen;
3331208c816Sbjh21 if (oak_ready(ncr_sc) == 0)
3341208c816Sbjh21 goto interrupt;
3351208c816Sbjh21
3361208c816Sbjh21 if (resid > OAK_TSIZE_OUT) {
3371208c816Sbjh21 /*
3381208c816Sbjh21 * Because of the chips DMA prefetch, phase changes
3391208c816Sbjh21 * etc, won't be detected until we have written at
3401208c816Sbjh21 * least one byte more. We pre-write 4 bytes so
3411208c816Sbjh21 * subsequent transfers will be aligned to a 4 byte
3421208c816Sbjh21 * boundary. Assuming disconects will only occur on
3431208c816Sbjh21 * block boundaries, we then correct for the pre-write
3441208c816Sbjh21 * when and if we get a phase change. If the chip had
3451208c816Sbjh21 * DMA byte counting hardware, the assumption would not
3461208c816Sbjh21 * be necessary.
3471208c816Sbjh21 */
34851475713Stsutsui KASSERT(BUS_SPACE_ALIGNED_POINTER(data, uint16_t));
3491208c816Sbjh21 bus_space_write_multi_2(pdmat, pdmah, OAK_PDMA_WRITE,
35051475713Stsutsui (uint16_t *)data, 4 / 2);
3511208c816Sbjh21 data += 4;
3521208c816Sbjh21 resid -= 4;
3531208c816Sbjh21
3541208c816Sbjh21 for (; resid >= OAK_TSIZE_OUT; resid -= OAK_TSIZE_OUT) {
3551208c816Sbjh21 if (oak_ready(ncr_sc) == 0) {
3561208c816Sbjh21 resid += 4; /* Overshot */
3571208c816Sbjh21 goto interrupt;
3581208c816Sbjh21 }
3591208c816Sbjh21 bus_space_write_multi_2(pdmat, pdmah, OAK_PDMA_WRITE,
36051475713Stsutsui (uint16_t *)data, OAK_TSIZE_OUT / 2);
3611208c816Sbjh21 data += OAK_TSIZE_OUT;
3621208c816Sbjh21 }
3631208c816Sbjh21 if (oak_ready(ncr_sc) == 0) {
3641208c816Sbjh21 resid += 4; /* Overshot */
3651208c816Sbjh21 goto interrupt;
3661208c816Sbjh21 }
3671208c816Sbjh21 }
3681208c816Sbjh21
3691208c816Sbjh21 if (resid) {
3701208c816Sbjh21 bus_space_write_multi_2(pdmat, pdmah, OAK_PDMA_WRITE,
37151475713Stsutsui (uint16_t *)data, resid / 2);
3721208c816Sbjh21 resid = 0;
3731208c816Sbjh21 }
3741208c816Sbjh21 for (i = TIMEOUT; i > 0; i--) {
3751208c816Sbjh21 if ((NCR5380_READ(ncr_sc, sci_csr)
3761208c816Sbjh21 & (SCI_CSR_DREQ|SCI_CSR_PHASE_MATCH))
3771208c816Sbjh21 != SCI_CSR_DREQ)
3781208c816Sbjh21 break;
3791208c816Sbjh21 }
3801208c816Sbjh21 if (i != 0)
3811208c816Sbjh21 bus_space_write_2(pdmat, pdmah, OAK_PDMA_WRITE, 0);
3821208c816Sbjh21 else
3831208c816Sbjh21 printf("%s: timeout waiting for final SCI_DSR_DREQ.\n",
38451475713Stsutsui device_xname(ncr_sc->sc_dev));
3851208c816Sbjh21
3861208c816Sbjh21 oak_wait_not_req(ncr_sc);
3871208c816Sbjh21 interrupt:
3881208c816Sbjh21 SCI_CLR_INTR(ncr_sc);
3891208c816Sbjh21 NCR5380_WRITE(ncr_sc, sci_mode,
3901208c816Sbjh21 NCR5380_READ(ncr_sc, sci_mode) & ~SCI_MODE_DMA);
3911208c816Sbjh21 NCR5380_WRITE(ncr_sc, sci_icmd, icmd);
3921208c816Sbjh21 splx(s);
39351475713Stsutsui return datalen - resid;
3941208c816Sbjh21 }
3951208c816Sbjh21 #endif
396