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.6 1994/07/06 02:53:39 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/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) {register int temp = 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 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 void ncr5380_intr(int adapter); 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, cf, aux) 183 struct device *parent; 184 struct cfdata *cf; 185 void *aux; 186 { 187 caddr_t si_addr; 188 struct obio_cf_loc *obio_loc = (struct obio_cf_loc *) CFDATA_LOC(cf); 189 190 si_addr = OBIO_DEFAULT_PARAM(caddr_t, obio_loc->obio_addr, OBIO_NCR_SCSI); 191 return !obio_probe_byte(si_addr); 192 } 193 194 static void 195 si_attach(parent, self, aux) 196 struct device *parent, *self; 197 void *aux; 198 { 199 caddr_t dvma_malloc(), si_addr; 200 int level, ncr_intr(), unit = DEVICE_UNIT(self); 201 struct ncr5380_softc *ncr5380 = (struct ncr5380_softc *) self; 202 struct obio_cf_loc *obio_loc = OBIO_LOC(self); 203 struct cfdata *new_match; 204 205 si_addr = OBIO_DEFAULT_PARAM(caddr_t, obio_loc->obio_addr, OBIO_NCR_SCSI); 206 ncr5380->sc_regs = (sci_regmap_t *) 207 obio_alloc(si_addr, OBIO_NCR_SCSI_SIZE, OBIO_WRITE); 208 209 level = OBIO_DEFAULT_PARAM(int, obio_loc->obio_level, 2); 210 211 ncr5380->sc_link.scsibus = unit; /* needed? */ 212 ncr5380->sc_link.adapter_softc = ncr5380; 213 ncr5380->sc_link.adapter_targ = 7; 214 ncr5380->sc_link.adapter = &ncr5380_switch; 215 ncr5380->sc_link.device = &ncr_dev; 216 217 obio_print(si_addr, level); 218 printf("\n"); 219 220 config_found(self, &(ncr5380->sc_link), si_print); 221 } 222 223 static u_int 224 ncr5380_adapter_info(struct ncr5380_softc *ncr5380) 225 { 226 return 1; 227 } 228 229 #define MIN_PHYS 65536 /*BARF!!!!*/ 230 static void 231 ncr5380_minphys(struct buf *bp) 232 { 233 if (bp->b_bcount > MIN_PHYS) { 234 printf("Uh-oh... ncr5380_minphys setting bp->b_bcount = %x.\n", MIN_PHYS); 235 bp->b_bcount = MIN_PHYS; 236 } 237 } 238 #undef MIN_PHYS 239 240 static int 241 ncr5380_scsi_cmd(struct scsi_xfer *xs) 242 { 243 int flags, s, r; 244 245 flags = xs->flags; 246 if (xs->bp) flags |= (SCSI_NOSLEEP); 247 if ( flags & ITSDONE ) { 248 printf("Already done?"); 249 xs->flags &= ~ITSDONE; 250 } 251 if ( ! ( flags & INUSE ) ) { 252 printf("Not in use?"); 253 xs->flags |= INUSE; 254 } 255 256 if ( flags & SCSI_RESET ) { 257 printf("flags & SCSIRESET.\n"); 258 if ( ! ( flags & SCSI_NOSLEEP ) ) { 259 s = splbio(); 260 ncr5380_reset_target(xs->sc_link->scsibus, xs->sc_link->target); 261 splx(s); 262 return(SUCCESSFULLY_QUEUED); 263 } else { 264 ncr5380_reset_target(xs->sc_link->scsibus, xs->sc_link->target); 265 if (ncr5380_poll(xs->sc_link->scsibus, xs->timeout)) { 266 return (HAD_ERROR); 267 } 268 return (COMPLETE); 269 } 270 } 271 #if 0 272 /* 273 * OK. Now that that's over with, let's pack up that 274 * SCSI puppy and send it off. If we can, we'll just 275 * queue and go; otherwise, we'll wait for the command 276 * to finish. 277 */ 278 if ( ! ( flags & SCSI_NOSLEEP ) ) { 279 s = splbio(); 280 ncr5380_send_cmd(xs); 281 splx(s); 282 return(SUCCESSFULLY_QUEUED); 283 } 284 #endif 285 286 r = ncr5380_send_cmd(xs); 287 xs->flags |= ITSDONE; 288 scsi_done(xs); 289 switch(r) { 290 case COMPLETE: 291 case SUCCESSFULLY_QUEUED: 292 r = SUCCESSFULLY_QUEUED; 293 if (xs->flags&SCSI_NOMASK) 294 r = COMPLETE; 295 break; 296 default: 297 break; 298 } 299 return r; 300 #if 0 301 do { 302 if (ncr5380_poll(xs->sc_link->scsibus, xs->timeout)) { 303 if ( ! ( xs->flags & SCSI_SILENT ) ) 304 printf("cmd fail.\n"); 305 cmd_cleanup 306 xs->error = XS_DRIVER_STUFFUP; 307 splx(s); 308 } 309 } while ( ! ( xs->flags & ITSDONE ) ); 310 #endif 311 } 312 313 static int 314 ncr5380_show_scsi_cmd(struct scsi_xfer *xs) 315 { 316 u_char *b = (u_char *) xs->cmd; 317 int i = 0; 318 319 if ( ! ( xs->flags & SCSI_RESET ) ) { 320 printf("si(%d:%d:%d)-", 321 xs->sc_link->scsibus, 322 xs->sc_link->target, 323 xs->sc_link->lun); 324 while (i < xs->cmdlen) { 325 if (i) printf(","); 326 printf("%x",b[i++]); 327 } 328 printf("-\n"); 329 } else { 330 printf("si(%d:%d:%d)-RESET-\n", 331 xs->sc_link->scsibus, 332 xs->sc_link->target, 333 xs->sc_link->lun); 334 } 335 } 336 337 /* 338 * Actual chip control. 339 */ 340 341 void 342 ncr5380_intr(int adapter) 343 { 344 register struct ncr5380_softc *ncr5380 = sicd.cd_devs[adapter]; 345 register volatile sci_regmap_t *regs = ncr5380->sc_regs; 346 347 SCI_CLR_INTR(regs); 348 regs->sci_mode = 0x00; 349 #ifdef DEBUG 350 printf ("ncr_intr\n"); 351 #endif 352 } 353 354 int 355 scsi_irq_intr(void) 356 { 357 #if 0 /* XXX - no way to get regs */ 358 register volatile sci_regmap_t *regs = ncr; 359 if (regs->sci_csr != SCI_CSR_PHASE_MATCH) 360 printf("scsi_irq_intr called (not just phase match -- " 361 "csr = 0x%x, bus_csr = 0x%x).\n", 362 regs->sci_csr, regs->sci_bus_csr); 363 ncr5380_intr(0); 364 #endif 365 return 1; 366 } 367 368 int 369 scsi_drq_intr(void) 370 { 371 #if 0 372 printf("scsi_drq_intr called.\n"); 373 ncr5380_intr(0); 374 #endif 375 return 1; 376 } 377 378 static int 379 ncr5380_reset_target(int adapter, int target) 380 { 381 register struct ncr5380_softc *ncr5380 = sicd.cd_devs[adapter]; 382 register volatile sci_regmap_t *regs = ncr5380->sc_regs; 383 int dummy; 384 385 regs->sci_icmd = SCI_ICMD_TEST; 386 regs->sci_icmd = SCI_ICMD_TEST | SCI_ICMD_RST; 387 delay(2500); 388 regs->sci_icmd = 0; 389 390 regs->sci_mode = 0; 391 regs->sci_tcmd = SCI_PHASE_DISC; 392 regs->sci_sel_enb = 0; 393 394 SCI_CLR_INTR(regs); 395 SCI_CLR_INTR(regs); 396 } 397 398 static int 399 ncr5380_poll(int adapter, int timeout) 400 { 401 } 402 403 static int 404 ncr5380_send_cmd(struct scsi_xfer *xs) 405 { 406 int s; 407 int sense; 408 409 /* ncr5380_show_scsi_cmd(xs); */ 410 s = splbio(); 411 sense = si_generic( xs->sc_link->scsibus, xs->sc_link->target, 412 xs->sc_link->lun, xs->cmd, xs->cmdlen, 413 xs->data, xs->datalen ); 414 splx(s); 415 if (sense) { 416 switch (sense) { 417 case 0x02: /* Check condition */ 418 #ifdef DEBUG 419 printf("check cond. target %d.\n", 420 xs->sc_link->target); 421 #endif 422 delay(10); /* Phil's fix for slow devices. */ 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