1 1.22 andvar /* $NetBSD: oak.c,v 1.22 2025/05/19 06:16:24 andvar Exp $ */ 2 1.1 bjh21 3 1.1 bjh21 /* 4 1.1 bjh21 * Copyright (c) 1998 The NetBSD Foundation, Inc. 5 1.1 bjh21 * All rights reserved. 6 1.1 bjh21 * 7 1.1 bjh21 * This code is derived from software contributed to The NetBSD Foundation 8 1.1 bjh21 * by Mark Brinicombe of Causality Limited. 9 1.1 bjh21 * 10 1.1 bjh21 * Redistribution and use in source and binary forms, with or without 11 1.1 bjh21 * modification, are permitted provided that the following conditions 12 1.1 bjh21 * are met: 13 1.1 bjh21 * 1. Redistributions of source code must retain the above copyright 14 1.1 bjh21 * notice, this list of conditions and the following disclaimer. 15 1.1 bjh21 * 2. Redistributions in binary form must reproduce the above copyright 16 1.1 bjh21 * notice, this list of conditions and the following disclaimer in the 17 1.1 bjh21 * documentation and/or other materials provided with the distribution. 18 1.1 bjh21 * 19 1.1 bjh21 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 1.1 bjh21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 1.1 bjh21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 1.1 bjh21 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 1.1 bjh21 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 1.1 bjh21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 1.1 bjh21 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 1.1 bjh21 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 1.1 bjh21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 1.1 bjh21 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 1.1 bjh21 * POSSIBILITY OF SUCH DAMAGE. 30 1.1 bjh21 */ 31 1.1 bjh21 32 1.1 bjh21 /* 33 1.7 bjh21 * Oak Solutions SCSI 1 driver using the generic NCR5380 driver. 34 1.2 bjh21 * 35 1.7 bjh21 * From <URL:http://foldoc.doc.ic.ac.uk/acorn/doc/scsi>: 36 1.7 bjh21 * --------8<-------- 37 1.7 bjh21 * From: Hugo Fiennes 38 1.7 bjh21 * [...] 39 1.7 bjh21 * The oak scsi plays some other tricks to get max around 2.2Mb/sec: 40 1.7 bjh21 * it is a 16- bit interface (using their own hardware and an 8-bit 41 1.7 bjh21 * scsi controller to 'double-up' the data). What it does is: every 42 1.7 bjh21 * 128 bytes it uses a polling loop (see above) to check data is 43 1.7 bjh21 * present and the drive has reported no errors, etc. Inside each 128 44 1.7 bjh21 * byte block it just reads data as fast as it can: on a normal card 45 1.7 bjh21 * this would result in disaster if the drive wasn't fast enough to 46 1.7 bjh21 * feed the machine: on the oak card however, the hardware will not 47 1.7 bjh21 * assert IOGT (IO grant), so hanging the machine in a wait state 48 1.7 bjh21 * until data is ready. This can have problems: if the drive is to 49 1.7 bjh21 * slow (unlikely) the machine will completely stiff as the ARM3 can't 50 1.7 bjh21 * be kept in such a state for more than 10(?) us. 51 1.7 bjh21 * -------->8-------- 52 1.7 bjh21 * 53 1.7 bjh21 * So far, my attempts at doing this have failed, though. 54 1.2 bjh21 * 55 1.2 bjh21 * This card has to be polled: it doesn't have anything connected to 56 1.2 bjh21 * PIRQ*. This seems to be a common failing of Archimedes disc 57 1.2 bjh21 * controllers. 58 1.1 bjh21 */ 59 1.1 bjh21 60 1.6 lukem #include <sys/cdefs.h> 61 1.22 andvar __KERNEL_RCSID(0, "$NetBSD: oak.c,v 1.22 2025/05/19 06:16:24 andvar Exp $"); 62 1.6 lukem 63 1.1 bjh21 #include <sys/param.h> 64 1.2 bjh21 65 1.1 bjh21 #include <sys/systm.h> 66 1.1 bjh21 #include <sys/kernel.h> 67 1.1 bjh21 #include <sys/device.h> 68 1.1 bjh21 #include <sys/buf.h> 69 1.1 bjh21 #include <dev/scsipi/scsi_all.h> 70 1.1 bjh21 #include <dev/scsipi/scsipi_all.h> 71 1.1 bjh21 #include <dev/scsipi/scsiconf.h> 72 1.1 bjh21 73 1.1 bjh21 #include <dev/ic/ncr5380reg.h> 74 1.1 bjh21 #include <dev/ic/ncr5380var.h> 75 1.1 bjh21 76 1.1 bjh21 #include <machine/bootconfig.h> 77 1.1 bjh21 78 1.1 bjh21 #include <dev/podulebus/podulebus.h> 79 1.1 bjh21 #include <dev/podulebus/podules.h> 80 1.4 bjh21 #include <dev/podulebus/powerromreg.h> 81 1.1 bjh21 82 1.7 bjh21 #include <dev/podulebus/oakreg.h> 83 1.7 bjh21 84 1.18 tsutsui int oak_match(device_t, cfdata_t, void *); 85 1.18 tsutsui void oak_attach(device_t, device_t, void *); 86 1.1 bjh21 87 1.7 bjh21 #if 0 88 1.18 tsutsui static int oak_pdma_in(struct ncr5380_softc *, int, int, uint8_t *); 89 1.18 tsutsui static int oak_pdma_out(struct ncr5380_softc *, int, int, uint8_t *); 90 1.7 bjh21 #endif 91 1.7 bjh21 92 1.1 bjh21 /* 93 1.1 bjh21 * Oak SCSI 1 softc structure. 94 1.1 bjh21 * 95 1.1 bjh21 * Contains the generic ncr5380 device node, podule information and 96 1.1 bjh21 * global information required by the driver. 97 1.1 bjh21 */ 98 1.1 bjh21 99 1.1 bjh21 struct oak_softc { 100 1.1 bjh21 struct ncr5380_softc sc_ncr5380; 101 1.7 bjh21 bus_space_tag_t sc_pdmat; 102 1.7 bjh21 bus_space_handle_t sc_pdmah; 103 1.1 bjh21 }; 104 1.1 bjh21 105 1.18 tsutsui CFATTACH_DECL_NEW(oak, sizeof(struct oak_softc), 106 1.12 thorpej oak_match, oak_attach, NULL, NULL); 107 1.1 bjh21 108 1.1 bjh21 /* 109 1.1 bjh21 * Card probe function 110 1.1 bjh21 * 111 1.1 bjh21 * Just match the manufacturer and podule ID's 112 1.1 bjh21 */ 113 1.1 bjh21 114 1.1 bjh21 int 115 1.18 tsutsui oak_match(device_t parent, cfdata_t cf, void *aux) 116 1.1 bjh21 { 117 1.1 bjh21 struct podulebus_attach_args *pa = aux; 118 1.1 bjh21 119 1.9 bjh21 if (pa->pa_product == PODULE_OAK_SCSI) 120 1.3 bjh21 return 1; 121 1.3 bjh21 122 1.3 bjh21 /* PowerROM */ 123 1.3 bjh21 if (pa->pa_product == PODULE_ALSYSTEMS_SCSI && 124 1.3 bjh21 podulebus_initloader(pa) == 0 && 125 1.3 bjh21 podloader_callloader(pa, 0, 0) == PRID_OAK_SCSI1) 126 1.3 bjh21 return 1; 127 1.1 bjh21 128 1.5 bjh21 return 0; 129 1.1 bjh21 } 130 1.1 bjh21 131 1.1 bjh21 /* 132 1.1 bjh21 * Card attach function 133 1.1 bjh21 * 134 1.1 bjh21 */ 135 1.1 bjh21 136 1.1 bjh21 void 137 1.18 tsutsui oak_attach(device_t parent, device_t self, void *aux) 138 1.1 bjh21 { 139 1.17 thorpej struct oak_softc *sc = device_private(self); 140 1.18 tsutsui struct ncr5380_softc *ncr_sc = &sc->sc_ncr5380; 141 1.1 bjh21 struct podulebus_attach_args *pa = aux; 142 1.8 bjh21 #ifndef NCR5380_USE_BUS_SPACE 143 1.18 tsutsui uint8_t *iobase; 144 1.8 bjh21 #endif 145 1.20 chs char hi_option[sizeof(device_xname(self)) + 8]; 146 1.1 bjh21 147 1.18 tsutsui ncr_sc->sc_dev = self; 148 1.18 tsutsui ncr_sc->sc_flags |= NCR5380_FORCE_POLLING; 149 1.18 tsutsui ncr_sc->sc_min_dma_len = 0; 150 1.18 tsutsui ncr_sc->sc_no_disconnect = 0xff; 151 1.18 tsutsui ncr_sc->sc_parity_disable = 0; 152 1.18 tsutsui 153 1.18 tsutsui ncr_sc->sc_dma_alloc = NULL; 154 1.18 tsutsui ncr_sc->sc_dma_free = NULL; 155 1.18 tsutsui ncr_sc->sc_dma_poll = NULL; 156 1.18 tsutsui ncr_sc->sc_dma_setup = NULL; 157 1.18 tsutsui ncr_sc->sc_dma_start = NULL; 158 1.18 tsutsui ncr_sc->sc_dma_eop = NULL; 159 1.18 tsutsui ncr_sc->sc_dma_stop = NULL; 160 1.18 tsutsui ncr_sc->sc_intr_on = NULL; 161 1.18 tsutsui ncr_sc->sc_intr_off = NULL; 162 1.1 bjh21 163 1.2 bjh21 #ifdef NCR5380_USE_BUS_SPACE 164 1.18 tsutsui ncr_sc->sc_regt = pa->pa_mod_t; 165 1.18 tsutsui bus_space_map(ncr_sc->sc_regt, pa->pa_mod_base, 8, 0, 166 1.18 tsutsui &ncr_sc->sc_regh); 167 1.18 tsutsui ncr_sc->sci_r0 = 0; 168 1.18 tsutsui ncr_sc->sci_r1 = 1; 169 1.18 tsutsui ncr_sc->sci_r2 = 2; 170 1.18 tsutsui ncr_sc->sci_r3 = 3; 171 1.18 tsutsui ncr_sc->sci_r4 = 4; 172 1.18 tsutsui ncr_sc->sci_r5 = 5; 173 1.18 tsutsui ncr_sc->sci_r6 = 6; 174 1.18 tsutsui ncr_sc->sci_r7 = 7; 175 1.2 bjh21 #else 176 1.18 tsutsui iobase = (uint8_t *)pa->pa_mod_base; 177 1.18 tsutsui ncr_sc->sci_r0 = iobase + 0; 178 1.18 tsutsui ncr_sc->sci_r1 = iobase + 4; 179 1.18 tsutsui ncr_sc->sci_r2 = iobase + 8; 180 1.18 tsutsui ncr_sc->sci_r3 = iobase + 12; 181 1.18 tsutsui ncr_sc->sci_r4 = iobase + 16; 182 1.18 tsutsui ncr_sc->sci_r5 = iobase + 20; 183 1.18 tsutsui ncr_sc->sci_r6 = iobase + 24; 184 1.18 tsutsui ncr_sc->sci_r7 = iobase + 28; 185 1.2 bjh21 #endif 186 1.7 bjh21 sc->sc_pdmat = pa->pa_mod_t; 187 1.7 bjh21 bus_space_map(sc->sc_pdmat, pa->pa_mod_base + OAK_PDMA_OFFSET, 0x20, 0, 188 1.7 bjh21 &sc->sc_pdmah); 189 1.1 bjh21 190 1.18 tsutsui ncr_sc->sc_rev = NCR_VARIANT_NCR5380; 191 1.1 bjh21 192 1.18 tsutsui ncr_sc->sc_pio_in = ncr5380_pio_in; 193 1.18 tsutsui ncr_sc->sc_pio_out = ncr5380_pio_out; 194 1.1 bjh21 195 1.1 bjh21 /* Provide an override for the host id */ 196 1.18 tsutsui ncr_sc->sc_channel.chan_id = 7; 197 1.13 itojun snprintf(hi_option, sizeof(hi_option), "%s.hostid", 198 1.18 tsutsui device_xname(self)); 199 1.1 bjh21 (void)get_bootconf_option(boot_args, hi_option, 200 1.18 tsutsui BOOTOPT_TYPE_INT, &ncr_sc->sc_channel.chan_id); 201 1.18 tsutsui ncr_sc->sc_adapter.adapt_minphys = minphys; 202 1.1 bjh21 203 1.18 tsutsui aprint_normal(": host=%d, using 8 bit PIO\n", 204 1.18 tsutsui ncr_sc->sc_channel.chan_id); 205 1.1 bjh21 206 1.18 tsutsui ncr5380_attach(ncr_sc); 207 1.1 bjh21 } 208 1.7 bjh21 209 1.7 bjh21 /* 210 1.7 bjh21 * XXX The code below doesn't work correctly. I probably need more 211 1.7 bjh21 * details on how the card works. [bjh21 20011202] 212 1.7 bjh21 */ 213 1.7 bjh21 #if 0 214 1.7 bjh21 215 1.7 bjh21 #ifndef OAK_TSIZE_OUT 216 1.7 bjh21 #define OAK_TSIZE_OUT 128 217 1.7 bjh21 #endif 218 1.7 bjh21 219 1.7 bjh21 #ifndef OAK_TSIZE_IN 220 1.7 bjh21 #define OAK_TSIZE_IN 128 221 1.7 bjh21 #endif 222 1.7 bjh21 223 1.7 bjh21 #define TIMEOUT 1000000 224 1.7 bjh21 225 1.16 perry static inline int 226 1.7 bjh21 oak_ready(struct ncr5380_softc *sc) 227 1.7 bjh21 { 228 1.7 bjh21 int i; 229 1.7 bjh21 int status; 230 1.7 bjh21 231 1.7 bjh21 for (i = TIMEOUT; i > 0; i--) { 232 1.7 bjh21 status = NCR5380_READ(sc, sci_csr); 233 1.7 bjh21 if ((status & (SCI_CSR_DREQ | SCI_CSR_PHASE_MATCH)) == 234 1.7 bjh21 (SCI_CSR_DREQ | SCI_CSR_PHASE_MATCH)) 235 1.18 tsutsui return 1; 236 1.7 bjh21 237 1.7 bjh21 if ((status & SCI_CSR_PHASE_MATCH) == 0 || 238 1.7 bjh21 SCI_BUSY(sc) == 0) 239 1.18 tsutsui return 0; 240 1.7 bjh21 } 241 1.18 tsutsui printf("%s: ready timeout\n", device_xname(sc->sc_dev)); 242 1.18 tsutsui return 0; 243 1.7 bjh21 244 1.7 bjh21 #if 0 /* The Linux driver does this: */ 245 1.7 bjh21 struct oak_softc *sc = (void *)ncr_sc; 246 1.7 bjh21 bus_space_tag_t pdmat = sc->sc_pdmat; 247 1.7 bjh21 bus_space_handle_t pdmah = sc->sc_pdmah; 248 1.7 bjh21 int i, status; 249 1.7 bjh21 250 1.7 bjh21 for (i = TIMEOUT; i > 0; i--) { 251 1.7 bjh21 status = bus_space_read_2(pdmat, pdmah, OAK_PDMA_STATUS); 252 1.7 bjh21 if (status & 0x200) 253 1.18 tsutsui return 0; 254 1.7 bjh21 if (status & 0x100) 255 1.18 tsutsui return 1; 256 1.7 bjh21 } 257 1.18 tsutsui printf("%s: ready timeout, status = 0x%x\n", 258 1.18 tsutsui device_xname(ncr_sc->sc_dev), status); 259 1.18 tsutsui return 0; 260 1.7 bjh21 #endif 261 1.7 bjh21 } 262 1.7 bjh21 263 1.7 bjh21 264 1.7 bjh21 265 1.7 bjh21 /* Return zero on success. */ 266 1.16 perry static inline void oak_wait_not_req(struct ncr5380_softc *sc) 267 1.7 bjh21 { 268 1.7 bjh21 int timo; 269 1.7 bjh21 for (timo = TIMEOUT; timo; timo--) { 270 1.7 bjh21 if ((NCR5380_READ(sc, sci_bus_csr) & SCI_BUS_REQ) == 0 || 271 1.7 bjh21 (NCR5380_READ(sc, sci_csr) & SCI_CSR_PHASE_MATCH) == 0 || 272 1.7 bjh21 SCI_BUSY(sc) == 0) { 273 1.7 bjh21 return; 274 1.7 bjh21 } 275 1.7 bjh21 } 276 1.18 tsutsui printf("%s: pdma not_req timeout\n", device_xname(sc->sc_dev)); 277 1.7 bjh21 } 278 1.7 bjh21 279 1.7 bjh21 static int 280 1.7 bjh21 oak_pdma_in(struct ncr5380_softc *ncr_sc, int phase, int datalen, 281 1.18 tsutsui uint8_t *data) 282 1.7 bjh21 { 283 1.7 bjh21 struct oak_softc *sc = (void *)ncr_sc; 284 1.7 bjh21 bus_space_tag_t pdmat = sc->sc_pdmat; 285 1.7 bjh21 bus_space_handle_t pdmah = sc->sc_pdmah; 286 1.7 bjh21 int s, resid, len; 287 1.7 bjh21 288 1.7 bjh21 s = splbio(); 289 1.7 bjh21 290 1.7 bjh21 NCR5380_WRITE(ncr_sc, sci_mode, 291 1.7 bjh21 NCR5380_READ(ncr_sc, sci_mode) | SCI_MODE_DMA); 292 1.7 bjh21 NCR5380_WRITE(ncr_sc, sci_irecv, 0); 293 1.7 bjh21 294 1.7 bjh21 resid = datalen; 295 1.7 bjh21 while (resid > 0) { 296 1.21 riastrad len = uimin(resid, OAK_TSIZE_IN); 297 1.7 bjh21 if (oak_ready(ncr_sc) == 0) 298 1.7 bjh21 goto interrupt; 299 1.18 tsutsui KASSERT(BUS_SPACE_ALIGNED_POINTER(data, uint16_t)); 300 1.7 bjh21 bus_space_read_multi_2(pdmat, pdmah, OAK_PDMA_READ, 301 1.18 tsutsui (uint16_t *)data, len / 2); 302 1.7 bjh21 data += len; 303 1.7 bjh21 resid -= len; 304 1.7 bjh21 } 305 1.7 bjh21 306 1.7 bjh21 oak_wait_not_req(ncr_sc); 307 1.7 bjh21 308 1.7 bjh21 interrupt: 309 1.7 bjh21 SCI_CLR_INTR(ncr_sc); 310 1.7 bjh21 NCR5380_WRITE(ncr_sc, sci_mode, 311 1.7 bjh21 NCR5380_READ(ncr_sc, sci_mode) & ~SCI_MODE_DMA); 312 1.7 bjh21 splx(s); 313 1.7 bjh21 return datalen - resid; 314 1.7 bjh21 } 315 1.7 bjh21 316 1.7 bjh21 static int 317 1.7 bjh21 oak_pdma_out(struct ncr5380_softc *ncr_sc, int phase, int datalen, 318 1.18 tsutsui uint8_t *data) 319 1.7 bjh21 { 320 1.18 tsutsui struct oak_softc *sc = (struct oak_softc *)ncr_sc; 321 1.7 bjh21 bus_space_tag_t pdmat = sc->sc_pdmat; 322 1.7 bjh21 bus_space_handle_t pdmah = sc->sc_pdmah; 323 1.7 bjh21 int i, s, icmd, resid; 324 1.7 bjh21 325 1.7 bjh21 s = splbio(); 326 1.7 bjh21 icmd = NCR5380_READ(ncr_sc, sci_icmd) & SCI_ICMD_RMASK; 327 1.7 bjh21 NCR5380_WRITE(ncr_sc, sci_icmd, icmd | SCI_ICMD_DATA); 328 1.7 bjh21 NCR5380_WRITE(ncr_sc, sci_mode, 329 1.7 bjh21 NCR5380_READ(ncr_sc, sci_mode) | SCI_MODE_DMA); 330 1.7 bjh21 NCR5380_WRITE(ncr_sc, sci_dma_send, 0); 331 1.7 bjh21 332 1.7 bjh21 resid = datalen; 333 1.7 bjh21 if (oak_ready(ncr_sc) == 0) 334 1.7 bjh21 goto interrupt; 335 1.7 bjh21 336 1.7 bjh21 if (resid > OAK_TSIZE_OUT) { 337 1.7 bjh21 /* 338 1.7 bjh21 * Because of the chips DMA prefetch, phase changes 339 1.7 bjh21 * etc, won't be detected until we have written at 340 1.7 bjh21 * least one byte more. We pre-write 4 bytes so 341 1.7 bjh21 * subsequent transfers will be aligned to a 4 byte 342 1.22 andvar * boundary. Assuming disconnects will only occur on 343 1.7 bjh21 * block boundaries, we then correct for the pre-write 344 1.7 bjh21 * when and if we get a phase change. If the chip had 345 1.7 bjh21 * DMA byte counting hardware, the assumption would not 346 1.7 bjh21 * be necessary. 347 1.7 bjh21 */ 348 1.18 tsutsui KASSERT(BUS_SPACE_ALIGNED_POINTER(data, uint16_t)); 349 1.7 bjh21 bus_space_write_multi_2(pdmat, pdmah, OAK_PDMA_WRITE, 350 1.18 tsutsui (uint16_t *)data, 4 / 2); 351 1.7 bjh21 data += 4; 352 1.7 bjh21 resid -= 4; 353 1.14 perry 354 1.7 bjh21 for (; resid >= OAK_TSIZE_OUT; resid -= OAK_TSIZE_OUT) { 355 1.7 bjh21 if (oak_ready(ncr_sc) == 0) { 356 1.7 bjh21 resid += 4; /* Overshot */ 357 1.7 bjh21 goto interrupt; 358 1.7 bjh21 } 359 1.7 bjh21 bus_space_write_multi_2(pdmat, pdmah, OAK_PDMA_WRITE, 360 1.18 tsutsui (uint16_t *)data, OAK_TSIZE_OUT / 2); 361 1.7 bjh21 data += OAK_TSIZE_OUT; 362 1.7 bjh21 } 363 1.7 bjh21 if (oak_ready(ncr_sc) == 0) { 364 1.7 bjh21 resid += 4; /* Overshot */ 365 1.7 bjh21 goto interrupt; 366 1.7 bjh21 } 367 1.7 bjh21 } 368 1.7 bjh21 369 1.7 bjh21 if (resid) { 370 1.7 bjh21 bus_space_write_multi_2(pdmat, pdmah, OAK_PDMA_WRITE, 371 1.18 tsutsui (uint16_t *)data, resid / 2); 372 1.7 bjh21 resid = 0; 373 1.7 bjh21 } 374 1.7 bjh21 for (i = TIMEOUT; i > 0; i--) { 375 1.7 bjh21 if ((NCR5380_READ(ncr_sc, sci_csr) 376 1.7 bjh21 & (SCI_CSR_DREQ|SCI_CSR_PHASE_MATCH)) 377 1.7 bjh21 != SCI_CSR_DREQ) 378 1.7 bjh21 break; 379 1.7 bjh21 } 380 1.7 bjh21 if (i != 0) 381 1.7 bjh21 bus_space_write_2(pdmat, pdmah, OAK_PDMA_WRITE, 0); 382 1.7 bjh21 else 383 1.7 bjh21 printf("%s: timeout waiting for final SCI_DSR_DREQ.\n", 384 1.18 tsutsui device_xname(ncr_sc->sc_dev)); 385 1.7 bjh21 386 1.7 bjh21 oak_wait_not_req(ncr_sc); 387 1.7 bjh21 interrupt: 388 1.7 bjh21 SCI_CLR_INTR(ncr_sc); 389 1.7 bjh21 NCR5380_WRITE(ncr_sc, sci_mode, 390 1.7 bjh21 NCR5380_READ(ncr_sc, sci_mode) & ~SCI_MODE_DMA); 391 1.7 bjh21 NCR5380_WRITE(ncr_sc, sci_icmd, icmd); 392 1.7 bjh21 splx(s); 393 1.18 tsutsui return datalen - resid; 394 1.7 bjh21 } 395 1.7 bjh21 #endif 396