[1094cf0d] | 1 | /* |
---|
[5a820308] | 2 | * RTEMS driver for TULIP based Ethernet Controller |
---|
[1094cf0d] | 3 | * |
---|
[5a820308] | 4 | * Copyright (C) 1999 Emmanuel Raguet. raguet@crf.canon.fr |
---|
| 5 | * |
---|
| 6 | * The license and distribution terms for this file may be |
---|
[3e25dfc8] | 7 | * found in the file LICENSE in this distribution or at |
---|
[c499856] | 8 | * http://www.rtems.org/license/LICENSE. |
---|
[5a820308] | 9 | * |
---|
[df49c60] | 10 | * ------------------------------------------------------------------------ |
---|
| 11 | * [22.05.2000,StWi/CWA] added support for the DEC/Intel 21143 chip |
---|
| 12 | * |
---|
[ac8f462] | 13 | * Thanks go to Andrew Klossner who provided the vital information about the |
---|
| 14 | * Intel 21143 chip. FWIW: The 21143 additions to this driver were initially |
---|
| 15 | * tested with a PC386 BSP using a Kingston KNE100TX with 21143PD chip. |
---|
[df49c60] | 16 | * |
---|
| 17 | * The driver will automatically detect whether there is a 21140 or 21143 |
---|
| 18 | * network card in the system and activate support accordingly. It will |
---|
| 19 | * look for the 21140 first. If the 21140 is not found the driver will |
---|
| 20 | * look for the 21143. |
---|
[ac8f462] | 21 | * |
---|
| 22 | * 2004-11-10, Joel/Richard - 21143 support works on MVME2100. |
---|
[df49c60] | 23 | * ------------------------------------------------------------------------ |
---|
[01b6ca9] | 24 | * |
---|
| 25 | * 2003-03-13, Greg Menke, gregory.menke@gsfc.nasa.gov |
---|
| 26 | * |
---|
| 27 | * Added support for up to 8 units (which is an arbitrary limit now), |
---|
| 28 | * consolidating their support into a single pair of rx/tx daemons and a |
---|
| 29 | * single ISR for all vectors servicing the DEC units. The driver now |
---|
| 30 | * simply uses whatever INTERRUPT_LINE the card supplies, requiring it |
---|
| 31 | * be configured either by the boot monitor or bspstart() hackery. |
---|
| 32 | * Tested on a MCP750 PPC based system with 2 DEC21140 boards. |
---|
| 33 | * |
---|
| 34 | * Also fixed a few bugs related to board configuration, start and stop. |
---|
| 35 | * |
---|
[1094cf0d] | 36 | */ |
---|
| 37 | |
---|
[d8d6a08] | 38 | #define __INSIDE_RTEMS_BSD_TCPIP_STACK__ |
---|
| 39 | |
---|
[a1efd7a] | 40 | #include <rtems.h> |
---|
[52597b9] | 41 | #include <inttypes.h> |
---|
[a1efd7a] | 42 | |
---|
| 43 | /* |
---|
| 44 | * This driver only supports architectures with the new style |
---|
| 45 | * exception processing. The following checks try to keep this |
---|
| 46 | * from being compiled on systems which can't support this driver. |
---|
| 47 | */ |
---|
| 48 | |
---|
[f7b46db] | 49 | #if defined(__i386__) |
---|
[df49c60] | 50 | #define DEC21140_SUPPORTED |
---|
[66913da2] | 51 | #define PCI_DRAM_OFFSET 0 |
---|
[a1efd7a] | 52 | #endif |
---|
[a5b5b50] | 53 | #if defined(__PPC__) |
---|
[df49c60] | 54 | #define DEC21140_SUPPORTED |
---|
[a1efd7a] | 55 | #endif |
---|
| 56 | |
---|
[a5b5b50] | 57 | #include <bsp.h> |
---|
| 58 | |
---|
[0b6ca8aa] | 59 | #if !defined(PCI_DRAM_OFFSET) |
---|
| 60 | #undef DEC21140_SUPPORTED |
---|
| 61 | #endif |
---|
| 62 | |
---|
[a1efd7a] | 63 | #if defined(DEC21140_SUPPORTED) |
---|
[3e780c1e] | 64 | #include <rtems/pci.h> |
---|
[a8e1959] | 65 | |
---|
[7c4ef9c] | 66 | #if defined(__PPC__) |
---|
[5a820308] | 67 | #include <libcpu/byteorder.h> |
---|
| 68 | #include <libcpu/io.h> |
---|
| 69 | #endif |
---|
[1094cf0d] | 70 | |
---|
[f82dabae] | 71 | #if defined(__i386__) |
---|
| 72 | #include <libcpu/byteorder.h> |
---|
[40d0a468] | 73 | #include <libcpu/page.h> |
---|
[f82dabae] | 74 | #endif |
---|
| 75 | |
---|
[1094cf0d] | 76 | #include <stdlib.h> |
---|
| 77 | #include <stdio.h> |
---|
| 78 | #include <stdarg.h> |
---|
[01b6ca9] | 79 | #include <string.h> |
---|
[593bc32] | 80 | #include <errno.h> |
---|
[1094cf0d] | 81 | #include <rtems/error.h> |
---|
[c22aeb4] | 82 | #include <rtems/bspIo.h> |
---|
[1094cf0d] | 83 | #include <rtems/rtems_bsdnet.h> |
---|
| 84 | |
---|
| 85 | #include <sys/param.h> |
---|
| 86 | #include <sys/mbuf.h> |
---|
| 87 | |
---|
| 88 | #include <sys/socket.h> |
---|
| 89 | #include <sys/sockio.h> |
---|
| 90 | #include <net/if.h> |
---|
| 91 | #include <netinet/in.h> |
---|
| 92 | #include <netinet/if_ether.h> |
---|
[a3d3d9a] | 93 | |
---|
[5a820308] | 94 | #include <bsp/irq.h> |
---|
[1094cf0d] | 95 | |
---|
| 96 | #ifdef malloc |
---|
| 97 | #undef malloc |
---|
| 98 | #endif |
---|
| 99 | #ifdef free |
---|
[a3d3d9a] | 100 | #undef free |
---|
[1094cf0d] | 101 | #endif |
---|
| 102 | |
---|
[5a820308] | 103 | #define DEC_DEBUG |
---|
| 104 | |
---|
[df49c60] | 105 | /* note: the 21143 isn't really a DEC, it's an Intel chip */ |
---|
[01b6ca9] | 106 | #define PCI_VENDOR_ID_DEC 0x1011 |
---|
| 107 | #define PCI_DEVICE_ID_DEC_21140 0x0009 |
---|
| 108 | #define PCI_DEVICE_ID_DEC_21143 0x0019 |
---|
| 109 | |
---|
| 110 | #define DRIVER_PREFIX "dc" |
---|
[1094cf0d] | 111 | |
---|
[96e62937] | 112 | #define IO_MASK 0x3 |
---|
[1094cf0d] | 113 | #define MEM_MASK 0xF |
---|
| 114 | |
---|
| 115 | /* command and status registers, 32-bit access, only if IO-ACCESS */ |
---|
[cc4c524b] | 116 | #define ioCSR0 0x00 /* bus mode register */ |
---|
| 117 | #define ioCSR1 0x08 /* transmit poll demand */ |
---|
| 118 | #define ioCSR2 0x10 /* receive poll demand */ |
---|
| 119 | #define ioCSR3 0x18 /* receive list base address */ |
---|
| 120 | #define ioCSR4 0x20 /* transmit list base address */ |
---|
| 121 | #define ioCSR5 0x28 /* status register */ |
---|
| 122 | #define ioCSR6 0x30 /* operation mode register */ |
---|
| 123 | #define ioCSR7 0x38 /* interrupt mask register */ |
---|
| 124 | #define ioCSR8 0x40 /* missed frame counter */ |
---|
| 125 | #define ioCSR9 0x48 /* Ethernet ROM register */ |
---|
| 126 | #define ioCSR10 0x50 /* reserved */ |
---|
| 127 | #define ioCSR11 0x58 /* full-duplex register */ |
---|
| 128 | #define ioCSR12 0x60 /* SIA status register */ |
---|
[1094cf0d] | 129 | #define ioCSR13 0x68 |
---|
| 130 | #define ioCSR14 0x70 |
---|
[cc4c524b] | 131 | #define ioCSR15 0x78 /* SIA general register */ |
---|
[1094cf0d] | 132 | |
---|
| 133 | /* command and status registers, 32-bit access, only if MEMORY-ACCESS */ |
---|
[cc4c524b] | 134 | #define memCSR0 0x00 /* bus mode register */ |
---|
| 135 | #define memCSR1 0x02 /* transmit poll demand */ |
---|
| 136 | #define memCSR2 0x04 /* receive poll demand */ |
---|
| 137 | #define memCSR3 0x06 /* receive list base address */ |
---|
| 138 | #define memCSR4 0x08 /* transmit list base address */ |
---|
| 139 | #define memCSR5 0x0A /* status register */ |
---|
| 140 | #define memCSR6 0x0C /* operation mode register */ |
---|
| 141 | #define memCSR7 0x0E /* interrupt mask register */ |
---|
| 142 | #define memCSR8 0x10 /* missed frame counter */ |
---|
| 143 | #define memCSR9 0x12 /* Ethernet ROM register */ |
---|
| 144 | #define memCSR10 0x14 /* reserved */ |
---|
| 145 | #define memCSR11 0x16 /* full-duplex register */ |
---|
| 146 | #define memCSR12 0x18 /* SIA status register */ |
---|
[1094cf0d] | 147 | #define memCSR13 0x1A |
---|
| 148 | #define memCSR14 0x1C |
---|
[cc4c524b] | 149 | #define memCSR15 0x1E /* SIA general register */ |
---|
[1094cf0d] | 150 | |
---|
| 151 | #define DEC_REGISTER_SIZE 0x100 /* to reserve virtual memory */ |
---|
| 152 | |
---|
[01b6ca9] | 153 | |
---|
| 154 | |
---|
| 155 | |
---|
[1094cf0d] | 156 | #define RESET_CHIP 0x00000001 |
---|
[51b9899] | 157 | #if defined(__PPC__) |
---|
[5a820308] | 158 | #define CSR0_MODE 0x0030e002 /* 01b08000 */ |
---|
| 159 | #else |
---|
| 160 | #define CSR0_MODE 0x0020e002 /* 01b08000 */ |
---|
| 161 | #endif |
---|
[1094cf0d] | 162 | #define ROM_ADDRESS 0x00004800 |
---|
[a3d3d9a] | 163 | #define CSR6_INIT 0x022cc000 /* 022c0000 020c0000 */ |
---|
| 164 | #define CSR6_TX 0x00002000 |
---|
| 165 | #define CSR6_TXRX 0x00002002 |
---|
[5a820308] | 166 | #define IT_SETUP 0x000100c0 /* 000100e0 */ |
---|
[a3d3d9a] | 167 | #define CLEAR_IT 0xFFFFFFFF |
---|
| 168 | #define NO_IT 0x00000000 |
---|
[1094cf0d] | 169 | |
---|
| 170 | /* message descriptor entry */ |
---|
| 171 | struct MD { |
---|
[5a820308] | 172 | /* used by hardware */ |
---|
[ee4f57d] | 173 | volatile uint32_t status; |
---|
| 174 | volatile uint32_t counts; |
---|
[a3d3d9a] | 175 | volatile uint32_t buf1, buf2; |
---|
[5a820308] | 176 | /* used by software */ |
---|
| 177 | volatile struct mbuf *m; |
---|
| 178 | volatile struct MD *next; |
---|
[01b6ca9] | 179 | } __attribute__ ((packed)); |
---|
| 180 | |
---|
| 181 | /* |
---|
| 182 | ** These buffers allocated for each unit, so ensure |
---|
| 183 | ** |
---|
| 184 | ** rtems_bsdnet_config.mbuf_bytecount |
---|
| 185 | ** rtems_bsdnet_config.mbuf_cluster_bytecount |
---|
| 186 | ** |
---|
| 187 | ** are adequately sized to provide enough clusters and mbufs for all the |
---|
| 188 | ** units. The default bsdnet configuration is sufficient for one dec |
---|
| 189 | ** unit, but will be nearing exhaustion with 2 or more. Although a |
---|
| 190 | ** little expensive in memory, the following configuration should |
---|
| 191 | ** eliminate all mbuf/cluster issues; |
---|
| 192 | ** |
---|
| 193 | ** rtems_bsdnet_config.mbuf_bytecount = 128*1024; |
---|
| 194 | ** rtems_bsdnet_config.mbuf_cluster_bytecount = 256*1024; |
---|
| 195 | */ |
---|
| 196 | |
---|
[cc4c524b] | 197 | #define NRXBUFS 16 /* number of receive buffers */ |
---|
| 198 | #define NTXBUFS 16 /* number of transmit buffers */ |
---|
[01b6ca9] | 199 | |
---|
[1094cf0d] | 200 | /* |
---|
[01b6ca9] | 201 | * Number of DEC boards supported by this driver |
---|
[1094cf0d] | 202 | */ |
---|
[cc4c524b] | 203 | #define NDECDRIVER 8 |
---|
[01b6ca9] | 204 | |
---|
[1094cf0d] | 205 | /* |
---|
| 206 | * Receive buffer size -- Allow for a full ethernet packet including CRC |
---|
| 207 | */ |
---|
[cc4c524b] | 208 | #define RBUF_SIZE 1536 |
---|
[1094cf0d] | 209 | |
---|
[cc4c524b] | 210 | #define ET_MINLEN 60 /* minimum message length */ |
---|
[1094cf0d] | 211 | |
---|
| 212 | /* |
---|
[01b6ca9] | 213 | ** Events, one per unit. The event is sent to the rx task from the isr |
---|
| 214 | ** or from the stack to the tx task whenever a unit needs service. The |
---|
| 215 | ** rx/tx tasks identify the requesting unit(s) by their particular |
---|
| 216 | ** events so only requesting units are serviced. |
---|
| 217 | */ |
---|
| 218 | |
---|
[a3d3d9a] | 219 | static rtems_event_set unit_signals[NDECDRIVER]= { RTEMS_EVENT_1, |
---|
[01b6ca9] | 220 | RTEMS_EVENT_2, |
---|
[a3d3d9a] | 221 | RTEMS_EVENT_3, |
---|
[01b6ca9] | 222 | RTEMS_EVENT_4, |
---|
[a3d3d9a] | 223 | RTEMS_EVENT_5, |
---|
[01b6ca9] | 224 | RTEMS_EVENT_6, |
---|
[a3d3d9a] | 225 | RTEMS_EVENT_7, |
---|
[01b6ca9] | 226 | RTEMS_EVENT_8 }; |
---|
| 227 | |
---|
[51b9899] | 228 | #if defined(__PPC__) |
---|
[a191b28] | 229 | #define phys_to_bus(address) ((unsigned int)((address)) + PCI_DRAM_OFFSET) |
---|
| 230 | #define bus_to_phys(address) ((unsigned int)((address)) - PCI_DRAM_OFFSET) |
---|
[5a820308] | 231 | #define CPU_CACHE_ALIGNMENT_FOR_BUFFER PPC_CACHE_ALIGNMENT |
---|
| 232 | #else |
---|
[95f5adb] | 233 | extern void Wait_X_ms( unsigned int timeToWait ); |
---|
[bdb2899] | 234 | #define phys_to_bus(address) ((unsigned int) ((address))) |
---|
| 235 | #define bus_to_phys(address) ((unsigned int) ((address))) |
---|
[a191b28] | 236 | #define rtems_bsp_delay_in_bus_cycles(cycle) Wait_X_ms( cycle/100 ) |
---|
[5a820308] | 237 | #define CPU_CACHE_ALIGNMENT_FOR_BUFFER PG_SIZE |
---|
| 238 | #endif |
---|
| 239 | |
---|
[1094cf0d] | 240 | #if (MCLBYTES < RBUF_SIZE) |
---|
| 241 | # error "Driver must have MCLBYTES > RBUF_SIZE" |
---|
| 242 | #endif |
---|
| 243 | |
---|
| 244 | /* |
---|
| 245 | * Per-device data |
---|
| 246 | */ |
---|
[01b6ca9] | 247 | struct dec21140_softc { |
---|
[5a820308] | 248 | |
---|
[cc4c524b] | 249 | struct arpcom arpcom; |
---|
[5a820308] | 250 | |
---|
[01b6ca9] | 251 | rtems_irq_connect_data irqInfo; |
---|
| 252 | rtems_event_set ioevent; |
---|
[1094cf0d] | 253 | |
---|
[96e62937] | 254 | int numRxbuffers, numTxbuffers; |
---|
| 255 | |
---|
[cc4c524b] | 256 | volatile struct MD *MDbase; |
---|
[01b6ca9] | 257 | volatile struct MD *nextRxMD; |
---|
[cc4c524b] | 258 | volatile unsigned char *bufferBase; |
---|
| 259 | int acceptBroadcast; |
---|
[a3d3d9a] | 260 | |
---|
[cc4c524b] | 261 | volatile struct MD *TxMD; |
---|
| 262 | volatile struct MD *SentTxMD; |
---|
| 263 | int PendingTxCount; |
---|
| 264 | int TxSuspended; |
---|
[01b6ca9] | 265 | |
---|
[cc4c524b] | 266 | unsigned int port; |
---|
| 267 | volatile uint32_t *base; |
---|
[01b6ca9] | 268 | |
---|
| 269 | /* |
---|
| 270 | * Statistics |
---|
| 271 | */ |
---|
[cc4c524b] | 272 | unsigned long rxInterrupts; |
---|
| 273 | unsigned long rxNotFirst; |
---|
| 274 | unsigned long rxNotLast; |
---|
| 275 | unsigned long rxGiant; |
---|
| 276 | unsigned long rxNonOctet; |
---|
| 277 | unsigned long rxRunt; |
---|
| 278 | unsigned long rxBadCRC; |
---|
| 279 | unsigned long rxOverrun; |
---|
| 280 | unsigned long rxCollision; |
---|
| 281 | |
---|
| 282 | unsigned long txInterrupts; |
---|
| 283 | unsigned long txDeferred; |
---|
| 284 | unsigned long txHeartbeat; |
---|
| 285 | unsigned long txLateCollision; |
---|
| 286 | unsigned long txRetryLimit; |
---|
| 287 | unsigned long txUnderrun; |
---|
| 288 | unsigned long txLostCarrier; |
---|
| 289 | unsigned long txRawWait; |
---|
[1094cf0d] | 290 | }; |
---|
| 291 | |
---|
| 292 | static struct dec21140_softc dec21140_softc[NDECDRIVER]; |
---|
[cc4c524b] | 293 | static rtems_id rxDaemonTid; |
---|
| 294 | static rtems_id txDaemonTid; |
---|
[01b6ca9] | 295 | |
---|
[fc91f51] | 296 | void dec21140_txDaemon (void *arg); |
---|
| 297 | |
---|
[1094cf0d] | 298 | /* |
---|
| 299 | * This routine reads a word (16 bits) from the serial EEPROM. |
---|
| 300 | */ |
---|
| 301 | /* EEPROM_Ctrl bits. */ |
---|
[cc4c524b] | 302 | #define EE_SHIFT_CLK 0x02 /* EEPROM shift clock. */ |
---|
| 303 | #define EE_CS 0x01 /* EEPROM chip select. */ |
---|
| 304 | #define EE_DATA_WRITE 0x04 /* EEPROM chip data in. */ |
---|
| 305 | #define EE_WRITE_0 0x01 |
---|
| 306 | #define EE_WRITE_1 0x05 |
---|
| 307 | #define EE_DATA_READ 0x08 /* EEPROM chip data out. */ |
---|
| 308 | #define EE_ENB (0x4800 | EE_CS) |
---|
[1094cf0d] | 309 | |
---|
| 310 | /* The EEPROM commands include the alway-set leading bit. */ |
---|
[cc4c524b] | 311 | #define EE_WRITE_CMD (5 << 6) |
---|
| 312 | #define EE_READ_CMD (6 << 6) |
---|
| 313 | #define EE_ERASE_CMD (7 << 6) |
---|
[1094cf0d] | 314 | |
---|
[cc4c524b] | 315 | static int eeget16(volatile uint32_t *ioaddr, int location) |
---|
[1094cf0d] | 316 | { |
---|
[01b6ca9] | 317 | int i; |
---|
| 318 | unsigned short retval = 0; |
---|
| 319 | int read_cmd = location | EE_READ_CMD; |
---|
[a3d3d9a] | 320 | |
---|
[01b6ca9] | 321 | st_le32(ioaddr, EE_ENB & ~EE_CS); |
---|
| 322 | st_le32(ioaddr, EE_ENB); |
---|
[a3d3d9a] | 323 | |
---|
[01b6ca9] | 324 | /* Shift the read command bits out. */ |
---|
| 325 | for (i = 10; i >= 0; i--) { |
---|
| 326 | short dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0; |
---|
| 327 | st_le32(ioaddr, EE_ENB | dataval); |
---|
| 328 | rtems_bsp_delay_in_bus_cycles(200); |
---|
| 329 | st_le32(ioaddr, EE_ENB | dataval | EE_SHIFT_CLK); |
---|
| 330 | rtems_bsp_delay_in_bus_cycles(200); |
---|
| 331 | st_le32(ioaddr, EE_ENB | dataval); /* Finish EEPROM a clock tick. */ |
---|
| 332 | rtems_bsp_delay_in_bus_cycles(200); |
---|
| 333 | } |
---|
| 334 | st_le32(ioaddr, EE_ENB); |
---|
[a3d3d9a] | 335 | |
---|
[01b6ca9] | 336 | for (i = 16; i > 0; i--) { |
---|
| 337 | st_le32(ioaddr, EE_ENB | EE_SHIFT_CLK); |
---|
| 338 | rtems_bsp_delay_in_bus_cycles(200); |
---|
| 339 | retval = (retval << 1) | ((ld_le32(ioaddr) & EE_DATA_READ) ? 1 : 0); |
---|
| 340 | st_le32(ioaddr, EE_ENB); |
---|
| 341 | rtems_bsp_delay_in_bus_cycles(200); |
---|
| 342 | } |
---|
| 343 | |
---|
| 344 | /* Terminate the EEPROM access. */ |
---|
| 345 | st_le32(ioaddr, EE_ENB & ~EE_CS); |
---|
| 346 | return ( ((retval<<8)&0xff00) | ((retval>>8)&0xff) ); |
---|
| 347 | } |
---|
| 348 | |
---|
| 349 | static void no_op(const rtems_irq_connect_data* irq) |
---|
| 350 | { |
---|
| 351 | return; |
---|
| 352 | } |
---|
| 353 | |
---|
[1094cf0d] | 354 | /* |
---|
[01b6ca9] | 355 | * DEC21140 interrupt handler |
---|
[1094cf0d] | 356 | */ |
---|
[01b6ca9] | 357 | static rtems_isr |
---|
| 358 | dec21140Enet_interrupt_handler ( struct dec21140_softc *sc ) |
---|
[1094cf0d] | 359 | { |
---|
[ee4f57d] | 360 | volatile uint32_t *tbase; |
---|
| 361 | uint32_t status; |
---|
[01b6ca9] | 362 | |
---|
[509fec9c] | 363 | tbase = (uint32_t*)(sc->base); |
---|
[01b6ca9] | 364 | |
---|
| 365 | /* |
---|
| 366 | * Read status |
---|
| 367 | */ |
---|
| 368 | status = ld_le32(tbase+memCSR5); |
---|
| 369 | st_le32((tbase+memCSR5), status); |
---|
| 370 | |
---|
| 371 | /* |
---|
| 372 | * Frame received? |
---|
| 373 | */ |
---|
| 374 | if( status & 0x000000c0 ) |
---|
| 375 | { |
---|
| 376 | sc->rxInterrupts++; |
---|
[26e90fb1] | 377 | rtems_bsdnet_event_send(rxDaemonTid, sc->ioevent); |
---|
[01b6ca9] | 378 | } |
---|
| 379 | } |
---|
[1094cf0d] | 380 | |
---|
[01b6ca9] | 381 | static rtems_isr |
---|
[6ffb0748] | 382 | dec21140Enet_interrupt_handler_entry(void) |
---|
[01b6ca9] | 383 | { |
---|
| 384 | int i; |
---|
| 385 | |
---|
| 386 | /* |
---|
| 387 | ** Check all the initialized dec units for interrupt service |
---|
[1094cf0d] | 388 | */ |
---|
[01b6ca9] | 389 | |
---|
| 390 | for(i=0; i< NDECDRIVER; i++ ) |
---|
| 391 | { |
---|
| 392 | if( dec21140_softc[i].base ) |
---|
| 393 | dec21140Enet_interrupt_handler( &dec21140_softc[i] ); |
---|
| 394 | } |
---|
| 395 | } |
---|
| 396 | |
---|
| 397 | /* |
---|
| 398 | * Initialize the ethernet hardware |
---|
| 399 | */ |
---|
| 400 | static void |
---|
| 401 | dec21140Enet_initialize_hardware (struct dec21140_softc *sc) |
---|
| 402 | { |
---|
| 403 | int i,st; |
---|
[cc4c524b] | 404 | volatile uint32_t *tbase; |
---|
[a3d3d9a] | 405 | volatile unsigned char *cp, *setup_frm, *eaddrs; |
---|
[01b6ca9] | 406 | volatile unsigned char *buffer; |
---|
| 407 | volatile struct MD *rmd; |
---|
| 408 | |
---|
[1094cf0d] | 409 | |
---|
| 410 | #ifdef DEC_DEBUG |
---|
[01b6ca9] | 411 | printk("dec2114x : %02x:%02x:%02x:%02x:%02x:%02x name '%s%d', io %x, mem %x, int %d\n", |
---|
| 412 | sc->arpcom.ac_enaddr[0], sc->arpcom.ac_enaddr[1], |
---|
| 413 | sc->arpcom.ac_enaddr[2], sc->arpcom.ac_enaddr[3], |
---|
| 414 | sc->arpcom.ac_enaddr[4], sc->arpcom.ac_enaddr[5], |
---|
| 415 | sc->arpcom.ac_if.if_name, sc->arpcom.ac_if.if_unit, |
---|
| 416 | sc->port, (unsigned) sc->base, sc->irqInfo.name ); |
---|
[1094cf0d] | 417 | #endif |
---|
[01b6ca9] | 418 | |
---|
| 419 | tbase = sc->base; |
---|
| 420 | |
---|
| 421 | /* |
---|
| 422 | * WARNING : First write in CSR6 |
---|
| 423 | * Then Reset the chip ( 1 in CSR0) |
---|
| 424 | */ |
---|
[a3d3d9a] | 425 | st_le32( (tbase+memCSR6), CSR6_INIT); |
---|
| 426 | st_le32( (tbase+memCSR0), RESET_CHIP); |
---|
[01b6ca9] | 427 | rtems_bsp_delay_in_bus_cycles(200); |
---|
| 428 | |
---|
[a3d3d9a] | 429 | st_le32( (tbase+memCSR7), NO_IT); |
---|
[01b6ca9] | 430 | |
---|
| 431 | /* |
---|
| 432 | * Init CSR0 |
---|
| 433 | */ |
---|
[a3d3d9a] | 434 | st_le32( (tbase+memCSR0), CSR0_MODE); |
---|
[01b6ca9] | 435 | |
---|
| 436 | /* |
---|
| 437 | * Init RX ring |
---|
| 438 | */ |
---|
[96e62937] | 439 | cp = (volatile unsigned char *)malloc(((sc->numRxbuffers+sc->numTxbuffers)*sizeof(struct MD)) |
---|
| 440 | + (sc->numTxbuffers*RBUF_SIZE) |
---|
[01b6ca9] | 441 | + CPU_CACHE_ALIGNMENT_FOR_BUFFER); |
---|
| 442 | sc->bufferBase = cp; |
---|
| 443 | cp += (CPU_CACHE_ALIGNMENT_FOR_BUFFER - (int)cp) & (CPU_CACHE_ALIGNMENT_FOR_BUFFER - 1); |
---|
[f7b46db] | 444 | #if defined(__i386__) |
---|
[a3d3d9a] | 445 | #ifdef PCI_BRIDGE_DOES_NOT_ENSURE_CACHE_COHERENCY_FOR_DMA |
---|
[01b6ca9] | 446 | if (_CPU_is_paging_enabled()) |
---|
| 447 | _CPU_change_memory_mapping_attribute |
---|
| 448 | (NULL, cp, |
---|
[96e62937] | 449 | ((sc->numRxbuffers+sc->numTxbuffers)*sizeof(struct MD)) |
---|
| 450 | + (sc->numTxbuffers*RBUF_SIZE), |
---|
[01b6ca9] | 451 | PTE_CACHE_DISABLE | PTE_WRITABLE); |
---|
[8846bbd] | 452 | #endif |
---|
[5a820308] | 453 | #endif |
---|
[01b6ca9] | 454 | rmd = (volatile struct MD*)cp; |
---|
| 455 | sc->MDbase = rmd; |
---|
| 456 | sc->nextRxMD = sc->MDbase; |
---|
[1094cf0d] | 457 | |
---|
[96e62937] | 458 | buffer = cp + ((sc->numRxbuffers+sc->numTxbuffers)*sizeof(struct MD)); |
---|
[01b6ca9] | 459 | st_le32( (tbase+memCSR3), (long)(phys_to_bus((long)(sc->MDbase)))); |
---|
[5a820308] | 460 | |
---|
[96e62937] | 461 | for (i=0 ; i<sc->numRxbuffers; i++) |
---|
[01b6ca9] | 462 | { |
---|
| 463 | struct mbuf *m; |
---|
[a3d3d9a] | 464 | |
---|
[01b6ca9] | 465 | /* allocate an mbuf for each receive descriptor */ |
---|
| 466 | MGETHDR (m, M_WAIT, MT_DATA); |
---|
| 467 | MCLGET (m, M_WAIT); |
---|
| 468 | m->m_pkthdr.rcvif = &sc->arpcom.ac_if; |
---|
| 469 | rmd->m = m; |
---|
[1094cf0d] | 470 | |
---|
[01b6ca9] | 471 | rmd->buf2 = phys_to_bus(rmd+1); |
---|
[a3d3d9a] | 472 | rmd->buf1 = phys_to_bus(mtod(m, void *)); |
---|
[01b6ca9] | 473 | rmd->status = 0x80000000; |
---|
| 474 | rmd->counts = 0xfdc00000 | (RBUF_SIZE); |
---|
| 475 | rmd->next = rmd+1; |
---|
| 476 | rmd++; |
---|
| 477 | } |
---|
| 478 | /* |
---|
| 479 | * mark last RX buffer. |
---|
| 480 | */ |
---|
[96e62937] | 481 | sc->MDbase [sc->numRxbuffers-1].buf2 = 0; |
---|
| 482 | sc->MDbase [sc->numRxbuffers-1].counts = 0xfec00000 | (RBUF_SIZE); |
---|
| 483 | sc->MDbase [sc->numRxbuffers-1].next = sc->MDbase; |
---|
[01b6ca9] | 484 | |
---|
| 485 | |
---|
| 486 | |
---|
| 487 | /* |
---|
| 488 | * Init TX ring |
---|
| 489 | */ |
---|
| 490 | st_le32( (tbase+memCSR4), (long)(phys_to_bus((long)(rmd))) ); |
---|
[96e62937] | 491 | for (i=0 ; i<sc->numTxbuffers; i++){ |
---|
[01b6ca9] | 492 | (rmd+i)->buf2 = phys_to_bus(rmd+i+1); |
---|
| 493 | (rmd+i)->buf1 = phys_to_bus(buffer + (i*RBUF_SIZE)); |
---|
| 494 | (rmd+i)->counts = 0x01000000; |
---|
| 495 | (rmd+i)->status = 0x0; |
---|
| 496 | (rmd+i)->next = rmd+i+1; |
---|
| 497 | (rmd+i)->m = 0; |
---|
[a3d3d9a] | 498 | } |
---|
[01b6ca9] | 499 | |
---|
| 500 | /* |
---|
| 501 | * mark last TX buffer. |
---|
| 502 | */ |
---|
[96e62937] | 503 | (rmd+sc->numTxbuffers-1)->buf2 = phys_to_bus(rmd); |
---|
| 504 | (rmd+sc->numTxbuffers-1)->next = rmd; |
---|
[01b6ca9] | 505 | |
---|
| 506 | |
---|
| 507 | /* |
---|
| 508 | * Build setup frame |
---|
| 509 | */ |
---|
| 510 | setup_frm = (volatile unsigned char *)(bus_to_phys(rmd->buf1)); |
---|
[bb9e843] | 511 | eaddrs = (unsigned char *)(sc->arpcom.ac_enaddr); |
---|
[01b6ca9] | 512 | /* Fill the buffer with our physical address. */ |
---|
| 513 | for (i = 1; i < 16; i++) { |
---|
| 514 | *setup_frm++ = eaddrs[0]; |
---|
| 515 | *setup_frm++ = eaddrs[1]; |
---|
| 516 | *setup_frm++ = eaddrs[0]; |
---|
| 517 | *setup_frm++ = eaddrs[1]; |
---|
| 518 | *setup_frm++ = eaddrs[2]; |
---|
| 519 | *setup_frm++ = eaddrs[3]; |
---|
| 520 | *setup_frm++ = eaddrs[2]; |
---|
| 521 | *setup_frm++ = eaddrs[3]; |
---|
| 522 | *setup_frm++ = eaddrs[4]; |
---|
| 523 | *setup_frm++ = eaddrs[5]; |
---|
| 524 | *setup_frm++ = eaddrs[4]; |
---|
| 525 | *setup_frm++ = eaddrs[5]; |
---|
| 526 | } |
---|
| 527 | |
---|
| 528 | /* Add the broadcast address when doing perfect filtering */ |
---|
| 529 | memset((void*) setup_frm, 0xff, 12); |
---|
| 530 | rmd->counts = 0x09000000 | 192 ; |
---|
| 531 | rmd->status = 0x80000000; |
---|
| 532 | st_le32( (tbase+memCSR6), CSR6_INIT | CSR6_TX); |
---|
| 533 | st_le32( (tbase+memCSR1), 1); |
---|
| 534 | |
---|
| 535 | while (rmd->status != 0x7fffffff); |
---|
[a3d3d9a] | 536 | rmd->counts = 0x01000000; |
---|
[01b6ca9] | 537 | |
---|
| 538 | sc->TxMD = rmd+1; |
---|
| 539 | |
---|
| 540 | sc->irqInfo.hdl = (rtems_irq_hdl)dec21140Enet_interrupt_handler_entry; |
---|
| 541 | sc->irqInfo.on = no_op; |
---|
| 542 | sc->irqInfo.off = no_op; |
---|
[8c83cbc] | 543 | sc->irqInfo.isOn = NULL; |
---|
[01b6ca9] | 544 | |
---|
[ac8f462] | 545 | #ifdef DEC_DEBUG |
---|
| 546 | printk( "dec2114x: Installing IRQ %d\n", sc->irqInfo.name ); |
---|
| 547 | #endif |
---|
[01b6ca9] | 548 | #ifdef BSP_SHARED_HANDLER_SUPPORT |
---|
| 549 | st = BSP_install_rtems_shared_irq_handler( &sc->irqInfo ); |
---|
| 550 | #else |
---|
| 551 | st = BSP_install_rtems_irq_handler( &sc->irqInfo ); |
---|
| 552 | #endif |
---|
[1094cf0d] | 553 | |
---|
[01b6ca9] | 554 | if (!st) |
---|
| 555 | rtems_panic ("dec2114x : Interrupt name %d already in use\n", sc->irqInfo.name ); |
---|
[1094cf0d] | 556 | } |
---|
| 557 | |
---|
| 558 | static void |
---|
| 559 | dec21140_rxDaemon (void *arg) |
---|
| 560 | { |
---|
[01b6ca9] | 561 | volatile struct MD *rmd; |
---|
| 562 | struct dec21140_softc *sc; |
---|
[96e62937] | 563 | struct ifnet *ifp; |
---|
[01b6ca9] | 564 | struct ether_header *eh; |
---|
| 565 | struct mbuf *m; |
---|
| 566 | unsigned int i,len; |
---|
| 567 | rtems_event_set events; |
---|
| 568 | |
---|
| 569 | for (;;) |
---|
| 570 | { |
---|
| 571 | |
---|
| 572 | rtems_bsdnet_event_receive( RTEMS_ALL_EVENTS, |
---|
| 573 | RTEMS_WAIT|RTEMS_EVENT_ANY, |
---|
| 574 | RTEMS_NO_TIMEOUT, |
---|
| 575 | &events); |
---|
| 576 | |
---|
| 577 | for(i=0; i< NDECDRIVER; i++ ) |
---|
| 578 | { |
---|
| 579 | sc = &dec21140_softc[i]; |
---|
| 580 | if( sc->base ) |
---|
| 581 | { |
---|
| 582 | if( events & sc->ioevent ) |
---|
| 583 | { |
---|
| 584 | ifp = &sc->arpcom.ac_if; |
---|
| 585 | rmd = sc->nextRxMD; |
---|
| 586 | |
---|
| 587 | /* |
---|
| 588 | ** Read off all the packets we've received on this unit |
---|
| 589 | */ |
---|
| 590 | while((rmd->status & 0x80000000) == 0) |
---|
| 591 | { |
---|
| 592 | /* printk("unit %i rx\n", ifp->if_unit ); */ |
---|
[a3d3d9a] | 593 | |
---|
[01b6ca9] | 594 | /* pass on the packet in the mbuf */ |
---|
| 595 | len = (rmd->status >> 16) & 0x7ff; |
---|
| 596 | m = (struct mbuf *)(rmd->m); |
---|
| 597 | m->m_len = m->m_pkthdr.len = len - sizeof(struct ether_header); |
---|
| 598 | eh = mtod (m, struct ether_header *); |
---|
| 599 | m->m_data += sizeof(struct ether_header); |
---|
| 600 | ether_input (ifp, eh, m); |
---|
| 601 | |
---|
| 602 | /* get a new mbuf for the 21140 */ |
---|
| 603 | MGETHDR (m, M_WAIT, MT_DATA); |
---|
| 604 | MCLGET (m, M_WAIT); |
---|
| 605 | m->m_pkthdr.rcvif = ifp; |
---|
| 606 | rmd->m = m; |
---|
| 607 | rmd->buf1 = phys_to_bus(mtod(m, void *)); |
---|
| 608 | |
---|
| 609 | /* mark the descriptor as ready to receive */ |
---|
| 610 | rmd->status = 0x80000000; |
---|
[a3d3d9a] | 611 | |
---|
[01b6ca9] | 612 | rmd=rmd->next; |
---|
| 613 | } |
---|
[1094cf0d] | 614 | |
---|
[01b6ca9] | 615 | sc->nextRxMD = rmd; |
---|
| 616 | } |
---|
| 617 | } |
---|
| 618 | } |
---|
[1094cf0d] | 619 | |
---|
[01b6ca9] | 620 | } |
---|
[1094cf0d] | 621 | } |
---|
| 622 | |
---|
| 623 | static void |
---|
| 624 | sendpacket (struct ifnet *ifp, struct mbuf *m) |
---|
| 625 | { |
---|
[01b6ca9] | 626 | struct dec21140_softc *dp = ifp->if_softc; |
---|
| 627 | volatile struct MD *tmd; |
---|
| 628 | volatile unsigned char *temp; |
---|
| 629 | struct mbuf *n; |
---|
| 630 | unsigned int len; |
---|
[cc4c524b] | 631 | volatile uint32_t *tbase; |
---|
[01b6ca9] | 632 | |
---|
| 633 | tbase = dp->base; |
---|
| 634 | /* |
---|
| 635 | * Waiting for Transmitter ready |
---|
[a3d3d9a] | 636 | */ |
---|
[01b6ca9] | 637 | |
---|
| 638 | tmd = dp->TxMD; |
---|
| 639 | n = m; |
---|
| 640 | |
---|
| 641 | while ((tmd->status & 0x80000000) != 0) |
---|
| 642 | { |
---|
| 643 | tmd=tmd->next; |
---|
| 644 | } |
---|
| 645 | |
---|
| 646 | len = 0; |
---|
| 647 | temp = (volatile unsigned char *)(bus_to_phys(tmd->buf1)); |
---|
[a3d3d9a] | 648 | |
---|
[01b6ca9] | 649 | for (;;) |
---|
| 650 | { |
---|
| 651 | len += m->m_len; |
---|
| 652 | memcpy((void*) temp, (char *)m->m_data, m->m_len); |
---|
| 653 | temp += m->m_len ; |
---|
| 654 | if ((m = m->m_next) == NULL) |
---|
| 655 | break; |
---|
| 656 | } |
---|
[1094cf0d] | 657 | |
---|
[01b6ca9] | 658 | if (len < ET_MINLEN) len = ET_MINLEN; |
---|
[a3d3d9a] | 659 | tmd->counts = 0xe1000000 | (len & 0x7ff); |
---|
[01b6ca9] | 660 | tmd->status = 0x80000000; |
---|
[5a820308] | 661 | |
---|
[01b6ca9] | 662 | st_le32( (tbase+memCSR1), 0x1); |
---|
[5a820308] | 663 | |
---|
[01b6ca9] | 664 | m_freem(n); |
---|
| 665 | |
---|
| 666 | dp->TxMD = tmd->next; |
---|
[1094cf0d] | 667 | } |
---|
| 668 | |
---|
| 669 | /* |
---|
| 670 | * Driver transmit daemon |
---|
| 671 | */ |
---|
| 672 | void |
---|
| 673 | dec21140_txDaemon (void *arg) |
---|
| 674 | { |
---|
[01b6ca9] | 675 | struct dec21140_softc *sc; |
---|
| 676 | struct ifnet *ifp; |
---|
| 677 | struct mbuf *m; |
---|
| 678 | int i; |
---|
| 679 | rtems_event_set events; |
---|
| 680 | |
---|
[a3d3d9a] | 681 | for (;;) |
---|
[01b6ca9] | 682 | { |
---|
[1094cf0d] | 683 | /* |
---|
[01b6ca9] | 684 | * Wait for packets bound for any of the dec units |
---|
[1094cf0d] | 685 | */ |
---|
[01b6ca9] | 686 | rtems_bsdnet_event_receive( RTEMS_ALL_EVENTS, |
---|
[a3d3d9a] | 687 | RTEMS_EVENT_ANY | RTEMS_WAIT, |
---|
[01b6ca9] | 688 | RTEMS_NO_TIMEOUT, &events); |
---|
| 689 | |
---|
| 690 | for(i=0; i< NDECDRIVER; i++ ) |
---|
| 691 | { |
---|
| 692 | sc = &dec21140_softc[i]; |
---|
| 693 | if( sc->base ) |
---|
| 694 | { |
---|
| 695 | if( events & sc->ioevent ) |
---|
| 696 | { |
---|
| 697 | ifp = &sc->arpcom.ac_if; |
---|
| 698 | |
---|
| 699 | /* |
---|
| 700 | * Send packets till queue is empty |
---|
| 701 | */ |
---|
[a3d3d9a] | 702 | for(;;) |
---|
[01b6ca9] | 703 | { |
---|
| 704 | IF_DEQUEUE(&ifp->if_snd, m); |
---|
| 705 | if( !m ) break; |
---|
| 706 | /* printk("unit %i tx\n", ifp->if_unit ); */ |
---|
| 707 | sendpacket (ifp, m); |
---|
| 708 | } |
---|
| 709 | |
---|
| 710 | ifp->if_flags &= ~IFF_OACTIVE; |
---|
| 711 | } |
---|
| 712 | } |
---|
| 713 | } |
---|
| 714 | |
---|
| 715 | } |
---|
| 716 | } |
---|
| 717 | |
---|
[1094cf0d] | 718 | static void |
---|
| 719 | dec21140_start (struct ifnet *ifp) |
---|
| 720 | { |
---|
[01b6ca9] | 721 | struct dec21140_softc *sc = ifp->if_softc; |
---|
[26e90fb1] | 722 | rtems_bsdnet_event_send( txDaemonTid, sc->ioevent ); |
---|
[01b6ca9] | 723 | ifp->if_flags |= IFF_OACTIVE; |
---|
[1094cf0d] | 724 | } |
---|
| 725 | |
---|
| 726 | /* |
---|
| 727 | * Initialize and start the device |
---|
| 728 | */ |
---|
| 729 | static void |
---|
| 730 | dec21140_init (void *arg) |
---|
| 731 | { |
---|
[01b6ca9] | 732 | struct dec21140_softc *sc = arg; |
---|
| 733 | struct ifnet *ifp = &sc->arpcom.ac_if; |
---|
[cc4c524b] | 734 | volatile uint32_t *tbase; |
---|
[01b6ca9] | 735 | |
---|
| 736 | /* |
---|
| 737 | * Set up DEC21140 hardware if its not already been done |
---|
| 738 | */ |
---|
| 739 | if( !sc->irqInfo.hdl ) |
---|
| 740 | { |
---|
| 741 | dec21140Enet_initialize_hardware (sc); |
---|
| 742 | } |
---|
| 743 | |
---|
| 744 | /* |
---|
| 745 | * Enable RX and TX |
---|
| 746 | */ |
---|
| 747 | tbase = sc->base; |
---|
| 748 | st_le32( (tbase+memCSR5), IT_SETUP); |
---|
[a3d3d9a] | 749 | st_le32( (tbase+memCSR7), IT_SETUP); |
---|
[cc4c524b] | 750 | st_le32( (tbase+memCSR6), CSR6_INIT | CSR6_TXRX); |
---|
[01b6ca9] | 751 | |
---|
| 752 | /* |
---|
| 753 | * Tell the world that we're running. |
---|
| 754 | */ |
---|
| 755 | ifp->if_flags |= IFF_RUNNING; |
---|
| 756 | } |
---|
| 757 | |
---|
[1094cf0d] | 758 | /* |
---|
| 759 | * Stop the device |
---|
| 760 | */ |
---|
| 761 | static void |
---|
| 762 | dec21140_stop (struct dec21140_softc *sc) |
---|
| 763 | { |
---|
[cc4c524b] | 764 | volatile uint32_t *tbase; |
---|
[1094cf0d] | 765 | struct ifnet *ifp = &sc->arpcom.ac_if; |
---|
| 766 | |
---|
| 767 | ifp->if_flags &= ~IFF_RUNNING; |
---|
| 768 | |
---|
| 769 | /* |
---|
| 770 | * Stop the transmitter |
---|
| 771 | */ |
---|
[01b6ca9] | 772 | tbase = sc->base; |
---|
[5a820308] | 773 | st_le32( (tbase+memCSR7), NO_IT); |
---|
| 774 | st_le32( (tbase+memCSR6), CSR6_INIT); |
---|
[01b6ca9] | 775 | |
---|
| 776 | /* free((void*)sc->bufferBase); */ |
---|
[1094cf0d] | 777 | } |
---|
| 778 | |
---|
| 779 | /* |
---|
| 780 | * Show interface statistics |
---|
| 781 | */ |
---|
| 782 | static void |
---|
| 783 | dec21140_stats (struct dec21140_softc *sc) |
---|
| 784 | { |
---|
[cc4c524b] | 785 | printf (" Rx Interrupts:%-8lu", sc->rxInterrupts); |
---|
| 786 | printf (" Not First:%-8lu", sc->rxNotFirst); |
---|
| 787 | printf (" Not Last:%-8lu\n", sc->rxNotLast); |
---|
| 788 | printf (" Giant:%-8lu", sc->rxGiant); |
---|
| 789 | printf (" Runt:%-8lu", sc->rxRunt); |
---|
| 790 | printf (" Non-octet:%-8lu\n", sc->rxNonOctet); |
---|
| 791 | printf (" Bad CRC:%-8lu", sc->rxBadCRC); |
---|
| 792 | printf (" Overrun:%-8lu", sc->rxOverrun); |
---|
| 793 | printf (" Collision:%-8lu\n", sc->rxCollision); |
---|
| 794 | |
---|
| 795 | printf (" Tx Interrupts:%-8lu", sc->txInterrupts); |
---|
| 796 | printf (" Deferred:%-8lu", sc->txDeferred); |
---|
| 797 | printf (" Missed Hearbeat:%-8lu\n", sc->txHeartbeat); |
---|
| 798 | printf (" No Carrier:%-8lu", sc->txLostCarrier); |
---|
| 799 | printf ("Retransmit Limit:%-8lu", sc->txRetryLimit); |
---|
| 800 | printf (" Late Collision:%-8lu\n", sc->txLateCollision); |
---|
| 801 | printf (" Underrun:%-8lu", sc->txUnderrun); |
---|
| 802 | printf (" Raw output wait:%-8lu\n", sc->txRawWait); |
---|
[1094cf0d] | 803 | } |
---|
| 804 | |
---|
| 805 | /* |
---|
| 806 | * Driver ioctl handler |
---|
| 807 | */ |
---|
| 808 | static int |
---|
[bd20bc8] | 809 | dec21140_ioctl (struct ifnet *ifp, ioctl_command_t command, caddr_t data) |
---|
[1094cf0d] | 810 | { |
---|
[01b6ca9] | 811 | struct dec21140_softc *sc = ifp->if_softc; |
---|
| 812 | int error = 0; |
---|
| 813 | |
---|
| 814 | switch (command) { |
---|
| 815 | case SIOCGIFADDR: |
---|
| 816 | case SIOCSIFADDR: |
---|
| 817 | ether_ioctl (ifp, command, data); |
---|
| 818 | break; |
---|
| 819 | |
---|
| 820 | case SIOCSIFFLAGS: |
---|
| 821 | switch (ifp->if_flags & (IFF_UP | IFF_RUNNING)) { |
---|
| 822 | case IFF_RUNNING: |
---|
| 823 | dec21140_stop (sc); |
---|
| 824 | break; |
---|
| 825 | |
---|
| 826 | case IFF_UP: |
---|
| 827 | dec21140_init (sc); |
---|
| 828 | break; |
---|
| 829 | |
---|
| 830 | case IFF_UP | IFF_RUNNING: |
---|
| 831 | dec21140_stop (sc); |
---|
| 832 | dec21140_init (sc); |
---|
| 833 | break; |
---|
| 834 | |
---|
| 835 | default: |
---|
| 836 | break; |
---|
| 837 | } |
---|
| 838 | break; |
---|
| 839 | |
---|
| 840 | case SIO_RTEMS_SHOW_STATS: |
---|
| 841 | dec21140_stats (sc); |
---|
| 842 | break; |
---|
[a3d3d9a] | 843 | |
---|
[01b6ca9] | 844 | /* |
---|
| 845 | * FIXME: All sorts of multicast commands need to be added here! |
---|
| 846 | */ |
---|
| 847 | default: |
---|
| 848 | error = EINVAL; |
---|
| 849 | break; |
---|
| 850 | } |
---|
| 851 | |
---|
| 852 | return error; |
---|
| 853 | } |
---|
| 854 | |
---|
| 855 | |
---|
| 856 | /* |
---|
| 857 | int iftap(struct ifnet *ifp, struct ether_header *eh, struct mbuf *m ) |
---|
| 858 | { |
---|
| 859 | int i; |
---|
| 860 | |
---|
| 861 | if( ifp->if_unit == 1 ) return 0; |
---|
| 862 | |
---|
| 863 | printf("unit %i, src ", ifp->if_unit ); |
---|
| 864 | for(i=0; i< ETHER_ADDR_LEN; i++) printf("%02x", (char) eh->ether_shost[i] ); |
---|
| 865 | printf(" dest "); |
---|
| 866 | for(i=0; i< ETHER_ADDR_LEN; i++) printf("%02x", (char) eh->ether_dhost[i] ); |
---|
| 867 | printf("\n"); |
---|
| 868 | |
---|
| 869 | return -1; |
---|
[1094cf0d] | 870 | } |
---|
[01b6ca9] | 871 | */ |
---|
| 872 | |
---|
[1094cf0d] | 873 | /* |
---|
| 874 | * Attach an DEC21140 driver to the system |
---|
| 875 | */ |
---|
| 876 | int |
---|
[461fa1bc] | 877 | rtems_dec21140_driver_attach (struct rtems_bsdnet_ifconfig *config, int attach) |
---|
[1094cf0d] | 878 | { |
---|
[01b6ca9] | 879 | struct dec21140_softc *sc; |
---|
| 880 | struct ifnet *ifp; |
---|
| 881 | char *unitName; |
---|
| 882 | int unitNumber; |
---|
| 883 | int mtu; |
---|
| 884 | unsigned char cvalue; |
---|
[c22aeb4] | 885 | #if defined(__i386__) |
---|
[cc4c524b] | 886 | uint32_t value; |
---|
| 887 | uint8_t interrupt; |
---|
[c22aeb4] | 888 | #endif |
---|
[01b6ca9] | 889 | int pbus, pdev, pfun; |
---|
[bb9e843] | 890 | #if defined(__PPC__) |
---|
[cc4c524b] | 891 | int tmp; |
---|
| 892 | uint32_t lvalue; |
---|
[01b6ca9] | 893 | #endif |
---|
| 894 | |
---|
| 895 | /* |
---|
| 896 | * Get the instance number for the board we're going to configure |
---|
| 897 | * from the user. |
---|
| 898 | */ |
---|
[ac8f462] | 899 | if( (unitNumber = rtems_bsdnet_parse_driver_name(config, &unitName)) == -1 ) |
---|
[01b6ca9] | 900 | { |
---|
| 901 | return 0; |
---|
| 902 | } |
---|
| 903 | if( strcmp(unitName, DRIVER_PREFIX) ) |
---|
| 904 | { |
---|
| 905 | printk("dec2114x : unit name '%s' not %s\n", unitName, DRIVER_PREFIX ); |
---|
| 906 | return 0; |
---|
| 907 | } |
---|
| 908 | |
---|
| 909 | /* |
---|
| 910 | * Find the board |
---|
| 911 | */ |
---|
[bb9e843] | 912 | if ( pci_find_device(PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_21140, |
---|
| 913 | unitNumber-1, &pbus, &pdev, &pfun) == -1 ) { |
---|
| 914 | if ( pci_find_device(PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_21143, |
---|
| 915 | unitNumber-1, &pbus, &pdev, &pfun) != -1 ) { |
---|
[01b6ca9] | 916 | |
---|
[bb9e843] | 917 | /* the 21143 chip must be enabled before it can be accessed */ |
---|
| 918 | #if defined(__i386__) |
---|
[a8e1959] | 919 | pci_write_config_dword(pbus, pdev, pfun, 0x40, 0 ); |
---|
[bb9e843] | 920 | #else |
---|
| 921 | pci_write_config_dword(pbus, pdev, pfun, 0x40, PCI_DEVICE_ID_DEC_21143); |
---|
| 922 | #endif |
---|
[01b6ca9] | 923 | |
---|
[bb9e843] | 924 | } else { |
---|
[01b6ca9] | 925 | printk("dec2114x : device '%s' not found on PCI bus\n", config->name ); |
---|
| 926 | return 0; |
---|
| 927 | } |
---|
| 928 | } |
---|
| 929 | |
---|
| 930 | #ifdef DEC_DEBUG |
---|
[bb9e843] | 931 | else { |
---|
[a3d3d9a] | 932 | printk("dec21140 : found device '%s', bus 0x%02x, dev 0x%02x, func 0x%02x\n", |
---|
[01b6ca9] | 933 | config->name, pbus, pdev, pfun); |
---|
| 934 | } |
---|
| 935 | #endif |
---|
| 936 | |
---|
| 937 | if ((unitNumber < 1) || (unitNumber > NDECDRIVER)) |
---|
| 938 | { |
---|
[5ce0489] | 939 | printk("dec2114x : unit %i is invalid, must be (1 <= n <= %d)\n", |
---|
| 940 | unitNumber, NDECDRIVER); |
---|
[01b6ca9] | 941 | return 0; |
---|
| 942 | } |
---|
| 943 | |
---|
| 944 | sc = &dec21140_softc[unitNumber - 1]; |
---|
| 945 | ifp = &sc->arpcom.ac_if; |
---|
[a3d3d9a] | 946 | if (ifp->if_softc != NULL) |
---|
[01b6ca9] | 947 | { |
---|
| 948 | printk("dec2114x : unit %i already in use.\n", unitNumber ); |
---|
| 949 | return 0; |
---|
| 950 | } |
---|
| 951 | |
---|
| 952 | |
---|
| 953 | /* |
---|
| 954 | ** Get this unit's rx/tx event |
---|
| 955 | */ |
---|
| 956 | sc->ioevent = unit_signals[unitNumber-1]; |
---|
| 957 | |
---|
[96e62937] | 958 | /* |
---|
[a3d3d9a] | 959 | ** Save the buffer counts |
---|
[96e62937] | 960 | */ |
---|
| 961 | sc->numRxbuffers = (config->rbuf_count) ? config->rbuf_count : NRXBUFS; |
---|
| 962 | sc->numTxbuffers = (config->xbuf_count) ? config->xbuf_count : NTXBUFS; |
---|
| 963 | |
---|
[01b6ca9] | 964 | |
---|
| 965 | /* |
---|
| 966 | * Get card address spaces & retrieve its isr vector |
---|
| 967 | */ |
---|
[f7b46db] | 968 | #if defined(__i386__) |
---|
[df49c60] | 969 | |
---|
[a8e1959] | 970 | pci_read_config_dword(pbus, pdev, pfun, 16, &value); |
---|
[01b6ca9] | 971 | sc->port = value & ~IO_MASK; |
---|
[a3d3d9a] | 972 | |
---|
[a8e1959] | 973 | pci_read_config_dword(pbus, pdev, pfun, 20, &value); |
---|
[01b6ca9] | 974 | if (_CPU_is_paging_enabled()) |
---|
| 975 | _CPU_map_phys_address((void **) &(sc->base), |
---|
| 976 | (void *)(value & ~MEM_MASK), |
---|
| 977 | DEC_REGISTER_SIZE , |
---|
| 978 | PTE_CACHE_DISABLE | PTE_WRITABLE); |
---|
| 979 | else |
---|
[cc4c524b] | 980 | sc->base = (uint32_t *)(value & ~MEM_MASK); |
---|
[a3d3d9a] | 981 | |
---|
[a8e1959] | 982 | pci_read_config_byte(pbus, pdev, pfun, 60, &interrupt); |
---|
[01b6ca9] | 983 | cvalue = interrupt; |
---|
[5a820308] | 984 | #endif |
---|
[51b9899] | 985 | #if defined(__PPC__) |
---|
[01b6ca9] | 986 | (void)pci_read_config_dword(pbus, |
---|
| 987 | pdev, |
---|
| 988 | pfun, |
---|
| 989 | PCI_BASE_ADDRESS_0, |
---|
| 990 | &lvalue); |
---|
[5a820308] | 991 | |
---|
[01b6ca9] | 992 | sc->port = lvalue & (unsigned int)(~IO_MASK); |
---|
[a3d3d9a] | 993 | |
---|
[01b6ca9] | 994 | (void)pci_read_config_dword(pbus, |
---|
| 995 | pdev, |
---|
| 996 | pfun, |
---|
| 997 | PCI_BASE_ADDRESS_1, |
---|
| 998 | &lvalue); |
---|
| 999 | |
---|
[a3d3d9a] | 1000 | tmp = (unsigned int)(lvalue & (unsigned int)(~MEM_MASK)) |
---|
[cc2fcc1] | 1001 | + (unsigned int)PCI_MEM_BASE; |
---|
[01b6ca9] | 1002 | |
---|
[f36eeb3] | 1003 | sc->base = (uint32_t*)(tmp); |
---|
[01b6ca9] | 1004 | |
---|
| 1005 | pci_read_config_byte(pbus, |
---|
| 1006 | pdev, |
---|
| 1007 | pfun, |
---|
| 1008 | PCI_INTERRUPT_LINE, |
---|
| 1009 | &cvalue); |
---|
| 1010 | |
---|
[5a820308] | 1011 | #endif |
---|
[01b6ca9] | 1012 | |
---|
| 1013 | /* |
---|
| 1014 | ** Prep the board |
---|
| 1015 | */ |
---|
[96e62937] | 1016 | |
---|
[01b6ca9] | 1017 | pci_write_config_word(pbus, pdev, pfun, |
---|
[cd38196f] | 1018 | PCI_COMMAND, |
---|
| 1019 | (uint16_t) ( PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER ) ); |
---|
[01b6ca9] | 1020 | |
---|
| 1021 | /* |
---|
| 1022 | ** Store the interrupt name, we'll use it later when we initialize |
---|
| 1023 | ** the board. |
---|
| 1024 | */ |
---|
| 1025 | memset(&sc->irqInfo,0,sizeof(rtems_irq_connect_data)); |
---|
| 1026 | sc->irqInfo.name = cvalue; |
---|
| 1027 | |
---|
| 1028 | |
---|
[ac8f462] | 1029 | #ifdef DEC_DEBUG |
---|
[5ce0489] | 1030 | printk("dec2114x : unit %d base address %p.\n", unitNumber, sc->base); |
---|
[ac8f462] | 1031 | #endif |
---|
[01b6ca9] | 1032 | |
---|
| 1033 | |
---|
| 1034 | /* |
---|
| 1035 | ** Setup ethernet address |
---|
| 1036 | */ |
---|
| 1037 | if (config->hardware_address) { |
---|
| 1038 | memcpy (sc->arpcom.ac_enaddr, config->hardware_address, |
---|
| 1039 | ETHER_ADDR_LEN); |
---|
| 1040 | } |
---|
| 1041 | else { |
---|
| 1042 | union {char c[64]; unsigned short s[32];} rombuf; |
---|
| 1043 | int i; |
---|
| 1044 | |
---|
| 1045 | for (i=0; i<32; i++){ |
---|
| 1046 | rombuf.s[i] = eeget16( sc->base + memCSR9, i); |
---|
| 1047 | } |
---|
[f7b46db] | 1048 | #if defined(__i386__) |
---|
[01b6ca9] | 1049 | for (i=0 ; i<(ETHER_ADDR_LEN/2); i++){ |
---|
| 1050 | sc->arpcom.ac_enaddr[2*i] = rombuf.c[20+2*i+1]; |
---|
| 1051 | sc->arpcom.ac_enaddr[2*i+1] = rombuf.c[20+2*i]; |
---|
[a3d3d9a] | 1052 | } |
---|
[38b81b5] | 1053 | #endif |
---|
[51b9899] | 1054 | #if defined(__PPC__) |
---|
[01b6ca9] | 1055 | memcpy (sc->arpcom.ac_enaddr, rombuf.c+20, ETHER_ADDR_LEN); |
---|
| 1056 | #endif |
---|
| 1057 | } |
---|
| 1058 | |
---|
| 1059 | if (config->mtu) |
---|
| 1060 | mtu = config->mtu; |
---|
| 1061 | else |
---|
| 1062 | mtu = ETHERMTU; |
---|
| 1063 | |
---|
| 1064 | sc->acceptBroadcast = !config->ignore_broadcast; |
---|
| 1065 | |
---|
| 1066 | /* |
---|
| 1067 | * Set up network interface values |
---|
| 1068 | */ |
---|
| 1069 | |
---|
| 1070 | /* ifp->if_tap = iftap; */ |
---|
| 1071 | |
---|
| 1072 | ifp->if_softc = sc; |
---|
| 1073 | ifp->if_unit = unitNumber; |
---|
| 1074 | ifp->if_name = unitName; |
---|
| 1075 | ifp->if_mtu = mtu; |
---|
| 1076 | ifp->if_init = dec21140_init; |
---|
| 1077 | ifp->if_ioctl = dec21140_ioctl; |
---|
| 1078 | ifp->if_start = dec21140_start; |
---|
| 1079 | ifp->if_output = ether_output; |
---|
| 1080 | ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX; |
---|
| 1081 | if (ifp->if_snd.ifq_maxlen == 0) |
---|
| 1082 | ifp->if_snd.ifq_maxlen = ifqmaxlen; |
---|
| 1083 | |
---|
| 1084 | /* |
---|
| 1085 | * Attach the interface |
---|
| 1086 | */ |
---|
| 1087 | if_attach (ifp); |
---|
| 1088 | ether_ifattach (ifp); |
---|
| 1089 | |
---|
| 1090 | #ifdef DEC_DEBUG |
---|
| 1091 | printk( "dec2114x : driver attached\n" ); |
---|
[38b81b5] | 1092 | #endif |
---|
[01b6ca9] | 1093 | |
---|
| 1094 | /* |
---|
| 1095 | * Start driver tasks if this is the first dec unit initialized |
---|
| 1096 | */ |
---|
[a3d3d9a] | 1097 | if (txDaemonTid == 0) |
---|
[01b6ca9] | 1098 | { |
---|
| 1099 | rxDaemonTid = rtems_bsdnet_newproc( "DCrx", 4096, |
---|
| 1100 | dec21140_rxDaemon, NULL); |
---|
[a3d3d9a] | 1101 | |
---|
[01b6ca9] | 1102 | txDaemonTid = rtems_bsdnet_newproc( "DCtx", 4096, |
---|
| 1103 | dec21140_txDaemon, NULL); |
---|
| 1104 | #ifdef DEC_DEBUG |
---|
| 1105 | printk( "dec2114x : driver tasks created\n" ); |
---|
| 1106 | #endif |
---|
| 1107 | } |
---|
| 1108 | |
---|
| 1109 | return 1; |
---|
[1094cf0d] | 1110 | }; |
---|
[01b6ca9] | 1111 | |
---|
[a1efd7a] | 1112 | #endif /* DEC21140_SUPPORTED */ |
---|