1 /* $NetBSD: bzsc.c,v 1.13 1996/10/13 03:06:50 christos Exp $ */ 2 3 /* 4 * Copyright (c) 1995 Daniel Widenfalk 5 * Copyright (c) 1994 Christian E. Hopps 6 * Copyright (c) 1982, 1990 The Regents of the University of California. 7 * All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 3. All advertising materials mentioning features or use of this software 18 * must display the following acknowledgement: 19 * This product includes software developed by the University of 20 * California, Berkeley and its contributors. 21 * 4. Neither the name of the University nor the names of its contributors 22 * may be used to endorse or promote products derived from this software 23 * without specific prior written permission. 24 * 25 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 28 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 29 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 30 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 31 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 34 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 35 * SUCH DAMAGE. 36 * 37 * @(#)dma.c 38 */ 39 40 #include <sys/param.h> 41 #include <sys/systm.h> 42 #include <sys/kernel.h> 43 #include <sys/device.h> 44 #include <scsi/scsi_all.h> 45 #include <scsi/scsiconf.h> 46 #include <vm/vm.h> 47 #include <vm/vm_kern.h> 48 #include <vm/vm_page.h> 49 #include <machine/pmap.h> 50 #include <amiga/amiga/custom.h> 51 #include <amiga/amiga/cc.h> 52 #include <amiga/amiga/device.h> 53 #include <amiga/amiga/isr.h> 54 #include <amiga/dev/sfasreg.h> 55 #include <amiga/dev/sfasvar.h> 56 #include <amiga/dev/zbusvar.h> 57 #include <amiga/dev/bzscreg.h> 58 #include <amiga/dev/bzscvar.h> 59 60 void bzscattach __P((struct device *, struct device *, void *)); 61 int bzscmatch __P((struct device *, void *, void *)); 62 63 struct scsi_adapter bzsc_scsiswitch = { 64 sfas_scsicmd, 65 sfas_minphys, 66 0, /* no lun support */ 67 0, /* no lun support */ 68 }; 69 70 struct scsi_device bzsc_scsidev = { 71 NULL, /* use default error handler */ 72 NULL, /* do not have a start functio */ 73 NULL, /* have no async handler */ 74 NULL, /* Use default done routine */ 75 }; 76 77 struct cfattach bzsc_ca = { 78 sizeof(struct bzsc_softc), bzscmatch, bzscattach 79 }; 80 81 struct cfdriver bzsc_cd = { 82 NULL, "bzsc", DV_DULL, NULL, 0 83 }; 84 85 int bzsc_intr __P((void *)); 86 void bzsc_set_dma_adr __P((struct sfas_softc *sc, vm_offset_t ptr, int mode)); 87 void bzsc_set_dma_tc __P((struct sfas_softc *sc, unsigned int len)); 88 int bzsc_setup_dma __P((struct sfas_softc *sc, vm_offset_t ptr, int len, 89 int mode)); 90 int bzsc_build_dma_chain __P((struct sfas_softc *sc, 91 struct sfas_dma_chain *chain, void *p, int l)); 92 int bzsc_need_bump __P((struct sfas_softc *sc, vm_offset_t ptr, int len)); 93 void bzsc_led_dummy __P((struct sfas_softc *sc, int mode)); 94 95 /* 96 * if we are an Advanced Systems & Software FastlaneZ3 97 */ 98 int 99 bzscmatch(pdp, match, auxp) 100 struct device *pdp; 101 void *match, *auxp; 102 { 103 struct zbus_args *zap; 104 vu_char *ta; 105 106 if (!is_a1200()) 107 return(0); 108 109 zap = auxp; 110 if (zap->manid != 0x2140 || zap->prodid != 11) 111 return(0); 112 113 ta = (vu_char *)(((char *)zap->va)+0x10010); 114 if (badbaddr((caddr_t)ta)) 115 return(0); 116 117 *ta = 0; 118 *ta = 1; 119 DELAY(5); 120 if (*ta != 1) 121 return(0); 122 123 return(1); 124 } 125 126 void 127 bzscattach(pdp, dp, auxp) 128 struct device *pdp; 129 struct device *dp; 130 void *auxp; 131 { 132 struct bzsc_softc *sc; 133 struct zbus_args *zap; 134 bzsc_regmap_p rp; 135 vu_char *fas; 136 137 zap = auxp; 138 fas = (vu_char *)(((char *)zap->va)+0x10000); 139 140 sc = (struct bzsc_softc *)dp; 141 rp = &sc->sc_regmap; 142 143 rp->FAS216.sfas_tc_low = &fas[0x00]; 144 rp->FAS216.sfas_tc_mid = &fas[0x02]; 145 rp->FAS216.sfas_fifo = &fas[0x04]; 146 rp->FAS216.sfas_command = &fas[0x06]; 147 rp->FAS216.sfas_dest_id = &fas[0x08]; 148 rp->FAS216.sfas_timeout = &fas[0x0A]; 149 rp->FAS216.sfas_syncper = &fas[0x0C]; 150 rp->FAS216.sfas_syncoff = &fas[0x0E]; 151 rp->FAS216.sfas_config1 = &fas[0x10]; 152 rp->FAS216.sfas_clkconv = &fas[0x12]; 153 rp->FAS216.sfas_test = &fas[0x14]; 154 rp->FAS216.sfas_config2 = &fas[0x16]; 155 rp->FAS216.sfas_config3 = &fas[0x18]; 156 rp->FAS216.sfas_tc_high = &fas[0x1C]; 157 rp->FAS216.sfas_fifo_bot = &fas[0x1E]; 158 rp->cclkaddr = &fas[0x21]; 159 rp->epowaddr = &fas[0x31]; 160 161 sc->sc_softc.sc_fas = (sfas_regmap_p)rp; 162 sc->sc_softc.sc_spec = 0; 163 164 sc->sc_softc.sc_led = bzsc_led_dummy; 165 166 sc->sc_softc.sc_setup_dma = bzsc_setup_dma; 167 sc->sc_softc.sc_build_dma_chain = bzsc_build_dma_chain; 168 sc->sc_softc.sc_need_bump = bzsc_need_bump; 169 170 sc->sc_softc.sc_clock_freq = 40; /* BlizzardII 1230 runs at 40MHz? */ 171 sc->sc_softc.sc_timeout = 250; /* Set default timeout to 250ms */ 172 sc->sc_softc.sc_config_flags = 0; 173 sc->sc_softc.sc_host_id = 7; 174 175 sc->sc_softc.sc_bump_sz = NBPG; 176 sc->sc_softc.sc_bump_pa = 0x0; 177 178 sfasinitialize((struct sfas_softc *)sc); 179 180 sc->sc_softc.sc_link.channel = SCSI_CHANNEL_ONLY_ONE; 181 sc->sc_softc.sc_link.adapter_softc = sc; 182 sc->sc_softc.sc_link.adapter_target = sc->sc_softc.sc_host_id; 183 sc->sc_softc.sc_link.adapter = &bzsc_scsiswitch; 184 sc->sc_softc.sc_link.device = &bzsc_scsidev; 185 sc->sc_softc.sc_link.openings = 1; 186 187 printf("\n"); 188 189 sc->sc_softc.sc_isr.isr_intr = bzsc_intr; 190 sc->sc_softc.sc_isr.isr_arg = &sc->sc_softc; 191 sc->sc_softc.sc_isr.isr_ipl = 2; 192 add_isr(&sc->sc_softc.sc_isr); 193 194 /* attach all scsi units on us */ 195 config_found(dp, &sc->sc_softc.sc_link, scsiprint); 196 } 197 198 int 199 bzsc_intr(arg) 200 void *arg; 201 { 202 struct sfas_softc *dev = arg; 203 bzsc_regmap_p rp; 204 int quickints; 205 206 rp = (bzsc_regmap_p)dev->sc_fas; 207 208 if (!(*rp->FAS216.sfas_status & SFAS_STAT_INTERRUPT_PENDING)) 209 return(0); 210 211 quickints = 16; 212 do { 213 dev->sc_status = *rp->FAS216.sfas_status; 214 dev->sc_interrupt = *rp->FAS216.sfas_interrupt; 215 216 if (dev->sc_interrupt & SFAS_INT_RESELECTED) { 217 dev->sc_resel[0] = *rp->FAS216.sfas_fifo; 218 dev->sc_resel[1] = *rp->FAS216.sfas_fifo; 219 } 220 sfasintr(dev); 221 } while((*rp->FAS216.sfas_status & SFAS_STAT_INTERRUPT_PENDING) && 222 --quickints); 223 224 return(1); 225 } 226 227 /* --------- */ 228 void 229 bzsc_set_dma_adr(sc, ptr, mode) 230 struct sfas_softc *sc; 231 vm_offset_t ptr; 232 int mode; 233 { 234 bzsc_regmap_p rp; 235 unsigned long p; 236 237 rp = (bzsc_regmap_p)sc->sc_fas; 238 239 p = ((unsigned long)ptr)>>1; 240 241 if (mode == SFAS_DMA_WRITE) 242 p |= BZSC_DMA_WRITE; 243 else 244 p |= BZSC_DMA_READ; 245 246 *rp->epowaddr = (u_char)(p>>24) & 0xFF; 247 *rp->cclkaddr = (u_char)(p>>16) & 0xFF; 248 *rp->cclkaddr = (u_char)(p>> 8) & 0xFF; 249 *rp->cclkaddr = (u_char)(p ) & 0xFF; 250 } 251 252 /* Set DMA transfer counter */ 253 void 254 bzsc_set_dma_tc(sc, len) 255 struct sfas_softc *sc; 256 unsigned int len; 257 { 258 *sc->sc_fas->sfas_tc_low = len; len >>= 8; 259 *sc->sc_fas->sfas_tc_mid = len; len >>= 8; 260 *sc->sc_fas->sfas_tc_high = len; 261 } 262 263 /* Initialize DMA for transfer */ 264 int 265 bzsc_setup_dma(sc, ptr, len, mode) 266 struct sfas_softc *sc; 267 vm_offset_t ptr; 268 int len; 269 int mode; 270 { 271 int retval; 272 273 retval = 0; 274 275 switch(mode) { 276 case SFAS_DMA_READ: 277 case SFAS_DMA_WRITE: 278 bzsc_set_dma_adr(sc, ptr, mode); 279 bzsc_set_dma_tc(sc, len); 280 break; 281 case SFAS_DMA_CLEAR: 282 default: 283 retval = (*sc->sc_fas->sfas_tc_high << 16) | 284 (*sc->sc_fas->sfas_tc_mid << 8) | 285 *sc->sc_fas->sfas_tc_low; 286 287 bzsc_set_dma_tc(sc, 0); 288 break; 289 } 290 291 return(retval); 292 } 293 294 /* Check if address and len is ok for DMA transfer */ 295 int 296 bzsc_need_bump(sc, ptr, len) 297 struct sfas_softc *sc; 298 vm_offset_t ptr; 299 int len; 300 { 301 int p; 302 303 p = (int)ptr & 0x03; 304 305 if (p) { 306 p = 4-p; 307 308 if (len < 256) 309 p = len; 310 } 311 312 return(p); 313 } 314 315 /* Interrupt driven routines */ 316 int 317 bzsc_build_dma_chain(sc, chain, p, l) 318 struct sfas_softc *sc; 319 struct sfas_dma_chain *chain; 320 void *p; 321 int l; 322 { 323 int n; 324 325 if (!l) 326 return(0); 327 328 #define set_link(n, p, l, f)\ 329 do { chain[n].ptr = (p); chain[n].len = (l); chain[n++].flg = (f); } while(0) 330 331 n = 0; 332 333 if (l < 512) 334 set_link(n, (vm_offset_t)p, l, SFAS_CHAIN_BUMP); 335 else if ( 336 #if defined(M68040) || defined(M68060) 337 ((mmutype == MMU_68040) && ((vm_offset_t)p >= 0xFFFC0000)) && 338 #endif 339 ((vm_offset_t)p >= 0xFF000000)) { 340 int len; 341 342 while(l) { 343 len = ((l > sc->sc_bump_sz) ? sc->sc_bump_sz : l); 344 345 set_link(n, (vm_offset_t)p, len, SFAS_CHAIN_BUMP); 346 347 p += len; 348 l -= len; 349 } 350 } else { 351 char *ptr; 352 vm_offset_t pa, lastpa; 353 int len, prelen, max_t; 354 355 ptr = p; 356 len = l; 357 358 pa = kvtop(ptr); 359 prelen = ((int)ptr & 0x03); 360 361 if (prelen) { 362 prelen = 4-prelen; 363 set_link(n, (vm_offset_t)ptr, prelen, SFAS_CHAIN_BUMP); 364 ptr += prelen; 365 len -= prelen; 366 } 367 368 lastpa = 0; 369 while(len > 3) { 370 pa = kvtop(ptr); 371 max_t = NBPG - (pa & PGOFSET); 372 if (max_t > len) 373 max_t = len; 374 375 max_t &= ~3; 376 377 if (lastpa == pa) 378 sc->sc_chain[n-1].len += max_t; 379 else 380 set_link(n, pa, max_t, SFAS_CHAIN_DMA); 381 382 lastpa = pa+max_t; 383 384 ptr += max_t; 385 len -= max_t; 386 } 387 388 if (len) 389 set_link(n, (vm_offset_t)ptr, len, SFAS_CHAIN_BUMP); 390 } 391 392 return(n); 393 } 394 395 /* Turn on led */ 396 void bzsc_led_dummy(sc, mode) 397 struct sfas_softc *sc; 398 int mode; 399 { 400 } 401