📄 devpccard.c
字号:
if (nslots == 0) return; _pcmspecial = pccard_pcmspecial; _pcmspecialclose = pccard_pcmspecialclose; for (i = 0; i != nslots; i++) { Cardbus *cb = &cbslots[i]; if ((cb->regs[SocketState] & SE_CCD) == 0) engine(cb, CardDetected); } delay(500); /* Allow time for power up */ for (i = 0; i != nslots; i++) { Cardbus *cb = &cbslots[i]; if (cb->regs[SocketState] & SE_POWER) engine(cb, CardPowered); /* Ack and enable interrupts on all events */ //cb->regs[SocketEvent] = cb->regs[SocketEvent]; //cb->regs[SocketMask] |= 0xF; //wrreg(cb, Rcscic, 0xC); }}static intpowerup(Cardbus *cb){ ulong state; ushort bcr; state = cb->regs[SocketState]; if (state & SS_PC16) { // print("#Y%ld: Probed a PC16 card, powering up card\n", cb - cbslots); cb->type = PC16; memset(&cb->linfo, 0, sizeof(Pcminfo)); /* power up and unreset, wait's are empirical (???) */ wrreg(cb, Rpc, Fautopower|Foutena|Fcardena); delay(300); wrreg(cb, Rigc, 0); delay(100); wrreg(cb, Rigc, Fnotreset); delay(500); return 1; } if (state & SS_CCD) return 0; if (state & SS_NOTCARD) { print("#Y%ld: No card inserted\n", cb - cbslots); return 0; } if (state & SS_BADVCC) { print("#Y%ld: Bad VCC request to card, powering down card!\n", cb - cbslots); cb->regs[SocketControl] = 0; return 0; } if ((state & SS_3V) == 0 && (state & SS_5V) == 0) { print("#Y%ld: Unsupported voltage, powering down card!\n", cb - cbslots); cb->regs[SocketControl] = 0; return 0; } //print("#Y%ld: card %spowered at %d volt\n", cb - cbslots, // (state & SS_POWER)? "": "not ", // (state & SS_3V)? 3: (state & SS_5V)? 5: -1); /* Power up the card * and make sure the secondary bus is not in reset. */ cb->regs[SocketControl] = (state & SS_5V)? SC_5V: SC_3V; delay(50); bcr = pcicfgr16(cb->pci, PciBCR); bcr &= ~0x40; pcicfgw16(cb->pci, PciBCR, bcr); delay(100); cb->type = PC32; return 1;}static voidpowerdown(Cardbus *cb){ ushort bcr; if (cb->type == PC16) { wrreg(cb, Rpc, 0); /* turn off card power */ wrreg(cb, Rwe, 0); /* no windows */ cb->type = -1; return; } bcr = pcicfgr16(cb->pci, PciBCR); bcr |= 0x40; pcicfgw16(cb->pci, PciBCR, bcr); cb->regs[SocketControl] = 0; cb->type = -1;}static voidconfigure(Cardbus *cb){ Pcidev *pci; ulong size, bar; int i, ioindex, memindex, r; //print("configuring slot %d (%s)\n", (int)(cb - cbslots), states[cb->state]); if (cb->state == SlotConfigured) return; engine(cb, CardConfigured); delay(50); /* Emperically established */ if (cb->type == PC16) { i82365configure(cb); return; } /* Scan the CardBus for new PCI devices */ pciscan(pcicfgr8(cb->pci, PciSBN), &cb->pci->bridge); pci = cb->pci->bridge; while (pci) { r = pcicfgr16(pci, PciPCR); r &= ~(PciPCR_IO|PciPCR_MEM); pcicfgw16(pci, PciPCR, r); /* * Treat the found device as an ordinary PCI card. * It seems that the CIS is not always present in * CardBus cards. * XXX, need to support multifunction cards */ memindex = ioindex = 0; for (i = 0; i != Nbars; i++) { if (pci->mem[i].size == 0) continue; if (pci->mem[i].bar & 1) { // Allocate I/O space if (ioindex > 1) { print("#Y%ld: WARNING: Can only configure 2 I/O slots\n", cb - cbslots); continue; } bar = ioreserve(-1, pci->mem[i].size, 0, "cardbus"); pci->mem[i].bar = bar | 1; pcicfgw32(pci, PciBAR0 + i * sizeof(ulong), pci->mem[i].bar); pcicfgw16(cb->pci, PciCBIBR0 + ioindex * 8, bar); pcicfgw16(cb->pci, PciCBILR0 + ioindex * 8, bar + pci->mem[i].size - 1); //print("ioindex[%d] %.8uX (%d)\n", // ioindex, bar, pci->mem[i].size); ioindex++; continue; } // Allocating memory space if (memindex > 1) { print("#Y%ld: WARNING: Can only configure 2 memory slots\n", cb - cbslots); continue; } bar = upamalloc(0, pci->mem[i].size, BY2PG); pci->mem[i].bar = bar | (pci->mem[i].bar & 0x80); pcicfgw32(pci, PciBAR0 + i * sizeof(ulong), pci->mem[i].bar); pcicfgw32(cb->pci, PciCBMBR0 + memindex * 8, bar); pcicfgw32(cb->pci, PciCBMLR0 + memindex * 8, bar + pci->mem[i].size - 1); if (pci->mem[i].bar & 0x80) { /* Enable prefetch */ r = pcicfgr16(cb->pci, PciBCR); r |= 1 << (8 + memindex); pcicfgw16(cb->pci, PciBCR, r); } //print("memindex[%d] %.8uX (%d)\n", // memindex, bar, pci->mem[i].size); memindex++; } if ((size = pcibarsize(pci, PciEBAR0)) > 0) { if (memindex > 1) print("#Y%ld: WARNING: Too many memory spaces, not mapping ROM space\n", cb - cbslots); else { pci->rom.bar = upamalloc(0, size, BY2PG); pci->rom.size = size; pcicfgw32(pci, PciEBAR0, pci->rom.bar); pcicfgw32(cb->pci, PciCBMBR0 + memindex * 8, pci->rom.bar); pcicfgw32(cb->pci, PciCBMLR0 + memindex * 8, pci->rom.bar + pci->rom.size - 1); } } /* Set the basic PCI registers for the device */ pci->pcr = pcicfgr16(pci, PciPCR); pci->pcr |= PciPCR_IO|PciPCR_MEM|PciPCR_Master; pci->cls = 8; pci->ltr = 64; pcicfgw16(pci, PciPCR, pci->pcr); pcicfgw8(pci, PciCLS, pci->cls); pcicfgw8(pci, PciLTR, pci->ltr); if (pcicfgr8(pci, PciINTP)) { pci->intl = pcicfgr8(cb->pci, PciINTL); pcicfgw8(pci, PciINTL, pci->intl); /* Route interrupts to INTA#/B# */ pcicfgw16(cb->pci, PciBCR, pcicfgr16(cb->pci, PciBCR) & ~(1 << 7)); } pci = pci->list; }}static voidunconfigure(Cardbus *cb){ Pcidev *pci; int i, ioindex, memindex, r; if (cb->type == PC16) { print("#Y%d: Don't know how to unconfigure a PC16 card\n", (int)(cb - cbslots)); memset(&cb->linfo, 0, sizeof(Pcminfo)); return; } pci = cb->pci->bridge; if (pci == nil) return; /* Not configured */ cb->pci->bridge = nil; memindex = ioindex = 0; while (pci) { Pcidev *_pci; for (i = 0; i != Nbars; i++) { if (pci->mem[i].size == 0) continue; if (pci->mem[i].bar & 1) { iofree(pci->mem[i].bar & ~1); pcicfgw16(cb->pci, PciCBIBR0 + ioindex * 8, (ushort)-1); pcicfgw16(cb->pci, PciCBILR0 + ioindex * 8, 0); ioindex++; continue; } upafree(pci->mem[i].bar & ~0xF, pci->mem[i].size); pcicfgw32(cb->pci, PciCBMBR0 + memindex * 8, (ulong)-1); pcicfgw32(cb->pci, PciCBMLR0 + memindex * 8, 0); r = pcicfgr16(cb->pci, PciBCR); r &= ~(1 << (8 + memindex)); pcicfgw16(cb->pci, PciBCR, r); memindex++; } if (pci->rom.bar && memindex < 2) { upafree(pci->rom.bar & ~0xF, pci->rom.size); pcicfgw32(cb->pci, PciCBMBR0 + memindex * 8, (ulong)-1); pcicfgw32(cb->pci, PciCBMLR0 + memindex * 8, 0); memindex++; } _pci = pci->list; free(_pci); pci = _pci; }}static voidi82365configure(Cardbus *cb){ int this; Cisdat cis; PCMmap *m; uchar type, link; /* * Read all tuples in attribute space. */ m = isamap(cb, 0, 0, 1); if(m == 0) return; cis.cisbase = KADDR(m->isa); cis.cispos = 0; cis.cisskip = 2; cis.cislen = m->len; /* loop through all the tuples */ for(;;){ this = cis.cispos; if(readc(&cis, &type) != 1) break; if(type == 0xFF) break; if(readc(&cis, &link) != 1) break; switch(type){ default: break; case 0x15: tvers1(cb, &cis, type); break; case 0x1A: tcfig(cb, &cis, type); break; case 0x1B: tentry(cb, &cis, type); break; } if(link == 0xFF) break; cis.cispos = this + (2+link); } isaunmap(m);}/* * look for a card whose version contains 'idstr' */static intpccard_pcmspecial(char *idstr, ISAConf *isa){ int i, irq; PCMconftab *ct, *et; Pcminfo *pi; Cardbus *cb; uchar x, we, *p; cb = nil; for (i = 0; i != nslots; i++) { cb = &cbslots[i]; lock(cb); if (cb->state == SlotConfigured && cb->type == PC16 && !cb->special && strstr(cb->linfo.verstr, idstr)) break; unlock(cb); } if (i == nslots) { // print("#Y: %s not found\n", idstr); return -1; } pi = &cb->linfo; /* * configure the PCMslot for IO. We assume very heavily that we can read * configuration info from the CIS. If not, we won't set up correctly. */ irq = isa->irq; if(irq == 2) irq = 9; et = &pi->ctab[pi->nctab]; ct = nil; for(i = 0; i < isa->nopt; i++){ int index; char *cp; if(strncmp(isa->opt[i], "index=", 6)) continue; index = strtol(&isa->opt[i][6], &cp, 0); if(cp == &isa->opt[i][6] || index >= pi->nctab) { unlock(cb); print("#Y%d: Cannot find index %d in conf table\n", (int)(cb - cbslots), index); return -1; } ct = &pi->ctab[index]; } if(ct == nil){ PCMconftab *t; /* assume default is right */ if(pi->defctab) ct = pi->defctab; else ct = pi->ctab; /* try for best match */ if(ct->nio == 0 || ct->io[0].start != isa->port || ((1<<irq) & ct->irqs) == 0){ for(t = pi->ctab; t < et; t++) if(t->nio && t->io[0].start == isa->port && ((1<<irq) & t->irqs)){ ct = t; break; } } if(ct->nio == 0 || ((1<<irq) & ct->irqs) == 0){ for(t = pi->ctab; t < et; t++) if(t->nio && ((1<<irq) & t->irqs)){ ct = t; break; } } if(ct->nio == 0){ for(t = pi->ctab; t < et; t++) if(t->nio){ ct = t; break; } } } if(ct == et || ct->nio == 0) { unlock(cb); print("#Y%d: No configuration?\n", (int)(cb - cbslots)); return -1; } if(isa->port == 0 && ct->io[0].start == 0) { unlock(cb); print("#Y%d: No part or start address\n", (int)(cb - cbslots)); return -1; } cb->special = 1; /* taken */ /* route interrupts */ isa->irq = irq; wrreg(cb, Rigc, irq | Fnotreset | Fiocard); /* set power and enable device */ x = vcode(ct->vpp1); wrreg(cb, Rpc, x|Fautopower|Foutena|Fcardena); /* 16-bit data path */ if(ct->bit16) x = Ftiming|Fiocs16|Fwidth16; else x = Ftiming; if(ct->nio == 2 && ct->io[1].start) x |= x<<4; wrreg(cb, Rio, x); /* * enable io port map 0 * the 'top' register value includes the last valid address */ if(isa->port == 0) isa->port = ct->io[0].start; we = rdreg(cb, Rwe); wrreg(cb, Riobtm0lo, isa->port); wrreg(cb, Riobtm0hi, isa->port>>8); i = isa->port+ct->io[0].len-1; wrreg(cb, Riotop0lo, i); wrreg(cb, Riotop0hi, i>>8); we |= 1<<6; if(ct->nio == 2 && ct->io[1].start){ wrreg(cb, Riobtm1lo, ct->io[1].start); wrreg(cb, Riobtm1hi, ct->io[1].start>>8); i = ct->io[1].start+ct->io[1].len-1; wrreg(cb, Riotop1lo, i); wrreg(cb, Riotop1hi, i>>8); we |= 1<<7; } wrreg(cb, Rwe, we); /* only touch Rconfig if it is present */ if(pi->conf_present & (1<<Rconfig)){ PCMmap *m; /* Reset adapter */ m = isamap(cb, pi->conf_addr + Rconfig, 1, 1); p = KADDR(m->isa + pi->conf_addr + Rconfig - m->ca); /* set configuration and interrupt type */ x = ct->index; if((ct->irqtype & 0x20)/* && ((ct->irqtype & 0x40)==0 || isa->irq>7)*/) x |= Clevel; *p = x; delay(5); isaunmap(m); } pi->port = isa->port; pi->irq = isa->irq; unlock(cb); print("#Y%d: %s irq %ld, port %lX\n", (int)(cb - cbslots), pi->verstr, isa->irq, isa->port); return (int)(cb - cbslots);}static voidpccard_pcmspecialclose(int slotno){ Cardbus *cb = &cbslots[slotno]; wrreg(cb, Rwe, 0); /* no windows */ cb->special = 0;}static intxcistuple(int slotno, int tuple, int subtuple, void *v, int nv, int attr){ PCMmap *m; Cisdat cis; int i, l; uchar *p; uchar type, link, n, c; int this, subtype;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -