1 /* $NetBSD: sec.c,v 1.15 2009/05/11 20:13:49 bjh21 Exp $ */ 2 3 /*- 4 * Copyright (c) 2000, 2001, 2006 Ben Harris 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. The name of the author may not be used to endorse or promote products 16 * derived from this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 */ 29 /* 30 * sec.c -- driver for Acorn SCSI expansion cards (AKA30, AKA31, AKA32) 31 * 32 * These cards are documented in: 33 * Acorn Archimedes 500 series / Acorn R200 series Technical Reference Manual 34 * Published by Acorn Computers Limited 35 * ISBN 1 85250 086 7 36 * Part number 0486,052 37 * Issue 1, November 1990 38 */ 39 40 #include <sys/cdefs.h> 41 __KERNEL_RCSID(0, "$NetBSD: sec.c,v 1.15 2009/05/11 20:13:49 bjh21 Exp $"); 42 43 #include <sys/param.h> 44 45 #include <sys/buf.h> 46 #include <sys/device.h> 47 #include <sys/malloc.h> 48 #include <sys/reboot.h> /* For bootverbose */ 49 #include <sys/syslog.h> 50 #include <sys/systm.h> 51 52 #include <dev/scsipi/scsi_all.h> 53 #include <dev/scsipi/scsipi_all.h> 54 #include <dev/scsipi/scsiconf.h> 55 56 #include <sys/bus.h> 57 58 #include <dev/ic/wd33c93reg.h> 59 #include <dev/ic/wd33c93var.h> 60 #include <dev/ic/nec71071reg.h> 61 62 #include <dev/podulebus/podulebus.h> 63 #include <dev/podulebus/podules.h> 64 #include <dev/podulebus/powerromreg.h> 65 #include <dev/podulebus/secreg.h> 66 67 #include "opt_ddb.h" 68 69 struct sec_softc { 70 struct wd33c93_softc sc_sbic; 71 bus_space_tag_t sc_pod_t; 72 bus_space_handle_t sc_pod_h; 73 bus_space_tag_t sc_mod_t; 74 bus_space_handle_t sc_mod_h; 75 void *sc_ih; 76 struct evcnt sc_intrcnt; 77 uint8_t sc_mpr; 78 79 /* Details of the current DMA transfer */ 80 bool sc_dmaactive; 81 void * sc_dmaaddr; 82 int sc_dmaoff; 83 size_t sc_dmalen; 84 bool sc_dmain; 85 /* Details of the current block within the above transfer */ 86 size_t sc_dmablk; 87 }; 88 89 #define SEC_DMABLK 16384 90 #define SEC_NBLKS 3 91 #define SEC_DMAMODE MODE_TMODE_DMD 92 93 /* autoconfiguration glue */ 94 static int sec_match(device_t, cfdata_t, void *); 95 static void sec_attach(device_t, device_t, void *); 96 97 /* shutdown hook */ 98 static bool sec_shutdown(device_t, int); 99 100 /* callbacks from MI WD33C93 driver */ 101 static int sec_dmasetup(struct wd33c93_softc *, void **, size_t *, int, 102 size_t *); 103 static int sec_dmago(struct wd33c93_softc *); 104 static void sec_dmastop(struct wd33c93_softc *); 105 static void sec_reset(struct wd33c93_softc *); 106 107 static int sec_intr(void *); 108 static int sec_dmatc(struct sec_softc *sc); 109 110 void sec_dumpdma(void *arg); 111 112 CFATTACH_DECL_NEW(sec, sizeof(struct sec_softc), 113 sec_match, sec_attach, NULL, NULL); 114 115 static inline void 116 sec_setpage(struct sec_softc *sc, int page) 117 { 118 119 sc->sc_mpr = (sc->sc_mpr & ~SEC_MPR_PAGE) | page; 120 bus_space_write_1(sc->sc_pod_t, sc->sc_pod_h, SEC_MPR, sc->sc_mpr); 121 } 122 123 static inline void 124 sec_cli(struct sec_softc *sc) 125 { 126 127 bus_space_write_1(sc->sc_pod_t, sc->sc_pod_h, SEC_CLRINT, 0); 128 } 129 130 static inline void 131 dmac_write(struct sec_softc *sc, int reg, uint8_t val) 132 { 133 134 bus_space_write_1(sc->sc_mod_t, sc->sc_mod_h, 135 SEC_DMAC + DMAC(reg), val); 136 } 137 138 static inline uint8_t 139 dmac_read(struct sec_softc *sc, int reg) 140 { 141 142 return bus_space_read_1(sc->sc_mod_t, sc->sc_mod_h, 143 SEC_DMAC + DMAC(reg)); 144 } 145 146 static int 147 sec_match(device_t parent, cfdata_t cf, void *aux) 148 { 149 struct podulebus_attach_args *pa = aux; 150 151 /* Standard ROM, skipping the MCS card that used the same ID. */ 152 if (pa->pa_product == PODULE_ACORN_SCSI && 153 strncmp(pa->pa_descr, "MCS", 3) != 0) 154 return 1; 155 156 /* PowerROM */ 157 if (pa->pa_product == PODULE_ALSYSTEMS_SCSI && 158 podulebus_initloader(pa) == 0 && 159 podloader_callloader(pa, 0, 0) == PRID_ACORN_SCSI1) 160 return 1; 161 162 return 0; 163 } 164 165 static void 166 sec_attach(device_t parent, device_t self, void *aux) 167 { 168 struct podulebus_attach_args *pa = aux; 169 struct sec_softc *sc = device_private(self); 170 int i; 171 172 sc->sc_sbic.sc_dev = self; 173 /* Set up bus spaces */ 174 sc->sc_pod_t = pa->pa_fast_t; 175 bus_space_map(pa->pa_fast_t, pa->pa_fast_base, 0x1000, 0, 176 &sc->sc_pod_h); 177 sc->sc_mod_t = pa->pa_mod_t; 178 bus_space_map(pa->pa_mod_t, pa->pa_mod_base, 0x1000, 0, 179 &sc->sc_mod_h); 180 181 sc->sc_sbic.sc_regt = sc->sc_mod_t; 182 bus_space_subregion(sc->sc_mod_t, sc->sc_mod_h, SEC_SBIC + 0, 1, 183 &sc->sc_sbic.sc_asr_regh); 184 bus_space_subregion(sc->sc_mod_t, sc->sc_mod_h, SEC_SBIC + 1, 1, 185 &sc->sc_sbic.sc_data_regh); 186 187 sc->sc_sbic.sc_id = 7; 188 sc->sc_sbic.sc_clkfreq = SEC_CLKFREQ; 189 sc->sc_sbic.sc_dmamode = SBIC_CTL_BURST_DMA; 190 191 sc->sc_sbic.sc_adapter.adapt_request = wd33c93_scsi_request; 192 sc->sc_sbic.sc_adapter.adapt_minphys = minphys; 193 194 sc->sc_sbic.sc_dmasetup = sec_dmasetup; 195 sc->sc_sbic.sc_dmago = sec_dmago; 196 sc->sc_sbic.sc_dmastop = sec_dmastop; 197 sc->sc_sbic.sc_reset = sec_reset; 198 199 sc->sc_mpr = 0; 200 bus_space_write_1(sc->sc_pod_t, sc->sc_pod_h, SEC_MPR, sc->sc_mpr); 201 202 for (i = 0; i < SEC_NPAGES; i++) { 203 sec_setpage(sc, i); 204 bus_space_set_region_2(sc->sc_mod_t, sc->sc_mod_h, 205 SEC_SRAM, 0, SEC_PAGESIZE / 2); 206 } 207 208 wd33c93_attach(&sc->sc_sbic); 209 210 evcnt_attach_dynamic(&sc->sc_intrcnt, EVCNT_TYPE_INTR, NULL, 211 device_xname(self), "intr"); 212 sc->sc_ih = podulebus_irq_establish(pa->pa_ih, IPL_BIO, sec_intr, 213 sc, &sc->sc_intrcnt); 214 sec_cli(sc); 215 sc->sc_mpr |= SEC_MPR_IE; 216 bus_space_write_1(sc->sc_pod_t, sc->sc_pod_h, SEC_MPR, sc->sc_mpr); 217 pmf_device_register1(sc->sc_sbic.sc_dev, NULL, NULL, sec_shutdown); 218 } 219 220 /* 221 * Before reboot, reset the page register to 0 so that RISC OS can see 222 * the podule ROM. 223 */ 224 static bool 225 sec_shutdown(device_t dev, int howto) 226 { 227 struct sec_softc *sc = device_private(dev); 228 229 sec_setpage(sc, 0); 230 return true; 231 } 232 233 static void 234 sec_copyin(struct sec_softc *sc, void *dest, int src, size_t size) 235 { 236 uint16_t tmp, *wptr; 237 int cnt, extra_byte; 238 239 KASSERT(src >= 0); 240 KASSERT(src + size <= SEC_MEMSIZE); 241 if (src % 2 != 0) { 242 /* 243 * There's a stray byte at the start. Read the word 244 * containing it. 245 */ 246 sec_setpage(sc, src / SEC_PAGESIZE); 247 tmp = bus_space_read_2(sc->sc_mod_t, sc->sc_mod_h, 248 SEC_SRAM + (src % SEC_PAGESIZE / 2)); 249 *(uint8_t *)dest = tmp >> 8; 250 dest = ((uint8_t *)dest) + 1; 251 src++; size--; 252 } 253 KASSERT(src % 2 == 0); 254 KASSERT(ALIGNED_POINTER(dest, uint16_t)); 255 wptr = dest; 256 extra_byte = size % 2; 257 size -= extra_byte; 258 while (size > 0) { 259 cnt = SEC_PAGESIZE - src % SEC_PAGESIZE; 260 if (cnt > size) 261 cnt = size; 262 sec_setpage(sc, src / SEC_PAGESIZE); 263 /* bus ops are in words */ 264 bus_space_read_region_2(sc->sc_mod_t, sc->sc_mod_h, 265 SEC_SRAM + src % SEC_PAGESIZE / 2, wptr, cnt / 2); 266 src += cnt; 267 wptr += cnt / 2; 268 size -= cnt; 269 } 270 if (extra_byte) { 271 sec_setpage(sc, src / SEC_PAGESIZE); 272 *(u_int8_t *)wptr = 273 bus_space_read_2(sc->sc_mod_t, sc->sc_mod_h, 274 SEC_SRAM + src % SEC_PAGESIZE / 2) & 0xff; 275 } 276 } 277 278 static void 279 sec_copyout(struct sec_softc *sc, const void *src, int dest, size_t size) 280 { 281 int cnt, extra_byte; 282 const uint16_t *wptr; 283 uint16_t tmp; 284 285 KASSERT(dest >= 0); 286 KASSERT(dest + size <= SEC_MEMSIZE); 287 if (dest % 2 != 0) { 288 /* 289 * There's a stray byte at the start. Read the word 290 * containing it. 291 */ 292 sec_setpage(sc, dest / SEC_PAGESIZE); 293 tmp = bus_space_read_2(sc->sc_mod_t, sc->sc_mod_h, 294 SEC_SRAM + (dest % SEC_PAGESIZE / 2)); 295 tmp &= 0xff; 296 tmp |= *(uint8_t const *)src << 8; 297 bus_space_write_2(sc->sc_mod_t, sc->sc_mod_h, 298 SEC_SRAM + (dest % SEC_PAGESIZE / 2), tmp); 299 src = ((uint8_t const *)src) + 1; 300 dest++; size--; 301 } 302 KASSERT(dest % 2 == 0); 303 KASSERT(ALIGNED_POINTER(src, uint16_t)); 304 wptr = src; 305 extra_byte = size % 2; 306 size -= extra_byte; 307 while (size > 0) { 308 cnt = SEC_PAGESIZE - dest % SEC_PAGESIZE; 309 if (cnt > size) 310 cnt = size; 311 sec_setpage(sc, dest / SEC_PAGESIZE); 312 /* bus ops are in words */ 313 bus_space_write_region_2(sc->sc_mod_t, sc->sc_mod_h, 314 dest % SEC_PAGESIZE / 2, wptr, cnt / 2); 315 wptr += cnt / 2; 316 dest += cnt; 317 size -= cnt; 318 } 319 if (extra_byte) { 320 /* 321 * There's a stray byte at the end. Read the word 322 * containing it. 323 */ 324 sec_setpage(sc, dest / SEC_PAGESIZE); 325 tmp = bus_space_read_2(sc->sc_mod_t, sc->sc_mod_h, 326 SEC_SRAM + (dest % SEC_PAGESIZE / 2)); 327 tmp &= 0xff00; 328 tmp |= *(uint8_t const *)wptr; 329 bus_space_write_2(sc->sc_mod_t, sc->sc_mod_h, 330 SEC_SRAM + (dest % SEC_PAGESIZE / 2), tmp); 331 } 332 } 333 334 static void 335 sec_dmablk(struct sec_softc *sc, int blk) 336 { 337 int off; 338 size_t len; 339 340 KASSERT(blk >= 0); 341 KASSERT(blk * SEC_DMABLK < sc->sc_dmalen); 342 off = (blk % SEC_NBLKS) * SEC_DMABLK + sc->sc_dmaoff; 343 len = MIN(SEC_DMABLK, sc->sc_dmalen - (blk * SEC_DMABLK)); 344 dmac_write(sc, NEC71071_ADDRLO, off & 0xff); 345 dmac_write(sc, NEC71071_ADDRMID, off >> 8); 346 dmac_write(sc, NEC71071_ADDRHI, 0); 347 /* 348 * "Note: The number of DMA transfer cycles is actually the 349 * value of the current count register + 1. Therefore, when 350 * programming the count register, specify the number of DMA 351 * transfers minus one." -- uPD71071 datasheet 352 */ 353 dmac_write(sc, NEC71071_COUNTLO, (len - 1) & 0xff); 354 dmac_write(sc, NEC71071_COUNTHI, (len - 1) >> 8); 355 } 356 357 static void 358 sec_copyoutblk(struct sec_softc *sc, int blk) 359 { 360 int off; 361 size_t len; 362 363 KASSERT(blk >= 0); 364 KASSERT(blk * SEC_DMABLK < sc->sc_dmalen); 365 KASSERT(!sc->sc_dmain); 366 off = (blk % SEC_NBLKS) * SEC_DMABLK + sc->sc_dmaoff; 367 len = MIN(SEC_DMABLK, sc->sc_dmalen - (blk * SEC_DMABLK)); 368 sec_copyout(sc, (char*)sc->sc_dmaaddr + (blk * SEC_DMABLK), off, len); 369 } 370 371 static void 372 sec_copyinblk(struct sec_softc *sc, int blk) 373 { 374 int off; 375 size_t len; 376 377 KASSERT(blk >= 0); 378 KASSERT(blk * SEC_DMABLK < sc->sc_dmalen); 379 KASSERT(sc->sc_dmain); 380 off = (blk % SEC_NBLKS) * SEC_DMABLK + sc->sc_dmaoff; 381 len = MIN(SEC_DMABLK, sc->sc_dmalen - (blk * SEC_DMABLK)); 382 sec_copyin(sc, (char*)sc->sc_dmaaddr + (blk * SEC_DMABLK), off, len); 383 } 384 385 static int 386 sec_dmasetup(struct wd33c93_softc *sc_sbic, void **addr, size_t *len, 387 int datain, size_t *dmasize) 388 { 389 struct sec_softc *sc = (struct sec_softc *)sc_sbic; 390 uint8_t mode; 391 392 sc->sc_dmaaddr = *addr; 393 sc->sc_dmaoff = ALIGNED_POINTER(*addr, uint16_t) ? 0 : 1; 394 sc->sc_dmalen = *len; 395 sc->sc_dmain = datain; 396 sc->sc_dmablk = 0; 397 mode = SEC_DMAMODE | (datain ? MODE_TDIR_IOTM : MODE_TDIR_MTIO); 398 /* Program first block into DMAC and queue up second. */ 399 dmac_write(sc, NEC71071_CHANNEL, 0); 400 if (!sc->sc_dmain) 401 sec_copyoutblk(sc, 0); 402 sec_dmablk(sc, 0); 403 /* Mode control register */ 404 dmac_write(sc, NEC71071_MODE, mode); 405 return sc->sc_dmalen; 406 } 407 408 static int 409 sec_dmago(struct wd33c93_softc *sc_sbic) 410 { 411 struct sec_softc *sc = (struct sec_softc *)sc_sbic; 412 413 dmac_write(sc, NEC71071_MASK, 0xe); 414 sc->sc_dmaactive = true; 415 if (!sc->sc_dmain && sc->sc_dmalen > SEC_DMABLK) 416 sec_copyoutblk(sc, 1); 417 return sc->sc_dmalen; 418 } 419 420 static void 421 sec_dmastop(struct wd33c93_softc *sc_sbic) 422 { 423 struct sec_softc *sc = (struct sec_softc *)sc_sbic; 424 425 dmac_write(sc, NEC71071_MASK, 0xf); 426 if (sc->sc_dmaactive && sc->sc_dmain) 427 sec_copyinblk(sc, sc->sc_dmablk); 428 sc->sc_dmaactive = false; 429 } 430 431 /* 432 * Reset the SCSI bus, and incidentally the SBIC and DMAC. 433 */ 434 static void 435 sec_reset(struct wd33c93_softc *sc_sbic) 436 { 437 struct sec_softc *sc = (struct sec_softc *)sc_sbic; 438 uint8_t asr, csr; 439 440 bus_space_write_1(sc->sc_pod_t, sc->sc_pod_h, SEC_MPR, 441 sc->sc_mpr | SEC_MPR_UR); 442 DELAY(7); 443 bus_space_write_1(sc->sc_pod_t, sc->sc_pod_h, SEC_MPR, sc->sc_mpr); 444 /* Wait for and clear the reset-complete interrupt */ 445 do 446 GET_SBIC_asr(sc_sbic, asr); 447 while (!(asr & SBIC_ASR_INT)); 448 GET_SBIC_csr(sc_sbic, csr); 449 dmac_write(sc, NEC71071_DCTRL1, DCTRL1_CMP | DCTRL1_RQL); 450 dmac_write(sc, NEC71071_DCTRL2, 0); 451 sec_cli(sc); 452 } 453 454 static int 455 sec_intr(void *arg) 456 { 457 struct sec_softc *sc = arg; 458 u_int8_t isr; 459 460 isr = bus_space_read_1(sc->sc_pod_t, sc->sc_pod_h, SEC_ISR); 461 if (!(isr & SEC_ISR_IRQ)) 462 return 0; 463 if (isr & SEC_ISR_DMAC) 464 sec_dmatc(sc); 465 if (isr & SEC_ISR_SBIC) 466 wd33c93_intr(&sc->sc_sbic); 467 return 1; 468 } 469 470 static int 471 sec_dmatc(struct sec_softc *sc) 472 { 473 474 sec_cli(sc); 475 /* DMAC finished block n-1 and is now working on block n */ 476 sc->sc_dmablk++; 477 if (sc->sc_dmalen > sc->sc_dmablk * SEC_DMABLK) { 478 dmac_write(sc, NEC71071_CHANNEL, 0); 479 sec_dmablk(sc, sc->sc_dmablk); 480 dmac_write(sc, NEC71071_MASK, 0xe); 481 if (!sc->sc_dmain && 482 sc->sc_dmalen > (sc->sc_dmablk + 1) * SEC_DMABLK) 483 sec_copyoutblk(sc, sc->sc_dmablk + 1); 484 } else { 485 /* All blocks fully processed. */ 486 sc->sc_dmaactive = false; 487 } 488 if (sc->sc_dmain) 489 sec_copyinblk(sc, sc->sc_dmablk - 1); 490 return 1; 491 } 492 493 #ifdef DDB 494 void 495 sec_dumpdma(void *arg) 496 { 497 struct sec_softc *sc = arg; 498 499 dmac_write(sc, NEC71071_CHANNEL, 0); 500 printf("%s: DMA state: cur count %02x%02x cur addr %02x%02x%02x ", 501 device_xname(sc->sc_sbic.sc_dev), 502 dmac_read(sc, NEC71071_COUNTHI), dmac_read(sc, NEC71071_COUNTLO), 503 dmac_read(sc, NEC71071_ADDRHI), dmac_read(sc, NEC71071_ADDRMID), 504 dmac_read(sc, NEC71071_ADDRLO)); 505 dmac_write(sc, NEC71071_CHANNEL, 0 | CHANNEL_WBASE); 506 printf("base count %02x%02x base addr %02x%02x%02x\n", 507 dmac_read(sc, NEC71071_COUNTHI), dmac_read(sc, NEC71071_COUNTLO), 508 dmac_read(sc, NEC71071_ADDRHI), dmac_read(sc, NEC71071_ADDRMID), 509 dmac_read(sc, NEC71071_ADDRLO)); 510 printf("%s: DMA state: dctrl %1x%02x mode %02x status %02x req %02x " 511 "mask %02x\n", 512 device_xname(sc->sc_sbic.sc_dev), dmac_read(sc, NEC71071_DCTRL2), 513 dmac_read(sc, NEC71071_DCTRL1), dmac_read(sc, NEC71071_MODE), 514 dmac_read(sc, NEC71071_STATUS), dmac_read(sc, NEC71071_REQUEST), 515 dmac_read(sc, NEC71071_MASK)); 516 printf("%s: soft DMA state: %zd@%p%s%d\n", 517 device_xname(sc->sc_sbic.sc_dev), 518 sc->sc_dmalen, sc->sc_dmaaddr, sc->sc_dmain ? "<-" : "->", 519 sc->sc_dmaoff); 520 } 521 522 void sec_dumpall(void); /* Call from DDB */ 523 524 extern struct cfdriver sec_cd; 525 526 void sec_dumpall(void) 527 { 528 int i; 529 struct sec_softc *sc; 530 531 for (i = 0; i < sec_cd.cd_ndevs; ++i) { 532 sc = device_lookup_private(&sec_cd, i); 533 if (sc != NULL) 534 sec_dumpdma(sc); 535 } 536 } 537 #endif 538