1 /* $NetBSD: si.c,v 1.14 1995/01/24 05:55:50 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 /* At autoconfig time, do NOT lower the spl! */ 285 if ((flags & SCSI_POLL) == 0) 286 s = splbio(); 287 288 if ( flags & SCSI_RESET ) { 289 printf("flags & SCSIRESET.\n"); 290 ncr5380_reset_scsibus(xs->sc_link->adapter_softc); 291 r = COMPLETE; 292 } else { 293 r = ncr5380_send_cmd(xs); 294 xs->flags |= ITSDONE; 295 scsi_done(xs); 296 } 297 298 if ((flags & SCSI_POLL) == 0) 299 splx(s); 300 301 switch(r) { 302 case COMPLETE: 303 case SUCCESSFULLY_QUEUED: 304 r = SUCCESSFULLY_QUEUED; 305 if (xs->flags & SCSI_POLL) 306 r = COMPLETE; 307 break; 308 default: 309 break; 310 } 311 return r; 312 } 313 314 #ifdef DEBUG 315 static int 316 ncr5380_show_scsi_cmd(struct scsi_xfer *xs) 317 { 318 u_char *b = (u_char *) xs->cmd; 319 int i = 0; 320 321 if ( ! ( xs->flags & SCSI_RESET ) ) { 322 printf("si(%d:%d:%d)-", 323 xs->sc_link->scsibus, 324 xs->sc_link->target, 325 xs->sc_link->lun); 326 while (i < xs->cmdlen) { 327 if (i) printf(","); 328 printf("%x",b[i++]); 329 } 330 printf("-\n"); 331 } else { 332 printf("si(%d:%d:%d)-RESET-\n", 333 xs->sc_link->scsibus, 334 xs->sc_link->target, 335 xs->sc_link->lun); 336 } 337 } 338 #endif 339 340 /* 341 * Actual chip control. 342 */ 343 344 static void 345 ncr_sbc_intr(struct ncr5380_softc *ncr5380) 346 { 347 volatile sci_regmap_t *regs = ncr5380->sc_regs; 348 349 if ((regs->sci_csr & SCI_CSR_INT) == 0) { 350 #ifdef DEBUG 351 printf (" ncr_sbc_intr: spurrious\n"); 352 #endif 353 return; 354 } 355 356 SCI_CLR_INTR(regs); 357 #ifdef DEBUG 358 printf (" ncr_sbc_intr\n"); 359 #endif 360 } 361 362 static void 363 ncr_dma_intr(struct ncr5380_softc *ncr5380) 364 { 365 volatile struct si_regs *regs = ncr5380->sc_regs; 366 367 #ifdef DEBUG 368 printf (" ncr_dma_intr\n"); 369 #endif 370 } 371 372 static int 373 ncr_intr(void *arg) 374 { 375 struct ncr5380_softc *ncr5380 = arg; 376 volatile struct si_regs *si = ncr5380->sc_regs; 377 int rv = 0; 378 379 /* Interrupts not enabled? Can not be for us. */ 380 if ((si->si_csr & SI_CSR_INTR_EN) == 0) 381 return rv; 382 383 if (si->si_csr & SI_CSR_DMA_IP) { 384 ncr_dma_intr(ncr5380); 385 rv++; 386 } 387 if (si->si_csr & SI_CSR_SBC_IP) { 388 ncr_sbc_intr(ncr5380); 389 rv++; 390 } 391 return rv; 392 } 393 394 static int 395 ncr5380_reset_adapter(struct ncr5380_softc *ncr5380) 396 { 397 volatile struct si_regs *si = ncr5380->sc_regs; 398 399 #ifdef DEBUG 400 if (si_debug) { 401 printf("si_reset_adapter\n"); 402 } 403 #endif 404 405 /* The reset bits are active low. */ 406 si->si_csr = 0; 407 delay(100); 408 si->si_csr = SI_CSR_FIFO_RES | SI_CSR_SCSI_RES; 409 } 410 411 static int 412 ncr5380_reset_scsibus(struct ncr5380_softc *ncr5380) 413 { 414 volatile sci_regmap_t *regs = ncr5380->sc_regs; 415 416 #ifdef DEBUG 417 if (si_debug) { 418 printf("si_reset_scsibus\n"); 419 } 420 #endif 421 422 regs->sci_icmd = SCI_ICMD_TEST; 423 regs->sci_icmd = SCI_ICMD_TEST | SCI_ICMD_RST; 424 delay(2500); 425 regs->sci_icmd = 0; 426 427 regs->sci_mode = 0; 428 regs->sci_tcmd = SCI_PHASE_DISC; 429 regs->sci_sel_enb = 0; 430 431 SCI_CLR_INTR(regs); 432 SCI_CLR_INTR(regs); 433 } 434 435 static int 436 ncr5380_poll(int adapter, int timeout) 437 { 438 } 439 440 static int 441 ncr5380_send_cmd(struct scsi_xfer *xs) 442 { 443 int sense; 444 445 #ifdef DIAGNOSTIC 446 if ((getsr() & PSL_IPL) < PSL_IPL2) 447 panic("ncr_send_cmd: bad spl"); 448 #endif 449 450 #ifdef DEBUG 451 if (si_debug & 2) 452 ncr5380_show_scsi_cmd(xs); 453 #endif 454 455 sense = si_generic( xs->sc_link->scsibus, xs->sc_link->target, 456 xs->sc_link->lun, xs->cmd, xs->cmdlen, 457 xs->data, xs->datalen ); 458 459 switch (sense) { 460 case 0: /* success */ 461 xs->resid = 0; 462 xs->error = XS_NOERROR; 463 break; 464 465 case 0x02: /* Check condition */ 466 #ifdef DEBUG 467 if (si_debug) 468 printf("check cond. target %d.\n", 469 xs->sc_link->target); 470 #endif 471 delay(10); /* Phil's fix for slow devices. */ 472 si_group0(xs->sc_link->scsibus, 473 xs->sc_link->target, 474 xs->sc_link->lun, 475 0x3, 0x0, 476 sizeof(struct scsi_sense_data), 477 0, (caddr_t) &(xs->sense), 478 sizeof(struct scsi_sense_data)); 479 xs->error = XS_SENSE; 480 break; 481 case 0x08: /* Busy */ 482 xs->error = XS_BUSY; 483 break; 484 default: 485 xs->error = XS_DRIVER_STUFFUP; 486 break; 487 488 } 489 return (COMPLETE); 490 } 491 492 static int 493 si_select_target(register volatile sci_regmap_t *regs, 494 u_char myid, u_char tid, int with_atn) 495 { 496 register u_char bid, icmd; 497 int ret = SCSI_RET_RETRY; 498 int arb_retries, arb_wait; 499 500 /* for our purposes.. */ 501 myid = 1 << myid; 502 tid = 1 << tid; 503 504 regs->sci_sel_enb = 0; /* we don't want any interrupts. */ 505 regs->sci_tcmd = 0; /* get into a harmless state */ 506 507 arb_retries = ARBITRATION_RETRIES; 508 509 retry_arbitration: 510 regs->sci_mode = 0; /* get into a harmless state */ 511 if (--arb_retries <= 0) { 512 #ifdef DEBUG 513 if (si_debug) { 514 printf("si_select: arb_retries expended\n"); 515 } 516 #endif 517 goto lost; 518 } 519 520 if ((regs->sci_bus_csr & (SCI_BUS_BSY|SCI_BUS_SEL)) && 521 (regs->sci_bus_csr & (SCI_BUS_BSY|SCI_BUS_SEL)) && 522 (regs->sci_bus_csr & (SCI_BUS_BSY|SCI_BUS_SEL))) 523 { 524 #ifdef DEBUG 525 if (si_debug) { 526 printf("si_select_target: still BSY|SEL\n"); 527 } 528 #endif 529 return ret; 530 } 531 532 regs->sci_odata = myid; 533 regs->sci_mode = SCI_MODE_ARB; 534 /* regs->sci_mode |= SCI_MODE_ARB; XXX? */ 535 536 /* AIP might not set if BSY went true after we checked */ 537 /* Wait up to about 100 usec. for it to appear. */ 538 arb_wait = 50; /* X2 */ 539 do { 540 if (regs->sci_icmd & SCI_ICMD_AIP) 541 break; 542 delay2us(); 543 } while (--arb_wait > 0); 544 if (arb_wait <= 0) { 545 /* XXX - Could have missed it? */ 546 goto retry_arbitration; 547 } 548 #ifdef DEBUG 549 if (si_debug) { 550 printf("si_select_target: API after %d tries (last wait %d)\n", 551 ARBITRATION_RETRIES - arb_retries, 552 (50 - arb_wait)); 553 } 554 #endif 555 556 delay(3); /* 2.2 uSec. arbitration delay */ 557 558 if (regs->sci_icmd & SCI_ICMD_LST) { 559 #ifdef DEBUG 560 if (si_debug) 561 printf ("lost 1\n"); 562 #endif 563 goto retry_arbitration; /* XXX */ 564 } 565 566 regs->sci_mode &= ~SCI_MODE_PAR_CHK; 567 bid = regs->sci_data; 568 569 if ((bid & ~myid) > myid) { 570 #ifdef DEBUG 571 if (si_debug) 572 printf ("lost 2\n"); 573 #endif 574 /* Trying again will not help. */ 575 goto lost; 576 } 577 if (regs->sci_icmd & SCI_ICMD_LST) { 578 #ifdef DEBUG 579 if (si_debug) 580 printf ("lost 3\n"); 581 #endif 582 goto lost; 583 } 584 585 /* Won arbitration, enter selection phase now */ 586 icmd = regs->sci_icmd & ~(SCI_ICMD_DIFF|SCI_ICMD_TEST); 587 icmd |= (with_atn ? (SCI_ICMD_SEL|SCI_ICMD_ATN) : SCI_ICMD_SEL); 588 regs->sci_icmd = icmd; 589 590 if (regs->sci_icmd & SCI_ICMD_LST) { 591 #ifdef DEBUG 592 if (si_debug) 593 printf ("nosel\n"); 594 #endif 595 goto nosel; 596 } 597 598 /* XXX a target that violates specs might still drive the bus XXX */ 599 /* XXX should put our id out, and after the delay check nothi XXX */ 600 /* XXX ng else is out there. XXX */ 601 602 delay2us(); 603 604 regs->sci_sel_enb = 0; 605 606 regs->sci_odata = myid | tid; 607 608 icmd |= SCI_ICMD_BSY|SCI_ICMD_DATA; 609 regs->sci_icmd = icmd; 610 611 /* regs->sci_mode &= ~SCI_MODE_ARB; 2 deskew delays, too */ 612 regs->sci_mode = 0; /* 2 deskew delays, too */ 613 614 icmd &= ~SCI_ICMD_BSY; 615 regs->sci_icmd = icmd; 616 617 /* bus settle delay, 400ns */ 618 delay2us(); /* too much (was 2) ? */ 619 620 regs->sci_mode |= SCI_MODE_PAR_CHK; 621 622 { 623 register int timeo = 2500;/* 250 msecs in 100 usecs chunks */ 624 while ((regs->sci_bus_csr & SCI_BUS_BSY) == 0) { 625 if (--timeo > 0) { 626 delay(100); 627 } else { 628 /* This is the "normal" no-such-device select error. */ 629 #ifdef DEBUG 630 if (si_debug) 631 printf("si_select: did not see BSY\n"); 632 #endif 633 goto nodev; 634 } 635 } 636 } 637 638 icmd &= ~(SCI_ICMD_DATA|SCI_ICMD_SEL); 639 regs->sci_icmd = icmd; 640 /* regs->sci_sel_enb = myid;*/ /* looks like we should NOT have it */ 641 /* XXX - SCI_MODE_PAR_CHK ? */ 642 return SCSI_RET_SUCCESS; 643 644 nodev: 645 ret = SCSI_RET_DEVICE_DOWN; 646 regs->sci_sel_enb = myid; 647 nosel: 648 icmd &= ~(SCI_ICMD_DATA|SCI_ICMD_SEL|SCI_ICMD_ATN); 649 regs->sci_icmd = icmd; 650 regs->sci_mode = 0; 651 return ret; 652 653 lost: 654 regs->sci_icmd = 0; 655 regs->sci_mode = 0; 656 #ifdef DEBUG 657 if (si_debug) { 658 printf("si_select: lost arbitration\n"); 659 } 660 #endif 661 return ret; 662 } 663 664 sci_data_out(regs, phase, count, data) 665 register volatile sci_regmap_t *regs; 666 unsigned char *data; 667 { 668 register unsigned char icmd; 669 register int cnt=0; 670 671 /* ..checks.. */ 672 673 icmd = regs->sci_icmd & ~(SCI_ICMD_DIFF|SCI_ICMD_TEST); 674 loop: 675 if (SCI_CUR_PHASE(regs->sci_bus_csr) != phase) 676 return cnt; 677 678 WAIT_FOR_REQ(regs); 679 icmd |= SCI_ICMD_DATA; 680 regs->sci_icmd = icmd; 681 regs->sci_odata = *data++; 682 icmd |= SCI_ICMD_ACK; 683 regs->sci_icmd = icmd; 684 685 icmd &= ~(SCI_ICMD_DATA|SCI_ICMD_ACK); 686 WAIT_FOR_NOT_REQ(regs); 687 regs->sci_icmd = icmd; 688 ++cnt; 689 if (--count > 0) 690 goto loop; 691 scsi_timeout_error: 692 return cnt; 693 } 694 695 sci_data_in(regs, phase, count, data) 696 register volatile sci_regmap_t *regs; 697 unsigned char *data; 698 { 699 register unsigned char icmd; 700 register int cnt=0; 701 702 /* ..checks.. */ 703 704 icmd = regs->sci_icmd & ~(SCI_ICMD_DIFF|SCI_ICMD_TEST); 705 706 loop: 707 if (SCI_CUR_PHASE(regs->sci_bus_csr) != phase) 708 return cnt; 709 710 WAIT_FOR_REQ(regs); 711 *data++ = regs->sci_data; 712 icmd |= SCI_ICMD_ACK; 713 regs->sci_icmd = icmd; 714 715 icmd &= ~SCI_ICMD_ACK; 716 WAIT_FOR_NOT_REQ(regs); 717 regs->sci_icmd = icmd; 718 ++cnt; 719 if (--count > 0) 720 goto loop; 721 722 scsi_timeout_error: 723 return cnt; 724 } 725 726 static int 727 si_command_transfer(register volatile sci_regmap_t *regs, 728 int maxlen, u_char *data, u_char *status, u_char *msg) 729 { 730 int xfer=0, phase; 731 732 /* printf("command_transfer called for 0x%x.\n", *data); */ 733 734 regs->sci_icmd = 0; 735 736 while (1) { 737 738 WAIT_FOR_REQ(regs); 739 740 phase = SCI_CUR_PHASE(regs->sci_bus_csr); 741 742 switch (phase) { 743 case SCSI_PHASE_CMD: 744 SCI_ACK(regs,SCSI_PHASE_CMD); 745 xfer += sci_data_out(regs, SCSI_PHASE_CMD, 746 maxlen, data); 747 return xfer; 748 case SCSI_PHASE_DATA_IN: 749 printf("Data in phase in command_transfer?\n"); 750 return 0; 751 case SCSI_PHASE_DATA_OUT: 752 printf("Data out phase in command_transfer?\n"); 753 return 0; 754 case SCSI_PHASE_STATUS: 755 SCI_ACK(regs,SCSI_PHASE_STATUS); 756 printf("status in command_transfer.\n"); 757 sci_data_in(regs, SCSI_PHASE_STATUS, 758 1, status); 759 break; 760 case SCSI_PHASE_MESSAGE_IN: 761 SCI_ACK(regs,SCSI_PHASE_MESSAGE_IN); 762 printf("msgin in command_transfer.\n"); 763 sci_data_in(regs, SCSI_PHASE_MESSAGE_IN, 764 1, msg); 765 break; 766 case SCSI_PHASE_MESSAGE_OUT: 767 SCI_ACK(regs,SCSI_PHASE_MESSAGE_OUT); 768 sci_data_out(regs, SCSI_PHASE_MESSAGE_OUT, 769 1, msg); 770 break; 771 default: 772 printf("Unexpected phase 0x%x in " 773 "command_transfer().\n", phase); 774 scsi_timeout_error: 775 return xfer; 776 break; 777 } 778 } 779 } 780 781 static int 782 si_data_transfer(register volatile sci_regmap_t *regs, 783 int maxlen, u_char *data, u_char *status, u_char *msg) 784 { 785 int retlen = 0, xfer, phase; 786 787 regs->sci_icmd = 0; 788 789 *status = 0; 790 791 while (1) { 792 793 WAIT_FOR_REQ(regs); 794 795 phase = SCI_CUR_PHASE(regs->sci_bus_csr); 796 797 switch (phase) { 798 case SCSI_PHASE_CMD: 799 printf("Command phase in data_transfer().\n"); 800 return retlen; 801 case SCSI_PHASE_DATA_IN: 802 SCI_ACK(regs,SCSI_PHASE_DATA_IN); 803 #if PSEUDO_DMA 804 xfer = sci_pdma_in(regs, SCSI_PHASE_DATA_IN, 805 maxlen, data); 806 #else 807 xfer = sci_data_in(regs, SCSI_PHASE_DATA_IN, 808 maxlen, data); 809 #endif 810 retlen += xfer; 811 maxlen -= xfer; 812 break; 813 case SCSI_PHASE_DATA_OUT: 814 SCI_ACK(regs,SCSI_PHASE_DATA_OUT); 815 #if PSEUDO_DMA 816 xfer = sci_pdma_out(regs, SCSI_PHASE_DATA_OUT, 817 maxlen, data); 818 #else 819 xfer = sci_data_out(regs, SCSI_PHASE_DATA_OUT, 820 maxlen, data); 821 #endif 822 retlen += xfer; 823 maxlen -= xfer; 824 break; 825 case SCSI_PHASE_STATUS: 826 SCI_ACK(regs,SCSI_PHASE_STATUS); 827 sci_data_in(regs, SCSI_PHASE_STATUS, 828 1, status); 829 break; 830 case SCSI_PHASE_MESSAGE_IN: 831 SCI_ACK(regs,SCSI_PHASE_MESSAGE_IN); 832 sci_data_in(regs, SCSI_PHASE_MESSAGE_IN, 833 1, msg); 834 if (*msg == 0) { 835 return retlen; 836 } else { 837 printf( "message 0x%x in " 838 "data_transfer.\n", *msg); 839 } 840 break; 841 case SCSI_PHASE_MESSAGE_OUT: 842 SCI_ACK(regs,SCSI_PHASE_MESSAGE_OUT); 843 sci_data_out(regs, SCSI_PHASE_MESSAGE_OUT, 844 1, msg); 845 break; 846 default: 847 printf( "Unexpected phase 0x%x in " 848 "data_transfer().\n", phase); 849 scsi_timeout_error: 850 return retlen; 851 break; 852 } 853 } 854 } 855 856 static int 857 si_dorequest(register volatile sci_regmap_t *regs, 858 int target, int lun, u_char *cmd, int cmdlen, 859 char *databuf, int datalen, int *sent, int *ret) 860 { 861 /* Returns 0 on success, -1 on internal error, or the status byte */ 862 int cmd_bytes_sent, r; 863 u_char stat, msg, c; 864 865 *sent = 0; 866 867 if ( ( r = si_select_target(regs, 7, target, 1) ) != SCSI_RET_SUCCESS) { 868 #ifdef DEBUG 869 if (si_debug) { 870 printf("si_dorequest: select returned %d\n", r); 871 } 872 #endif 873 *ret = r; 874 SCI_CLR_INTR(regs); 875 switch (r) { 876 case SCSI_RET_RETRY: 877 return 0x08; 878 default: 879 printf("si_select_target(target %d, lun %d) failed(%d).\n", 880 target, lun, r); 881 case SCSI_RET_DEVICE_DOWN: 882 return -1; 883 } 884 } 885 886 c = 0x80 | lun; 887 888 if ((cmd_bytes_sent = si_command_transfer(regs, cmdlen, 889 (u_char *) cmd, &stat, &c)) != cmdlen) 890 { 891 SCI_CLR_INTR(regs); 892 *ret = SCSI_RET_COMMAND_FAIL; 893 printf("Data underrun sending CCB (%d bytes of %d, sent).\n", 894 cmd_bytes_sent, cmdlen); 895 return -1; 896 } 897 898 *sent=si_data_transfer(regs, datalen, (u_char *)databuf, 899 &stat, &msg); 900 #ifdef DEBUG 901 if (si_debug) { 902 printf("si_dorequest: data transfered = %d\n", *sent); 903 } 904 #endif 905 906 *ret = 0; 907 return stat; 908 } 909 910 static int 911 si_generic(int adapter, int id, int lun, struct scsi_generic *cmd, 912 int cmdlen, void *databuf, int datalen) 913 { 914 register struct ncr5380_softc *ncr5380 = sicd.cd_devs[adapter]; 915 register volatile sci_regmap_t *regs = ncr5380->sc_regs; 916 int i,j,sent,ret; 917 918 if (cmd->opcode == TEST_UNIT_READY) /* XXX */ 919 cmd->bytes[0] = ((u_char) lun << 5); 920 921 i = si_dorequest(regs, id, lun, (u_char *) cmd, cmdlen, 922 databuf, datalen, &sent, &ret); 923 924 return i; 925 } 926 927 static int 928 si_group0(int adapter, int id, int lun, int opcode, int addr, int len, 929 int flags, caddr_t databuf, int datalen) 930 { 931 register struct ncr5380_softc *ncr5380 = sicd.cd_devs[adapter]; 932 register volatile sci_regmap_t *regs = ncr5380->sc_regs; 933 unsigned char cmd[6]; 934 int i,j,sent,ret; 935 936 cmd[0] = opcode; /* Operation code */ 937 cmd[1] = (lun << 5) | ((addr >> 16) & 0x1F); /* Lun & MSB of addr */ 938 cmd[2] = (addr >> 8) & 0xFF; /* addr */ 939 cmd[3] = addr & 0xFF; /* LSB of addr */ 940 cmd[4] = len; /* Allocation length */ 941 cmd[5] = flags; /* Link/Flag */ 942 943 i = si_dorequest(regs, id, lun, cmd, 6, databuf, datalen, &sent, &ret); 944 945 return i; 946 } 947