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