1 /* $NetBSD: si.c,v 1.11 1994/12/13 18:31:52 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 static int si_debug=0; 43 44 #include <sys/types.h> 45 #include <sys/malloc.h> 46 #include <sys/param.h> 47 #include <sys/systm.h> 48 #include <sys/errno.h> 49 #include <sys/buf.h> 50 #include <sys/proc.h> 51 #include <sys/user.h> 52 #include <sys/device.h> 53 54 #include <machine/autoconf.h> 55 #include <machine/isr.h> 56 #include <machine/obio.h> 57 58 #include <scsi/scsi_all.h> 59 #include <scsi/scsi_debug.h> 60 #include <scsi/scsiconf.h> 61 62 #include "scsi_defs.h" 63 #include "scsi_5380.h" 64 65 #define SCI_PHASE_DISC 0 /* sort of ... */ 66 #define SCI_CLR_INTR(regs) ((volatile)(regs->sci_iack)) 67 #define SCI_ACK(ptr,phase) (ptr)->sci_tcmd = (phase) 68 #define SCSI_TIMEOUT_VAL 10000000 69 #define WAIT_FOR_NOT_REQ(ptr) { \ 70 int scsi_timeout = SCSI_TIMEOUT_VAL; \ 71 while ( ((ptr)->sci_bus_csr & SCI_BUS_REQ) && \ 72 ((ptr)->sci_bus_csr & SCI_BUS_REQ) && \ 73 ((ptr)->sci_bus_csr & SCI_BUS_REQ) && \ 74 (--scsi_timeout) ); \ 75 if (!scsi_timeout) { \ 76 printf("scsi timeout--WAIT_FOR_NOT_REQ---%s, line %d.\n", \ 77 __FILE__, __LINE__); \ 78 goto scsi_timeout_error; \ 79 } \ 80 } 81 #define WAIT_FOR_REQ(ptr) { \ 82 int scsi_timeout = SCSI_TIMEOUT_VAL; \ 83 while ( (((ptr)->sci_bus_csr & SCI_BUS_REQ) == 0) && \ 84 (((ptr)->sci_bus_csr & SCI_BUS_REQ) == 0) && \ 85 (((ptr)->sci_bus_csr & SCI_BUS_REQ) == 0) && \ 86 (--scsi_timeout) ); \ 87 if (!scsi_timeout) { \ 88 printf("scsi timeout--WAIT_FOR_REQ---%s, line %d.\n", \ 89 __FILE__, __LINE__); \ 90 goto scsi_timeout_error; \ 91 } \ 92 } 93 #define WAIT_FOR_BSY(ptr) { \ 94 int scsi_timeout = SCSI_TIMEOUT_VAL; \ 95 while ( (((ptr)->sci_bus_csr & SCI_BUS_BSY) == 0) && \ 96 (((ptr)->sci_bus_csr & SCI_BUS_BSY) == 0) && \ 97 (((ptr)->sci_bus_csr & SCI_BUS_BSY) == 0) && \ 98 (--scsi_timeout) ); \ 99 if (!scsi_timeout) { \ 100 printf("scsi timeout--WAIT_FOR_BSY---%s, line %d.\n", \ 101 __FILE__, __LINE__); \ 102 goto scsi_timeout_error; \ 103 } \ 104 } 105 106 #ifdef DDB 107 int Debugger(); 108 #else 109 #define Debugger() panic("Should call Debugger here %s:%d", \ 110 __FILE__, __LINE__) 111 #endif 112 113 struct ncr5380_softc { 114 struct device sc_dev; 115 volatile void *sc_regs; 116 int sc_adapter_target; 117 struct scsi_link sc_link; 118 }; 119 120 static u_int ncr5380_adapter_info(struct ncr5380_softc *ncr5380); 121 static void ncr5380_minphys(struct buf *bp); 122 static int ncr5380_scsi_cmd(struct scsi_xfer *xs); 123 124 static int ncr5380_show_scsi_cmd(struct scsi_xfer *xs); 125 static int ncr5380_reset_target(int adapter, int target); 126 static int ncr5380_poll(int adapter, int timeout); 127 static int ncr5380_send_cmd(struct scsi_xfer *xs); 128 129 int ncr5380_intr(void *); 130 131 static int si_generic(int adapter, int id, int lun, 132 struct scsi_generic *cmd, int cmdlen, 133 void *databuf, int datalen); 134 static int si_group0(int adapter, int id, int lun, 135 int opcode, int addr, int len, 136 int flags, caddr_t databuf, int datalen); 137 138 static char scsi_name[] = "si"; 139 140 struct scsi_adapter ncr5380_switch = { 141 ncr5380_scsi_cmd, /* scsi_cmd() */ 142 ncr5380_minphys, /* scsi_minphys() */ 143 0, /* open_target_lu() */ 144 0, /* close_target_lu() */ 145 ncr5380_adapter_info, /* adapter_info() */ 146 scsi_name, /* name */ 147 0, 0 /* spare[2] */ 148 }; 149 150 /* This is copied from julian's bt driver */ 151 /* "so we have a default dev struct for our link struct." */ 152 struct scsi_device ncr_dev = { 153 NULL, /* Use default error handler. */ 154 NULL, /* Use default start handler. */ 155 NULL, /* Use default async handler. */ 156 NULL, /* Use default "done" routine. */ 157 "si", /* name of device type */ 158 0, /* device type dependent flags */ 159 0, 0 /* spare[2] */ 160 }; 161 162 extern int matchbyname(); 163 static int si_match(); 164 static void si_attach(); 165 166 struct cfdriver sicd = { 167 NULL, "si", si_match, si_attach, DV_DULL, 168 sizeof(struct ncr5380_softc), NULL, 0, 169 }; 170 171 static int 172 si_print(aux, name) 173 void *aux; 174 char *name; 175 { 176 if (name) 177 printf("%s: (sc_link = 0x%x)", name, (int) aux); 178 return UNCONF; 179 } 180 181 static int 182 si_match(parent, vcf, args) 183 struct device *parent; 184 void *vcf, *args; 185 { 186 struct cfdata *cf = vcf; 187 struct confargs *ca = args; 188 int x; 189 190 if (ca->ca_paddr == -1) 191 ca->ca_paddr = OBIO_NCR_SCSI; 192 if (ca->ca_intpri == -1) 193 ca->ca_intpri = 2; 194 195 /* The peek returns non-zero on error. */ 196 x = bus_peek(ca->ca_bustype, ca->ca_paddr, 1); 197 return (x != -1); 198 } 199 200 static void 201 si_attach(parent, self, args) 202 struct device *parent, *self; 203 void *args; 204 { 205 struct ncr5380_softc *ncr5380 = (struct ncr5380_softc *) self; 206 register volatile sci_regmap_t *regs; 207 struct confargs *ca = args; 208 int unit = self->dv_unit; 209 caddr_t dvma_malloc(); /* XXX */ 210 211 printf("\n"); 212 213 regs = (sci_regmap_t *) 214 obio_alloc(ca->ca_paddr, OBIO_NCR_SCSI_SIZE); 215 216 ncr5380->sc_regs = regs; 217 ncr5380->sc_link.scsibus = unit; /* needed? */ 218 ncr5380->sc_link.adapter_softc = ncr5380; 219 ncr5380->sc_link.adapter_targ = 7; 220 ncr5380->sc_link.adapter = &ncr5380_switch; 221 ncr5380->sc_link.device = &ncr_dev; 222 223 isr_add_autovect(ncr5380_intr, (void *)ncr5380, ca->ca_intpri); 224 225 config_found(self, &(ncr5380->sc_link), si_print); 226 } 227 228 static u_int 229 ncr5380_adapter_info(struct ncr5380_softc *ncr5380) 230 { 231 return 1; 232 } 233 234 #define MIN_PHYS 65536 /*BARF!!!!*/ 235 static void 236 ncr5380_minphys(struct buf *bp) 237 { 238 if (bp->b_bcount > MIN_PHYS) { 239 printf("Uh-oh... ncr5380_minphys setting bp->b_bcount = %x.\n", MIN_PHYS); 240 bp->b_bcount = MIN_PHYS; 241 } 242 } 243 #undef MIN_PHYS 244 245 static int 246 ncr5380_scsi_cmd(struct scsi_xfer *xs) 247 { 248 int flags, s, r; 249 250 flags = xs->flags; 251 if (xs->bp) flags |= (SCSI_NOSLEEP); 252 if ( flags & ITSDONE ) { 253 printf("Already done?"); 254 xs->flags &= ~ITSDONE; 255 } 256 if ( ! ( flags & INUSE ) ) { 257 printf("Not in use?"); 258 xs->flags |= INUSE; 259 } 260 261 if ( flags & SCSI_RESET ) { 262 printf("flags & SCSIRESET.\n"); 263 if ( ! ( flags & SCSI_NOSLEEP ) ) { 264 s = splbio(); 265 ncr5380_reset_target(xs->sc_link->scsibus, xs->sc_link->target); 266 splx(s); 267 return(SUCCESSFULLY_QUEUED); 268 } else { 269 ncr5380_reset_target(xs->sc_link->scsibus, xs->sc_link->target); 270 if (ncr5380_poll(xs->sc_link->scsibus, xs->timeout)) { 271 return (HAD_ERROR); 272 } 273 return (COMPLETE); 274 } 275 } 276 #if 0 277 /* 278 * OK. Now that that's over with, let's pack up that 279 * SCSI puppy and send it off. If we can, we'll just 280 * queue and go; otherwise, we'll wait for the command 281 * to finish. 282 */ 283 if ( ! ( flags & SCSI_NOSLEEP ) ) { 284 s = splbio(); 285 ncr5380_send_cmd(xs); 286 splx(s); 287 return(SUCCESSFULLY_QUEUED); 288 } 289 #endif 290 291 r = ncr5380_send_cmd(xs); 292 xs->flags |= ITSDONE; 293 scsi_done(xs); 294 switch(r) { 295 case COMPLETE: 296 case SUCCESSFULLY_QUEUED: 297 r = SUCCESSFULLY_QUEUED; 298 if (xs->flags&SCSI_NOMASK) 299 r = COMPLETE; 300 break; 301 default: 302 break; 303 } 304 return r; 305 #if 0 306 do { 307 if (ncr5380_poll(xs->sc_link->scsibus, xs->timeout)) { 308 if ( ! ( xs->flags & SCSI_SILENT ) ) 309 printf("cmd fail.\n"); 310 cmd_cleanup 311 xs->error = XS_DRIVER_STUFFUP; 312 splx(s); 313 } 314 } while ( ! ( xs->flags & ITSDONE ) ); 315 #endif 316 } 317 318 static int 319 ncr5380_show_scsi_cmd(struct scsi_xfer *xs) 320 { 321 u_char *b = (u_char *) xs->cmd; 322 int i = 0; 323 324 if ( ! ( xs->flags & SCSI_RESET ) ) { 325 printf("si(%d:%d:%d)-", 326 xs->sc_link->scsibus, 327 xs->sc_link->target, 328 xs->sc_link->lun); 329 while (i < xs->cmdlen) { 330 if (i) printf(","); 331 printf("%x",b[i++]); 332 } 333 printf("-\n"); 334 } else { 335 printf("si(%d:%d:%d)-RESET-\n", 336 xs->sc_link->scsibus, 337 xs->sc_link->target, 338 xs->sc_link->lun); 339 } 340 } 341 342 /* 343 * Actual chip control. 344 */ 345 346 int 347 ncr5380_intr(void *arg) 348 { 349 register struct ncr5380_softc *ncr5380 = arg; 350 register volatile sci_regmap_t *regs = ncr5380->sc_regs; 351 352 if (regs->sci_csr & SCI_CSR_INT) { 353 SCI_CLR_INTR(regs); 354 #ifdef DEBUG 355 printf (" ncr_intr\n"); 356 #endif 357 return (1); /* we handled it */ 358 } 359 return (0); 360 } 361 362 int 363 scsi_irq_intr(void) 364 { 365 #if 0 /* XXX - no way to get regs */ 366 register volatile sci_regmap_t *regs = ncr; 367 if (regs->sci_csr != SCI_CSR_PHASE_MATCH) 368 printf("scsi_irq_intr called (not just phase match -- " 369 "csr = 0x%x, bus_csr = 0x%x).\n", 370 regs->sci_csr, regs->sci_bus_csr); 371 ncr5380_intr(0); 372 #endif 373 return 1; 374 } 375 376 int 377 scsi_drq_intr(void) 378 { 379 #if 0 380 printf("scsi_drq_intr called.\n"); 381 ncr5380_intr(0); 382 #endif 383 return 1; 384 } 385 386 static int 387 ncr5380_reset_target(int adapter, int target) 388 { 389 register struct ncr5380_softc *ncr5380 = sicd.cd_devs[adapter]; 390 register volatile sci_regmap_t *regs = ncr5380->sc_regs; 391 int dummy; 392 393 regs->sci_icmd = SCI_ICMD_TEST; 394 regs->sci_icmd = SCI_ICMD_TEST | SCI_ICMD_RST; 395 delay(2500); 396 regs->sci_icmd = 0; 397 398 regs->sci_mode = 0; 399 regs->sci_tcmd = SCI_PHASE_DISC; 400 regs->sci_sel_enb = 0; 401 402 SCI_CLR_INTR(regs); 403 SCI_CLR_INTR(regs); 404 } 405 406 static int 407 ncr5380_poll(int adapter, int timeout) 408 { 409 } 410 411 static int 412 ncr5380_send_cmd(struct scsi_xfer *xs) 413 { 414 int s; 415 int sense; 416 417 /* ncr5380_show_scsi_cmd(xs); */ 418 s = splbio(); 419 sense = si_generic( xs->sc_link->scsibus, xs->sc_link->target, 420 xs->sc_link->lun, xs->cmd, xs->cmdlen, 421 xs->data, xs->datalen ); 422 splx(s); 423 if (sense) { 424 switch (sense) { 425 case 0x02: /* Check condition */ 426 #ifdef DEBUG 427 printf("check cond. target %d.\n", 428 xs->sc_link->target); 429 #endif 430 delay(10); /* Phil's fix for slow devices. */ 431 s = splbio(); 432 si_group0(xs->sc_link->scsibus, 433 xs->sc_link->target, 434 xs->sc_link->lun, 435 0x3, 0x0, 436 sizeof(struct scsi_sense_data), 437 0, (caddr_t) &(xs->sense), 438 sizeof(struct scsi_sense_data)); 439 splx(s); 440 xs->error = XS_SENSE; 441 return HAD_ERROR; 442 case 0x08: /* Busy */ 443 xs->error = XS_BUSY; 444 return HAD_ERROR; 445 default: 446 xs->error = XS_DRIVER_STUFFUP; 447 return HAD_ERROR; 448 } 449 } 450 xs->error = XS_NOERROR; 451 return (COMPLETE); 452 } 453 454 static int 455 si_select_target(register volatile sci_regmap_t *regs, 456 u_char myid, u_char tid, int with_atn) 457 { 458 register u_char bid, icmd; 459 int ret = SCSI_RET_RETRY; 460 461 if ((regs->sci_bus_csr & (SCI_BUS_BSY|SCI_BUS_SEL)) && 462 (regs->sci_bus_csr & (SCI_BUS_BSY|SCI_BUS_SEL)) && 463 (regs->sci_bus_csr & (SCI_BUS_BSY|SCI_BUS_SEL))) 464 return ret; 465 466 /* for our purposes.. */ 467 myid = 1 << myid; 468 tid = 1 << tid; 469 470 regs->sci_sel_enb = 0; /* we don't want any interrupts. */ 471 regs->sci_tcmd = 0; /* get into a harmless state */ 472 regs->sci_mode = 0; /* get into a harmless state */ 473 474 regs->sci_odata = myid; 475 regs->sci_mode = SCI_MODE_ARB; 476 /* regs->sci_mode |= SCI_MODE_ARB; XXX? */ 477 /* AIP might not set if BSY went true after we checked */ 478 for (bid = 0; bid < 20; bid++) /* 20usec circa */ 479 if (regs->sci_icmd & SCI_ICMD_AIP) 480 break; 481 if ((regs->sci_icmd & SCI_ICMD_AIP) == 0) { 482 goto lost; 483 } 484 485 delay(2200); /* 2.2 millisecond arbitration delay */ 486 487 if (regs->sci_icmd & SCI_ICMD_LST) { 488 #ifdef DEBUG 489 printf ("lost 1\n"); 490 #endif 491 goto lost; 492 } 493 494 regs->sci_mode &= ~SCI_MODE_PAR_CHK; 495 bid = regs->sci_data; 496 497 if ((bid & ~myid) > myid) { 498 #ifdef DEBUG 499 printf ("lost 2\n"); 500 #endif 501 goto lost; 502 } 503 if (regs->sci_icmd & SCI_ICMD_LST) { 504 #ifdef DEBUG 505 printf ("lost 3\n"); 506 #endif 507 goto lost; 508 } 509 510 /* Won arbitration, enter selection phase now */ 511 icmd = regs->sci_icmd & ~(SCI_ICMD_DIFF|SCI_ICMD_TEST); 512 icmd |= (with_atn ? (SCI_ICMD_SEL|SCI_ICMD_ATN) : SCI_ICMD_SEL); 513 icmd |= SCI_ICMD_BSY; 514 regs->sci_icmd = icmd; 515 516 if (regs->sci_icmd & SCI_ICMD_LST) { 517 #ifdef DEBUG 518 printf ("nosel\n"); 519 #endif 520 goto nosel; 521 } 522 523 /* XXX a target that violates specs might still drive the bus XXX */ 524 /* XXX should put our id out, and after the delay check nothi XXX */ 525 /* XXX ng else is out there. XXX */ 526 527 delay2us(); 528 529 regs->sci_tcmd = 0; 530 regs->sci_odata = myid | tid; 531 regs->sci_sel_enb = 0; 532 533 /* regs->sci_mode &= ~SCI_MODE_ARB; 2 deskew delays, too */ 534 regs->sci_mode = 0; /* 2 deskew delays, too */ 535 536 icmd |= SCI_ICMD_DATA; 537 icmd &= ~(SCI_ICMD_BSY); 538 539 regs->sci_icmd = icmd; 540 541 /* bus settle delay, 400ns */ 542 delay2us(); /* too much (was 2) ? */ 543 544 /* regs->sci_mode |= SCI_MODE_PAR_CHK; */ 545 546 { 547 register int timeo = 2500;/* 250 msecs in 100 usecs chunks */ 548 while ((regs->sci_bus_csr & SCI_BUS_BSY) == 0) { 549 if (--timeo > 0) { 550 delay(100); 551 } else { 552 goto nodev; 553 } 554 } 555 } 556 557 icmd &= ~(SCI_ICMD_DATA|SCI_ICMD_SEL); 558 regs->sci_icmd = icmd; 559 /* regs->sci_sel_enb = myid;*/ /* looks like we should NOT have it */ 560 return SCSI_RET_SUCCESS; 561 nodev: 562 ret = SCSI_RET_DEVICE_DOWN; 563 regs->sci_sel_enb = myid; 564 nosel: 565 icmd &= ~(SCI_ICMD_DATA|SCI_ICMD_SEL|SCI_ICMD_ATN); 566 regs->sci_icmd = icmd; 567 lost: 568 regs->sci_mode = 0; 569 570 return ret; 571 } 572 573 sci_data_out(regs, phase, count, data) 574 register volatile sci_regmap_t *regs; 575 unsigned char *data; 576 { 577 register unsigned char icmd; 578 register int cnt=0; 579 580 /* ..checks.. */ 581 582 icmd = regs->sci_icmd & ~(SCI_ICMD_DIFF|SCI_ICMD_TEST); 583 loop: 584 if (SCI_CUR_PHASE(regs->sci_bus_csr) != phase) 585 return cnt; 586 587 WAIT_FOR_REQ(regs); 588 icmd |= SCI_ICMD_DATA; 589 regs->sci_icmd = icmd; 590 regs->sci_odata = *data++; 591 icmd |= SCI_ICMD_ACK; 592 regs->sci_icmd = icmd; 593 594 icmd &= ~(SCI_ICMD_DATA|SCI_ICMD_ACK); 595 WAIT_FOR_NOT_REQ(regs); 596 regs->sci_icmd = icmd; 597 ++cnt; 598 if (--count > 0) 599 goto loop; 600 scsi_timeout_error: 601 return cnt; 602 } 603 604 sci_data_in(regs, phase, count, data) 605 register volatile sci_regmap_t *regs; 606 unsigned char *data; 607 { 608 register unsigned char icmd; 609 register int cnt=0; 610 611 /* ..checks.. */ 612 613 icmd = regs->sci_icmd & ~(SCI_ICMD_DIFF|SCI_ICMD_TEST); 614 615 loop: 616 if (SCI_CUR_PHASE(regs->sci_bus_csr) != phase) 617 return cnt; 618 619 WAIT_FOR_REQ(regs); 620 *data++ = regs->sci_data; 621 icmd |= SCI_ICMD_ACK; 622 regs->sci_icmd = icmd; 623 624 icmd &= ~SCI_ICMD_ACK; 625 WAIT_FOR_NOT_REQ(regs); 626 regs->sci_icmd = icmd; 627 ++cnt; 628 if (--count > 0) 629 goto loop; 630 631 scsi_timeout_error: 632 return cnt; 633 } 634 635 static int 636 si_command_transfer(register volatile sci_regmap_t *regs, 637 int maxlen, u_char *data, u_char *status, u_char *msg) 638 { 639 int xfer=0, phase; 640 641 /* printf("command_transfer called for 0x%x.\n", *data); */ 642 643 regs->sci_icmd = 0; 644 645 while (1) { 646 647 WAIT_FOR_REQ(regs); 648 649 phase = SCI_CUR_PHASE(regs->sci_bus_csr); 650 651 switch (phase) { 652 case SCSI_PHASE_CMD: 653 SCI_ACK(regs,SCSI_PHASE_CMD); 654 xfer += sci_data_out(regs, SCSI_PHASE_CMD, 655 maxlen, data); 656 return xfer; 657 case SCSI_PHASE_DATA_IN: 658 printf("Data in phase in command_transfer?\n"); 659 return 0; 660 case SCSI_PHASE_DATA_OUT: 661 printf("Data out phase in command_transfer?\n"); 662 return 0; 663 case SCSI_PHASE_STATUS: 664 SCI_ACK(regs,SCSI_PHASE_STATUS); 665 printf("status in command_transfer.\n"); 666 sci_data_in(regs, SCSI_PHASE_STATUS, 667 1, status); 668 break; 669 case SCSI_PHASE_MESSAGE_IN: 670 SCI_ACK(regs,SCSI_PHASE_MESSAGE_IN); 671 printf("msgin in command_transfer.\n"); 672 sci_data_in(regs, SCSI_PHASE_MESSAGE_IN, 673 1, msg); 674 break; 675 case SCSI_PHASE_MESSAGE_OUT: 676 SCI_ACK(regs,SCSI_PHASE_MESSAGE_OUT); 677 sci_data_out(regs, SCSI_PHASE_MESSAGE_OUT, 678 1, msg); 679 break; 680 default: 681 printf("Unexpected phase 0x%x in " 682 "command_transfer().\n", phase); 683 scsi_timeout_error: 684 return xfer; 685 break; 686 } 687 } 688 } 689 690 static int 691 si_data_transfer(register volatile sci_regmap_t *regs, 692 int maxlen, u_char *data, u_char *status, u_char *msg) 693 { 694 int retlen = 0, xfer, phase; 695 696 regs->sci_icmd = 0; 697 698 *status = 0; 699 700 while (1) { 701 702 WAIT_FOR_REQ(regs); 703 704 phase = SCI_CUR_PHASE(regs->sci_bus_csr); 705 706 switch (phase) { 707 case SCSI_PHASE_CMD: 708 printf("Command phase in data_transfer().\n"); 709 return retlen; 710 case SCSI_PHASE_DATA_IN: 711 SCI_ACK(regs,SCSI_PHASE_DATA_IN); 712 #if PSEUDO_DMA 713 xfer = sci_pdma_in(regs, SCSI_PHASE_DATA_IN, 714 maxlen, data); 715 #else 716 xfer = sci_data_in(regs, SCSI_PHASE_DATA_IN, 717 maxlen, data); 718 #endif 719 retlen += xfer; 720 maxlen -= xfer; 721 break; 722 case SCSI_PHASE_DATA_OUT: 723 SCI_ACK(regs,SCSI_PHASE_DATA_OUT); 724 #if PSEUDO_DMA 725 xfer = sci_pdma_out(regs, SCSI_PHASE_DATA_OUT, 726 maxlen, data); 727 #else 728 xfer = sci_data_out(regs, SCSI_PHASE_DATA_OUT, 729 maxlen, data); 730 #endif 731 retlen += xfer; 732 maxlen -= xfer; 733 break; 734 case SCSI_PHASE_STATUS: 735 SCI_ACK(regs,SCSI_PHASE_STATUS); 736 sci_data_in(regs, SCSI_PHASE_STATUS, 737 1, status); 738 break; 739 case SCSI_PHASE_MESSAGE_IN: 740 SCI_ACK(regs,SCSI_PHASE_MESSAGE_IN); 741 sci_data_in(regs, SCSI_PHASE_MESSAGE_IN, 742 1, msg); 743 if (*msg == 0) { 744 return retlen; 745 } else { 746 printf( "message 0x%x in " 747 "data_transfer.\n", *msg); 748 } 749 break; 750 case SCSI_PHASE_MESSAGE_OUT: 751 SCI_ACK(regs,SCSI_PHASE_MESSAGE_OUT); 752 sci_data_out(regs, SCSI_PHASE_MESSAGE_OUT, 753 1, msg); 754 break; 755 default: 756 printf( "Unexpected phase 0x%x in " 757 "data_transfer().\n", phase); 758 scsi_timeout_error: 759 return retlen; 760 break; 761 } 762 } 763 } 764 765 static int 766 si_dorequest(register volatile sci_regmap_t *regs, 767 int target, int lun, u_char *cmd, int cmdlen, 768 char *databuf, int datalen, int *sent, int *ret) 769 { 770 /* Returns 0 on success, -1 on internal error, or the status byte */ 771 int cmd_bytes_sent, r; 772 u_char stat, msg, c; 773 774 *sent = 0; 775 776 if ( ( r = si_select_target(regs, 7, target, 1) ) != SCSI_RET_SUCCESS) { 777 *ret = r; 778 SCI_CLR_INTR(regs); 779 switch (r) { 780 case SCSI_RET_RETRY: 781 return 0x08; 782 default: 783 printf("si_select_target(target %d, lun %d) failed(%d).\n", 784 target, lun, r); 785 case SCSI_RET_DEVICE_DOWN: 786 return -1; 787 } 788 } 789 790 c = 0x80 | lun; 791 792 if ((cmd_bytes_sent = si_command_transfer(regs, cmdlen, 793 (u_char *) cmd, &stat, &c)) 794 != cmdlen) { 795 SCI_CLR_INTR(regs); 796 *ret = SCSI_RET_COMMAND_FAIL; 797 printf("Data underrun sending CCB (%d bytes of %d, sent).\n", 798 cmd_bytes_sent, cmdlen); 799 return -1; 800 } 801 802 *sent=si_data_transfer(regs, datalen, (u_char *)databuf, 803 &stat, &msg); 804 805 *ret = 0; 806 return stat; 807 } 808 809 static int 810 si_generic(int adapter, int id, int lun, struct scsi_generic *cmd, 811 int cmdlen, void *databuf, int datalen) 812 { 813 register struct ncr5380_softc *ncr5380 = sicd.cd_devs[adapter]; 814 register volatile sci_regmap_t *regs = ncr5380->sc_regs; 815 int i,j,sent,ret; 816 817 if (cmd->opcode == TEST_UNIT_READY) /* XXX */ 818 cmd->bytes[0] = ((u_char) lun << 5); 819 820 i = si_dorequest(regs, id, lun, (u_char *) cmd, cmdlen, 821 databuf, datalen, &sent, &ret); 822 823 return i; 824 } 825 826 static int 827 si_group0(int adapter, int id, int lun, int opcode, int addr, int len, 828 int flags, caddr_t databuf, int datalen) 829 { 830 register struct ncr5380_softc *ncr5380 = sicd.cd_devs[adapter]; 831 register volatile sci_regmap_t *regs = ncr5380->sc_regs; 832 unsigned char cmd[6]; 833 int i,j,sent,ret; 834 835 cmd[0] = opcode; /* Operation code */ 836 cmd[1] = (lun << 5) | ((addr >> 16) & 0x1F); /* Lun & MSB of addr */ 837 cmd[2] = (addr >> 8) & 0xFF; /* addr */ 838 cmd[3] = addr & 0xFF; /* LSB of addr */ 839 cmd[4] = len; /* Allocation length */ 840 cmd[5] = flags; /* Link/Flag */ 841 842 i = si_dorequest(regs, id, lun, cmd, 6, databuf, datalen, &sent, &ret); 843 844 return i; 845 } 846