1 1.39 tsutsui /* $NetBSD: si_obio.c,v 1.39 2024/12/20 23:52:00 tsutsui Exp $ */ 2 1.1 gwr 3 1.7 gwr /*- 4 1.7 gwr * Copyright (c) 1996 The NetBSD Foundation, Inc. 5 1.1 gwr * All rights reserved. 6 1.1 gwr * 7 1.7 gwr * This code is derived from software contributed to The NetBSD Foundation 8 1.7 gwr * by Adam Glass, David Jones, and Gordon W. Ross. 9 1.7 gwr * 10 1.1 gwr * Redistribution and use in source and binary forms, with or without 11 1.1 gwr * modification, are permitted provided that the following conditions 12 1.1 gwr * are met: 13 1.1 gwr * 1. Redistributions of source code must retain the above copyright 14 1.1 gwr * notice, this list of conditions and the following disclaimer. 15 1.1 gwr * 2. Redistributions in binary form must reproduce the above copyright 16 1.1 gwr * notice, this list of conditions and the following disclaimer in the 17 1.1 gwr * documentation and/or other materials provided with the distribution. 18 1.1 gwr * 19 1.7 gwr * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 1.7 gwr * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 1.7 gwr * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 1.9 gwr * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 1.9 gwr * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 1.7 gwr * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 1.7 gwr * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 1.7 gwr * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 1.7 gwr * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 1.7 gwr * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 1.7 gwr * POSSIBILITY OF SUCH DAMAGE. 30 1.1 gwr */ 31 1.1 gwr 32 1.1 gwr /* 33 1.1 gwr * This file contains only the machine-dependent parts of the 34 1.1 gwr * Sun3 SCSI driver. (Autoconfig stuff and DMA functions.) 35 1.1 gwr * The machine-independent parts are in ncr5380sbc.c 36 1.1 gwr * 37 1.1 gwr * Supported hardware includes: 38 1.1 gwr * Sun SCSI-3 on OBIO (Sun3/50,Sun3/60) 39 1.1 gwr * Sun SCSI-3 on VME (Sun3/160,Sun3/260) 40 1.1 gwr * 41 1.1 gwr * Could be made to support the Sun3/E if someone wanted to. 42 1.1 gwr * 43 1.1 gwr * Note: Both supported variants of the Sun SCSI-3 adapter have 44 1.1 gwr * some really unusual "features" for this driver to deal with, 45 1.1 gwr * generally related to the DMA engine. The OBIO variant will 46 1.1 gwr * ignore any attempt to write the FIFO count register while the 47 1.1 gwr * SCSI bus is in DATA_IN or DATA_OUT phase. This is dealt with 48 1.1 gwr * by setting the FIFO count early in COMMAND or MSG_IN phase. 49 1.1 gwr * 50 1.1 gwr * The VME variant has a bit to enable or disable the DMA engine, 51 1.1 gwr * but that bit also gates the interrupt line from the NCR5380! 52 1.1 gwr * Therefore, in order to get any interrupt from the 5380, (i.e. 53 1.1 gwr * for reselect) one must clear the DMA engine transfer count and 54 1.1 gwr * then enable DMA. This has the further complication that you 55 1.1 gwr * CAN NOT touch the NCR5380 while the DMA enable bit is set, so 56 1.1 gwr * we have to turn DMA back off before we even look at the 5380. 57 1.1 gwr * 58 1.1 gwr * What wonderfully whacky hardware this is! 59 1.1 gwr * 60 1.1 gwr * Credits, history: 61 1.1 gwr * 62 1.1 gwr * David Jones wrote the initial version of this module, which 63 1.1 gwr * included support for the VME adapter only. (no reselection). 64 1.1 gwr * 65 1.1 gwr * Gordon Ross added support for the OBIO adapter, and re-worked 66 1.1 gwr * both the VME and OBIO code to support disconnect/reselect. 67 1.1 gwr * (Required figuring out the hardware "features" noted above.) 68 1.1 gwr * 69 1.1 gwr * The autoconfiguration boilerplate came from Adam Glass. 70 1.1 gwr */ 71 1.1 gwr 72 1.1 gwr /***************************************************************** 73 1.1 gwr * OBIO functions for DMA 74 1.1 gwr ****************************************************************/ 75 1.27 lukem 76 1.27 lukem #include <sys/cdefs.h> 77 1.39 tsutsui __KERNEL_RCSID(0, "$NetBSD: si_obio.c,v 1.39 2024/12/20 23:52:00 tsutsui Exp $"); 78 1.1 gwr 79 1.1 gwr #include <sys/param.h> 80 1.1 gwr #include <sys/systm.h> 81 1.1 gwr #include <sys/errno.h> 82 1.1 gwr #include <sys/kernel.h> 83 1.1 gwr #include <sys/device.h> 84 1.1 gwr #include <sys/buf.h> 85 1.1 gwr #include <sys/proc.h> 86 1.1 gwr 87 1.14 bouyer #include <dev/scsipi/scsi_all.h> 88 1.14 bouyer #include <dev/scsipi/scsipi_all.h> 89 1.14 bouyer #include <dev/scsipi/scsipi_debug.h> 90 1.14 bouyer #include <dev/scsipi/scsiconf.h> 91 1.1 gwr 92 1.1 gwr #include <machine/autoconf.h> 93 1.1 gwr #include <machine/dvma.h> 94 1.1 gwr 95 1.18 gwr /* #define DEBUG XXX */ 96 1.1 gwr 97 1.1 gwr #include <dev/ic/ncr5380reg.h> 98 1.1 gwr #include <dev/ic/ncr5380var.h> 99 1.1 gwr 100 1.1 gwr #include "sireg.h" 101 1.1 gwr #include "sivar.h" 102 1.1 gwr #include "am9516.h" 103 1.1 gwr 104 1.1 gwr /* 105 1.1 gwr * How many uS. to delay after touching the am9516 UDC. 106 1.1 gwr */ 107 1.1 gwr #define UDC_WAIT_USEC 5 108 1.1 gwr 109 1.29 chs void si_obio_dma_setup(struct ncr5380_softc *); 110 1.29 chs void si_obio_dma_start(struct ncr5380_softc *); 111 1.29 chs void si_obio_dma_eop(struct ncr5380_softc *); 112 1.29 chs void si_obio_dma_stop(struct ncr5380_softc *); 113 1.29 chs 114 1.29 chs static void si_obio_reset(struct ncr5380_softc *); 115 1.29 chs 116 1.31 perry static inline void si_obio_udc_write(volatile struct si_regs *, int, int); 117 1.31 perry static inline int si_obio_udc_read(volatile struct si_regs *, int); 118 1.8 gwr 119 1.8 gwr 120 1.1 gwr /* 121 1.1 gwr * New-style autoconfig attachment 122 1.1 gwr */ 123 1.1 gwr 124 1.34 tsutsui static int si_obio_match(device_t, cfdata_t, void *); 125 1.34 tsutsui static void si_obio_attach(device_t, device_t, void *); 126 1.1 gwr 127 1.34 tsutsui CFATTACH_DECL_NEW(si_obio, sizeof(struct si_softc), 128 1.25 thorpej si_obio_match, si_obio_attach, NULL, NULL); 129 1.1 gwr 130 1.10 gwr /* 131 1.11 gwr * Options for disconnect/reselect, DMA, and interrupts. 132 1.11 gwr * By default, allow disconnect/reselect on targets 4-6. 133 1.11 gwr * Those are normally tapes that really need it enabled. 134 1.10 gwr */ 135 1.16 gwr int si_obio_options = 0x0f; 136 1.1 gwr 137 1.1 gwr 138 1.39 tsutsui static int 139 1.34 tsutsui si_obio_match(device_t parent, cfdata_t cf, void *aux) 140 1.1 gwr { 141 1.16 gwr struct confargs *ca = aux; 142 1.1 gwr 143 1.16 gwr /* Make sure something is there... */ 144 1.5 gwr if (bus_peek(ca->ca_bustype, ca->ca_paddr + 1, 1) == -1) 145 1.34 tsutsui return 0; 146 1.1 gwr 147 1.5 gwr /* Default interrupt priority. */ 148 1.5 gwr if (ca->ca_intpri == -1) 149 1.5 gwr ca->ca_intpri = 2; 150 1.1 gwr 151 1.34 tsutsui return 1; 152 1.1 gwr } 153 1.1 gwr 154 1.39 tsutsui static void 155 1.34 tsutsui si_obio_attach(device_t parent, device_t self, void *args) 156 1.1 gwr { 157 1.34 tsutsui struct si_softc *sc = device_private(self); 158 1.1 gwr struct ncr5380_softc *ncr_sc = &sc->ncr_sc; 159 1.32 thorpej struct cfdata *cf = device_cfdata(self); 160 1.1 gwr struct confargs *ca = args; 161 1.1 gwr 162 1.34 tsutsui ncr_sc->sc_dev = self; 163 1.33 tsutsui sc->sc_bst = ca->ca_bustag; 164 1.33 tsutsui sc->sc_dmat = ca->ca_dmatag; 165 1.33 tsutsui 166 1.33 tsutsui if (bus_space_map(sc->sc_bst, ca->ca_paddr, sizeof(struct si_regs), 0, 167 1.33 tsutsui &sc->sc_bsh) != 0) { 168 1.34 tsutsui aprint_error(": can't map register\n"); 169 1.33 tsutsui return; 170 1.33 tsutsui } 171 1.33 tsutsui sc->sc_regs = bus_space_vaddr(sc->sc_bst, sc->sc_bsh); 172 1.33 tsutsui 173 1.33 tsutsui if (bus_dmamap_create(sc->sc_dmat, MAXPHYS, 1, MAXPHYS, 0, 174 1.33 tsutsui BUS_DMA_NOWAIT, &sc->sc_dmap) != 0) { 175 1.34 tsutsui aprint_error(": can't create DMA map\n"); 176 1.33 tsutsui return; 177 1.33 tsutsui } 178 1.33 tsutsui 179 1.11 gwr /* Get options from config flags if specified. */ 180 1.11 gwr if (cf->cf_flags) 181 1.11 gwr sc->sc_options = cf->cf_flags; 182 1.11 gwr else 183 1.11 gwr sc->sc_options = si_obio_options; 184 1.11 gwr 185 1.34 tsutsui aprint_normal(": options=0x%x\n", sc->sc_options); 186 1.1 gwr 187 1.1 gwr sc->sc_adapter_type = ca->ca_bustype; 188 1.1 gwr 189 1.1 gwr /* 190 1.1 gwr * MD function pointers used by the MI code. 191 1.1 gwr */ 192 1.1 gwr ncr_sc->sc_pio_out = ncr5380_pio_out; 193 1.1 gwr ncr_sc->sc_pio_in = ncr5380_pio_in; 194 1.1 gwr ncr_sc->sc_dma_alloc = si_dma_alloc; 195 1.1 gwr ncr_sc->sc_dma_free = si_dma_free; 196 1.1 gwr ncr_sc->sc_dma_setup = si_obio_dma_setup; 197 1.1 gwr ncr_sc->sc_dma_start = si_obio_dma_start; 198 1.2 gwr ncr_sc->sc_dma_poll = si_dma_poll; 199 1.2 gwr ncr_sc->sc_dma_eop = si_obio_dma_eop; 200 1.1 gwr ncr_sc->sc_dma_stop = si_obio_dma_stop; 201 1.1 gwr ncr_sc->sc_intr_on = NULL; 202 1.1 gwr ncr_sc->sc_intr_off = NULL; 203 1.1 gwr 204 1.1 gwr /* Need DVMA-capable memory for the UDC command block. */ 205 1.34 tsutsui sc->sc_dmacmd = dvma_malloc(sizeof(struct udc_table)); 206 1.1 gwr 207 1.1 gwr /* Attach interrupt handler. */ 208 1.5 gwr isr_add_autovect(si_intr, (void *)sc, ca->ca_intpri); 209 1.1 gwr 210 1.16 gwr /* Reset the hardware. */ 211 1.16 gwr si_obio_reset(ncr_sc); 212 1.16 gwr 213 1.1 gwr /* Do the common attach stuff. */ 214 1.1 gwr si_attach(sc); 215 1.1 gwr } 216 1.1 gwr 217 1.16 gwr static void 218 1.16 gwr si_obio_reset(struct ncr5380_softc *ncr_sc) 219 1.16 gwr { 220 1.16 gwr struct si_softc *sc = (struct si_softc *)ncr_sc; 221 1.16 gwr volatile struct si_regs *si = sc->sc_regs; 222 1.16 gwr 223 1.16 gwr #ifdef DEBUG 224 1.16 gwr if (si_debug) { 225 1.34 tsutsui printf("%s\n", __func__); 226 1.16 gwr } 227 1.16 gwr #endif 228 1.16 gwr 229 1.16 gwr /* 230 1.16 gwr * The SCSI3 controller has an 8K FIFO to buffer data between the 231 1.16 gwr * 5380 and the DMA. Make sure it starts out empty. 232 1.16 gwr * 233 1.16 gwr * The reset bits in the CSR are active low. 234 1.16 gwr */ 235 1.16 gwr si->si_csr = 0; 236 1.16 gwr delay(10); 237 1.16 gwr si->si_csr = SI_CSR_FIFO_RES | SI_CSR_SCSI_RES | SI_CSR_INTR_EN; 238 1.16 gwr delay(10); 239 1.16 gwr si->fifo_count = 0; 240 1.16 gwr } 241 1.1 gwr 242 1.39 tsutsui static inline void 243 1.29 chs si_obio_udc_write(volatile struct si_regs *si, int regnum, int value) 244 1.1 gwr { 245 1.34 tsutsui 246 1.1 gwr si->udc_addr = regnum; 247 1.1 gwr delay(UDC_WAIT_USEC); 248 1.1 gwr si->udc_data = value; 249 1.1 gwr delay(UDC_WAIT_USEC); 250 1.1 gwr } 251 1.1 gwr 252 1.39 tsutsui static inline int 253 1.29 chs si_obio_udc_read(volatile struct si_regs *si, int regnum) 254 1.1 gwr { 255 1.1 gwr int value; 256 1.1 gwr 257 1.1 gwr si->udc_addr = regnum; 258 1.1 gwr delay(UDC_WAIT_USEC); 259 1.1 gwr value = si->udc_data; 260 1.1 gwr delay(UDC_WAIT_USEC); 261 1.1 gwr 262 1.34 tsutsui return value; 263 1.1 gwr } 264 1.1 gwr 265 1.1 gwr 266 1.1 gwr /* 267 1.1 gwr * This function is called during the COMMAND or MSG_IN phase 268 1.22 wiz * that precedes a DATA_IN or DATA_OUT phase, in case we need 269 1.1 gwr * to setup the DMA engine before the bus enters a DATA phase. 270 1.1 gwr * 271 1.1 gwr * The OBIO "si" IGNORES any attempt to set the FIFO count 272 1.1 gwr * register after the SCSI bus goes into any DATA phase, so 273 1.1 gwr * this function has to setup the evil FIFO logic. 274 1.1 gwr */ 275 1.39 tsutsui void 276 1.29 chs si_obio_dma_setup(struct ncr5380_softc *ncr_sc) 277 1.1 gwr { 278 1.1 gwr struct si_softc *sc = (struct si_softc *)ncr_sc; 279 1.2 gwr struct sci_req *sr = ncr_sc->sc_current; 280 1.2 gwr struct si_dma_handle *dh = sr->sr_dma_hand; 281 1.1 gwr volatile struct si_regs *si = sc->sc_regs; 282 1.2 gwr struct udc_table *cmd; 283 1.2 gwr long data_pa, cmd_pa; 284 1.2 gwr int xlen; 285 1.2 gwr 286 1.2 gwr /* 287 1.2 gwr * Get the DVMA mapping for this segment. 288 1.2 gwr * XXX - Should separate allocation and mapin. 289 1.2 gwr */ 290 1.33 tsutsui data_pa = dh->dh_dmaaddr; 291 1.2 gwr if (data_pa & 1) 292 1.34 tsutsui panic("%s: bad pa=0x%lx", __func__, data_pa); 293 1.33 tsutsui xlen = dh->dh_dmalen; 294 1.2 gwr sc->sc_reqlen = xlen; /* XXX: or less? */ 295 1.1 gwr 296 1.1 gwr #ifdef DEBUG 297 1.2 gwr if (si_debug & 2) { 298 1.34 tsutsui printf("%s: dh=%p, pa=0x%lx, xlen=0x%x\n", 299 1.34 tsutsui __func__, dh, data_pa, xlen); 300 1.1 gwr } 301 1.1 gwr #endif 302 1.1 gwr 303 1.1 gwr /* Reset the UDC. (In case not already reset?) */ 304 1.1 gwr si_obio_udc_write(si, UDC_ADR_COMMAND, UDC_CMD_RESET); 305 1.1 gwr 306 1.1 gwr /* Reset the FIFO */ 307 1.1 gwr si->si_csr &= ~SI_CSR_FIFO_RES; /* active low */ 308 1.1 gwr si->si_csr |= SI_CSR_FIFO_RES; 309 1.1 gwr 310 1.1 gwr /* Set direction (send/recv) */ 311 1.2 gwr if (dh->dh_flags & SIDH_OUT) { 312 1.1 gwr si->si_csr |= SI_CSR_SEND; 313 1.1 gwr } else { 314 1.1 gwr si->si_csr &= ~SI_CSR_SEND; 315 1.1 gwr } 316 1.1 gwr 317 1.1 gwr /* Set the FIFO counter. */ 318 1.1 gwr si->fifo_count = xlen; 319 1.1 gwr 320 1.2 gwr /* Reset the UDC. */ 321 1.2 gwr si_obio_udc_write(si, UDC_ADR_COMMAND, UDC_CMD_RESET); 322 1.2 gwr 323 1.1 gwr /* 324 1.2 gwr * XXX: Reset the FIFO again! Comment from Sprite: 325 1.28 wiz * Go through reset again because of the bug on the 3/50 326 1.1 gwr * where bytes occasionally linger in the DMA fifo. 327 1.1 gwr */ 328 1.1 gwr si->si_csr &= ~SI_CSR_FIFO_RES; /* active low */ 329 1.1 gwr si->si_csr |= SI_CSR_FIFO_RES; 330 1.1 gwr 331 1.1 gwr #ifdef DEBUG 332 1.2 gwr /* Make sure the extra FIFO reset did not hit the count. */ 333 1.2 gwr if (si->fifo_count != xlen) { 334 1.34 tsutsui printf("%s: fifo_count=0x%x, xlen=0x%x\n", 335 1.34 tsutsui __func__, si->fifo_count, xlen); 336 1.1 gwr Debugger(); 337 1.1 gwr } 338 1.1 gwr #endif 339 1.1 gwr 340 1.1 gwr /* 341 1.2 gwr * Set up the DMA controller. The DMA controller on 342 1.2 gwr * OBIO needs a command block in DVMA space. 343 1.1 gwr */ 344 1.1 gwr cmd = sc->sc_dmacmd; 345 1.1 gwr cmd->addrh = ((data_pa & 0xFF0000) >> 8) | UDC_ADDR_INFO; 346 1.1 gwr cmd->addrl = data_pa & 0xFFFF; 347 1.1 gwr cmd->count = xlen / 2; /* bytes -> words */ 348 1.1 gwr cmd->cmrh = UDC_CMR_HIGH; 349 1.1 gwr if (dh->dh_flags & SIDH_OUT) { 350 1.2 gwr if (xlen & 1) 351 1.2 gwr cmd->count++; 352 1.1 gwr cmd->cmrl = UDC_CMR_LSEND; 353 1.1 gwr cmd->rsel = UDC_RSEL_SEND; 354 1.1 gwr } else { 355 1.1 gwr cmd->cmrl = UDC_CMR_LRECV; 356 1.1 gwr cmd->rsel = UDC_RSEL_RECV; 357 1.1 gwr } 358 1.1 gwr 359 1.1 gwr /* Tell the DMA chip where the control block is. */ 360 1.17 gwr cmd_pa = dvma_kvtopa(cmd, BUS_OBIO); 361 1.34 tsutsui si_obio_udc_write(si, UDC_ADR_CAR_HIGH, (cmd_pa & 0xff0000) >> 8); 362 1.34 tsutsui si_obio_udc_write(si, UDC_ADR_CAR_LOW, (cmd_pa & 0xffff)); 363 1.1 gwr 364 1.1 gwr /* Tell the chip to be a DMA master. */ 365 1.1 gwr si_obio_udc_write(si, UDC_ADR_MODE, UDC_MODE); 366 1.1 gwr 367 1.1 gwr /* Tell the chip to interrupt on error. */ 368 1.1 gwr si_obio_udc_write(si, UDC_ADR_COMMAND, UDC_CMD_CIE); 369 1.1 gwr 370 1.2 gwr /* Will do "start chain" command in _dma_start. */ 371 1.2 gwr } 372 1.2 gwr 373 1.2 gwr 374 1.39 tsutsui void 375 1.29 chs si_obio_dma_start(struct ncr5380_softc *ncr_sc) 376 1.2 gwr { 377 1.2 gwr struct si_softc *sc = (struct si_softc *)ncr_sc; 378 1.2 gwr struct sci_req *sr = ncr_sc->sc_current; 379 1.2 gwr struct si_dma_handle *dh = sr->sr_dma_hand; 380 1.2 gwr volatile struct si_regs *si = sc->sc_regs; 381 1.2 gwr int s; 382 1.2 gwr 383 1.2 gwr #ifdef DEBUG 384 1.2 gwr if (si_debug & 2) { 385 1.34 tsutsui printf("%s: sr=%p\n", __func__, sr); 386 1.2 gwr } 387 1.2 gwr #endif 388 1.2 gwr 389 1.2 gwr /* This MAY be time critical (not sure). */ 390 1.2 gwr s = splhigh(); 391 1.1 gwr 392 1.1 gwr /* Finally, give the UDC a "start chain" command. */ 393 1.1 gwr si_obio_udc_write(si, UDC_ADR_COMMAND, UDC_CMD_STRT_CHN); 394 1.1 gwr 395 1.1 gwr /* 396 1.1 gwr * Acknowledge the phase change. (After DMA setup!) 397 1.1 gwr * Put the SBIC into DMA mode, and start the transfer. 398 1.1 gwr */ 399 1.1 gwr if (dh->dh_flags & SIDH_OUT) { 400 1.1 gwr *ncr_sc->sci_tcmd = PHASE_DATA_OUT; 401 1.1 gwr SCI_CLR_INTR(ncr_sc); 402 1.1 gwr *ncr_sc->sci_icmd = SCI_ICMD_DATA; 403 1.1 gwr *ncr_sc->sci_mode |= (SCI_MODE_DMA | SCI_MODE_DMA_IE); 404 1.1 gwr *ncr_sc->sci_dma_send = 0; /* start it */ 405 1.1 gwr } else { 406 1.1 gwr *ncr_sc->sci_tcmd = PHASE_DATA_IN; 407 1.1 gwr SCI_CLR_INTR(ncr_sc); 408 1.1 gwr *ncr_sc->sci_icmd = 0; 409 1.1 gwr *ncr_sc->sci_mode |= (SCI_MODE_DMA | SCI_MODE_DMA_IE); 410 1.1 gwr *ncr_sc->sci_irecv = 0; /* start it */ 411 1.1 gwr } 412 1.1 gwr 413 1.2 gwr splx(s); 414 1.1 gwr ncr_sc->sc_state |= NCR_DOINGDMA; 415 1.1 gwr 416 1.1 gwr #ifdef DEBUG 417 1.1 gwr if (si_debug & 2) { 418 1.34 tsutsui printf("%s: started, flags=0x%x\n", 419 1.34 tsutsui __func__, ncr_sc->sc_state); 420 1.1 gwr } 421 1.1 gwr #endif 422 1.1 gwr } 423 1.1 gwr 424 1.1 gwr 425 1.39 tsutsui void 426 1.29 chs si_obio_dma_eop(struct ncr5380_softc *ncr_sc) 427 1.1 gwr { 428 1.1 gwr 429 1.1 gwr /* Not needed - DMA was stopped prior to examining sci_csr */ 430 1.1 gwr } 431 1.1 gwr 432 1.1 gwr 433 1.39 tsutsui void 434 1.29 chs si_obio_dma_stop(struct ncr5380_softc *ncr_sc) 435 1.1 gwr { 436 1.1 gwr struct si_softc *sc = (struct si_softc *)ncr_sc; 437 1.1 gwr struct sci_req *sr = ncr_sc->sc_current; 438 1.1 gwr struct si_dma_handle *dh = sr->sr_dma_hand; 439 1.1 gwr volatile struct si_regs *si = sc->sc_regs; 440 1.1 gwr int resid, ntrans, tmo, udc_cnt; 441 1.1 gwr 442 1.1 gwr if ((ncr_sc->sc_state & NCR_DOINGDMA) == 0) { 443 1.1 gwr #ifdef DEBUG 444 1.34 tsutsui printf("%s: DMA not running\n", __func__); 445 1.1 gwr #endif 446 1.1 gwr return; 447 1.1 gwr } 448 1.1 gwr ncr_sc->sc_state &= ~NCR_DOINGDMA; 449 1.1 gwr 450 1.2 gwr NCR_TRACE("si_dma_stop: top, csr=0x%x\n", si->si_csr); 451 1.2 gwr 452 1.2 gwr /* OK, have either phase mis-match or end of DMA. */ 453 1.2 gwr /* Set an impossible phase to prevent data movement? */ 454 1.2 gwr *ncr_sc->sci_tcmd = PHASE_INVALID; 455 1.2 gwr 456 1.2 gwr /* Check for DMA errors. */ 457 1.1 gwr if (si->si_csr & (SI_CSR_DMA_CONFLICT | SI_CSR_DMA_BUS_ERR)) { 458 1.4 christos printf("si: DMA error, csr=0x%x, reset\n", si->si_csr); 459 1.1 gwr sr->sr_xs->error = XS_DRIVER_STUFFUP; 460 1.1 gwr ncr_sc->sc_state |= NCR_ABORTING; 461 1.16 gwr si_obio_reset(ncr_sc); 462 1.2 gwr goto out; 463 1.1 gwr } 464 1.1 gwr 465 1.1 gwr /* Note that timeout may have set the error flag. */ 466 1.1 gwr if (ncr_sc->sc_state & NCR_ABORTING) 467 1.1 gwr goto out; 468 1.1 gwr 469 1.1 gwr /* 470 1.1 gwr * After a read, wait for the FIFO to empty. 471 1.1 gwr * Note: this only works on the OBIO version. 472 1.1 gwr */ 473 1.1 gwr if ((dh->dh_flags & SIDH_OUT) == 0) { 474 1.1 gwr tmo = 200000; /* X10 = 2 sec. */ 475 1.1 gwr for (;;) { 476 1.1 gwr if (si->si_csr & SI_CSR_FIFO_EMPTY) 477 1.1 gwr break; 478 1.1 gwr if (--tmo <= 0) { 479 1.26 wiz printf("si: DMA FIFO did not empty, reset\n"); 480 1.1 gwr ncr_sc->sc_state |= NCR_ABORTING; 481 1.16 gwr /* si_obio_reset(ncr_sc); */ 482 1.1 gwr goto out; 483 1.1 gwr } 484 1.1 gwr delay(10); 485 1.1 gwr } 486 1.1 gwr } 487 1.1 gwr 488 1.1 gwr /* 489 1.15 gwr * Now try to figure out how much actually transferred. 490 1.1 gwr * The fifo_count might not reflect how many bytes were 491 1.2 gwr * actually transferred. 492 1.1 gwr */ 493 1.1 gwr resid = si->fifo_count & 0xFFFF; 494 1.1 gwr ntrans = sc->sc_reqlen - resid; 495 1.1 gwr 496 1.1 gwr #ifdef DEBUG 497 1.1 gwr if (si_debug & 2) { 498 1.34 tsutsui printf("%s: resid=0x%x ntrans=0x%x\n", 499 1.34 tsutsui __func__, resid, ntrans); 500 1.1 gwr } 501 1.1 gwr #endif 502 1.1 gwr 503 1.1 gwr /* XXX: Treat (ntrans==0) as a special, non-error case? */ 504 1.1 gwr if (ntrans < MIN_DMA_LEN) { 505 1.4 christos printf("si: fifo count: 0x%x\n", resid); 506 1.1 gwr ncr_sc->sc_state |= NCR_ABORTING; 507 1.1 gwr goto out; 508 1.1 gwr } 509 1.1 gwr if (ntrans > ncr_sc->sc_datalen) 510 1.34 tsutsui panic("%s: excess transfer", __func__); 511 1.1 gwr 512 1.1 gwr /* Adjust data pointer */ 513 1.1 gwr ncr_sc->sc_dataptr += ntrans; 514 1.1 gwr ncr_sc->sc_datalen -= ntrans; 515 1.1 gwr 516 1.1 gwr /* 517 1.1 gwr * After a read, we may need to clean-up 518 1.1 gwr * "Left-over bytes" (yuck!) 519 1.1 gwr */ 520 1.1 gwr if ((dh->dh_flags & SIDH_OUT) == 0) { 521 1.1 gwr /* If odd transfer count, grab last byte by hand. */ 522 1.1 gwr if (ntrans & 1) { 523 1.1 gwr NCR_TRACE("si_dma_stop: leftover 1 at 0x%x\n", 524 1.1 gwr (int) ncr_sc->sc_dataptr - 1); 525 1.1 gwr ncr_sc->sc_dataptr[-1] = 526 1.1 gwr (si->fifo_data & 0xff00) >> 8; 527 1.1 gwr goto out; 528 1.1 gwr } 529 1.37 msaitoh /* UDC might not have transferred the last word. */ 530 1.1 gwr udc_cnt = si_obio_udc_read(si, UDC_ADR_COUNT); 531 1.1 gwr if (((udc_cnt * 2) - resid) == 2) { 532 1.1 gwr NCR_TRACE("si_dma_stop: leftover 2 at 0x%x\n", 533 1.1 gwr (int) ncr_sc->sc_dataptr - 2); 534 1.1 gwr ncr_sc->sc_dataptr[-2] = 535 1.1 gwr (si->fifo_data & 0xff00) >> 8; 536 1.1 gwr ncr_sc->sc_dataptr[-1] = 537 1.1 gwr (si->fifo_data & 0x00ff); 538 1.1 gwr } 539 1.1 gwr } 540 1.1 gwr 541 1.1 gwr out: 542 1.1 gwr /* Reset the UDC. */ 543 1.1 gwr si_obio_udc_write(si, UDC_ADR_COMMAND, UDC_CMD_RESET); 544 1.1 gwr si->fifo_count = 0; 545 1.1 gwr si->si_csr &= ~SI_CSR_SEND; 546 1.1 gwr 547 1.2 gwr /* Reset the FIFO */ 548 1.2 gwr si->si_csr &= ~SI_CSR_FIFO_RES; /* active low */ 549 1.2 gwr si->si_csr |= SI_CSR_FIFO_RES; 550 1.1 gwr 551 1.1 gwr /* Put SBIC back in PIO mode. */ 552 1.2 gwr /* XXX: set tcmd to PHASE_INVALID? */ 553 1.1 gwr *ncr_sc->sci_mode &= ~(SCI_MODE_DMA | SCI_MODE_DMA_IE); 554 1.1 gwr *ncr_sc->sci_icmd = 0; 555 1.1 gwr } 556 1.1 gwr 557