1 1.40 thorpej /* $NetBSD: ahsc.c,v 1.40 2021/08/07 16:18:41 thorpej Exp $ */ 2 1.4 cgd 3 1.1 chopps /* 4 1.1 chopps * Copyright (c) 1982, 1990 The Regents of the University of California. 5 1.1 chopps * All rights reserved. 6 1.1 chopps * 7 1.1 chopps * Redistribution and use in source and binary forms, with or without 8 1.1 chopps * modification, are permitted provided that the following conditions 9 1.1 chopps * are met: 10 1.1 chopps * 1. Redistributions of source code must retain the above copyright 11 1.1 chopps * notice, this list of conditions and the following disclaimer. 12 1.1 chopps * 2. Redistributions in binary form must reproduce the above copyright 13 1.1 chopps * notice, this list of conditions and the following disclaimer in the 14 1.1 chopps * documentation and/or other materials provided with the distribution. 15 1.33 agc * 3. Neither the name of the University nor the names of its contributors 16 1.33 agc * may be used to endorse or promote products derived from this software 17 1.33 agc * without specific prior written permission. 18 1.33 agc * 19 1.33 agc * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 20 1.33 agc * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 1.33 agc * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 1.33 agc * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 23 1.33 agc * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 1.33 agc * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 1.33 agc * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 1.33 agc * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 1.33 agc * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 1.33 agc * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 1.33 agc * SUCH DAMAGE. 30 1.33 agc * 31 1.33 agc * @(#)dma.c 32 1.33 agc */ 33 1.33 agc 34 1.33 agc /* 35 1.33 agc * Copyright (c) 1994 Christian E. Hopps 36 1.33 agc * 37 1.33 agc * Redistribution and use in source and binary forms, with or without 38 1.33 agc * modification, are permitted provided that the following conditions 39 1.33 agc * are met: 40 1.33 agc * 1. Redistributions of source code must retain the above copyright 41 1.33 agc * notice, this list of conditions and the following disclaimer. 42 1.33 agc * 2. Redistributions in binary form must reproduce the above copyright 43 1.33 agc * notice, this list of conditions and the following disclaimer in the 44 1.33 agc * documentation and/or other materials provided with the distribution. 45 1.1 chopps * 3. All advertising materials mentioning features or use of this software 46 1.1 chopps * must display the following acknowledgement: 47 1.1 chopps * This product includes software developed by the University of 48 1.1 chopps * California, Berkeley and its contributors. 49 1.1 chopps * 4. Neither the name of the University nor the names of its contributors 50 1.1 chopps * may be used to endorse or promote products derived from this software 51 1.1 chopps * without specific prior written permission. 52 1.1 chopps * 53 1.1 chopps * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 54 1.1 chopps * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 55 1.1 chopps * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 56 1.1 chopps * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 57 1.1 chopps * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 58 1.1 chopps * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 59 1.1 chopps * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 60 1.1 chopps * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 61 1.1 chopps * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 62 1.1 chopps * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 63 1.1 chopps * SUCH DAMAGE. 64 1.1 chopps * 65 1.1 chopps * @(#)dma.c 66 1.1 chopps */ 67 1.29 aymeric 68 1.29 aymeric #include <sys/cdefs.h> 69 1.40 thorpej __KERNEL_RCSID(0, "$NetBSD: ahsc.c,v 1.40 2021/08/07 16:18:41 thorpej Exp $"); 70 1.29 aymeric 71 1.1 chopps #include <sys/param.h> 72 1.1 chopps #include <sys/systm.h> 73 1.1 chopps #include <sys/kernel.h> 74 1.1 chopps #include <sys/device.h> 75 1.19 bouyer #include <dev/scsipi/scsi_all.h> 76 1.19 bouyer #include <dev/scsipi/scsipi_all.h> 77 1.19 bouyer #include <dev/scsipi/scsiconf.h> 78 1.1 chopps #include <amiga/amiga/custom.h> 79 1.1 chopps #include <amiga/amiga/cc.h> 80 1.22 is #include <amiga/amiga/cfdev.h> 81 1.1 chopps #include <amiga/amiga/device.h> 82 1.8 chopps #include <amiga/amiga/isr.h> 83 1.1 chopps #include <amiga/dev/dmavar.h> 84 1.1 chopps #include <amiga/dev/sbicreg.h> 85 1.1 chopps #include <amiga/dev/sbicvar.h> 86 1.1 chopps #include <amiga/dev/ahscreg.h> 87 1.6 chopps #include <amiga/dev/zbusvar.h> 88 1.26 aymeric 89 1.26 aymeric #include <machine/cpu.h> 90 1.1 chopps 91 1.38 chs void ahscattach(device_t, device_t, void *); 92 1.38 chs int ahscmatch(device_t, cfdata_t, void *); 93 1.1 chopps 94 1.28 aymeric void ahsc_enintr(struct sbic_softc *); 95 1.28 aymeric void ahsc_dmastop(struct sbic_softc *); 96 1.28 aymeric int ahsc_dmanext(struct sbic_softc *); 97 1.28 aymeric int ahsc_dmaintr(void *); 98 1.28 aymeric int ahsc_dmago(struct sbic_softc *, char *, int, int); 99 1.1 chopps 100 1.12 veego #ifdef DEBUG 101 1.28 aymeric void ahsc_dump(void); 102 1.12 veego #endif 103 1.12 veego 104 1.1 chopps #ifdef DEBUG 105 1.1 chopps int ahsc_dmadebug = 0; 106 1.1 chopps #endif 107 1.1 chopps 108 1.38 chs CFATTACH_DECL_NEW(ahsc, sizeof(struct sbic_softc), 109 1.31 thorpej ahscmatch, ahscattach, NULL, NULL); 110 1.11 thorpej 111 1.1 chopps /* 112 1.1 chopps * if we are an A3000 we are here. 113 1.1 chopps */ 114 1.1 chopps int 115 1.38 chs ahscmatch(device_t parent, cfdata_t cf, void *aux) 116 1.1 chopps { 117 1.1 chopps 118 1.38 chs if (is_a3000() && matchname(aux, "ahsc")) 119 1.1 chopps return(1); 120 1.1 chopps return(0); 121 1.1 chopps } 122 1.1 chopps 123 1.1 chopps void 124 1.38 chs ahscattach(device_t parent, device_t self, void *aux) 125 1.1 chopps { 126 1.1 chopps volatile struct sdmac *rp; 127 1.38 chs struct sbic_softc *sc = device_private(self); 128 1.22 is struct cfdev *cdp, *ecdp; 129 1.27 bouyer struct scsipi_adapter *adapt = &sc->sc_adapter; 130 1.27 bouyer struct scsipi_channel *chan = &sc->sc_channel; 131 1.22 is 132 1.38 chs sc->sc_dev = self; 133 1.38 chs 134 1.22 is ecdp = &cfdev[ncfdev]; 135 1.28 aymeric 136 1.22 is for (cdp = cfdev; cdp < ecdp; cdp++) { 137 1.28 aymeric if (cdp->rom.manid == 8738 && 138 1.22 is cdp->rom.prodid == 35) 139 1.22 is break; 140 1.22 is } 141 1.2 chopps 142 1.1 chopps sc->sc_cregs = rp = ztwomap(0xdd0000); 143 1.1 chopps /* 144 1.1 chopps * disable ints and reset bank register 145 1.1 chopps */ 146 1.1 chopps rp->CNTR = CNTR_PDMD; 147 1.37 phx amiga_membarrier(); 148 1.1 chopps rp->DAWR = DAWR_AHSC; 149 1.37 phx amiga_membarrier(); 150 1.10 chopps sc->sc_enintr = ahsc_enintr; 151 1.1 chopps sc->sc_dmago = ahsc_dmago; 152 1.1 chopps sc->sc_dmanext = ahsc_dmanext; 153 1.1 chopps sc->sc_dmastop = ahsc_dmastop; 154 1.1 chopps sc->sc_dmacmd = 0; 155 1.1 chopps 156 1.1 chopps /* 157 1.32 wiz * everything is a valid DMA address 158 1.1 chopps */ 159 1.1 chopps sc->sc_dmamask = 0; 160 1.21 is 161 1.22 is if (cdp < ecdp) { 162 1.22 is sc->sc_sbic.sbic_asr_p = ((vu_char *)rp + 0x43); 163 1.22 is sc->sc_sbic.sbic_value_p = ((vu_char *)rp + 0x47); 164 1.34 wiz printf(": modified for Apollo CPU board\n"); 165 1.22 is } else { 166 1.22 is sc->sc_sbic.sbic_asr_p = ((vu_char *)rp + 0x41); 167 1.22 is sc->sc_sbic.sbic_value_p = ((vu_char *)rp + 0x43); 168 1.22 is printf("\n"); 169 1.22 is } 170 1.21 is 171 1.1 chopps sc->sc_clkfreq = sbic_clock_override ? sbic_clock_override : 143; 172 1.24 thorpej 173 1.27 bouyer /* 174 1.27 bouyer * Fill in the scsipi_adapter. 175 1.27 bouyer */ 176 1.27 bouyer memset(adapt, 0, sizeof(*adapt)); 177 1.38 chs adapt->adapt_dev = self; 178 1.28 aymeric adapt->adapt_nchannels = 1; 179 1.27 bouyer adapt->adapt_openings = 7; 180 1.27 bouyer adapt->adapt_max_periph = 1; 181 1.27 bouyer adapt->adapt_request = sbic_scsipi_request; 182 1.27 bouyer adapt->adapt_minphys = sbic_minphys; 183 1.24 thorpej 184 1.27 bouyer /* 185 1.27 bouyer * Fill in the scsipi_channel. 186 1.27 bouyer */ 187 1.27 bouyer memset(chan, 0, sizeof(*chan)); 188 1.27 bouyer chan->chan_adapter = adapt; 189 1.27 bouyer chan->chan_bustype = &scsi_bustype; 190 1.27 bouyer chan->chan_channel = 0; 191 1.28 aymeric chan->chan_ntargets = 8; 192 1.27 bouyer chan->chan_nluns = 8; 193 1.27 bouyer chan->chan_id = 7; 194 1.9 chopps 195 1.9 chopps sbicinit(sc); 196 1.1 chopps 197 1.8 chopps sc->sc_isr.isr_intr = ahsc_dmaintr; 198 1.8 chopps sc->sc_isr.isr_arg = sc; 199 1.8 chopps sc->sc_isr.isr_ipl = 2; 200 1.8 chopps add_isr (&sc->sc_isr); 201 1.1 chopps 202 1.1 chopps /* 203 1.1 chopps * attach all scsi units on us 204 1.1 chopps */ 205 1.40 thorpej config_found(self, chan, scsiprint, CFARGS_NONE); 206 1.1 chopps } 207 1.1 chopps 208 1.1 chopps void 209 1.28 aymeric ahsc_enintr(struct sbic_softc *dev) 210 1.1 chopps { 211 1.1 chopps volatile struct sdmac *sdp; 212 1.1 chopps 213 1.1 chopps sdp = dev->sc_cregs; 214 1.1 chopps 215 1.10 chopps dev->sc_flags |= SBICF_INTR; 216 1.10 chopps sdp->CNTR = CNTR_PDMD | CNTR_INTEN; 217 1.37 phx amiga_membarrier(); 218 1.1 chopps } 219 1.1 chopps 220 1.1 chopps int 221 1.28 aymeric ahsc_dmago(struct sbic_softc *dev, char *addr, int count, int flags) 222 1.1 chopps { 223 1.1 chopps volatile struct sdmac *sdp; 224 1.1 chopps 225 1.1 chopps sdp = dev->sc_cregs; 226 1.1 chopps /* 227 1.1 chopps * Set up the command word based on flags 228 1.1 chopps */ 229 1.1 chopps dev->sc_dmacmd = CNTR_PDMD | CNTR_INTEN; 230 1.1 chopps if ((flags & DMAGO_READ) == 0) 231 1.1 chopps dev->sc_dmacmd |= CNTR_DDIR; 232 1.1 chopps #ifdef DEBUG 233 1.1 chopps if (ahsc_dmadebug & DDB_IO) 234 1.16 christos printf("ahsc_dmago: cmd %x\n", dev->sc_dmacmd); 235 1.1 chopps #endif 236 1.1 chopps 237 1.1 chopps dev->sc_flags |= SBICF_INTR; 238 1.1 chopps sdp->CNTR = dev->sc_dmacmd; 239 1.37 phx amiga_membarrier(); 240 1.1 chopps sdp->ACR = (u_int) dev->sc_cur->dc_addr; 241 1.37 phx amiga_membarrier(); 242 1.1 chopps sdp->ST_DMA = 1; 243 1.37 phx amiga_membarrier(); 244 1.8 chopps 245 1.1 chopps return(dev->sc_tcnt); 246 1.1 chopps } 247 1.1 chopps 248 1.1 chopps void 249 1.28 aymeric ahsc_dmastop(struct sbic_softc *dev) 250 1.1 chopps { 251 1.1 chopps volatile struct sdmac *sdp; 252 1.1 chopps int s; 253 1.37 phx vu_short istr; 254 1.1 chopps 255 1.1 chopps sdp = dev->sc_cregs; 256 1.1 chopps 257 1.1 chopps #ifdef DEBUG 258 1.1 chopps if (ahsc_dmadebug & DDB_FOLLOW) 259 1.16 christos printf("ahsc_dmastop()\n"); 260 1.1 chopps #endif 261 1.1 chopps if (dev->sc_dmacmd) { 262 1.1 chopps s = splbio(); 263 1.1 chopps if ((dev->sc_dmacmd & (CNTR_TCEN | CNTR_DDIR)) == 0) { 264 1.1 chopps /* 265 1.1 chopps * only FLUSH if terminal count not enabled, 266 1.1 chopps * and reading from peripheral 267 1.1 chopps */ 268 1.1 chopps sdp->FLUSH = 1; 269 1.37 phx amiga_membarrier(); 270 1.37 phx do { 271 1.37 phx istr = sdp->ISTR; 272 1.37 phx amiga_membarrier(); 273 1.37 phx } while ((istr & ISTR_FE_FLG) == 0); 274 1.1 chopps } 275 1.28 aymeric /* 276 1.32 wiz * clear possible interrupt and stop DMA 277 1.1 chopps */ 278 1.1 chopps sdp->CINT = 1; 279 1.37 phx amiga_membarrier(); 280 1.1 chopps sdp->SP_DMA = 1; 281 1.37 phx amiga_membarrier(); 282 1.1 chopps dev->sc_dmacmd = 0; 283 1.1 chopps splx(s); 284 1.1 chopps } 285 1.1 chopps } 286 1.1 chopps 287 1.1 chopps int 288 1.28 aymeric ahsc_dmaintr(void *arg) 289 1.1 chopps { 290 1.12 veego struct sbic_softc *dev = arg; 291 1.1 chopps volatile struct sdmac *sdp; 292 1.8 chopps int stat, found; 293 1.8 chopps 294 1.8 chopps sdp = dev->sc_cregs; 295 1.8 chopps stat = sdp->ISTR; 296 1.37 phx amiga_membarrier(); 297 1.8 chopps 298 1.8 chopps if ((stat & (ISTR_INT_F|ISTR_INT_P)) == 0) 299 1.8 chopps return (0); 300 1.1 chopps 301 1.1 chopps #ifdef DEBUG 302 1.8 chopps if (ahsc_dmadebug & DDB_FOLLOW) 303 1.38 chs printf("%s: dmaintr 0x%x\n", device_xname(dev->sc_dev), stat); 304 1.1 chopps #endif 305 1.1 chopps 306 1.8 chopps /* 307 1.8 chopps * both, SCSI and DMA interrupts arrive here. I chose 308 1.8 chopps * arbitrarily that DMA interrupts should have higher 309 1.8 chopps * precedence than SCSI interrupts. 310 1.8 chopps */ 311 1.8 chopps found = 0; 312 1.8 chopps if (stat & ISTR_E_INT) { 313 1.8 chopps ++found; 314 1.8 chopps 315 1.8 chopps sdp->CINT = 1; /* clear possible interrupt */ 316 1.37 phx amiga_membarrier(); 317 1.8 chopps 318 1.1 chopps /* 319 1.28 aymeric * check for SCSI ints in the same go and 320 1.8 chopps * eventually save an interrupt 321 1.1 chopps */ 322 1.8 chopps } 323 1.1 chopps 324 1.8 chopps if (dev->sc_flags & SBICF_INTR && stat & ISTR_INTS) 325 1.8 chopps found += sbicintr(dev); 326 1.1 chopps return(found); 327 1.1 chopps } 328 1.1 chopps 329 1.1 chopps 330 1.1 chopps int 331 1.28 aymeric ahsc_dmanext(struct sbic_softc *dev) 332 1.1 chopps { 333 1.1 chopps volatile struct sdmac *sdp; 334 1.37 phx vu_short istr; 335 1.1 chopps 336 1.1 chopps sdp = dev->sc_cregs; 337 1.1 chopps 338 1.1 chopps if (dev->sc_cur > dev->sc_last) { 339 1.1 chopps /* shouldn't happen !! */ 340 1.16 christos printf("ahsc_dmanext at end !!!\n"); 341 1.1 chopps ahsc_dmastop(dev); 342 1.1 chopps return(0); 343 1.1 chopps } 344 1.1 chopps if ((dev->sc_dmacmd & (CNTR_TCEN | CNTR_DDIR)) == 0) { 345 1.28 aymeric /* 346 1.1 chopps * only FLUSH if terminal count not enabled, 347 1.1 chopps * and reading from peripheral 348 1.1 chopps */ 349 1.1 chopps sdp->FLUSH = 1; 350 1.37 phx amiga_membarrier(); 351 1.37 phx do { 352 1.37 phx istr = sdp->ISTR; 353 1.37 phx amiga_membarrier(); 354 1.37 phx } while ((istr & ISTR_FE_FLG) == 0); 355 1.27 bouyer } 356 1.28 aymeric /* 357 1.32 wiz * clear possible interrupt and stop DMA 358 1.1 chopps */ 359 1.1 chopps sdp->CINT = 1; /* clear possible interrupt */ 360 1.37 phx amiga_membarrier(); 361 1.32 wiz sdp->SP_DMA = 1; /* stop DMA */ 362 1.37 phx amiga_membarrier(); 363 1.1 chopps sdp->CNTR = dev->sc_dmacmd; 364 1.37 phx amiga_membarrier(); 365 1.1 chopps sdp->ACR = (u_int)dev->sc_cur->dc_addr; 366 1.37 phx amiga_membarrier(); 367 1.1 chopps sdp->ST_DMA = 1; 368 1.37 phx amiga_membarrier(); 369 1.8 chopps 370 1.1 chopps dev->sc_tcnt = dev->sc_cur->dc_count << 1; 371 1.1 chopps return(dev->sc_tcnt); 372 1.1 chopps } 373 1.1 chopps 374 1.1 chopps #ifdef DEBUG 375 1.1 chopps void 376 1.28 aymeric ahsc_dump(void) 377 1.1 chopps { 378 1.20 thorpej extern struct cfdriver ahsc_cd; 379 1.36 cegger struct sbic_softc *sc; 380 1.10 chopps int i; 381 1.1 chopps 382 1.36 cegger for (i = 0; i < ahsc_cd.cd_ndevs; ++i) { 383 1.36 cegger sc = device_lookup_private(&ahsc_cd, i); 384 1.36 cegger if (sc != NULL) 385 1.36 cegger sbic_dump(sc); 386 1.36 cegger } 387 1.1 chopps } 388 1.1 chopps #endif 389