ethersaturn.c 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  1. #include "u.h"
  2. #include "../port/lib.h"
  3. #include "mem.h"
  4. #include "dat.h"
  5. #include "fns.h"
  6. #include "io.h"
  7. #include "../port/error.h"
  8. #include "../port/netif.h"
  9. #include "msaturn.h"
  10. #include "etherif.h"
  11. enum{
  12. Etcr = Saturn + 0x0c00,
  13. Etsr = Saturn + 0x0c02,
  14. Ercr = Saturn + 0x0c04,
  15. Ersr = Saturn + 0x0c06,
  16. Eisr = Saturn + 0x0d04,
  17. Eimr = Saturn + 0x0d06,
  18. Emacaddr0 = Saturn + 0x0e02,
  19. Miicr = Saturn + 0x0f02,
  20. Miiwdr = Saturn + 0x0f04,
  21. Miirdr = Saturn + 0x0f06,
  22. Ethermem = 0xf2c00000,
  23. Etherfsize = 0x2000,
  24. Nrx = 14,
  25. Ntx = 2, // Nrx + Ntx must be 16
  26. Ersr_rxfpmask = 0xf,
  27. Ersr_rxevent = RBIT(0, ushort),
  28. Etcr_txfpmask = 0xf,
  29. Ercr_rxenab = RBIT(0, ushort),
  30. Ercr_auienab = RBIT(2, ushort),
  31. Etcr_txstart = RBIT(1, ushort),
  32. Etcr_retries = 0xf<<8,
  33. Ei_txecall = RBIT(0, ushort),
  34. Ei_txretry = RBIT(2, ushort),
  35. Ei_txdefer = RBIT(3, ushort),
  36. Ei_txcrs = RBIT(4, ushort),
  37. Ei_txdone = RBIT(5, ushort),
  38. Ei_rxcrcerr = RBIT(8, ushort),
  39. Ei_rxdrib = RBIT(9, ushort),
  40. Ei_rxdone = RBIT(10, ushort),
  41. Ei_rxshort = RBIT(11, ushort),
  42. Ei_rxlong = RBIT(12, ushort),
  43. Miicr_regshift = 6,
  44. Miicr_read = RBIT(10, ushort),
  45. Miicr_preambledis = RBIT(12, ushort),
  46. Miicr_accack = RBIT(14, ushort),
  47. Miicr_accbsy = RBIT(15, ushort),
  48. };
  49. typedef struct {
  50. Lock;
  51. int txbusy;
  52. int txempty;
  53. int txfull;
  54. int ntx; /* number of entries in transmit ring */
  55. int rxlast;
  56. int active;
  57. ulong interrupts; /* statistics */
  58. ulong overflows;
  59. } Ctlr;
  60. static ushort*etcr=(ushort*)Etcr;
  61. static ushort*etsr=(ushort*)Etsr;
  62. static ushort*ercr=(ushort*)Ercr;
  63. static ushort*ersr=(ushort*)Ersr;
  64. static ushort*eimr=(ushort*)Eimr;
  65. static ushort*eisr=(ushort*)Eisr;
  66. static ushort*miicr=(ushort*)Miicr;
  67. static ushort*miirdr=(ushort*)Miirdr;
  68. static void
  69. txfill(Ether*ether, Ctlr*ctlr)
  70. {
  71. int len;
  72. Block *b;
  73. ushort*dst;
  74. while(ctlr->ntx<Ntx){
  75. if((b=qget(ether->oq)) == nil)
  76. break;
  77. len = BLEN(b);
  78. dst = (ushort*)(Ethermem+(ctlr->txempty+Nrx)*Etherfsize);
  79. *dst = len;
  80. memmove(&dst[1], b->rp, len);
  81. ctlr->ntx++;
  82. ctlr->txempty++;
  83. if(ctlr->txempty==Ntx)
  84. ctlr->txempty = 0;
  85. freeb(b);
  86. }
  87. }
  88. static void
  89. txrestart(Ctlr*ctlr)
  90. {
  91. if(ctlr->ntx==0 || ctlr->txbusy)
  92. return;
  93. ctlr->txbusy = 1;
  94. *etcr = Etcr_txstart|Etcr_retries|(ctlr->txfull+Nrx);
  95. }
  96. static void interrupt(Ureg*, void*);
  97. static void
  98. transmit(Ether*ether)
  99. {
  100. Ctlr *ctlr;
  101. ctlr = ether->ctlr;
  102. ilock(ctlr);
  103. txfill(ether, ctlr);
  104. txrestart(ctlr);
  105. iunlock(ctlr);
  106. }
  107. static void
  108. interrupt(Ureg*, void*arg)
  109. {
  110. Ctlr*ctlr;
  111. Ether*ether = arg;
  112. Etherpkt*pkt;
  113. ushort ie;
  114. int rx, len;
  115. Block *b;
  116. ctlr = ether->ctlr;
  117. if(!ctlr->active)
  118. return; /* not ours */
  119. ctlr->interrupts++;
  120. ilock(ctlr);
  121. ie = *eisr;
  122. *eisr = ie;
  123. intack();
  124. if(ie==0)
  125. iprint("interrupt: no interrupt source?\n");
  126. if(ie&Ei_txdone){
  127. if((*etcr&Etcr_txstart)==0){
  128. if(ctlr->txbusy){
  129. ctlr->txbusy = 0;
  130. ctlr->ntx--;
  131. ctlr->txfull++;
  132. if(ctlr->txfull==Ntx)
  133. ctlr->txfull = 0;
  134. }
  135. txrestart(ctlr);
  136. txfill(ether, ctlr);
  137. txrestart(ctlr);
  138. }
  139. else
  140. iprint("interrupt: bogus tx interrupt\n");
  141. ie &= ~Ei_txdone;
  142. }
  143. if(ie&Ei_rxdone){
  144. rx=*ersr&Ersr_rxfpmask;
  145. while(ctlr->rxlast!=rx){
  146. ctlr->rxlast++;
  147. if(ctlr->rxlast >= Nrx)
  148. ctlr->rxlast = 0;
  149. pkt = (Etherpkt*)(Ethermem+ctlr->rxlast*Etherfsize);
  150. len = *(ushort*)pkt;
  151. if((b = iallocb(len+sizeof(ushort))) != nil){
  152. memmove(b->wp, pkt, len+sizeof(ushort));
  153. b->rp += sizeof(ushort);
  154. b->wp = b->rp + len;
  155. etheriq(ether, b, 1);
  156. }else
  157. ether->soverflows++;
  158. rx=*ersr&Ersr_rxfpmask;
  159. }
  160. ie &= ~Ei_rxdone;
  161. }
  162. if(ie&Ei_txretry){
  163. iprint("ethersaturn: txretry!\n");
  164. ie &= ~Ei_txretry;
  165. ctlr->txbusy = 0;
  166. txrestart(ctlr);
  167. }
  168. ie &= ~Ei_txcrs;
  169. if(ie)
  170. iprint("interrupt: unhandled interrupts %.4uX\n", ie);
  171. iunlock(ctlr);
  172. }
  173. static int
  174. reset(Ether* ether)
  175. {
  176. Ctlr*ctlr;
  177. *ercr = 0;
  178. ctlr = malloc(sizeof(*ctlr));
  179. memset(ctlr, 0, sizeof(*ctlr));
  180. ctlr->active = 1;
  181. ether->ctlr = ctlr;
  182. ether->transmit = transmit;
  183. ether->interrupt = interrupt;
  184. ether->irq = Vecether;
  185. ether->arg = ether;
  186. memmove(ether->ea, (ushort*)Emacaddr0, Eaddrlen);
  187. *ercr = Ercr_rxenab|Ercr_auienab|(Nrx-1);
  188. *eimr = Ei_rxdone|Ei_txretry|Ei_txdone;
  189. iprint("reset: ercr %.4uX\n", *ercr);
  190. return 0;
  191. }
  192. void
  193. ethersaturnlink(void)
  194. {
  195. addethercard("saturn", reset);
  196. }