etherwavelan.c 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  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. };
  77. static Ctlr *ctlrhead, *ctlrtail;
  78. static void
  79. wavelanpciscan(void)
  80. {
  81. int i;
  82. ulong pa;
  83. Pcidev *p;
  84. Ctlr *ctlr;
  85. p = nil;
  86. while(p = pcimatch(p, 0, 0)){
  87. for(i=0; i<nelem(wavelanpci); i++)
  88. if(p->vid == wavelanpci[i].vid && p->did == wavelanpci[i].did)
  89. break;
  90. if(i==nelem(wavelanpci))
  91. continue;
  92. /*
  93. * On the Prism, bar[0] is the memory-mapped register address (4KB),
  94. */
  95. if(p->mem[0].size != 4096){
  96. print("wavelanpci: %.4ux %.4ux: unlikely mmio size\n", p->vid, p->did);
  97. continue;
  98. }
  99. ctlr = malloc(sizeof(Ctlr));
  100. ctlr->pcidev = p;
  101. pa = upamalloc(p->mem[0].bar&~0xF, p->mem[0].size, 0);
  102. if(pa == 0){
  103. print("wavelanpci: %.4ux %.4ux: upamalloc 0x%.8lux %d failed\n", p->vid, p->did, p->mem[0].bar&~0xF, p->mem[0].size);
  104. free(ctlr);
  105. continue;
  106. }
  107. ctlr->mmb = (ushort*)KADDR(pa);
  108. if(ctlrhead != nil)
  109. ctlrtail->next = ctlr;
  110. else
  111. ctlrhead = ctlr;
  112. ctlrtail = ctlr;
  113. pcisetbme(p);
  114. }
  115. }
  116. static int
  117. wavelanpcireset(Ether *ether)
  118. {
  119. int i;
  120. char *p;
  121. Ctlr *ctlr;
  122. if(ctlrhead == nil)
  123. wavelanpciscan();
  124. /*
  125. * Allow plan9.ini to set vid, did?
  126. */
  127. for(ctlr=ctlrhead; ctlr!=nil; ctlr=ctlr->next)
  128. if(ctlr->active == 0)
  129. break;
  130. if(ctlr == nil)
  131. return -1;
  132. ctlr->active = 1;
  133. ilock(ctlr);
  134. ether->irq = ctlr->pcidev->intl;
  135. ether->tbdf = ctlr->pcidev->tbdf;
  136. /*
  137. * Really hard reset.
  138. */
  139. csr_outs(ctlr, WR_PciCor, 0x0080);
  140. delay(250);
  141. csr_outs(ctlr, WR_PciCor, 0x0000);
  142. delay(500);
  143. for(i=0; i<2*10; i++){
  144. if(!(csr_ins(ctlr, WR_Cmd)&WCmdBusy))
  145. break;
  146. delay(100);
  147. }
  148. if(i >= 2*10)
  149. print("wavelan pci %.4ux %.4ux: reset timeout %.4ux\n",
  150. ctlr->pcidev->vid, ctlr->pcidev->did, csr_ins(ctlr, WR_Cmd));
  151. if(wavelanreset(ether, ctlr) < 0){
  152. iunlock(ctlr);
  153. ether->ctlr = nil;
  154. return -1;
  155. }
  156. for(i = 0; i < ether->nopt; i++){
  157. if(p = strchr(ether->opt[i], '='))
  158. *p = ' ';
  159. w_option(ctlr, ether->opt[i], strlen(ether->opt[i]));
  160. }
  161. iunlock(ctlr);
  162. return 0;
  163. }
  164. void
  165. etherwavelanlink(void)
  166. {
  167. addethercard("wavelan", wavelanpcmciareset);
  168. addethercard("wavelanpci", wavelanpcireset);
  169. }