|
|
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.