1 /* $NetBSD: gtsc.c,v 1.41 2012/10/27 17:17:29 chs Exp $ */ 2 3 /* 4 * Copyright (c) 1982, 1990 The Regents of the University of California. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. Neither the name of the University nor the names of its contributors 16 * may be used to endorse or promote products derived from this software 17 * without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 * 31 * @(#)dma.c 32 */ 33 34 /* 35 * Copyright (c) 1994 Christian E. Hopps 36 * 37 * Redistribution and use in source and binary forms, with or without 38 * modification, are permitted provided that the following conditions 39 * are met: 40 * 1. Redistributions of source code must retain the above copyright 41 * notice, this list of conditions and the following disclaimer. 42 * 2. Redistributions in binary form must reproduce the above copyright 43 * notice, this list of conditions and the following disclaimer in the 44 * documentation and/or other materials provided with the distribution. 45 * 3. All advertising materials mentioning features or use of this software 46 * must display the following acknowledgement: 47 * This product includes software developed by the University of 48 * California, Berkeley and its contributors. 49 * 4. Neither the name of the University nor the names of its contributors 50 * may be used to endorse or promote products derived from this software 51 * without specific prior written permission. 52 * 53 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 54 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 55 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 56 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 57 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 58 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 59 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 60 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 61 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 62 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 63 * SUCH DAMAGE. 64 * 65 * @(#)dma.c 66 */ 67 68 #include <sys/cdefs.h> 69 __KERNEL_RCSID(0, "$NetBSD: gtsc.c,v 1.41 2012/10/27 17:17:29 chs Exp $"); 70 71 #include <sys/param.h> 72 #include <sys/systm.h> 73 #include <sys/kernel.h> 74 #include <sys/device.h> 75 #include <sys/intr.h> 76 #include <machine/cpu.h> 77 #include <dev/scsipi/scsi_all.h> 78 #include <dev/scsipi/scsipi_all.h> 79 #include <dev/scsipi/scsiconf.h> 80 #include <amiga/amiga/custom.h> 81 #include <amiga/amiga/cc.h> 82 #include <amiga/amiga/device.h> 83 #include <amiga/amiga/isr.h> 84 #include <amiga/dev/dmavar.h> 85 #include <amiga/dev/sbicreg.h> 86 #include <amiga/dev/sbicvar.h> 87 #include <amiga/dev/gtscreg.h> 88 #include <amiga/dev/zbusvar.h> 89 #include <amiga/dev/gvpbusvar.h> 90 91 void gtscattach(device_t, device_t, void *); 92 int gtscmatch(device_t, cfdata_t, void *); 93 94 void gtsc_enintr(struct sbic_softc *); 95 void gtsc_dmastop(struct sbic_softc *); 96 int gtsc_dmanext(struct sbic_softc *); 97 int gtsc_dmaintr(void *); 98 int gtsc_dmago(struct sbic_softc *, char *, int, int); 99 100 #ifdef DEBUG 101 void gtsc_dump(void); 102 #endif 103 104 int gtsc_maxdma = 0; /* Maximum size per DMA transfer */ 105 int gtsc_dmamask = 0; 106 int gtsc_dmabounce = 0; 107 int gtsc_clock_override = 0; 108 109 #ifdef DEBUG 110 int gtsc_debug = 0; 111 #endif 112 113 CFATTACH_DECL_NEW(gtsc, sizeof(struct sbic_softc), 114 gtscmatch, gtscattach, NULL, NULL); 115 116 int 117 gtscmatch(device_t parent, cfdata_t cf, void *aux) 118 { 119 struct gvpbus_args *gap; 120 121 gap = aux; 122 if (gap->flags & GVP_SCSI) 123 return(1); 124 return(0); 125 } 126 127 /* 128 * attach all devices on our board. 129 */ 130 void 131 gtscattach(device_t parent, device_t self, void *aux) 132 { 133 volatile struct sdmac *rp; 134 struct gvpbus_args *gap; 135 struct sbic_softc *sc = device_private(self); 136 struct scsipi_adapter *adapt = &sc->sc_adapter; 137 struct scsipi_channel *chan = &sc->sc_channel; 138 139 gap = aux; 140 sc->sc_dev = self; 141 sc->sc_cregs = rp = gap->zargs.va; 142 143 /* 144 * disable ints and reset bank register 145 */ 146 rp->CNTR = 0; 147 amiga_membarrier(); 148 if ((gap->flags & GVP_NOBANK) == 0) { 149 rp->bank = 0; 150 amiga_membarrier(); 151 } 152 153 sc->sc_dmago = gtsc_dmago; 154 sc->sc_enintr = gtsc_enintr; 155 sc->sc_dmanext = gtsc_dmanext; 156 sc->sc_dmastop = gtsc_dmastop; 157 sc->sc_dmacmd = 0; 158 159 sc->sc_flags |= SBICF_BADDMA; 160 if (gtsc_dmamask) 161 sc->sc_dmamask = gtsc_dmamask; 162 else if (gap->flags & GVP_24BITDMA) 163 sc->sc_dmamask = ~0x00ffffff; 164 else if (gap->flags & GVP_25BITDMA) 165 sc->sc_dmamask = ~0x01ffffff; 166 else 167 sc->sc_dmamask = ~0x07ffffff; 168 printf(": dmamask 0x%lx", ~sc->sc_dmamask); 169 170 if ((gap->flags & GVP_NOBANK) == 0) 171 sc->gtsc_bankmask = (~sc->sc_dmamask >> 18) & 0x01c0; 172 173 #if 0 174 /* 175 * if the user requests a bounce buffer or 176 * the users kva space is not ztwo and DMA needs it 177 * try and allocate a bounce buffer. If we allocate 178 * one and it is in ztwo space leave maxdma to user 179 * setting or default to MAXPHYS else the address must 180 * be on the chip bus so decrease it to either the users 181 * setting or 1024 bytes. 182 * 183 * XXX this needs to change if we move to multiple memory segments. 184 */ 185 if (gtsc_dmabounce || kvtop(sc) & sc->sc_dmamask) { 186 sc->sc_dmabuffer = (char *) alloc_z2mem(MAXPHYS * 8); /* XXX */ 187 if (isztwomem(sc->sc_dmabuffer)) 188 printf(" bounce pa 0x%x", kvtop(sc->sc_dmabuffer)); 189 else if (gtsc_maxdma == 0) { 190 gtsc_maxdma = 1024; 191 printf(" bounce pa 0x%x", 192 PREP_DMA_MEM(sc->sc_dmabuffer)); 193 } 194 } 195 #endif 196 if (gtsc_maxdma == 0) 197 gtsc_maxdma = MAXPHYS; 198 199 printf(" flags %x", gap->flags); 200 printf(" maxdma %d\n", gtsc_maxdma); 201 202 sc->sc_sbic.sbic_asr_p = (volatile unsigned char *)rp + 0x61; 203 sc->sc_sbic.sbic_value_p = (volatile unsigned char *)rp + 0x63; 204 amiga_membarrier(); 205 206 sc->sc_clkfreq = gtsc_clock_override ? gtsc_clock_override : 207 ((gap->flags & GVP_14MHZ) ? 143 : 72); 208 printf("sc_clkfreg: %ld.%ld MHz\n", sc->sc_clkfreq / 10, sc->sc_clkfreq % 10); 209 210 /* 211 * Fill in the scsipi_adapter. 212 */ 213 memset(adapt, 0, sizeof(*adapt)); 214 adapt->adapt_dev = self; 215 adapt->adapt_nchannels = 1; 216 adapt->adapt_openings = 7; 217 adapt->adapt_max_periph = 1; 218 adapt->adapt_request = sbic_scsipi_request; 219 adapt->adapt_minphys = sbic_minphys; 220 221 /* 222 * Fill in the scsipi_channel. 223 */ 224 memset(chan, 0, sizeof(*chan)); 225 chan->chan_adapter = adapt; 226 chan->chan_bustype = &scsi_bustype; 227 chan->chan_channel = 0; 228 chan->chan_ntargets = 8; 229 chan->chan_nluns = 8; 230 chan->chan_id = 7; 231 232 sbicinit(sc); 233 234 sc->sc_isr.isr_intr = gtsc_dmaintr; 235 sc->sc_isr.isr_arg = sc; 236 sc->sc_isr.isr_ipl = 2; 237 add_isr(&sc->sc_isr); 238 239 /* 240 * attach all scsi units on us 241 */ 242 config_found(self, chan, scsiprint); 243 } 244 245 void 246 gtsc_enintr(struct sbic_softc *dev) 247 { 248 volatile struct sdmac *sdp; 249 250 sdp = dev->sc_cregs; 251 252 dev->sc_flags |= SBICF_INTR; 253 sdp->CNTR = GVP_CNTR_INTEN; 254 amiga_membarrier(); 255 } 256 257 int 258 gtsc_dmago(struct sbic_softc *dev, char *addr, int count, int flags) 259 { 260 volatile struct sdmac *sdp; 261 262 sdp = dev->sc_cregs; 263 /* 264 * Set up the command word based on flags 265 */ 266 dev->sc_dmacmd = GVP_CNTR_INTEN; 267 if ((flags & DMAGO_READ) == 0) 268 dev->sc_dmacmd |= GVP_CNTR_DDIR; 269 270 #ifdef DEBUG 271 if (gtsc_debug & DDB_IO) 272 printf("gtsc_dmago: cmd %x\n", dev->sc_dmacmd); 273 #endif 274 dev->sc_flags |= SBICF_INTR; 275 sdp->CNTR = dev->sc_dmacmd; 276 amiga_membarrier(); 277 if((u_int)dev->sc_cur->dc_addr & dev->sc_dmamask) { 278 #if 1 279 printf("gtsc_dmago: pa %p->%lx dmacmd %x", 280 dev->sc_cur->dc_addr, 281 (u_int)dev->sc_cur->dc_addr & ~dev->sc_dmamask, 282 dev->sc_dmacmd); 283 #endif 284 sdp->ACR = 0x00f80000; /***********************************/ 285 } else 286 sdp->ACR = (u_int) dev->sc_cur->dc_addr; 287 amiga_membarrier(); 288 if (dev->gtsc_bankmask) { 289 sdp->bank = 290 dev->gtsc_bankmask & (((u_int)dev->sc_cur->dc_addr) >> 18); 291 amiga_membarrier(); 292 } 293 sdp->ST_DMA = 1; 294 amiga_membarrier(); 295 296 /* 297 * restrict transfer count to maximum 298 */ 299 if (dev->sc_tcnt > gtsc_maxdma) 300 dev->sc_tcnt = gtsc_maxdma; 301 #if 1 302 if((u_int)dev->sc_cur->dc_addr & dev->sc_dmamask) 303 printf(" tcnt %ld\n", dev->sc_tcnt); 304 #endif 305 return(dev->sc_tcnt); 306 } 307 308 void 309 gtsc_dmastop(struct sbic_softc *dev) 310 { 311 volatile struct sdmac *sdp; 312 int s; 313 314 sdp = dev->sc_cregs; 315 316 #ifdef DEBUG 317 if (gtsc_debug & DDB_FOLLOW) 318 printf("gtsc_dmastop()\n"); 319 #endif 320 if (dev->sc_dmacmd) { 321 /* 322 * clear possible interrupt and stop DMA 323 */ 324 s = splbio(); 325 sdp->CNTR &= ~GVP_CNTR_INT_P; 326 amiga_membarrier(); 327 sdp->SP_DMA = 1; 328 amiga_membarrier(); 329 dev->sc_dmacmd = 0; 330 splx(s); 331 } 332 } 333 334 int 335 gtsc_dmaintr(void *arg) 336 { 337 struct sbic_softc *dev = arg; 338 volatile struct sdmac *sdp; 339 int stat; 340 341 sdp = dev->sc_cregs; 342 stat = sdp->CNTR; 343 amiga_membarrier(); 344 if ((stat & GVP_CNTR_INT_P) == 0) 345 return (0); 346 #ifdef DEBUG 347 if (gtsc_debug & DDB_FOLLOW) 348 printf("%s: dmaintr 0x%x\n", device_xname(dev->sc_dev), stat); 349 #endif 350 if (dev->sc_flags & SBICF_INTR) 351 if (sbicintr(dev)) 352 return (1); 353 return(0); 354 } 355 356 357 int 358 gtsc_dmanext(struct sbic_softc *dev) 359 { 360 volatile struct sdmac *sdp; 361 362 sdp = dev->sc_cregs; 363 364 if (dev->sc_cur > dev->sc_last) { 365 /* shouldn't happen !! */ 366 printf("gtsc_dmanext at end !!!\n"); 367 gtsc_dmastop(dev); 368 return(0); 369 } 370 /* 371 * clear possible interrupt and stop DMA 372 */ 373 sdp->CNTR &= ~GVP_CNTR_INT_P; 374 amiga_membarrier(); 375 sdp->SP_DMA = 1; 376 amiga_membarrier(); 377 378 sdp->CNTR = dev->sc_dmacmd; 379 amiga_membarrier(); 380 sdp->ACR = (u_int) dev->sc_cur->dc_addr; 381 amiga_membarrier(); 382 if (dev->gtsc_bankmask) { 383 sdp->bank = 384 dev->gtsc_bankmask & ((u_int)dev->sc_cur->dc_addr >> 18); 385 amiga_membarrier(); 386 } 387 sdp->ST_DMA = 1; 388 amiga_membarrier(); 389 390 dev->sc_tcnt = dev->sc_cur->dc_count << 1; 391 if (dev->sc_tcnt > gtsc_maxdma) 392 dev->sc_tcnt = gtsc_maxdma; 393 #ifdef DEBUG 394 if (gtsc_debug & DDB_FOLLOW) 395 printf("gtsc_dmanext ret: %ld\n", dev->sc_tcnt); 396 #endif 397 return(dev->sc_tcnt); 398 } 399 400 #ifdef DEBUG 401 void 402 gtsc_dump(void) 403 { 404 extern struct cfdriver gtsc_cd; 405 struct sbic_softc *sc; 406 int i; 407 408 for (i = 0; i < gtsc_cd.cd_ndevs; ++i) { 409 sc = device_lookup_private(>sc_cd, i); 410 if (sc != NULL) 411 sbic_dump(sc); 412 } 413 } 414 #endif 415