|
|
1.1 ! root 1: {\rtf0\ansi{\fonttbl\f0\fmodern Ohlfs;\f1\fmodern Courier;} ! 2: \paperw13040 ! 3: \paperh10200 ! 4: \margl120 ! 5: \margr120 ! 6: {\colortbl\red0\green0\blue0;} ! 7: \pard\tx1152\tx2304\tx3456\tx4608\tx5760\tx6912\tx8064\tx9216\tx10368\tx11520\f0\b0\i0\ul0\fs24 current m68k Etehernet driver notes\ ! 8: \ ! 9: ! 10: \f1\b\fs28 Globals ! 11: \f0\b0\fs24 \ ! 12: \ ! 13: struct en_softc en_softc[] - one per interface.\ ! 14: \ ! 15: ! 16: \f1\b\fs28 Functions ! 17: \f0\b0\fs24 \ ! 18: \ ! 19: int enprobe(caddr_t reg, int ctrl) \ ! 20: // ! 21: \f1\b\fs28 called from ! 22: \f0\b0\fs24 : \ ! 23: // via autoconf, in endriver\ ! 24: \{\ ! 25: return "real" address ! 26: \fc0 (w/slot_id_map offset) ! 27: of en registers;\ ! 28: \}\ ! 29: \ ! 30: int enattach( ! 31: struct bus_device *bd ! 32: ) \ ! 33: ! 34: // ! 35: \f1\b\fs28 called from ! 36: \f0\b0\fs24 : via autoconf, in endriver\ ! 37: ! 38: \{\ ! 39: get enet address saved by ROM in global etheraddr, save it in \ ! 40: en_softc and write to hardware;\ ! 41: if_attach( ! 42: eninit, NULL, enoutput, engetbuf, encontrol, ! 43: a slew of args);\ ! 44: \}\ ! 45: \ ! 46: int eninit(netif_t netif)\ ! 47: // ! 48: \f1\b\fs28 called from ! 49: \f0\b0\fs24 :\ ! 50: // en_setaddr\ ! 51: / enattach\ ! 52: / encontrol\ ! 53: \{\ ! 54: get *en_softc from netif;\ ! 55: basic "get s/w and h/w state to known condition" stuff;\ ! 56: set new phys address if spec'd in en_softc.is_flags;\ ! 57: queue up ! 58: NTXBUFS ! 59: DMA buffers ib en_softc. ! 60: is_tx_free ! 61: ;\ ! 62: queue up ! 63: NRXBUFS ! 64: DMA buffers in hardware queue;\ ! 65: \}\ ! 66: \ ! 67: int ! 68: en_rx_grabbufs(struct en_softc *is)\ ! 69: ! 70: \pard\tx1140\tx2300\tx3440\tx4600\tx5760\tx6900\tx8060\tx9200\tx10360\tx11520 // ! 71: \f1\b\fs28 called from ! 72: \f0\b0\fs24 :\ ! 73: / timeout() callout from in ! 74: \pard\tx1152\tx2304\tx3456\tx4608\tx5760\tx6912\tx8064\tx9216\tx10368\tx11520\fc0 en_rx_dmaintr ! 75: \pard\tx1140\tx2300\tx3440\tx4600\tx5760\tx6900\tx8060\tx9200\tx10360\tx11520\fc0 () ! 76: \ ! 77: ! 78: \pard\tx1152\tx2304\tx3456\tx4608\tx5760\tx6912\tx8064\tx9216\tx10368\tx11520\fc0 \{\ ! 79: get memory via if_busalloc for all DMA headers in is_rx_free,\ ! 80: enqueue result in hardware queue;\ ! 81: \}\ ! 82: \ ! 83: void en_rx_dmaintr(int unit)\ ! 84: ! 85: \pard\tx1140\tx2300\tx3440\tx4600\tx5760\tx6900\tx8060\tx9200\tx10360\tx11520 // ! 86: \f1\b\fs28 called from ! 87: \f0\b0\fs24 :\ ! 88: / DMA interrupt handler\ ! 89: ! 90: \pard\tx1152\tx2304\tx3456\tx4608\tx5760\tx6912\tx8064\tx9216\tx10368\tx11520\fc0 \{\ ! 91: if any DMA errors\ ! 92: log to console (but keep going...!);\ ! 93: get length of packet from DMA engine;\ ! 94: if invalid length \{\ ! 95: log error;\ ! 96: if_errors_set();\ ! 97: re-enqueue this header and buffer on h/w;\ ! 98: \}\ ! 99: nb = if_rbusget(dma buffer, HDR_SIZE + length);\ ! 100: if_handle_input(en_softc->is_if, nb, NULL);\ ! 101: if_busalloc() a new DMA buffer;\ ! 102: if none available\ ! 103: put this header on is_rx_free\ ! 104: else\ ! 105: enqueue this header and buffer on h/w;\ ! 106: record is_last_rx timestamp;\ ! 107: \}\ ! 108: \ ! 109: int enoutput(netif_t netif,\ ! 110: netbuf_t nb,\ ! 111: void *dst)\ ! 112: ! 113: \pard\tx1140\tx2300\tx3440\tx4600\tx5760\tx6900\tx8060\tx9200\tx10360\tx11520 // ! 114: \f1\b\fs28 called from ! 115: \f0\b0\fs24 :\ ! 116: // higher layer protocol - registered in if_attach() in enattach().\ ! 117: ! 118: \pard\tx1152\tx2304\tx3456\tx4608\tx5760\tx6912\tx8064\tx9216\tx10368\tx11520\fc0 \{\ ! 119: /*\ ! 120: * Crufty crap:\ ! 121: * \ ! 122: * struct ifnet *ifp = (struct ifnet *)netif; \ ! 123: * struct mbuf *m = (struct mbuf *)nb; \ ! 124: *\ ! 125: * Find out from Brad or jks why the "XXX" one these lines and what \ ! 126: * we hope to do about this kind of thing in the future...\ ! 127: */\ ! 128: \ ! 129: ! 130: \pard\tx1140\tx2300\tx3440\tx4600\tx5760\tx6900\tx8060\tx9200\tx10360\tx11520 get *en_softc from netif;\ ! 131: if not running or net down \{\ ! 132: nb_free(nb);\ ! 133: return ENETDOWN;\ ! 134: \}\ ! 135: ! 136: \pard\tx1152\tx2304\tx3456\tx4608\tx5760\tx6912\tx8064\tx9216\tx10368\tx11520\fc0 copy dest addr from dst to mtod(m, struct ether_header *);\ ! 137: copy source addr from en_softc to mtod(m, struct ether_header *);\ ! 138: if (IF_QFULL(&ifp->if_snd)) \{\ ! 139: handle queue full error;\ ! 140: return ENOBUFS;\ ! 141: \}\ ! 142: IF_ENQUEUE(&ifp->if_snd, m);\ ! 143: if not active\ ! 144: enstart();\ ! 145: return 0;\ ! 146: \}\ ! 147: \ ! 148: int enstart(dev_t dev)\ ! 149: ! 150: \pard\tx1140\tx2300\tx3440\tx4600\tx5760\tx6900\tx8060\tx9200\tx10360\tx11520 // ! 151: \f1\b\fs28 called from ! 152: \f0\b0\fs24 :\ ! 153: / ! 154: \pard\tx1152\tx2304\tx3456\tx4608\tx5760\tx6912\tx8064\tx9216\tx10368\tx11520\fc0 en_tx_dmaintr ! 155: \pard\tx1140\tx2300\tx3440\tx4600\tx5760\tx6900\tx8060\tx9200\tx10360\tx11520\fc0 (), ! 156: \pard\tx1152\tx2304\tx3456\tx4608\tx5760\tx6912\tx8064\tx9216\tx10368\tx11520\fc0 enoutput ! 157: \pard\tx1140\tx2300\tx3440\tx4600\tx5760\tx6900\tx8060\tx9200\tx10360\tx11520\fc0 () ! 158: \ ! 159: ! 160: \pard\tx1152\tx2304\tx3456\tx4608\tx5760\tx6912\tx8064\tx9216\tx10368\tx11520\fc0 \{\ ! 161: dequeue an mbuf from our netif;\ ! 162: get a free DMA header from is_tx_free;\ ! 163: if none \{\ ! 164: log error;\ ! 165: nb_free(nb);\ ! 166: return;\ ! 167: \}\ ! 168: if_busalloc(free hdr, netbuf);\ ! 169: calculate DMA start/end registers kludges;\ ! 170: splimp();\ ! 171: start en_jam timeout timer;\ ! 172: dma_enqueue() the header (in h/w if necessary);\ ! 173: set output_active flag;\ ! 174: splx();\ ! 175: \}\ ! 176: \ ! 177: int en_down(int unit)\ ! 178: ! 179: \pard\tx1140\tx2300\tx3440\tx4600\tx5760\tx6900\tx8060\tx9200\tx10360\tx11520 // ! 180: \f1\b\fs28 called from ! 181: \f0\b0\fs24 :\ ! 182: // boot (to take net down)\ ! 183: // en_jam(), on "I give up, it's broken"\ ! 184: ! 185: \pard\tx1152\tx2304\tx3456\tx4608\tx5760\tx6912\tx8064\tx9216\tx10368\tx11520\fc0 \{\ ! 186: if_down();\ ! 187: \}\ ! 188: \ ! 189: int en_antijam(struct en_softc *is)\ ! 190: ! 191: \pard\tx1140\tx2300\tx3440\tx4600\tx5760\tx6900\tx8060\tx9200\tx10360\tx11520 // ! 192: \f1\b\fs28 called from ! 193: \f0\b0\fs24 :\ ! 194: // en_jam, timeout() callout after "I give up"\ ! 195: // untimeout()'d in encontrol( ! 196: \pard\tx1152\tx2304\tx3456\tx4608\tx5760\tx6912\tx8064\tx9216\tx10368\tx11520\fc0 IFCONTROL_SETFLAGS ! 197: \pard\tx1140\tx2300\tx3440\tx4600\tx5760\tx6900\tx8060\tx9200\tx10360\tx11520 );\ ! 198: ! 199: \pard\tx1152\tx2304\tx3456\tx4608\tx5760\tx6912\tx8064\tx9216\tx10368\tx11520\fc0 \{\ ! 200: clear jammed flag;\ ! 201: huh???\ ! 202: \}\ ! 203: \ ! 204: int en_jam(struct en_softc *is)\ ! 205: ! 206: \pard\tx1140\tx2300\tx3440\tx4600\tx5760\tx6900\tx8060\tx9200\tx10360\tx11520 // ! 207: \f1\b\fs28 called from ! 208: \f0\b0\fs24 :\ ! 209: // timeout() callout from enstart();\ ! 210: ! 211: \fc0 // tx_intr, on "no heartbeat detect" ! 212: \ ! 213: ! 214: \pard\tx1152\tx2304\tx3456\tx4608\tx5760\tx6912\tx8064\tx9216\tx10368\tx11520\fc0 \{\ ! 215: if thin wire mode \{\ ! 216: if heartbeat on TPE \{\ ! 217: select TPE;\ ! 218: return OK;\ ! 219: \}\ ! 220: \}\ ! 221: else \{\ ! 222: if heartbeat\ ! 223: return OK (Huh???)\ ! 224: \}\ ! 225: log error message;\ ! 226: en_down();\ ! 227: enable en_antijam() timeout;\ ! 228: return error;\ ! 229: \} \ ! 230: \ ! 231: void en_tx_dmaintr(int unit)\ ! 232: ! 233: \pard\tx1140\tx2300\tx3440\tx4600\tx5760\tx6900\tx8060\tx9200\tx10360\tx11520 // ! 234: \f1\b\fs28 called from ! 235: \f0\b0\fs24 :\ ! 236: // DMA interrupt handler\ ! 237: ! 238: \pard\tx1152\tx2304\tx3456\tx4608\tx5760\tx6912\tx8064\tx9216\tx10368\tx11520\fc0 \{\ ! 239: disable en_jam timeout;\ ! 240: while(dhp = dma_dequeue()) \{\ ! 241: if any DMA channel errors \{\ ! 242: dma_enqueue() this dhp;\ ! 243: return;\ ! 244: \}\ ! 245: ! 246: \pard\tx1140\tx2300\tx3440\tx4600\tx5760\tx6900\tx8060\tx9200\tx10360\tx11520\fc0 if > 16 collision error \{\ ! 247: if_oerrors_set();\ ! 248: if jam_count exceeded and not currently jammed \{\ ! 249: if(en_jam())\ ! 250: goto out;\ ! 251: \}\ ! 252: dma_enqueue this dhp as a retry;\ ! 253: return;\ ! 254: \}\ ! 255: if TPE \{\ ! 256: if en_rx timeout exceeded \{\ ! 257: /* huh??? this is tx... */\ ! 258: if(en_jam()) \{\ ! 259: dma_enqueue this hdr;\ ! 260: return;\ ! 261: \}\ ! 262: \}\ ! 263: \}\ ! 264: out:\ ! 265: if_busfree(dhp);\ ! 266: enqueue this dhp on is_tx_free;\ ! 267: ! 268: \pard\tx1152\tx2304\tx3456\tx4608\tx5760\tx6912\tx8064\tx9216\tx10368\tx11520\fc0 \}\ ! 269: \ ! 270: return;\ ! 271: \}\ ! 272: \ ! 273: int encontrol(netif_t netif,\ ! 274: const char *command,\ ! 275: void *data)\ ! 276: ! 277: \pard\tx1140\tx2300\tx3440\tx4600\tx5760\tx6900\tx8060\tx9200\tx10360\tx11520 // ! 278: \f1\b\fs28 called from ! 279: \f0\b0\fs24 :\ ! 280: // higher level protocol, registered in if_attaach()\ ! 281: ! 282: \pard\tx1152\tx2304\tx3456\tx4608\tx5760\tx6912\tx8064\tx9216\tx10368\tx11520\fc0 \{\ ! 283: misc crufty stuff;\ ! 284: \}\ ! 285: \ ! 286: \ ! 287: ! 288: \f1\b\fs28 Notes ! 289: \f0\b0\fs24 \ ! 290: \ ! 291: 1. We should probably NOT use ifnet, ONLY netif_t. Get ptr to local \ ! 292: data (or an id) from the "void *if_private(netif_t netif)" \ ! 293: function in netif.\ ! 294: \ ! 295: 2. headers, buffers, and stuff\ ! 296: \ ! 297: struct mbuf \{\ ! 298: struct mbuf *m_next; /* next buffer in chain */\ ! 299: u_long m_off; /* offset of data */\ ! 300: short m_len; /* amount of data in this mbuf */\ ! 301: short m_type; /* mbuf type (0 == free) */\ ! 302: union \{\ ! 303: u_char mun_dat[MLEN]; /* data storage */\ ! 304: struct \{\ ! 305: short mun_cltype; /* "cluster" type */\ ! 306: int (*mun_clfun)();\ ! 307: int mun_clarg;\ ! 308: int (*mun_clswp)();\ ! 309: \} mun_cl;\ ! 310: \} m_un;\ ! 311: struct mbuf *m_act; /* link in higher-level mbuf list */\ ! 312: \};\ ! 313: \ ! 314: struct dma_hdr \{\ ! 315: struct dma_hdr *volatile dh_link;/* pts to next dma_hdr in chain */\ ! 316: char *dh_start; /* pts to start of buffer for dma */\ ! 317: char *dh_stop; /* pts to end of buffer + 1 for dma */\ ! 318: volatile int dh_flags; /* see below */\ ! 319: volatile int dh_state; /* csr at time of dma interrupt */\ ! 320: char *volatile dh_next; /* next at time of dma interrupt */\ ! 321: int dh_drvarg; /* for use by driver */\ ! 322: \};\ ! 323: \ ! 324: struct ether_header \{\ ! 325: u_char ether_dhost[6];\ ! 326: u_char ether_shost[6];\ ! 327: u_short ether_type;\ ! 328: \};\ ! 329: \ ! 330: actual ethernet packet \{\ ! 331: /* \ ! 332: * physically contiguous memory.\ ! 333: * On TX, \ ! 334: */\ ! 335: struct ether_header hdr;\ ! 336: some data;\ ! 337: \}\ ! 338: \ ! 339: struct enbuf \{\ ! 340: union \{\ ! 341: struct enbuf *Uenb_next;\ ! 342: char Uenb_data[BUF_SIZE];\ ! 343: \} Uenbuf;\ ! 344: \};\ ! 345: \ ! 346: enoutput():\ ! 347: \ ! 348: Currently, it's actually passed an mbuf, although this is declared\ ! 349: as a netbuf_t (opaque).\ ! 350: \ ! 351: ðer_header = mbuf->m_off.\ ! 352: \ ! 353: enstart():\ ! 354: This is a total hack. We get an mbuf via IF_DEQUEUE, which should\ ! 355: not be visible to us. Then we cast the mbuf to a netbuf_t. We get\ ! 356: the size of the mbuf via nb_size() (which is legal). Then we cast\ ! 357: a DMA header (which we get from is_tx_free) to a en_dma_buf_t and\ ! 358: pass it to if_busalloc().\ ! 359: ! 360: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.