1 /* $NetBSD: siop.c,v 1.6 2017/06/25 12:15:04 maxv 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 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 /* 656 * find a free scheduler slot and load it. 657 */ 658 #define SIOP_NSLOTS 0x40 659 for (; slot < SIOP_NSLOTS; slot++) { 660 /* 661 * If cmd if 0x80000000 the slot is free 662 */ 663 if (ctoh32(script[(Ent_script_sched_slot0 / 4) + slot * 2]) == 664 0x80000000) 665 break; 666 } 667 if (slot == SIOP_NSLOTS) { 668 /* 669 * no more free slot, no need to continue. freeze the queue 670 * and requeue this command. 671 */ 672 printf("no mode free slot\n"); 673 return; 674 } 675 676 /* patch scripts with DSA addr */ 677 dsa = local_to_PCI((u_long)siop_xfer); 678 679 /* CMD script: MOVE MEMORY addr */ 680 siop_xfer->resel[E_ldsa_abs_slot_Used[0]] = 681 htoc32(scriptaddr + Ent_script_sched_slot0 + slot * 8); 682 _wbinv((u_long)siop_xfer, sizeof(*siop_xfer)); 683 /* scheduler slot: JUMP ldsa_select */ 684 script[(Ent_script_sched_slot0 / 4) + slot * 2 + 1] = 685 htoc32(dsa + siop_common_xfer_size + Ent_ldsa_select); 686 /* 687 * Change JUMP cmd so that this slot will be handled 688 */ 689 script[(Ent_script_sched_slot0 / 4) + slot * 2] = htoc32(0x80080000); 690 adp->currschedslot = slot; 691 692 /* make sure SCRIPT processor will read valid data */ 693 _wbinv((u_long)script, SIOP_SCRIPT_SIZE); 694 /* Signal script it has some work to do */ 695 writeb(adp->addr + SIOP_ISTAT, ISTAT_SIGP); 696 /* and wait for IRQ */ 697 } 698 699 static void 700 siop_xfer_setup(struct siop_xfer *xfer, void *scriptaddr) 701 { 702 const int off_msg_in = offsetof(struct siop_common_xfer, msg_in); 703 const int off_status = offsetof(struct siop_common_xfer, status); 704 uint32_t dsa, *scr; 705 int i; 706 707 memset(xfer, 0, sizeof(*xfer)); 708 dsa = local_to_PCI((u_long)xfer); 709 xfer->siop_tables.t_msgout.count = htoc32(1); 710 xfer->siop_tables.t_msgout.addr = htoc32(dsa); 711 xfer->siop_tables.t_msgin.count = htoc32(1); 712 xfer->siop_tables.t_msgin.addr = htoc32(dsa + off_msg_in); 713 xfer->siop_tables.t_extmsgin.count = htoc32(2); 714 xfer->siop_tables.t_extmsgin.addr = htoc32(dsa + off_msg_in + 1); 715 xfer->siop_tables.t_extmsgdata.addr = htoc32(dsa + off_msg_in + 3); 716 xfer->siop_tables.t_status.count = htoc32(1); 717 xfer->siop_tables.t_status.addr = htoc32(dsa + off_status); 718 719 /* The select/reselect script */ 720 scr = xfer->resel; 721 for (i = 0; i < __arraycount(load_dsa); i++) 722 scr[i] = htoc32(load_dsa[i]); 723 724 /* 725 * 0x78000000 is a 'move data8 to reg'. data8 is the second 726 * octet, reg offset is the third. 727 */ 728 scr[Ent_rdsa0 / 4] = htoc32(0x78100000 | ((dsa & 0x000000ff) << 8)); 729 scr[Ent_rdsa1 / 4] = htoc32(0x78110000 | ( dsa & 0x0000ff00 )); 730 scr[Ent_rdsa2 / 4] = htoc32(0x78120000 | ((dsa & 0x00ff0000) >> 8)); 731 scr[Ent_rdsa3 / 4] = htoc32(0x78130000 | ((dsa & 0xff000000) >> 16)); 732 scr[E_ldsa_abs_reselected_Used[0]] = 733 htoc32(scriptaddr + Ent_reselected); 734 scr[E_ldsa_abs_reselect_Used[0]] = htoc32(scriptaddr + Ent_reselect); 735 scr[E_ldsa_abs_selected_Used[0]] = htoc32(scriptaddr + Ent_selected); 736 scr[E_ldsa_abs_data_Used[0]] = 737 htoc32(dsa + sizeof(struct siop_common_xfer) + Ent_ldsa_data); 738 /* JUMP foo, IF FALSE - used by MOVE MEMORY to clear the slot */ 739 scr[Ent_ldsa_data / 4] = htoc32(0x80000000); 740 } 741 742 static int 743 siop_add_reselsw(struct siop_adapter *adp, int target, int lunsw_off) 744 { 745 uint32_t *script = adp->script; 746 int reseloff; 747 void *scriptaddr = (void *)local_to_PCI((u_long)adp->script); 748 749 /* 750 * add an entry to resel switch 751 */ 752 reseloff = Ent_resel_targ0 / 4 + target * 2; 753 if ((ctoh32(script[reseloff]) & 0xff) != 0xff) { 754 /* it's not free */ 755 printf("siop: resel switch full\n"); 756 return EBUSY; 757 } 758 759 /* JUMP abs_foo, IF target | 0x80; */ 760 script[reseloff + 0] = htoc32(0x800c0080 | target); 761 script[reseloff + 1] = 762 htoc32(scriptaddr + lunsw_off * 4 + Ent_lun_switch_entry); 763 764 siop_update_scntl3(adp, target, lunsw_off); 765 return 0; 766 } 767 768 static void 769 siop_update_scntl3(struct siop_adapter *adp, int target, int lunsw_off) 770 { 771 uint32_t *script = adp->script; 772 773 /* MOVE target->id >> 24 TO SCNTL3 */ 774 script[lunsw_off + (Ent_restore_scntl3 / 4)] = 775 htoc32(0x78030000 | ((adp->clock_div >> 16) & 0x0000ff00)); 776 /* MOVE target->id >> 8 TO SXFER */ 777 script[lunsw_off + (Ent_restore_scntl3 / 4) + 2] = 778 htoc32(0x78050000 | (0x000000000 & 0x0000ff00)); 779 _wbinv((u_long)script, SIOP_SCRIPT_SIZE); 780 } 781 782 783 /* 784 * SCSI functions 785 */ 786 787 static int 788 _scsi_inquire(struct siop_adapter *adp, int t, int l, int buflen, char *buf) 789 { 790 struct scsipi_inquiry *cmd = (struct scsipi_inquiry *)adp->cmd; 791 struct scsipi_inquiry_data *inqbuf = 792 (struct scsipi_inquiry_data *)adp->data; 793 struct scsi_xfer xs; 794 int error; 795 796 memset(cmd, 0, sizeof(*cmd)); 797 cmd->opcode = INQUIRY; 798 cmd->length = SCSIPI_INQUIRY_LENGTH_SCSI2; 799 memset(inqbuf, 0, sizeof(*inqbuf)); 800 801 memset(&xs, 0, sizeof(xs)); 802 xs.target = t; 803 xs.lun = l; 804 xs.cmdlen = sizeof(*cmd); 805 xs.cmd = (void *)cmd; 806 xs.datalen = SCSIPI_INQUIRY_LENGTH_SCSI2; 807 xs.data = (void *)inqbuf; 808 809 xs.error = XS_NOERROR; 810 xs.resid = xs.datalen; 811 xs.status = SCSI_OK; 812 813 error = siop_scsi_request(adp, &xs); 814 if (error != 0) 815 return error; 816 817 memcpy(buf, inqbuf, buflen); 818 return 0; 819 } 820 821 static void 822 scsi_request_sense(struct siop_adapter *adp, struct scsi_xfer *xs) 823 { 824 struct scsi_request_sense *cmd = adp->sense; 825 struct scsi_sense_data *data = (struct scsi_sense_data *)adp->data; 826 struct scsi_xfer sense; 827 int error; 828 829 memset(cmd, 0, sizeof(struct scsi_request_sense)); 830 cmd->opcode = SCSI_REQUEST_SENSE; 831 cmd->length = sizeof(struct scsi_sense_data); 832 memset(data, 0, sizeof(struct scsi_sense_data)); 833 834 memset(&sense, 0, sizeof(sense)); 835 sense.target = xs->target; 836 sense.lun = xs->lun; 837 sense.cmdlen = sizeof(struct scsi_request_sense); 838 sense.cmd = (void *)cmd; 839 sense.datalen = sizeof(struct scsi_sense_data); 840 sense.data = (void *)data; 841 842 sense.error = XS_NOERROR; 843 sense.resid = sense.datalen; 844 sense.status = SCSI_OK; 845 846 error = siop_scsi_request(adp, &sense); 847 switch (error) { 848 case 0: 849 /* we have a valid sense */ 850 xs->error = XS_SENSE; 851 return; 852 case EINTR: 853 /* REQUEST_SENSE interrupted by bus reset. */ 854 xs->error = XS_RESET; 855 return; 856 case EIO: 857 /* request sense coudn't be performed */ 858 /* 859 * XXX this isn't quite right but we don't have anything 860 * better for now 861 */ 862 xs->error = XS_DRIVER_STUFFUP; 863 return; 864 default: 865 /* Notify that request sense failed. */ 866 xs->error = XS_DRIVER_STUFFUP; 867 printf("request sense failed with error %d\n", error); 868 return; 869 } 870 } 871 872 /* 873 * scsi_interpret_sense: 874 * 875 * Look at the returned sense and act on the error, determining 876 * the unix error number to pass back. (0 = report no error) 877 * 878 * NOTE: If we return ERESTART, we are expected to haved 879 * thawed the device! 880 * 881 * THIS IS THE DEFAULT ERROR HANDLER FOR SCSI DEVICES. 882 */ 883 static int 884 scsi_interpret_sense(struct siop_adapter *adp, struct scsi_xfer *xs) 885 { 886 struct scsi_sense_data *sense; 887 u_int8_t key; 888 int error; 889 uint32_t info; 890 static const char *error_mes[] = { 891 "soft error (corrected)", 892 "not ready", "medium error", 893 "non-media hardware failure", "illegal request", 894 "unit attention", "readonly device", 895 "no data found", "vendor unique", 896 "copy aborted", "command aborted", 897 "search returned equal", "volume overflow", 898 "verify miscompare", "unknown error key" 899 }; 900 901 sense = (struct scsi_sense_data *)xs->data; 902 903 DPRINTF((" sense debug information:\n")); 904 DPRINTF(("\tcode 0x%x valid %d\n", 905 SSD_RCODE(sense->response_code), 906 sense->response_code & SSD_RCODE_VALID ? 1 : 0)); 907 DPRINTF(("\tseg 0x%x key 0x%x ili 0x%x eom 0x%x fmark 0x%x\n", 908 sense->segment, 909 SSD_SENSE_KEY(sense->flags), 910 sense->flags & SSD_ILI ? 1 : 0, 911 sense->flags & SSD_EOM ? 1 : 0, 912 sense->flags & SSD_FILEMARK ? 1 : 0)); 913 DPRINTF(("\ninfo: 0x%x 0x%x 0x%x 0x%x followed by %d " 914 "extra bytes\n", 915 sense->info[0], 916 sense->info[1], 917 sense->info[2], 918 sense->info[3], 919 sense->extra_len)); 920 921 switch (SSD_RCODE(sense->response_code)) { 922 923 /* 924 * Old SCSI-1 and SASI devices respond with 925 * codes other than 70. 926 */ 927 case 0x00: /* no error (command completed OK) */ 928 return 0; 929 case 0x04: /* drive not ready after it was selected */ 930 if (adp->sd->sc_flags & FLAGS_REMOVABLE) 931 adp->sd->sc_flags &= ~FLAGS_MEDIA_LOADED; 932 /* XXX - display some sort of error here? */ 933 return EIO; 934 case 0x20: /* invalid command */ 935 return EINVAL; 936 case 0x25: /* invalid LUN (Adaptec ACB-4000) */ 937 return EACCES; 938 939 /* 940 * If it's code 70, use the extended stuff and 941 * interpret the key 942 */ 943 case 0x71: /* delayed error */ 944 key = SSD_SENSE_KEY(sense->flags); 945 printf(" DEFERRED ERROR, key = 0x%x\n", key); 946 /* FALLTHROUGH */ 947 case 0x70: 948 if ((sense->response_code & SSD_RCODE_VALID) != 0) 949 info = _4btol(sense->info); 950 else 951 info = 0; 952 key = SSD_SENSE_KEY(sense->flags); 953 954 switch (key) { 955 case SKEY_NO_SENSE: 956 case SKEY_RECOVERED_ERROR: 957 if (xs->resid == xs->datalen && xs->datalen) { 958 /* 959 * Why is this here? 960 */ 961 xs->resid = 0; /* not short read */ 962 } 963 case SKEY_EQUAL: 964 error = 0; 965 break; 966 case SKEY_NOT_READY: 967 if (adp->sd->sc_flags & FLAGS_REMOVABLE) 968 adp->sd->sc_flags &= ~FLAGS_MEDIA_LOADED; 969 if (sense->asc == 0x3A) { 970 error = ENODEV; /* Medium not present */ 971 } else 972 error = EIO; 973 break; 974 case SKEY_ILLEGAL_REQUEST: 975 error = EINVAL; 976 break; 977 case SKEY_UNIT_ATTENTION: 978 if (sense->asc == 0x29 && 979 sense->ascq == 0x00) { 980 /* device or bus reset */ 981 return ERESTART; 982 } 983 if (adp->sd->sc_flags & FLAGS_REMOVABLE) 984 adp->sd->sc_flags &= ~FLAGS_MEDIA_LOADED; 985 if (!(adp->sd->sc_flags & FLAGS_REMOVABLE)) 986 return ERESTART; 987 error = EIO; 988 break; 989 case SKEY_DATA_PROTECT: 990 error = EROFS; 991 break; 992 case SKEY_BLANK_CHECK: 993 error = 0; 994 break; 995 case SKEY_ABORTED_COMMAND: 996 /* XXX XXX initialize 'error' */ 997 break; 998 case SKEY_VOLUME_OVERFLOW: 999 error = ENOSPC; 1000 break; 1001 default: 1002 error = EIO; 1003 break; 1004 } 1005 1006 /* Print brief(er) sense information */ 1007 printf("%s", error_mes[key - 1]); 1008 if ((sense->response_code & SSD_RCODE_VALID) != 0) { 1009 switch (key) { 1010 case SKEY_NOT_READY: 1011 case SKEY_ILLEGAL_REQUEST: 1012 case SKEY_UNIT_ATTENTION: 1013 case SKEY_DATA_PROTECT: 1014 break; 1015 case SKEY_BLANK_CHECK: 1016 printf(", requested size: %d (decimal)", 1017 info); 1018 break; 1019 case SKEY_ABORTED_COMMAND: 1020 printf(", cmd 0x%x, info 0x%x", 1021 xs->cmd->opcode, info); 1022 break; 1023 default: 1024 printf(", info = %d (decimal)", info); 1025 } 1026 } 1027 if (sense->extra_len != 0) { 1028 int n; 1029 printf(", data ="); 1030 for (n = 0; n < sense->extra_len; n++) 1031 printf(" %x", sense->csi[n]); 1032 } 1033 printf("\n"); 1034 return error; 1035 1036 /* 1037 * Some other code, just report it 1038 */ 1039 default: 1040 printf("Sense Error Code 0x%x", 1041 SSD_RCODE(sense->response_code)); 1042 if ((sense->response_code & SSD_RCODE_VALID) != 0) { 1043 struct scsi_sense_data_unextended *usense = 1044 (struct scsi_sense_data_unextended *)sense; 1045 printf(" at block no. %d (decimal)", 1046 _3btol(usense->block)); 1047 } 1048 printf("\n"); 1049 return EIO; 1050 } 1051 } 1052 1053 static int 1054 scsi_probe(struct siop_adapter *adp) 1055 { 1056 struct scsipi_inquiry_data *inqbuf; 1057 int found, t, l; 1058 uint8_t device; 1059 char buf[SCSIPI_INQUIRY_LENGTH_SCSI2], 1060 product[sizeof(inqbuf->product) + 1]; 1061 1062 found = 0; 1063 for (t = 0; t < 8; t++) { 1064 if (t == adp->id) 1065 continue; 1066 for (l = 0; l < 8; l++) { 1067 if (_scsi_inquire(adp, t, l, sizeof(buf), buf) != 0) 1068 continue; 1069 1070 inqbuf = (struct scsipi_inquiry_data *)buf; 1071 device = inqbuf->device & SID_TYPE; 1072 if (device == T_NODEVICE) 1073 continue; 1074 if (device != T_DIRECT && 1075 device != T_OPTICAL && 1076 device != T_SIMPLE_DIRECT) 1077 continue; 1078 1079 memset(product, 0, sizeof(product)); 1080 strncpy(product, inqbuf->product, sizeof(product) - 1); 1081 printf("/dev/disk/scsi/0%d%d: <%s>\n", t, l, product); 1082 found++; 1083 } 1084 } 1085 return found; 1086 } 1087 1088 int 1089 scsi_inquire(struct sd_softc *sd, int buflen, void *buf) 1090 { 1091 struct siop_adapter *adp; 1092 int error; 1093 1094 if (sd->sc_bus != 0) 1095 return ENOTSUP; 1096 if (adapt.addr == 0) 1097 return ENOENT; 1098 adp = &adapt; 1099 1100 adp->sd = sd; 1101 error = _scsi_inquire(adp, sd->sc_target, sd->sc_lun, buflen, buf); 1102 adp->sd = NULL; 1103 1104 return error; 1105 } 1106 1107 /* 1108 * scsi_mode_sense 1109 * get a sense page from a device 1110 */ 1111 1112 int 1113 scsi_mode_sense(struct sd_softc *sd, int byte2, int page, 1114 struct scsi_mode_parameter_header_6 *data, int len) 1115 { 1116 struct scsi_mode_sense_6 cmd; 1117 1118 memset(&cmd, 0, sizeof(cmd)); 1119 cmd.opcode = SCSI_MODE_SENSE_6; 1120 cmd.byte2 = byte2; 1121 cmd.page = page; 1122 cmd.length = len & 0xff; 1123 1124 return scsi_command(sd, (void *)&cmd, sizeof(cmd), (void *)data, len); 1125 } 1126 1127 int 1128 scsi_command(struct sd_softc *sd, void *cmd, int cmdlen, void *data, 1129 int datalen) 1130 { 1131 struct siop_adapter *adp; 1132 struct scsi_xfer xs; 1133 int error; 1134 1135 if (sd->sc_bus != 0) 1136 return ENOTSUP; 1137 if (adapt.addr == 0) 1138 return ENOENT; 1139 adp = &adapt; 1140 1141 memcpy(adp->cmd, cmd, cmdlen); 1142 adp->sd = sd; 1143 1144 memset(&xs, 0, sizeof(xs)); 1145 xs.target = sd->sc_target; 1146 xs.lun = sd->sc_lun; 1147 xs.cmdlen = cmdlen; 1148 xs.cmd = adp->cmd; 1149 xs.datalen = datalen; 1150 xs.data = adp->data; 1151 1152 xs.error = XS_NOERROR; 1153 xs.resid = datalen; 1154 xs.status = SCSI_OK; 1155 1156 error = siop_scsi_request(adp, &xs); 1157 adp->sd = NULL; 1158 if (error != 0) 1159 return error; 1160 1161 if (datalen > 0) 1162 memcpy(data, adp->data, datalen); 1163 return 0; 1164 } 1165 1166 /* 1167 * Initialize the device. 1168 */ 1169 int 1170 siop_init(int bus, int dev, int func) 1171 { 1172 struct siop_adapter tmp; 1173 struct siop_xfer *xfer; 1174 struct scsipi_generic *cmd; 1175 struct scsi_request_sense *sense; 1176 uint32_t reg; 1177 u_long addr; 1178 uint32_t *script; 1179 int slot, id, i; 1180 void *scriptaddr; 1181 u_char *data; 1182 const int clock_div = 3; /* 53c810 */ 1183 1184 slot = PCISlotnum(bus, dev, func); 1185 if (slot == -1) 1186 return ENOENT; 1187 1188 addr = PCIAddress(slot, 1, PCI_MAPREG_TYPE_MEM); 1189 if (addr == 0xffffffff) 1190 return EINVAL; 1191 enablePCI(slot, 0, 1, 1); 1192 1193 script = ALLOC(uint32_t, SIOP_SCRIPT_SIZE); 1194 if (script == NULL) 1195 return ENOMEM; 1196 scriptaddr = (void *)local_to_PCI((u_long)script); 1197 cmd = ALLOC(struct scsipi_generic, SIOP_SCSI_COMMAND_SIZE); 1198 if (cmd == NULL) 1199 return ENOMEM; 1200 sense = ALLOC(struct scsi_request_sense, SIOP_SCSI_COMMAND_SIZE); 1201 if (sense == NULL) 1202 return ENOMEM; 1203 data = ALLOC(u_char, SIOP_SCSI_DATA_SIZE); 1204 if (data == NULL) 1205 return ENOMEM; 1206 xfer = ALLOC(struct siop_xfer, sizeof(struct siop_xfer)); 1207 if (xfer == NULL) 1208 return ENOMEM; 1209 siop_xfer_setup(xfer, scriptaddr); 1210 1211 id = readb(addr + SIOP_SCID) & SCID_ENCID_MASK; 1212 1213 /* reset bus */ 1214 reg = readb(addr + SIOP_SCNTL1); 1215 writeb(addr + SIOP_SCNTL1, reg | SCNTL1_RST); 1216 delay(100); 1217 writeb(addr + SIOP_SCNTL1, reg); 1218 1219 /* reset the chip */ 1220 writeb(addr + SIOP_ISTAT, ISTAT_SRST); 1221 delay(1000); 1222 writeb(addr + SIOP_ISTAT, 0); 1223 1224 /* init registers */ 1225 writeb(addr + SIOP_SCNTL0, SCNTL0_ARB_MASK | SCNTL0_EPC | SCNTL0_AAP); 1226 writeb(addr + SIOP_SCNTL1, 0); 1227 writeb(addr + SIOP_SCNTL3, clock_div); 1228 writeb(addr + SIOP_SXFER, 0); 1229 writeb(addr + SIOP_DIEN, 0xff); 1230 writeb(addr + SIOP_SIEN0, 0xff & ~(SIEN0_CMP | SIEN0_SEL | SIEN0_RSL)); 1231 writeb(addr + SIOP_SIEN1, 0xff & ~(SIEN1_HTH | SIEN1_GEN)); 1232 writeb(addr + SIOP_STEST2, 0); 1233 writeb(addr + SIOP_STEST3, STEST3_TE); 1234 writeb(addr + SIOP_STIME0, (0xb << STIME0_SEL_SHIFT)); 1235 writeb(addr + SIOP_SCID, id | SCID_RRE); 1236 writeb(addr + SIOP_RESPID0, 1 << id); 1237 writeb(addr + SIOP_DCNTL, DCNTL_COM); 1238 1239 /* BeBox uses PCIC */ 1240 writeb(addr + SIOP_STEST1, STEST1_SCLK); 1241 1242 siop_pci_reset(addr); 1243 1244 /* copy and patch the script */ 1245 for (i = 0; i < __arraycount(siop_script); i++) 1246 script[i] = htoc32(siop_script[i]); 1247 for (i = 0; i < __arraycount(E_abs_msgin_Used); i++) 1248 script[E_abs_msgin_Used[i]] = 1249 htoc32(scriptaddr + Ent_msgin_space); 1250 1251 /* start script */ 1252 _wbinv((u_long)script, SIOP_SCRIPT_SIZE); 1253 writel(addr + SIOP_DSP, (int)scriptaddr + Ent_reselect); 1254 1255 memset(&tmp, 0, sizeof(tmp)); 1256 tmp.id = id; 1257 tmp.clock_div = clock_div; 1258 tmp.addr = addr; 1259 tmp.script = script; 1260 tmp.xfer = xfer; 1261 tmp.cmd = cmd; 1262 tmp.sense = sense; 1263 tmp.data = data; 1264 tmp.currschedslot = 0; 1265 tmp.sel_t = -1; 1266 1267 if (scsi_probe(&tmp) == 0) 1268 return ENXIO; 1269 adapt = tmp; 1270 return 0; 1271 } 1272