1 1.45 thorpej /* $NetBSD: atzsc.c,v 1.45 2021/08/07 16:18:41 thorpej Exp $ */ 2 1.7 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.35 agc * 3. Neither the name of the University nor the names of its contributors 16 1.35 agc * may be used to endorse or promote products derived from this software 17 1.35 agc * without specific prior written permission. 18 1.35 agc * 19 1.35 agc * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 20 1.35 agc * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 1.35 agc * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 1.35 agc * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 23 1.35 agc * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 1.35 agc * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 1.35 agc * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 1.35 agc * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 1.35 agc * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 1.35 agc * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 1.35 agc * SUCH DAMAGE. 30 1.35 agc * 31 1.35 agc * @(#)dma.c 32 1.35 agc */ 33 1.35 agc 34 1.35 agc /* 35 1.35 agc * Copyright (c) 1994 Christian E. Hopps 36 1.35 agc * 37 1.35 agc * Redistribution and use in source and binary forms, with or without 38 1.35 agc * modification, are permitted provided that the following conditions 39 1.35 agc * are met: 40 1.35 agc * 1. Redistributions of source code must retain the above copyright 41 1.35 agc * notice, this list of conditions and the following disclaimer. 42 1.35 agc * 2. Redistributions in binary form must reproduce the above copyright 43 1.35 agc * notice, this list of conditions and the following disclaimer in the 44 1.35 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.31 aymeric 68 1.31 aymeric #include <sys/cdefs.h> 69 1.45 thorpej __KERNEL_RCSID(0, "$NetBSD: atzsc.c,v 1.45 2021/08/07 16:18:41 thorpej Exp $"); 70 1.31 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.37 ad #include <sys/intr.h> 76 1.42 phx #include <machine/cpu.h> 77 1.23 bouyer #include <dev/scsipi/scsi_all.h> 78 1.23 bouyer #include <dev/scsipi/scsipi_all.h> 79 1.23 bouyer #include <dev/scsipi/scsiconf.h> 80 1.1 chopps #include <amiga/amiga/custom.h> 81 1.1 chopps #include <amiga/amiga/cc.h> 82 1.1 chopps #include <amiga/amiga/device.h> 83 1.11 chopps #include <amiga/amiga/isr.h> 84 1.1 chopps #include <amiga/dev/dmavar.h> 85 1.1 chopps #include <amiga/dev/sbicreg.h> 86 1.1 chopps #include <amiga/dev/sbicvar.h> 87 1.1 chopps #include <amiga/dev/atzscreg.h> 88 1.9 chopps #include <amiga/dev/zbusvar.h> 89 1.1 chopps 90 1.43 chs void atzscattach(device_t, device_t, void *); 91 1.43 chs int atzscmatch(device_t, cfdata_t, void *); 92 1.1 chopps 93 1.30 aymeric void atzsc_enintr(struct sbic_softc *); 94 1.30 aymeric void atzsc_dmastop(struct sbic_softc *); 95 1.30 aymeric int atzsc_dmanext(struct sbic_softc *); 96 1.30 aymeric int atzsc_dmaintr(void *); 97 1.30 aymeric int atzsc_dmago(struct sbic_softc *, char *, int, int); 98 1.1 chopps 99 1.16 veego #ifdef DEBUG 100 1.30 aymeric void atzsc_dump(void); 101 1.16 veego #endif 102 1.16 veego 103 1.1 chopps #ifdef DEBUG 104 1.1 chopps int atzsc_dmadebug = 0; 105 1.1 chopps #endif 106 1.1 chopps 107 1.43 chs CFATTACH_DECL_NEW(atzsc, sizeof(struct sbic_softc), 108 1.33 thorpej atzscmatch, atzscattach, NULL, NULL); 109 1.14 thorpej 110 1.1 chopps /* 111 1.40 phx * if we are a A2091 SCSI 112 1.1 chopps */ 113 1.1 chopps int 114 1.43 chs atzscmatch(device_t parent, cfdata_t cf, void *aux) 115 1.1 chopps { 116 1.9 chopps struct zbus_args *zap; 117 1.1 chopps 118 1.43 chs zap = aux; 119 1.1 chopps 120 1.1 chopps /* 121 1.1 chopps * Check manufacturer and product id. 122 1.1 chopps * I was informed that older boards can be 2 also. 123 1.1 chopps */ 124 1.1 chopps if (zap->manid == 514 && (zap->prodid == 3 || zap->prodid == 2)) 125 1.1 chopps return(1); 126 1.1 chopps else 127 1.1 chopps return(0); 128 1.1 chopps } 129 1.1 chopps 130 1.1 chopps void 131 1.43 chs atzscattach(device_t parent, device_t self, void *aux) 132 1.1 chopps { 133 1.1 chopps volatile struct sdmac *rp; 134 1.43 chs struct sbic_softc *sc = device_private(self); 135 1.9 chopps struct zbus_args *zap; 136 1.29 bouyer struct scsipi_adapter *adapt = &sc->sc_adapter; 137 1.29 bouyer struct scsipi_channel *chan = &sc->sc_channel; 138 1.1 chopps 139 1.43 chs zap = aux; 140 1.30 aymeric 141 1.43 chs sc->sc_dev = self; 142 1.1 chopps sc->sc_cregs = rp = zap->va; 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.40 phx amiga_membarrier(); 148 1.1 chopps rp->DAWR = DAWR_ATZSC; 149 1.40 phx amiga_membarrier(); 150 1.13 chopps sc->sc_enintr = atzsc_enintr; 151 1.1 chopps sc->sc_dmago = atzsc_dmago; 152 1.1 chopps sc->sc_dmanext = atzsc_dmanext; 153 1.1 chopps sc->sc_dmastop = atzsc_dmastop; 154 1.2 chopps sc->sc_dmacmd = 0; 155 1.1 chopps 156 1.1 chopps /* 157 1.2 chopps * only 24 bit mem. 158 1.1 chopps */ 159 1.5 chopps sc->sc_flags |= SBICF_BADDMA; 160 1.2 chopps sc->sc_dmamask = ~0x00ffffff; 161 1.12 chopps #if 0 162 1.11 chopps /* 163 1.30 aymeric * If the users kva space is not ztwo try and allocate a bounce buffer. 164 1.6 chopps * XXX this needs to change if we move to multiple memory segments. 165 1.6 chopps */ 166 1.6 chopps if (kvtop(sc) & sc->sc_dmamask) { 167 1.12 chopps sc->sc_dmabuffer = (char *)alloc_z2mem(MAXPHYS * 8); /* XXX */ 168 1.6 chopps if (isztwomem(sc->sc_dmabuffer)) 169 1.20 christos printf(" bounce pa 0x%x", kvtop(sc->sc_dmabuffer)); 170 1.6 chopps else if (sc->sc_dmabuffer) 171 1.20 christos printf(" bounce pa 0x%x", 172 1.6 chopps PREP_DMA_MEM(sc->sc_dmabuffer)); 173 1.6 chopps } 174 1.12 chopps #endif 175 1.25 is sc->sc_sbic.sbic_asr_p = (volatile unsigned char *)rp + 0x91; 176 1.25 is sc->sc_sbic.sbic_value_p = (volatile unsigned char *)rp + 0x93; 177 1.25 is 178 1.1 chopps sc->sc_clkfreq = sbic_clock_override ? sbic_clock_override : 77; 179 1.30 aymeric 180 1.20 christos printf(": dmamask 0x%lx\n", ~sc->sc_dmamask); 181 1.2 chopps 182 1.29 bouyer /* 183 1.29 bouyer * Fill in the scsipi_adapter. 184 1.29 bouyer */ 185 1.29 bouyer memset(adapt, 0, sizeof(*adapt)); 186 1.43 chs adapt->adapt_dev = self; 187 1.29 bouyer adapt->adapt_nchannels = 1; 188 1.29 bouyer adapt->adapt_openings = 7; 189 1.29 bouyer adapt->adapt_max_periph = 1; 190 1.29 bouyer adapt->adapt_request = sbic_scsipi_request; 191 1.29 bouyer adapt->adapt_minphys = sbic_minphys; 192 1.27 thorpej 193 1.29 bouyer /* 194 1.29 bouyer * Fill in the scsipi_channel. 195 1.29 bouyer */ 196 1.29 bouyer memset(chan, 0, sizeof(*chan)); 197 1.29 bouyer chan->chan_adapter = adapt; 198 1.29 bouyer chan->chan_bustype = &scsi_bustype; 199 1.29 bouyer chan->chan_channel = 0; 200 1.29 bouyer chan->chan_ntargets = 8; 201 1.29 bouyer chan->chan_nluns = 8; 202 1.29 bouyer chan->chan_id = 7; 203 1.12 chopps 204 1.12 chopps sbicinit(sc); 205 1.1 chopps 206 1.11 chopps sc->sc_isr.isr_intr = atzsc_dmaintr; 207 1.11 chopps sc->sc_isr.isr_arg = sc; 208 1.11 chopps sc->sc_isr.isr_ipl = 2; 209 1.11 chopps add_isr (&sc->sc_isr); 210 1.1 chopps 211 1.1 chopps /* 212 1.1 chopps * attach all scsi units on us 213 1.1 chopps */ 214 1.45 thorpej config_found(self, chan, scsiprint, CFARGS_NONE); 215 1.1 chopps } 216 1.1 chopps 217 1.1 chopps void 218 1.30 aymeric atzsc_enintr(struct sbic_softc *dev) 219 1.1 chopps { 220 1.1 chopps volatile struct sdmac *sdp; 221 1.1 chopps 222 1.1 chopps sdp = dev->sc_cregs; 223 1.1 chopps 224 1.13 chopps dev->sc_flags |= SBICF_INTR; 225 1.13 chopps sdp->CNTR = CNTR_PDMD | CNTR_INTEN; 226 1.40 phx amiga_membarrier(); 227 1.1 chopps } 228 1.1 chopps 229 1.1 chopps int 230 1.30 aymeric atzsc_dmago(struct sbic_softc *dev, char *addr, int count, int flags) 231 1.1 chopps { 232 1.1 chopps volatile struct sdmac *sdp; 233 1.1 chopps 234 1.1 chopps sdp = dev->sc_cregs; 235 1.1 chopps /* 236 1.1 chopps * Set up the command word based on flags 237 1.1 chopps */ 238 1.1 chopps dev->sc_dmacmd = CNTR_PDMD | CNTR_INTEN; 239 1.1 chopps if ((flags & DMAGO_READ) == 0) 240 1.1 chopps dev->sc_dmacmd |= CNTR_DDIR; 241 1.1 chopps #ifdef DEBUG 242 1.1 chopps if (atzsc_dmadebug & DDB_IO) 243 1.20 christos printf("atzsc_dmago: cmd %x\n", dev->sc_dmacmd); 244 1.1 chopps #endif 245 1.1 chopps 246 1.1 chopps dev->sc_flags |= SBICF_INTR; 247 1.1 chopps sdp->CNTR = dev->sc_dmacmd; 248 1.40 phx amiga_membarrier(); 249 1.1 chopps sdp->ACR = (u_int) dev->sc_cur->dc_addr; 250 1.40 phx amiga_membarrier(); 251 1.1 chopps sdp->ST_DMA = 1; 252 1.40 phx amiga_membarrier(); 253 1.11 chopps 254 1.1 chopps return(dev->sc_tcnt); 255 1.1 chopps } 256 1.1 chopps 257 1.1 chopps void 258 1.30 aymeric atzsc_dmastop(struct sbic_softc *dev) 259 1.1 chopps { 260 1.1 chopps volatile struct sdmac *sdp; 261 1.1 chopps int s; 262 1.40 phx vu_short istr; 263 1.1 chopps 264 1.1 chopps sdp = dev->sc_cregs; 265 1.1 chopps 266 1.1 chopps #ifdef DEBUG 267 1.1 chopps if (atzsc_dmadebug & DDB_FOLLOW) 268 1.20 christos printf("atzsc_dmastop()\n"); 269 1.1 chopps #endif 270 1.1 chopps if (dev->sc_dmacmd) { 271 1.1 chopps s = splbio(); 272 1.1 chopps if ((dev->sc_dmacmd & (CNTR_TCEN | CNTR_DDIR)) == 0) { 273 1.1 chopps /* 274 1.1 chopps * only FLUSH if terminal count not enabled, 275 1.1 chopps * and reading from peripheral 276 1.1 chopps */ 277 1.1 chopps sdp->FLUSH = 1; 278 1.40 phx amiga_membarrier(); 279 1.40 phx do { 280 1.40 phx istr = sdp->ISTR; 281 1.40 phx amiga_membarrier(); 282 1.40 phx } while ((istr & ISTR_FE_FLG) == 0); 283 1.1 chopps } 284 1.30 aymeric /* 285 1.34 wiz * clear possible interrupt and stop DMA 286 1.1 chopps */ 287 1.1 chopps sdp->CINT = 1; 288 1.40 phx amiga_membarrier(); 289 1.1 chopps sdp->SP_DMA = 1; 290 1.40 phx amiga_membarrier(); 291 1.1 chopps dev->sc_dmacmd = 0; 292 1.1 chopps splx(s); 293 1.1 chopps } 294 1.1 chopps } 295 1.1 chopps 296 1.1 chopps int 297 1.30 aymeric atzsc_dmaintr(void *arg) 298 1.1 chopps { 299 1.16 veego struct sbic_softc *dev = arg; 300 1.1 chopps volatile struct sdmac *sdp; 301 1.11 chopps int stat, found; 302 1.11 chopps 303 1.11 chopps sdp = dev->sc_cregs; 304 1.11 chopps stat = sdp->ISTR; 305 1.11 chopps 306 1.11 chopps if ((stat & (ISTR_INT_F|ISTR_INT_P)) == 0) 307 1.11 chopps return (0); 308 1.1 chopps 309 1.1 chopps #ifdef DEBUG 310 1.11 chopps if (atzsc_dmadebug & DDB_FOLLOW) 311 1.43 chs printf("%s: dmaintr 0x%x\n", device_xname(dev->sc_dev), stat); 312 1.1 chopps #endif 313 1.1 chopps 314 1.11 chopps /* 315 1.11 chopps * both, SCSI and DMA interrupts arrive here. I chose 316 1.11 chopps * arbitrarily that DMA interrupts should have higher 317 1.11 chopps * precedence than SCSI interrupts. 318 1.11 chopps */ 319 1.11 chopps found = 0; 320 1.11 chopps if (stat & ISTR_E_INT) { 321 1.11 chopps found++; 322 1.11 chopps 323 1.11 chopps sdp->CINT = 1; /* clear possible interrupt */ 324 1.40 phx amiga_membarrier(); 325 1.30 aymeric 326 1.1 chopps /* 327 1.30 aymeric * check for SCSI ints in the same go and 328 1.11 chopps * eventually save an interrupt 329 1.1 chopps */ 330 1.11 chopps } 331 1.1 chopps 332 1.11 chopps if (dev->sc_flags & SBICF_INTR && stat & ISTR_INTS) 333 1.11 chopps found += sbicintr(dev); 334 1.1 chopps return(found); 335 1.1 chopps } 336 1.1 chopps 337 1.1 chopps 338 1.1 chopps int 339 1.30 aymeric atzsc_dmanext(struct sbic_softc *dev) 340 1.1 chopps { 341 1.1 chopps volatile struct sdmac *sdp; 342 1.40 phx vu_short istr; 343 1.1 chopps 344 1.1 chopps sdp = dev->sc_cregs; 345 1.1 chopps 346 1.1 chopps if (dev->sc_cur > dev->sc_last) { 347 1.1 chopps /* shouldn't happen !! */ 348 1.20 christos printf("atzsc_dmanext at end !!!\n"); 349 1.1 chopps atzsc_dmastop(dev); 350 1.1 chopps return(0); 351 1.1 chopps } 352 1.1 chopps if ((dev->sc_dmacmd & (CNTR_TCEN | CNTR_DDIR)) == 0) { 353 1.30 aymeric /* 354 1.1 chopps * only FLUSH if terminal count not enabled, 355 1.1 chopps * and reading from peripheral 356 1.1 chopps */ 357 1.1 chopps sdp->FLUSH = 1; 358 1.40 phx amiga_membarrier(); 359 1.40 phx do { 360 1.40 phx istr = sdp->ISTR; 361 1.40 phx amiga_membarrier(); 362 1.40 phx } while ((istr & ISTR_FE_FLG) == 0); 363 1.29 bouyer } 364 1.30 aymeric /* 365 1.34 wiz * clear possible interrupt and stop DMA 366 1.1 chopps */ 367 1.1 chopps sdp->CINT = 1; /* clear possible interrupt */ 368 1.40 phx amiga_membarrier(); 369 1.34 wiz sdp->SP_DMA = 1; /* stop DMA */ 370 1.40 phx amiga_membarrier(); 371 1.1 chopps sdp->CNTR = dev->sc_dmacmd; 372 1.40 phx amiga_membarrier(); 373 1.1 chopps sdp->ACR = (u_int)dev->sc_cur->dc_addr; 374 1.40 phx amiga_membarrier(); 375 1.1 chopps sdp->ST_DMA = 1; 376 1.40 phx amiga_membarrier(); 377 1.11 chopps 378 1.1 chopps dev->sc_tcnt = dev->sc_cur->dc_count << 1; 379 1.1 chopps return(dev->sc_tcnt); 380 1.1 chopps } 381 1.1 chopps 382 1.1 chopps #ifdef DEBUG 383 1.1 chopps void 384 1.30 aymeric atzsc_dump(void) 385 1.1 chopps { 386 1.24 thorpej extern struct cfdriver atzsc_cd; 387 1.38 cegger struct sbic_softc *sc; 388 1.13 chopps int i; 389 1.1 chopps 390 1.38 cegger for (i = 0; i < atzsc_cd.cd_ndevs; ++i) { 391 1.39 phx sc = device_lookup_private(&atzsc_cd, i); 392 1.38 cegger if (sc != NULL) 393 1.38 cegger sbic_dump(sc); 394 1.38 cegger } 395 1.1 chopps } 396 1.1 chopps #endif 397