1 /* $NetBSD: siop.c,v 1.4 2014/06/14 20:50:12 phx Exp $ */ 2 /* 3 * Copyright (c) 2010 KIYOHARA Takashi 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 19 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 21 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 23 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 24 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 * POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28 #include <lib/libsa/stand.h> 29 #include <lib/libkern/libkern.h> 30 31 #include <dev/microcode/siop/siop.out> 32 33 #include "boot.h" 34 #include "sdvar.h" 35 36 #ifdef DEBUG 37 #define DPRINTF(x) printf x 38 #else 39 #define DPRINTF(x) 40 #endif 41 42 #define ALLOC(T, A) \ 43 (T *)(((uint32_t)alloc(sizeof(T) + (A)) + (A)) & ~((A) - 1)) 44 #define VTOPHYS(va) (uint32_t)(va) 45 #define DEVTOV(pa) (uint32_t)(pa) 46 #define wbinv(adr, siz) _wbinv(VTOPHYS(adr), (uint32_t)(siz)) 47 #define inv(adr, siz) _inv(VTOPHYS(adr), (uint32_t)(siz)) 48 49 /* 53c810 supports little endian */ 50 #define htoc32(x) htole32(x) 51 #define ctoh32(x) le32toh(x) 52 53 static void siop_pci_reset(int); 54 55 static void siop_setuptables(struct siop_adapter *, struct siop_xfer *, 56 struct scsi_xfer *); 57 static void siop_ma(struct siop_adapter *, struct scsi_xfer *); 58 static void siop_sdp(struct siop_adapter *, struct siop_xfer *, 59 struct scsi_xfer *, int); 60 static void siop_update_resid(struct siop_adapter *, struct siop_xfer *, 61 struct scsi_xfer *, int); 62 63 static int siop_intr(struct siop_adapter *); 64 static void siop_scsicmd_end(struct siop_adapter *, struct scsi_xfer *); 65 static int siop_scsi_request(struct siop_adapter *, struct scsi_xfer *); 66 static void siop_start(struct siop_adapter *, struct scsi_xfer *); 67 static void siop_xfer_setup(struct siop_xfer *, void *); 68 69 static int siop_add_reselsw(struct siop_adapter *, int, int); 70 static void siop_update_scntl3(struct siop_adapter *, int, int); 71 72 static int _scsi_inquire(struct siop_adapter *, int, int, int, char *); 73 static void scsi_request_sense(struct siop_adapter *, struct scsi_xfer *); 74 static int scsi_interpret_sense(struct siop_adapter *, struct scsi_xfer *); 75 static int scsi_probe(struct siop_adapter *); 76 77 static struct siop_adapter adapt; 78 79 80 static void 81 siop_pci_reset(int addr) 82 { 83 int dmode, ctest5; 84 const int maxburst = 4; /* 53c810 */ 85 86 dmode = readb(addr + SIOP_DMODE); 87 88 ctest5 = readb(addr + SIOP_CTEST5); 89 writeb(addr + SIOP_CTEST4, readb(addr + SIOP_CTEST4) & ~CTEST4_BDIS); 90 ctest5 &= ~CTEST5_BBCK; 91 ctest5 |= (maxburst - 1) & CTEST5_BBCK; 92 writeb(addr + SIOP_CTEST5, ctest5); 93 94 dmode |= DMODE_ERL; 95 dmode &= ~DMODE_BL_MASK; 96 dmode |= ((maxburst - 1) << DMODE_BL_SHIFT) & DMODE_BL_MASK; 97 writeb(addr + SIOP_DMODE, dmode); 98 } 99 100 101 static void 102 siop_setuptables(struct siop_adapter *adp, struct siop_xfer *xfer, 103 struct scsi_xfer *xs) 104 { 105 int msgoffset = 1; 106 107 xfer->siop_tables.id = 108 htoc32((adp->clock_div << 24) | (xs->target << 16)); 109 memset(xfer->siop_tables.msg_out, 0, sizeof(xfer->siop_tables.msg_out)); 110 /* request sense doesn't disconnect */ 111 if (xs->cmd->opcode == SCSI_REQUEST_SENSE) 112 xfer->siop_tables.msg_out[0] = MSG_IDENTIFY(xs->lun, 0); 113 else 114 xfer->siop_tables.msg_out[0] = MSG_IDENTIFY(xs->lun, 1); 115 116 xfer->siop_tables.t_msgout.count = htoc32(msgoffset); 117 xfer->siop_tables.status = 118 htoc32(SCSI_SIOP_NOSTATUS); /* set invalid status */ 119 120 xfer->siop_tables.cmd.count = htoc32(xs->cmdlen); 121 xfer->siop_tables.cmd.addr = htoc32(local_to_PCI((u_long)xs->cmd)); 122 if (xs->datalen != 0) { 123 xfer->siop_tables.data[0].count = htoc32(xs->datalen); 124 xfer->siop_tables.data[0].addr = 125 htoc32(local_to_PCI((u_long)xs->data)); 126 } 127 } 128 129 static void 130 siop_ma(struct siop_adapter *adp, struct scsi_xfer *xs) 131 { 132 int offset, dbc; 133 134 /* 135 * compute how much of the current table didn't get handled when 136 * a phase mismatch occurs 137 */ 138 if (xs->datalen == 0) 139 return; /* no valid data transfer */ 140 141 offset = readb(adp->addr + SIOP_SCRATCHA + 1); 142 if (offset >= SIOP_NSG) { 143 printf("bad offset in siop_sdp (%d)\n", offset); 144 return; 145 } 146 dbc = readl(adp->addr + SIOP_DBC) & 0x00ffffff; 147 xs->resid = dbc; 148 } 149 150 static void 151 siop_clearfifo(struct siop_adapter *adp) 152 { 153 int timo = 0; 154 uint8_t ctest3 = readb(adp->addr + SIOP_CTEST3); 155 156 DPRINTF(("DMA FIFO not empty!\n")); 157 writeb(adp->addr + SIOP_CTEST3, ctest3 | CTEST3_CLF); 158 while ((readb(adp->addr + SIOP_CTEST3) & CTEST3_CLF) != 0) { 159 delay(1); 160 if (++timo > 1000) { 161 printf("Clear FIFO failed!\n"); 162 writeb(adp->addr + SIOP_CTEST3, 163 readb(adp->addr + SIOP_CTEST3) & ~CTEST3_CLF); 164 return; 165 } 166 } 167 } 168 169 static void 170 siop_sdp(struct siop_adapter *adp, struct siop_xfer *xfer, struct scsi_xfer *xs, 171 int offset) 172 { 173 174 if (xs->datalen == 0) 175 return; /* no data pointers to save */ 176 177 /* 178 * offset == SIOP_NSG may be a valid condition if we get a Save data 179 * pointer when the xfer is done. Just ignore the Save data pointer 180 * in this case 181 */ 182 if (offset == SIOP_NSG) 183 return; 184 /* 185 * Save data pointer. We do this by adjusting the tables to point 186 * at the begginning of the data not yet transfered. 187 * offset points to the first table with untransfered data. 188 */ 189 190 /* 191 * before doing that we decrease resid from the ammount of data which 192 * has been transfered. 193 */ 194 siop_update_resid(adp, xfer, xs, offset); 195 196 #if 0 197 /* 198 * First let see if we have a resid from a phase mismatch. If so, 199 * we have to adjst the table at offset to remove transfered data. 200 */ 201 if (siop_cmd->flags & CMDFL_RESID) { 202 scr_table_t *table; 203 204 siop_cmd->flags &= ~CMDFL_RESID; 205 table = &xfer->siop_tables.data[offset]; 206 /* "cut" already transfered data from this table */ 207 table->addr = 208 htoc32(ctoh32(table->addr) + ctoh32(table->count) - 209 siop_cmd->resid); 210 table->count = htoc32(siop_cmd->resid); 211 } 212 #endif 213 214 /* 215 * now we can remove entries which have been transfered. 216 * We just move the entries with data left at the beggining of the 217 * tables 218 */ 219 memmove(xfer->siop_tables.data, &xfer->siop_tables.data[offset], 220 (SIOP_NSG - offset) * sizeof(scr_table_t)); 221 } 222 223 static void 224 siop_update_resid(struct siop_adapter *adp, struct siop_xfer *xfer, 225 struct scsi_xfer *xs, int offset) 226 { 227 int i; 228 229 if (xs->datalen == 0) 230 return; /* no data to transfer */ 231 232 /* 233 * update resid. First account for the table entries which have 234 * been fully completed. 235 */ 236 for (i = 0; i < offset; i++) 237 xs->resid -= ctoh32(xfer->siop_tables.data[i].count); 238 #if 0 239 /* 240 * if CMDFL_RESID is set, the last table (pointed by offset) is a 241 * partial transfers. If not, offset points to the entry folloing 242 * the last full transfer. 243 */ 244 if (siop_cmd->flags & CMDFL_RESID) { 245 scr_table_t *table = &xfer->siop_tables.data[offset]; 246 247 xs->resid -= ctoh32(table->count) - xs->resid; 248 } 249 #endif 250 } 251 252 253 #define CALL_SCRIPT(ent) writel(adp->addr + SIOP_DSP, scriptaddr + ent); 254 255 static int 256 siop_intr(struct siop_adapter *adp) 257 { 258 struct siop_xfer *siop_xfer = NULL; 259 struct scsi_xfer *xs = NULL; 260 u_long scriptaddr = local_to_PCI((u_long)adp->script); 261 int offset, target, lun, tag, restart = 0, need_reset = 0; 262 uint32_t dsa, irqcode; 263 uint16_t sist; 264 uint8_t dstat, sstat1, istat; 265 266 istat = readb(adp->addr + SIOP_ISTAT); 267 if ((istat & (ISTAT_INTF | ISTAT_DIP | ISTAT_SIP)) == 0) 268 return 0; 269 if (istat & ISTAT_INTF) { 270 printf("INTRF\n"); 271 writeb(adp->addr + SIOP_ISTAT, ISTAT_INTF); 272 } 273 if ((istat & (ISTAT_DIP | ISTAT_SIP | ISTAT_ABRT)) == 274 (ISTAT_DIP | ISTAT_ABRT)) 275 /* clear abort */ 276 writeb(adp->addr + SIOP_ISTAT, 0); 277 /* use DSA to find the current siop_cmd */ 278 dsa = readl(adp->addr + SIOP_DSA); 279 if (dsa >= local_to_PCI((u_long)adp->xfer) && 280 dsa < local_to_PCI((u_long)adp->xfer) + SIOP_TABLE_SIZE) { 281 dsa -= local_to_PCI((u_long)adp->xfer); 282 siop_xfer = adp->xfer; 283 _inv((u_long)siop_xfer, sizeof(*siop_xfer)); 284 285 xs = adp->xs; 286 } 287 288 if (istat & ISTAT_DIP) 289 dstat = readb(adp->addr + SIOP_DSTAT); 290 if (istat & ISTAT_SIP) { 291 if (istat & ISTAT_DIP) 292 delay(10); 293 /* 294 * Can't read sist0 & sist1 independently, or we have to 295 * insert delay 296 */ 297 sist = readw(adp->addr + SIOP_SIST0); 298 sstat1 = readb(adp->addr + SIOP_SSTAT1); 299 300 if ((sist & SIST0_MA) && need_reset == 0) { 301 if (siop_xfer) { 302 int scratcha0; 303 304 dstat = readb(adp->addr + SIOP_DSTAT); 305 /* 306 * first restore DSA, in case we were in a S/G 307 * operation. 308 */ 309 writel(adp->addr + SIOP_DSA, 310 local_to_PCI((u_long)siop_xfer)); 311 scratcha0 = readb(adp->addr + SIOP_SCRATCHA); 312 switch (sstat1 & SSTAT1_PHASE_MASK) { 313 case SSTAT1_PHASE_STATUS: 314 /* 315 * previous phase may be aborted for any reason 316 * ( for example, the target has less data to 317 * transfer than requested). Compute resid and 318 * just go to status, the command should 319 * terminate. 320 */ 321 if (scratcha0 & A_flag_data) 322 siop_ma(adp, xs); 323 else if ((dstat & DSTAT_DFE) == 0) 324 siop_clearfifo(adp); 325 CALL_SCRIPT(Ent_status); 326 return 1; 327 case SSTAT1_PHASE_MSGIN: 328 /* 329 * target may be ready to disconnect 330 * Compute resid which would be used later 331 * if a save data pointer is needed. 332 */ 333 if (scratcha0 & A_flag_data) 334 siop_ma(adp, xs); 335 else if ((dstat & DSTAT_DFE) == 0) 336 siop_clearfifo(adp); 337 writeb(adp->addr + SIOP_SCRATCHA, 338 scratcha0 & ~A_flag_data); 339 CALL_SCRIPT(Ent_msgin); 340 return 1; 341 } 342 printf("unexpected phase mismatch %d\n", 343 sstat1 & SSTAT1_PHASE_MASK); 344 } else 345 printf("phase mismatch without command\n"); 346 need_reset = 1; 347 } 348 if (sist & (SIST1_STO << 8)) { 349 /* selection time out, assume there's no device here */ 350 if (siop_xfer) { 351 xs->error = XS_SELTIMEOUT; 352 goto end; 353 } else 354 printf("selection timeout without command\n"); 355 } 356 357 /* Else it's an unhandled exception (for now). */ 358 printf("unhandled scsi interrupt," 359 " sist=0x%x sstat1=0x%x DSA=0x%x DSP=0x%lx\n", 360 sist, sstat1, dsa, 361 readl(adp->addr + SIOP_DSP) - scriptaddr); 362 if (siop_xfer) { 363 xs->error = XS_SELTIMEOUT; 364 goto end; 365 } 366 need_reset = 1; 367 } 368 if (need_reset) { 369 reset: 370 printf("XXXXX: fatal error, need reset the bus...\n"); 371 return 1; 372 } 373 374 //scintr: 375 if ((istat & ISTAT_DIP) && (dstat & DSTAT_SIR)) { /* script interrupt */ 376 irqcode = readl(adp->addr + SIOP_DSPS); 377 /* 378 * no command, or an inactive command is only valid for a 379 * reselect interrupt 380 */ 381 if ((irqcode & 0x80) == 0) { 382 if (siop_xfer == NULL) { 383 printf( 384 "script interrupt 0x%x with invalid DSA\n", 385 irqcode); 386 goto reset; 387 } 388 } 389 switch(irqcode) { 390 case A_int_err: 391 printf("error, DSP=0x%lx\n", 392 readl(adp->addr + SIOP_DSP) - scriptaddr); 393 if (xs) { 394 xs->error = XS_SELTIMEOUT; 395 goto end; 396 } else { 397 goto reset; 398 } 399 case A_int_reseltarg: 400 printf("reselect with invalid target\n"); 401 goto reset; 402 case A_int_resellun: 403 target = readb(adp->addr + SIOP_SCRATCHA) & 0xf; 404 lun = readb(adp->addr + SIOP_SCRATCHA + 1); 405 tag = readb(adp->addr + SIOP_SCRATCHA + 2); 406 if (target != adp->xs->target || 407 lun != adp->xs->lun || 408 tag != 0) { 409 printf("unknwon resellun:" 410 " target %d lun %d tag %d\n", 411 target, lun, tag); 412 goto reset; 413 } 414 siop_xfer = adp->xfer; 415 dsa = local_to_PCI((u_long)siop_xfer); 416 writel(adp->addr + SIOP_DSP, 417 dsa + sizeof(struct siop_common_xfer) + 418 Ent_ldsa_reload_dsa); 419 _wbinv((u_long)siop_xfer, sizeof(*siop_xfer)); 420 return 1; 421 case A_int_reseltag: 422 printf("reselect with invalid tag\n"); 423 goto reset; 424 case A_int_disc: 425 offset = readb(adp->addr + SIOP_SCRATCHA + 1); 426 siop_sdp(adp, siop_xfer, xs, offset); 427 #if 0 428 /* we start again with no offset */ 429 siop_cmd->saved_offset = SIOP_NOOFFSET; 430 #endif 431 _wbinv((u_long)siop_xfer, sizeof(*siop_xfer)); 432 CALL_SCRIPT(Ent_script_sched); 433 return 1; 434 case A_int_resfail: 435 printf("reselect failed\n"); 436 return 1; 437 case A_int_done: 438 if (xs == NULL) { 439 printf("done without command, DSA=0x%lx\n", 440 local_to_PCI((u_long)adp->xfer)); 441 return 1; 442 } 443 /* update resid. */ 444 offset = readb(adp->addr + SIOP_SCRATCHA + 1); 445 #if 0 446 /* 447 * if we got a disconnect between the last data phase 448 * and the status phase, offset will be 0. In this 449 * case, siop_cmd->saved_offset will have the proper 450 * value if it got updated by the controller 451 */ 452 if (offset == 0 && 453 siop_cmd->saved_offset != SIOP_NOOFFSET) 454 offset = siop_cmd->saved_offset; 455 #endif 456 siop_update_resid(adp, siop_xfer, xs, offset); 457 goto end; 458 default: 459 printf("unknown irqcode %x\n", irqcode); 460 if (xs) { 461 xs->error = XS_SELTIMEOUT; 462 goto end; 463 } 464 goto reset; 465 } 466 return 1; 467 } 468 /* We just should't get there */ 469 panic("siop_intr: I shouldn't be there !"); 470 471 return 1; 472 473 end: 474 /* 475 * restart the script now if command completed properly 476 * Otherwise wait for siop_scsicmd_end(), we may need to cleanup the 477 * queue 478 */ 479 xs->status = ctoh32(siop_xfer->siop_tables.status); 480 if (xs->status == SCSI_OK) 481 writel(adp->addr + SIOP_DSP, scriptaddr + Ent_script_sched); 482 else 483 restart = 1; 484 siop_scsicmd_end(adp, xs); 485 if (restart) 486 writel(adp->addr + SIOP_DSP, scriptaddr + Ent_script_sched); 487 488 return 1; 489 } 490 491 static void 492 siop_scsicmd_end(struct siop_adapter *adp, struct scsi_xfer *xs) 493 { 494 495 switch(xs->status) { 496 case SCSI_OK: 497 xs->error = XS_NOERROR; 498 break; 499 case SCSI_BUSY: 500 case SCSI_CHECK: 501 case SCSI_QUEUE_FULL: 502 xs->error = XS_BUSY; 503 break; 504 case SCSI_SIOP_NOCHECK: 505 /* 506 * don't check status, xs->error is already valid 507 */ 508 break; 509 case SCSI_SIOP_NOSTATUS: 510 /* 511 * the status byte was not updated, cmd was 512 * aborted 513 */ 514 xs->error = XS_SELTIMEOUT; 515 break; 516 default: 517 printf("invalid status code %d\n", xs->status); 518 xs->error = XS_DRIVER_STUFFUP; 519 } 520 _inv((u_long)xs->cmd, xs->cmdlen); 521 if (xs->datalen != 0) 522 _inv((u_long)xs->data, xs->datalen); 523 xs->xs_status = XS_STS_DONE; 524 } 525 526 static int 527 siop_scsi_request(struct siop_adapter *adp, struct scsi_xfer *xs) 528 { 529 void *xfer = adp->xfer; 530 int timo, error; 531 532 if (adp->sel_t != xs->target) { 533 const int free_lo = __arraycount(siop_script); 534 int i; 535 void *scriptaddr = (void *)local_to_PCI((u_long)adp->script); 536 537 if (adp->sel_t != -1) 538 adp->script[Ent_resel_targ0 / 4 + adp->sel_t * 2] = 539 htoc32(0x800c00ff); 540 541 for (i = 0; i < __arraycount(lun_switch); i++) 542 adp->script[free_lo + i] = htoc32(lun_switch[i]); 543 adp->script[free_lo + E_abs_lunsw_return_Used[0]] = 544 htoc32(scriptaddr + Ent_lunsw_return); 545 546 siop_add_reselsw(adp, xs->target, free_lo); 547 548 adp->sel_t = xs->target; 549 } 550 551 restart: 552 553 siop_setuptables(adp, xfer, xs); 554 555 /* load the DMA maps */ 556 if (xs->datalen != 0) 557 _inv((u_long)xs->data, xs->datalen); 558 _wbinv((u_long)xs->cmd, xs->cmdlen); 559 560 _wbinv((u_long)xfer, sizeof(struct siop_xfer)); 561 siop_start(adp, xs); 562 563 adp->xs = xs; 564 timo = 0; 565 while (!(xs->xs_status & XS_STS_DONE)) { 566 delay(1000); 567 siop_intr(adp); 568 569 if (timo++ > 3000) { /* XXXX: 3sec */ 570 printf("%s: timeout\n", __func__); 571 return ETIMEDOUT; 572 } 573 } 574 575 if (xs->error != XS_NOERROR) { 576 if (xs->error == XS_BUSY || xs->status == SCSI_CHECK) 577 scsi_request_sense(adp, xs); 578 579 switch (xs->error) { 580 case XS_SENSE: 581 case XS_SHORTSENSE: 582 error = scsi_interpret_sense(adp, xs); 583 break; 584 case XS_RESOURCE_SHORTAGE: 585 printf("adapter resource shortage\n"); 586 587 /* FALLTHROUGH */ 588 case XS_BUSY: 589 error = EBUSY; 590 break; 591 case XS_REQUEUE: 592 printf("XXXX: requeue...\n"); 593 error = ERESTART; 594 break; 595 case XS_SELTIMEOUT: 596 case XS_TIMEOUT: 597 error = EIO; 598 break; 599 case XS_RESET: 600 error = EIO; 601 break; 602 case XS_DRIVER_STUFFUP: 603 printf("generic HBA error\n"); 604 error = EIO; 605 break; 606 default: 607 printf("invalid return code from adapter: %d\n", 608 xs->error); 609 error = EIO; 610 break; 611 } 612 if (error == ERESTART) { 613 xs->error = XS_NOERROR; 614 xs->status = SCSI_OK; 615 xs->xs_status &= ~XS_STS_DONE; 616 goto restart; 617 } 618 return error; 619 } 620 return 0; 621 } 622 623 static void 624 siop_start(struct siop_adapter *adp, struct scsi_xfer *xs) 625 { 626 struct siop_xfer *siop_xfer = adp->xfer; 627 uint32_t dsa, *script = adp->script; 628 int target, lun, slot; 629 void *scriptaddr = (void *)local_to_PCI((u_long)script); 630 const int siop_common_xfer_size = sizeof(struct siop_common_xfer); 631 632 /* 633 * The queue management here is a bit tricky: the script always looks 634 * at the slot from first to last, so if we always use the first 635 * free slot commands can stay at the tail of the queue ~forever. 636 * The algorithm used here is to restart from the head when we know 637 * that the queue is empty, and only add commands after the last one. 638 * When we're at the end of the queue wait for the script to clear it. 639 * The best thing to do here would be to implement a circular queue, 640 * but using only 53c720 features this can be "interesting". 641 * A mid-way solution could be to implement 2 queues and swap orders. 642 */ 643 slot = adp->currschedslot; 644 /* 645 * If the instruction is 0x80000000 (JUMP foo, IF FALSE) the slot is 646 * free. As this is the last used slot, all previous slots are free, 647 * we can restart from 0. 648 */ 649 if (ctoh32(script[(Ent_script_sched_slot0 / 4) + slot * 2]) == 650 0x80000000) { 651 slot = adp->currschedslot = 0; 652 } else { 653 slot++; 654 } 655 target = xs->target; 656 lun = xs->lun; 657 /* 658 * find a free scheduler slot and load it. 659 */ 660 #define SIOP_NSLOTS 0x40 661 for (; slot < SIOP_NSLOTS; slot++) { 662 /* 663 * If cmd if 0x80000000 the slot is free 664 */ 665 if (ctoh32(script[(Ent_script_sched_slot0 / 4) + slot * 2]) == 666 0x80000000) 667 break; 668 } 669 if (slot == SIOP_NSLOTS) { 670 /* 671 * no more free slot, no need to continue. freeze the queue 672 * and requeue this command. 673 */ 674 printf("no mode free slot\n"); 675 return; 676 } 677 678 /* patch scripts with DSA addr */ 679 dsa = local_to_PCI((u_long)siop_xfer); 680 681 /* CMD script: MOVE MEMORY addr */ 682 siop_xfer->resel[E_ldsa_abs_slot_Used[0]] = 683 htoc32(scriptaddr + Ent_script_sched_slot0 + slot * 8); 684 _wbinv((u_long)siop_xfer, sizeof(*siop_xfer)); 685 /* scheduler slot: JUMP ldsa_select */ 686 script[(Ent_script_sched_slot0 / 4) + slot * 2 + 1] = 687 htoc32(dsa + siop_common_xfer_size + Ent_ldsa_select); 688 /* 689 * Change JUMP cmd so that this slot will be handled 690 */ 691 script[(Ent_script_sched_slot0 / 4) + slot * 2] = htoc32(0x80080000); 692 adp->currschedslot = slot; 693 694 /* make sure SCRIPT processor will read valid data */ 695 _wbinv((u_long)script, SIOP_SCRIPT_SIZE); 696 /* Signal script it has some work to do */ 697 writeb(adp->addr + SIOP_ISTAT, ISTAT_SIGP); 698 /* and wait for IRQ */ 699 } 700 701 static void 702 siop_xfer_setup(struct siop_xfer *xfer, void *scriptaddr) 703 { 704 const int off_msg_in = offsetof(struct siop_common_xfer, msg_in); 705 const int off_status = offsetof(struct siop_common_xfer, status); 706 uint32_t dsa, *scr; 707 int i; 708 709 memset(xfer, 0, sizeof(*xfer)); 710 dsa = local_to_PCI((u_long)xfer); 711 xfer->siop_tables.t_msgout.count = htoc32(1); 712 xfer->siop_tables.t_msgout.addr = htoc32(dsa); 713 xfer->siop_tables.t_msgin.count = htoc32(1); 714 xfer->siop_tables.t_msgin.addr = htoc32(dsa + off_msg_in); 715 xfer->siop_tables.t_extmsgin.count = htoc32(2); 716 xfer->siop_tables.t_extmsgin.addr = htoc32(dsa + off_msg_in + 1); 717 xfer->siop_tables.t_extmsgdata.addr = htoc32(dsa + off_msg_in + 3); 718 xfer->siop_tables.t_status.count = htoc32(1); 719 xfer->siop_tables.t_status.addr = htoc32(dsa + off_status); 720 721 /* The select/reselect script */ 722 scr = xfer->resel; 723 for (i = 0; i < __arraycount(load_dsa); i++) 724 scr[i] = htoc32(load_dsa[i]); 725 726 /* 727 * 0x78000000 is a 'move data8 to reg'. data8 is the second 728 * octet, reg offset is the third. 729 */ 730 scr[Ent_rdsa0 / 4] = htoc32(0x78100000 | ((dsa & 0x000000ff) << 8)); 731 scr[Ent_rdsa1 / 4] = htoc32(0x78110000 | ( dsa & 0x0000ff00 )); 732 scr[Ent_rdsa2 / 4] = htoc32(0x78120000 | ((dsa & 0x00ff0000) >> 8)); 733 scr[Ent_rdsa3 / 4] = htoc32(0x78130000 | ((dsa & 0xff000000) >> 16)); 734 scr[E_ldsa_abs_reselected_Used[0]] = 735 htoc32(scriptaddr + Ent_reselected); 736 scr[E_ldsa_abs_reselect_Used[0]] = htoc32(scriptaddr + Ent_reselect); 737 scr[E_ldsa_abs_selected_Used[0]] = htoc32(scriptaddr + Ent_selected); 738 scr[E_ldsa_abs_data_Used[0]] = 739 htoc32(dsa + sizeof(struct siop_common_xfer) + Ent_ldsa_data); 740 /* JUMP foo, IF FALSE - used by MOVE MEMORY to clear the slot */ 741 scr[Ent_ldsa_data / 4] = htoc32(0x80000000); 742 } 743 744 static int 745 siop_add_reselsw(struct siop_adapter *adp, int target, int lunsw_off) 746 { 747 uint32_t *script = adp->script; 748 int reseloff; 749 void *scriptaddr = (void *)local_to_PCI((u_long)adp->script); 750 751 /* 752 * add an entry to resel switch 753 */ 754 reseloff = Ent_resel_targ0 / 4 + target * 2; 755 if ((ctoh32(script[reseloff]) & 0xff) != 0xff) { 756 /* it's not free */ 757 printf("siop: resel switch full\n"); 758 return EBUSY; 759 } 760 761 /* JUMP abs_foo, IF target | 0x80; */ 762 script[reseloff + 0] = htoc32(0x800c0080 | target); 763 script[reseloff + 1] = 764 htoc32(scriptaddr + lunsw_off * 4 + Ent_lun_switch_entry); 765 766 siop_update_scntl3(adp, target, lunsw_off); 767 return 0; 768 } 769 770 static void 771 siop_update_scntl3(struct siop_adapter *adp, int target, int lunsw_off) 772 { 773 uint32_t *script = adp->script; 774 775 /* MOVE target->id >> 24 TO SCNTL3 */ 776 script[lunsw_off + (Ent_restore_scntl3 / 4)] = 777 htoc32(0x78030000 | ((adp->clock_div >> 16) & 0x0000ff00)); 778 /* MOVE target->id >> 8 TO SXFER */ 779 script[lunsw_off + (Ent_restore_scntl3 / 4) + 2] = 780 htoc32(0x78050000 | (0x000000000 & 0x0000ff00)); 781 _wbinv((u_long)script, SIOP_SCRIPT_SIZE); 782 } 783 784 785 /* 786 * SCSI functions 787 */ 788 789 static int 790 _scsi_inquire(struct siop_adapter *adp, int t, int l, int buflen, char *buf) 791 { 792 struct scsipi_inquiry *cmd = (struct scsipi_inquiry *)adp->cmd; 793 struct scsipi_inquiry_data *inqbuf = 794 (struct scsipi_inquiry_data *)adp->data; 795 struct scsi_xfer xs; 796 int error; 797 798 memset(cmd, 0, sizeof(*cmd)); 799 cmd->opcode = INQUIRY; 800 cmd->length = SCSIPI_INQUIRY_LENGTH_SCSI2; 801 memset(inqbuf, 0, sizeof(*inqbuf)); 802 803 memset(&xs, 0, sizeof(xs)); 804 xs.target = t; 805 xs.lun = l; 806 xs.cmdlen = sizeof(*cmd); 807 xs.cmd = (void *)cmd; 808 xs.datalen = SCSIPI_INQUIRY_LENGTH_SCSI2; 809 xs.data = (void *)inqbuf; 810 811 xs.error = XS_NOERROR; 812 xs.resid = xs.datalen; 813 xs.status = SCSI_OK; 814 815 error = siop_scsi_request(adp, &xs); 816 if (error != 0) 817 return error; 818 819 memcpy(buf, inqbuf, buflen); 820 return 0; 821 } 822 823 static void 824 scsi_request_sense(struct siop_adapter *adp, struct scsi_xfer *xs) 825 { 826 struct scsi_request_sense *cmd = adp->sense; 827 struct scsi_sense_data *data = (struct scsi_sense_data *)adp->data; 828 struct scsi_xfer sense; 829 int error; 830 831 memset(cmd, 0, sizeof(struct scsi_request_sense)); 832 cmd->opcode = SCSI_REQUEST_SENSE; 833 cmd->length = sizeof(struct scsi_sense_data); 834 memset(data, 0, sizeof(struct scsi_sense_data)); 835 836 memset(&sense, 0, sizeof(sense)); 837 sense.target = xs->target; 838 sense.lun = xs->lun; 839 sense.cmdlen = sizeof(struct scsi_request_sense); 840 sense.cmd = (void *)cmd; 841 sense.datalen = sizeof(struct scsi_sense_data); 842 sense.data = (void *)data; 843 844 sense.error = XS_NOERROR; 845 sense.resid = sense.datalen; 846 sense.status = SCSI_OK; 847 848 error = siop_scsi_request(adp, &sense); 849 switch (error) { 850 case 0: 851 /* we have a valid sense */ 852 xs->error = XS_SENSE; 853 return; 854 case EINTR: 855 /* REQUEST_SENSE interrupted by bus reset. */ 856 xs->error = XS_RESET; 857 return; 858 case EIO: 859 /* request sense coudn't be performed */ 860 /* 861 * XXX this isn't quite right but we don't have anything 862 * better for now 863 */ 864 xs->error = XS_DRIVER_STUFFUP; 865 return; 866 default: 867 /* Notify that request sense failed. */ 868 xs->error = XS_DRIVER_STUFFUP; 869 printf("request sense failed with error %d\n", error); 870 return; 871 } 872 } 873 874 /* 875 * scsi_interpret_sense: 876 * 877 * Look at the returned sense and act on the error, determining 878 * the unix error number to pass back. (0 = report no error) 879 * 880 * NOTE: If we return ERESTART, we are expected to haved 881 * thawed the device! 882 * 883 * THIS IS THE DEFAULT ERROR HANDLER FOR SCSI DEVICES. 884 */ 885 static int 886 scsi_interpret_sense(struct siop_adapter *adp, struct scsi_xfer *xs) 887 { 888 struct scsi_sense_data *sense; 889 u_int8_t key; 890 int error; 891 uint32_t info; 892 static const char *error_mes[] = { 893 "soft error (corrected)", 894 "not ready", "medium error", 895 "non-media hardware failure", "illegal request", 896 "unit attention", "readonly device", 897 "no data found", "vendor unique", 898 "copy aborted", "command aborted", 899 "search returned equal", "volume overflow", 900 "verify miscompare", "unknown error key" 901 }; 902 903 sense = (struct scsi_sense_data *)xs->data; 904 905 DPRINTF((" sense debug information:\n")); 906 DPRINTF(("\tcode 0x%x valid %d\n", 907 SSD_RCODE(sense->response_code), 908 sense->response_code & SSD_RCODE_VALID ? 1 : 0)); 909 DPRINTF(("\tseg 0x%x key 0x%x ili 0x%x eom 0x%x fmark 0x%x\n", 910 sense->segment, 911 SSD_SENSE_KEY(sense->flags), 912 sense->flags & SSD_ILI ? 1 : 0, 913 sense->flags & SSD_EOM ? 1 : 0, 914 sense->flags & SSD_FILEMARK ? 1 : 0)); 915 DPRINTF(("\ninfo: 0x%x 0x%x 0x%x 0x%x followed by %d " 916 "extra bytes\n", 917 sense->info[0], 918 sense->info[1], 919 sense->info[2], 920 sense->info[3], 921 sense->extra_len)); 922 923 switch (SSD_RCODE(sense->response_code)) { 924 925 /* 926 * Old SCSI-1 and SASI devices respond with 927 * codes other than 70. 928 */ 929 case 0x00: /* no error (command completed OK) */ 930 return 0; 931 case 0x04: /* drive not ready after it was selected */ 932 if (adp->sd->sc_flags & FLAGS_REMOVABLE) 933 adp->sd->sc_flags &= ~FLAGS_MEDIA_LOADED; 934 /* XXX - display some sort of error here? */ 935 return EIO; 936 case 0x20: /* invalid command */ 937 return EINVAL; 938 case 0x25: /* invalid LUN (Adaptec ACB-4000) */ 939 return EACCES; 940 941 /* 942 * If it's code 70, use the extended stuff and 943 * interpret the key 944 */ 945 case 0x71: /* delayed error */ 946 key = SSD_SENSE_KEY(sense->flags); 947 printf(" DEFERRED ERROR, key = 0x%x\n", key); 948 /* FALLTHROUGH */ 949 case 0x70: 950 if ((sense->response_code & SSD_RCODE_VALID) != 0) 951 info = _4btol(sense->info); 952 else 953 info = 0; 954 key = SSD_SENSE_KEY(sense->flags); 955 956 switch (key) { 957 case SKEY_NO_SENSE: 958 case SKEY_RECOVERED_ERROR: 959 if (xs->resid == xs->datalen && xs->datalen) { 960 /* 961 * Why is this here? 962 */ 963 xs->resid = 0; /* not short read */ 964 } 965 case SKEY_EQUAL: 966 error = 0; 967 break; 968 case SKEY_NOT_READY: 969 if (adp->sd->sc_flags & FLAGS_REMOVABLE) 970 adp->sd->sc_flags &= ~FLAGS_MEDIA_LOADED; 971 if (sense->asc == 0x3A) { 972 error = ENODEV; /* Medium not present */ 973 } else 974 error = EIO; 975 break; 976 case SKEY_ILLEGAL_REQUEST: 977 error = EINVAL; 978 break; 979 case SKEY_UNIT_ATTENTION: 980 if (sense->asc == 0x29 && 981 sense->ascq == 0x00) { 982 /* device or bus reset */ 983 return ERESTART; 984 } 985 if (adp->sd->sc_flags & FLAGS_REMOVABLE) 986 adp->sd->sc_flags &= ~FLAGS_MEDIA_LOADED; 987 if (!(adp->sd->sc_flags & FLAGS_REMOVABLE)) 988 return ERESTART; 989 error = EIO; 990 break; 991 case SKEY_DATA_PROTECT: 992 error = EROFS; 993 break; 994 case SKEY_BLANK_CHECK: 995 error = 0; 996 break; 997 case SKEY_ABORTED_COMMAND: 998 break; 999 case SKEY_VOLUME_OVERFLOW: 1000 error = ENOSPC; 1001 break; 1002 default: 1003 error = EIO; 1004 break; 1005 } 1006 1007 /* Print brief(er) sense information */ 1008 printf("%s", error_mes[key - 1]); 1009 if ((sense->response_code & SSD_RCODE_VALID) != 0) { 1010 switch (key) { 1011 case SKEY_NOT_READY: 1012 case SKEY_ILLEGAL_REQUEST: 1013 case SKEY_UNIT_ATTENTION: 1014 case SKEY_DATA_PROTECT: 1015 break; 1016 case SKEY_BLANK_CHECK: 1017 printf(", requested size: %d (decimal)", 1018 info); 1019 break; 1020 case SKEY_ABORTED_COMMAND: 1021 printf(", cmd 0x%x, info 0x%x", 1022 xs->cmd->opcode, info); 1023 break; 1024 default: 1025 printf(", info = %d (decimal)", info); 1026 } 1027 } 1028 if (sense->extra_len != 0) { 1029 int n; 1030 printf(", data ="); 1031 for (n = 0; n < sense->extra_len; n++) 1032 printf(" %x", sense->csi[n]); 1033 } 1034 printf("\n"); 1035 return error; 1036 1037 /* 1038 * Some other code, just report it 1039 */ 1040 default: 1041 printf("Sense Error Code 0x%x", 1042 SSD_RCODE(sense->response_code)); 1043 if ((sense->response_code & SSD_RCODE_VALID) != 0) { 1044 struct scsi_sense_data_unextended *usense = 1045 (struct scsi_sense_data_unextended *)sense; 1046 printf(" at block no. %d (decimal)", 1047 _3btol(usense->block)); 1048 } 1049 printf("\n"); 1050 return EIO; 1051 } 1052 } 1053 1054 static int 1055 scsi_probe(struct siop_adapter *adp) 1056 { 1057 struct scsipi_inquiry_data *inqbuf; 1058 int found, t, l; 1059 uint8_t device; 1060 char buf[SCSIPI_INQUIRY_LENGTH_SCSI2], 1061 product[sizeof(inqbuf->product) + 1]; 1062 1063 found = 0; 1064 for (t = 0; t < 8; t++) { 1065 if (t == adp->id) 1066 continue; 1067 for (l = 0; l < 8; l++) { 1068 if (_scsi_inquire(adp, t, l, sizeof(buf), buf) != 0) 1069 continue; 1070 1071 inqbuf = (struct scsipi_inquiry_data *)buf; 1072 device = inqbuf->device & SID_TYPE; 1073 if (device == T_NODEVICE) 1074 continue; 1075 if (device != T_DIRECT && 1076 device != T_OPTICAL && 1077 device != T_SIMPLE_DIRECT) 1078 continue; 1079 1080 memset(product, 0, sizeof(product)); 1081 strncpy(product, inqbuf->product, sizeof(product) - 1); 1082 printf("/dev/disk/scsi/0%d%d: <%s>\n", t, l, product); 1083 found++; 1084 } 1085 } 1086 return found; 1087 } 1088 1089 int 1090 scsi_inquire(struct sd_softc *sd, int buflen, void *buf) 1091 { 1092 struct siop_adapter *adp; 1093 int error; 1094 1095 if (sd->sc_bus != 0) 1096 return ENOTSUP; 1097 if (adapt.addr == 0) 1098 return ENOENT; 1099 adp = &adapt; 1100 1101 adp->sd = sd; 1102 error = _scsi_inquire(adp, sd->sc_target, sd->sc_lun, buflen, buf); 1103 adp->sd = NULL; 1104 1105 return error; 1106 } 1107 1108 /* 1109 * scsi_mode_sense 1110 * get a sense page from a device 1111 */ 1112 1113 int 1114 scsi_mode_sense(struct sd_softc *sd, int byte2, int page, 1115 struct scsi_mode_parameter_header_6 *data, int len) 1116 { 1117 struct scsi_mode_sense_6 cmd; 1118 1119 memset(&cmd, 0, sizeof(cmd)); 1120 cmd.opcode = SCSI_MODE_SENSE_6; 1121 cmd.byte2 = byte2; 1122 cmd.page = page; 1123 cmd.length = len & 0xff; 1124 1125 return scsi_command(sd, (void *)&cmd, sizeof(cmd), (void *)data, len); 1126 } 1127 1128 int 1129 scsi_command(struct sd_softc *sd, void *cmd, int cmdlen, void *data, 1130 int datalen) 1131 { 1132 struct siop_adapter *adp; 1133 struct scsi_xfer xs; 1134 int error; 1135 1136 if (sd->sc_bus != 0) 1137 return ENOTSUP; 1138 if (adapt.addr == 0) 1139 return ENOENT; 1140 adp = &adapt; 1141 1142 memcpy(adp->cmd, cmd, cmdlen); 1143 adp->sd = sd; 1144 1145 memset(&xs, 0, sizeof(xs)); 1146 xs.target = sd->sc_target; 1147 xs.lun = sd->sc_lun; 1148 xs.cmdlen = cmdlen; 1149 xs.cmd = adp->cmd; 1150 xs.datalen = datalen; 1151 xs.data = adp->data; 1152 1153 xs.error = XS_NOERROR; 1154 xs.resid = datalen; 1155 xs.status = SCSI_OK; 1156 1157 error = siop_scsi_request(adp, &xs); 1158 adp->sd = NULL; 1159 if (error != 0) 1160 return error; 1161 1162 if (datalen > 0) 1163 memcpy(data, adp->data, datalen); 1164 return 0; 1165 } 1166 1167 /* 1168 * Initialize the device. 1169 */ 1170 int 1171 siop_init(int bus, int dev, int func) 1172 { 1173 struct siop_adapter tmp; 1174 struct siop_xfer *xfer; 1175 struct scsipi_generic *cmd; 1176 struct scsi_request_sense *sense; 1177 uint32_t reg; 1178 u_long addr; 1179 uint32_t *script; 1180 int slot, id, i; 1181 void *scriptaddr; 1182 u_char *data; 1183 const int clock_div = 3; /* 53c810 */ 1184 1185 slot = PCISlotnum(bus, dev, func); 1186 if (slot == -1) 1187 return ENOENT; 1188 1189 addr = PCIAddress(slot, 1, PCI_MAPREG_TYPE_MEM); 1190 if (addr == 0xffffffff) 1191 return EINVAL; 1192 enablePCI(slot, 0, 1, 1); 1193 1194 script = ALLOC(uint32_t, SIOP_SCRIPT_SIZE); 1195 if (script == NULL) 1196 return ENOMEM; 1197 scriptaddr = (void *)local_to_PCI((u_long)script); 1198 cmd = ALLOC(struct scsipi_generic, SIOP_SCSI_COMMAND_SIZE); 1199 if (cmd == NULL) 1200 return ENOMEM; 1201 sense = ALLOC(struct scsi_request_sense, SIOP_SCSI_COMMAND_SIZE); 1202 if (sense == NULL) 1203 return ENOMEM; 1204 data = ALLOC(u_char, SIOP_SCSI_DATA_SIZE); 1205 if (data == NULL) 1206 return ENOMEM; 1207 xfer = ALLOC(struct siop_xfer, sizeof(struct siop_xfer)); 1208 if (xfer == NULL) 1209 return ENOMEM; 1210 siop_xfer_setup(xfer, scriptaddr); 1211 1212 id = readb(addr + SIOP_SCID) & SCID_ENCID_MASK; 1213 1214 /* reset bus */ 1215 reg = readb(addr + SIOP_SCNTL1); 1216 writeb(addr + SIOP_SCNTL1, reg | SCNTL1_RST); 1217 delay(100); 1218 writeb(addr + SIOP_SCNTL1, reg); 1219 1220 /* reset the chip */ 1221 writeb(addr + SIOP_ISTAT, ISTAT_SRST); 1222 delay(1000); 1223 writeb(addr + SIOP_ISTAT, 0); 1224 1225 /* init registers */ 1226 writeb(addr + SIOP_SCNTL0, SCNTL0_ARB_MASK | SCNTL0_EPC | SCNTL0_AAP); 1227 writeb(addr + SIOP_SCNTL1, 0); 1228 writeb(addr + SIOP_SCNTL3, clock_div); 1229 writeb(addr + SIOP_SXFER, 0); 1230 writeb(addr + SIOP_DIEN, 0xff); 1231 writeb(addr + SIOP_SIEN0, 0xff & ~(SIEN0_CMP | SIEN0_SEL | SIEN0_RSL)); 1232 writeb(addr + SIOP_SIEN1, 0xff & ~(SIEN1_HTH | SIEN1_GEN)); 1233 writeb(addr + SIOP_STEST2, 0); 1234 writeb(addr + SIOP_STEST3, STEST3_TE); 1235 writeb(addr + SIOP_STIME0, (0xb << STIME0_SEL_SHIFT)); 1236 writeb(addr + SIOP_SCID, id | SCID_RRE); 1237 writeb(addr + SIOP_RESPID0, 1 << id); 1238 writeb(addr + SIOP_DCNTL, DCNTL_COM); 1239 1240 /* BeBox uses PCIC */ 1241 writeb(addr + SIOP_STEST1, STEST1_SCLK); 1242 1243 siop_pci_reset(addr); 1244 1245 /* copy and patch the script */ 1246 for (i = 0; i < __arraycount(siop_script); i++) 1247 script[i] = htoc32(siop_script[i]); 1248 for (i = 0; i < __arraycount(E_abs_msgin_Used); i++) 1249 script[E_abs_msgin_Used[i]] = 1250 htoc32(scriptaddr + Ent_msgin_space); 1251 1252 /* start script */ 1253 _wbinv((u_long)script, SIOP_SCRIPT_SIZE); 1254 writel(addr + SIOP_DSP, (int)scriptaddr + Ent_reselect); 1255 1256 memset(&tmp, 0, sizeof(tmp)); 1257 tmp.id = id; 1258 tmp.clock_div = clock_div; 1259 tmp.addr = addr; 1260 tmp.script = script; 1261 tmp.xfer = xfer; 1262 tmp.cmd = cmd; 1263 tmp.sense = sense; 1264 tmp.data = data; 1265 tmp.currschedslot = 0; 1266 tmp.sel_t = -1; 1267 1268 if (scsi_probe(&tmp) == 0) 1269 return ENXIO; 1270 adapt = tmp; 1271 return 0; 1272 } 1273