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