1 /* $NetBSD: si.c,v 1.15 1995/03/26 19:23:12 gwr Exp $ */ 2 3 /* 4 * Copyright (C) 1994 Adam Glass, Gordon W. Ross 5 * Copyright (C) 1993 Allen K. Briggs, Chris P. Caputo, 6 * Michael L. Finch, Bradley A. Grantham, and 7 * Lawrence A. Kesteloot 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 Alice Group. 21 * 4. The names of the Alice Group or any of its members may not be used 22 * to endorse or promote products derived from this software without 23 * specific prior written permission. 24 * 25 * THIS SOFTWARE IS PROVIDED BY THE ALICE GROUP ``AS IS'' AND ANY EXPRESS OR 26 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 27 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 28 * IN NO EVENT SHALL THE ALICE GROUP BE LIABLE FOR ANY DIRECT, INDIRECT, 29 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 30 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 31 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 32 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 33 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 34 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 35 */ 36 37 #define DEBUG 1 38 39 /* XXX - Need to add support for real DMA. -gwr */ 40 /* #define PSEUDO_DMA 1 (broken) */ 41 42 #include <sys/types.h> 43 #include <sys/malloc.h> 44 #include <sys/param.h> 45 #include <sys/systm.h> 46 #include <sys/errno.h> 47 #include <sys/buf.h> 48 #include <sys/proc.h> 49 #include <sys/user.h> 50 #include <sys/device.h> 51 52 #include <machine/autoconf.h> 53 #include <machine/isr.h> 54 #include <machine/obio.h> 55 56 #include <scsi/scsi_all.h> 57 #include <scsi/scsi_debug.h> 58 #include <scsi/scsiconf.h> 59 60 #include "scsi_defs.h" 61 #include "scsi_5380.h" 62 #include "scsi_sunsi.h" 63 64 #ifdef DEBUG 65 static int si_debug = 0; 66 static int si_flags = 0 /* | SDEV_DB2 */ ; 67 #endif 68 69 #define SCI_PHASE_DISC 0 /* sort of ... */ 70 #define SCI_CLR_INTR(regs) ((volatile)(regs->sci_iack)) 71 #define SCI_ACK(ptr,phase) (ptr)->sci_tcmd = (phase) 72 #define SCSI_TIMEOUT_VAL 10000000 73 #define WAIT_FOR_NOT_REQ(ptr) { \ 74 int scsi_timeout = SCSI_TIMEOUT_VAL; \ 75 while ( ((ptr)->sci_bus_csr & SCI_BUS_REQ) && \ 76 ((ptr)->sci_bus_csr & SCI_BUS_REQ) && \ 77 ((ptr)->sci_bus_csr & SCI_BUS_REQ) && \ 78 (--scsi_timeout) ); \ 79 if (!scsi_timeout) { \ 80 printf("scsi timeout--WAIT_FOR_NOT_REQ---%s, line %d.\n", \ 81 __FILE__, __LINE__); \ 82 goto scsi_timeout_error; \ 83 } \ 84 } 85 #define WAIT_FOR_REQ(ptr) { \ 86 int scsi_timeout = SCSI_TIMEOUT_VAL; \ 87 while ( (((ptr)->sci_bus_csr & SCI_BUS_REQ) == 0) && \ 88 (((ptr)->sci_bus_csr & SCI_BUS_REQ) == 0) && \ 89 (((ptr)->sci_bus_csr & SCI_BUS_REQ) == 0) && \ 90 (--scsi_timeout) ); \ 91 if (!scsi_timeout) { \ 92 printf("scsi timeout--WAIT_FOR_REQ---%s, line %d.\n", \ 93 __FILE__, __LINE__); \ 94 goto scsi_timeout_error; \ 95 } \ 96 } 97 #define WAIT_FOR_BSY(ptr) { \ 98 int scsi_timeout = SCSI_TIMEOUT_VAL; \ 99 while ( (((ptr)->sci_bus_csr & SCI_BUS_BSY) == 0) && \ 100 (((ptr)->sci_bus_csr & SCI_BUS_BSY) == 0) && \ 101 (((ptr)->sci_bus_csr & SCI_BUS_BSY) == 0) && \ 102 (--scsi_timeout) ); \ 103 if (!scsi_timeout) { \ 104 printf("scsi timeout--WAIT_FOR_BSY---%s, line %d.\n", \ 105 __FILE__, __LINE__); \ 106 goto scsi_timeout_error; \ 107 } \ 108 } 109 110 #define ARBITRATION_RETRIES 1000 111 112 #ifdef DDB 113 int Debugger(); 114 #else 115 #define Debugger() panic("Should call Debugger here %s:%d", \ 116 __FILE__, __LINE__) 117 #endif 118 119 struct ncr5380_softc { 120 struct device sc_dev; 121 volatile void *sc_regs; 122 int sc_adapter_type; 123 struct scsi_link sc_link; 124 }; 125 126 static void ncr5380_minphys(struct buf *bp); 127 static int ncr5380_scsi_cmd(struct scsi_xfer *xs); 128 static int ncr5380_reset_adapter(struct ncr5380_softc *); 129 static int ncr5380_reset_scsibus(struct ncr5380_softc *); 130 static int ncr5380_poll(int adapter, int timeout); 131 static int ncr5380_send_cmd(struct scsi_xfer *xs); 132 133 static int ncr_intr(void *); 134 135 static int si_generic(int adapter, int id, int lun, 136 struct scsi_generic *cmd, int cmdlen, 137 void *databuf, int datalen); 138 static int si_group0(int adapter, int id, int lun, 139 int opcode, int addr, int len, 140 int flags, caddr_t databuf, int datalen); 141 142 static char scsi_name[] = "si"; 143 144 struct scsi_adapter ncr5380_switch = { 145 ncr5380_scsi_cmd, /* scsi_cmd() */ 146 ncr5380_minphys, /* scsi_minphys() */ 147 NULL, /* open_target_lu() */ 148 NULL, /* close_target_lu() */ 149 }; 150 151 /* This is copied from julian's bt driver */ 152 /* "so we have a default dev struct for our link struct." */ 153 struct scsi_device ncr_dev = { 154 NULL, /* Use default error handler. */ 155 NULL, /* Use default start handler. */ 156 NULL, /* Use default async handler. */ 157 NULL, /* Use default "done" routine. */ 158 }; 159 160 static int si_match(); 161 static void si_attach(); 162 163 struct cfdriver sicd = { 164 NULL, "si", si_match, si_attach, DV_DULL, 165 sizeof(struct ncr5380_softc), NULL, 0, 166 }; 167 168 static int 169 si_print(aux, name) 170 void *aux; 171 char *name; 172 { 173 } 174 175 static int 176 si_match(parent, vcf, args) 177 struct device *parent; 178 void *vcf, *args; 179 { 180 struct cfdata *cf = vcf; 181 struct confargs *ca = args; 182 int x; 183 184 /* Allow default address for OBIO only. */ 185 switch (ca->ca_bustype) { 186 case BUS_OBIO: 187 if (ca->ca_paddr == -1) 188 ca->ca_paddr = OBIO_NCR_SCSI; 189 break; 190 case BUS_VME16: 191 if (ca->ca_paddr == -1) 192 return (0); 193 break; 194 default: 195 return (0); 196 } 197 198 /* Default interrupt priority always splbio==2 */ 199 if (ca->ca_intpri == -1) 200 ca->ca_intpri = 2; 201 202 x = bus_peek(ca->ca_bustype, ca->ca_paddr + 1, 1); 203 return (x != -1); 204 } 205 206 static void 207 si_attach(parent, self, args) 208 struct device *parent, *self; 209 void *args; 210 { 211 struct ncr5380_softc *ncr5380 = (struct ncr5380_softc *) self; 212 volatile sci_regmap_t *regs; 213 struct confargs *ca = args; 214 215 switch (ca->ca_bustype) { 216 217 case BUS_OBIO: 218 regs = (sci_regmap_t *) 219 obio_alloc(ca->ca_paddr, sizeof(*regs)); 220 isr_add_autovect(ncr_intr, (void *)ncr5380, 221 ca->ca_intpri); 222 break; 223 224 case BUS_VME16: 225 regs = (sci_regmap_t *) 226 bus_mapin(ca->ca_bustype, ca->ca_paddr, sizeof(*regs)); 227 isr_add_vectored(ncr_intr, (void *)ncr5380, 228 ca->ca_intpri, ca->ca_intvec); 229 break; 230 231 default: 232 printf("unknown\n"); 233 return; 234 } 235 236 ncr5380->sc_adapter_type = ca->ca_bustype; 237 ncr5380->sc_regs = regs; 238 239 /* 240 * fill in the prototype scsi_link. 241 */ 242 ncr5380->sc_link.adapter_softc = ncr5380; 243 ncr5380->sc_link.adapter_target = 7; 244 ncr5380->sc_link.adapter = &ncr5380_switch; 245 ncr5380->sc_link.device = &ncr_dev; 246 ncr5380->sc_link.openings = 2; 247 #ifdef DEBUG 248 ncr5380->sc_link.flags |= si_flags; 249 #endif 250 251 printf("\n"); 252 ncr5380_reset_adapter(ncr5380); 253 ncr5380_reset_scsibus(ncr5380); 254 config_found(self, &(ncr5380->sc_link), si_print); 255 } 256 257 #define MIN_PHYS 65536 /*BARF!!!!*/ 258 static void 259 ncr5380_minphys(struct buf *bp) 260 { 261 if (bp->b_bcount > MIN_PHYS) { 262 printf("Uh-oh... ncr5380_minphys setting bp->b_bcount = %x.\n", MIN_PHYS); 263 bp->b_bcount = MIN_PHYS; 264 } 265 } 266 #undef MIN_PHYS 267 268 static int 269 ncr5380_scsi_cmd(struct scsi_xfer *xs) 270 { 271 int flags, s, r; 272 273 flags = xs->flags; 274 if (xs->bp) flags |= (SCSI_NOSLEEP); 275 if ( flags & ITSDONE ) { 276 printf("Already done?"); 277 xs->flags &= ~ITSDONE; 278 } 279 if ( ! ( flags & INUSE ) ) { 280 printf("Not in use?"); 281 xs->flags |= INUSE; 282 } 283 284 s = splbio(); 285 286 if ( flags & SCSI_RESET ) { 287 printf("flags & SCSIRESET.\n"); 288 ncr5380_reset_scsibus(xs->sc_link->adapter_softc); 289 r = COMPLETE; 290 } else { 291 r = ncr5380_send_cmd(xs); 292 xs->flags |= ITSDONE; 293 scsi_done(xs); 294 } 295 296 splx(s); 297 298 switch(r) { 299 case COMPLETE: 300 case SUCCESSFULLY_QUEUED: 301 r = SUCCESSFULLY_QUEUED; 302 if (xs->flags & SCSI_POLL) 303 r = COMPLETE; 304 break; 305 default: 306 break; 307 } 308 return r; 309 } 310 311 #ifdef DEBUG 312 static int 313 ncr5380_show_scsi_cmd(struct scsi_xfer *xs) 314 { 315 u_char *b = (u_char *) xs->cmd; 316 int i = 0; 317 318 if ( ! ( xs->flags & SCSI_RESET ) ) { 319 printf("si(%d:%d:%d)-", 320 xs->sc_link->scsibus, 321 xs->sc_link->target, 322 xs->sc_link->lun); 323 while (i < xs->cmdlen) { 324 if (i) printf(","); 325 printf("%x",b[i++]); 326 } 327 printf("-\n"); 328 } else { 329 printf("si(%d:%d:%d)-RESET-\n", 330 xs->sc_link->scsibus, 331 xs->sc_link->target, 332 xs->sc_link->lun); 333 } 334 } 335 #endif 336 337 /* 338 * Actual chip control. 339 */ 340 341 static void 342 ncr_sbc_intr(struct ncr5380_softc *ncr5380) 343 { 344 volatile sci_regmap_t *regs = ncr5380->sc_regs; 345 346 if ((regs->sci_csr & SCI_CSR_INT) == 0) { 347 #ifdef DEBUG 348 printf (" ncr_sbc_intr: spurrious\n"); 349 #endif 350 return; 351 } 352 353 SCI_CLR_INTR(regs); 354 #ifdef DEBUG 355 printf (" ncr_sbc_intr\n"); 356 #endif 357 } 358 359 static void 360 ncr_dma_intr(struct ncr5380_softc *ncr5380) 361 { 362 volatile struct si_regs *regs = ncr5380->sc_regs; 363 364 #ifdef DEBUG 365 printf (" ncr_dma_intr\n"); 366 #endif 367 } 368 369 static int 370 ncr_intr(void *arg) 371 { 372 struct ncr5380_softc *ncr5380 = arg; 373 volatile struct si_regs *si = ncr5380->sc_regs; 374 int rv = 0; 375 376 /* Interrupts not enabled? Can not be for us. */ 377 if ((si->si_csr & SI_CSR_INTR_EN) == 0) 378 return rv; 379 380 if (si->si_csr & SI_CSR_DMA_IP) { 381 ncr_dma_intr(ncr5380); 382 rv++; 383 } 384 if (si->si_csr & SI_CSR_SBC_IP) { 385 ncr_sbc_intr(ncr5380); 386 rv++; 387 } 388 return rv; 389 } 390 391 static int 392 ncr5380_reset_adapter(struct ncr5380_softc *ncr5380) 393 { 394 volatile struct si_regs *si = ncr5380->sc_regs; 395 396 #ifdef DEBUG 397 if (si_debug) { 398 printf("si_reset_adapter\n"); 399 } 400 #endif 401 402 /* The reset bits are active low. */ 403 si->si_csr = 0; 404 delay(100); 405 si->si_csr = SI_CSR_FIFO_RES | SI_CSR_SCSI_RES; 406 } 407 408 static int 409 ncr5380_reset_scsibus(struct ncr5380_softc *ncr5380) 410 { 411 volatile sci_regmap_t *regs = ncr5380->sc_regs; 412 413 #ifdef DEBUG 414 if (si_debug) { 415 printf("si_reset_scsibus\n"); 416 } 417 #endif 418 419 regs->sci_icmd = SCI_ICMD_TEST; 420 regs->sci_icmd = SCI_ICMD_TEST | SCI_ICMD_RST; 421 delay(2500); 422 regs->sci_icmd = 0; 423 424 regs->sci_mode = 0; 425 regs->sci_tcmd = SCI_PHASE_DISC; 426 regs->sci_sel_enb = 0; 427 428 SCI_CLR_INTR(regs); 429 SCI_CLR_INTR(regs); 430 } 431 432 static int 433 ncr5380_poll(int adapter, int timeout) 434 { 435 } 436 437 static int 438 ncr5380_send_cmd(struct scsi_xfer *xs) 439 { 440 int sense; 441 442 #ifdef DIAGNOSTIC 443 if ((getsr() & PSL_IPL) < PSL_IPL2) 444 panic("ncr_send_cmd: bad spl"); 445 #endif 446 447 #ifdef DEBUG 448 if (si_debug & 2) 449 ncr5380_show_scsi_cmd(xs); 450 #endif 451 452 sense = si_generic( xs->sc_link->scsibus, xs->sc_link->target, 453 xs->sc_link->lun, xs->cmd, xs->cmdlen, 454 xs->data, xs->datalen ); 455 456 switch (sense) { 457 case 0: /* success */ 458 xs->resid = 0; 459 xs->error = XS_NOERROR; 460 break; 461 462 case 0x02: /* Check condition */ 463 #ifdef DEBUG 464 if (si_debug) 465 printf("check cond. target %d.\n", 466 xs->sc_link->target); 467 #endif 468 delay(10); /* Phil's fix for slow devices. */ 469 si_group0(xs->sc_link->scsibus, 470 xs->sc_link->target, 471 xs->sc_link->lun, 472 0x3, 0x0, 473 sizeof(struct scsi_sense_data), 474 0, (caddr_t) &(xs->sense), 475 sizeof(struct scsi_sense_data)); 476 xs->error = XS_SENSE; 477 break; 478 case 0x08: /* Busy */ 479 xs->error = XS_BUSY; 480 break; 481 default: 482 xs->error = XS_DRIVER_STUFFUP; 483 break; 484 485 } 486 return (COMPLETE); 487 } 488 489 static int 490 si_select_target(register volatile sci_regmap_t *regs, 491 u_char myid, u_char tid, int with_atn) 492 { 493 register u_char bid, icmd; 494 int ret = SCSI_RET_RETRY; 495 int arb_retries, arb_wait; 496 497 /* for our purposes.. */ 498 myid = 1 << myid; 499 tid = 1 << tid; 500 501 regs->sci_sel_enb = 0; /* we don't want any interrupts. */ 502 regs->sci_tcmd = 0; /* get into a harmless state */ 503 504 arb_retries = ARBITRATION_RETRIES; 505 506 retry_arbitration: 507 regs->sci_mode = 0; /* get into a harmless state */ 508 if (--arb_retries <= 0) { 509 #ifdef DEBUG 510 if (si_debug) { 511 printf("si_select: arb_retries expended\n"); 512 } 513 #endif 514 goto lost; 515 } 516 517 if ((regs->sci_bus_csr & (SCI_BUS_BSY|SCI_BUS_SEL)) && 518 (regs->sci_bus_csr & (SCI_BUS_BSY|SCI_BUS_SEL)) && 519 (regs->sci_bus_csr & (SCI_BUS_BSY|SCI_BUS_SEL))) 520 { 521 #ifdef DEBUG 522 if (si_debug) { 523 printf("si_select_target: still BSY|SEL\n"); 524 } 525 #endif 526 return ret; 527 } 528 529 regs->sci_odata = myid; 530 regs->sci_mode = SCI_MODE_ARB; 531 /* regs->sci_mode |= SCI_MODE_ARB; XXX? */ 532 533 /* AIP might not set if BSY went true after we checked */ 534 /* Wait up to about 100 usec. for it to appear. */ 535 arb_wait = 50; /* X2 */ 536 do { 537 if (regs->sci_icmd & SCI_ICMD_AIP) 538 break; 539 delay2us(); 540 } while (--arb_wait > 0); 541 if (arb_wait <= 0) { 542 /* XXX - Could have missed it? */ 543 goto retry_arbitration; 544 } 545 #ifdef DEBUG 546 if (si_debug) { 547 printf("si_select_target: API after %d tries (last wait %d)\n", 548 ARBITRATION_RETRIES - arb_retries, 549 (50 - arb_wait)); 550 } 551 #endif 552 553 delay(3); /* 2.2 uSec. arbitration delay */ 554 555 if (regs->sci_icmd & SCI_ICMD_LST) { 556 #ifdef DEBUG 557 if (si_debug) 558 printf ("lost 1\n"); 559 #endif 560 goto retry_arbitration; /* XXX */ 561 } 562 563 regs->sci_mode &= ~SCI_MODE_PAR_CHK; 564 bid = regs->sci_data; 565 566 if ((bid & ~myid) > myid) { 567 #ifdef DEBUG 568 if (si_debug) 569 printf ("lost 2\n"); 570 #endif 571 /* Trying again will not help. */ 572 goto lost; 573 } 574 if (regs->sci_icmd & SCI_ICMD_LST) { 575 #ifdef DEBUG 576 if (si_debug) 577 printf ("lost 3\n"); 578 #endif 579 goto lost; 580 } 581 582 /* Won arbitration, enter selection phase now */ 583 icmd = regs->sci_icmd & ~(SCI_ICMD_DIFF|SCI_ICMD_TEST); 584 icmd |= (with_atn ? (SCI_ICMD_SEL|SCI_ICMD_ATN) : SCI_ICMD_SEL); 585 regs->sci_icmd = icmd; 586 587 if (regs->sci_icmd & SCI_ICMD_LST) { 588 #ifdef DEBUG 589 if (si_debug) 590 printf ("nosel\n"); 591 #endif 592 goto nosel; 593 } 594 595 /* XXX a target that violates specs might still drive the bus XXX */ 596 /* XXX should put our id out, and after the delay check nothi XXX */ 597 /* XXX ng else is out there. XXX */ 598 599 delay2us(); 600 601 regs->sci_sel_enb = 0; 602 603 regs->sci_odata = myid | tid; 604 605 icmd |= SCI_ICMD_BSY|SCI_ICMD_DATA; 606 regs->sci_icmd = icmd; 607 608 /* regs->sci_mode &= ~SCI_MODE_ARB; 2 deskew delays, too */ 609 regs->sci_mode = 0; /* 2 deskew delays, too */ 610 611 icmd &= ~SCI_ICMD_BSY; 612 regs->sci_icmd = icmd; 613 614 /* bus settle delay, 400ns */ 615 delay2us(); /* too much (was 2) ? */ 616 617 regs->sci_mode |= SCI_MODE_PAR_CHK; 618 619 { 620 register int timeo = 2500;/* 250 msecs in 100 usecs chunks */ 621 while ((regs->sci_bus_csr & SCI_BUS_BSY) == 0) { 622 if (--timeo > 0) { 623 delay(100); 624 } else { 625 /* This is the "normal" no-such-device select error. */ 626 #ifdef DEBUG 627 if (si_debug) 628 printf("si_select: did not see BSY\n"); 629 #endif 630 goto nodev; 631 } 632 } 633 } 634 635 icmd &= ~(SCI_ICMD_DATA|SCI_ICMD_SEL); 636 regs->sci_icmd = icmd; 637 /* regs->sci_sel_enb = myid;*/ /* looks like we should NOT have it */ 638 /* XXX - SCI_MODE_PAR_CHK ? */ 639 return SCSI_RET_SUCCESS; 640 641 nodev: 642 ret = SCSI_RET_DEVICE_DOWN; 643 regs->sci_sel_enb = myid; 644 nosel: 645 icmd &= ~(SCI_ICMD_DATA|SCI_ICMD_SEL|SCI_ICMD_ATN); 646 regs->sci_icmd = icmd; 647 regs->sci_mode = 0; 648 return ret; 649 650 lost: 651 regs->sci_icmd = 0; 652 regs->sci_mode = 0; 653 #ifdef DEBUG 654 if (si_debug) { 655 printf("si_select: lost arbitration\n"); 656 } 657 #endif 658 return ret; 659 } 660 661 sci_data_out(regs, phase, count, data) 662 register volatile sci_regmap_t *regs; 663 unsigned char *data; 664 { 665 register unsigned char icmd; 666 register int cnt=0; 667 668 /* ..checks.. */ 669 670 icmd = regs->sci_icmd & ~(SCI_ICMD_DIFF|SCI_ICMD_TEST); 671 loop: 672 if (SCI_CUR_PHASE(regs->sci_bus_csr) != phase) 673 return cnt; 674 675 WAIT_FOR_REQ(regs); 676 icmd |= SCI_ICMD_DATA; 677 regs->sci_icmd = icmd; 678 regs->sci_odata = *data++; 679 icmd |= SCI_ICMD_ACK; 680 regs->sci_icmd = icmd; 681 682 icmd &= ~(SCI_ICMD_DATA|SCI_ICMD_ACK); 683 WAIT_FOR_NOT_REQ(regs); 684 regs->sci_icmd = icmd; 685 ++cnt; 686 if (--count > 0) 687 goto loop; 688 scsi_timeout_error: 689 return cnt; 690 } 691 692 sci_data_in(regs, phase, count, data) 693 register volatile sci_regmap_t *regs; 694 unsigned char *data; 695 { 696 register unsigned char icmd; 697 register int cnt=0; 698 699 /* ..checks.. */ 700 701 icmd = regs->sci_icmd & ~(SCI_ICMD_DIFF|SCI_ICMD_TEST); 702 703 loop: 704 if (SCI_CUR_PHASE(regs->sci_bus_csr) != phase) 705 return cnt; 706 707 WAIT_FOR_REQ(regs); 708 *data++ = regs->sci_data; 709 icmd |= SCI_ICMD_ACK; 710 regs->sci_icmd = icmd; 711 712 icmd &= ~SCI_ICMD_ACK; 713 WAIT_FOR_NOT_REQ(regs); 714 regs->sci_icmd = icmd; 715 ++cnt; 716 if (--count > 0) 717 goto loop; 718 719 scsi_timeout_error: 720 return cnt; 721 } 722 723 static int 724 si_command_transfer(register volatile sci_regmap_t *regs, 725 int maxlen, u_char *data, u_char *status, u_char *msg) 726 { 727 int xfer=0, phase; 728 729 /* printf("command_transfer called for 0x%x.\n", *data); */ 730 731 regs->sci_icmd = 0; 732 733 while (1) { 734 735 WAIT_FOR_REQ(regs); 736 737 phase = SCI_CUR_PHASE(regs->sci_bus_csr); 738 739 switch (phase) { 740 case SCSI_PHASE_CMD: 741 SCI_ACK(regs,SCSI_PHASE_CMD); 742 xfer += sci_data_out(regs, SCSI_PHASE_CMD, 743 maxlen, data); 744 return xfer; 745 case SCSI_PHASE_DATA_IN: 746 printf("Data in phase in command_transfer?\n"); 747 return 0; 748 case SCSI_PHASE_DATA_OUT: 749 printf("Data out phase in command_transfer?\n"); 750 return 0; 751 case SCSI_PHASE_STATUS: 752 SCI_ACK(regs,SCSI_PHASE_STATUS); 753 printf("status in command_transfer.\n"); 754 sci_data_in(regs, SCSI_PHASE_STATUS, 755 1, status); 756 break; 757 case SCSI_PHASE_MESSAGE_IN: 758 SCI_ACK(regs,SCSI_PHASE_MESSAGE_IN); 759 printf("msgin in command_transfer.\n"); 760 sci_data_in(regs, SCSI_PHASE_MESSAGE_IN, 761 1, msg); 762 break; 763 case SCSI_PHASE_MESSAGE_OUT: 764 SCI_ACK(regs,SCSI_PHASE_MESSAGE_OUT); 765 sci_data_out(regs, SCSI_PHASE_MESSAGE_OUT, 766 1, msg); 767 break; 768 default: 769 printf("Unexpected phase 0x%x in " 770 "command_transfer().\n", phase); 771 scsi_timeout_error: 772 return xfer; 773 break; 774 } 775 } 776 } 777 778 static int 779 si_data_transfer(register volatile sci_regmap_t *regs, 780 int maxlen, u_char *data, u_char *status, u_char *msg) 781 { 782 int retlen = 0, xfer, phase; 783 784 regs->sci_icmd = 0; 785 786 *status = 0; 787 788 while (1) { 789 790 WAIT_FOR_REQ(regs); 791 792 phase = SCI_CUR_PHASE(regs->sci_bus_csr); 793 794 switch (phase) { 795 case SCSI_PHASE_CMD: 796 printf("Command phase in data_transfer().\n"); 797 return retlen; 798 case SCSI_PHASE_DATA_IN: 799 SCI_ACK(regs,SCSI_PHASE_DATA_IN); 800 #if PSEUDO_DMA 801 xfer = sci_pdma_in(regs, SCSI_PHASE_DATA_IN, 802 maxlen, data); 803 #else 804 xfer = sci_data_in(regs, SCSI_PHASE_DATA_IN, 805 maxlen, data); 806 #endif 807 retlen += xfer; 808 maxlen -= xfer; 809 break; 810 case SCSI_PHASE_DATA_OUT: 811 SCI_ACK(regs,SCSI_PHASE_DATA_OUT); 812 #if PSEUDO_DMA 813 xfer = sci_pdma_out(regs, SCSI_PHASE_DATA_OUT, 814 maxlen, data); 815 #else 816 xfer = sci_data_out(regs, SCSI_PHASE_DATA_OUT, 817 maxlen, data); 818 #endif 819 retlen += xfer; 820 maxlen -= xfer; 821 break; 822 case SCSI_PHASE_STATUS: 823 SCI_ACK(regs,SCSI_PHASE_STATUS); 824 sci_data_in(regs, SCSI_PHASE_STATUS, 825 1, status); 826 break; 827 case SCSI_PHASE_MESSAGE_IN: 828 SCI_ACK(regs,SCSI_PHASE_MESSAGE_IN); 829 sci_data_in(regs, SCSI_PHASE_MESSAGE_IN, 830 1, msg); 831 if (*msg == 0) { 832 return retlen; 833 } else { 834 printf( "message 0x%x in " 835 "data_transfer.\n", *msg); 836 } 837 break; 838 case SCSI_PHASE_MESSAGE_OUT: 839 SCI_ACK(regs,SCSI_PHASE_MESSAGE_OUT); 840 sci_data_out(regs, SCSI_PHASE_MESSAGE_OUT, 841 1, msg); 842 break; 843 default: 844 printf( "Unexpected phase 0x%x in " 845 "data_transfer().\n", phase); 846 scsi_timeout_error: 847 return retlen; 848 break; 849 } 850 } 851 } 852 853 static int 854 si_dorequest(register volatile sci_regmap_t *regs, 855 int target, int lun, u_char *cmd, int cmdlen, 856 char *databuf, int datalen, int *sent, int *ret) 857 { 858 /* Returns 0 on success, -1 on internal error, or the status byte */ 859 int cmd_bytes_sent, r; 860 u_char stat, msg, c; 861 862 *sent = 0; 863 864 if ( ( r = si_select_target(regs, 7, target, 1) ) != SCSI_RET_SUCCESS) { 865 #ifdef DEBUG 866 if (si_debug) { 867 printf("si_dorequest: select returned %d\n", r); 868 } 869 #endif 870 *ret = r; 871 SCI_CLR_INTR(regs); 872 switch (r) { 873 case SCSI_RET_RETRY: 874 return 0x08; 875 default: 876 printf("si_select_target(target %d, lun %d) failed(%d).\n", 877 target, lun, r); 878 case SCSI_RET_DEVICE_DOWN: 879 return -1; 880 } 881 } 882 883 c = 0x80 | lun; 884 885 if ((cmd_bytes_sent = si_command_transfer(regs, cmdlen, 886 (u_char *) cmd, &stat, &c)) != cmdlen) 887 { 888 SCI_CLR_INTR(regs); 889 *ret = SCSI_RET_COMMAND_FAIL; 890 printf("Data underrun sending CCB (%d bytes of %d, sent).\n", 891 cmd_bytes_sent, cmdlen); 892 return -1; 893 } 894 895 *sent=si_data_transfer(regs, datalen, (u_char *)databuf, 896 &stat, &msg); 897 #ifdef DEBUG 898 if (si_debug) { 899 printf("si_dorequest: data transfered = %d\n", *sent); 900 } 901 #endif 902 903 *ret = 0; 904 return stat; 905 } 906 907 static int 908 si_generic(int adapter, int id, int lun, struct scsi_generic *cmd, 909 int cmdlen, void *databuf, int datalen) 910 { 911 register struct ncr5380_softc *ncr5380 = sicd.cd_devs[adapter]; 912 register volatile sci_regmap_t *regs = ncr5380->sc_regs; 913 int i,j,sent,ret; 914 915 if (cmd->opcode == TEST_UNIT_READY) /* XXX */ 916 cmd->bytes[0] = ((u_char) lun << 5); 917 918 i = si_dorequest(regs, id, lun, (u_char *) cmd, cmdlen, 919 databuf, datalen, &sent, &ret); 920 921 return i; 922 } 923 924 static int 925 si_group0(int adapter, int id, int lun, int opcode, int addr, int len, 926 int flags, caddr_t databuf, int datalen) 927 { 928 register struct ncr5380_softc *ncr5380 = sicd.cd_devs[adapter]; 929 register volatile sci_regmap_t *regs = ncr5380->sc_regs; 930 unsigned char cmd[6]; 931 int i,j,sent,ret; 932 933 cmd[0] = opcode; /* Operation code */ 934 cmd[1] = (lun << 5) | ((addr >> 16) & 0x1F); /* Lun & MSB of addr */ 935 cmd[2] = (addr >> 8) & 0xFF; /* addr */ 936 cmd[3] = addr & 0xFF; /* LSB of addr */ 937 cmd[4] = len; /* Allocation length */ 938 cmd[5] = flags; /* Link/Flag */ 939 940 i = si_dorequest(regs, id, lun, cmd, 6, databuf, datalen, &sent, &ret); 941 942 return i; 943 } 944