etherwavelan.c 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. /* Pci/pcmcia code for wavelan.c */
  2. #include "u.h"
  3. #include "../port/lib.h"
  4. #include "mem.h"
  5. #include "dat.h"
  6. #include "fns.h"
  7. #include "io.h"
  8. #include "../port/error.h"
  9. #include "../port/netif.h"
  10. #include "etherif.h"
  11. #include "wavelan.h"
  12. static int
  13. wavelanpcmciareset(Ether *ether)
  14. {
  15. int i;
  16. char *p;
  17. Ctlr *ctlr;
  18. if((ctlr = malloc(sizeof(Ctlr))) == nil)
  19. return -1;
  20. ilock(ctlr);
  21. ctlr->ctlrno = ether->ctlrno;
  22. if (ether->port==0)
  23. ether->port=WDfltIOB;
  24. ctlr->iob = ether->port;
  25. if (ether->irq==0)
  26. ether->irq=WDfltIRQ;
  27. if (ioalloc(ether->port,WIOLen,0,"wavelan")<0){
  28. // print("#l%d: port 0x%lx in use\n",
  29. // ether->ctlrno, ether->port);
  30. goto abort1;
  31. }
  32. /*
  33. * If id= is specified, card must match. Otherwise try generic.
  34. */
  35. ctlr->slot = -1;
  36. for(i=0; i<ether->nopt; i++){
  37. if(cistrncmp(ether->opt[i], "id=", 3) == 0){
  38. if((ctlr->slot = pcmspecial(&ether->opt[i][3], ether)) < 0)
  39. goto abort;
  40. break;
  41. }
  42. }
  43. if(ctlr->slot == -1){
  44. for (i=0; wavenames[i]; i++)
  45. if((ctlr->slot = pcmspecial(wavenames[i], ether))>=0)
  46. break;
  47. if(!wavenames[i]){
  48. DEBUG("no wavelan found\n");
  49. goto abort;
  50. }
  51. }
  52. // DEBUG("#l%d: port=0x%lx irq=%ld\n",
  53. // ether->ctlrno, ether->port, ether->irq);
  54. if(wavelanreset(ether, ctlr) < 0){
  55. abort:
  56. iofree(ether->port);
  57. abort1:
  58. iunlock(ctlr);
  59. free(ctlr);
  60. ether->ctlr = nil;
  61. return -1;
  62. }
  63. for(i = 0; i < ether->nopt; i++){
  64. if(p = strchr(ether->opt[i], '='))
  65. *p = ' ';
  66. w_option(ctlr, ether->opt[i], strlen(ether->opt[i]));
  67. }
  68. iunlock(ctlr);
  69. return 0;
  70. }
  71. static struct {
  72. int vid;
  73. int did;
  74. } wavelanpci[] = {
  75. 0x1260, 0x3873, /* Intersil Prism2.5 */
  76. 0x1737, 0x0019, /* Linksys WPC-11 untested */
  77. };
  78. static Ctlr *ctlrhead, *ctlrtail;
  79. static void
  80. wavelanpciscan(void)
  81. {
  82. int i;
  83. void *mem;
  84. Pcidev *p;
  85. Ctlr *ctlr;
  86. p = nil;
  87. while(p = pcimatch(p, 0, 0)){
  88. for(i=0; i<nelem(wavelanpci); i++)
  89. if(p->vid == wavelanpci[i].vid && p->did == wavelanpci[i].did)
  90. break;
  91. if(i==nelem(wavelanpci))
  92. continue;
  93. /*
  94. * On the Prism, bar[0] is the memory-mapped register address (4KB),
  95. */
  96. if(p->mem[0].size != 4096){
  97. print("wavelanpci: %.4ux %.4ux: unlikely mmio size\n", p->vid, p->did);
  98. continue;
  99. }
  100. ctlr = malloc(sizeof(Ctlr));
  101. ctlr->pcidev = p;
  102. mem = vmap(p->mem[0].bar&~0xF, p->mem[0].size);
  103. if(mem == nil){
  104. print("wavelanpci: %.4ux %.4ux: vmap 0x%.8lux %d failed\n", p->vid, p->did, p->mem[0].bar&~0xF, p->mem[0].size);
  105. free(ctlr);
  106. continue;
  107. }
  108. ctlr->mmb = mem;
  109. if(ctlrhead != nil)
  110. ctlrtail->next = ctlr;
  111. else
  112. ctlrhead = ctlr;
  113. ctlrtail = ctlr;
  114. pcisetbme(p);
  115. }
  116. }
  117. static int
  118. wavelanpcireset(Ether *ether)
  119. {
  120. int i;
  121. char *p;
  122. Ctlr *ctlr;
  123. if(ctlrhead == nil)
  124. wavelanpciscan();
  125. /*
  126. * Allow plan9.ini to set vid, did?
  127. */
  128. for(ctlr=ctlrhead; ctlr!=nil; ctlr=ctlr->next)
  129. if(ctlr->active == 0)
  130. break;
  131. if(ctlr == nil)
  132. return -1;
  133. ctlr->active = 1;
  134. ilock(ctlr);
  135. ether->irq = ctlr->pcidev->intl;
  136. ether->tbdf = ctlr->pcidev->tbdf;
  137. /*
  138. * Really hard reset.
  139. */
  140. csr_outs(ctlr, WR_PciCor, 0x0080);
  141. delay(250);
  142. csr_outs(ctlr, WR_PciCor, 0x0000);
  143. delay(500);
  144. for(i=0; i<2*10; i++){
  145. if(!(csr_ins(ctlr, WR_Cmd)&WCmdBusy))
  146. break;
  147. delay(100);
  148. }
  149. if(i >= 2*10)
  150. print("wavelan pci %.4ux %.4ux: reset timeout %.4ux\n",
  151. ctlr->pcidev->vid, ctlr->pcidev->did, csr_ins(ctlr, WR_Cmd));
  152. if(wavelanreset(ether, ctlr) < 0){
  153. iunlock(ctlr);
  154. ether->ctlr = nil;
  155. return -1;
  156. }
  157. for(i = 0; i < ether->nopt; i++){
  158. if(p = strchr(ether->opt[i], '='))
  159. *p = ' ';
  160. w_option(ctlr, ether->opt[i], strlen(ether->opt[i]));
  161. }
  162. iunlock(ctlr);
  163. return 0;
  164. }
  165. void
  166. etherwavelanlink(void)
  167. {
  168. addethercard("wavelan", wavelanpcmciareset);
  169. addethercard("wavelanpci", wavelanpcireset);
  170. }