* added 0.99 linux version
[mascara-docs.git] / i386 / linux / linux-2.3.21 / drivers / ap1000 / mac.c
blob8e85ff555adeef694701aacda63ba738c9b95dfe
1 /*
2 * Copyright 1996 The Australian National University.
3 * Copyright 1996 Fujitsu Laboratories Limited
4 *
5 * This software may be distributed under the terms of the Gnu
6 * Public License version 2 or later
7 */
8 /*
9 * Routines for controlling the FORMAC+
11 #include <linux/types.h>
12 #include <linux/string.h>
13 #include <linux/kernel.h>
14 #include <linux/skbuff.h>
15 #include <linux/interrupt.h>
16 #include <linux/if_ether.h> /* For the statistics structure. */
17 #include <linux/netdevice.h>
18 #include <linux/if_arp.h>
19 #include <linux/inet.h>
20 #include <net/sock.h>
22 #include <asm/ap1000/apreg.h>
23 #include <asm/ap1000/apservice.h>
24 #include <asm/pgtable.h>
26 #include "apfddi.h"
27 #include "smt-types.h"
28 #include "am79c830.h"
29 #include "mac.h"
30 #include "plc.h"
31 #include "apfddi-reg.h"
33 #define MAC_DEBUG 0
35 /* Values for dma_state */
36 #define IDLE 0
37 #define XMITTING 1
38 #define RECVING 2
41 * Messages greater than this value are transferred to the FDDI send buffer
42 * using DMA.
44 #define DMA_XMIT_THRESHOLD 64
45 #define DMA_RECV_THRESHOLD 64
48 * If the FDDI receive buffer is occupied by less than this value, then
49 * sending has priority.
51 #define RECV_THRESHOLD (20*1024)
53 #define DMA_RESET_MASKS ((AP_CLR_INTR_MASK<<DMA_INTR_NORMAL_SH) | \
54 (AP_CLR_INTR_MASK<<DMA_INTR_ERROR_SH))
56 #define DMA_INTR_REQS ((AP_INTR_REQ<<DMA_INTR_NORMAL_SH) | \
57 (AP_INTR_REQ<<DMA_INTR_ERROR_SH))
59 static void mac_print_state(void);
61 typedef unsigned int mac_status_t;
63 static volatile struct mac_queue *mac_queue_top = NULL;
64 static volatile struct mac_queue *mac_queue_bottom = NULL;
66 struct formac_state {
67 LoopbackType loopback;
68 int ring_op;
69 int recv_ptr;
70 int recv_empty;
71 int recv_ovf;
72 int xmit_ptr;
73 int xmit_free;
74 int xmit_start;
75 int xmit_chains;
76 int xmit_more_ptr;
77 int frames_xmitted;
78 int xmit_chain_start[3];
79 int frames_recvd;
80 int recv_aborted;
81 int xmit_aborted;
82 int wrong_bb;
83 int recv_error;
84 volatile struct mac_queue *cur_macq; /* Current queue el for send DMA */
85 volatile struct mac_buf cur_mbuf; /* Current mac_buf for send DMA */
86 struct sk_buff *cur_skb; /* skb for received packets by DMA */
87 int dma_state;
90 #define SPFRAMES_SIZE 64 /* # words for special frames area */
91 #define RECV_BUF_START SPFRAMES_SIZE
92 #define RECV_BUF_END (BUFFER_SIZE / 2 + 2048)
93 #define RECV_BUF_SIZE (RECV_BUF_END - RECV_BUF_START)
94 #define XMIT_BUF_START RECV_BUF_END
95 #define XMIT_BUF_END BUFFER_SIZE
97 #define S2_RMT_EVENTS (S2_CLAIM_STATE | S2_MY_CLAIM | S2_HIGHER_CLAIM | \
98 S2_LOWER_CLAIM | S2_BEACON_STATE | S2_MY_BEACON | \
99 S2_OTHER_BEACON | S2_RING_OP | S2_MULTIPLE_DA | \
100 S2_TOKEN_ERR | S2_DUPL_CLAIM | S2_TRT_EXP_RECOV)
102 struct mac_info *this_mac_info;
103 struct formac_state this_mac_state;
106 mac_init(struct mac_info *mip)
108 struct formac_state *msp = &this_mac_state;
110 bif_add_debug_key('f',mac_print_state,"show FDDI mac state");
112 this_mac_info = mip;
114 mac->cmdreg1 = C1_SOFTWARE_RESET;
115 mac->said = (mip->s_address[0] << 8) + mip->s_address[1];
116 mac->laim = (mip->l_address[0] << 8) + mip->l_address[1];
117 mac->laic = (mip->l_address[2] << 8) + mip->l_address[3];
118 mac->lail = (mip->l_address[4] << 8) + mip->l_address[5];
119 mac->sagp = (mip->s_group_adrs[0] << 8) + mip->s_group_adrs[1];
120 mac->lagm = (mip->l_group_adrs[0] << 8) + mip->l_group_adrs[1];
121 mac->lagc = (mip->l_group_adrs[2] << 8) + mip->l_group_adrs[3];
122 mac->lagl = (mip->l_group_adrs[4] << 8) + mip->l_group_adrs[5];
123 mac->tmax = mip->tmax >> 5;
124 mac->tvx = (mip->tvx - 254) / 255; /* it's -ve, round downwards */
125 mac->treq0 = mip->treq;
126 mac->treq1 = mip->treq >> 16;
127 mac->pri0 = ~0;
128 mac->pri1 = ~0;
129 mac->pri2 = ~0;
130 mac->mdreg2 = /*M2_STRIP_FCS +*/ M2_CHECK_PARITY + M2_EVEN_PARITY
131 + 3 * M2_RCV_BYTE_BDRY + M2_ENABLE_HSREQ
132 + M2_ENABLE_NPDMA + M2_SYNC_NPDMA + M2_RECV_BAD_FRAMES;
133 mac->eacb = RECV_BUF_START - 1;
134 mac->earv = XMIT_BUF_START - 1;
135 mac->eas = mac->earv;
136 mac->eaa0 = BUFFER_SIZE - 1;
137 mac->eaa1 = mac->eaa0;
138 mac->eaa2 = mac->eaa1;
139 mac->wpxsf = 0;
140 mac->rpr = RECV_BUF_START;
141 mac->wpr = RECV_BUF_START + 1;
142 mac->swpr = RECV_BUF_START;
143 mac->wpxs = mac->eas;
144 mac->swpxs = mac->eas;
145 mac->rpxs = mac->eas;
146 mac->wpxa0 = XMIT_BUF_START;
147 mac->rpxa0 = XMIT_BUF_START;
149 memset(msp, 0, sizeof(*msp));
150 msp->recv_ptr = RECV_BUF_START;
151 msp->recv_empty = 1;
152 msp->xmit_ptr = XMIT_BUF_START;
153 msp->xmit_free = XMIT_BUF_START + 1;
154 msp->xmit_start = XMIT_BUF_START;
155 msp->xmit_chains = 0;
156 msp->frames_xmitted = 0;
157 msp->frames_recvd = 0;
158 msp->recv_aborted = 0;
160 mac->mdreg1 = M1_MODE_MEMORY;
162 mac_make_spframes();
164 return 0;
168 mac_inited(struct mac_info *mip)
170 struct formac_state *msp = &this_mac_state;
171 mac_status_t st1, st2;
173 if (mac->said != (mip->s_address[0] << 8) + mip->s_address[1]
174 || mac->laim != (mip->l_address[0] << 8) + mip->l_address[1]
175 || mac->laic != (mip->l_address[2] << 8) + mip->l_address[3]
176 || mac->lail != (mip->l_address[4] << 8) + mip->l_address[5]
177 || mac->sagp != (mip->s_group_adrs[0] << 8) + mip->s_group_adrs[1]
178 || mac->lagm != (mip->l_group_adrs[0] << 8) + mip->l_group_adrs[1]
179 || mac->lagc != (mip->l_group_adrs[2] << 8) + mip->l_group_adrs[3]
180 || mac->lagl != (mip->l_group_adrs[4] << 8) + mip->l_group_adrs[5])
181 return 1;
182 if ((mac->mdreg1 & ~M1_ADDET) != (M1_MODE_ONLINE | M1_SELECT_RA
183 | M1_FULL_DUPLEX))
184 return 3;
185 if (mac->treq0 != (mip->treq & 0xffff)
186 || mac->treq1 != ((unsigned)mip->treq >> 16))
187 return 4;
189 st1 = (mac->st1u << 16) + mac->st1l;
190 st2 = (mac->st2u << 16) + mac->st2l;
191 if ((st2 & S2_RING_OP) == 0)
192 return 5;
194 /* It's probably OK, reset some things to be safe. */
195 this_mac_info = mip;
196 *csr0 &= ~CS0_HREQ;
197 mac->tmax = mip->tmax >> 5;
198 mac->tvx = (mip->tvx - 254) / 255; /* it's -ve, round downwards */
199 mac->pri0 = ~0;
200 mac->pri1 = ~0;
201 mac->pri2 = ~0;
202 mac->mdreg2 = /*M2_STRIP_FCS +*/ M2_CHECK_PARITY + M2_EVEN_PARITY
203 + 3 * M2_RCV_BYTE_BDRY + M2_ENABLE_HSREQ
204 + M2_ENABLE_NPDMA + M2_SYNC_NPDMA + M2_RECV_BAD_FRAMES;
206 /* clear out the receive queue */
207 mac->mdreg1 = (mac->mdreg1 & ~M1_ADDET) | M1_ADDET_DISABLE_RECV;
208 mac->rpr = RECV_BUF_START;
209 mac->wpr = RECV_BUF_START + 1;
210 mac->swpr = RECV_BUF_START;
212 memset(msp, 0, sizeof(*msp));
213 msp->recv_ptr = RECV_BUF_START;
214 msp->recv_empty = 1;
216 /* XXX reset transmit pointers */
217 mac->cmdreg2 = C2_ABORT_XMIT;
218 mac->cmdreg2 = C2_RESET_XMITQS;
219 mac->wpxa0 = XMIT_BUF_START;
220 mac->rpxa0 = XMIT_BUF_START;
221 msp->xmit_ptr = XMIT_BUF_START;
222 msp->xmit_free = XMIT_BUF_START + 1;
223 msp->xmit_start = XMIT_BUF_START;
224 msp->xmit_chains = 0;
226 mac_make_spframes();
227 mac->cmdreg1 = C1_CLR_ALL_LOCKS;
229 msp->frames_xmitted = 0;
230 msp->frames_recvd = 0;
231 msp->recv_aborted = 0;
232 msp->ring_op = 1;
234 mac->mdreg1 = (mac->mdreg1 & ~M1_ADDET) | M1_ADDET_NSA;
235 mac->imsk1u = ~(S1_XMIT_ABORT | S1_END_FRAME_ASYNC0) >> 16;
236 mac->imsk1l = ~(S1_PAR_ERROR_ASYNC0 | S1_QUEUE_LOCK_ASYNC0);
237 mac->imsk2u = ~(S2_RECV_COMPLETE | S2_RECV_BUF_FULL | S2_RECV_FIFO_OVF
238 | S2_ERR_SPECIAL_FR | S2_RMT_EVENTS
239 | S2_NP_SIMULT_LOAD) >> 16;
240 mac->imsk2l = ~(S2_RMT_EVENTS | S2_MISSED_FRAME);
242 return 0;
245 void mac_make_spframes(void)
247 volatile int *bp;
248 struct mac_info *mip = this_mac_info;
249 int sa;
250 struct formac_state *msp = &this_mac_state;
252 /* initialize memory to avoid parity errors */
253 *csr0 &= ~CS0_HREQ;
254 *csr1 &= ~CS1_BUF_WR_TAG;
255 for (bp = &buffer_mem[BUFFER_SIZE]; bp > &buffer_mem[XMIT_BUF_START];)
256 *--bp = 0xdeadbeef;
257 for (; bp > buffer_mem;)
258 *--bp = 0xfeedf00d;
259 buffer_mem[msp->recv_ptr] = 0;
261 bp = buffer_mem;
262 *bp++ = 0; /* auto-void frame pointer (not used) */
264 /* make claim frame */
265 sa = bp - buffer_mem;
266 *bp++ = 0xd8000011; /* claim frame descr. + length */
267 *bp++ = 0xc3; /* FC value for claim frame, long addr */
268 *bp++ = (mip->l_address[0] << 24) + (mip->l_address[1] << 16)
269 + (mip->l_address[2] << 8) + mip->l_address[3];
270 *bp++ = (mip->l_address[4] << 24) + (mip->l_address[5] << 16)
271 + (mip->l_address[0] << 8) + mip->l_address[1];
272 *bp++ = (mip->l_address[2] << 24) + (mip->l_address[3] << 16)
273 + (mip->l_address[4] << 8) + mip->l_address[5];
274 *bp++ = mip->treq;
275 mac->sacl = bp - buffer_mem; /* points to pointer to claim frame */
276 *bp++ = 0xa0000000 + sa; /* pointer to start of claim frame */
278 /* make beacon frame */
279 sa = bp - buffer_mem;
280 *bp++ = 0xd8000011; /* beacon frame descr. + length */
281 *bp++ = 0xc2; /* FC value for beacon frame, long addr */
282 *bp++ = 0; /* DA = 0 */
283 *bp++ = (mip->l_address[0] << 8) + mip->l_address[1];
284 *bp++ = (mip->l_address[2] << 24) + (mip->l_address[3] << 16)
285 + (mip->l_address[4] << 8) + mip->l_address[5];
286 *bp++ = 0; /* beacon reason = failed claim */
287 mac->sabc = bp - buffer_mem;
288 *bp++ = 0xa0000000 + sa; /* pointer to start of beacon frame */
291 void mac_reset(LoopbackType loopback)
293 int mode;
294 struct formac_state *msp = &this_mac_state;
296 msp->loopback = loopback;
297 switch (loopback) {
298 case loop_none:
299 mode = M1_MODE_ONLINE;
300 break;
301 case loop_formac:
302 mode = M1_MODE_INT_LOOP;
303 break;
304 default:
305 mode = M1_MODE_EXT_LOOP;
306 break;
308 mac->mdreg1 = mode | M1_ADDET_NSA | M1_SELECT_RA | M1_FULL_DUPLEX;
309 mac->cmdreg1 = C1_IDLE_LISTEN;
310 mac->cmdreg1 = C1_CLR_ALL_LOCKS;
311 mac->imsk1u = ~(S1_XMIT_ABORT | S1_END_FRAME_ASYNC0) >> 16;
312 mac->imsk1l = ~(S1_PAR_ERROR_ASYNC0 | S1_QUEUE_LOCK_ASYNC0);
313 mac->imsk2u = ~(S2_RECV_COMPLETE | S2_RECV_BUF_FULL | S2_RECV_FIFO_OVF
314 | S2_ERR_SPECIAL_FR | S2_RMT_EVENTS
315 | S2_NP_SIMULT_LOAD) >> 16;
316 mac->imsk2l = ~(S2_RMT_EVENTS | S2_MISSED_FRAME);
319 void mac_claim(void)
321 mac->cmdreg1 = C1_CLAIM_LISTEN;
324 void mac_disable(void)
326 mac->mdreg1 = M1_MODE_MEMORY;
327 mac->imsk1u = ~0;
328 mac->imsk1l = ~0;
329 mac->imsk2u = ~0;
330 mac->imsk2l = ~0;
331 mac->wpr = mac->swpr + 1;
332 if (mac->wpr > mac->earv)
333 mac->wpr = mac->eacb + 1;
334 buffer_mem[mac->swpr] = 0;
337 void mac_stats(void)
339 struct formac_state *msp = &this_mac_state;
341 if (msp->recv_ovf)
342 printk("%d receive buffer overflows\n", msp->recv_ovf);
343 if (msp->wrong_bb)
344 printk("%d frames on wrong byte bdry\n", msp->wrong_bb);
345 printk("%d frames transmitted, %d aborted\n", msp->frames_xmitted,
346 msp->xmit_aborted);
347 printk("%d frames received, %d aborted\n", msp->frames_recvd,
348 msp->recv_aborted);
349 printk("%d frames received with errors\n", msp->recv_error);
352 void mac_sleep(void)
354 /* disable the receiver */
355 mac->mdreg1 = (mac->mdreg1 & ~M1_ADDET) | M1_ADDET_DISABLE_RECV;
358 void mac_poll(void)
360 mac_status_t st1, st2;
361 struct formac_state *msp = &this_mac_state;
362 int up, f, d, l, r, e, i;
364 st1 = (mac->st1u << 16) + mac->st1l;
365 st2 = (mac->st2u << 16) + mac->st2l;
367 if (st2 & S2_NP_SIMULT_LOAD)
368 panic("NP/formac simultaneous load!!!");
370 up = (st2 & S2_RING_OP) != 0;
371 if (up != msp->ring_op) {
372 /* ring has come up or down */
373 msp->ring_op = up;
374 printk("mac: ring %s\n", up? "up": "down");
375 set_ring_op(up);
378 if (up) {
379 if (st1 & S1_XMIT_ABORT) {
380 ++msp->xmit_aborted;
381 if (st1 & S1_QUEUE_LOCK_ASYNC0) {
382 printk("mac: xmit queue locked, resetting xmit buffer\n");
383 mac->cmdreg2 = C2_RESET_XMITQS; /* XXX bit gross */
384 mac->rpxa0 = XMIT_BUF_START;
385 buffer_mem[XMIT_BUF_START] = 0;
386 msp->xmit_ptr = XMIT_BUF_START;
387 msp->xmit_start = XMIT_BUF_START;
388 msp->xmit_chains = 0;
389 mac->cmdreg1 = C1_CLR_ASYNCQ0_LOCK;
390 st1 &= ~(S1_END_CHAIN_ASYNC0 | S1_END_FRAME_ASYNC0
391 | S1_XINSTR_FULL_ASYNC0);
392 } else
393 st1 |= S1_END_FRAME_ASYNC0;
394 } else if (st1 & S1_QUEUE_LOCK_ASYNC0) {
395 printk("mac: xmit queue locked, why?\n");
396 mac->cmdreg1 = C1_CLR_ASYNCQ0_LOCK;
399 if (st1 & S1_END_FRAME_ASYNC0) {
400 /* advance xmit_start */
401 e = msp->xmit_start;
402 while (e != msp->xmit_ptr) {
403 /* find the end of the current frame */
404 f = buffer_mem[e]; /* read pointer */
405 if (f == 0)
406 break; /* huh?? */
407 f &= 0xffff;
408 d = buffer_mem[f]; /* read descriptor */
409 l = ((d & 0xffff) + ((d >> TD_BYTE_BDRY_LG) & 3) + 3) >> 2;
410 e = f + 1 + l; /* index of ptr at end of frame */
411 r = mac->rpxa0;
412 if ((r <= msp->xmit_ptr && r < e && e <= msp->xmit_ptr)
413 || (r > msp->xmit_ptr && (r < e || e <= msp->xmit_ptr)))
414 break; /* up to current frame */
415 /* printk("frame @ %x done\n", msp->xmit_start); */
416 msp->xmit_start = e;
417 if ((st1 & S1_XMIT_ABORT) == 0)
418 ++msp->frames_xmitted;
419 if ((msp->xmit_chains == 1 && e == msp->xmit_ptr) ||
420 (msp->xmit_chains > 1 && e == msp->xmit_chain_start[1])) {
421 /* we've finished chain 0 */
422 --msp->xmit_chains;
423 for (i = 0; i < msp->xmit_chains; ++i)
424 msp->xmit_chain_start[i] = msp->xmit_chain_start[i+1];
425 if (msp->xmit_chains >= 2) {
426 mac->cmdreg2 = C2_XMIT_ASYNCQ0;
427 /* printk("mac_poll: xmit chain\n"); */
429 if (msp->xmit_chains == 0)
430 *csr0 &= ~CS0_LED1;
434 * Now that we have a bit more space in the transmit buffer,
435 * see if we want to put another frame in.
437 #if MAC_DEBUG
438 printk("Removed space in transmit buffer.\n");
439 #endif
440 mac_process();
444 if (st2 & S2_RMT_EVENTS) {
445 rmt_event(st2);
448 if (st2 & S2_RECV_COMPLETE) {
450 * A frame has just finished arriving in the receive buffer.
452 *csr0 |= CS0_LED2;
453 msp->recv_empty = 0;
454 #if MAC_DEBUG
455 printk("Frame has just trickled in...\n");
456 #endif
457 mac_process();
460 if (st2 & S2_RECV_BUF_FULL) {
462 * receive buffer overflow: reset and unlock the receive buffer.
464 /* printk("mac: receive buffer full\n"); */
465 mac->rpr = RECV_BUF_START;
466 mac->wpr = RECV_BUF_START + 1;
467 mac->swpr = RECV_BUF_START;
468 msp->recv_ptr = RECV_BUF_START;
469 msp->recv_empty = 1;
470 buffer_mem[RECV_BUF_START] = 0;
471 mac->cmdreg1 = C1_CLR_RECVQ_LOCK;
472 ++msp->recv_ovf;
474 #if 0
475 } else if (st2 & S2_RECV_FIFO_OVF) {
476 printk("mac: receive FIFO overflow\n");
477 /* any further action required here? */
479 } else if (st2 & S2_MISSED_FRAME) {
480 printk("mac: missed frame\n");
481 #endif
484 if (st2 & S2_ERR_SPECIAL_FR) {
485 printk("mac: bug: error in special frame\n");
486 mac_disable();
490 void
491 mac_xmit_alloc(sp, bb)
492 struct mac_buf *sp;
493 int bb;
495 int nwords;
497 nwords = (sp->length + bb + 3) >> 2;
498 sp->fr_start = mac_xalloc(nwords + 2);
499 sp->fr_end = sp->fr_start + nwords + 1;
500 sp->ptr = (char *) &buffer_mem[sp->fr_start + 1] + bb;
501 buffer_mem[sp->fr_start] = TD_MAGIC + (bb << TD_BYTE_BDRY_LG) + sp->length;
504 void
505 mac_queue_frame(sp)
506 struct mac_buf *sp;
508 struct formac_state *msp = &this_mac_state;
510 buffer_mem[sp->fr_end] = 0; /* null pointer at end of frame */
511 buffer_mem[msp->xmit_ptr] = PT_MAGIC + sp->fr_start;
512 if (msp->xmit_chains <= 2) {
513 msp->xmit_chain_start[msp->xmit_chains] = msp->xmit_ptr;
514 if (msp->xmit_chains < 2)
515 mac->cmdreg2 = C2_XMIT_ASYNCQ0;
516 ++msp->xmit_chains;
517 } else {
518 buffer_mem[msp->xmit_more_ptr] |= TD_MORE;
520 msp->xmit_ptr = sp->fr_end;
521 msp->xmit_more_ptr = sp->fr_start;
522 *csr0 |= CS0_LED1;
526 mac_xalloc(int nwords)
528 int fr_start;
529 struct formac_state *msp = &this_mac_state;
532 * Find some room in the transmit buffer.
534 fr_start = msp->xmit_free;
535 if (fr_start > msp->xmit_start) {
536 if (fr_start + nwords > XMIT_BUF_END) {
537 /* no space at end - see if we can start again from the front */
538 fr_start = XMIT_BUF_START;
539 if (fr_start + nwords > msp->xmit_start)
540 panic("no space in xmit buffer (1)");
542 } else {
543 if (fr_start + nwords > msp->xmit_start)
544 panic("no space in xmit buffer (2)");
547 msp->xmit_free = fr_start + nwords;
549 return fr_start;
553 mac_recv_frame(sp)
554 struct mac_buf *sp;
556 struct formac_state *msp = &this_mac_state;
557 int status, bb, orig_recv_ptr;
559 orig_recv_ptr = msp->recv_ptr;
560 for (;;) {
561 status = buffer_mem[msp->recv_ptr];
562 if ((status & RS_VALID) == 0) {
563 if (status != 0) {
564 printk("recv buf out of sync: recv_ptr=%x status=%x\n",
565 msp->recv_ptr, status);
566 printk(" rpr=%x swpr=%x, buf[rpr]=%x\n", mac->rpr, mac->swpr,
567 buffer_mem[mac->rpr]);
568 msp->recv_ptr = mac->swpr;
570 *csr0 &= ~CS0_LED2;
571 msp->recv_empty = 1;
572 if (mac->rpr == orig_recv_ptr)
573 mac->rpr = msp->recv_ptr;
574 return 0;
576 if (status & RS_ABORTED)
577 ++msp->recv_aborted;
578 else {
579 bb = (status >> RS_BYTE_BDRY_LG) & 3;
580 if (bb != 3) {
581 ++msp->wrong_bb;
582 bb = 3;
584 if ((status & RS_ERROR) == 0)
585 break;
586 ++msp->recv_error;
587 msp->recv_ptr += NWORDS((status & RS_LENGTH) + bb);
589 if (++msp->recv_ptr >= RECV_BUF_END)
590 msp->recv_ptr -= RECV_BUF_SIZE;
592 ++msp->frames_recvd;
593 if (mac->rpr == orig_recv_ptr)
594 mac->rpr = msp->recv_ptr;
596 sp->fr_start = msp->recv_ptr;
597 sp->length = (status & RS_LENGTH) + bb; /* + 4 (status) - 4 (FCS) */
598 sp->ptr = (void *) &buffer_mem[sp->fr_start];
599 if ((msp->recv_ptr += NWORDS(sp->length) + 1) >= RECV_BUF_END)
600 msp->recv_ptr -= RECV_BUF_SIZE;
601 sp->fr_end = msp->recv_ptr;
602 sp->wraplen = (RECV_BUF_END - sp->fr_start) * 4;
603 sp->wrapptr = (void *) &buffer_mem[RECV_BUF_START];
605 return 1;
608 void
609 mac_discard_frame(sp)
610 struct mac_buf *sp;
612 mac->rpr = sp->fr_end;
616 * Return the number of bytes free in the async 0 transmit queue.
619 mac_xmit_space(void)
621 struct formac_state *msp = &this_mac_state;
622 int nw;
624 if (msp->xmit_free > msp->xmit_start) {
625 nw = XMIT_BUF_END - msp->xmit_free;
626 if (nw < msp->xmit_start - XMIT_BUF_START)
627 nw = msp->xmit_start - XMIT_BUF_START;
628 } else
629 nw = msp->xmit_start - msp->xmit_free;
630 return nw <= 2? 0: (nw - 2) << 2;
634 * Return the number of bytes of frames available in the receive queue.
637 mac_recv_level(void)
639 int nw;
641 nw = mac->swpr - mac->rpr;
642 if (nw < 0)
643 nw += mac->earv - mac->eacb;
644 return nw << 2;
648 * Return 1 iff all transmission has been completed, 0 otherwise.
650 int mac_xmit_done(void)
652 struct formac_state *msp = &this_mac_state;
654 return msp->xmit_chains == 0;
658 * Append skbuff packet to queue.
660 int mac_queue_append (struct sk_buff *skb)
662 struct mac_queue *el;
663 unsigned flags;
664 save_flags(flags); cli();
666 #if MAC_DEBUG
667 printk("Appending queue element skb 0x%x\n", skb);
668 #endif
670 if ((el = (struct mac_queue *)kmalloc(sizeof(*el), GFP_ATOMIC)) == NULL) {
671 restore_flags(flags);
672 return 1;
674 el->next = NULL;
675 el->skb = skb;
677 if (mac_queue_top == NULL) {
678 mac_queue_top = mac_queue_bottom = el;
680 else {
681 mac_queue_bottom->next = el;
682 mac_queue_bottom = el;
684 restore_flags(flags);
685 return 0;
689 * If the packet originated from the same FDDI subnet as we are on,
690 * there is no need to perform checksumming as FDDI will does this
691 * us.
693 #define CHECK_IF_CHECKSUM_REQUIRED(skb) \
694 if ((skb)->protocol == ETH_P_IP) { \
695 extern struct cap_init cap_init; \
696 int *from_ip = (int *)((skb)->data+12); \
697 int *to_ip = (int *)((skb)->data+16); \
698 if ((*from_ip & cap_init.netmask) == (*to_ip & cap_init.netmask)) \
699 (skb)->ip_summed = CHECKSUM_UNNECESSARY; \
703 * Try to send and/or recv frames.
705 void mac_process(void)
707 volatile struct dma_chan *dma = (volatile struct dma_chan *) DMA3;
708 struct formac_state *msp = &this_mac_state;
709 struct mac_queue *el;
710 int nw=0, mrl = 0, fstart, send_buffer_full = 0;
711 unsigned flags;
713 save_flags(flags); cli();
715 #if MAC_DEBUG
716 printk("In mac_process()\n");
717 #endif
720 * Check if the DMA is being used.
722 if (msp->dma_state != IDLE) {
723 restore_flags(flags);
724 return;
727 while (mac_queue_top != NULL || /* Something to transmit */
728 (mrl = mac_recv_level()) > 0) { /* Frames in receive buffer */
729 send_buffer_full = 0;
730 #if MAC_DEBUG
731 printk("mac_process(): something to do... mqt %x mrl is %d\n",
732 mac_queue_top, mrl);
733 #endif
734 if (mac_queue_top != NULL && mrl < RECV_THRESHOLD) {
735 el = (struct mac_queue *)mac_queue_top;
738 * Check there is enough space in the FDDI send buffer.
740 if (mac_xmit_space() < el->skb->len) {
741 #if MAC_DEBUG
742 printk("process_queue(): FDDI send buffer is full\n");
743 #endif
744 send_buffer_full = 1;
746 else {
747 #if MAC_DEBUG
748 printk("mac_process(): sending a frame\n");
749 #endif
751 * Update mac_queue_top.
753 mac_queue_top = mac_queue_top->next;
756 * Allocate space in the FDDI send buffer.
758 msp->cur_mbuf.length = el->skb->len-3;
759 mac_xmit_alloc((struct mac_buf *)&msp->cur_mbuf, 3);
762 * If message size is greater than DMA_XMIT_THRESHOLD, send
763 * using DMA, otherwise use memcpy().
765 if (el->skb->len > DMA_XMIT_THRESHOLD) {
767 * Start the DMA.
769 #if MAC_DEBUG
770 printk("mac_process(): Starting send DMA...\n");
771 #endif
772 nw = msp->cur_mbuf.fr_end - msp->cur_mbuf.fr_start + 1;
773 mac->wpxa0 = msp->cur_mbuf.fr_start + 1;
775 *csr0 |= CS0_HREQ_WA0;
777 msp->cur_macq = el;
778 msp->dma_state = XMITTING;
779 dma->st = DMA_DMST_RST;
780 dma->st = DMA_RESET_MASKS;
781 dma->hskip = 1; /* skip = 0, count = 1 */
782 dma->vskip = 1; /* skip = 0, count = 1 */
783 dma->maddr = (u_char *)
784 mmu_v2p((unsigned long)el->skb->data);
785 dma->cmd = DMA_DCMD_ST + DMA_DCMD_TYP_AUTO +
786 DMA_DCMD_TD_MD + nw;
787 *csr0 &= ~CS0_DMA_RECV;
788 *csr0 |= CS0_DMA_ENABLE;
791 * Don't process any more packets since the DMA is
792 * being used.
794 break;
796 else { /* el->skb->len <= DMA_XMIT_THRESHOLD */
798 * Copy the data directly into the FDDI buffer.
800 #if MAC_DEBUG
801 printk("mac_proces(): Copying send data...\n");
802 #endif
803 memcpy(msp->cur_mbuf.ptr - 3, el->skb->data,
804 ROUND4(el->skb->len));
805 mac_queue_frame((struct mac_buf *)&msp->cur_mbuf);
806 dev_kfree_skb(el->skb);
807 kfree_s(el, sizeof(*el));
808 continue;
813 * We have reached here if there is not enough space in the
814 * send buffer. Try to receive some packets instead.
818 if (mac_recv_frame((struct mac_buf *)&msp->cur_mbuf)) {
819 volatile int fc, llc_header_word2;
820 int pkt_len = 0;
822 #if MAC_DEBUG
823 printk("mac_process(): Receiving frames...\n");
824 #endif
826 * Get the fc, note only word accesses are allowed from the
827 * FDDI buffers.
829 if (msp->cur_mbuf.wraplen > 4) {
830 fc = *(int *)(msp->cur_mbuf.ptr+4);
832 else {
834 * fc_word must be at the start of the FDDI buffer.
836 #if MAC_DEBUG
837 printk("Grabbed fc_word from wrapptr, wraplen %d\n",
838 msp->cur_mbuf.wraplen);
839 #endif
840 fc = *(int *)msp->cur_mbuf.wrapptr;
842 fc &= 0xff;
844 #if MAC_DEBUG
845 printk("fc is 0x%x\n", fc);
846 #endif
847 if (fc < 0x50 || fc > 0x57) {
848 mac_discard_frame((struct mac_buf *)&msp->cur_mbuf);
849 continue;
853 * Determine the size of the packet data and allocate a socket
854 * buffer.
856 pkt_len = msp->cur_mbuf.length - FDDI_HARDHDR_LEN;
857 #if MAC_DEBUG
858 printk("Packet of length %d\n", pkt_len);
859 #endif
860 msp->cur_skb = dev_alloc_skb(ROUND4(pkt_len));
862 if (msp->cur_skb == NULL) {
863 printk("mac_process(): Memory squeeze, dropping packet.\n");
864 apfddi_stats->rx_dropped++;
865 restore_flags(flags);
866 return;
868 msp->cur_skb->dev = apfddi_device;
871 * Hardware header isn't copied to skbuff.
873 msp->cur_skb->mac.raw = msp->cur_skb->data;
874 apfddi_stats->rx_packets++;
877 * Determine protocol from llc header.
879 if (msp->cur_mbuf.wraplen < FDDI_HARDHDR_LEN) {
880 llc_header_word2 = *(int *)(msp->cur_mbuf.wrapptr +
881 (FDDI_HARDHDR_LEN -
882 msp->cur_mbuf.wraplen - 4));
884 else {
885 llc_header_word2 = *(int *)(msp->cur_mbuf.ptr +
886 FDDI_HARDHDR_LEN - 4);
888 msp->cur_skb->protocol = llc_header_word2 & 0xFFFF;
889 #if MAC_DEBUG
890 printk("Got protocol 0x%x\n", msp->cur_skb->protocol);
891 #endif
894 * Copy data into socket buffer, which may be wrapped around the
895 * FDDI buffer. Use memcpy if the size of the data is less
896 * than DMA_RECV_THRESHOLD. Note if DMA is used, then wrap-
897 * arounds are handled automatically.
899 if (pkt_len < DMA_RECV_THRESHOLD) {
900 if (msp->cur_mbuf.length < msp->cur_mbuf.wraplen) {
901 memcpy(skb_put(msp->cur_skb, ROUND4(pkt_len)),
902 msp->cur_mbuf.ptr + FDDI_HARDHDR_LEN,
903 ROUND4(pkt_len));
905 else if (msp->cur_mbuf.wraplen < FDDI_HARDHDR_LEN) {
906 #if MAC_DEBUG
907 printk("Wrap case 2\n");
908 #endif
909 memcpy(skb_put(msp->cur_skb, ROUND4(pkt_len)),
910 msp->cur_mbuf.wrapptr +
911 (FDDI_HARDHDR_LEN - msp->cur_mbuf.wraplen),
912 ROUND4(pkt_len));
914 else {
915 #if MAC_DEBUG
916 printk("wrap case 3\n");
917 #endif
918 memcpy(skb_put(msp->cur_skb,
919 ROUND4(msp->cur_mbuf.wraplen-
920 FDDI_HARDHDR_LEN)),
921 msp->cur_mbuf.ptr + FDDI_HARDHDR_LEN,
922 ROUND4(msp->cur_mbuf.wraplen - FDDI_HARDHDR_LEN));
923 memcpy(skb_put(msp->cur_skb,
924 ROUND4(msp->cur_mbuf.length -
925 msp->cur_mbuf.wraplen)),
926 msp->cur_mbuf.wrapptr,
927 ROUND4(msp->cur_mbuf.length -
928 msp->cur_mbuf.wraplen));
931 #if MAC_DEBUG
932 if (msp->cur_skb->protocol == ETH_P_IP) {
933 dump_packet("apfddi_rx:", msp->cur_skb->data, pkt_len, 0);
935 else if (msp->cur_skb->protocol == ETH_P_ARP) {
936 struct arphdr *arp = (struct arphdr *)msp->cur_skb->data;
937 printk("arp->ar_op is 0x%x ar_hrd %d ar_pro 0x%x ar_hln %d ar_ln %d\n",
938 arp->ar_op, arp->ar_hrd, arp->ar_pro, arp->ar_hln,
939 arp->ar_pln);
940 printk("sender hardware address: %x:%x:%x:%x:%x:%x\n",
941 *((u_char *)msp->cur_skb->data+8),
942 *((u_char *)msp->cur_skb->data+9),
943 *((u_char *)msp->cur_skb->data+10),
944 *((u_char *)msp->cur_skb->data+11),
945 *((u_char *)msp->cur_skb->data+12),
946 *((u_char *)msp->cur_skb->data+13));
947 printk("sender IP number %d.%d.%d.%d\n",
948 *((u_char *)msp->cur_skb->data+14),
949 *((u_char *)msp->cur_skb->data+15),
950 *((u_char *)msp->cur_skb->data+16),
951 *((u_char *)msp->cur_skb->data+17));
952 printk("receiver hardware address: %x:%x:%x:%x:%x:%x\n",
953 *((u_char *)msp->cur_skb->data+18),
954 *((u_char *)msp->cur_skb->data+19),
955 *((u_char *)msp->cur_skb->data+20),
956 *((u_char *)msp->cur_skb->data+21),
957 *((u_char *)msp->cur_skb->data+22),
958 *((u_char *)msp->cur_skb->data+23));
959 printk("receiver IP number %d.%d.%d.%d\n",
960 *((u_char *)msp->cur_skb->data+24),
961 *((u_char *)msp->cur_skb->data+25),
962 *((u_char *)msp->cur_skb->data+26),
963 *((u_char *)msp->cur_skb->data+27));
965 #endif
966 CHECK_IF_CHECKSUM_REQUIRED(msp->cur_skb);
969 * Inform the network layer of the new packet.
971 #if MAC_DEBUG
972 printk("Calling netif_rx()\n");
973 #endif
974 netif_rx(msp->cur_skb);
977 * Remove frame from FDDI buffer.
979 mac_discard_frame((struct mac_buf *)&msp->cur_mbuf);
980 continue;
982 else {
984 * Set up dma and break.
986 #if MAC_DEBUG
987 printk("mac_process(): Starting receive DMA...\n");
988 #endif
989 nw = NWORDS(pkt_len);
990 msp->dma_state = RECVING;
991 *csr0 &= ~(CS0_HREQ | CS0_DMA_ENABLE);
992 /* *csr1 |= CS1_RESET_FIFO;
993 *csr1 &= ~CS1_RESET_FIFO; */
994 if ((*csr1 & CS1_FIFO_LEVEL) != 0) {
995 int x;
996 printk("fifo not empty! (csr1 = 0x%x) emptying...", *csr1);
997 do {
998 x = *fifo;
999 } while ((*csr1 & CS1_FIFO_LEVEL) != 0);
1000 printk("done\n");
1002 fstart = msp->cur_mbuf.fr_start + NWORDS(FDDI_HARDHDR_LEN);
1003 if (fstart >= RECV_BUF_END)
1004 fstart -= RECV_BUF_SIZE;
1005 mac->rpr = fstart;
1006 #if MAC_DEBUG
1007 printk("rpr=0x%x, nw=0x%x, stat=0x%x\n",
1008 mac->rpr, nw, buffer_mem[msp->cur_mbuf.fr_start]);
1009 #endif
1010 dma->st = DMA_DMST_RST;
1011 dma->st = DMA_RESET_MASKS;
1012 dma->hskip = 1; /* skip = 0, count = 1 */
1013 dma->vskip = 1; /* skip = 0, count = 1 */
1014 dma->maddr = (u_char *)
1015 mmu_v2p((unsigned long)
1016 skb_put(msp->cur_skb, ROUND4(pkt_len)));
1017 dma->cmd = DMA_DCMD_ST + DMA_DCMD_TYP_AUTO + DMA_DCMD_TD_DM
1018 + nw - 4;
1019 *csr0 |= CS0_HREQ_RECV | CS0_DMA_RECV;
1020 *csr0 |= CS0_DMA_ENABLE;
1021 #if MAC_DEBUG
1022 printk("mac_process(): DMA is away!\n");
1023 #endif
1024 break;
1027 else {
1028 #if MAC_DEBUG
1029 printk("mac_recv_frame failed\n");
1030 #endif
1031 if (msp->recv_empty && send_buffer_full)
1032 break;
1036 * Update mac_queue_bottom.
1038 if (mac_queue_top == NULL)
1039 mac_queue_bottom = NULL;
1041 #if MAC_DEBUG
1042 printk("End of mac_process()\n");
1043 #endif
1044 restore_flags(flags);
1048 #define DMA_IN(reg) (*(volatile unsigned *)(reg))
1049 #define DMA_OUT(reg,v) (*(volatile unsigned *)(reg) = (v))
1052 * DMA completion handler.
1054 void mac_dma_complete(void)
1056 volatile struct dma_chan *dma;
1057 struct formac_state *msp = &this_mac_state;
1058 unsigned a;
1060 a = DMA_IN(DMA3_DMST);
1061 if (!(a & DMA_INTR_REQS)) {
1062 if (msp->dma_state != IDLE && (a & DMA_DMST_AC) == 0) {
1063 printk("dma completed but no interrupt!\n");
1064 msp->dma_state = IDLE;
1066 return;
1069 DMA_OUT(DMA3_DMST,AP_CLR_INTR_REQ<<DMA_INTR_NORMAL_SH);
1070 DMA_OUT(DMA3_DMST,AP_CLR_INTR_REQ<<DMA_INTR_ERROR_SH);
1072 dma = (volatile struct dma_chan *) DMA3;
1074 #if MAC_DEBUG
1075 printk("In mac_dma_complete\n");
1076 #endif
1078 if (msp->dma_state == XMITTING && ((dma->st & DMA_DMST_AC) == 0)) {
1080 * Transmit DMA finished.
1082 int i = 20;
1083 #if MAC_DEBUG
1084 printk("In mac_dma_complete for transmit complete\n");
1085 #endif
1086 while (*csr1 & CS1_FIFO_LEVEL) {
1087 if (--i <= 0) {
1088 printk("csr0=0x%x csr1=0x%x: fifo not emptying\n", *csr0,
1089 *csr1);
1090 return;
1093 *csr0 &= ~(CS0_HREQ | CS0_DMA_ENABLE);
1094 msp->dma_state = IDLE;
1095 #if MAC_DEBUG
1096 printk("mac_dma_complete(): Calling mac_queue_frame\n");
1097 #endif
1098 mac_queue_frame((struct mac_buf *)&msp->cur_mbuf);
1099 dev_kfree_skb(msp->cur_macq->skb);
1100 kfree_s((struct mac_buf *)msp->cur_macq, sizeof(*(msp->cur_macq)));
1101 msp->cur_macq = NULL;
1102 #if MAC_DEBUG
1103 printk("mac_dma_complete(): Calling mac_process()\n");
1104 #endif
1105 mac_process();
1106 #if MAC_DEBUG
1107 printk("End of mac_dma_complete transmitting\n");
1108 #endif
1110 else if (msp->dma_state == RECVING && ((dma->st & DMA_DMST_AC) == 0)) {
1112 * Receive DMA finished. Copy the last four words from the
1113 * fifo into the buffer, after turning off the host requests.
1114 * We do this to avoid reading past the end of frame.
1116 int *ip, i;
1118 #if MAC_DEBUG
1119 printk("In mac_dma_complete for receive complete\n");
1120 #endif
1121 msp->dma_state = IDLE;
1122 ip = (int *)mmu_p2v((unsigned long)dma->cmaddr);
1124 #if MAC_DEBUG
1125 printk("ip is 0x%x, skb->data is 0x%x\n", ip, msp->cur_skb->data);
1126 #endif
1128 *csr0 &= ~(CS0_DMA_ENABLE | CS0_HREQ);
1130 for (i = 0; (*csr1 & CS1_FIFO_LEVEL); ++i)
1131 ip[i] = *fifo;
1132 if (i != 4)
1133 printk("mac_dma_complete(): not four words remaining in fifo?\n");
1134 #if MAC_DEBUG
1135 printk("Copied last four words out of fifo\n");
1136 #endif
1139 * Remove the frame from the FDDI receive buffer.
1141 mac_discard_frame((struct mac_buf *)&msp->cur_mbuf);
1143 CHECK_IF_CHECKSUM_REQUIRED(msp->cur_skb);
1146 * Now inject the packet into the network system.
1148 netif_rx(msp->cur_skb);
1150 #if MAC_DEBUG
1151 dump_packet("mac_dma_complete:", msp->cur_skb->data, 0, 0);
1152 #endif
1155 * Check if any more frames can be processed.
1157 mac_process();
1159 #if MAC_DEBUG
1160 printk("End of mac_dma_complete receiving\n");
1161 #endif
1163 #if MAC_DEBUG
1164 printk("End of mac_dma_complete()\n");
1165 #endif
1168 static void mac_print_state(void)
1170 struct formac_state *msp = &this_mac_state;
1172 printk("DMA3_DMST is 0x%x dma_state is %d\n", DMA_IN(DMA3_DMST),
1173 msp->dma_state);
1174 printk("csr0 = 0x%x, csr1 = 0x%x\n", *csr0, *csr1);