1 /* $NetBSD: siop.c,v 1.5 2014/12/12 15:57:30 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 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 break; 997 case SKEY_VOLUME_OVERFLOW: 998 error = ENOSPC; 999 break; 1000 default: 1001 error = EIO; 1002 break; 1003 } 1004 1005 /* Print brief(er) sense information */ 1006 printf("%s", error_mes[key - 1]); 1007 if ((sense->response_code & SSD_RCODE_VALID) != 0) { 1008 switch (key) { 1009 case SKEY_NOT_READY: 1010 case SKEY_ILLEGAL_REQUEST: 1011 case SKEY_UNIT_ATTENTION: 1012 case SKEY_DATA_PROTECT: 1013 break; 1014 case SKEY_BLANK_CHECK: 1015 printf(", requested size: %d (decimal)", 1016 info); 1017 break; 1018 case SKEY_ABORTED_COMMAND: 1019 printf(", cmd 0x%x, info 0x%x", 1020 xs->cmd->opcode, info); 1021 break; 1022 default: 1023 printf(", info = %d (decimal)", info); 1024 } 1025 } 1026 if (sense->extra_len != 0) { 1027 int n; 1028 printf(", data ="); 1029 for (n = 0; n < sense->extra_len; n++) 1030 printf(" %x", sense->csi[n]); 1031 } 1032 printf("\n"); 1033 return error; 1034 1035 /* 1036 * Some other code, just report it 1037 */ 1038 default: 1039 printf("Sense Error Code 0x%x", 1040 SSD_RCODE(sense->response_code)); 1041 if ((sense->response_code & SSD_RCODE_VALID) != 0) { 1042 struct scsi_sense_data_unextended *usense = 1043 (struct scsi_sense_data_unextended *)sense; 1044 printf(" at block no. %d (decimal)", 1045 _3btol(usense->block)); 1046 } 1047 printf("\n"); 1048 return EIO; 1049 } 1050 } 1051 1052 static int 1053 scsi_probe(struct siop_adapter *adp) 1054 { 1055 struct scsipi_inquiry_data *inqbuf; 1056 int found, t, l; 1057 uint8_t device; 1058 char buf[SCSIPI_INQUIRY_LENGTH_SCSI2], 1059 product[sizeof(inqbuf->product) + 1]; 1060 1061 found = 0; 1062 for (t = 0; t < 8; t++) { 1063 if (t == adp->id) 1064 continue; 1065 for (l = 0; l < 8; l++) { 1066 if (_scsi_inquire(adp, t, l, sizeof(buf), buf) != 0) 1067 continue; 1068 1069 inqbuf = (struct scsipi_inquiry_data *)buf; 1070 device = inqbuf->device & SID_TYPE; 1071 if (device == T_NODEVICE) 1072 continue; 1073 if (device != T_DIRECT && 1074 device != T_OPTICAL && 1075 device != T_SIMPLE_DIRECT) 1076 continue; 1077 1078 memset(product, 0, sizeof(product)); 1079 strncpy(product, inqbuf->product, sizeof(product) - 1); 1080 printf("/dev/disk/scsi/0%d%d: <%s>\n", t, l, product); 1081 found++; 1082 } 1083 } 1084 return found; 1085 } 1086 1087 int 1088 scsi_inquire(struct sd_softc *sd, int buflen, void *buf) 1089 { 1090 struct siop_adapter *adp; 1091 int error; 1092 1093 if (sd->sc_bus != 0) 1094 return ENOTSUP; 1095 if (adapt.addr == 0) 1096 return ENOENT; 1097 adp = &adapt; 1098 1099 adp->sd = sd; 1100 error = _scsi_inquire(adp, sd->sc_target, sd->sc_lun, buflen, buf); 1101 adp->sd = NULL; 1102 1103 return error; 1104 } 1105 1106 /* 1107 * scsi_mode_sense 1108 * get a sense page from a device 1109 */ 1110 1111 int 1112 scsi_mode_sense(struct sd_softc *sd, int byte2, int page, 1113 struct scsi_mode_parameter_header_6 *data, int len) 1114 { 1115 struct scsi_mode_sense_6 cmd; 1116 1117 memset(&cmd, 0, sizeof(cmd)); 1118 cmd.opcode = SCSI_MODE_SENSE_6; 1119 cmd.byte2 = byte2; 1120 cmd.page = page; 1121 cmd.length = len & 0xff; 1122 1123 return scsi_command(sd, (void *)&cmd, sizeof(cmd), (void *)data, len); 1124 } 1125 1126 int 1127 scsi_command(struct sd_softc *sd, void *cmd, int cmdlen, void *data, 1128 int datalen) 1129 { 1130 struct siop_adapter *adp; 1131 struct scsi_xfer xs; 1132 int error; 1133 1134 if (sd->sc_bus != 0) 1135 return ENOTSUP; 1136 if (adapt.addr == 0) 1137 return ENOENT; 1138 adp = &adapt; 1139 1140 memcpy(adp->cmd, cmd, cmdlen); 1141 adp->sd = sd; 1142 1143 memset(&xs, 0, sizeof(xs)); 1144 xs.target = sd->sc_target; 1145 xs.lun = sd->sc_lun; 1146 xs.cmdlen = cmdlen; 1147 xs.cmd = adp->cmd; 1148 xs.datalen = datalen; 1149 xs.data = adp->data; 1150 1151 xs.error = XS_NOERROR; 1152 xs.resid = datalen; 1153 xs.status = SCSI_OK; 1154 1155 error = siop_scsi_request(adp, &xs); 1156 adp->sd = NULL; 1157 if (error != 0) 1158 return error; 1159 1160 if (datalen > 0) 1161 memcpy(data, adp->data, datalen); 1162 return 0; 1163 } 1164 1165 /* 1166 * Initialize the device. 1167 */ 1168 int 1169 siop_init(int bus, int dev, int func) 1170 { 1171 struct siop_adapter tmp; 1172 struct siop_xfer *xfer; 1173 struct scsipi_generic *cmd; 1174 struct scsi_request_sense *sense; 1175 uint32_t reg; 1176 u_long addr; 1177 uint32_t *script; 1178 int slot, id, i; 1179 void *scriptaddr; 1180 u_char *data; 1181 const int clock_div = 3; /* 53c810 */ 1182 1183 slot = PCISlotnum(bus, dev, func); 1184 if (slot == -1) 1185 return ENOENT; 1186 1187 addr = PCIAddress(slot, 1, PCI_MAPREG_TYPE_MEM); 1188 if (addr == 0xffffffff) 1189 return EINVAL; 1190 enablePCI(slot, 0, 1, 1); 1191 1192 script = ALLOC(uint32_t, SIOP_SCRIPT_SIZE); 1193 if (script == NULL) 1194 return ENOMEM; 1195 scriptaddr = (void *)local_to_PCI((u_long)script); 1196 cmd = ALLOC(struct scsipi_generic, SIOP_SCSI_COMMAND_SIZE); 1197 if (cmd == NULL) 1198 return ENOMEM; 1199 sense = ALLOC(struct scsi_request_sense, SIOP_SCSI_COMMAND_SIZE); 1200 if (sense == NULL) 1201 return ENOMEM; 1202 data = ALLOC(u_char, SIOP_SCSI_DATA_SIZE); 1203 if (data == NULL) 1204 return ENOMEM; 1205 xfer = ALLOC(struct siop_xfer, sizeof(struct siop_xfer)); 1206 if (xfer == NULL) 1207 return ENOMEM; 1208 siop_xfer_setup(xfer, scriptaddr); 1209 1210 id = readb(addr + SIOP_SCID) & SCID_ENCID_MASK; 1211 1212 /* reset bus */ 1213 reg = readb(addr + SIOP_SCNTL1); 1214 writeb(addr + SIOP_SCNTL1, reg | SCNTL1_RST); 1215 delay(100); 1216 writeb(addr + SIOP_SCNTL1, reg); 1217 1218 /* reset the chip */ 1219 writeb(addr + SIOP_ISTAT, ISTAT_SRST); 1220 delay(1000); 1221 writeb(addr + SIOP_ISTAT, 0); 1222 1223 /* init registers */ 1224 writeb(addr + SIOP_SCNTL0, SCNTL0_ARB_MASK | SCNTL0_EPC | SCNTL0_AAP); 1225 writeb(addr + SIOP_SCNTL1, 0); 1226 writeb(addr + SIOP_SCNTL3, clock_div); 1227 writeb(addr + SIOP_SXFER, 0); 1228 writeb(addr + SIOP_DIEN, 0xff); 1229 writeb(addr + SIOP_SIEN0, 0xff & ~(SIEN0_CMP | SIEN0_SEL | SIEN0_RSL)); 1230 writeb(addr + SIOP_SIEN1, 0xff & ~(SIEN1_HTH | SIEN1_GEN)); 1231 writeb(addr + SIOP_STEST2, 0); 1232 writeb(addr + SIOP_STEST3, STEST3_TE); 1233 writeb(addr + SIOP_STIME0, (0xb << STIME0_SEL_SHIFT)); 1234 writeb(addr + SIOP_SCID, id | SCID_RRE); 1235 writeb(addr + SIOP_RESPID0, 1 << id); 1236 writeb(addr + SIOP_DCNTL, DCNTL_COM); 1237 1238 /* BeBox uses PCIC */ 1239 writeb(addr + SIOP_STEST1, STEST1_SCLK); 1240 1241 siop_pci_reset(addr); 1242 1243 /* copy and patch the script */ 1244 for (i = 0; i < __arraycount(siop_script); i++) 1245 script[i] = htoc32(siop_script[i]); 1246 for (i = 0; i < __arraycount(E_abs_msgin_Used); i++) 1247 script[E_abs_msgin_Used[i]] = 1248 htoc32(scriptaddr + Ent_msgin_space); 1249 1250 /* start script */ 1251 _wbinv((u_long)script, SIOP_SCRIPT_SIZE); 1252 writel(addr + SIOP_DSP, (int)scriptaddr + Ent_reselect); 1253 1254 memset(&tmp, 0, sizeof(tmp)); 1255 tmp.id = id; 1256 tmp.clock_div = clock_div; 1257 tmp.addr = addr; 1258 tmp.script = script; 1259 tmp.xfer = xfer; 1260 tmp.cmd = cmd; 1261 tmp.sense = sense; 1262 tmp.data = data; 1263 tmp.currschedslot = 0; 1264 tmp.sel_t = -1; 1265 1266 if (scsi_probe(&tmp) == 0) 1267 return ENXIO; 1268 adapt = tmp; 1269 return 0; 1270 } 1271