1 /* 2 Copyright 1998-1999, Be Incorporated. All Rights Reserved. 3 This file may be used under the terms of the Be Sample Code License. 4 */ 5 6 /* 7 ** 53c8xx.c - Symbios 53c8xx SIM 8 */ 9 10 #define DEBUG_SYMBIOS 1 /* Print Debugging Messages */ 11 #define DEBUG_ISR 0 /* messages in ISR... leave off */ 12 #define DEBUG_PM 0 /* messages when Phase Mismatch occurs... leave off */ 13 #define DEBUG_SAFETY 0 /* don't load driver if serial debug off */ 14 15 #define USE_STATFS 0 16 17 /* 18 ** Debugging Macros 19 */ 20 #if DEBUG_SYMBIOS 21 #define d_printf dprintf 22 #else 23 #define d_printf(x...) 24 #endif 25 26 #include <OS.h> 27 #include <KernelExport.h> 28 #include <PCI.h> 29 #include <CAM.h> 30 #include <ByteOrder.h> 31 32 /* shorthand byteswapping macros */ 33 #define LE(n) B_HOST_TO_LENDIAN_INT32(n) 34 #define HE(n) B_LENDIAN_TO_HOST_INT32(n) 35 36 #include <stdlib.h> 37 #include <stdio.h> 38 #include <stdarg.h> 39 40 #include <string.h> 41 #include <iovec.h> 42 43 #include "53c8xx.h" 44 45 #include "symbios.h" 46 47 #if USE_STATFS 48 #include <stat_module.h> 49 50 static int32 51 stat_controller(void *stats, char **buf) 52 { 53 Symbios *s = (Symbios *) stats; 54 55 if(*buf = (char *) malloc(256)){ 56 sprintf(*buf, 57 "Chipset: %s\n" 58 "IO Base: 0x%08x\n" 59 "SRAM Base: 0x%08x\n" 60 "IRQ Line: %d\n" 61 "SCSI Bus: %s\n", 62 s->name, s->iobase, s->sram_phys, s->irq, 63 s->max_targ_id > 7 ? "Wide" : "Narrow"); 64 return strlen(*buf); 65 } else { 66 return 0; 67 } 68 } 69 70 static int32 71 stat_target(void *stats, char **buf) 72 { 73 SymTarg *st = (SymTarg *) stats; 74 75 if(st->flags & tf_ignore){ 76 *buf = NULL; 77 return 0; 78 } 79 80 if(*buf = (char *) malloc(256)){ 81 if(st->offset){ 82 sprintf(*buf, 83 "Width: %s\n" 84 "Transfer: Sync\n" 85 "Period: %d ns\n" 86 "Offset: %d\n", 87 st->wide ? "Wide" : "Narrow", 88 st->period, 89 st->offset 90 ); 91 } else { 92 sprintf(*buf, 93 "Width: %s\n" 94 "Transfer: Async\n", 95 st->wide ? "Wide" : "Narrow"); 96 } 97 return strlen(*buf); 98 } else { 99 return 0; 100 } 101 } 102 103 104 static void register_stats(Symbios *s) 105 { 106 char buf[128]; 107 stat_module_info_t *stats; 108 int i; 109 110 if(s->registered) return; 111 112 if(get_module("generic/stat_module", (module_info**) &stats) == B_OK){ 113 sprintf(buf,"scsi/53c8xx/%d/info",s->num); 114 stats->register_statistics(buf, s, stat_controller); 115 for(i=0;i<=s->max_targ_id;i++){ 116 sprintf(buf,"scsi/53c8xx/%d/targ_%x",s->num,i); 117 stats->register_statistics(buf, &(s->targ[i]), stat_target); 118 } 119 s->registered = 1; 120 } else { 121 dprintf("symbios: cannot find stats module...\n"); 122 } 123 } 124 125 #else 126 #define register_stats(x) 127 128 #endif 129 130 /* 131 ** Constants for the SIM 132 */ 133 #define SIM_VERSION 0x01 134 #define HBA_VERSION 0x01 135 136 static char sim_vendor_name[] = "Be, Inc."; 137 static char hba_vendor_name[] = "Symbios"; 138 139 static pci_module_info *pci; 140 static cam_for_sim_module_info *cam; 141 142 static char cam_name[] = B_CAM_FOR_SIM_MODULE_NAME; 143 static char pci_name[] = B_PCI_MODULE_NAME; 144 145 /* 146 ** Supported Device / Device Attributes table 147 */ 148 #define symf_sram 0x0001 /* on board SCRIPTS ram */ 149 #define symf_doubler 0x0002 /* SCLK doubler available */ 150 #define symf_quadrupler 0x0004 /* SCLK quadrupler available */ 151 #define symf_untested 0x1000 /* never actually tested one of these */ 152 #define symf_wide 0x0008 /* supports WIDE bus */ 153 #define symf_short 0x0010 /* short max period (8) */ 154 155 static struct { 156 uint32 id; 157 uint32 rev; 158 char *name; 159 int flags; 160 } devinfo[] = { 161 { 0x0001, 0x10, "53c810a", symf_short }, 162 { 0x0001, 0x00, "53c810", symf_short }, 163 { 0x0006, 0x00, "53c860", symf_wide | symf_short | symf_untested }, 164 { 0x0004, 0x00, "53c815", symf_short | symf_untested }, 165 { 0x0002, 0x00, "53c820", symf_wide | symf_short | symf_untested }, 166 { 0x0003, 0x10, "53c825a", symf_wide | symf_short |symf_sram | symf_untested }, 167 { 0x0003, 0x00, "53c825", symf_wide | symf_short | symf_untested }, 168 { 0x000f, 0x02, "53c875", symf_wide | symf_sram | symf_doubler }, 169 { 0x000f, 0x00, "53c875", symf_wide | symf_sram }, 170 { 0x008f, 0x00, "53c875j", symf_wide | symf_sram | symf_doubler }, 171 { 0x000d, 0x00, "53c885", symf_wide | symf_sram | symf_untested }, 172 { 0x000c, 0x00, "53c895", symf_wide | symf_sram | symf_quadrupler | symf_untested }, 173 { 0x000b, 0x00, "53c896", symf_wide | symf_sram | symf_untested }, 174 { 0, 0, NULL, 0 } 175 }; 176 177 #include "scripts.c" 178 179 static void 180 setparams(SymTarg *t, uint period, uint offset, uint wide) 181 { 182 Symbios *s = t->adapter; 183 184 if(wide){ 185 if(!t->wide) kprintf("symbios%ld: target %ld wide\n",s->num,t->id); 186 t->wide = 1; 187 } else { 188 t->wide = 0; 189 } 190 191 if(period){ 192 int i; 193 for(i=0;i<s->syncsize;i++){ 194 if(period <= s->syncinfo[i].period){ 195 t->period = s->syncinfo[i].period; 196 t->offset = offset; 197 198 t->device[3] = s->syncinfo[i].scntl3; 199 if(t->wide) t->device[3] |= 0x08; 200 t->device[2] = t->id; 201 t->device[1] = s->syncinfo[i].sxfer | (offset & 0x0f); 202 t->device[0] = 0; 203 kprintf("symbios%ld: target %ld sync period=%ld, offset=%d\n", 204 s->num, t->id, t->period, offset); 205 return; 206 } 207 } 208 } 209 210 t->period = 0; 211 t->offset = 0; 212 213 t->device[3] = s->scntl3; /* scntl3 - clock divisor */ 214 if(t->wide) t->device[3] |= 0x08; 215 t->device[2] = t->id; /* dest id */ 216 t->device[1] = 0; /* sync xfer */ 217 t->device[0] = 0; /* reserved */ 218 } 219 220 static long init_symbios(Symbios *s, int restarting); 221 222 /* 223 ** IO Macros 224 */ 225 226 /* XXX - fix me bjs */ 227 #define inb(p) (*pci->read_io_8)(s->iobase + p) 228 #define outb(p,v) (*pci->write_io_8)(s->iobase + p,v) 229 #define inw(p) (*pci->read_io_16)(s->iobase + p) 230 #define outw(p,v) (*pci->write_io_16)(s->iobase + p,v) 231 #define in32(p) (*pci->read_io_32)(s->iobase + p) 232 #define out32(p,v) (*pci->write_io_32)(s->iobase + p,v) 233 234 235 /* patch in an external symbol */ 236 #define RESOLV(sname,value) \ 237 { int i; \ 238 d_printf("symbios%d: relocting %d instances of %s to 0x%08x\n", \ 239 s->num,sizeof(E_##sname##_Used)/4,#sname,value); \ 240 for(i=0;i<(sizeof(E_##sname##_Used)/4);i++) { \ 241 scr[E_##sname##_Used[i]] = ((uint32) value); \ 242 } \ 243 } 244 245 /* calc phys addr of a ptr inside the sram area */ 246 #define PHADDR(lvar) ((s->sram_phys) + (((uint32) &(lvar)) - ((uint32) s->script))) 247 248 /* calc phys addr of a ptr inside the priv area */ 249 /*#define PPHADDR(ptr) (st->priv_phys + (((uint32) ptr) - ((uint32) st->priv)))*/ 250 #define PPHADDR(ptr) (phys + (((uint32) ptr) - ((uint32) sp))) 251 252 /* prepare a Targ's scripts indirect table for one or more exec_io's */ 253 static void prep_io(SymPriv *sp, uint32 phys) 254 { 255 sp->syncmsg.address = LE(PPHADDR(sp->_syncmsg)); 256 sp->syncmsg.count = LE(3); 257 258 sp->widemsg.address = LE(PPHADDR(sp->_widemsg)); 259 sp->widemsg.count = LE(2); 260 261 sp->sendmsg.address = LE(PPHADDR(sp->_sendmsg)); 262 263 sp->recvmsg.address = LE(PPHADDR(sp->_recvmsg)); 264 sp->recvmsg.count = LE(1); 265 266 sp->status.address = LE(PPHADDR(sp->_status)); 267 sp->status.count = LE(1); 268 269 sp->extdmsg.address = LE(PPHADDR(sp->_extdmsg)); 270 sp->extdmsg.count = LE(1); 271 272 sp->command.address = LE(PPHADDR(sp->_command)); 273 } 274 275 /* 276 * actually execute an io transaction via SCRIPTS 277 * you MUST hold st->sem_targ before calling this 278 * 279 */ 280 static void exec_io(SymTarg *st, void *cmd, int cmdlen, void *msg, int msglen, 281 void *data, int datalen, int sg) 282 { 283 cpu_status former; 284 Symbios *s = st->adapter; 285 286 memcpy((void *) &(st->priv->device.count), st->device, 4); 287 288 st->priv->sendmsg.count = LE(msglen); 289 memcpy(st->priv->_sendmsg, msg, msglen); 290 st->priv->command.count = LE(cmdlen); 291 memcpy(st->priv->_command, cmd, cmdlen); 292 293 st->table_phys = st->priv_phys + ADJUST_PRIV_TO_TABLE; 294 295 if(datalen){ 296 int i,sgcount; 297 uint32 opcode; 298 SymInd *t = st->priv->table; 299 physical_entry *pe = (physical_entry *) &(st->priv->table[1]); 300 301 if(st->inbound){ 302 opcode = s->op_in; 303 st->datain_phys = st->table_phys; 304 st->dataout_phys = s->sram_phys + Ent_phase_dataerr; 305 } else { 306 opcode = s->op_out; 307 st->dataout_phys = st->table_phys; 308 st->datain_phys = s->sram_phys + Ent_phase_dataerr; 309 } 310 311 if(sg) { 312 iovec *vec = (iovec *) data; 313 for(sgcount=0,i=0;i<datalen;i++){ 314 get_memory_map(vec[i].iov_base, vec[i].iov_len, &pe[sgcount], 130-sgcount); 315 while(pe[sgcount].size && (sgcount < 130)){ 316 t[sgcount].address = LE((uint32) pe[sgcount].address); 317 t[sgcount].count = LE(opcode | pe[sgcount].size); 318 sgcount++; 319 } 320 if((sgcount == 130) && pe[sgcount].size){ 321 panic("symbios: sg list overrun"); 322 } 323 } 324 } else { 325 get_memory_map(data, datalen, pe, 130); 326 for(i=0;pe[i].size;i++){ 327 t[i].address = LE((uint32) pe[i].address); 328 t[i].count = LE(opcode | pe[i].size); 329 } 330 sgcount = i; 331 } 332 t[sgcount].count = LE(OP_END); 333 t[sgcount].address = LE(ARG_END); 334 335 // for(i=0;i<=sgcount;i++){ 336 // dprintf("sym: %04d - %08x %08x\n",i,t[i].address,t[i].count); 337 // } 338 } else { 339 st->datain_phys = s->sram_phys + Ent_phase_dataerr; 340 st->dataout_phys = s->sram_phys + Ent_phase_dataerr; 341 } 342 343 // dprintf("sym: pp = %08x di = %08x do = %08x\n",st->priv_phys,st->datain_phys,st->dataout_phys); 344 345 st->status = status_queued; 346 347 /* dprintf("symbios: enqueueing %02x %02x %02x ... for %d (%d bytes %s)\n", 348 ((uchar *)cmd)[0],((uchar *)cmd)[1],((uchar *)cmd)[2], 349 st->device[2],datalen,st->inbound?"IN":"OUT"); 350 */ 351 former = disable_interrupts(); 352 acquire_spinlock(&(s->hwlock)); 353 354 /* enqueue the request */ 355 if(s->startqueuetail){ 356 s->startqueuetail->next = st; 357 } else { 358 s->startqueue = st; 359 } 360 st->next = NULL; 361 s->startqueuetail = st; 362 363 /* If the adapter is idle, signal it so that this request may be started */ 364 if(s->status == IDLE) outb(sym_istat, sym_istat_sigp); 365 366 release_spinlock(&(s->hwlock)); 367 restore_interrupts(former); 368 369 /* wait for completion */ 370 acquire_sem(st->sem_done); 371 372 #if 0 373 if(acquire_sem_etc(st->sem_done, 1, B_TIMEOUT, 10*1000000) != B_OK){ 374 kprintf("sym: targ %d never finished, argh...\n",st->device[2]); 375 init_symbios(st->adapter,1); 376 st->state = sTIMEOUT; 377 return; 378 } 379 #endif 380 } 381 382 383 #if DEBUG_ISR 384 #define kp kprintf 385 #else 386 #define kp(x...) 387 #endif 388 389 static int32 390 scsi_int_dispatch(void *data) 391 { 392 Symbios *s = (Symbios *) data; 393 int reselected = 0; 394 uchar istat; 395 396 if(s->reset) return B_UNHANDLED_INTERRUPT; 397 398 acquire_spinlock(&(s->hwlock)); 399 istat = inb(sym_istat); 400 401 if(istat & sym_istat_dip){ 402 uchar dstat = inb(sym_dstat); 403 404 if(dstat & sym_dstat_sir){ 405 /* Handle and interrupt from the SCRIPTS program */ 406 uint32 status = HE(in32(sym_dsps)); 407 // kprintf("<%02x>",status); 408 409 switch(status){ 410 case status_ready: 411 kp("sym: ready\n"); 412 break; 413 414 case status_iocomplete: 415 kp("sym: done %08x\n",s->active); 416 if(s->active){ 417 /* io is complete -- any more io is an error */ 418 s->active->datain_phys = s->sram_phys + Ent_phase_dataerr; 419 s->active->dataout_phys = s->sram_phys + Ent_phase_dataerr; 420 } 421 break; 422 423 case status_reselected:{ 424 uint32 id = inb(sym_ssid); 425 if(id & sym_ssid_val) { 426 s->active = &(s->targ[id & s->idmask]); 427 kp("sym: resel %08x\n",s->active); 428 if(s->active->status != status_waiting){ 429 s->active = NULL; 430 kprintf("symbios: bad reselect %ld\n",id & sym_ssid_encid); 431 } else { 432 reselected = 1; 433 } 434 } else { 435 kprintf("symbios: invalid reselection!?\n"); 436 } 437 break; 438 } 439 440 case status_timeout: 441 /* inform the unlucky party and dequeue it */ 442 kp("sym: timeout %08lx\n",s->startqueue); 443 if(s->startqueue){ 444 s->startqueue->status = status_timeout; 445 release_sem_etc(s->startqueue->sem_done, 1, B_DO_NOT_RESCHEDULE); 446 if(!(s->startqueue = s->startqueue->next)){ 447 s->startqueuetail = NULL; 448 } 449 } 450 break; 451 452 case status_selected: 453 /* selection succeeded. Remove from start queue and make active */ 454 kp("sym: selected %08lx\n",s->startqueue); 455 if(s->startqueue){ 456 s->active = s->startqueue; 457 s->active->status = status_active; 458 if(!(s->startqueue = s->startqueue->next)){ 459 s->startqueuetail = NULL; 460 } 461 } 462 break; 463 464 case status_syncin: 465 setparams(s->active, 466 s->active->priv->_syncmsg[1]*4, 467 s->active->priv->_syncmsg[2], 468 s->active->wide); 469 break; 470 471 case status_widein: 472 setparams(s->active, s->active->period, s->active->offset, 473 s->active->priv->_widemsg[1]); 474 break; 475 476 case status_ignore_residue: 477 kprintf("ignore residue 0x%02x\n",s->active->priv->_extdmsg[0]); 478 break; 479 480 case status_disconnect: 481 kp("sym: disc %08lx\n",s->active); 482 /* device disconnected. make inactive */ 483 if(s->active){ 484 s->active->status = status_waiting; 485 s->active = NULL; 486 } 487 break; 488 489 case status_badmsg: 490 kp("sym: badmsg %02x\n",s->active->priv->_recvmsg[0]); 491 492 case status_complete: 493 case status_badstatus: 494 case status_overrun: 495 case status_underrun: 496 case status_badphase: 497 case status_badextmsg: 498 kp("sym: error %08lx / %02x\n",s->active,status); 499 /* transaction completed successfully or in error. report our status. */ 500 if(s->active){ 501 s->active->status = status; 502 release_sem_etc(s->active->sem_done, 1, B_DO_NOT_RESCHEDULE); 503 s->active = NULL; 504 } 505 break; 506 507 case status_selftest: 508 /* signal a response to the selftest ... don't actually start up the 509 SCRIPTS like we normally do */ 510 s->status = OFFLINE; 511 goto done; 512 break; 513 514 default: 515 kp("sym: int 0x%08lx ...\n",status); 516 } 517 goto reschedule; 518 } else { 519 kprintf("symbios: weird error, dstat = %02x\n",dstat); 520 } 521 } 522 523 if(istat & sym_istat_sip){ 524 uchar sist0; 525 sist0 = inb(sym_sist1); 526 527 if(sist0 & sym_sist1_sbmc){ 528 kprintf("sym: SBMC %02x!\n",inb(sym_stest4) & 0xc0); 529 } 530 531 if(sist0 & sym_sist1_sto){ 532 /* select timeout */ 533 kp("sym: Timeout %08lx\n",s->startqueue); 534 /* inform the unlucky party and dequeue it */ 535 if(s->startqueue){ 536 s->startqueue->status = status_timeout; 537 release_sem_etc(s->startqueue->sem_done, 1, B_DO_NOT_RESCHEDULE); 538 if(!(s->startqueue = s->startqueue->next)){ 539 s->startqueuetail = NULL; 540 } 541 } else { 542 kprintf("symbios: ghost target timed out\n"); 543 } 544 inb(sym_sist0); // apparently we MUST read sist0 as well 545 goto reschedule; 546 } 547 548 sist0 = inb(sym_sist0) & 0x8f; 549 550 if(sist0 && s->active){ 551 if(sist0 & sym_sist0_ma){ 552 /* phase mismatch -- we experienced a disconnect while in 553 a DataIn or DataOut... gotta figure out how much we 554 transferred, update the sgtable, take the FIFOs into 555 account, etc (see 9-9 in Symbios PCI-SCSI Programming Guide) */ 556 SymInd *t; 557 uint32 dfifo_val, bytesleft, dbc; 558 uint32 dsp = HE(in32(sym_dsp)); 559 uint32 n = (dsp - s->active->table_phys) / 8 - 1; 560 561 if((dsp < s->active->priv_phys) || (n > 129)) { 562 /* we mismatched during some other phase ?! */ 563 kprintf("Phase Mismatch (dsp = 0x%08lx)\n",dsp); 564 goto reschedule; 565 } 566 567 t = &(s->active->priv->table[n]); 568 569 #if 0 570 t->count = HE(t->count); 571 t->address = HE(t->count); 572 #endif 573 /* dbc initially = table[n].count, counts down */ 574 dbc = (uint32) HE(in32(sym_dbc)) & 0x00ffffffL; 575 576 t->count &= 0xffffff; 577 #if DEBUG_PM 578 kprintf("PM(%s) dbc=0x%08x, n=%02d, a=0x%08x, l=0x%08x\n", 579 s->active->inbound ? " in" : "out", dbc, n, t->address, t->count); 580 #endif 581 if(s->active->inbound){ 582 /* data in is easy... flush happens automatically */ 583 t->address += t->count - dbc; 584 t->count = dbc; 585 #if DEBUG_PM 586 kprintf(" a=0x%08x, l=0x%08x\n", 587 t->address, t->count); 588 #endif 589 s->active->datain_phys = s->active->table_phys + 8*(t->count ? n : n+1); 590 t->count |= s->op_in; 591 #if 0 592 t->count = LE(t->count); 593 t->address = LE(t->address); 594 #endif 595 goto reschedule; 596 } else { 597 if(inb(sym_ctest5) & 0x20){ 598 /* wide FIFO */ 599 dfifo_val = ((inb(sym_ctest5) & 0x03) << 8) | inb(sym_dfifo); 600 bytesleft = (dfifo_val - (dbc & 0x3ff)) & 0x3ff; 601 } else { 602 dfifo_val = (inb(sym_dfifo) & 0x7f); 603 bytesleft = (dfifo_val - (dbc & 0x7f)) & 0x7f; 604 } 605 if(inb(sym_sstat0) & 0x20) bytesleft++; 606 if(inb(sym_sstat2) & 0x20) bytesleft++; 607 if(inb(sym_sstat0) & 0x40) bytesleft++; 608 if(inb(sym_sstat2) & 0x40) bytesleft++; 609 610 /* clear fifo */ 611 outb(sym_ctest3, 0x04); 612 613 t->address += t->count - dbc; 614 t->count = dbc; 615 616 /* adjust for data that didn't make it to the target */ 617 t->address -= bytesleft; 618 t->count += bytesleft; 619 #if DEBUG_PM 620 kprintf(" a=0x%08x, l=0x%08x\n", 621 t->address, t->count); 622 #endif 623 s->active->dataout_phys = s->active->table_phys + 8*(t->count ? n : n+1); 624 t->count |= s->op_out; 625 #if 0 626 t->count = LE(t->count); 627 t->address = LE(t->address); 628 #endif 629 spin(10); 630 goto reschedule; 631 } 632 } 633 634 if(sist0 & sym_sist0_udc){ 635 kprintf("symbios: Unexpected Disconnect (dsp = 0x%08lx)\n", in32(sym_dsp)); 636 } 637 638 if(sist0 & sym_sist0_sge){ 639 kprintf("symbios: SCSI Gross Error\n"); 640 } 641 642 if(sist0 & sym_sist0_rst){ 643 kprintf("symbios: SCSI Reset\n"); 644 } 645 646 if(sist0 & sym_sist0_par){ 647 kprintf("symbios: Parity Error\n"); 648 } 649 650 s->active->status = status_badphase; 651 release_sem_etc(s->active->sem_done, 1, B_DO_NOT_RESCHEDULE); 652 s->active = NULL; 653 654 goto reschedule; 655 } 656 } else { 657 /* nothing happened... must be somebody else's problem */ 658 release_spinlock(&(s->hwlock)); 659 return B_UNHANDLED_INTERRUPT; 660 } 661 662 reschedule: 663 /* start the SCRIPTS processor at one of three places, depending on state 664 ** 665 ** 1. If there is an active transaction, insure that the script is patched 666 ** correctly, the DSA is loaded, and start up at "switch". 667 ** 668 ** 2. If there is a transaction at the head of the startqueue, set the DSA 669 ** and start up at "start" to try to select the target and start the 670 ** transaction 671 ** 672 ** 3. If there is nothing else to do, go to "idle" and wait for signal or 673 ** reselection 674 */ 675 676 if(s->active){ 677 out32(sym_dsa, s->active->priv_phys + ADJUST_PRIV_TO_DSA); 678 s->script[PATCH_DATAIN] = LE(s->active->datain_phys); 679 s->script[PATCH_DATAOUT] = LE(s->active->dataout_phys); 680 681 s->active->status = status_active; 682 s->status = ACTIVE; 683 if(reselected){ 684 out32(sym_dsp, LE(s->sram_phys + Ent_switch_resel)); 685 //kp("sym: restart @ %08x / reselected\n",Ent_switch_resel); 686 } else { 687 out32(sym_dsp, LE(s->sram_phys + Ent_switch)); 688 //kp("sym: restart @ %08x / selected\n", Ent_switch); 689 } 690 } else { 691 if(s->startqueue){ 692 out32(sym_dsa, LE(s->startqueue->priv_phys + ADJUST_PRIV_TO_DSA)); 693 694 s->startqueue->status = status_selecting; 695 s->status = START; 696 out32(sym_dsp, LE(s->sram_phys + Ent_start)); 697 //kp("sym: restart @ %08x / started\n", Ent_start); 698 } else { 699 s->status = IDLE; 700 out32(sym_dsp, LE(s->sram_phys + Ent_idle)); 701 //kp("sym: restart @ %08x / idle\n", Ent_idle); 702 } 703 } 704 705 done: 706 release_spinlock(&(s->hwlock)); 707 return B_HANDLED_INTERRUPT; 708 } 709 710 711 /* init the adapter... if restarting, no bus reset or whathaveyou */ 712 static long init_symbios(Symbios *s, int restarting) 713 { 714 d_printf("symbios%ld: init_symbios()\n",s->num); 715 716 if(restarting){ 717 s->reset = 1; 718 } else { 719 s->reset = 0; 720 } 721 722 if(!restarting){ 723 /* reset the SCSI bus */ 724 dprintf("symbios%ld: scsi bus reset\n",s->num); 725 outb(sym_scntl1, sym_scntl1_rst); 726 spin(25); 727 outb(sym_scntl1, 0); 728 spin(250000); 729 730 /* clear ints */ 731 inb(sym_istat); 732 inb(sym_sist0); 733 inb(sym_sist1); 734 inb(sym_dstat); 735 736 install_io_interrupt_handler(s->irq, scsi_int_dispatch, s, 0); 737 d_printf("symbios%ld: registered interrupt handler for irq %ld\n",s->num,s->irq); 738 } 739 740 /* enable irqs, prefetch, no 53c700 compat */ 741 outb(sym_dcntl, sym_dcntl_com); 742 743 /* enable all DMA ints */ 744 outb(sym_dien, sym_dien_sir | sym_dien_mdpe | sym_dien_bf | sym_dien_abrt 745 | sym_dien_iid); 746 /* enable all fatal SCSI ints */ 747 outb(sym_sien0, sym_sien0_ma | sym_sien0_sge | sym_sien0_udc | sym_sien0_rst | 748 sym_sien0_par); 749 outb(sym_sien1, sym_sien1_sto | sym_sien1_sbmc); // XXX 750 751 /* sel / hth timeouts */ 752 outb(sym_stime0, 0xbb); 753 754 /* clear ints */ 755 inb(sym_istat); 756 inb(sym_sist0); 757 inb(sym_sist1); 758 inb(sym_dstat); 759 760 /* clear ints */ 761 inb(sym_sist0); 762 inb(sym_sist1); 763 inb(sym_dstat); 764 765 if(restarting){ 766 s->reset = 0; 767 } else { 768 int i; 769 s->status = TEST; 770 771 dprintf("symbios%ld: selftest ",s->num); 772 out32(sym_dsp, LE(s->sram_phys + Ent_test)); 773 for(i=0;(s->status == TEST) && i<10;i++) { 774 dprintf("."); 775 spin(10000); 776 } 777 if(s->status == TEST){ 778 dprintf("FAIL\n"); 779 return B_ERROR; //XXX teardown 780 } else { 781 dprintf("PASS\n"); 782 } 783 } 784 785 s->status = IDLE; 786 out32(sym_dsp, LE(s->sram_phys + Ent_idle)); 787 d_printf("symbios%ld: started script\n",s->num); 788 789 return B_NO_ERROR; 790 } 791 792 /* When an inquiry succeeds the negotiator gets the option to attempt to 793 ** request a better transfer agreement with the target. 794 */ 795 static void negotiator(Symbios *s, SymTarg *targ, uchar *ident, uchar *msg) 796 { 797 if(ident[7] & 0x20){ /* wide supported */ 798 if(targ->flags & tf_ask_wide){ 799 uchar cmd[6] = { 0, 0, 0, 0, 0, 0 }; 800 targ->flags &= (~tf_ask_wide); /* only ask once */ 801 802 dprintf("symbios%ld: negotiating wide xfer with target %ld\n", 803 s->num,targ->id); 804 805 msg[1] = 0x01; /* extended message */ 806 msg[2] = 0x02; /* length */ 807 msg[3] = 0x03; /* sync negotiate */ 808 msg[4] = 0x01; /* 16 bit wide */ 809 810 exec_io(targ, cmd, 6, msg, 5, NULL, 0, 0); 811 } 812 } 813 814 if(ident[7] & 0x10){ /* sync supported */ 815 if(targ->flags & tf_ask_sync) { 816 uchar cmd[6] = { 0, 0, 0, 0, 0, 0 }; 817 818 targ->flags &= (~tf_ask_sync); /* only ask once */ 819 820 dprintf("symbios%ld: negotiating sync xfer with target %ld\n", 821 s->num,targ->id); 822 823 msg[1] = 0x01; /* extended message */ 824 msg[2] = 0x03; /* length */ 825 msg[3] = 0x01; /* sync negotiate */ 826 msg[4] = s->syncinfo[0].period / 4; /* sync period / 4 */ 827 msg[5] = s->maxoffset; 828 829 exec_io(targ, cmd, 6, msg, 6, NULL, 0, 0); 830 } 831 } 832 } 833 834 /* Convert a CCB_SCSIIO into a BL_CCB32 and (possibly SG array). 835 ** 836 */ 837 static long sim_execute_scsi_io(Symbios *s, CCB_HEADER *ccbh) 838 { 839 CCB_SCSIIO *ccb = (CCB_SCSIIO *) ccbh; 840 uchar *cdb; 841 physical_entry pe[2]; 842 SymTarg *targ; 843 uchar msg[8]; 844 845 targ = s->targ + ccb->cam_ch.cam_target_id; 846 847 if(targ->flags & tf_ignore){ 848 ccbh->cam_status = CAM_SEL_TIMEOUT; 849 return B_OK; 850 } 851 852 if(ccb->cam_ch.cam_flags & CAM_CDB_POINTER) { 853 cdb = ccb->cam_cdb_io.cam_cdb_ptr; 854 } else { 855 cdb = ccb->cam_cdb_io.cam_cdb_bytes; 856 } 857 858 get_memory_map((void*) (ccb->cam_sim_priv), 1536, pe, 2); 859 860 /* identify message */ 861 msg[0] = 0xC0 | (ccb->cam_ch.cam_target_lun & 0x07); 862 863 /* fill out table */ 864 prep_io((SymPriv *) ccb->cam_sim_priv, (uint32) pe[0].address); 865 866 /* insure only one transaction at a time for any given target */ 867 acquire_sem(targ->sem_targ); 868 869 targ->priv = (SymPriv *) ccb->cam_sim_priv;; 870 targ->priv_phys = (uint32 ) pe[0].address; 871 872 targ->inbound = (ccb->cam_ch.cam_flags & CAM_DIR_IN) ? 1 : 0; 873 874 if(ccb->cam_ch.cam_flags & CAM_SCATTER_VALID){ 875 exec_io(targ, cdb, ccb->cam_cdb_len, msg, 1, 876 ccb->cam_data_ptr, ccb->cam_sglist_cnt, 1); 877 } else { 878 exec_io(targ, cdb, ccb->cam_cdb_len, msg, 1, 879 ccb->cam_data_ptr, ccb->cam_dxfer_len, 0); 880 } 881 882 /* dprintf("symbios%d: state = 0x%02x, status = 0x%02x\n", 883 s->num,targ->state,targ->priv->status[0]);*/ 884 885 /* decode status */ 886 switch(targ->status){ 887 case status_complete: 888 if((ccb->cam_scsi_status=targ->priv->_status[0]) != 0) { 889 ccbh->cam_status = CAM_REQ_CMP_ERR; 890 891 /* nonzero status is an error ... 0x02 = check condition */ 892 if((ccb->cam_scsi_status == 0x02) && 893 !(ccb->cam_ch.cam_flags & CAM_DIS_AUTOSENSE) && 894 ccb->cam_sense_ptr && ccb->cam_sense_len){ 895 uchar command[6]; 896 897 command[0] = 0x03; /* request_sense */ 898 command[1] = ccb->cam_ch.cam_target_lun << 5; 899 command[2] = 0; 900 command[3] = 0; 901 command[4] = ccb->cam_sense_len; 902 command[5] = 0; 903 904 targ->inbound = 1; 905 exec_io(targ, command, 6, msg, 1, 906 ccb->cam_sense_ptr, ccb->cam_sense_len, 0); 907 908 if(targ->priv->_status[0]){ 909 ccb->cam_ch.cam_status |= CAM_AUTOSENSE_FAIL; 910 } else { 911 ccb->cam_ch.cam_status |= CAM_AUTOSNS_VALID; 912 } 913 } 914 } else { 915 ccbh->cam_status = CAM_REQ_CMP; 916 917 if(cdb[0] == 0x12) { 918 /* inquiry just succeeded ... is it non SG and with enough data to 919 snoop the support bits? */ 920 if(!(ccb->cam_ch.cam_flags & CAM_SCATTER_VALID) && (ccb->cam_dxfer_len>7)){ 921 negotiator(s, targ, ccb->cam_data_ptr, msg); 922 } 923 } 924 } 925 break; 926 927 case status_timeout: 928 ccbh->cam_status = CAM_SEL_TIMEOUT; 929 break; 930 931 default: // XXX 932 ccbh->cam_status = CAM_SEL_TIMEOUT; 933 } 934 935 targ->status = status_inactive; 936 // dprintf("symbios%d: releasing targ @ 0x%08x\n",s->num,targ); 937 release_sem(targ->sem_targ); 938 return B_OK; 939 } 940 941 /* 942 ** sim_path_inquiry returns info on the target/lun. 943 */ 944 static long sim_path_inquiry(Symbios *s, CCB_HEADER *ccbh) 945 { 946 CCB_PATHINQ *ccb; 947 ccb = (CCB_PATHINQ *) ccbh; 948 ccb->cam_version_num = SIM_VERSION; 949 ccb->cam_target_sprt = 0; 950 ccb->cam_hba_eng_cnt = 0; 951 memset (ccb->cam_vuhba_flags, 0, VUHBA); 952 ccb->cam_sim_priv = SIM_PRIV; 953 ccb->cam_async_flags = 0; 954 ccb->cam_initiator_id = s->host_targ_id; 955 ccb->cam_hba_inquiry = s->max_targ_id > 7 ? PI_WIDE_16 : 0 ; 956 strncpy (ccb->cam_sim_vid, sim_vendor_name, SIM_ID); 957 strncpy (ccb->cam_hba_vid, hba_vendor_name, HBA_ID); 958 ccb->cam_osd_usage = 0; 959 ccbh->cam_status = CAM_REQ_CMP; 960 register_stats(s); 961 return 0; 962 } 963 964 965 /* 966 ** sim_extended_path_inquiry returns info on the target/lun. 967 */ 968 static long sim_extended_path_inquiry(Symbios *s, CCB_HEADER *ccbh) 969 { 970 CCB_EXTENDED_PATHINQ *ccb; 971 972 sim_path_inquiry(s, ccbh); 973 ccb = (CCB_EXTENDED_PATHINQ *) ccbh; 974 sprintf(ccb->cam_sim_version, "%d.0", SIM_VERSION); 975 sprintf(ccb->cam_hba_version, "%d.0", HBA_VERSION); 976 strncpy(ccb->cam_controller_family, "Symbios", FAM_ID); 977 strncpy(ccb->cam_controller_type, s->name, TYPE_ID); 978 return 0; 979 } 980 981 /* 982 ** scsi_sim_action performes the scsi i/o command embedded in the 983 ** passed ccb. 984 ** 985 ** The target/lun ids are assumed to be in range. 986 */ 987 static long sim_action(Symbios *s, CCB_HEADER *ccbh) 988 { 989 ccbh->cam_status = CAM_REQ_INPROG; 990 switch(ccbh->cam_func_code){ 991 case XPT_SCSI_IO: 992 return sim_execute_scsi_io(s,ccbh); 993 case XPT_PATH_INQ: 994 return sim_path_inquiry(s,ccbh); 995 case XPT_EXTENDED_PATH_INQ: 996 return sim_extended_path_inquiry(s, ccbh); 997 default: 998 ccbh->cam_status = CAM_REQ_INVALID; 999 return -1; 1000 } 1001 } 1002 1003 static void reloc_script(Symbios *s) 1004 { 1005 int i; 1006 ulong *scr = s->script; 1007 1008 memcpy(scr, SCRIPT, sizeof(SCRIPT)); 1009 for(i=0;i<PATCHES;i++){ 1010 scr[LABELPATCHES[i]] += s->sram_phys; 1011 } 1012 d_printf("symbios%ld: loaded %ld byte SCRIPT, relocated %ld labels\n", 1013 s->num, sizeof(SCRIPT), PATCHES); 1014 1015 /* disable scsi ints */ 1016 outb(sym_scratcha, 0x42); 1017 outb(sym_scratcha+1, 0x00); 1018 outb(sym_scratchb, 0x04); 1019 outb(sym_sien0, 0); 1020 outb(sym_sien1, 0); 1021 outb(sym_dien, sym_dien_sir); 1022 1023 /* clear ints */ 1024 inb(sym_sist0); 1025 inb(sym_sist1); 1026 inb(sym_dstat); 1027 1028 outb(sym_dmode, ( sym_dmode_diom | sym_dmode_siom, 0 )); /* FIXME: ??? */ 1029 } 1030 1031 static uint32 sym_readclock(Symbios *s) 1032 { 1033 uint32 ms,a,i; 1034 bigtime_t t0,t1; 1035 1036 outw(sym_sien0 , 0); /* mask all scsi interrupts */ 1037 outb(sym_dien , 0); /* mask all dma interrupts */ 1038 inw(sym_sist0); /* clear pending scsi interrupts */ 1039 outb(sym_scntl3, 4); /* set pre-scaler to divide by 3 */ 1040 1041 for(a=0,i=0;i<5;i++){ 1042 ms = 0; 1043 outb(sym_stime1, 0); /* disable general purpose timer */ 1044 spin(10000); /* let it all settle for 10ms */ 1045 inw(sym_sist0); /* another one, just to be sure :) */ 1046 1047 t0 = system_time(); 1048 outb(sym_stime1, 11); /* delay of 128ms */ 1049 while (!(inb(sym_sist1) & sym_sist1_gen)) snooze(250); 1050 t1 = system_time(); 1051 ms = (t1-t0)/1000 + 10; /* we seem to be off by 10ms typically */ 1052 1053 a += ((1 << 11) * 4400) / ms; 1054 } 1055 1056 outb(sym_stime1, 0); /* disable general purpose timer */ 1057 return a / 5; 1058 } 1059 1060 static uchar id_bits[8] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 }; 1061 1062 /* 1063 ** Allocate the actual memory for the cardinfo object 1064 */ 1065 static Symbios *create_cardinfo(int num, pci_info *pi, int flags) 1066 { 1067 char name[32]; 1068 Symbios *s; 1069 int i,scf; 1070 area_id aid; 1071 uint32 stest2,stest4; 1072 1073 if((pi->u.h0.interrupt_line == 0) || (pi->u.h0.interrupt_line > 128)) { 1074 return NULL; /* invalid IRQ */ 1075 } 1076 1077 if(!(s = (Symbios *) malloc(sizeof(Symbios)))) return NULL; 1078 1079 s->num = num; 1080 s->iobase = pi->u.h0.base_registers[0]; 1081 s->irq = pi->u.h0.interrupt_line; 1082 s->hwlock = 0; 1083 s->startqueue = NULL; 1084 s->startqueuetail = NULL; 1085 s->active = NULL; 1086 1087 sprintf(name,"sym%d:sram",num); 1088 if(flags & symf_sram){ 1089 unsigned char *c; 1090 s->sram_phys = pi->u.h0.base_registers[2]; 1091 if((aid=map_physical_memory(name, (void *) s->sram_phys, 4096, 1092 B_ANY_KERNEL_ADDRESS, B_READ_AREA + B_WRITE_AREA, 1093 (void **) &(s->script))) < 0){ 1094 free(s); 1095 return NULL; 1096 } 1097 /* memory io test */ 1098 c = (unsigned char *) s->script; 1099 for(i=0;i<4096;i++) c[i] = (255 - (i & 0xff)); 1100 for(i=0;i<4096;i++) { 1101 if(c[i] != (255 - (i & 0xff))) { 1102 d_printf("symbios%d: scripts ram io error @ %d\n",num,i); 1103 goto err; 1104 } 1105 } 1106 } else { 1107 uchar *a; 1108 physical_entry entries[2]; 1109 aid = create_area(name, (void **)&a, B_ANY_KERNEL_ADDRESS, 4096*5, 1110 B_CONTIGUOUS, B_READ_AREA | B_WRITE_AREA); 1111 if(aid == B_ERROR || aid == B_BAD_VALUE || aid == B_NO_MEMORY){ 1112 free(s); 1113 return NULL; 1114 } 1115 get_memory_map(a, 4096, entries, 2); 1116 s->sram_phys = (uint32) entries[0].address; 1117 s->script = (uint32 *) a; 1118 } 1119 1120 d_printf("symbios%d: scripts ram @ 0x%08lx, mapped to 0x%08lx (%s)\n", 1121 num, s->sram_phys, (uint32) s->script, 1122 flags & symf_sram ? "onboard" : "offboard" ); 1123 1124 /* what are we set at now? */ 1125 s->host_targ_id = inb(sym_scid) & 0x07; 1126 dprintf("symbios%ld: host id %ld\n",s->num,s->host_targ_id); 1127 1128 s->host_targ_id = 7; /* XXX figure this out somehow... */ 1129 s->max_targ_id = (flags & symf_wide) ? 15 : 7; 1130 1131 stest2 = inb(sym_stest2); 1132 stest4 = inb(sym_stest4); 1133 1134 /* software reset */ 1135 outb(sym_istat, sym_istat_srst); 1136 spin(10000); 1137 outb(sym_istat, 0); 1138 spin(10000); 1139 1140 /* initiator mode, full arbitration */ 1141 outb(sym_scntl0, sym_scntl0_arb0 | sym_scntl0_arb1); 1142 1143 outb(sym_scntl1, 0); 1144 outb(sym_scntl2, 0); 1145 1146 /* initiator id=7, respond to reselection */ 1147 /* respond to reselect of id 7 */ 1148 outb(sym_respid, id_bits[s->host_targ_id]); 1149 outb(sym_scid, sym_scid_rre | s->host_targ_id); 1150 1151 outb(sym_dmode, 0); 1152 1153 dprintf("symbios%ld: stest2 = 0x%02lx, stest4 = 0x%02lx\n",s->num,stest2,stest4); 1154 1155 /* no differential, no loopback, no hiz, no always-wide, no filter, no lowlevel */ 1156 outb(sym_stest2, 0); // save diff bit 1157 outb(sym_stest3, 0); 1158 1159 // if(flags & symf_quadrupler){ 1160 // outb(sym_stest4, sym_stest4_lvd); 1161 // } 1162 1163 outb(sym_stest1, 0); /* make sure clock doubler is OFF */ 1164 1165 s->sclk = sym_readclock(s); 1166 dprintf("symbios%ld: clock is %ldKHz\n",s->num,s->sclk); 1167 1168 if(flags & symf_doubler){ 1169 /* if we have a doubler and we don't already have an 80MHz clock */ 1170 if((s->sclk > 35000) && (s->sclk < 45000)){ 1171 dprintf("symbios%ld: enabling clock doubler...\n",s->num); 1172 outb(sym_stest1, 0x08); /* enable doubler */ 1173 spin(200); /* wait 20us */ 1174 outb(sym_stest3, 0xa0); /* halt sclk, enable TolerANT*/ 1175 outb(sym_scntl3, 0x05); /* SCLK/4 */ 1176 outb(sym_stest1, 0x0c); /* engage doubler */ 1177 outb(sym_stest3, 0x80); /* reenable sclk, leave TolerANT on */ 1178 1179 spin(3000); 1180 1181 s->sclk = sym_readclock(s); 1182 dprintf("symbios%ld: clock is %ldKHz\n",s->num,s->sclk); 1183 } 1184 } 1185 if(flags & symf_quadrupler){ 1186 if((s->sclk > 35000) && (s->sclk < 45000)){ 1187 dprintf("symbios%ld: enabling clock quadrupler...\n",s->num); 1188 outb(sym_stest1, 0x08); /* enable doubler */ 1189 spin(200); /* wait 20us */ 1190 outb(sym_stest3, 0xa0); /* halt sclk, enable TolerANT*/ 1191 outb(sym_scntl3, 0x05); /* SCLK/4 */ 1192 outb(sym_stest1, 0x0c); /* engage doubler */ 1193 outb(sym_stest3, 0x80); /* reenable sclk, leave TolerANT on */ 1194 1195 spin(3000); 1196 1197 s->sclk = sym_readclock(s); 1198 dprintf("symbios%ld: clock is %ldKHz\n",s->num,s->sclk); 1199 s->sclk = 160000; 1200 } 1201 } 1202 outb(sym_stest3, 0x80); /* leave TolerANT on */ 1203 1204 scf = 0; 1205 /* set CCF / SCF according to specs */ 1206 if(s->sclk < 25010) { 1207 dprintf("symbios%ld: unsupported clock frequency\n",s->num); 1208 goto err; // s->scntl3 = 0x01; 1209 } else if(s->sclk < 37510){ 1210 dprintf("symbios%ld: unsupported clock frequency\n",s->num); 1211 goto err; // s->scntl3 = 0x02; 1212 } else if(s->sclk < 50010){ 1213 /* 40MHz - divide by 1, 2 */ 1214 scf = 0x10; 1215 s->scntl3 = 0x03; 1216 } else if(s->sclk < 75010){ 1217 dprintf("symbios%ld: unsupported clock frequency\n",s->num); 1218 goto err; // s->scntl3 = 0x04; 1219 } else if(s->sclk < 85000){ 1220 /* 80 MHz - divide by 2, 4*/ 1221 scf = 0x30; 1222 s->scntl3 = 0x05; 1223 } else { 1224 /* 160 MHz - divide by 4, 8 */ 1225 scf = 0x50; 1226 s->scntl3 = 0x07; 1227 } 1228 1229 1230 s->maxoffset = (flags & symf_short) ? 8 : 15 ; 1231 s->syncsize = 0; 1232 1233 if(scf == 0x50){ 1234 /* calculate values for 160MHz clock */ 1235 for(i=0;i<4;i++){ 1236 s->syncinfo[s->syncsize].sxfer = i << 5; 1237 s->syncinfo[s->syncsize].scntl3 = s->scntl3 | 0x90; /* /2, Ultra2 */ 1238 s->syncinfo[s->syncsize].period_ns = (625 * (i+4)) / 100; 1239 s->syncinfo[s->syncsize].period = 4 * (s->syncinfo[s->syncsize].period_ns / 4); 1240 s->syncsize++; 1241 } 1242 } 1243 1244 if(scf >= 0x30){ 1245 /* calculate values for 80MHz clock */ 1246 for(i=0;i<4;i++){ 1247 s->syncinfo[s->syncsize].sxfer = i << 5; 1248 if(scf == 0x30){ 1249 s->syncinfo[s->syncsize].scntl3 = s->scntl3 | 0x90; /* /2, Ultra */ 1250 } else { 1251 s->syncinfo[s->syncsize].scntl3 = s->scntl3 | 0xb0; /* /4, Ultra2 */ 1252 } 1253 1254 s->syncinfo[s->syncsize].period_ns = (125 * (i+4)) / 10; 1255 s->syncinfo[s->syncsize].period = 4 * (s->syncinfo[s->syncsize].period_ns / 4); 1256 s->syncsize++; 1257 } 1258 } 1259 1260 /* calculate values for 40MHz clock */ 1261 for(i=0;i<8;i++){ 1262 s->syncinfo[s->syncsize].sxfer = i << 5; 1263 s->syncinfo[s->syncsize].scntl3 = s->scntl3 | scf; 1264 s->syncinfo[s->syncsize].period_ns = 25 * (i+4); 1265 s->syncinfo[s->syncsize].period = 4 * (s->syncinfo[s->syncsize].period_ns / 4); 1266 s->syncsize++; 1267 } 1268 1269 for(i=0;i<s->syncsize;i++){ 1270 dprintf("symbios%ld: syncinfo[%d] = { %02x, %02x, %d ns, %d ns }\n", 1271 s->num, i, 1272 s->syncinfo[i].sxfer, s->syncinfo[i].scntl3, 1273 s->syncinfo[i].period_ns, s->syncinfo[i].period); 1274 } 1275 1276 for(i=0;i<16;i++){ 1277 s->targ[i].id = i; 1278 s->targ[i].adapter = s; 1279 s->targ[i].wide = 0; 1280 s->targ[i].offset = 0; 1281 s->targ[i].status = status_inactive; 1282 1283 if((i == s->host_targ_id) || (i > s->max_targ_id)){ 1284 s->targ[i].flags = tf_ignore; 1285 } else { 1286 s->targ[i].flags = tf_ask_sync; 1287 if(flags & symf_wide) s->targ[i].flags |= tf_ask_wide; 1288 // s->targ[i].flags = 0; 1289 1290 setparams(s->targ + i, 0, 0, 0); 1291 1292 sprintf(name,"sym%ld:%02d:lock",s->num,i); 1293 s->targ[i].sem_targ = create_sem(1,name); 1294 1295 sprintf(name,"sym%ld:%02d:done",s->num,i); 1296 s->targ[i].sem_done = create_sem(0,name); 1297 } 1298 } 1299 1300 if(flags & symf_wide){ 1301 s->idmask = 15; 1302 s->op_in = OP_WDATA_IN; 1303 s->op_out = OP_WDATA_OUT; 1304 } else { 1305 s->idmask = 7; 1306 s->op_in = OP_NDATA_IN; 1307 s->op_out = OP_NDATA_OUT; 1308 } 1309 1310 reloc_script(s); 1311 return s; 1312 1313 err: 1314 free(s); 1315 delete_area(aid); 1316 return NULL; 1317 } 1318 1319 1320 /* 1321 ** Multiple Card Cruft 1322 */ 1323 #define MAXCARDS 4 1324 1325 static Symbios *cardinfo[MAXCARDS] = { NULL, NULL, NULL, NULL }; 1326 1327 static long sim_init0(void) { return init_symbios(cardinfo[0],0); } 1328 static long sim_init1(void) { return init_symbios(cardinfo[1],0); } 1329 static long sim_init2(void) { return init_symbios(cardinfo[2],0); } 1330 static long sim_init3(void) { return init_symbios(cardinfo[3],0); } 1331 static long sim_action0(CCB_HEADER *ccbh) { return sim_action(cardinfo[0],ccbh); } 1332 static long sim_action1(CCB_HEADER *ccbh) { return sim_action(cardinfo[1],ccbh); } 1333 static long sim_action2(CCB_HEADER *ccbh) { return sim_action(cardinfo[2],ccbh); } 1334 static long sim_action3(CCB_HEADER *ccbh) { return sim_action(cardinfo[3],ccbh); } 1335 1336 static long (*sim_init_funcs[MAXCARDS])(void) = { 1337 sim_init0, sim_init1, sim_init2, sim_init3 1338 }; 1339 1340 static long (*sim_action_funcs[MAXCARDS])(CCB_HEADER *) = { 1341 sim_action0, sim_action1, sim_action2, sim_action3 1342 }; 1343 1344 1345 /* 1346 ** Detect the controller and register the SIM with the CAM layer. 1347 ** returns the number of controllers installed... 1348 */ 1349 static int 1350 sim_install_symbios(void) 1351 { 1352 int i, j, iobase, irq; 1353 int cardcount = 0; 1354 pci_info h; 1355 CAM_SIM_ENTRY entry; 1356 1357 dprintf("symbios: sim_install()\n"); 1358 1359 for (i = 0; ; i++) { 1360 if ((*pci->get_nth_pci_info) (i, &h) != B_NO_ERROR) { 1361 /*if(!cardcount) d_printf("symbios: no controller found\n");*/ 1362 break; 1363 } 1364 1365 // d_printf("scan: %04x %04x %02x\n", h.device_id, h.vendor_id, h.revision); 1366 1367 #define PCI_VENDOR_SYMBIOS 0x1000 1368 1369 if(h.vendor_id == PCI_VENDOR_SYMBIOS) { 1370 for(j=0;devinfo[j].id;j++){ 1371 if((devinfo[j].id == h.device_id) && (h.revision >= devinfo[j].rev)){ 1372 iobase = h.u.h0.base_registers[0]; 1373 irq = h.u.h0.interrupt_line; 1374 d_printf("symbios%d: %s controller @ 0x%08x, irq %d\n", 1375 cardcount, devinfo[j].name, iobase, irq); 1376 1377 if(cardcount == MAXCARDS){ 1378 d_printf("symbios: too many controllers!\n"); 1379 return cardcount; 1380 } 1381 1382 if((cardinfo[cardcount]=create_cardinfo(cardcount,&h,devinfo[j].flags)) != NULL){ 1383 cardinfo[cardcount]->name = devinfo[j].name; 1384 entry.sim_init = sim_init_funcs[cardcount]; 1385 entry.sim_action = sim_action_funcs[cardcount]; 1386 cardinfo[cardcount]->registered = 0; 1387 register_stats(cardinfo[cardcount]); 1388 1389 (*cam->xpt_bus_register)(&entry); 1390 cardcount++; 1391 } else { 1392 d_printf("symbios%d: cannot allocate cardinfo\n",cardcount); 1393 } 1394 break; 1395 } 1396 } 1397 } 1398 } 1399 1400 return cardcount; 1401 } 1402 1403 static status_t std_ops(int32 op, ...) 1404 { 1405 switch(op) { 1406 case B_MODULE_INIT: 1407 #if DEBUG_SAFETY 1408 set_dprintf_enabled(true); 1409 #endif 1410 load_driver_symbols("53c8xx"); 1411 1412 if (get_module(pci_name, (module_info **) &pci) != B_OK) 1413 return B_ERROR; 1414 1415 if (get_module(cam_name, (module_info **) &cam) != B_OK) { 1416 put_module(pci_name); 1417 return B_ERROR; 1418 } 1419 1420 if(sim_install_symbios()){ 1421 return B_OK; 1422 } 1423 1424 put_module(pci_name); 1425 put_module(cam_name); 1426 return B_ERROR; 1427 1428 case B_MODULE_UNINIT: 1429 put_module(pci_name); 1430 put_module(cam_name); 1431 return B_OK; 1432 1433 default: 1434 return B_ERROR; 1435 } 1436 } 1437 1438 static 1439 sim_module_info sim_symbios_module = { 1440 { "busses/scsi/53c8xx/v1", 0, &std_ops } 1441 }; 1442 1443 _EXPORT 1444 module_info *modules[] = 1445 { 1446 (module_info *) &sim_symbios_module, 1447 NULL 1448 }; 1449 1450