1 /* 2 cardbus and pcmcia (grmph) support. 3 */ 4 #include "u.h" 5 #include "../port/lib.h" 6 #include "mem.h" 7 #include "dat.h" 8 #include "fns.h" 9 #include "../port/error.h" 10 #include "io.h" 11 12 #define DEBUG 0 13 14 #pragma varargck type "T" int 15 16 #define MAP(x,o) (Rmap + (x)*0x8 + o) 17 18 enum { 19 TI_vid = 0x104c, 20 TI_1131_did = 0xAC15, 21 TI_1250_did = 0xAC16, 22 TI_1450_did = 0xAC1B, 23 TI_1251A_did = 0xAC1D, 24 TI_1420_did = 0xAC51, 25 26 Ricoh_vid = 0x1180, 27 Ricoh_475_did = 0x0475, 28 Ricoh_476_did = 0x0476, 29 Ricoh_478_did = 0x0478, 30 31 O2_vid = 0x1217, 32 O2_OZ711M3_did = 0x7134, 33 34 Nslots = 4, /* Maximum number of CardBus slots to use */ 35 36 K = 1024, 37 M = K * K, 38 39 LegacyAddr = 0x3e0, 40 NUMEVENTS = 10, 41 42 TI1131xSC = 0x80, /* system control */ 43 TI122X_SC_INTRTIE = 1 << 29, 44 TI12xxIM = 0x8c, /* */ 45 TI1131xCC = 0x91, /* card control */ 46 TI113X_CC_RIENB = 1 << 7, 47 TI113X_CC_ZVENABLE = 1 << 6, 48 TI113X_CC_PCI_IRQ_ENA = 1 << 5, 49 TI113X_CC_PCI_IREQ = 1 << 4, 50 TI113X_CC_PCI_CSC = 1 << 3, 51 TI113X_CC_SPKROUTEN = 1 << 1, 52 TI113X_CC_IFG = 1 << 0, 53 TI1131xDC = 0x92, /* device control */ 54 }; 55 56 typedef struct Variant Variant; 57 struct Variant { 58 ushort vid; 59 ushort did; 60 char *name; 61 }; 62 63 static Variant variant[] = { 64 { Ricoh_vid, Ricoh_475_did, "Ricoh 475 PCI/Cardbus bridge", }, 65 { Ricoh_vid, Ricoh_476_did, "Ricoh 476 PCI/Cardbus bridge", }, 66 { Ricoh_vid, Ricoh_478_did, "Ricoh 478 PCI/Cardbus bridge", }, 67 { TI_vid, TI_1131_did, "TI PCI-1131 Cardbus Controller", }, 68 { TI_vid, TI_1250_did, "TI PCI-1250 Cardbus Controller", }, 69 { TI_vid, TI_1450_did, "TI PCI-1450 Cardbus Controller", }, 70 { TI_vid, TI_1251A_did, "TI PCI-1251A Cardbus Controller", }, 71 { TI_vid, TI_1420_did, "TI PCI-1420 Cardbus Controller", }, 72 { O2_vid, O2_OZ711M3_did, "O2Micro OZ711M3 MemoryCardBus", }, 73 }; 74 75 /* Cardbus registers */ 76 enum { 77 SocketEvent = 0, 78 SE_CCD = 3 << 1, 79 SE_POWER = 1 << 3, 80 SocketMask = 1, 81 SocketState = 2, 82 SS_CCD = 3 << 1, 83 SS_POWER = 1 << 3, 84 SS_PC16 = 1 << 4, 85 SS_CBC = 1 << 5, 86 SS_NOTCARD = 1 << 7, 87 SS_BADVCC = 1 << 9, 88 SS_5V = 1 << 10, 89 SS_3V = 1 << 11, 90 SocketForce = 3, 91 SocketControl = 4, 92 SC_5V = 0x22, 93 SC_3V = 0x33, 94 }; 95 96 enum { 97 PciPCR_IO = 1 << 0, 98 PciPCR_MEM = 1 << 1, 99 PciPCR_Master = 1 << 2, 100 101 PciPMC = 0xa4, 102 103 Nbars = 6, 104 Ncmd = 10, 105 CBIRQ = 9, 106 107 PC16, 108 PC32, 109 }; 110 111 enum { 112 Ti82365, 113 Tpd6710, 114 Tpd6720, 115 Tvg46x, 116 }; 117 118 /* 119 * Intel 82365SL PCIC controller for the PCMCIA or 120 * Cirrus Logic PD6710/PD6720 which is mostly register compatible 121 */ 122 enum 123 { 124 /* 125 * registers indices 126 */ 127 Rid= 0x0, /* identification and revision */ 128 Ris= 0x1, /* interface status */ 129 Rpc= 0x2, /* power control */ 130 Foutena= (1<<7), /* output enable */ 131 Fautopower= (1<<5), /* automatic power switching */ 132 Fcardena= (1<<4), /* PC card enable */ 133 Rigc= 0x3, /* interrupt and general control */ 134 Fiocard= (1<<5), /* I/O card (vs memory) */ 135 Fnotreset= (1<<6), /* reset if not set */ 136 FSMIena= (1<<4), /* enable change interrupt on SMI */ 137 Rcsc= 0x4, /* card status change */ 138 Rcscic= 0x5, /* card status change interrupt config */ 139 Fchangeena= (1<<3), /* card changed */ 140 Fbwarnena= (1<<1), /* card battery warning */ 141 Fbdeadena= (1<<0), /* card battery dead */ 142 Rwe= 0x6, /* address window enable */ 143 Fmem16= (1<<5), /* use A23-A12 to decode address */ 144 Rio= 0x7, /* I/O control */ 145 Fwidth16= (1<<0), /* 16 bit data width */ 146 Fiocs16= (1<<1), /* IOCS16 determines data width */ 147 Fzerows= (1<<2), /* zero wait state */ 148 Ftiming= (1<<3), /* timing register to use */ 149 Riobtm0lo= 0x8, /* I/O address 0 start low byte */ 150 Riobtm0hi= 0x9, /* I/O address 0 start high byte */ 151 Riotop0lo= 0xa, /* I/O address 0 stop low byte */ 152 Riotop0hi= 0xb, /* I/O address 0 stop high byte */ 153 Riobtm1lo= 0xc, /* I/O address 1 start low byte */ 154 Riobtm1hi= 0xd, /* I/O address 1 start high byte */ 155 Riotop1lo= 0xe, /* I/O address 1 stop low byte */ 156 Riotop1hi= 0xf, /* I/O address 1 stop high byte */ 157 Rmap= 0x10, /* map 0 */ 158 159 /* 160 * CL-PD67xx extension registers 161 */ 162 Rmisc1= 0x16, /* misc control 1 */ 163 F5Vdetect= (1<<0), 164 Fvcc3V= (1<<1), 165 Fpmint= (1<<2), 166 Fpsirq= (1<<3), 167 Fspeaker= (1<<4), 168 Finpack= (1<<7), 169 Rfifo= 0x17, /* fifo control */ 170 Fflush= (1<<7), /* flush fifo */ 171 Rmisc2= 0x1E, /* misc control 2 */ 172 Flowpow= (1<<1), /* low power mode */ 173 Rchipinfo= 0x1F, /* chip information */ 174 Ratactl= 0x26, /* ATA control */ 175 176 /* 177 * offsets into the system memory address maps 178 */ 179 Mbtmlo= 0x0, /* System mem addr mapping start low byte */ 180 Mbtmhi= 0x1, /* System mem addr mapping start high byte */ 181 F16bit= (1<<7), /* 16-bit wide data path */ 182 Mtoplo= 0x2, /* System mem addr mapping stop low byte */ 183 Mtophi= 0x3, /* System mem addr mapping stop high byte */ 184 Ftimer1= (1<<6), /* timer set 1 */ 185 Mofflo= 0x4, /* Card memory offset address low byte */ 186 Moffhi= 0x5, /* Card memory offset address high byte */ 187 Fregactive= (1<<6), /* attribute memory */ 188 189 /* 190 * configuration registers - they start at an offset in attribute 191 * memory found in the CIS. 192 */ 193 Rconfig= 0, 194 Creset= (1<<7), /* reset device */ 195 Clevel= (1<<6), /* level sensitive interrupt line */ 196 }; 197 198 /* 199 * read and crack the card information structure enough to set 200 * important parameters like power 201 */ 202 /* cis memory walking */ 203 typedef struct Cisdat Cisdat; 204 struct Cisdat { 205 uchar *cisbase; 206 int cispos; 207 int cisskip; 208 int cislen; 209 }; 210 211 typedef struct Pcminfo Pcminfo; 212 struct Pcminfo { 213 char verstr[512]; /* Version string */ 214 PCMmap mmap[4]; /* maps, last is always for the kernel */ 215 ulong conf_addr; /* Config address */ 216 uchar conf_present; /* Config register present */ 217 int nctab; /* In use configuration tables */ 218 PCMconftab ctab[8]; /* Configuration tables */ 219 PCMconftab *defctab; /* Default conftab */ 220 221 int port; /* Actual port usage */ 222 int irq; /* Actual IRQ usage */ 223 }; 224 225 typedef struct Cardbus Cardbus; 226 struct Cardbus { 227 Lock; 228 Variant *variant; /* Which CardBus chipset */ 229 Pcidev *pci; /* The bridge itself */ 230 ulong *regs; /* Cardbus registers */ 231 int ltype; /* Legacy type */ 232 int lindex; /* Legacy port index address */ 233 int ldata; /* Legacy port data address */ 234 int lbase; /* Base register for this socket */ 235 236 int state; /* Current state of card */ 237 int type; /* Type of card */ 238 Pcminfo linfo; /* PCMCIA slot info */ 239 240 int special; /* card is allocated to a driver */ 241 242 int refs; /* Number of refs to slot */ 243 Lock refslock; /* inc/dev ref lock */ 244 }; 245 246 static int managerstarted; 247 248 enum { 249 Mshift= 12, 250 Mgran= (1<<Mshift), /* granularity of maps */ 251 Mmask= ~(Mgran-1), /* mask for address bits important to the chip */ 252 }; 253 254 static Cardbus cbslots[Nslots]; 255 static int nslots; 256 257 static ulong exponent[8] = { 258 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 259 }; 260 261 static ulong vmant[16] = { 262 10, 12, 13, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 70, 80, 90, 263 }; 264 265 static ulong mantissa[16] = { 266 0, 10, 12, 13, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 70, 80, 267 }; 268 269 static char Enocard[] = "No card in slot"; 270 271 enum 272 { 273 CMdown, 274 CMpower, 275 }; 276 277 static Cmdtab pccardctlmsg[] = 278 { 279 CMdown, "down", 2, 280 CMpower, "power", 1, 281 }; 282 283 static int powerup(Cardbus *); 284 static void configure(Cardbus *); 285 static void powerdown(Cardbus *cb); 286 static void unconfigure(Cardbus *cb); 287 288 static void i82365probe(Cardbus *cb, int lindex, int ldata); 289 static void i82365configure(Cardbus *cb); 290 static PCMmap *isamap(Cardbus *cb, ulong offset, int len, int attr); 291 static void isaunmap(PCMmap* m); 292 static uchar rdreg(Cardbus *cb, int index); 293 static void wrreg(Cardbus *cb, int index, uchar val); 294 static int readc(Cisdat *cis, uchar *x); 295 static void tvers1(Cardbus *cb, Cisdat *cis, int ); 296 static void tcfig(Cardbus *cb, Cisdat *cis, int ); 297 static void tentry(Cardbus *cb, Cisdat *cis, int ); 298 static int vcode(int volt); 299 static int pccard_pcmspecial(char *idstr, ISAConf *isa); 300 static void pccard_pcmspecialclose(int slotno); 301 302 enum { 303 CardDetected, 304 CardPowered, 305 CardEjected, 306 CardConfigured, 307 }; 308 309 static char *messages[] = { 310 [CardDetected] "CardDetected", 311 [CardPowered] "CardPowered", 312 [CardEjected] "CardEjected", 313 [CardConfigured] "CardConfigured", 314 }; 315 316 enum { 317 SlotEmpty, 318 SlotFull, 319 SlotPowered, 320 SlotConfigured, 321 }; 322 323 static char *states[] = { 324 [SlotEmpty] "SlotEmpty", 325 [SlotFull] "SlotFull", 326 [SlotPowered] "SlotPowered", 327 [SlotConfigured] "SlotConfigured", 328 }; 329 330 static void 331 engine(Cardbus *cb, int message) 332 { 333 if(DEBUG) 334 print("engine(%ld): %s(%s)\n", cb - cbslots, 335 states[cb->state], messages[message]); 336 switch (cb->state) { 337 case SlotEmpty: 338 339 switch (message) { 340 case CardDetected: 341 cb->state = SlotFull; 342 powerup(cb); 343 break; 344 case CardEjected: 345 break; 346 default: 347 if(DEBUG) 348 print("#Y%ld: Invalid message %s in SlotEmpty state\n", 349 cb - cbslots, messages[message]); 350 break; 351 } 352 break; 353 354 case SlotFull: 355 356 switch (message) { 357 case CardPowered: 358 cb->state = SlotPowered; 359 configure(cb); 360 break; 361 case CardEjected: 362 cb->state = SlotEmpty; 363 powerdown(cb); 364 break; 365 default: 366 if(DEBUG) 367 print("#Y%ld: Invalid message %s in SlotFull state\n", 368 cb - cbslots, messages[message]); 369 break; 370 } 371 break; 372 373 case SlotPowered: 374 375 switch (message) { 376 case CardConfigured: 377 cb->state = SlotConfigured; 378 break; 379 case CardEjected: 380 cb->state = SlotEmpty; 381 unconfigure(cb); 382 powerdown(cb); 383 break; 384 default: 385 print("#Y%ld: Invalid message %s in SlotPowered state\n", 386 cb - cbslots, messages[message]); 387 break; 388 } 389 break; 390 391 case SlotConfigured: 392 393 switch (message) { 394 case CardEjected: 395 cb->state = SlotEmpty; 396 unconfigure(cb); 397 powerdown(cb); 398 break; 399 default: 400 if(DEBUG) 401 print("#Y%ld: Invalid message %s in SlotConfigured state\n", 402 cb - cbslots, messages[message]); 403 break; 404 } 405 break; 406 } 407 } 408 409 static void 410 qengine(Cardbus *cb, int message) 411 { 412 lock(cb); 413 engine(cb, message); 414 unlock(cb); 415 } 416 417 typedef struct Events Events; 418 struct Events { 419 Cardbus *cb; 420 int message; 421 }; 422 423 static Lock levents; 424 static Events events[NUMEVENTS]; 425 static Rendez revents; 426 static int nevents; 427 428 static void 429 iengine(Cardbus *cb, int message) 430 { 431 if (nevents >= NUMEVENTS) { 432 print("#Y: Too many events queued, discarding request\n"); 433 return; 434 } 435 ilock(&levents); 436 events[nevents].cb = cb; 437 events[nevents].message = message; 438 nevents++; 439 iunlock(&levents); 440 wakeup(&revents); 441 } 442 443 static int 444 eventoccured(void) 445 { 446 return nevents > 0; 447 } 448 449 static void 450 processevents(void *) 451 { 452 while (1) { 453 int message; 454 Cardbus *cb; 455 456 sleep(&revents, (int (*)(void *))eventoccured, nil); 457 458 cb = nil; 459 message = 0; 460 ilock(&levents); 461 if (nevents > 0) { 462 cb = events[0].cb; 463 message = events[0].message; 464 nevents--; 465 if (nevents > 0) 466 memmove(events, &events[1], nevents * sizeof(Events)); 467 } 468 iunlock(&levents); 469 470 if (cb) 471 qengine(cb, message); 472 } 473 } 474 475 static void 476 cbinterrupt(Ureg *, void *) 477 { 478 int i; 479 480 for (i = 0; i != nslots; i++) { 481 Cardbus *cb = &cbslots[i]; 482 ulong event, state; 483 484 event = cb->regs[SocketEvent]; 485 if(!(event & (SE_POWER|SE_CCD))) 486 continue; 487 state = cb->regs[SocketState]; 488 rdreg(cb, Rcsc); /* Ack the interrupt */ 489 490 if(DEBUG) 491 print("#Y%ld: interrupt: event %.8lX, state %.8lX, (%s)\n", 492 cb - cbslots, event, state, states[cb->state]); 493 494 if (event & SE_CCD) { 495 cb->regs[SocketEvent] |= SE_CCD; /* Ack interrupt */ 496 if (state & SE_CCD) { 497 if (cb->state != SlotEmpty) { 498 print("#Y: take cardejected interrupt\n"); 499 iengine(cb, CardEjected); 500 } 501 } 502 else 503 iengine(cb, CardDetected); 504 } 505 506 if (event & SE_POWER) { 507 cb->regs[SocketEvent] |= SE_POWER; /* Ack interrupt */ 508 iengine(cb, CardPowered); 509 } 510 } 511 } 512 513 void 514 devpccardlink(void) 515 { 516 static int initialized; 517 Pcidev *pci; 518 int i; 519 uchar intl; 520 char *p; 521 void *baddrva; 522 523 if (initialized) 524 return; 525 initialized = 1; 526 527 if((p=getconf("pccard0")) && strncmp(p, "disabled", 8)==0) 528 return; 529 530 if(_pcmspecial) 531 return; 532 533 /* Allocate legacy space */ 534 if (ioalloc(LegacyAddr, 2, 0, "i82365.0") < 0) 535 print("#Y: WARNING: Cannot allocate legacy ports\n"); 536 537 /* Find all CardBus controllers */ 538 pci = nil; 539 intl = 0xff; 540 while ((pci = pcimatch(pci, 0, 0)) != nil) { 541 ulong baddr; 542 Cardbus *cb; 543 int slot; 544 uchar pin; 545 546 if(pci->ccrb != 6 || pci->ccru != 7) 547 continue; 548 for (i = 0; i != nelem(variant); i++) 549 if (pci->vid == variant[i].vid && pci->did == variant[i].did) 550 break; 551 if (i == nelem(variant)) 552 continue; 553 554 /* initialize this slot */ 555 slot = nslots++; 556 cb = &cbslots[slot]; 557 558 cb->pci = pci; 559 cb->variant = &variant[i]; 560 561 if (pci->vid != TI_vid) { 562 /* 563 * Gross hack, needs a fix. Inherit the mappings from 564 * 9load for the TIs (pb) 565 */ 566 pcicfgw32(pci, PciCBMBR0, 0xffffffff); 567 pcicfgw32(pci, PciCBMLR0, 0); 568 pcicfgw32(pci, PciCBMBR1, 0xffffffff); 569 pcicfgw32(pci, PciCBMLR1, 0); 570 pcicfgw32(pci, PciCBIBR0, 0xffffffff); 571 pcicfgw32(pci, PciCBILR0, 0); 572 pcicfgw32(pci, PciCBIBR1, 0xffffffff); 573 pcicfgw32(pci, PciCBILR1, 0); 574 } 575 576 /* Set up PCI bus numbers if needed. */ 577 if (pcicfgr8(pci, PciSBN) == 0) { 578 static int busbase = 0x20; 579 580 pcicfgw8(pci, PciSBN, busbase); 581 pcicfgw8(pci, PciUBN, busbase + 2); 582 busbase += 3; 583 } 584 585 /* Patch up intl if needed. */ 586 if ((pin = pcicfgr8(pci, PciINTP)) != 0 && 587 (pci->intl == 0xff || pci->intl == 0)) { 588 pci->intl = pciipin(nil, pin); 589 pcicfgw8(pci, PciINTL, pci->intl); 590 591 if (pci->intl == 0xff || pci->intl == 0) 592 print("#Y%ld: No interrupt?\n", cb - cbslots); 593 } 594 595 /* Don't you love standards! */ 596 if (pci->vid == TI_vid) { 597 if (pci->did <= TI_1131_did) { 598 uchar cc; 599 600 cc = pcicfgr8(pci, TI1131xCC); 601 cc &= ~(TI113X_CC_PCI_IRQ_ENA | 602 TI113X_CC_PCI_IREQ | 603 TI113X_CC_PCI_CSC | 604 TI113X_CC_ZVENABLE); 605 cc |= TI113X_CC_PCI_IRQ_ENA | 606 TI113X_CC_PCI_IREQ | 607 TI113X_CC_SPKROUTEN; 608 pcicfgw8(pci, TI1131xCC, cc); 609 610 /* PCI interrupts only */ 611 pcicfgw8(pci, TI1131xDC, 612 pcicfgr8(pci, TI1131xDC) & ~6); 613 614 /* CSC ints to PCI bus. */ 615 wrreg(cb, Rigc, rdreg(cb, Rigc) | 0x10); 616 } 617 else if (pci->did == TI_1250_did) { 618 print("No support yet for the TI_1250_did, prod pb\n"); 619 } 620 else if (pci->did == TI_1420_did) { 621 /* Disable Vcc protection */ 622 pcicfgw32(cb->pci, 0x80, 623 pcicfgr32(cb->pci, 0x80) | (1 << 21)); 624 } 625 626 pcicfgw16(cb->pci, PciPMC, pcicfgr16(cb->pci, PciPMC) & ~3); 627 } 628 if (pci->vid == O2_vid) { 629 if(DEBUG) 630 print("writing O2 config\n"); 631 pcicfgw8(cb->pci, 0x94, 0xCA); 632 pcicfgw8(cb->pci, 0xD4, 0xCA); 633 } 634 635 if (intl != 0xff && intl != pci->intl) 636 intrenable(pci->intl, cbinterrupt, cb, pci->tbdf, "cardbus"); 637 intl = pci->intl; 638 639 if ((baddr = pcicfgr32(cb->pci, PciBAR0)) == 0) { 640 int size = (pci->did == Ricoh_478_did)? 0x10000: 0x1000; 641 642 baddr = upaalloc(size, size); 643 baddrva = vmap(baddr, size); 644 pcicfgw32(cb->pci, PciBAR0, baddr); 645 cb->regs = (ulong *)baddrva; 646 } 647 else 648 cb->regs = (ulong *)vmap(baddr, 4096); 649 cb->state = SlotEmpty; 650 651 /* Don't really know what to do with this... */ 652 i82365probe(cb, LegacyAddr, LegacyAddr + 1); 653 654 print("#Y%ld: %s, %.8ulX intl %d\n", cb - cbslots, 655 variant[i].name, baddr, pci->intl); 656 } 657 658 if (nslots == 0){ 659 iofree(LegacyAddr); 660 return; 661 } 662 663 _pcmspecial = pccard_pcmspecial; 664 _pcmspecialclose = pccard_pcmspecialclose; 665 666 for (i = 0; i != nslots; i++) { 667 Cardbus *cb = &cbslots[i]; 668 669 if ((cb->regs[SocketState] & SE_CCD) == 0) 670 engine(cb, CardDetected); 671 } 672 673 delay(500); /* Allow time for power up */ 674 675 for (i = 0; i != nslots; i++) { 676 Cardbus *cb = &cbslots[i]; 677 678 if (cb->regs[SocketState] & SE_POWER) 679 engine(cb, CardPowered); 680 681 /* Ack and enable interrupts on all events */ 682 // cb->regs[SocketEvent] = cb->regs[SocketEvent]; 683 cb->regs[SocketMask] |= 0xF; 684 wrreg(cb, Rcscic, 0xC); 685 } 686 } 687 688 static int 689 powerup(Cardbus *cb) 690 { 691 ulong state; 692 ushort bcr; 693 694 state = cb->regs[SocketState]; 695 if (state & SS_PC16) { 696 if(DEBUG) 697 print("#Y%ld: Probed a PC16 card, powering up card\n", 698 cb - cbslots); 699 cb->type = PC16; 700 memset(&cb->linfo, 0, sizeof(Pcminfo)); 701 702 /* power up and unreset, wait's are empirical (???) */ 703 wrreg(cb, Rpc, Fautopower|Foutena|Fcardena); 704 delay(300); 705 wrreg(cb, Rigc, 0); 706 delay(100); 707 wrreg(cb, Rigc, Fnotreset); 708 delay(500); 709 710 // return 1; 711 } 712 713 if (state & SS_CCD) 714 return 0; 715 716 if (state & SS_NOTCARD) { 717 print("#Y%ld: No card inserted\n", cb - cbslots); 718 return 0; 719 } 720 721 if ((state & SS_3V) == 0 && (state & SS_5V) == 0) { 722 print("#Y%ld: Unsupported voltage, powering down card!\n", 723 cb - cbslots); 724 cb->regs[SocketControl] = 0; 725 return 0; 726 } 727 728 if(DEBUG) 729 print("#Y%ld: card %spowered at %d volt\n", cb - cbslots, 730 (state & SS_POWER)? "": "not ", 731 (state & SS_3V)? 3: (state & SS_5V)? 5: -1); 732 733 /* Power up the card 734 * and make sure the secondary bus is not in reset. 735 */ 736 cb->regs[SocketControl] = (state & SS_5V)? SC_5V: SC_3V; 737 delay(50); 738 bcr = pcicfgr16(cb->pci, PciBCR); 739 bcr &= ~0x40; 740 pcicfgw16(cb->pci, PciBCR, bcr); 741 delay(100); 742 743 if (state & SS_PC16) 744 cb->type = PC16; 745 else 746 cb->type = PC32; 747 748 return 1; 749 } 750 751 static void 752 powerdown(Cardbus *cb) 753 { 754 ushort bcr; 755 756 if (cb->type == PC16) { 757 758 wrreg(cb, Rpc, 0); /* turn off card power */ 759 wrreg(cb, Rwe, 0); /* no windows */ 760 761 cb->type = -1; 762 return; 763 } 764 765 bcr = pcicfgr16(cb->pci, PciBCR); 766 bcr |= 0x40; 767 pcicfgw16(cb->pci, PciBCR, bcr); 768 cb->regs[SocketControl] = 0; 769 cb->type = -1; 770 } 771 772 static void 773 configure(Cardbus *cb) 774 { 775 int i, r; 776 ulong size, bar; 777 Pcidev *pci; 778 ulong membase, iobase, memlen, iolen, rombase, romlen; 779 780 if(DEBUG) 781 print("configuring slot %ld (%s)\n", cb - cbslots, states[cb->state]); 782 if (cb->state == SlotConfigured) 783 return; 784 engine(cb, CardConfigured); 785 786 delay(50); /* Emperically established */ 787 788 if (cb->type == PC16) { 789 i82365configure(cb); 790 return; 791 } 792 793 /* Scan the CardBus for new PCI devices */ 794 pciscan(pcicfgr8(cb->pci, PciSBN), &cb->pci->bridge); 795 796 /* 797 * size the devices on the bus, reserve a minimum for devices arriving later, 798 * allow for ROM space, allocate space, and set the cardbus mapping registers 799 */ 800 pcibussize(cb->pci->bridge, &memlen, &iolen); /* TO DO: need initial alignments */ 801 802 romlen = 0; 803 for(pci = cb->pci->bridge; pci != nil; pci = pci->list){ 804 size = pcibarsize(pci, PciEBAR0); 805 if(size > 0){ 806 pci->rom.bar = -1; 807 pci->rom.size = size; 808 romlen += size; 809 } 810 } 811 812 if(iolen < 512) 813 iolen = 512; 814 iobase = ioreserve(~0, iolen, 0, "cardbus"); 815 pcicfgw32(cb->pci, PciCBIBR0, iobase); 816 pcicfgw32(cb->pci, PciCBILR0, iobase + iolen-1); 817 pcicfgw32(cb->pci, PciCBIBR1, 0); 818 pcicfgw32(cb->pci, PciCBILR1, 0); 819 820 rombase = memlen; 821 memlen += romlen; 822 if(memlen < 1*1024*1024) 823 memlen = 1*1024*1024; 824 membase = upaalloc(memlen, 4*1024*1024); /* TO DO: better alignment */ 825 pcicfgw32(cb->pci, PciCBMBR0, membase); 826 pcicfgw32(cb->pci, PciCBMLR0, membase + memlen-1); 827 pcicfgw32(cb->pci, PciCBMBR1, 0); 828 pcicfgw32(cb->pci, PciCBMLR1, 0); 829 830 // pcibussize(cb->pci->bridge, &membase, &iobase); /* now assign them */ 831 rombase += membase; 832 833 for(pci = cb->pci->bridge; pci != nil; pci = pci->list){ 834 r = pcicfgr16(pci, PciPCR); 835 r &= ~(PciPCR_IO|PciPCR_MEM); 836 pcicfgw16(pci, PciPCR, r); 837 838 /* 839 * Treat the found device as an ordinary PCI card. 840 * It seems that the CIS is not always present in 841 * CardBus cards. 842 * XXX, need to support multifunction cards 843 */ 844 for(i = 0; i < Nbars; i++) { 845 if(pci->mem[i].size == 0) 846 continue; 847 bar = pci->mem[i].bar; 848 if(bar & 1) 849 bar += iobase; 850 else 851 bar += membase; 852 pci->mem[i].bar = bar; 853 pcicfgw32(pci, PciBAR0 + 4*i, bar); 854 if((bar & 1) == 0){ 855 print("%T mem[%d] %8.8lux %d\n", pci->tbdf, i, bar, pci->mem[i].size); 856 if(bar & 0x80){ /* TO DO: enable prefetch */ 857 ; 858 } 859 } 860 } 861 if((size = pcibarsize(pci, PciEBAR0)) > 0) { /* TO DO: can this be done by pci.c? */ 862 pci->rom.bar = rombase; 863 pci->rom.size = size; 864 rombase += size; 865 pcicfgw32(pci, PciEBAR0, pci->rom.bar); 866 } 867 868 /* Set the basic PCI registers for the device */ 869 pci->pcr = pcicfgr16(pci, PciPCR); 870 pci->pcr |= PciPCR_IO|PciPCR_MEM|PciPCR_Master; 871 pci->cls = 8; 872 pci->ltr = 64; 873 pcicfgw16(pci, PciPCR, pci->pcr); 874 pcicfgw8(pci, PciCLS, pci->cls); 875 pcicfgw8(pci, PciLTR, pci->ltr); 876 877 if (pcicfgr8(pci, PciINTP)) { 878 pci->intl = pcicfgr8(cb->pci, PciINTL); 879 pcicfgw8(pci, PciINTL, pci->intl); 880 881 /* Route interrupts to INTA#/B# */ 882 pcicfgw16(cb->pci, PciBCR, 883 pcicfgr16(cb->pci, PciBCR) & ~(1 << 7)); 884 } 885 } 886 } 887 888 static void 889 unconfigure(Cardbus *cb) 890 { 891 Pcidev *pci; 892 int i, ioindex, memindex, r; 893 894 if (cb->type == PC16) { 895 print("#Y%d: Don't know how to unconfigure a PC16 card\n", 896 (int)(cb - cbslots)); 897 898 memset(&cb->linfo, 0, sizeof(Pcminfo)); 899 return; 900 } 901 902 pci = cb->pci->bridge; 903 if (pci == nil) 904 return; /* Not configured */ 905 cb->pci->bridge = nil; 906 907 memindex = ioindex = 0; 908 while (pci) { 909 Pcidev *_pci; 910 911 for (i = 0; i != Nbars; i++) { 912 if (pci->mem[i].size == 0) 913 continue; 914 if (pci->mem[i].bar & 1) { 915 iofree(pci->mem[i].bar & ~1); 916 pcicfgw16(cb->pci, PciCBIBR0 + ioindex * 8, 917 (ushort)-1); 918 pcicfgw16(cb->pci, PciCBILR0 + ioindex * 8, 0); 919 ioindex++; 920 continue; 921 } 922 923 upafree(pci->mem[i].bar & ~0xF, pci->mem[i].size); 924 pcicfgw32(cb->pci, PciCBMBR0 + memindex * 8, (ulong)-1); 925 pcicfgw32(cb->pci, PciCBMLR0 + memindex * 8, 0); 926 r = pcicfgr16(cb->pci, PciBCR); 927 r &= ~(1 << (8 + memindex)); 928 pcicfgw16(cb->pci, PciBCR, r); 929 memindex++; 930 } 931 932 if (pci->rom.bar && memindex < 2) { 933 upafree(pci->rom.bar & ~0xF, pci->rom.size); 934 pcicfgw32(cb->pci, PciCBMBR0 + memindex * 8, (ulong)-1); 935 pcicfgw32(cb->pci, PciCBMLR0 + memindex * 8, 0); 936 memindex++; 937 } 938 939 _pci = pci->list; 940 free(_pci); 941 pci = _pci; 942 } 943 } 944 945 static void 946 i82365configure(Cardbus *cb) 947 { 948 int this; 949 Cisdat cis; 950 PCMmap *m; 951 uchar type, link; 952 953 /* 954 * Read all tuples in attribute space. 955 */ 956 m = isamap(cb, 0, 0, 1); 957 if(m == 0) 958 return; 959 960 cis.cisbase = KADDR(m->isa); 961 cis.cispos = 0; 962 cis.cisskip = 2; 963 cis.cislen = m->len; 964 965 /* loop through all the tuples */ 966 for(;;){ 967 this = cis.cispos; 968 if(readc(&cis, &type) != 1) 969 break; 970 if(type == 0xFF) 971 break; 972 if(readc(&cis, &link) != 1) 973 break; 974 975 switch(type){ 976 default: 977 break; 978 case 0x15: 979 tvers1(cb, &cis, type); 980 break; 981 case 0x1A: 982 tcfig(cb, &cis, type); 983 break; 984 case 0x1B: 985 tentry(cb, &cis, type); 986 break; 987 } 988 989 if(link == 0xFF) 990 break; 991 cis.cispos = this + (2+link); 992 } 993 isaunmap(m); 994 } 995 996 /* 997 * look for a card whose version contains 'idstr' 998 */ 999 static int 1000 pccard_pcmspecial(char *idstr, ISAConf *isa) 1001 { 1002 int i, irq; 1003 PCMconftab *ct, *et; 1004 Pcminfo *pi; 1005 Cardbus *cb; 1006 uchar x, we, *p; 1007 1008 cb = nil; 1009 for (i = 0; i != nslots; i++) { 1010 cb = &cbslots[i]; 1011 1012 lock(cb); 1013 if (cb->state == SlotConfigured && 1014 cb->type == PC16 && 1015 !cb->special && 1016 strstr(cb->linfo.verstr, idstr)) 1017 break; 1018 unlock(cb); 1019 } 1020 1021 if (i == nslots) { 1022 if(0 && DEBUG) 1023 print("#Y: %s not found\n", idstr); 1024 return -1; 1025 } 1026 1027 pi = &cb->linfo; 1028 1029 /* 1030 * configure the PCMslot for IO. We assume very heavily that we can read 1031 * configuration info from the CIS. If not, we won't set up correctly. 1032 */ 1033 irq = isa->irq; 1034 if(irq == 2) 1035 irq = 9; 1036 1037 et = &pi->ctab[pi->nctab]; 1038 ct = nil; 1039 for(i = 0; i < isa->nopt; i++){ 1040 int index; 1041 char *cp; 1042 1043 if(strncmp(isa->opt[i], "index=", 6)) 1044 continue; 1045 index = strtol(&isa->opt[i][6], &cp, 0); 1046 if(cp == &isa->opt[i][6] || index >= pi->nctab) { 1047 unlock(cb); 1048 print("#Y%d: Cannot find index %d in conf table\n", 1049 (int)(cb - cbslots), index); 1050 return -1; 1051 } 1052 ct = &pi->ctab[index]; 1053 } 1054 1055 if(ct == nil){ 1056 PCMconftab *t; 1057 1058 /* assume default is right */ 1059 if(pi->defctab) 1060 ct = pi->defctab; 1061 else 1062 ct = pi->ctab; 1063 1064 /* try for best match */ 1065 if(ct->nio == 0 1066 || ct->io[0].start != isa->port || ((1<<irq) & ct->irqs) == 0){ 1067 for(t = pi->ctab; t < et; t++) 1068 if(t->nio 1069 && t->io[0].start == isa->port 1070 && ((1<<irq) & t->irqs)){ 1071 ct = t; 1072 break; 1073 } 1074 } 1075 if(ct->nio == 0 || ((1<<irq) & ct->irqs) == 0){ 1076 for(t = pi->ctab; t < et; t++) 1077 if(t->nio && ((1<<irq) & t->irqs)){ 1078 ct = t; 1079 break; 1080 } 1081 } 1082 if(ct->nio == 0){ 1083 for(t = pi->ctab; t < et; t++) 1084 if(t->nio){ 1085 ct = t; 1086 break; 1087 } 1088 } 1089 } 1090 1091 if(ct == et || ct->nio == 0) { 1092 unlock(cb); 1093 print("#Y%d: No configuration?\n", (int)(cb - cbslots)); 1094 return -1; 1095 } 1096 if(isa->port == 0 && ct->io[0].start == 0) { 1097 unlock(cb); 1098 print("#Y%d: No part or start address\n", (int)(cb - cbslots)); 1099 return -1; 1100 } 1101 1102 cb->special = 1; /* taken */ 1103 1104 /* route interrupts */ 1105 isa->irq = irq; 1106 wrreg(cb, Rigc, irq | Fnotreset | Fiocard); 1107 1108 /* set power and enable device */ 1109 x = vcode(ct->vpp1); 1110 wrreg(cb, Rpc, x|Fautopower|Foutena|Fcardena); 1111 1112 /* 16-bit data path */ 1113 if(ct->bit16) 1114 x = Ftiming|Fiocs16|Fwidth16; 1115 else 1116 x = Ftiming; 1117 if(ct->nio == 2 && ct->io[1].start) 1118 x |= x<<4; 1119 wrreg(cb, Rio, x); 1120 1121 /* 1122 * enable io port map 0 1123 * the 'top' register value includes the last valid address 1124 */ 1125 if(isa->port == 0) 1126 isa->port = ct->io[0].start; 1127 we = rdreg(cb, Rwe); 1128 wrreg(cb, Riobtm0lo, isa->port); 1129 wrreg(cb, Riobtm0hi, isa->port>>8); 1130 i = isa->port+ct->io[0].len-1; 1131 wrreg(cb, Riotop0lo, i); 1132 wrreg(cb, Riotop0hi, i>>8); 1133 we |= 1<<6; 1134 if(ct->nio == 2 && ct->io[1].start){ 1135 wrreg(cb, Riobtm1lo, ct->io[1].start); 1136 wrreg(cb, Riobtm1hi, ct->io[1].start>>8); 1137 i = ct->io[1].start+ct->io[1].len-1; 1138 wrreg(cb, Riotop1lo, i); 1139 wrreg(cb, Riotop1hi, i>>8); 1140 we |= 1<<7; 1141 } 1142 wrreg(cb, Rwe, we); 1143 1144 /* only touch Rconfig if it is present */ 1145 if(pi->conf_present & (1<<Rconfig)){ 1146 PCMmap *m; 1147 1148 /* Reset adapter */ 1149 m = isamap(cb, pi->conf_addr + Rconfig, 1, 1); 1150 p = KADDR(m->isa + pi->conf_addr + Rconfig - m->ca); 1151 1152 /* set configuration and interrupt type */ 1153 x = ct->index; 1154 if(ct->irqtype & 0x20) 1155 x |= Clevel; 1156 *p = x; 1157 delay(5); 1158 1159 isaunmap(m); 1160 } 1161 1162 pi->port = isa->port; 1163 pi->irq = isa->irq; 1164 unlock(cb); 1165 1166 print("#Y%ld: %s irq %d, port %lX\n", cb - cbslots, pi->verstr, isa->irq, isa->port); 1167 return (int)(cb - cbslots); 1168 } 1169 1170 static void 1171 pccard_pcmspecialclose(int slotno) 1172 { 1173 Cardbus *cb = &cbslots[slotno]; 1174 1175 wrreg(cb, Rwe, 0); /* no windows */ 1176 cb->special = 0; 1177 } 1178 1179 static Chan* 1180 pccardattach(char *spec) 1181 { 1182 if (!managerstarted) { 1183 managerstarted = 1; 1184 kproc("cardbus", processevents, nil); 1185 } 1186 return devattach('Y', spec); 1187 } 1188 1189 enum 1190 { 1191 Qdir, 1192 Qctl, 1193 1194 Nents = 1, 1195 }; 1196 1197 #define SLOTNO(c) ((ulong)((c->qid.path>>8)&0xff)) 1198 #define TYPE(c) ((ulong)(c->qid.path&0xff)) 1199 #define QID(s,t) (((s)<<8)|(t)) 1200 1201 static int 1202 pccardgen(Chan *c, char*, Dirtab *, int , int i, Dir *dp) 1203 { 1204 int slotno; 1205 Qid qid; 1206 long len; 1207 int entry; 1208 1209 if(i == DEVDOTDOT){ 1210 mkqid(&qid, Qdir, 0, QTDIR); 1211 devdir(c, qid, "#Y", 0, eve, 0555, dp); 1212 return 1; 1213 } 1214 1215 len = 0; 1216 if(i >= Nents * nslots) return -1; 1217 slotno = i / Nents; 1218 entry = i % Nents; 1219 if (entry == 0) { 1220 qid.path = QID(slotno, Qctl); 1221 snprint(up->genbuf, sizeof up->genbuf, "cb%dctl", slotno); 1222 } 1223 else { 1224 /* Entries for memory regions. I'll implement them when 1225 needed. (pb) */ 1226 } 1227 qid.vers = 0; 1228 qid.type = QTFILE; 1229 devdir(c, qid, up->genbuf, len, eve, 0660, dp); 1230 return 1; 1231 } 1232 1233 static Walkqid* 1234 pccardwalk(Chan *c, Chan *nc, char **name, int nname) 1235 { 1236 return devwalk(c, nc, name, nname, 0, 0, pccardgen); 1237 } 1238 1239 static int 1240 pccardstat(Chan *c, uchar *db, int n) 1241 { 1242 return devstat(c, db, n, 0, 0, pccardgen); 1243 } 1244 1245 static void 1246 increfp(Cardbus *cb) 1247 { 1248 lock(&cb->refslock); 1249 cb->refs++; 1250 unlock(&cb->refslock); 1251 } 1252 1253 static void 1254 decrefp(Cardbus *cb) 1255 { 1256 lock(&cb->refslock); 1257 cb->refs--; 1258 unlock(&cb->refslock); 1259 } 1260 1261 static Chan* 1262 pccardopen(Chan *c, int omode) 1263 { 1264 if (c->qid.type & QTDIR){ 1265 if(omode != OREAD) 1266 error(Eperm); 1267 } else 1268 increfp(&cbslots[SLOTNO(c)]); 1269 c->mode = openmode(omode); 1270 c->flag |= COPEN; 1271 c->offset = 0; 1272 return c; 1273 } 1274 1275 static void 1276 pccardclose(Chan *c) 1277 { 1278 if(c->flag & COPEN) 1279 if((c->qid.type & QTDIR) == 0) 1280 decrefp(&cbslots[SLOTNO(c)]); 1281 } 1282 1283 static long 1284 pccardread(Chan *c, void *a, long n, vlong offset) 1285 { 1286 Cardbus *cb; 1287 char *buf, *p, *e; 1288 int i; 1289 1290 switch(TYPE(c)){ 1291 case Qdir: 1292 return devdirread(c, a, n, 0, 0, pccardgen); 1293 1294 case Qctl: 1295 buf = p = malloc(READSTR); 1296 buf[0] = 0; 1297 e = p + READSTR; 1298 1299 cb = &cbslots[SLOTNO(c)]; 1300 lock(cb); 1301 p = seprint(p, e, "slot %ld: %s; ", cb - cbslots, states[cb->state]); 1302 1303 switch (cb->type) { 1304 case -1: 1305 seprint(p, e, "\n"); 1306 break; 1307 1308 case PC32: 1309 if (cb->pci->bridge) { 1310 Pcidev *pci = cb->pci->bridge; 1311 int i; 1312 1313 while (pci) { 1314 p = seprint(p, e, "%.4uX %.4uX; irq %d\n", 1315 pci->vid, pci->did, pci->intl); 1316 for (i = 0; i != Nbars; i++) 1317 if (pci->mem[i].size) 1318 p = seprint(p, e, 1319 "\tmem[%d] %.8ulX (%.8uX)\n", 1320 i, pci->mem[i].bar, 1321 pci->mem[i].size); 1322 if (pci->rom.size) 1323 p = seprint(p, e, "\tROM %.8ulX (%.8uX)\n", 1324 pci->rom.bar, pci->rom.size); 1325 pci = pci->list; 1326 } 1327 } 1328 break; 1329 1330 case PC16: 1331 if (cb->state == SlotConfigured) { 1332 Pcminfo *pi = &cb->linfo; 1333 1334 p = seprint(p, e, "%s port %X; irq %d;\n", 1335 pi->verstr, pi->port, 1336 pi->irq); 1337 for (i = 0; i != pi->nctab; i++) { 1338 PCMconftab *ct; 1339 int j; 1340 1341 ct = &pi->ctab[i]; 1342 p = seprint(p, e, 1343 "\tconfiguration[%d] irqs %.4uX; vpp %d, %d; %s\n", 1344 i, ct->irqs, ct->vpp1, ct->vpp2, 1345 (ct == pi->defctab)? "(default);": ""); 1346 for (j = 0; j != ct->nio; j++) 1347 if (ct->io[j].len > 0) 1348 p = seprint(p, e, "\t\tio[%d] %.8ulX %uld\n", 1349 j, ct->io[j].start, ct->io[j].len); 1350 } 1351 } 1352 break; 1353 } 1354 unlock(cb); 1355 1356 n = readstr(offset, a, n, buf); 1357 free(buf); 1358 return n; 1359 } 1360 return 0; 1361 } 1362 1363 static long 1364 pccardwrite(Chan *c, void *v, long n, vlong) 1365 { 1366 Rune r; 1367 ulong n0; 1368 char *device; 1369 Cmdbuf *cbf; 1370 Cmdtab *ct; 1371 Cardbus *cb; 1372 1373 n0 = n; 1374 switch(TYPE(c)){ 1375 case Qctl: 1376 cb = &cbslots[SLOTNO(c)]; 1377 1378 cbf = parsecmd(v, n); 1379 if(waserror()){ 1380 free(cbf); 1381 nexterror(); 1382 } 1383 ct = lookupcmd(cbf, pccardctlmsg, nelem(pccardctlmsg)); 1384 switch(ct->index){ 1385 case CMdown: 1386 device = cbf->f[1]; 1387 device += chartorune(&r, device); 1388 if ((n = devno(r, 1)) >= 0 && devtab[n]->config) 1389 devtab[n]->config(0, device, nil); 1390 qengine(cb, CardEjected); 1391 break; 1392 case CMpower: 1393 if ((cb->regs[SocketState] & SS_CCD) == 0) 1394 qengine(cb, CardDetected); 1395 break; 1396 } 1397 poperror(); 1398 free(cbf); 1399 break; 1400 } 1401 return n0 - n; 1402 } 1403 1404 Dev pccarddevtab = { 1405 'Y', 1406 "cardbus", 1407 1408 devreset, 1409 devinit, 1410 devshutdown, 1411 pccardattach, 1412 pccardwalk, 1413 pccardstat, 1414 pccardopen, 1415 devcreate, 1416 pccardclose, 1417 pccardread, 1418 devbread, 1419 pccardwrite, 1420 devbwrite, 1421 devremove, 1422 devwstat, 1423 }; 1424 1425 static PCMmap * 1426 isamap(Cardbus *cb, ulong offset, int len, int attr) 1427 { 1428 uchar we, bit; 1429 PCMmap *m, *nm; 1430 Pcminfo *pi; 1431 int i; 1432 ulong e; 1433 1434 pi = &cb->linfo; 1435 1436 /* convert offset to granularity */ 1437 if(len <= 0) 1438 len = 1; 1439 e = ROUND(offset+len, Mgran); 1440 offset &= Mmask; 1441 len = e - offset; 1442 1443 /* look for a map that covers the right area */ 1444 we = rdreg(cb, Rwe); 1445 bit = 1; 1446 nm = 0; 1447 for(m = pi->mmap; m < &pi->mmap[nelem(pi->mmap)]; m++){ 1448 if((we & bit)) 1449 if(m->attr == attr) 1450 if(offset >= m->ca && e <= m->cea){ 1451 1452 m->ref++; 1453 return m; 1454 } 1455 bit <<= 1; 1456 if(nm == 0 && m->ref == 0) 1457 nm = m; 1458 } 1459 m = nm; 1460 if(m == 0) 1461 return 0; 1462 1463 /* if isa space isn't big enough, free it and get more */ 1464 if(m->len < len){ 1465 if(m->isa){ 1466 umbfree(m->isa, m->len); 1467 m->len = 0; 1468 } 1469 m->isa = PADDR(umbmalloc(0, len, Mgran)); 1470 if(m->isa == 0){ 1471 print("isamap: out of isa space\n"); 1472 return 0; 1473 } 1474 m->len = len; 1475 } 1476 1477 /* set up new map */ 1478 m->ca = offset; 1479 m->cea = m->ca + m->len; 1480 m->attr = attr; 1481 i = m - pi->mmap; 1482 bit = 1<<i; 1483 wrreg(cb, Rwe, we & ~bit); /* disable map before changing it */ 1484 wrreg(cb, MAP(i, Mbtmlo), m->isa>>Mshift); 1485 wrreg(cb, MAP(i, Mbtmhi), (m->isa>>(Mshift+8)) | F16bit); 1486 wrreg(cb, MAP(i, Mtoplo), (m->isa+m->len-1)>>Mshift); 1487 wrreg(cb, MAP(i, Mtophi), ((m->isa+m->len-1)>>(Mshift+8))); 1488 offset -= m->isa; 1489 offset &= (1<<25)-1; 1490 offset >>= Mshift; 1491 wrreg(cb, MAP(i, Mofflo), offset); 1492 wrreg(cb, MAP(i, Moffhi), (offset>>8) | (attr ? Fregactive : 0)); 1493 wrreg(cb, Rwe, we | bit); /* enable map */ 1494 m->ref = 1; 1495 1496 return m; 1497 } 1498 1499 static void 1500 isaunmap(PCMmap* m) 1501 { 1502 m->ref--; 1503 } 1504 1505 /* 1506 * reading and writing card registers 1507 */ 1508 static uchar 1509 rdreg(Cardbus *cb, int index) 1510 { 1511 outb(cb->lindex, cb->lbase + index); 1512 return inb(cb->ldata); 1513 } 1514 1515 static void 1516 wrreg(Cardbus *cb, int index, uchar val) 1517 { 1518 outb(cb->lindex, cb->lbase + index); 1519 outb(cb->ldata, val); 1520 } 1521 1522 static int 1523 readc(Cisdat *cis, uchar *x) 1524 { 1525 if(cis->cispos >= cis->cislen) 1526 return 0; 1527 *x = cis->cisbase[cis->cisskip*cis->cispos]; 1528 cis->cispos++; 1529 return 1; 1530 } 1531 1532 static ulong 1533 getlong(Cisdat *cis, int size) 1534 { 1535 uchar c; 1536 int i; 1537 ulong x; 1538 1539 x = 0; 1540 for(i = 0; i < size; i++){ 1541 if(readc(cis, &c) != 1) 1542 break; 1543 x |= c<<(i*8); 1544 } 1545 return x; 1546 } 1547 1548 static void 1549 tcfig(Cardbus *cb, Cisdat *cis, int ) 1550 { 1551 uchar size, rasize, rmsize; 1552 uchar last; 1553 Pcminfo *pi; 1554 1555 if(readc(cis, &size) != 1) 1556 return; 1557 rasize = (size&0x3) + 1; 1558 rmsize = ((size>>2)&0xf) + 1; 1559 if(readc(cis, &last) != 1) 1560 return; 1561 1562 pi = &cb->linfo; 1563 pi->conf_addr = getlong(cis, rasize); 1564 pi->conf_present = getlong(cis, rmsize); 1565 } 1566 1567 static void 1568 tvers1(Cardbus *cb, Cisdat *cis, int ) 1569 { 1570 uchar c, major, minor, last; 1571 int i; 1572 Pcminfo *pi; 1573 1574 pi = &cb->linfo; 1575 if(readc(cis, &major) != 1) 1576 return; 1577 if(readc(cis, &minor) != 1) 1578 return; 1579 last = 0; 1580 for(i = 0; i < sizeof(pi->verstr) - 1; i++){ 1581 if(readc(cis, &c) != 1) 1582 return; 1583 if(c == 0) 1584 c = ';'; 1585 if(c == '\n') 1586 c = ';'; 1587 if(c == 0xff) 1588 break; 1589 if(c == ';' && last == ';') 1590 continue; 1591 pi->verstr[i] = c; 1592 last = c; 1593 } 1594 pi->verstr[i] = 0; 1595 } 1596 1597 static ulong 1598 microvolt(Cisdat *cis) 1599 { 1600 uchar c; 1601 ulong microvolts; 1602 ulong exp; 1603 1604 if(readc(cis, &c) != 1) 1605 return 0; 1606 exp = exponent[c&0x7]; 1607 microvolts = vmant[(c>>3)&0xf]*exp; 1608 while(c & 0x80){ 1609 if(readc(cis, &c) != 1) 1610 return 0; 1611 switch(c){ 1612 case 0x7d: 1613 break; /* high impedence when sleeping */ 1614 case 0x7e: 1615 case 0x7f: 1616 microvolts = 0; /* no connection */ 1617 break; 1618 default: 1619 exp /= 10; 1620 microvolts += exp*(c&0x7f); 1621 } 1622 } 1623 return microvolts; 1624 } 1625 1626 static ulong 1627 nanoamps(Cisdat *cis) 1628 { 1629 uchar c; 1630 ulong nanoamps; 1631 1632 if(readc(cis, &c) != 1) 1633 return 0; 1634 nanoamps = exponent[c&0x7]*vmant[(c>>3)&0xf]; 1635 while(c & 0x80){ 1636 if(readc(cis, &c) != 1) 1637 return 0; 1638 if(c == 0x7d || c == 0x7e || c == 0x7f) 1639 nanoamps = 0; 1640 } 1641 return nanoamps; 1642 } 1643 1644 /* 1645 * only nominal voltage (feature 1) is important for config, 1646 * other features must read card to stay in sync. 1647 */ 1648 static ulong 1649 power(Cisdat *cis) 1650 { 1651 uchar feature; 1652 ulong mv; 1653 1654 mv = 0; 1655 if(readc(cis, &feature) != 1) 1656 return 0; 1657 if(feature & 1) 1658 mv = microvolt(cis); 1659 if(feature & 2) 1660 microvolt(cis); 1661 if(feature & 4) 1662 microvolt(cis); 1663 if(feature & 8) 1664 nanoamps(cis); 1665 if(feature & 0x10) 1666 nanoamps(cis); 1667 if(feature & 0x20) 1668 nanoamps(cis); 1669 if(feature & 0x40) 1670 nanoamps(cis); 1671 return mv/1000000; 1672 } 1673 1674 static ulong 1675 ttiming(Cisdat *cis, int scale) 1676 { 1677 uchar unscaled; 1678 ulong nanosecs; 1679 1680 if(readc(cis, &unscaled) != 1) 1681 return 0; 1682 nanosecs = (mantissa[(unscaled>>3)&0xf]*exponent[unscaled&7])/10; 1683 nanosecs = nanosecs * exponent[scale]; 1684 return nanosecs; 1685 } 1686 1687 static void 1688 timing(Cisdat *cis, PCMconftab *ct) 1689 { 1690 uchar c, i; 1691 1692 if(readc(cis, &c) != 1) 1693 return; 1694 i = c&0x3; 1695 if(i != 3) 1696 ct->maxwait = ttiming(cis, i); /* max wait */ 1697 i = (c>>2)&0x7; 1698 if(i != 7) 1699 ct->readywait = ttiming(cis, i); /* max ready/busy wait */ 1700 i = (c>>5)&0x7; 1701 if(i != 7) 1702 ct->otherwait = ttiming(cis, i); /* reserved wait */ 1703 } 1704 1705 static void 1706 iospaces(Cisdat *cis, PCMconftab *ct) 1707 { 1708 uchar c; 1709 int i, nio; 1710 1711 ct->nio = 0; 1712 if(readc(cis, &c) != 1) 1713 return; 1714 1715 ct->bit16 = ((c>>5)&3) >= 2; 1716 if(!(c & 0x80)){ 1717 ct->io[0].start = 0; 1718 ct->io[0].len = 1<<(c&0x1f); 1719 ct->nio = 1; 1720 return; 1721 } 1722 1723 if(readc(cis, &c) != 1) 1724 return; 1725 1726 /* 1727 * For each of the range descriptions read the 1728 * start address and the length (value is length-1). 1729 */ 1730 nio = (c&0xf)+1; 1731 for(i = 0; i < nio; i++){ 1732 ct->io[i].start = getlong(cis, (c>>4)&0x3); 1733 ct->io[i].len = getlong(cis, (c>>6)&0x3)+1; 1734 } 1735 ct->nio = nio; 1736 } 1737 1738 static void 1739 irq(Cisdat *cis, PCMconftab *ct) 1740 { 1741 uchar c; 1742 1743 if(readc(cis, &c) != 1) 1744 return; 1745 ct->irqtype = c & 0xe0; 1746 if(c & 0x10) 1747 ct->irqs = getlong(cis, 2); 1748 else 1749 ct->irqs = 1<<(c&0xf); 1750 ct->irqs &= 0xDEB8; /* levels available to card */ 1751 } 1752 1753 static void 1754 memspace(Cisdat *cis, int asize, int lsize, int host) 1755 { 1756 ulong haddress, address, len; 1757 1758 len = getlong(cis, lsize)*256; 1759 address = getlong(cis, asize)*256; 1760 USED(len, address); 1761 if(host){ 1762 haddress = getlong(cis, asize)*256; 1763 USED(haddress); 1764 } 1765 } 1766 1767 static void 1768 tentry(Cardbus *cb, Cisdat *cis, int ) 1769 { 1770 uchar c, i, feature; 1771 PCMconftab *ct; 1772 Pcminfo *pi; 1773 1774 pi = &cb->linfo; 1775 if(pi->nctab >= nelem(pi->ctab)) 1776 return; 1777 if(readc(cis, &c) != 1) 1778 return; 1779 ct = &pi->ctab[pi->nctab++]; 1780 1781 /* copy from last default config */ 1782 if(pi->defctab) 1783 *ct = *pi->defctab; 1784 1785 ct->index = c & 0x3f; 1786 1787 /* is this the new default? */ 1788 if(c & 0x40) 1789 pi->defctab = ct; 1790 1791 /* memory wait specified? */ 1792 if(c & 0x80){ 1793 if(readc(cis, &i) != 1) 1794 return; 1795 if(i&0x80) 1796 ct->memwait = 1; 1797 } 1798 1799 if(readc(cis, &feature) != 1) 1800 return; 1801 switch(feature&0x3){ 1802 case 1: 1803 ct->vpp1 = ct->vpp2 = power(cis); 1804 break; 1805 case 2: 1806 power(cis); 1807 ct->vpp1 = ct->vpp2 = power(cis); 1808 break; 1809 case 3: 1810 power(cis); 1811 ct->vpp1 = power(cis); 1812 ct->vpp2 = power(cis); 1813 break; 1814 default: 1815 break; 1816 } 1817 if(feature&0x4) 1818 timing(cis, ct); 1819 if(feature&0x8) 1820 iospaces(cis, ct); 1821 if(feature&0x10) 1822 irq(cis, ct); 1823 switch((feature>>5)&0x3){ 1824 case 1: 1825 memspace(cis, 0, 2, 0); 1826 break; 1827 case 2: 1828 memspace(cis, 2, 2, 0); 1829 break; 1830 case 3: 1831 if(readc(cis, &c) != 1) 1832 return; 1833 for(i = 0; i <= (c&0x7); i++) 1834 memspace(cis, (c>>5)&0x3, (c>>3)&0x3, c&0x80); 1835 break; 1836 } 1837 } 1838 1839 static void 1840 i82365probe(Cardbus *cb, int lindex, int ldata) 1841 { 1842 uchar c, id; 1843 int dev = 0; /* According to the Ricoh spec 00->3F _and_ 80->BF seem 1844 to be the same socket A (ditto for B). */ 1845 1846 outb(lindex, Rid + (dev<<7)); 1847 id = inb(ldata); 1848 if((id & 0xf0) != 0x80) 1849 return; /* not a memory & I/O card */ 1850 if((id & 0x0f) == 0x00) 1851 return; /* no revision number, not possible */ 1852 1853 cb->lindex = lindex; 1854 cb->ldata = ldata; 1855 cb->ltype = Ti82365; 1856 cb->lbase = (int)(cb - cbslots) * 0x40; 1857 1858 switch(id){ 1859 case 0x82: 1860 case 0x83: 1861 case 0x84: 1862 /* could be a cirrus */ 1863 outb(cb->lindex, Rchipinfo + (dev<<7)); 1864 outb(cb->ldata, 0); 1865 c = inb(cb->ldata); 1866 if((c & 0xc0) != 0xc0) 1867 break; 1868 c = inb(cb->ldata); 1869 if((c & 0xc0) != 0x00) 1870 break; 1871 if(c & 0x20){ 1872 cb->ltype = Tpd6720; 1873 } else { 1874 cb->ltype = Tpd6710; 1875 } 1876 1877 /* low power mode */ 1878 outb(cb->lindex, Rmisc2 + (dev<<7)); 1879 c = inb(cb->ldata); 1880 outb(cb->ldata, c & ~Flowpow); 1881 break; 1882 break; 1883 } 1884 1885 /* if it's not a Cirrus, it could be a Vadem... */ 1886 if(cb->ltype == Ti82365){ 1887 /* unlock the Vadem extended regs */ 1888 outb(cb->lindex, 0x0E + (dev<<7)); 1889 outb(cb->lindex, 0x37 + (dev<<7)); 1890 1891 /* make the id register show the Vadem id */ 1892 outb(cb->lindex, 0x3A + (dev<<7)); 1893 c = inb(cb->ldata); 1894 outb(cb->ldata, c|0xC0); 1895 outb(cb->lindex, Rid + (dev<<7)); 1896 c = inb(cb->ldata); 1897 if(c & 0x08) 1898 cb->ltype = Tvg46x; 1899 1900 /* go back to Intel compatible id */ 1901 outb(cb->lindex, 0x3A + (dev<<7)); 1902 c = inb(cb->ldata); 1903 outb(cb->ldata, c & ~0xC0); 1904 } 1905 } 1906 1907 static int 1908 vcode(int volt) 1909 { 1910 switch(volt){ 1911 case 5: 1912 return 1; 1913 case 12: 1914 return 2; 1915 default: 1916 return 0; 1917 } 1918 } 1919