1 /* $NetBSD: ptsc.c,v 1.8 2002/10/05 17:16:35 chs Exp $ */ 2 3 /* 4 * Copyright (c) 1995 Scott Stevens 5 * Copyright (c) 1995 Daniel Widenfalk 6 * Copyright (c) 1994 Christian E. Hopps 7 * Copyright (c) 1982, 1990 The Regents of the University of California. 8 * All rights reserved. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the University of 21 * California, Berkeley and its contributors. 22 * 4. Neither the name of the University nor the names of its contributors 23 * may be used to endorse or promote products derived from this software 24 * without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 36 * SUCH DAMAGE. 37 * 38 * @(#)ptsc.c 39 */ 40 41 /* 42 * Power-tec SCSI-2 driver uses SFAS216 generic driver 43 * 44 * Thanks to Alsystems for loaning a development card and providing 45 * programming information. 46 */ 47 48 #include <sys/param.h> 49 #include <sys/systm.h> 50 #include <sys/kernel.h> 51 #include <sys/device.h> 52 #include <dev/scsipi/scsi_all.h> 53 #include <dev/scsipi/scsipi_all.h> 54 #include <dev/scsipi/scsiconf.h> 55 #include <machine/io.h> 56 #include <machine/intr.h> 57 #include <machine/bootconfig.h> 58 #include <acorn32/podulebus/podulebus.h> 59 #include <acorn32/podulebus/sfasreg.h> 60 #include <acorn32/podulebus/sfasvar.h> 61 #include <acorn32/podulebus/ptscreg.h> 62 #include <acorn32/podulebus/ptscvar.h> 63 #include <dev/podulebus/podules.h> 64 #include <dev/podulebus/powerromreg.h> 65 66 int ptscmatch __P((struct device *, struct cfdata *, void *)); 67 void ptscattach __P((struct device *, struct device *, void *)); 68 69 CFATTACH_DECL(ptsc, sizeof(struct ptsc_softc), 70 ptscmatch, ptscattach, NULL, NULL); 71 72 int ptsc_intr(void *); 73 int ptsc_setup_dma(void *, void *, int, int); 74 int ptsc_build_dma_chain(void *, void *, void *, int); 75 int ptsc_need_bump(void *, void *, int); 76 void ptsc_led(void *, int); 77 78 void ptsc_set_dma_adr(struct sfas_softc *, void *); 79 void ptsc_set_dma_tc(struct sfas_softc *, unsigned int); 80 void ptsc_set_dma_mode(struct sfas_softc *, int); 81 82 /* 83 * if we are a Power-tec SCSI-2 card 84 */ 85 int 86 ptscmatch(pdp, cf, auxp) 87 struct device *pdp; 88 struct cfdata *cf; 89 void *auxp; 90 { 91 struct podule_attach_args *pa = (struct podule_attach_args *)auxp; 92 93 /* Look for the card */ 94 95 /* 96 * All Power-tec cards effectively have PowerROMS. Note, 97 * though, that here, if we fail to initialise the loader, we 98 * assume this _is_ the right kind of card. 99 */ 100 if (pa->pa_product == PODULE_ALSYSTEMS_SCSI && 101 (podulebus_initloader(pa) != 0 || 102 podloader_callloader(pa, 0, 0) == PRID_POWERTEC)) 103 return 1; 104 105 return 0; 106 } 107 108 void 109 ptscattach(pdp, dp, auxp) 110 struct device *pdp; 111 struct device *dp; 112 void *auxp; 113 { 114 struct ptsc_softc *sc = (struct ptsc_softc *)dp; 115 struct podule_attach_args *pa; 116 ptsc_regmap_p rp = &sc->sc_regmap; 117 vu_char *fas; 118 119 pa = (struct podule_attach_args *)auxp; 120 121 if (pa->pa_podule_number == -1) 122 panic("Podule has disappeared !"); 123 124 sc->sc_specific.sc_podule_number = pa->pa_podule_number; 125 sc->sc_specific.sc_podule = pa->pa_podule; 126 sc->sc_specific.sc_iobase = 127 (vu_char *)sc->sc_specific.sc_podule->fast_base; 128 129 rp->chipreset = &sc->sc_specific.sc_iobase[PTSC_CONTROL_CHIPRESET]; 130 rp->inten = &sc->sc_specific.sc_iobase[PTSC_CONTROL_INTEN]; 131 rp->status = &sc->sc_specific.sc_iobase[PTSC_STATUS]; 132 rp->term = &sc->sc_specific.sc_iobase[PTSC_CONTROL_TERM]; 133 rp->led = &sc->sc_specific.sc_iobase[PTSC_CONTROL_LED]; 134 fas = &sc->sc_specific.sc_iobase[PTSC_FASOFFSET_BASE]; 135 136 rp->FAS216.sfas_tc_low = &fas[PTSC_FASOFFSET_TCL]; 137 rp->FAS216.sfas_tc_mid = &fas[PTSC_FASOFFSET_TCM]; 138 rp->FAS216.sfas_fifo = &fas[PTSC_FASOFFSET_FIFO]; 139 rp->FAS216.sfas_command = &fas[PTSC_FASOFFSET_COMMAND]; 140 rp->FAS216.sfas_dest_id = &fas[PTSC_FASOFFSET_DESTID]; 141 rp->FAS216.sfas_timeout = &fas[PTSC_FASOFFSET_TIMEOUT]; 142 rp->FAS216.sfas_syncper = &fas[PTSC_FASOFFSET_PERIOD]; 143 rp->FAS216.sfas_syncoff = &fas[PTSC_FASOFFSET_OFFSET]; 144 rp->FAS216.sfas_config1 = &fas[PTSC_FASOFFSET_CONFIG1]; 145 rp->FAS216.sfas_clkconv = &fas[PTSC_FASOFFSET_CLOCKCONV]; 146 rp->FAS216.sfas_test = &fas[PTSC_FASOFFSET_TEST]; 147 rp->FAS216.sfas_config2 = &fas[PTSC_FASOFFSET_CONFIG2]; 148 rp->FAS216.sfas_config3 = &fas[PTSC_FASOFFSET_CONFIG3]; 149 rp->FAS216.sfas_tc_high = &fas[PTSC_FASOFFSET_TCH]; 150 rp->FAS216.sfas_fifo_bot = &fas[PTSC_FASOFFSET_FIFOBOTTOM]; 151 152 sc->sc_softc.sc_fas = (sfas_regmap_p)rp; 153 sc->sc_softc.sc_spec = &sc->sc_specific; 154 155 sc->sc_softc.sc_led = ptsc_led; 156 157 sc->sc_softc.sc_setup_dma = ptsc_setup_dma; 158 sc->sc_softc.sc_build_dma_chain = ptsc_build_dma_chain; 159 sc->sc_softc.sc_need_bump = ptsc_need_bump; 160 161 sc->sc_softc.sc_clock_freq = 40; /* Power-Tec runs at 8MHz */ 162 sc->sc_softc.sc_timeout = 250; /* Set default timeout to 250ms */ 163 sc->sc_softc.sc_config_flags = SFAS_NO_DMA /*| SFAS_NF_DEBUG*/; 164 sc->sc_softc.sc_host_id = 7; /* Should check the jumpers */ 165 166 sc->sc_softc.sc_bump_sz = NBPG; 167 sc->sc_softc.sc_bump_pa = 0x0; 168 169 sfasinitialize((struct sfas_softc *)sc); 170 171 sc->sc_softc.sc_adapter.adapt_dev = &sc->sc_softc.sc_dev; 172 sc->sc_softc.sc_adapter.adapt_nchannels = 1; 173 sc->sc_softc.sc_adapter.adapt_openings = 7; 174 sc->sc_softc.sc_adapter.adapt_max_periph = 1; 175 sc->sc_softc.sc_adapter.adapt_ioctl = NULL; 176 sc->sc_softc.sc_adapter.adapt_minphys = sfas_minphys; 177 sc->sc_softc.sc_adapter.adapt_request = sfas_scsi_request; 178 179 sc->sc_softc.sc_channel.chan_adapter = &sc->sc_softc.sc_adapter; 180 sc->sc_softc.sc_channel.chan_bustype = &scsi_bustype; 181 sc->sc_softc.sc_channel.chan_channel = 0; 182 sc->sc_softc.sc_channel.chan_ntargets = 8; 183 sc->sc_softc.sc_channel.chan_nluns = 8; 184 sc->sc_softc.sc_channel.chan_id = sc->sc_softc.sc_host_id; 185 186 /* Provide an override for the host id */ 187 (void)get_bootconf_option(boot_args, "ptsc.hostid", 188 BOOTOPT_TYPE_INT, &sc->sc_softc.sc_channel.chan_id); 189 190 printf(": host=%d", sc->sc_softc.sc_channel.chan_id); 191 192 /* initialise the card */ 193 /* *rp->term = 0;*/ 194 *rp->inten = (PTSC_POLL?0:1); 195 *rp->led = 0; 196 197 #if PTSC_POLL == 0 198 evcnt_attach_dynamic(&sc->sc_softc.sc_intrcnt, EVCNT_TYPE_INTR, NULL, 199 dp->dv_xname, "intr"); 200 sc->sc_softc.sc_ih = podulebus_irq_establish(pa->pa_ih, IPL_BIO, 201 ptsc_intr, &sc->sc_softc, &sc->sc_softc.sc_intrcnt); 202 if (sc->sc_softc.sc_ih == NULL) 203 panic("%s: Cannot install IRQ handler", dp->dv_xname); 204 #else 205 printf(" polling"); 206 sc->sc_softc.sc_adapter.adapt_flags = SCSIPI_ADAPT_POLL_ONLY; 207 #endif 208 209 printf("\n"); 210 211 /* attach all scsi units on us */ 212 config_found(dp, &sc->sc_softc.sc_channel, scsiprint); 213 } 214 215 216 int 217 ptsc_intr(arg) 218 void *arg; 219 { 220 struct sfas_softc *dev = arg; 221 ptsc_regmap_p rp; 222 int quickints; 223 224 rp = (ptsc_regmap_p)dev->sc_fas; 225 226 if (*rp->FAS216.sfas_status & SFAS_STAT_INTERRUPT_PENDING) { 227 quickints = 16; 228 do { 229 dev->sc_status = *rp->FAS216.sfas_status; 230 dev->sc_interrupt = *rp->FAS216.sfas_interrupt; 231 232 if (dev->sc_interrupt & SFAS_INT_RESELECTED) { 233 dev->sc_resel[0] = *rp->FAS216.sfas_fifo; 234 dev->sc_resel[1] = *rp->FAS216.sfas_fifo; 235 } 236 237 sfasintr(dev); 238 239 } while((*rp->FAS216.sfas_status & SFAS_STAT_INTERRUPT_PENDING) 240 && --quickints); 241 } 242 243 return(0); /* Pass interrupt on down the chain */ 244 } 245 246 /* Load transfer address into dma register */ 247 void 248 ptsc_set_dma_adr(sc, ptr) 249 struct sfas_softc *sc; 250 void *ptr; 251 { 252 #if 0 253 ptsc_regmap_p rp; 254 unsigned int *p; 255 unsigned int d; 256 #endif 257 #if 0 258 printf("ptsc_set_dma_adr(sc = 0x%08x, ptr = 0x%08x)\n", (u_int)sc, (u_int)ptr); 259 #endif 260 return; 261 #if 0 262 rp = (ptsc_regmap_p)sc->sc_fas; 263 264 d = (unsigned int)ptr; 265 p = (unsigned int *)((d & 0xFFFFFF) + (int)rp->dmabase); 266 267 *rp->clear=0; 268 *p = d; 269 #endif 270 } 271 272 /* Set DMA transfer counter */ 273 void 274 ptsc_set_dma_tc(sc, len) 275 struct sfas_softc *sc; 276 unsigned int len; 277 { 278 printf("ptsc_set_dma_tc(sc, len = 0x%08x)", len); 279 280 *sc->sc_fas->sfas_tc_low = len; len >>= 8; 281 *sc->sc_fas->sfas_tc_mid = len; len >>= 8; 282 *sc->sc_fas->sfas_tc_high = len; 283 } 284 285 /* Set DMA mode */ 286 void 287 ptsc_set_dma_mode(sc, mode) 288 struct sfas_softc *sc; 289 int mode; 290 { 291 #if 0 292 struct csc_specific *spec; 293 294 spec = sc->sc_spec; 295 296 spec->portbits = (spec->portbits & ~FLSC_PB_DMA_BITS) | mode; 297 *((flsc_regmap_p)sc->sc_fas)->hardbits = spec->portbits; 298 #endif 299 } 300 301 /* Initialize DMA for transfer */ 302 int 303 ptsc_setup_dma(v, ptr, len, mode) 304 void *v; 305 void *ptr; 306 int len; 307 int mode; 308 { 309 return(0); 310 311 #if 0 312 struct sfas_softc *sc = v; 313 int retval; 314 315 retval = 0; 316 317 printf("ptsc_setup_dma(sc, ptr = 0x%08x, len = 0x%08x, mode = 0x%08x)\n", (u_int)ptr, len, mode); 318 319 switch(mode) { 320 case SFAS_DMA_READ: 321 case SFAS_DMA_WRITE: 322 flsc_set_dma_adr(sc, ptr); 323 if (mode == SFAS_DMA_READ) 324 flsc_set_dma_mode(sc,FLSC_PB_ENABLE_DMA | FLSC_PB_DMA_READ); 325 else 326 flsc_set_dma_mode(sc,FLSC_PB_ENABLE_DMA | FLSC_PB_DMA_WRITE); 327 328 flsc_set_dma_tc(sc, len); 329 break; 330 331 case SFAS_DMA_CLEAR: 332 default: 333 flsc_set_dma_mode(sc, FLSC_PB_DISABLE_DMA); 334 flsc_set_dma_adr(sc, 0); 335 336 retval = (*sc->sc_fas->sfas_tc_high << 16) | 337 (*sc->sc_fas->sfas_tc_mid << 8) | 338 *sc->sc_fas->sfas_tc_low; 339 340 flsc_set_dma_tc(sc, 0); 341 break; 342 } 343 344 return(retval); 345 #endif 346 } 347 348 /* Check if address and len is ok for DMA transfer */ 349 int 350 ptsc_need_bump(v, ptr, len) 351 void *v; 352 void *ptr; 353 int len; 354 { 355 int p; 356 357 p = (int)ptr & 0x03; 358 359 if (p) { 360 p = 4-p; 361 362 if (len < 256) 363 p = len; 364 } 365 366 return(p); 367 } 368 369 /* Interrupt driven routines */ 370 int 371 ptsc_build_dma_chain(void *v1, void *v2, void *p, int l) 372 { 373 #if 0 374 vm_offset_t pa, lastpa; 375 char *ptr; 376 int len, prelen, postlen, max_t, n; 377 #endif 378 #if 0 379 printf("ptsc_build_dma_chain()\n"); 380 #endif 381 return(0); 382 383 #if 0 384 if (l == 0) 385 return(0); 386 387 #define set_link(n, p, l, f)\ 388 do { chain[n].ptr = (p); chain[n].len = (l); chain[n++].flg = (f); } while(0) 389 390 n = 0; 391 392 if (l < 512) 393 set_link(n, (vm_offset_t)p, l, SFAS_CHAIN_BUMP); 394 else if (p >= (void *)0xFF000000) { 395 while(l != 0) { 396 len = ((l > sc->sc_bump_sz) ? sc->sc_bump_sz : l); 397 398 set_link(n, (vm_offset_t)p, len, SFAS_CHAIN_BUMP); 399 400 p += len; 401 l -= len; 402 } 403 } else { 404 ptr = p; 405 len = l; 406 407 pa = kvtop(ptr); 408 prelen = ((int)ptr & 0x03); 409 410 if (prelen) { 411 prelen = 4-prelen; 412 set_link(n, (vm_offset_t)ptr, prelen, SFAS_CHAIN_BUMP); 413 ptr += prelen; 414 len -= prelen; 415 } 416 417 lastpa = 0; 418 while(len > 3) { 419 pa = kvtop(ptr); 420 max_t = NBPG - (pa & PGOFSET); 421 if (max_t > len) 422 max_t = len; 423 424 max_t &= ~3; 425 426 if (lastpa == pa) 427 sc->sc_chain[n-1].len += max_t; 428 else 429 set_link(n, pa, max_t, SFAS_CHAIN_DMA); 430 431 lastpa = pa+max_t; 432 433 ptr += max_t; 434 len -= max_t; 435 } 436 437 if (len) 438 set_link(n, (vm_offset_t)ptr, len, SFAS_CHAIN_BUMP); 439 } 440 441 return(n); 442 #endif 443 } 444 445 /* Turn on/off led */ 446 void 447 ptsc_led(void *v, int mode) 448 { 449 struct sfas_softc *sc = v; 450 ptsc_regmap_p rp; 451 452 rp = (ptsc_regmap_p)sc->sc_fas; 453 454 if (mode) { 455 sc->sc_led_status++; 456 } else { 457 if (sc->sc_led_status) 458 sc->sc_led_status--; 459 } 460 *rp->led = (sc->sc_led_status?1:0); 461 } 462