source: rtems/bsps/lm32/shared/net/tsmac.c @ 762fa62

5
Last change on this file since 762fa62 was 031df391, checked in by Sebastian Huber <sebastian.huber@…>, on 04/23/18 at 07:53:31

bsps: Move legacy network drivers to bsps

This patch is a part of the BSP source reorganization.

Update #3285.

  • Property mode set to 100644
File size: 19.8 KB
Line 
1/*
2 *  This file contains definitions for LatticeMico32 TSMAC (Tri-Speed MAC)
3 *
4 *  COPYRIGHT (c) 1989-1999.
5 *  On-Line Applications Research Corporation (OAR).
6 *
7 *  The license and distribution terms for this file may be
8 *  found in the file LICENSE in this distribution or at
9 *  http://www.rtems.org/license/LICENSE.
10 *
11 *  Jukka Pietarinen <jukka.pietarinen@mrf.fi>, 2008,
12 *  Micro-Research Finland Oy
13 */
14
15#define __INSIDE_RTEMS_BSD_TCPIP_STACK__
16#define _KERNEL
17
18#include <rtems.h>
19#include <bsp.h>
20#include <stdio.h>
21#include <string.h>
22#include <errno.h>
23#include <rtems/error.h>
24#include <rtems/bspIo.h>
25#include <rtems/rtems_bsdnet.h>
26
27#include <sys/param.h>
28#include <sys/mbuf.h>
29#include <sys/socket.h>
30#include <sys/sockio.h>
31
32#include <net/if.h>
33
34#include <netinet/in.h>
35#include <netinet/if_ether.h>
36
37#include "../include/system_conf.h"
38#include "tsmac.h"
39#include "dp83848phy.h"
40
41struct tsmac_softc {
42  struct arpcom arpcom;
43  void *ioaddr;
44  rtems_id rxDaemonTid;
45  rtems_id txDaemonTid;
46
47  /*
48   * Statistics
49   */
50  int rxInterrupts;
51  int rxPktIgnore;
52  int rxLenCheckError;
53  int rxLongFrame;
54  int rxShortFrame;
55  int rxIPGViolation;
56  int rxCRCError;
57  int rxOKPackets;
58  int rxControlFrame;
59  int rxPauseFrame;
60  int rxMulticast;
61  int rxBroadcast;
62  int rxVLANTag;
63  int rxPreShrink;
64  int rxDribNib;
65  int rxUnsupOPCD;
66  int rxByteCnt;
67  int rxFifoFull;
68
69  int txInterrupts;
70  int txUnicast;
71  int txPauseFrame;
72  int txMulticast;
73  int txBroadcast;
74  int txVLANTag;
75  int txBadFCS;
76  int txJumboCnt;
77  int txByteCnt;
78  int txLostCarrier;
79  int txFifoFull;
80};
81
82/*
83 * Macros to access tsmac wrapper registers.
84 */
85
86static inline uint32_t tsmacread(unsigned int reg)
87{
88  return *((uint32_t *)(TS_MAC_CORE_BASE_ADDRESS + reg));
89}
90
91static inline void tsmacwrite(unsigned int reg, uint32_t value)
92{
93  *((uint32_t *)(TS_MAC_CORE_BASE_ADDRESS + reg)) = value;
94}
95
96/*
97 * tsmac is a wishbone to MAC wrapper.
98 * The macros below access to MAC registers.
99 */
100
101static inline uint16_t tsmacregread(unsigned int reg)
102{
103  tsmacwrite(LM32_TSMAC_MAC_REGS_ADDR_RW, reg);
104  return *((uint16_t *)(TS_MAC_CORE_BASE_ADDRESS + LM32_TSMAC_MAC_REGS_DATA + 2));
105}
106
107static inline void tsmacregwrite(unsigned int reg, uint16_t value)
108{
109  *((uint16_t *)(TS_MAC_CORE_BASE_ADDRESS + LM32_TSMAC_MAC_REGS_DATA + 2)) = value;
110  tsmacwrite(LM32_TSMAC_MAC_REGS_ADDR_RW, REGS_ADDR_WRITE | reg);
111}
112
113/*
114#define DEBUG 1
115*/
116
117/* We support one interface */
118
119#define TSMAC_NUM  1
120#define TSMAC_NAME "TSMAC"
121#define TSMAC_MAC0 0x00
122#define TSMAC_MAC1 0x0E
123#define TSMAC_MAC2 0xB2
124#define TSMAC_MAC3 0x00
125#define TSMAC_MAC4 0x00
126#define TSMAC_MAC5 0x01
127
128/*
129 *  The interrupt vector number associated with the tsmac device
130 *  driver.
131 */
132
133#define TSMAC_VECTOR    ( TS_MAC_CORE_IRQ )
134#define TSMAC_IRQMASK   ( 1 << TSMAC_VECTOR )
135
136rtems_isr tsmac_interrupt_handler(rtems_vector_number vector);
137
138extern rtems_isr_entry set_vector(rtems_isr_entry handler,
139                                 rtems_vector_number vector, int type);
140
141/*
142 * Macros to access PHY registers through the (G)MII
143 */
144
145uint16_t tsmacphyread(unsigned int reg)
146{
147  tsmacregwrite(LM32_TSMAC_GMII_MNG_CTL_BYTE0,
148                ((DEFAULT_PHY_ADDRESS & GMII_MNG_CTL_PHY_ADD_MASK) <<
149                 GMII_MNG_CTL_PHY_ADD_SHIFT) |
150                ((reg & GMII_MNG_CTL_REG_ADD_MASK) <<
151                 GMII_MNG_CTL_REG_ADD_SHIFT) |
152                GMII_MNG_CTL_READ_PHYREG);
153
154  /* Wait for management interface to be ready */
155  while(!(tsmacregread(LM32_TSMAC_GMII_MNG_CTL_BYTE0) & GMII_MNG_CTL_CMD_FIN));
156
157  return tsmacregread(LM32_TSMAC_GMII_MNG_DAT_BYTE0);
158}
159
160void tsmacphywrite(unsigned int reg, uint16_t value)
161{
162  tsmacregwrite(LM32_TSMAC_GMII_MNG_DAT_BYTE0, value);
163  tsmacregwrite(LM32_TSMAC_GMII_MNG_CTL_BYTE0,
164                ((DEFAULT_PHY_ADDRESS & GMII_MNG_CTL_PHY_ADD_MASK) <<
165                 GMII_MNG_CTL_PHY_ADD_SHIFT) |
166                ((reg & GMII_MNG_CTL_REG_ADD_MASK) <<
167                 GMII_MNG_CTL_REG_ADD_SHIFT) |
168                GMII_MNG_CTL_WRITE_PHYREG);
169
170  /* Wait for management interface to be ready */
171  while(!(tsmacregread(LM32_TSMAC_GMII_MNG_CTL_BYTE0) & GMII_MNG_CTL_CMD_FIN));
172}
173
174/*
175 * Event definitions
176 */
177#define INTERRUPT_EVENT      RTEMS_EVENT_1
178#define START_TRANSMIT_EVENT RTEMS_EVENT_2
179
180static struct tsmac_softc tsmac_softc[TSMAC_NUM];
181
182#ifdef CPU_U32_FIX
183
184/*
185 * Routine to align the received packet so that the ip header
186 * is on a 32-bit boundary. Necessary for cpu's that do not
187 * allow unaligned loads and stores and when the 32-bit DMA
188 * mode is used.
189 *
190 * Transfers are done on word basis to avoid possibly slow byte
191 * and half-word writes.
192 *
193 * Copied over from sonic.c driver
194 */
195
196void ipalign(struct mbuf *m)
197{
198  unsigned int *first, *last, data;
199  unsigned int tmp = 0;
200
201  if ((((int) m->m_data) & 2) && (m->m_len)) {
202    last = (unsigned int *) ((((int) m->m_data) + m->m_len + 8) & ~3);
203    first = (unsigned int *) (((int) m->m_data) & ~3);
204    tmp = *first << 16;
205    first++;
206    do {
207      data = *first;
208      *first = tmp | (data >> 16);
209      tmp = data << 16;
210      first++;
211    } while (first <= last);
212
213    m->m_data = (caddr_t)(((int) m->m_data) + 2);
214  }
215}
216#endif
217
218/*
219 * Receive task
220 */
221static void tsmac_rxDaemon(void *arg)
222{
223  struct tsmac_softc *tsmac = (struct tsmac_softc *) arg;
224  struct ifnet *ifp = &tsmac->arpcom.ac_if;
225  rtems_event_set events;
226  int rxq, count, len, data;
227
228#ifdef DEBUG
229  printk(TSMAC_NAME ": tsmac_rxDaemon\n");
230#endif
231
232  for(;;)
233    {
234      rtems_bsdnet_event_receive( RTEMS_ALL_EVENTS,
235                                  RTEMS_WAIT | RTEMS_EVENT_ANY,
236                                  RTEMS_NO_TIMEOUT,
237                                  &events);
238
239#ifdef DEBUG
240      printk(TSMAC_NAME ": tsmac_rxDaemon wakeup\n");
241#endif
242
243      for (;;)
244        {
245          struct mbuf* m;
246          struct ether_header* eh;
247          uint32_t *buf;
248
249          /* Get number of RX frames in RX FIFO */
250          rxq = tsmacread(LM32_TSMAC_RX_FRAMES_CNT);
251
252          if (rxq == 0)
253            break;
254
255          /* Get length of frame */
256          len = tsmacread(LM32_TSMAC_RX_LEN_FIFO);
257#ifdef DEBUG
258          printk(TSMAC_NAME ": Frames %d, len 0x%04x (%d)\n",
259                 rxq, len, len);
260#endif
261
262          /*
263           * Get memory for packet
264           */
265          MGETHDR(m, M_WAIT, MT_DATA);
266          MCLGET(m, M_WAIT);
267
268          m->m_pkthdr.rcvif = ifp;
269
270          buf = (uint32_t *) mtod(m, uint32_t*);
271          for (count = 0; count < len; count += 4)
272            {
273              data = tsmacread(LM32_TSMAC_RX_DATA_FIFO);
274              *buf++ = data;
275#ifdef DEBUG
276              printk("%08x ", data);
277#endif
278            }
279#ifdef DEBUG
280          printk("\n");
281#endif
282
283          m->m_len = m->m_pkthdr.len =
284            len - sizeof(uint32_t) - sizeof(struct ether_header);
285          eh = mtod(m, struct ether_header*);
286          m->m_data += sizeof(struct ether_header);
287
288#ifdef CPU_U32_FIX
289      ipalign(m);       /* Align packet on 32-bit boundary */
290#endif
291
292          /* Notify the ip stack that there is a new packet */
293          ether_input(ifp, eh, m);
294
295          /*
296           * Release RX frame
297           */
298        }
299    }
300}
301
302static unsigned char tsmac_txbuf[2048];
303
304static void tsmac_sendpacket(struct ifnet *ifp, struct mbuf *m)
305{
306  struct mbuf *nm = m;
307  int len = 0, i;
308  uint32_t *buf;
309
310#ifdef DEBUG
311  printk(TSMAC_NAME ": tsmac_sendpacket\n");
312#endif
313
314  do
315    {
316#ifdef DEBUG
317      printk("mbuf: 0x%08x len %03x: ", nm->m_data, nm->m_len);
318      for (i = 0; i < nm->m_len; i++)
319        {
320          printk("%02x", mtod(nm, unsigned char*)[i]);
321          if (i & 1)
322            printk(" ");
323        }
324      printk("\n");
325#endif
326
327      if (nm->m_len > 0)
328        {
329          memcpy(&tsmac_txbuf[len], (char *)nm->m_data, nm->m_len);
330          len += nm->m_len;
331        }
332    }
333  while ((nm = nm->m_next) != 0);
334
335  buf = (uint32_t *) tsmac_txbuf;
336  for (i = 0; i < len; i += 4)
337    {
338#ifdef DEBUG
339      printk("%08x", *buf);
340#endif
341      tsmacwrite(LM32_TSMAC_TX_DATA_FIFO, *buf++);
342    }
343#ifdef DEBUG
344  printk("\n");
345#endif
346
347  /*
348   * Enqueue TX frame
349   */
350  tsmacwrite(LM32_TSMAC_TX_LEN_FIFO, len);
351}
352
353/*
354 * Transmit task
355 */
356static void tsmac_txDaemon(void *arg)
357{
358  struct tsmac_softc *tsmac = (struct tsmac_softc *) arg;
359  struct ifnet *ifp = &tsmac->arpcom.ac_if;
360  struct mbuf *m;
361  rtems_event_set events;
362  int txq;
363
364#ifdef DEBUG
365  printk(TSMAC_NAME ": tsmac_txDaemon\n");
366#endif
367
368  for (;;)
369    {
370      /*
371       * Wait for packet
372       */
373      rtems_bsdnet_event_receive (START_TRANSMIT_EVENT | INTERRUPT_EVENT,
374                                  RTEMS_EVENT_ANY | RTEMS_WAIT,
375                                  RTEMS_NO_TIMEOUT, &events);
376#ifdef DEBUG
377      printk(TSMAC_NAME ": tsmac_txDaemon event\n");
378#endif
379      for (;;)
380        {
381          /*
382           * Here we should read amount of transmit memory available
383           */
384
385          txq = 2048;
386
387          if (txq < ifp->if_mtu)
388            {
389              /*
390               * Here we need to enable transmit done IRQ
391               */
392#ifdef DEBUG
393              printk(TSMAC_NAME ": TXMA %d < MTU + CW%d\n", txq,
394                     ifp->if_mtu);
395#endif
396              break;
397            }
398
399          /*
400           * Get the next mbuf chain to transmit.
401           */
402          IF_DEQUEUE(&ifp->if_snd, m);
403#ifdef DEBUG
404          printk(TSMAC_NAME ": mbuf %08x\n", (int) m);
405#endif
406          if (!m)
407            break;
408          tsmac_sendpacket(ifp, m);
409
410          m_freem(m);
411        }
412      ifp->if_flags &= ~IFF_OACTIVE;
413    }
414}
415
416/*
417 * Initialize TSMAC hardware
418 */
419void tsmac_init_hardware(struct tsmac_softc *tsmac)
420{
421  unsigned char *mac_addr;
422  int version_id, phyid, stat;
423
424#ifdef DEBUG
425  printk(TSMAC_NAME ": tsmac_init_hardware\n");
426#endif
427
428  version_id = tsmacread(LM32_TSMAC_VERID);
429#ifdef DEBUG
430  printk(TSMAC_NAME ": Version ID %08x\n", version_id);
431#endif
432
433#ifdef DEBUG
434  printk(TSMAC_NAME ": MAC MODE %04x\n", tsmacregread(LM32_TSMAC_MODE_BYTE0));
435  printk(TSMAC_NAME ": MAC TX_RX_CTL %04x\n", tsmacregread(LM32_TSMAC_TX_RX_CTL_BYTE0));
436  printk(TSMAC_NAME ": MAC MAX_PKT_SIZE %04x\n", tsmacregread(LM32_TSMAC_MAX_PKT_SIZE_BYTE0));
437  printk(TSMAC_NAME ": MAC IPG_VAL %04x\n", tsmacregread(LM32_TSMAC_IPG_VAL_BYTE0));
438  printk(TSMAC_NAME ": MAC MAC_ADDR0 %04x\n",
439         tsmacregread(LM32_TSMAC_MAC_ADDR_0_BYTE0));
440  printk(TSMAC_NAME ": MAC MAC_ADDR1 %04x\n",
441         tsmacregread(LM32_TSMAC_MAC_ADDR_1_BYTE0));
442  printk(TSMAC_NAME ": MAC MAC_ADDR2 %04x\n",
443         tsmacregread(LM32_TSMAC_MAC_ADDR_2_BYTE0));
444  printk(TSMAC_NAME ": MAC TX_RX_STS %04x\n",
445         tsmacregread(LM32_TSMAC_TX_RX_STS_BYTE0));
446#endif
447
448  /*
449   * Set our physical address
450   */
451  mac_addr = tsmac->arpcom.ac_enaddr;
452  tsmacregwrite(LM32_TSMAC_MAC_ADDR_0_BYTE0, (mac_addr[0] << 8) | mac_addr[1]);
453  tsmacregwrite(LM32_TSMAC_MAC_ADDR_1_BYTE0, (mac_addr[2] << 8) | mac_addr[3]);
454  tsmacregwrite(LM32_TSMAC_MAC_ADDR_2_BYTE0, (mac_addr[4] << 8) | mac_addr[5]);
455
456#ifdef DEBUG
457  printk(TSMAC_NAME ": After setting MAC address.\n");
458  printk(TSMAC_NAME ": MAC MAC_ADDR0 %04x\n",
459         tsmacregread(LM32_TSMAC_MAC_ADDR_0_BYTE0));
460  printk(TSMAC_NAME ": MAC MAC_ADDR1 %04x\n",
461         tsmacregread(LM32_TSMAC_MAC_ADDR_1_BYTE0));
462  printk(TSMAC_NAME ": MAC MAC_ADDR2 %04x\n",
463         tsmacregread(LM32_TSMAC_MAC_ADDR_2_BYTE0));
464#endif
465
466  /*
467   * Configure PHY
468   */
469
470  phyid = tsmacphyread(PHY_PHYIDR1);
471#ifdef DEBUG
472  printk(TSMAC_NAME ": PHYIDR1 %08x\n", phyid);
473#endif
474  phyid = tsmacphyread(PHY_PHYIDR2);
475#ifdef DEBUG
476  printk(TSMAC_NAME ": PHYIDR2 %08x\n", phyid);
477#endif
478
479#ifdef TSMAC_FORCE_10BASET
480  /* Force 10baseT mode, no AN, full duplex */
481  tsmacphywrite(PHY_BMCR, PHY_BMCR_DUPLEX_MODE);
482  stat = tsmacphyread(PHY_BMCR);
483#ifdef DEBUG
484  printk(TSMAC_NAME ": PHY BMCR %04x, wrote %04x\n", stat,
485         PHY_BMCR_DUPLEX_MODE);
486#endif
487  stat = tsmacphyread(PHY_BMSR);
488#ifdef DEBUG
489  printk(TSMAC_NAME ": PHY BMSR %04x\n", stat);
490#endif
491  /* Support for 10baseT modes only */
492  tsmacphywrite(PHY_ANAR, PHY_ANAR_10_FD | PHY_ANAR_10 | PHY_ANAR_SEL_DEF);
493  stat = tsmacphyread(PHY_ANAR);
494#ifdef DEBUG
495  printk(TSMAC_NAME ": PHY ANAR %04x, wrote %04x\n", stat,
496         PHY_ANAR_10_FD | PHY_ANAR_10 | PHY_ANAR_SEL_DEF);
497#endif
498#endif /* TSMAC_FORCE_10BASET */
499  stat = tsmacphyread(PHY_PHYSTS);
500#ifdef DEBUG
501  printk(TSMAC_NAME ": PHY PHYSTS %04x\n", stat);
502#endif
503
504  /* Enable receive and transmit interrupts */
505  tsmacwrite(LM32_TSMAC_INTR_ENB, INTR_ENB |
506             INTR_RX_SMRY | INTR_TX_SMRY |
507             INTR_RX_PKT_RDY | INTR_TX_PKT_SENT);
508}
509
510/*
511 * Initialize and start the device
512 */
513void tsmac_init(void *arg)
514{
515  struct tsmac_softc *tsmac = &tsmac_softc[0];
516  struct ifnet *ifp = &tsmac->arpcom.ac_if;
517
518#ifdef DEBUG
519  printk(TSMAC_NAME ": tsmac_init, tsmac->txDaemonTid = 0x%x\n",
520         tsmac->txDaemonTid);
521#endif
522
523  if (tsmac->txDaemonTid == 0)
524    {
525      /*
526       * Initialize hardware
527       */
528      tsmac_init_hardware(tsmac);
529
530      /*
531       * Start driver tasks
532       */
533      tsmac->txDaemonTid = rtems_bsdnet_newproc ("TSMACtx", 4096,
534                                               tsmac_txDaemon, tsmac);
535      tsmac->rxDaemonTid = rtems_bsdnet_newproc ("TSMACrx", 4096,
536                                               tsmac_rxDaemon, tsmac);
537      /*
538       * Setup interrupt handler
539       */
540      set_vector( tsmac_interrupt_handler, TSMAC_VECTOR, 1 );
541
542      /* Interrupt line for TSMAC */
543      lm32_interrupt_unmask(TSMAC_IRQMASK);
544   }
545
546  ifp->if_flags |= IFF_RUNNING;
547
548  /*
549   * Receive broadcast
550   */
551
552  tsmacregwrite(LM32_TSMAC_TX_RX_CTL_BYTE0, TX_RX_CTL_RECEIVE_BRDCST |
553                TX_RX_CTL_RECEIVE_PAUSE);
554
555  /*
556   * Enable transmitter
557   * Flow control enable
558   * Enable receiver
559   */
560
561  tsmacregwrite(LM32_TSMAC_MODE_BYTE0, MODE_TX_EN | MODE_RX_EN | MODE_FC_EN);
562
563  /*
564   * Wake up receive task to receive packets in queue
565   */
566  rtems_bsdnet_event_send(tsmac->rxDaemonTid, INTERRUPT_EVENT);
567}
568
569void tsmac_stop(struct ifnet *ifp)
570{
571  /*
572   * Mask tsmac interrupts
573   */
574  lm32_interrupt_mask(TSMAC_IRQMASK);
575
576  ifp->if_flags &= ~IFF_RUNNING;
577
578  /*
579   * Disable transmitter and receiver
580   */
581  tsmacregwrite(LM32_TSMAC_MODE_BYTE0, 0);
582}
583
584/*
585 * Send packet
586 */
587void tsmac_start(struct ifnet *ifp)
588{
589  struct tsmac_softc *tsmac = ifp->if_softc;
590
591  rtems_bsdnet_event_send (tsmac->txDaemonTid, START_TRANSMIT_EVENT);
592  ifp->if_flags |= IFF_OACTIVE;
593}
594
595void tsmac_stats(struct tsmac_softc *tsmac)
596{
597  /*
598   * Update counters from TSMAC MIB counters
599   */
600
601  tsmac->rxPktIgnore = tsmacread(LM32_TSMAC_RX_PKT_IGNR_CNT);
602  tsmac->rxLenCheckError = tsmacread(LM32_TSMAC_RX_LEN_CHK_ERR_CNT);
603  tsmac->rxLongFrame = tsmacread(LM32_TSMAC_RX_LNG_FRM_CNT);
604  tsmac->rxShortFrame = tsmacread(LM32_TSMAC_RX_SHRT_FRM_CNT);
605  tsmac->rxIPGViolation = tsmacread(LM32_TSMAC_RX_IPG_VIOL_CNT);
606  tsmac->rxCRCError = tsmacread(LM32_TSMAC_RX_CRC_ERR_CNT);
607  tsmac->rxOKPackets = tsmacread(LM32_TSMAC_RX_OK_PKT_CNT);
608  tsmac->rxControlFrame = tsmacread(LM32_TSMAC_RX_CTL_FRM_CNT);
609  tsmac->rxPauseFrame = tsmacread(LM32_TSMAC_RX_PAUSE_FRM_CNT);
610  tsmac->rxMulticast = tsmacread(LM32_TSMAC_RX_MULTICAST_CNT);
611  tsmac->rxBroadcast = tsmacread(LM32_TSMAC_RX_BRDCAST_CNT);
612  tsmac->rxVLANTag = tsmacread(LM32_TSMAC_RX_VLAN_TAG_CNT);
613  tsmac->rxPreShrink = tsmacread(LM32_TSMAC_RX_PRE_SHRINK_CNT);
614  tsmac->rxDribNib = tsmacread(LM32_TSMAC_RX_DRIB_NIB_CNT);
615  tsmac->rxUnsupOPCD = tsmacread(LM32_TSMAC_RX_UNSUP_OPCD_CNT);
616  tsmac->rxByteCnt = tsmacread(LM32_TSMAC_RX_BYTE_CNT);
617
618  tsmac->txUnicast = tsmacread(LM32_TSMAC_TX_UNICAST_CNT);
619  tsmac->txPauseFrame = tsmacread(LM32_TSMAC_TX_PAUSE_FRM_CNT);
620  tsmac->txMulticast = tsmacread(LM32_TSMAC_TX_MULTICAST_CNT);
621  tsmac->txBroadcast = tsmacread(LM32_TSMAC_TX_BRDCAST_CNT);
622  tsmac->txVLANTag = tsmacread(LM32_TSMAC_TX_VLAN_TAG_CNT);
623  tsmac->txBadFCS = tsmacread(LM32_TSMAC_TX_BAD_FCS_CNT);
624  tsmac->txJumboCnt = tsmacread(LM32_TSMAC_TX_JUMBO_CNT);
625  tsmac->txByteCnt = tsmacread(LM32_TSMAC_TX_BYTE_CNT);
626
627  printk("RX Interrupts:    %8d", tsmac->rxInterrupts);
628  printk(" RX Len Chk Error: %8d", tsmac->rxLenCheckError);
629  printk(" RX Long Frame:    %8d\n", tsmac->rxLongFrame);
630  printk("RX Short Frame:   %8d", tsmac->rxShortFrame);
631  printk(" RX IPG Violation: %8d", tsmac->rxIPGViolation);
632  printk(" RX CRC Errors:    %8d\n", tsmac->rxCRCError);
633  printk("RX OK Packets:    %8d", tsmac->rxOKPackets);
634  printk(" RX Control Frame: %8d", tsmac->rxControlFrame);
635  printk(" RX Pause Frame:   %8d\n", tsmac->rxPauseFrame);
636  printk("RX Multicast:     %8d", tsmac->rxMulticast);
637  printk(" RX Broadcast:     %8d", tsmac->rxBroadcast);
638  printk(" RX VLAN Tag:      %8d\n", tsmac->rxVLANTag);
639  printk("RX Pre Shrink:    %8d", tsmac->rxPreShrink);
640  printk(" RX Dribb. Nibble: %8d", tsmac->rxDribNib);
641  printk(" RX Unsupp. OPCD:  %8d\n", tsmac->rxUnsupOPCD);
642  printk("RX Byte Count:    %8d", tsmac->rxByteCnt);
643  printk(" RX FIFO Full:     %8d\n", tsmac->rxFifoFull);
644
645  printk("TX Interrupts:    %8d", tsmac->txInterrupts);
646  printk(" TX Unicast:       %8d", tsmac->txUnicast);
647  printk(" TX Pause Frame:   %8d\n", tsmac->txPauseFrame);
648  printk("TX Multicast:     %8d", tsmac->txMulticast);
649  printk(" TX Broadcast:     %8d", tsmac->txBroadcast);
650  printk(" TX VLAN Tag:      %8d\n", tsmac->txVLANTag);
651  printk("TX Bad FSC:       %8d", tsmac->txBadFCS);
652  printk(" TX Jumbo Frame:   %8d", tsmac->txJumboCnt);
653  printk(" TX Byte Count:    %8d\n", tsmac->txByteCnt);
654  printk("TX FIFO Full:     %8d\n", tsmac->txFifoFull);
655}
656
657/*
658 * TSMAC ioctl handler
659 */
660
661int tsmac_ioctl(struct ifnet *ifp, ioctl_command_t command, caddr_t data)
662{
663  struct tsmac_softc *tsmac = ifp->if_softc;
664  int error = 0;
665
666  switch (command) {
667  case SIOCGIFADDR:
668  case SIOCSIFADDR:
669    ether_ioctl (ifp, command, data);
670    break;
671
672  case SIOCSIFFLAGS:
673    switch (ifp->if_flags & (IFF_UP | IFF_RUNNING)) {
674    case IFF_RUNNING:
675      tsmac_stop ((struct ifnet *) tsmac);
676      break;
677
678    case IFF_UP:
679      tsmac_init ((struct ifnet *) tsmac);
680      break;
681
682    case IFF_UP | IFF_RUNNING:
683      tsmac_stop ((struct ifnet *) tsmac);
684      tsmac_init ((struct ifnet *) tsmac);
685      break;
686
687    default:
688      break;
689    }
690    break;
691
692  case SIO_RTEMS_SHOW_STATS:
693    tsmac_stats (tsmac);
694    break;
695
696  default:
697    error = EINVAL;
698    break;
699  }
700  return error;
701}
702
703/*
704 * Attach a TSMAC driver
705 */
706int rtems_tsmac_driver_attach(struct rtems_bsdnet_ifconfig *config, int attaching)
707{
708  struct tsmac_softc *tsmac;
709  struct ifnet *ifp;
710  int mtu, i;
711  int unit;
712  char *unitName;
713
714  if ((unit = rtems_bsdnet_parse_driver_name(config, &unitName)) < 0)
715    {
716      printk(TSMAC_NAME ": Driver name parsing failed.\n");
717      return 0;
718    }
719
720  if ((unit < 0) || (unit >= TSMAC_NUM))
721    {
722      printk(TSMAC_NAME ": Bad unit number %d.\n", unit);
723      return 0;
724    }
725
726  tsmac = &tsmac_softc[unit];
727
728  ifp = &tsmac->arpcom.ac_if;
729  if (ifp->if_softc != NULL)
730    {
731      printk(TSMAC_NAME ": Driver already in use.\n");
732      return 0;
733    }
734
735  /* Base address for TSMAC */
736  if (config->bpar == 0)
737    {
738      printk(TSMAC_NAME ": Using default base address 0x%08x.\n", TS_MAC_CORE_BASE_ADDRESS);
739      config->bpar = TS_MAC_CORE_BASE_ADDRESS;
740    }
741  tsmac->ioaddr = config->bpar;
742
743  /* Hardware address for TSMAC */
744  if (config->hardware_address == 0)
745    {
746      printk(TSMAC_NAME ": Using default hardware address.\n");
747      tsmac->arpcom.ac_enaddr[0] = TSMAC_MAC0;
748      tsmac->arpcom.ac_enaddr[1] = TSMAC_MAC1;
749      tsmac->arpcom.ac_enaddr[2] = TSMAC_MAC2;
750      tsmac->arpcom.ac_enaddr[3] = TSMAC_MAC3;
751      tsmac->arpcom.ac_enaddr[4] = TSMAC_MAC4;
752      tsmac->arpcom.ac_enaddr[5] = TSMAC_MAC5;
753    }
754  else
755    memcpy(tsmac->arpcom.ac_enaddr, config->hardware_address, ETHER_ADDR_LEN);
756
757  printk(TSMAC_NAME ": MAC address ");
758  for (i = 0; i < ETHER_ADDR_LEN; i++)
759    {
760      printk("%02x", tsmac->arpcom.ac_enaddr[i]);
761      if (i != ETHER_ADDR_LEN-1)
762        printk(":");
763      else
764        printk("\n");
765    }
766
767  if (config->mtu)
768    mtu = config->mtu;
769  else
770    mtu = ETHERMTU;
771
772  /*
773   * Set up network interface values
774   */
775  ifp->if_softc = tsmac;
776  ifp->if_unit = unit;
777  ifp->if_name = unitName;
778  ifp->if_mtu = mtu;
779  ifp->if_init = tsmac_init;
780  ifp->if_ioctl = tsmac_ioctl;
781  ifp->if_start = tsmac_start;
782  ifp->if_output = ether_output;
783  ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX;
784
785  if (ifp->if_snd.ifq_maxlen == 0)
786    ifp->if_snd.ifq_maxlen = ifqmaxlen;
787
788  if_attach(ifp);
789  ether_ifattach(ifp);
790
791  return 1;
792}
793
794rtems_isr tsmac_interrupt_handler(rtems_vector_number vector)
795{
796  struct tsmac_softc *tsmac = &tsmac_softc[0];
797  uint32_t irq_stat, rx_stat, tx_stat;
798
799  irq_stat = tsmacread(LM32_TSMAC_INTR_SRC);
800  if (irq_stat & INTR_RX_PKT_RDY)
801    {
802      tsmac->rxInterrupts++;
803      rtems_bsdnet_event_send(tsmac->rxDaemonTid, INTERRUPT_EVENT);
804    }
805
806  if (irq_stat & INTR_TX_PKT_SENT)
807    {
808      tsmac->txInterrupts++;
809      rtems_bsdnet_event_send(tsmac->txDaemonTid, INTERRUPT_EVENT);
810    }
811
812  rx_stat = tsmacread(LM32_TSMAC_RX_STATUS);
813  if (rx_stat & STAT_RX_FIFO_FULL)
814    tsmac->rxFifoFull++;
815
816  tx_stat = tsmacread(LM32_TSMAC_TX_STATUS);
817  if (tx_stat & STAT_TX_FIFO_FULL)
818    tsmac->txFifoFull++;
819
820  lm32_interrupt_ack(TSMAC_IRQMASK);
821}
822
Note: See TracBrowser for help on using the repository browser.