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