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