1 /* $NetBSD: wstsc.c,v 1.19 1997/08/27 11:23:24 bouyer Exp $ */ 2 3 /* 4 * Copyright (c) 1994 Michael L. Hitch 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 * @(#)supradma.c 37 */ 38 #include <sys/param.h> 39 #include <sys/systm.h> 40 #include <sys/kernel.h> 41 #include <sys/device.h> 42 #include <dev/scsipi/scsi_all.h> 43 #include <dev/scsipi/scsipi_all.h> 44 #include <dev/scsipi/scsiconf.h> 45 #include <amiga/amiga/device.h> 46 #include <amiga/amiga/isr.h> 47 #include <amiga/dev/scireg.h> 48 #include <amiga/dev/scivar.h> 49 #include <amiga/dev/zbusvar.h> 50 51 void wstscattach __P((struct device *, struct device *, void *)); 52 int wstscmatch __P((struct device *, struct cfdata *, void *)); 53 54 int wstsc_dma_xfer_in __P((struct sci_softc *dev, int len, 55 register u_char *buf, int phase)); 56 int wstsc_dma_xfer_out __P((struct sci_softc *dev, int len, 57 register u_char *buf, int phase)); 58 int wstsc_dma_xfer_in2 __P((struct sci_softc *dev, int len, 59 register u_short *buf, int phase)); 60 int wstsc_dma_xfer_out2 __P((struct sci_softc *dev, int len, 61 register u_short *buf, int phase)); 62 int wstsc_intr __P((void *)); 63 64 struct scsipi_adapter wstsc_scsiswitch = { 65 sci_scsicmd, 66 sci_minphys, 67 0, /* no lun support */ 68 0, /* no lun support */ 69 }; 70 71 struct scsipi_device wstsc_scsidev = { 72 NULL, /* use default error handler */ 73 NULL, /* do not have a start functio */ 74 NULL, /* have no async handler */ 75 NULL, /* Use default done routine */ 76 }; 77 78 #ifdef DEBUG 79 extern int sci_debug; 80 #define QPRINTF(a) if (sci_debug > 1) printf a 81 #else 82 #define QPRINTF(a) 83 #endif 84 85 extern int sci_data_wait; 86 87 int supradma_pseudo = 0; /* 0=none, 1=byte, 2=word */ 88 89 struct cfattach wstsc_ca = { 90 sizeof(struct sci_softc), wstscmatch, wstscattach 91 }; 92 93 struct cfdriver wstsc_cd = { 94 NULL, "wstsc", DV_DULL, NULL, 0 95 }; 96 97 /* 98 * if this a Supra WordSync board 99 */ 100 int 101 wstscmatch(pdp, cfp, auxp) 102 struct device *pdp; 103 struct cfdata *cfp; 104 void *auxp; 105 { 106 struct zbus_args *zap; 107 108 zap = auxp; 109 110 /* 111 * Check manufacturer and product id. 112 */ 113 if (zap->manid == 1056 && ( 114 zap->prodid == 12 || /* WordSync */ 115 zap->prodid == 13)) /* ByteSync */ 116 return(1); 117 else 118 return(0); 119 } 120 121 void 122 wstscattach(pdp, dp, auxp) 123 struct device *pdp, *dp; 124 void *auxp; 125 { 126 volatile u_char *rp; 127 struct sci_softc *sc; 128 struct zbus_args *zap; 129 130 printf("\n"); 131 132 zap = auxp; 133 134 sc = (struct sci_softc *)dp; 135 rp = zap->va; 136 /* 137 * set up 5380 register pointers 138 * (Needs check on which Supra board this is - for now, 139 * just do the WordSync) 140 */ 141 sc->sci_data = rp + 0; 142 sc->sci_odata = rp + 0; 143 sc->sci_icmd = rp + 2; 144 sc->sci_mode = rp + 4; 145 sc->sci_tcmd = rp + 6; 146 sc->sci_bus_csr = rp + 8; 147 sc->sci_sel_enb = rp + 8; 148 sc->sci_csr = rp + 10; 149 sc->sci_dma_send = rp + 10; 150 sc->sci_idata = rp + 12; 151 sc->sci_trecv = rp + 12; 152 sc->sci_iack = rp + 14; 153 sc->sci_irecv = rp + 14; 154 155 if (supradma_pseudo == 2) { 156 sc->dma_xfer_in = (int(*)(struct sci_softc *, int, u_char *, int))wstsc_dma_xfer_in2; 157 sc->dma_xfer_out = (int(*)(struct sci_softc *, int, u_char *, int))wstsc_dma_xfer_out2; 158 } 159 else if (supradma_pseudo == 1) { 160 sc->dma_xfer_in = wstsc_dma_xfer_in; 161 sc->dma_xfer_out = wstsc_dma_xfer_out; 162 } 163 164 sc->sc_isr.isr_intr = wstsc_intr; 165 sc->sc_isr.isr_arg = sc; 166 sc->sc_isr.isr_ipl = 2; 167 add_isr(&sc->sc_isr); 168 169 scireset(sc); 170 171 sc->sc_link.scsipi_scsi.channel = SCSI_CHANNEL_ONLY_ONE; 172 sc->sc_link.adapter_softc = sc; 173 sc->sc_link.scsipi_scsi.adapter_target = 7; 174 sc->sc_link.adapter = &wstsc_scsiswitch; 175 sc->sc_link.device = &wstsc_scsidev; 176 sc->sc_link.openings = 1; 177 sc->sc_link.scsipi_scsi.max_target = 7; 178 sc->sc_link.type = BUS_SCSI; 179 TAILQ_INIT(&sc->sc_xslist); 180 181 /* 182 * attach all scsi units on us 183 */ 184 config_found(dp, &sc->sc_link, scsiprint); 185 } 186 187 int 188 wstsc_dma_xfer_in (dev, len, buf, phase) 189 struct sci_softc *dev; 190 int len; 191 register u_char *buf; 192 int phase; 193 { 194 int wait = sci_data_wait; 195 volatile register u_char *sci_dma = dev->sci_idata; 196 volatile register u_char *sci_csr = dev->sci_csr; 197 #ifdef DEBUG 198 u_char *obp = (u_char *) buf; 199 #endif 200 201 QPRINTF(("supradma_in %d, csr=%02x\n", len, *dev->sci_bus_csr)); 202 203 *dev->sci_tcmd = phase; 204 *dev->sci_icmd = 0; 205 *dev->sci_mode = SCI_MODE_DMA; 206 *dev->sci_irecv = 0; 207 208 while (len >= 128) { 209 wait = sci_data_wait; 210 while ((*sci_csr & (SCI_CSR_DREQ|SCI_CSR_PHASE_MATCH)) != 211 (SCI_CSR_DREQ|SCI_CSR_PHASE_MATCH)) { 212 if (!(*sci_csr & SCI_CSR_PHASE_MATCH) 213 || !(*dev->sci_bus_csr & SCI_BUS_BSY) 214 || --wait < 0) { 215 #ifdef DEBUG 216 if (sci_debug | 1) 217 printf("supradma2_in fail: l%d i%x w%d\n", 218 len, *dev->sci_bus_csr, wait); 219 #endif 220 *dev->sci_mode = 0; 221 return 0; 222 } 223 } 224 225 #define R1 (*buf++ = *sci_dma) 226 R1; R1; R1; R1; R1; R1; R1; R1; 227 R1; R1; R1; R1; R1; R1; R1; R1; 228 R1; R1; R1; R1; R1; R1; R1; R1; 229 R1; R1; R1; R1; R1; R1; R1; R1; 230 R1; R1; R1; R1; R1; R1; R1; R1; 231 R1; R1; R1; R1; R1; R1; R1; R1; 232 R1; R1; R1; R1; R1; R1; R1; R1; 233 R1; R1; R1; R1; R1; R1; R1; R1; 234 R1; R1; R1; R1; R1; R1; R1; R1; 235 R1; R1; R1; R1; R1; R1; R1; R1; 236 R1; R1; R1; R1; R1; R1; R1; R1; 237 R1; R1; R1; R1; R1; R1; R1; R1; 238 R1; R1; R1; R1; R1; R1; R1; R1; 239 R1; R1; R1; R1; R1; R1; R1; R1; 240 R1; R1; R1; R1; R1; R1; R1; R1; 241 R1; R1; R1; R1; R1; R1; R1; R1; 242 len -= 128; 243 } 244 245 while (len > 0) { 246 wait = sci_data_wait; 247 while ((*sci_csr & (SCI_CSR_DREQ|SCI_CSR_PHASE_MATCH)) != 248 (SCI_CSR_DREQ|SCI_CSR_PHASE_MATCH)) { 249 if (!(*sci_csr & SCI_CSR_PHASE_MATCH) 250 || !(*dev->sci_bus_csr & SCI_BUS_BSY) 251 || --wait < 0) { 252 #ifdef DEBUG 253 if (sci_debug | 1) 254 printf("supradma1_in fail: l%d i%x w%d\n", 255 len, *dev->sci_bus_csr, wait); 256 #endif 257 *dev->sci_mode = 0; 258 return 0; 259 } 260 } 261 262 *buf++ = *sci_dma; 263 len--; 264 } 265 266 QPRINTF(("supradma_in {%d} %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", 267 len, obp[0], obp[1], obp[2], obp[3], obp[4], obp[5], 268 obp[6], obp[7], obp[8], obp[9])); 269 270 *dev->sci_mode = 0; 271 return 0; 272 } 273 274 int 275 wstsc_dma_xfer_out (dev, len, buf, phase) 276 struct sci_softc *dev; 277 int len; 278 register u_char *buf; 279 int phase; 280 { 281 int wait = sci_data_wait; 282 volatile register u_char *sci_dma = dev->sci_data; 283 volatile register u_char *sci_csr = dev->sci_csr; 284 285 QPRINTF(("supradma_out %d, csr=%02x\n", len, *dev->sci_bus_csr)); 286 287 QPRINTF(("supradma_out {%d} %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", 288 len, buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], 289 buf[6], buf[7], buf[8], buf[9])); 290 291 *dev->sci_tcmd = phase; 292 *dev->sci_mode = SCI_MODE_DMA; 293 *dev->sci_icmd = SCI_ICMD_DATA; 294 *dev->sci_dma_send = 0; 295 while (len > 0) { 296 wait = sci_data_wait; 297 while ((*sci_csr & (SCI_CSR_DREQ|SCI_CSR_PHASE_MATCH)) != 298 (SCI_CSR_DREQ|SCI_CSR_PHASE_MATCH)) { 299 if (!(*sci_csr & SCI_CSR_PHASE_MATCH) 300 || !(*dev->sci_bus_csr & SCI_BUS_BSY) 301 || --wait < 0) { 302 #ifdef DEBUG 303 if (sci_debug) 304 printf("supradma_out fail: l%d i%x w%d\n", 305 len, *dev->sci_bus_csr, wait); 306 #endif 307 *dev->sci_mode = 0; 308 return 0; 309 } 310 } 311 312 *sci_dma = *buf++; 313 len--; 314 } 315 316 wait = sci_data_wait; 317 while ((*sci_csr & (SCI_CSR_DREQ|SCI_CSR_PHASE_MATCH)) == 318 SCI_CSR_PHASE_MATCH && --wait); 319 320 321 *dev->sci_mode = 0; 322 *dev->sci_icmd = 0; 323 return 0; 324 } 325 326 327 int 328 wstsc_dma_xfer_in2 (dev, len, buf, phase) 329 struct sci_softc *dev; 330 int len; 331 register u_short *buf; 332 int phase; 333 { 334 volatile register u_short *sci_dma = (u_short *)(dev->sci_idata + 0x10); 335 volatile register u_char *sci_csr = dev->sci_csr + 0x10; 336 #ifdef DEBUG 337 u_char *obp = (u_char *) buf; 338 #endif 339 #if 0 340 int wait = sci_data_wait; 341 #endif 342 343 QPRINTF(("supradma_in2 %d, csr=%02x\n", len, *dev->sci_bus_csr)); 344 345 *dev->sci_tcmd = phase; 346 *dev->sci_mode = SCI_MODE_DMA; 347 *dev->sci_icmd = 0; 348 *(dev->sci_irecv + 16) = 0; 349 while (len >= 128) { 350 #if 0 351 wait = sci_data_wait; 352 while ((*sci_csr & (SCI_CSR_DREQ|SCI_CSR_PHASE_MATCH)) != 353 (SCI_CSR_DREQ|SCI_CSR_PHASE_MATCH)) { 354 if (!(*sci_csr & SCI_CSR_PHASE_MATCH) 355 || !(*dev->sci_bus_csr & SCI_BUS_BSY) 356 || --wait < 0) { 357 #ifdef DEBUG 358 if (sci_debug | 1) 359 printf("supradma2_in2 fail: l%d i%x w%d\n", 360 len, *dev->sci_bus_csr, wait); 361 #endif 362 *dev->sci_mode &= ~SCI_MODE_DMA; 363 return 0; 364 } 365 } 366 #else 367 while (!(*sci_csr & SCI_CSR_DREQ)) 368 ; 369 #endif 370 371 #define R2 (*buf++ = *sci_dma) 372 R2; R2; R2; R2; R2; R2; R2; R2; 373 R2; R2; R2; R2; R2; R2; R2; R2; 374 R2; R2; R2; R2; R2; R2; R2; R2; 375 R2; R2; R2; R2; R2; R2; R2; R2; 376 R2; R2; R2; R2; R2; R2; R2; R2; 377 R2; R2; R2; R2; R2; R2; R2; R2; 378 R2; R2; R2; R2; R2; R2; R2; R2; 379 R2; R2; R2; R2; R2; R2; R2; R2; 380 len -= 128; 381 } 382 while (len > 0) { 383 #if 0 384 wait = sci_data_wait; 385 while ((*sci_csr & (SCI_CSR_DREQ|SCI_CSR_PHASE_MATCH)) != 386 (SCI_CSR_DREQ|SCI_CSR_PHASE_MATCH)) { 387 if (!(*sci_csr & SCI_CSR_PHASE_MATCH) 388 || !(*dev->sci_bus_csr & SCI_BUS_BSY) 389 || --wait < 0) { 390 #ifdef DEBUG 391 if (sci_debug | 1) 392 printf("supradma1_in2 fail: l%d i%x w%d\n", 393 len, *dev->sci_bus_csr, wait); 394 #endif 395 *dev->sci_mode &= ~SCI_MODE_DMA; 396 return 0; 397 } 398 } 399 #else 400 while (!(*sci_csr * SCI_CSR_DREQ)) 401 ; 402 #endif 403 404 *buf++ = *sci_dma; 405 len -= 2; 406 } 407 408 QPRINTF(("supradma_in2 {%d} %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", 409 len, obp[0], obp[1], obp[2], obp[3], obp[4], obp[5], 410 obp[6], obp[7], obp[8], obp[9])); 411 412 *dev->sci_irecv = 0; 413 *dev->sci_mode = 0; 414 return 0; 415 } 416 417 int 418 wstsc_dma_xfer_out2 (dev, len, buf, phase) 419 struct sci_softc *dev; 420 int len; 421 register u_short *buf; 422 int phase; 423 { 424 volatile register u_short *sci_dma = (ushort *)(dev->sci_data + 0x10); 425 volatile register u_char *sci_bus_csr = dev->sci_bus_csr; 426 #ifdef DEBUG 427 u_char *obp = (u_char *) buf; 428 #endif 429 #if 0 430 int wait = sci_data_wait; 431 #endif 432 433 QPRINTF(("supradma_out2 %d, csr=%02x\n", len, *dev->sci_bus_csr)); 434 435 QPRINTF(("supradma_out2 {%d} %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", 436 len, obp[0], obp[1], obp[2], obp[3], obp[4], obp[5], 437 obp[6], obp[7], obp[8], obp[9])); 438 439 *dev->sci_tcmd = phase; 440 *dev->sci_mode = SCI_MODE_DMA; 441 *dev->sci_icmd = SCI_ICMD_DATA; 442 *dev->sci_dma_send = 0; 443 while (len > 64) { 444 #if 0 445 wait = sci_data_wait; 446 while ((*sci_csr & (SCI_CSR_DREQ|SCI_CSR_PHASE_MATCH)) != 447 (SCI_CSR_DREQ|SCI_CSR_PHASE_MATCH)) { 448 if (!(*sci_csr & SCI_CSR_PHASE_MATCH) 449 || !(*dev->sci_bus_csr & SCI_BUS_BSY) 450 || --wait < 0) { 451 #ifdef DEBUG 452 if (sci_debug) 453 printf("supradma_out2 fail: l%d i%x w%d\n", 454 len, csr, wait); 455 #endif 456 *dev->sci_mode = 0; 457 return 0; 458 } 459 } 460 #else 461 *dev->sci_mode = 0; 462 *dev->sci_icmd &= ~SCI_ICMD_ACK; 463 while (!(*sci_bus_csr & SCI_BUS_REQ)) 464 ; 465 *dev->sci_mode = SCI_MODE_DMA; 466 *dev->sci_dma_send = 0; 467 #endif 468 469 #define W2 (*sci_dma = *buf++) 470 W2; W2; W2; W2; W2; W2; W2; W2; 471 W2; W2; W2; W2; W2; W2; W2; W2; 472 if (*(sci_bus_csr + 0x10) & SCI_BUS_REQ) 473 ; 474 len -= 64; 475 } 476 477 while (len > 0) { 478 #if 0 479 wait = sci_data_wait; 480 while ((*sci_csr & (SCI_CSR_DREQ|SCI_CSR_PHASE_MATCH)) != 481 (SCI_CSR_DREQ|SCI_CSR_PHASE_MATCH)) { 482 if (!(*sci_csr & SCI_CSR_PHASE_MATCH) 483 || !(*dev->sci_bus_csr & SCI_BUS_BSY) 484 || --wait < 0) { 485 #ifdef DEBUG 486 if (sci_debug) 487 printf("supradma_out2 fail: l%d i%x w%d\n", 488 len, csr, wait); 489 #endif 490 *dev->sci_mode = 0; 491 return 0; 492 } 493 } 494 #else 495 *dev->sci_mode = 0; 496 *dev->sci_icmd &= ~SCI_ICMD_ACK; 497 while (!(*sci_bus_csr & SCI_BUS_REQ)) 498 ; 499 *dev->sci_mode = SCI_MODE_DMA; 500 *dev->sci_dma_send = 0; 501 #endif 502 503 *sci_dma = *buf++; 504 if (*(sci_bus_csr + 0x10) & SCI_BUS_REQ) 505 ; 506 len -= 2; 507 } 508 509 #if 0 510 wait = sci_data_wait; 511 while ((*sci_csr & (SCI_CSR_DREQ|SCI_CSR_PHASE_MATCH)) == 512 SCI_CSR_PHASE_MATCH && --wait); 513 #endif 514 515 516 *dev->sci_irecv = 0; 517 *dev->sci_icmd &= ~SCI_ICMD_ACK; 518 *dev->sci_mode = 0; 519 *dev->sci_icmd = 0; 520 return 0; 521 } 522 523 int 524 wstsc_intr(arg) 525 void *arg; 526 { 527 struct sci_softc *dev = arg; 528 u_char stat; 529 530 if ((*(dev->sci_csr + 0x10) & SCI_CSR_INT) == 0) 531 return (0); 532 stat = *(dev->sci_iack + 0x10); 533 return (1); 534 } 535