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