etherif.c 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326
  1. #include "all.h"
  2. #include "io.h"
  3. #include "mem.h"
  4. #include "../ip/ip.h"
  5. #include "etherif.h"
  6. extern int etherga620reset(Ether*);
  7. extern int ether21140reset(Ether*);
  8. extern int etherelnk3reset(Ether*);
  9. extern int etheri82557reset(Ether*);
  10. extern int dp83815reset(Ether*);
  11. extern int dp83820pnp(Ether*);
  12. extern int rtl8139pnp(Ether*);
  13. static struct
  14. {
  15. char* type;
  16. int (*reset)(Ether*);
  17. } etherctlr[] =
  18. {
  19. { "ga620", etherga620reset, },
  20. { "21140", ether21140reset, },
  21. { "2114x", ether21140reset, },
  22. { "3C509", etherelnk3reset, },
  23. { "83815", dp83815reset, },
  24. { "dp83820", dp83820pnp, },
  25. { "elnk3", etherelnk3reset, },
  26. { "i82557", etheri82557reset, },
  27. { "rtl8139", rtl8139pnp, },
  28. { 0, },
  29. };
  30. static Ether etherif[MaxEther];
  31. void
  32. etheriq(Ether* ether, Msgbuf* mb)
  33. {
  34. ilock(&ether->rqlock);
  35. if(ether->rqhead)
  36. ether->rqtail->next = mb;
  37. else
  38. ether->rqhead = mb;
  39. ether->rqtail = mb;
  40. mb->next = 0;
  41. iunlock(&ether->rqlock);
  42. wakeup(&ether->rqr);
  43. }
  44. static int
  45. isinput(void* arg)
  46. {
  47. return ((Ether*)arg)->rqhead != 0;
  48. }
  49. #include "compat.h"
  50. static void
  51. etheri(void)
  52. {
  53. Ether *ether;
  54. Ifc *ifc;
  55. Msgbuf *mb;
  56. Enpkt *p;
  57. ether = getarg();
  58. ifc = &ether->ifc;
  59. print("ether%di: %E %I\n", ether->ctlrno, ether->ifc.ea, ether->ifc.ipa);
  60. (*ether->attach)(ether);
  61. for(;;) {
  62. while(!isinput(ether))
  63. sleep(&ether->rqr, isinput, ether);
  64. ilock(&ether->rqlock);
  65. if(ether->rqhead == 0) {
  66. iunlock(&ether->rqlock);
  67. continue;
  68. }
  69. mb = ether->rqhead;
  70. ether->rqhead = mb->next;
  71. iunlock(&ether->rqlock);
  72. p = (Enpkt*)mb->data;
  73. switch(nhgets(p->type)){
  74. case Arptype:
  75. arpreceive(p, mb->count, ifc);
  76. break;
  77. case Iptype:
  78. ipreceive(p, mb->count, ifc);
  79. ifc->rxpkt++;
  80. ifc->work[0].count++;
  81. ifc->work[1].count++;
  82. ifc->work[2].count++;
  83. ifc->rate[0].count += mb->count;
  84. ifc->rate[1].count += mb->count;
  85. ifc->rate[2].count += mb->count;
  86. break;
  87. }
  88. mbfree(mb);
  89. }
  90. }
  91. static void
  92. ethero(void)
  93. {
  94. Ether *ether;
  95. Ifc *ifc;
  96. Msgbuf *mb;
  97. int len;
  98. ether = getarg();
  99. ifc = &ether->ifc;
  100. print("ether%do: %E %I\n", ether->ctlrno, ifc->ea, ifc->ipa);
  101. for(;;) {
  102. for(;;) {
  103. mb = recv(ifc->reply, 0);
  104. if(mb != nil)
  105. break;
  106. }
  107. if(mb->data == 0) {
  108. print("ether%do: pkt nil cat=%d free=%d\n",
  109. ether->ctlrno, mb->category, mb->flags&FREE);
  110. if(!(mb->flags & FREE))
  111. mbfree(mb);
  112. continue;
  113. }
  114. len = mb->count;
  115. if(len > ETHERMAXTU) {
  116. print("ether%do: pkt too big - %d\n", ether->ctlrno, len);
  117. mbfree(mb);
  118. continue;
  119. }
  120. if(len < ETHERMINTU) {
  121. memset(mb->data+len, 0, ETHERMINTU-len);
  122. mb->count = len = ETHERMINTU;
  123. }
  124. memmove(((Enpkt*)(mb->data))->s, ifc->ea, sizeof(ifc->ea));
  125. ilock(&ether->tqlock);
  126. if(ether->tqhead)
  127. ether->tqtail->next = mb;
  128. else
  129. ether->tqhead = mb;
  130. ether->tqtail = mb;
  131. mb->next = 0;
  132. iunlock(&ether->tqlock);
  133. (*ether->transmit)(ether);
  134. ifc->work[0].count++;
  135. ifc->work[1].count++;
  136. ifc->work[2].count++;
  137. ifc->rate[0].count += len;
  138. ifc->rate[1].count += len;
  139. ifc->rate[2].count += len;
  140. ifc->txpkt++;
  141. }
  142. }
  143. Msgbuf*
  144. etheroq(Ether* ether)
  145. {
  146. Msgbuf *mb;
  147. mb = nil;
  148. ilock(&ether->tqlock);
  149. if(ether->tqhead){
  150. mb = ether->tqhead;
  151. ether->tqhead = mb->next;
  152. }
  153. iunlock(&ether->tqlock);
  154. return mb;
  155. }
  156. static void
  157. cmd_state(int, char*[])
  158. {
  159. Ether *ether;
  160. Ifc *ifc;
  161. for(ether = &etherif[0]; ether < &etherif[MaxEther]; ether++){
  162. if(ether->mbps == 0)
  163. continue;
  164. ifc = &ether->ifc;
  165. if(!isvalidip(ifc->ipa))
  166. continue;
  167. print("ether stats %d\n", ether->ctlrno);
  168. print(" work =%7W%7W%7W pkts\n", ifc->work+0, ifc->work+1, ifc->work+2);
  169. print(" rate =%7W%7W%7W tBps\n", ifc->rate+0, ifc->rate+1, ifc->rate+2);
  170. print(" err = %3ld rc %3ld sum\n", ifc->rcverr, ifc->sumerr);
  171. }
  172. }
  173. void
  174. etherstart(void)
  175. {
  176. Ether *ether;
  177. Ifc *ifc;
  178. int anystarted;
  179. char buf[100], *p;
  180. anystarted = 0;
  181. for(ether = &etherif[0]; ether < &etherif[MaxEther]; ether++){
  182. if(ether->mbps == 0)
  183. continue;
  184. ifc = &ether->ifc;
  185. lock(ifc);
  186. getipa(ifc, ether->ctlrno);
  187. if(!isvalidip(ifc->ipa)){
  188. unlock(ifc);
  189. ether->mbps = 0;
  190. continue;
  191. }
  192. if(ifc->reply == 0){
  193. dofilter(ifc->work+0, C0a, C0b, 1);
  194. dofilter(ifc->work+1, C1a, C1b, 1);
  195. dofilter(ifc->work+2, C2a, C2b, 1);
  196. dofilter(ifc->rate+0, C0a, C0b, 1000);
  197. dofilter(ifc->rate+1, C1a, C1b, 1000);
  198. dofilter(ifc->rate+2, C2a, C2b, 1000);
  199. ifc->reply = newqueue(Nqueue);
  200. }
  201. unlock(ifc);
  202. sprint(ether->oname, "ether%do", ether->ctlrno);
  203. userinit(ethero, ether, ether->oname);
  204. sprint(ether->iname, "ether%di", ether->ctlrno);
  205. userinit(etheri, ether, ether->iname);
  206. ifc->next = enets;
  207. enets = ifc;
  208. anystarted++;
  209. }
  210. if(anystarted){
  211. cmd_install("state", "-- ether stats", cmd_state);
  212. arpstart();
  213. if((p = getconf("route")) && strlen(p) < sizeof(buf)-7){
  214. sprint(buf, "route %s", p);
  215. cmd_exec(buf);
  216. }
  217. }
  218. }
  219. static int
  220. parseether(uchar *to, char *from)
  221. {
  222. char nip[4];
  223. char *p;
  224. int i;
  225. p = from;
  226. while(*p == ' ')
  227. ++p;
  228. for(i = 0; i < 6; i++){
  229. if(*p == 0)
  230. return -1;
  231. nip[0] = *p++;
  232. if(*p == 0)
  233. return -1;
  234. nip[1] = *p++;
  235. nip[2] = 0;
  236. to[i] = strtoul(nip, 0, 16);
  237. if(*p == ':')
  238. p++;
  239. }
  240. return 0;
  241. }
  242. void
  243. etherinit(void)
  244. {
  245. Ether *ether;
  246. int i, n, ctlrno;
  247. for(ctlrno = 0; ctlrno < MaxEther; ctlrno++){
  248. ether = &etherif[ctlrno];
  249. memset(ether, 0, sizeof(Ether));
  250. if(!isaconfig("ether", ctlrno, ether))
  251. continue;
  252. for(n = 0; etherctlr[n].type; n++){
  253. if(cistrcmp(etherctlr[n].type, ether->type))
  254. continue;
  255. ether->ctlrno = ctlrno;
  256. ether->tbdf = BUSUNKNOWN;
  257. for(i = 0; i < ether->nopt; i++){
  258. if(strncmp(ether->opt[i], "ea=", 3))
  259. continue;
  260. if(parseether(ether->ea, &ether->opt[i][3]) == -1)
  261. memset(ether->ea, 0, Easize);
  262. }
  263. if((*etherctlr[n].reset)(ether))
  264. break;
  265. if(ether->irq == 2)
  266. ether->irq = 9;
  267. setvec(Int0vec + ether->irq, ether->interrupt, ether);
  268. memmove(ether->ifc.ea, ether->ea, sizeof(ether->ea));
  269. print("ether%d: %s: %dMbps port 0x%lux irq %ld",
  270. ctlrno, ether->type, ether->mbps, ether->port, ether->irq);
  271. if(ether->mem)
  272. print(" addr 0x%lux", ether->mem & ~KZERO);
  273. if(ether->size)
  274. print(" size 0x%lux", ether->size);
  275. print(": ");
  276. for(i = 0; i < sizeof(ether->ea); i++)
  277. print("%2.2ux", ether->ea[i]);
  278. print("\n");
  279. break;
  280. }
  281. }
  282. }