source: rtems/c/src/lib/libbsp/lm32/shared/tsmac/tsmac.c @ 612297e8

5
Last change on this file since 612297e8 was 612297e8, checked in by Joel Sherrill <joel@…>, on 07/12/16 at 10:44:17

Misc: Spell length correctly

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