1 #include "u.h" 2 #include "lib.h" 3 #include "mem.h" 4 #include "dat.h" 5 #include "fns.h" 6 #include "io.h" 7 #include "ip.h" 8 9 #include "etherif.h" 10 11 static Ether ether[MaxEther]; 12 13 extern int ether2114xreset(Ether*); 14 extern int elnk3reset(Ether*); 15 extern int i82557reset(Ether*); 16 extern int igbepnp(Ether *); 17 extern int elnk3reset(Ether*); 18 extern int ether589reset(Ether*); 19 extern int ne2000reset(Ether*); 20 extern int wd8003reset(Ether*); 21 extern int ec2treset(Ether*); 22 extern int amd79c970reset(Ether*); 23 extern int rtl8139pnp(Ether*); 24 extern int rtl8169pnp(Ether*); 25 extern int ether83815reset(Ether*); 26 extern int rhinepnp(Ether*); 27 28 struct { 29 char *type; 30 int (*reset)(Ether*); 31 int noprobe; 32 } ethercards[] = { 33 { "21140", ether2114xreset, 0, }, 34 { "2114x", ether2114xreset, 0, }, 35 { "i82557", i82557reset, 0, }, 36 { "igbe", igbepnp, 0, }, 37 { "elnk3", elnk3reset, 0, }, 38 { "3C509", elnk3reset, 0, }, 39 { "3C575", elnk3reset, 0, }, 40 { "3C589", ether589reset, 1, }, 41 { "3C562", ether589reset, 1, }, 42 { "589E", ether589reset, 1, }, 43 { "NE2000", ne2000reset, 0, }, 44 { "WD8003", wd8003reset, 1, }, 45 { "EC2T", ec2treset, 0, }, 46 { "AMD79C970", amd79c970reset, 0, }, 47 { "RTL8139", rtl8139pnp, 0, }, 48 { "RTL8169", rtl8169pnp, 0, }, 49 { "83815", ether83815reset, 0, }, 50 { "rhine", rhinepnp, 0, }, 51 52 { 0, } 53 }; 54 55 static void xetherdetach(void); 56 57 int 58 etherinit(void) 59 { 60 Ether *ctlr; 61 int ctlrno, i, mask, n, x; 62 63 fmtinstall('E', eipfmt); 64 65 etherdetach = xetherdetach; 66 mask = 0; 67 for(ctlrno = 0; ctlrno < MaxEther; ctlrno++){ 68 ctlr = ðer[ctlrno]; 69 memset(ctlr, 0, sizeof(Ether)); 70 if(iniread && isaconfig("ether", ctlrno, ctlr) == 0) 71 continue; 72 73 for(n = 0; ethercards[n].type; n++){ 74 if(!iniread){ 75 if(ethercards[n].noprobe) 76 continue; 77 memset(ctlr, 0, sizeof(Ether)); 78 strcpy(ctlr->type, ethercards[n].type); 79 } 80 else if(cistrcmp(ethercards[n].type, ctlr->type)) 81 continue; 82 ctlr->ctlrno = ctlrno; 83 84 x = splhi(); 85 if((*ethercards[n].reset)(ctlr)){ 86 splx(x); 87 if(iniread) 88 break; 89 else 90 continue; 91 } 92 93 ctlr->state = 1; 94 mask |= 1<<ctlrno; 95 if(ctlr->irq == 2) 96 ctlr->irq = 9; 97 setvec(VectorPIC + ctlr->irq, ctlr->interrupt, ctlr); 98 99 print("ether#%d: %s: port 0x%luX irq %lud", 100 ctlr->ctlrno, ctlr->type, ctlr->port, ctlr->irq); 101 if(ctlr->mem) 102 print(" addr 0x%luX", ctlr->mem & ~KZERO); 103 if(ctlr->size) 104 print(" size 0x%luX", ctlr->size); 105 print(": %E\n", ctlr->ea); 106 107 if(ctlr->nrb == 0) 108 ctlr->nrb = Nrb; 109 ctlr->rb = ialloc(sizeof(RingBuf)*ctlr->nrb, 0); 110 if(ctlr->ntb == 0) 111 ctlr->ntb = Ntb; 112 ctlr->tb = ialloc(sizeof(RingBuf)*ctlr->ntb, 0); 113 114 ctlr->rh = 0; 115 ctlr->ri = 0; 116 for(i = 0; i < ctlr->nrb; i++) 117 ctlr->rb[i].owner = Interface; 118 119 ctlr->th = 0; 120 ctlr->ti = 0; 121 for(i = 0; i < ctlr->ntb; i++) 122 ctlr->tb[i].owner = Host; 123 124 splx(x); 125 break; 126 } 127 } 128 129 return mask; 130 } 131 132 void 133 etherinitdev(int i, char *s) 134 { 135 sprint(s, "ether%d", i); 136 } 137 138 void 139 etherprintdevs(int i) 140 { 141 print(" ether%d", i); 142 } 143 144 static Ether* 145 attach(int ctlrno) 146 { 147 Ether *ctlr; 148 149 if(ctlrno >= MaxEther || ether[ctlrno].state == 0) 150 return 0; 151 152 ctlr = ðer[ctlrno]; 153 if(ctlr->state == 1){ 154 ctlr->state = 2; 155 (*ctlr->attach)(ctlr); 156 } 157 158 return ctlr; 159 } 160 161 static void 162 xetherdetach(void) 163 { 164 Ether *ctlr; 165 int ctlrno, x; 166 167 x = splhi(); 168 for(ctlrno = 0; ctlrno < MaxEther; ctlrno++){ 169 ctlr = ðer[ctlrno]; 170 if(ctlr->detach && ctlr->state != 0) 171 ctlr->detach(ctlr); 172 } 173 splx(x); 174 } 175 176 uchar* 177 etheraddr(int ctlrno) 178 { 179 Ether *ctlr; 180 181 if((ctlr = attach(ctlrno)) == 0) 182 return 0; 183 184 return ctlr->ea; 185 } 186 187 static int 188 wait(RingBuf* ring, uchar owner, int timo) 189 { 190 ulong start; 191 192 start = m->ticks; 193 while(TK2MS(m->ticks - start) < timo){ 194 if(ring->owner != owner) 195 return 1; 196 } 197 198 return 0; 199 } 200 201 int 202 etherrxpkt(int ctlrno, Etherpkt* pkt, int timo) 203 { 204 int n; 205 Ether *ctlr; 206 RingBuf *ring; 207 208 if((ctlr = attach(ctlrno)) == 0) 209 return 0; 210 211 ring = &ctlr->rb[ctlr->rh]; 212 if(wait(ring, Interface, timo) == 0){ 213 if(debug) 214 print("ether%d: rx timeout\n", ctlrno); 215 return 0; 216 } 217 218 n = ring->len; 219 memmove(pkt, ring->pkt, n); 220 ring->owner = Interface; 221 ctlr->rh = NEXT(ctlr->rh, ctlr->nrb); 222 223 return n; 224 } 225 226 int 227 etherrxflush(int ctlrno) 228 { 229 int n; 230 Ether *ctlr; 231 RingBuf *ring; 232 233 if((ctlr = attach(ctlrno)) == 0) 234 return 0; 235 236 n = 0; 237 for(;;){ 238 ring = &ctlr->rb[ctlr->rh]; 239 if(wait(ring, Interface, 100) == 0) 240 break; 241 242 ring->owner = Interface; 243 ctlr->rh = NEXT(ctlr->rh, ctlr->nrb); 244 n++; 245 } 246 247 return n; 248 } 249 250 int 251 ethertxpkt(int ctlrno, Etherpkt* pkt, int len, int) 252 { 253 Ether *ctlr; 254 RingBuf *ring; 255 int s; 256 257 if((ctlr = attach(ctlrno)) == 0) 258 return 0; 259 260 ring = &ctlr->tb[ctlr->th]; 261 if(wait(ring, Interface, 1000) == 0){ 262 print("ether%d: tx buffer timeout\n", ctlrno); 263 return 0; 264 } 265 266 memmove(pkt->s, ctlr->ea, Eaddrlen); 267 if(debug) 268 print("%E to %E...\n", pkt->s, pkt->d); 269 memmove(ring->pkt, pkt, len); 270 if(len < ETHERMINTU){ 271 memset(ring->pkt+len, 0, ETHERMINTU-len); 272 len = ETHERMINTU; 273 } 274 ring->len = len; 275 ring->owner = Interface; 276 ctlr->th = NEXT(ctlr->th, ctlr->ntb); 277 s = splhi(); 278 (*ctlr->transmit)(ctlr); 279 splx(s); 280 281 return 1; 282 } 283