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