123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197 |
- /* Pci/pcmcia code for wavelan.c */
- #include "u.h"
- #include "../port/lib.h"
- #include "mem.h"
- #include "dat.h"
- #include "fns.h"
- #include "io.h"
- #include "../port/error.h"
- #include "../port/netif.h"
- #include "etherif.h"
- #include "wavelan.h"
- static int
- wavelanpcmciareset(Ether *ether)
- {
- int i;
- char *p;
- Ctlr *ctlr;
- if((ctlr = malloc(sizeof(Ctlr))) == nil)
- return -1;
- ilock(ctlr);
- ctlr->ctlrno = ether->ctlrno;
- if (ether->port==0)
- ether->port=WDfltIOB;
- ctlr->iob = ether->port;
- if (ether->irq==0)
- ether->irq=WDfltIRQ;
- if (ioalloc(ether->port,WIOLen,0,"wavelan")<0){
- // print("#l%d: port 0x%lx in use\n",
- // ether->ctlrno, ether->port);
- goto abort1;
- }
- /*
- * If id= is specified, card must match. Otherwise try generic.
- */
- ctlr->slot = -1;
- for(i=0; i<ether->nopt; i++){
- if(cistrncmp(ether->opt[i], "id=", 3) == 0){
- if((ctlr->slot = pcmspecial(ðer->opt[i][3], ether)) < 0)
- goto abort;
- break;
- }
- }
- if(ctlr->slot == -1){
- for (i=0; wavenames[i]; i++)
- if((ctlr->slot = pcmspecial(wavenames[i], ether))>=0)
- break;
- if(!wavenames[i]){
- DEBUG("no wavelan found\n");
- goto abort;
- }
- }
- // DEBUG("#l%d: port=0x%lx irq=%ld\n",
- // ether->ctlrno, ether->port, ether->irq);
- if(wavelanreset(ether, ctlr) < 0){
- abort:
- iofree(ether->port);
- abort1:
- iunlock(ctlr);
- free(ctlr);
- ether->ctlr = nil;
- return -1;
- }
- for(i = 0; i < ether->nopt; i++){
- if(p = strchr(ether->opt[i], '='))
- *p = ' ';
- w_option(ctlr, ether->opt[i], strlen(ether->opt[i]));
- }
- iunlock(ctlr);
- return 0;
- }
- static struct {
- int vid;
- int did;
- } wavelanpci[] = {
- 0x1260, 0x3873, /* Intersil Prism2.5 */
- 0x1737, 0x0019, /* Linksys WPC-11 untested */
- };
- static Ctlr *ctlrhead, *ctlrtail;
- static void
- wavelanpciscan(void)
- {
- int i;
- void *mem;
- Pcidev *p;
- Ctlr *ctlr;
- p = nil;
- while(p = pcimatch(p, 0, 0)){
- for(i=0; i<nelem(wavelanpci); i++)
- if(p->vid == wavelanpci[i].vid && p->did == wavelanpci[i].did)
- break;
- if(i==nelem(wavelanpci))
- continue;
- /*
- * On the Prism, bar[0] is the memory-mapped register address (4KB),
- */
- if(p->mem[0].size != 4096){
- print("wavelanpci: %.4ux %.4ux: unlikely mmio size\n", p->vid, p->did);
- continue;
- }
- ctlr = malloc(sizeof(Ctlr));
- ctlr->pcidev = p;
- mem = vmap(p->mem[0].bar&~0xF, p->mem[0].size);
- if(mem == nil){
- print("wavelanpci: %.4ux %.4ux: vmap 0x%.8lux %d failed\n", p->vid, p->did, p->mem[0].bar&~0xF, p->mem[0].size);
- free(ctlr);
- continue;
- }
- ctlr->mmb = mem;
- if(ctlrhead != nil)
- ctlrtail->next = ctlr;
- else
- ctlrhead = ctlr;
- ctlrtail = ctlr;
- pcisetbme(p);
- }
- }
- static int
- wavelanpcireset(Ether *ether)
- {
- int i;
- char *p;
- Ctlr *ctlr;
- if(ctlrhead == nil)
- wavelanpciscan();
- /*
- * Allow plan9.ini to set vid, did?
- */
- for(ctlr=ctlrhead; ctlr!=nil; ctlr=ctlr->next)
- if(ctlr->active == 0)
- break;
- if(ctlr == nil)
- return -1;
- ctlr->active = 1;
- ilock(ctlr);
- ether->irq = ctlr->pcidev->intl;
- ether->tbdf = ctlr->pcidev->tbdf;
- /*
- * Really hard reset.
- */
- csr_outs(ctlr, WR_PciCor, 0x0080);
- delay(250);
- csr_outs(ctlr, WR_PciCor, 0x0000);
- delay(500);
- for(i=0; i<2*10; i++){
- if(!(csr_ins(ctlr, WR_Cmd)&WCmdBusy))
- break;
- delay(100);
- }
- if(i >= 2*10)
- print("wavelan pci %.4ux %.4ux: reset timeout %.4ux\n",
- ctlr->pcidev->vid, ctlr->pcidev->did, csr_ins(ctlr, WR_Cmd));
- if(wavelanreset(ether, ctlr) < 0){
- iunlock(ctlr);
- ether->ctlr = nil;
- return -1;
- }
- for(i = 0; i < ether->nopt; i++){
- if(p = strchr(ether->opt[i], '='))
- *p = ' ';
- w_option(ctlr, ether->opt[i], strlen(ether->opt[i]));
- }
- iunlock(ctlr);
- return 0;
- }
-
- void
- etherwavelanlink(void)
- {
- addethercard("wavelan", wavelanpcmciareset);
- addethercard("wavelanpci", wavelanpcireset);
- }
|