|
|
1.1 ! root 1: /* Previous - ethernet.c ! 2: ! 3: This file is distributed under the GNU Public License, version 2 or at ! 4: your option any later version. Read the file gpl.txt for details. ! 5: ! 6: Network adapter for non-turbo and turbo NeXT machines. ! 7: ! 8: */ ! 9: ! 10: #include "ioMem.h" ! 11: #include "ioMemTables.h" ! 12: #include "m68000.h" ! 13: #include "configuration.h" ! 14: #include "sysReg.h" ! 15: #include "dma.h" ! 16: #include "bmap.h" ! 17: #include "ethernet.h" ! 18: #include "enet_slirp.h" ! 19: #include "enet_pcap.h" ! 20: #include "cycInt.h" ! 21: #include "statusbar.h" ! 22: ! 23: ! 24: #define LOG_EN_LEVEL LOG_DEBUG ! 25: #define LOG_EN_REG_LEVEL LOG_DEBUG ! 26: #define LOG_EN_DATA 0 ! 27: ! 28: #define IO_SEG_MASK 0x1FFFF ! 29: ! 30: ! 31: struct { ! 32: Uint8 tx_status; ! 33: Uint8 tx_mask; ! 34: Uint8 tx_mode; ! 35: Uint8 rx_status; ! 36: Uint8 rx_mask; ! 37: Uint8 rx_mode; ! 38: Uint8 reset; ! 39: ! 40: Uint8 mac_addr[6]; ! 41: } enet; ! 42: ! 43: bool enet_stopped; ! 44: ! 45: #define TXSTAT_READY 0x80 /* r */ ! 46: #define TXSTAT_NET_BUSY 0x40 /* r */ ! 47: #define TXSTAT_TX_RECVD 0x20 /* r */ ! 48: #define TXSTAT_SHORTED 0x10 /* r */ ! 49: #define TXSTAT_UNDERFLOW 0x08 /* rw */ ! 50: #define TXSTAT_COLL 0x04 /* rw */ ! 51: #define TXSTAT_16COLLS 0x02 /* rw */ ! 52: #define TXSTAT_PAR_ERR 0x01 /* rw */ ! 53: ! 54: #define TXMASK_PKT_RDY 0x80 ! 55: #define TXMASK_TX_RECVD 0x20 ! 56: #define TXMASK_UNDERFLOW 0x08 ! 57: #define TXMASK_COLL 0x04 ! 58: #define TXMASK_16COLLS 0x02 ! 59: #define TXMASK_PAR_ERR 0x01 ! 60: ! 61: #define RXSTAT_PKT_OK 0x80 /* rw */ ! 62: #define RXSTAT_RESET_PKT 0x10 /* r */ ! 63: #define RXSTAT_SHORT_PKT 0x08 /* rw */ ! 64: #define RXSTAT_ALIGN_ERR 0x04 /* rw */ ! 65: #define RXSTAT_CRC_ERR 0x02 /* rw */ ! 66: #define RXSTAT_OVERFLOW 0x01 /* rw */ ! 67: ! 68: #define RXMASK_PKT_OK 0x80 ! 69: #define RXMASK_RESET_PKT 0x10 ! 70: #define RXMASK_SHORT_PKT 0x80 ! 71: #define RXMASK_ALIGN_ERR 0x40 ! 72: #define RXMASK_CRC_ERR 0x20 ! 73: #define RXMASK_OVERFLOW 0x10 ! 74: ! 75: #define TXMODE_COLL_ATMPT 0xF0 /* r */ ! 76: #define TXMODE_IGNORE_PAR 0x08 /* rw */ ! 77: #define TXMODE_TM 0x04 /* rw */ ! 78: #define TXMODE_DIS_LOOP 0x02 /* rw */ ! 79: #define TXMODE_DIS_CONTNT 0x01 /* rw */ ! 80: ! 81: #define RXMODE_TEST_CRC 0x80 ! 82: #define RXMODE_ADDR_SIZE 0x10 ! 83: #define RXMODE_ENA_SHORT 0x08 ! 84: #define RXMODE_ENA_RST 0x04 ! 85: #define RXMODE_MATCH_MODE 0x03 ! 86: ! 87: #define EN_RESET 0x80 /* w */ ! 88: ! 89: ! 90: void enet_reset(void); ! 91: ! 92: void (*enet_output)(void); ! 93: void (*enet_input)(Uint8 *pkt, int pkt_len); ! 94: void (*enet_start)(Uint8 *mac); ! 95: void (*enet_stop)(void); ! 96: ! 97: void EN_TX_Status_Read(void) { // 0x02006000 ! 98: IoMem[IoAccessCurrentAddress & IO_SEG_MASK] = enet.tx_status; ! 99: Log_Printf(LOG_EN_REG_LEVEL,"[EN] Transmitter status read at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc()); ! 100: } ! 101: ! 102: void EN_TX_Status_Write(void) { ! 103: Uint8 val=IoMem[IoAccessCurrentAddress & IO_SEG_MASK]; ! 104: Log_Printf(LOG_EN_REG_LEVEL,"[EN] Transmitter status write at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc()); ! 105: if (ConfigureParams.System.bTurbo) { ! 106: enet.tx_status&=~val; ! 107: } else { ! 108: enet.tx_status&=~(val&0x0F); ! 109: } ! 110: ! 111: if ((enet.tx_status&enet.tx_mask&0x0F)==0) { ! 112: set_interrupt(INT_EN_TX, RELEASE_INT); ! 113: } ! 114: } ! 115: ! 116: void EN_TX_Mask_Read(void) { // 0x02006001 ! 117: IoMem[IoAccessCurrentAddress & IO_SEG_MASK] = enet.tx_mask&0xAF; ! 118: Log_Printf(LOG_EN_REG_LEVEL,"[EN] Transmitter masks read at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc()); ! 119: } ! 120: ! 121: void EN_TX_Mask_Write(void) { ! 122: enet.tx_mask=IoMem[IoAccessCurrentAddress & IO_SEG_MASK]; ! 123: Log_Printf(LOG_EN_REG_LEVEL,"[EN] Transmitter masks write at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc()); ! 124: ! 125: if ((enet.tx_status&enet.tx_mask&0x0F)==0) { ! 126: set_interrupt(INT_EN_TX, RELEASE_INT); ! 127: } ! 128: } ! 129: ! 130: void EN_RX_Status_Read(void) { // 0x02006002 ! 131: IoMem[IoAccessCurrentAddress & IO_SEG_MASK] = enet.rx_status; ! 132: Log_Printf(LOG_EN_REG_LEVEL,"[EN] Receiver status read at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc()); ! 133: } ! 134: ! 135: void EN_RX_Status_Write(void) { ! 136: Uint8 val=IoMem[IoAccessCurrentAddress & IO_SEG_MASK]; ! 137: Log_Printf(LOG_EN_REG_LEVEL,"[EN] Receiver status write at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc()); ! 138: enet.rx_status&=~(val&0x8F); ! 139: ! 140: if ((enet.rx_status&enet.rx_mask&0x8F)==0) { ! 141: set_interrupt(INT_EN_RX, RELEASE_INT); ! 142: } ! 143: } ! 144: ! 145: void EN_RX_Mask_Read(void) { // 0x02006003 ! 146: IoMem[IoAccessCurrentAddress & IO_SEG_MASK] = enet.rx_mask&0x9F; ! 147: Log_Printf(LOG_EN_REG_LEVEL,"[EN] Receiver masks read at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc()); ! 148: } ! 149: ! 150: void EN_RX_Mask_Write(void) { ! 151: enet.rx_mask=IoMem[IoAccessCurrentAddress & IO_SEG_MASK]; ! 152: Log_Printf(LOG_EN_REG_LEVEL,"[EN] Receiver masks write at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc()); ! 153: ! 154: if ((enet.rx_status&enet.rx_mask&0x8F)==0) { ! 155: set_interrupt(INT_EN_RX, RELEASE_INT); ! 156: } ! 157: } ! 158: ! 159: void EN_TX_Mode_Read(void) { // 0x02006004 ! 160: IoMem[IoAccessCurrentAddress & IO_SEG_MASK] = enet.tx_mode; ! 161: Log_Printf(LOG_EN_REG_LEVEL,"[EN] Transmitter mode read at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc()); ! 162: } ! 163: ! 164: void EN_TX_Mode_Write(void) { ! 165: enet.tx_mode=IoMem[IoAccessCurrentAddress & IO_SEG_MASK]; ! 166: Log_Printf(LOG_EN_REG_LEVEL,"[EN] Transmitter mode write at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc()); ! 167: } ! 168: ! 169: void EN_RX_Mode_Read(void) { // 0x02006005 ! 170: IoMem[IoAccessCurrentAddress & IO_SEG_MASK] = enet.rx_mode; ! 171: Log_Printf(LOG_EN_REG_LEVEL,"[EN] Receiver mode read at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc()); ! 172: } ! 173: ! 174: void EN_RX_Mode_Write(void) { ! 175: enet.rx_mode=IoMem[IoAccessCurrentAddress & IO_SEG_MASK]; ! 176: Log_Printf(LOG_EN_REG_LEVEL,"[EN] Receiver mode write at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc()); ! 177: } ! 178: ! 179: void EN_Reset_Write(void) { // 0x02006006 ! 180: enet.reset=IoMem[IoAccessCurrentAddress & IO_SEG_MASK]; ! 181: Log_Printf(LOG_EN_REG_LEVEL,"[EN] Reset write at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc()); ! 182: enet_reset(); ! 183: } ! 184: ! 185: void EN_NodeID0_Read(void) { // 0x02006008 ! 186: IoMem[IoAccessCurrentAddress & IO_SEG_MASK] = enet.mac_addr[0]; ! 187: Log_Printf(LOG_EN_REG_LEVEL,"[EN] MAC byte 0 read at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc()); ! 188: } ! 189: ! 190: void EN_NodeID0_Write(void) { ! 191: enet.mac_addr[0]=IoMem[IoAccessCurrentAddress & IO_SEG_MASK]; ! 192: Log_Printf(LOG_EN_REG_LEVEL,"[EN] MAC byte 0 write at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc()); ! 193: } ! 194: ! 195: void EN_NodeID1_Read(void) { // 0x02006009 ! 196: IoMem[IoAccessCurrentAddress & IO_SEG_MASK] = enet.mac_addr[1]; ! 197: Log_Printf(LOG_EN_REG_LEVEL,"[EN] MAC byte 1 read at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc()); ! 198: } ! 199: ! 200: void EN_NodeID1_Write(void) { ! 201: enet.mac_addr[1]=IoMem[IoAccessCurrentAddress & IO_SEG_MASK]; ! 202: Log_Printf(LOG_EN_REG_LEVEL,"[EN] MAC byte 1 write at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc()); ! 203: } ! 204: ! 205: void EN_NodeID2_Read(void) { // 0x0200600a ! 206: IoMem[IoAccessCurrentAddress & IO_SEG_MASK] = enet.mac_addr[2]; ! 207: Log_Printf(LOG_EN_REG_LEVEL,"[EN] MAC byte 2 read at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc()); ! 208: } ! 209: ! 210: void EN_NodeID2_Write(void) { ! 211: enet.mac_addr[2]=IoMem[IoAccessCurrentAddress & IO_SEG_MASK]; ! 212: Log_Printf(LOG_EN_REG_LEVEL,"[EN] MAC byte 2 write at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc()); ! 213: } ! 214: ! 215: void EN_NodeID3_Read(void) { // 0x0200600b ! 216: IoMem[IoAccessCurrentAddress & IO_SEG_MASK] = enet.mac_addr[3]; ! 217: Log_Printf(LOG_EN_REG_LEVEL,"[EN] MAC byte 3 read at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc()); ! 218: } ! 219: ! 220: void EN_NodeID3_Write(void) { ! 221: enet.mac_addr[3]=IoMem[IoAccessCurrentAddress & IO_SEG_MASK]; ! 222: Log_Printf(LOG_EN_REG_LEVEL,"[EN] MAC byte 3 write at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc()); ! 223: } ! 224: ! 225: void EN_NodeID4_Read(void) { // 0x0200600c ! 226: IoMem[IoAccessCurrentAddress & IO_SEG_MASK] = enet.mac_addr[4]; ! 227: Log_Printf(LOG_EN_REG_LEVEL,"[EN] MAC byte 4 read at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc()); ! 228: } ! 229: ! 230: void EN_NodeID4_Write(void) { ! 231: enet.mac_addr[4]=IoMem[IoAccessCurrentAddress & IO_SEG_MASK]; ! 232: Log_Printf(LOG_EN_REG_LEVEL,"[EN] MAC byte 4 write at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc()); ! 233: } ! 234: ! 235: void EN_NodeID5_Read(void) { // 0x0200600d ! 236: IoMem[IoAccessCurrentAddress & IO_SEG_MASK] = enet.mac_addr[5]; ! 237: Log_Printf(LOG_EN_REG_LEVEL,"[EN] MAC byte 5 read at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc()); ! 238: } ! 239: ! 240: void EN_NodeID5_Write(void) { ! 241: enet.mac_addr[5]=IoMem[IoAccessCurrentAddress & IO_SEG_MASK]; ! 242: Log_Printf(LOG_EN_REG_LEVEL,"[EN] MAC byte 5 write at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc()); ! 243: } ! 244: ! 245: void EN_CounterLo_Read(void) { // 0x02006007 ! 246: IoMem[IoAccessCurrentAddress & IO_SEG_MASK] = ((enet_tx_buffer.limit-enet_tx_buffer.size)*8)&0xFF; /* FIXME: counter value */ ! 247: Log_Printf(LOG_EN_REG_LEVEL,"[EN] Receiver mode read at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc()); ! 248: } ! 249: ! 250: void EN_CounterHi_Read(void) { // 0x0200600f ! 251: IoMem[IoAccessCurrentAddress & IO_SEG_MASK] = (((enet_tx_buffer.limit-enet_tx_buffer.size)*8)>>8)&0x3F; /* FIXME: counter value */ ! 252: Log_Printf(LOG_EN_REG_LEVEL,"[EN] Receiver mode read at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc()); ! 253: } ! 254: ! 255: static void enet_tx_interrupt(Uint8 intr) { ! 256: enet.tx_status|=intr; ! 257: if (enet.tx_status&enet.tx_mask) { ! 258: set_interrupt(INT_EN_TX, SET_INT); ! 259: } ! 260: } ! 261: ! 262: static void enet_rx_interrupt(Uint8 intr) { ! 263: enet.rx_status|=intr; ! 264: if (enet.rx_status&enet.rx_mask) { ! 265: set_interrupt(INT_EN_RX, SET_INT); ! 266: } ! 267: } ! 268: ! 269: /* Functions to find out if we are intended to receive a packet */ ! 270: ! 271: /* Non-turbo */ ! 272: #define RX_NOPACKETS 0 // Accept no packets ! 273: #define RX_LIMITED 1 // Accept broadcast/limited ! 274: #define RX_NORMAL 2 // Accept broadcast/multicast ! 275: #define RX_PROMISCUOUS 3 // Accept all packets ! 276: ! 277: /* Turbo */ ! 278: #define RX_ENABLED 0x80 // Accept packets ! 279: #define RX_ANY 0x01 // Accept any packets ! 280: #define RX_OWN 0x02 // Accept own packets ! 281: ! 282: static bool recv_multicast(Uint8 *packet) { ! 283: if (packet[0]&0x01) ! 284: return true; ! 285: else ! 286: return false; ! 287: } ! 288: ! 289: static bool recv_local_multicast(Uint8 *packet) { ! 290: if (packet[0]&0x01 && ! 291: (packet[0]&0xFE) == enet.mac_addr[0] && ! 292: packet[1] == enet.mac_addr[1] && ! 293: packet[2] == enet.mac_addr[2]) ! 294: return true; ! 295: else ! 296: return false; ! 297: } ! 298: ! 299: static bool recv_me(Uint8 *packet) { ! 300: if (packet[0] == enet.mac_addr[0] && ! 301: packet[1] == enet.mac_addr[1] && ! 302: packet[2] == enet.mac_addr[2] && ! 303: packet[3] == enet.mac_addr[3] && ! 304: packet[4] == enet.mac_addr[4] && ! 305: (packet[5] == enet.mac_addr[5] || (enet.rx_mode&RXMODE_ADDR_SIZE))) ! 306: return true; ! 307: else ! 308: return false; ! 309: } ! 310: ! 311: static bool recv_me_turbo(Uint8 *packet) { ! 312: if (packet[0] == enet.mac_addr[0] && ! 313: packet[1] == enet.mac_addr[1] && ! 314: packet[2] == enet.mac_addr[2] && ! 315: packet[3] == enet.mac_addr[3] && ! 316: packet[4] == enet.mac_addr[4] && ! 317: packet[5] == enet.mac_addr[5]) ! 318: return true; ! 319: else ! 320: return false; ! 321: } ! 322: ! 323: static bool recv_broadcast(Uint8 *packet) { ! 324: if (packet[0] == 0xFF && ! 325: packet[1] == 0xFF && ! 326: packet[2] == 0xFF && ! 327: packet[3] == 0xFF && ! 328: packet[4] == 0xFF && ! 329: packet[5] == 0xFF) ! 330: return true; ! 331: else ! 332: return false; ! 333: } ! 334: ! 335: static bool enet_packet_for_me(Uint8 *packet) { ! 336: ! 337: if (ConfigureParams.System.bTurbo) { ! 338: if (enet.rx_mode&RX_ENABLED) { ! 339: if (enet.rx_mode&RX_ANY) { ! 340: return true; ! 341: } else if (enet.rx_mode&RX_OWN) { ! 342: if (recv_broadcast(packet) || recv_me_turbo(packet)) { ! 343: return true; ! 344: } ! 345: } else { ! 346: if (recv_broadcast(packet)) { ! 347: return true; ! 348: } ! 349: } ! 350: } ! 351: return false; ! 352: } ! 353: ! 354: switch (enet.rx_mode&RXMODE_MATCH_MODE) { ! 355: case RX_NOPACKETS: ! 356: return false; ! 357: ! 358: case RX_LIMITED: ! 359: if (recv_broadcast(packet) || recv_me(packet) || recv_local_multicast(packet)) ! 360: return true; ! 361: else ! 362: return false; ! 363: ! 364: case RX_NORMAL: ! 365: if (recv_broadcast(packet) || recv_me(packet) || recv_multicast(packet)) ! 366: return true; ! 367: else ! 368: return false; ! 369: ! 370: case RX_PROMISCUOUS: ! 371: return true; ! 372: ! 373: default: return false; ! 374: } ! 375: } ! 376: ! 377: void enet_receive(Uint8 *pkt, int len) { ! 378: if (enet_packet_for_me(pkt)) { ! 379: #if 1 /* Hack for short packets from SLIRP */ ! 380: if (len<60) { ! 381: Log_Printf(LOG_WARN, "[EN] HACK: short packet received (%i byte). Fixed.", len); ! 382: len = 60; ! 383: } ! 384: #endif ! 385: memcpy(enet_rx_buffer.data,pkt,len); ! 386: enet_rx_buffer.size=enet_rx_buffer.limit=len; ! 387: enet.tx_status |= TXSTAT_NET_BUSY; ! 388: } else { ! 389: Log_Printf(LOG_WARN, "[EN] Packet is not for me."); ! 390: } ! 391: } ! 392: ! 393: static void print_buf(Uint8 *buf, Uint32 size) { ! 394: #if LOG_EN_DATA ! 395: int i; ! 396: for (i=0; i<size; i++) { ! 397: if (i==14 || (i-14)%16==0) { ! 398: printf("\n"); ! 399: } ! 400: printf("%02X ",buf[i]); ! 401: } ! 402: printf("\n"); ! 403: #endif ! 404: } ! 405: ! 406: ! 407: #define ENET_FRAMESIZE_MIN 64 /* 46 byte data and 14 byte header, 4 byte CRC */ ! 408: #define ENET_FRAMESIZE_MAX 1518 /* 1500 byte data and 14 byte header, 4 byte CRC */ ! 409: ! 410: /* Ethernet periodic check */ ! 411: #define ENET_IO_DELAY 500 /* use 500 for NeXT hardware test, 20 for status test */ ! 412: #define ENET_IO_SHORT 40 /* use 40 for 68030 hardware test */ ! 413: ! 414: enum { ! 415: RECV_STATE_WAITING, ! 416: RECV_STATE_RECEIVING ! 417: } receiver_state; ! 418: ! 419: bool tx_done; ! 420: bool rx_chain; ! 421: int old_size; ! 422: int en_state; ! 423: ! 424: #define EN_DISCONNECTED 0 ! 425: #define EN_LOOPBACK 1 ! 426: #define EN_THINWIRE 2 ! 427: #define EN_TWISTEDPAIR 3 ! 428: ! 429: /* Fujitsu ethernet controller */ ! 430: static int enet_state(void) { ! 431: if (ConfigureParams.System.nMachineType == NEXT_CUBE030) { ! 432: if (enet.tx_mode&TXMODE_DIS_LOOP) { ! 433: if (ConfigureParams.Ethernet.bEthernetConnected) { ! 434: return EN_THINWIRE; ! 435: } ! 436: } else { ! 437: return EN_LOOPBACK; ! 438: } ! 439: } else if (bmap_tpe_select) { ! 440: if (ConfigureParams.Ethernet.bEthernetConnected) { ! 441: if (ConfigureParams.Ethernet.bTwistedPair) { ! 442: return EN_TWISTEDPAIR; ! 443: } ! 444: } ! 445: } else { ! 446: if (enet.tx_mode&TXMODE_DIS_LOOP) { ! 447: if (ConfigureParams.Ethernet.bEthernetConnected) { ! 448: if (!ConfigureParams.Ethernet.bTwistedPair) { ! 449: return EN_THINWIRE; ! 450: } ! 451: } ! 452: } else { ! 453: return EN_LOOPBACK; ! 454: } ! 455: } ! 456: return EN_DISCONNECTED; ! 457: } ! 458: ! 459: static void enet_io(void) { ! 460: ! 461: en_state = enet_state(); ! 462: ! 463: /* Receive packet */ ! 464: switch (receiver_state) { ! 465: case RECV_STATE_WAITING: ! 466: if (enet_rx_buffer.size>0) { ! 467: Statusbar_BlinkLed(DEVICE_LED_ENET); ! 468: Log_Printf(LOG_EN_LEVEL, "[EN] Receiving packet from %02X:%02X:%02X:%02X:%02X:%02X", ! 469: enet_rx_buffer.data[6], enet_rx_buffer.data[7], enet_rx_buffer.data[8], ! 470: enet_rx_buffer.data[9], enet_rx_buffer.data[10], enet_rx_buffer.data[11]); ! 471: print_buf(enet_rx_buffer.data, enet_rx_buffer.size); ! 472: enet_rx_buffer.size+=4; ! 473: enet_rx_buffer.limit+=4; ! 474: rx_chain = false; ! 475: enet.rx_status&=~RXSTAT_PKT_OK; ! 476: if (enet_rx_buffer.size<ENET_FRAMESIZE_MIN && !(enet.rx_mode&RXMODE_ENA_SHORT)) { ! 477: Log_Printf(LOG_WARN, "[EN] Received packet is short (%i byte)",enet_rx_buffer.size); ! 478: enet_rx_interrupt(RXSTAT_SHORT_PKT); ! 479: enet_rx_buffer.size = 0; ! 480: enet.tx_status &= ~TXSTAT_NET_BUSY; ! 481: break; /* Keep on waiting for a good packet */ ! 482: } else /* Fall through to receiving state */ ! 483: receiver_state = RECV_STATE_RECEIVING; ! 484: } else if (en_state == EN_THINWIRE || en_state == EN_TWISTEDPAIR) { ! 485: /* Receive from real world network */ ! 486: enet_output(); ! 487: break; ! 488: } else ! 489: break; ! 490: case RECV_STATE_RECEIVING: ! 491: if (enet_rx_buffer.size>0) { ! 492: old_size = enet_rx_buffer.size; ! 493: dma_enet_write_memory(rx_chain); ! 494: if (enet_rx_buffer.size==old_size) { ! 495: Log_Printf(LOG_WARN, "[EN] Receiving packet: Error! Receiver overflow (DMA disabled)!"); ! 496: enet_rx_interrupt(RXSTAT_OVERFLOW); ! 497: rx_chain = false; ! 498: enet_rx_buffer.size = 0; ! 499: enet.tx_status &= ~TXSTAT_NET_BUSY; ! 500: receiver_state = RECV_STATE_WAITING; ! 501: break; /* Go back to waiting state */ ! 502: } ! 503: if (enet_rx_buffer.size>0) { ! 504: Log_Printf(LOG_WARN, "[EN] Receiving packet: Transfer not complete!"); ! 505: rx_chain = true; ! 506: break; /* Loop in receiving state */ ! 507: } else { /* done */ ! 508: Log_Printf(LOG_EN_LEVEL, "[EN] Receiving packet: Transfer complete."); ! 509: rx_chain = false; ! 510: enet_rx_interrupt(RXSTAT_PKT_OK); ! 511: if (en_state == EN_LOOPBACK) { /* same for thin wire loopback? */ ! 512: enet_tx_interrupt(TXSTAT_TX_RECVD); ! 513: } ! 514: enet.tx_status &= ~TXSTAT_NET_BUSY; ! 515: receiver_state = RECV_STATE_WAITING; ! 516: } ! 517: } ! 518: break; ! 519: ! 520: default: ! 521: break; ! 522: } ! 523: ! 524: /* Send packet */ ! 525: if (enet.tx_status&TXSTAT_READY) { ! 526: if (en_state != EN_DISCONNECTED) { ! 527: if (enet.tx_status&TXSTAT_NET_BUSY) { ! 528: /* Wait until network is free */ ! 529: Log_Printf(LOG_WARN, "[EN] Network is busy. Transmission delayed."); ! 530: } else { ! 531: old_size = enet_tx_buffer.size; ! 532: tx_done=dma_enet_read_memory(); ! 533: if (enet_tx_buffer.size>0) { ! 534: enet.tx_status &= ~TXSTAT_TX_RECVD; ! 535: if (enet_tx_buffer.size==old_size && !tx_done) { ! 536: Log_Printf(LOG_WARN, "[EN] Sending packet: Error! Transmitter underflow (no EOP)!"); ! 537: enet_tx_interrupt(TXSTAT_UNDERFLOW); ! 538: enet_tx_buffer.size=0; ! 539: } else if (enet_tx_buffer.size>15) { ! 540: enet_tx_buffer.size-=15; ! 541: } else if (tx_done) { ! 542: Log_Printf(LOG_WARN, "[EN] Transmitter error: Early EOP!"); ! 543: enet_tx_buffer.size=0; ! 544: tx_done = false; ! 545: } ! 546: } ! 547: if (tx_done) { ! 548: Statusbar_BlinkLed(DEVICE_LED_ENET); ! 549: Log_Printf(LOG_EN_LEVEL, "[EN] Sending packet to %02X:%02X:%02X:%02X:%02X:%02X", ! 550: enet_tx_buffer.data[0], enet_tx_buffer.data[1], enet_tx_buffer.data[2], ! 551: enet_tx_buffer.data[3], enet_tx_buffer.data[4], enet_tx_buffer.data[5]); ! 552: print_buf(enet_tx_buffer.data, enet_tx_buffer.size); ! 553: if (en_state == EN_LOOPBACK) { ! 554: /* Loop back */ ! 555: Log_Printf(LOG_WARN, "[EN] Loopback packet."); ! 556: enet_receive(enet_tx_buffer.data, enet_tx_buffer.size); ! 557: } else { ! 558: /* Send to real world network */ ! 559: enet_input(enet_tx_buffer.data,enet_tx_buffer.size); ! 560: /* Simultaneously receive packet on thin ethernet */ ! 561: if (en_state == EN_THINWIRE) { ! 562: enet_receive(enet_tx_buffer.data, enet_tx_buffer.size); ! 563: } ! 564: } ! 565: enet_tx_buffer.size=0; ! 566: } ! 567: } ! 568: } ! 569: } ! 570: } ! 571: ! 572: /* AT&T ethernet controller for turbo systems */ ! 573: #define TXMODE_ENABLE 0x80 ! 574: #define RXMODE_ENABLE 0x80 ! 575: #define TXMODE_LOOP 0x02 ! 576: #define TXMODE_TPE 0x04 ! 577: #define ENCTRL_TPE 0x40 ! 578: ! 579: void EN_Control_Read(void) { // 0x02006006 ! 580: Uint8 val = enet.reset; ! 581: if (ConfigureParams.Ethernet.bEthernetConnected && ConfigureParams.Ethernet.bTwistedPair) { ! 582: val &= ~ENCTRL_TPE; ! 583: } else { ! 584: val |= ENCTRL_TPE; ! 585: } ! 586: IoMem[IoAccessCurrentAddress & IO_SEG_MASK] = val; ! 587: Log_Printf(LOG_EN_REG_LEVEL,"[newEN] Control read at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc()); ! 588: } ! 589: ! 590: void EN_Control_Write(void) { ! 591: enet.reset=(IoMem[IoAccessCurrentAddress & IO_SEG_MASK])&EN_RESET; ! 592: Log_Printf(LOG_EN_REG_LEVEL,"[newEN] Control write at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc()); ! 593: enet_reset(); ! 594: } ! 595: ! 596: static int new_enet_state(void) { ! 597: if (enet.tx_mode&TXMODE_LOOP) { ! 598: return EN_LOOPBACK; ! 599: } else if (ConfigureParams.Ethernet.bEthernetConnected) { ! 600: if (enet.tx_mode&TXMODE_TPE) { ! 601: if (ConfigureParams.Ethernet.bTwistedPair) { ! 602: return EN_TWISTEDPAIR; ! 603: } ! 604: } else { ! 605: if (!ConfigureParams.Ethernet.bTwistedPair) { ! 606: return EN_THINWIRE; ! 607: } ! 608: } ! 609: } ! 610: return EN_DISCONNECTED; ! 611: } ! 612: ! 613: static void new_enet_io(void) { ! 614: ! 615: en_state = new_enet_state(); ! 616: ! 617: /* Receive packet */ ! 618: switch (receiver_state) { ! 619: case RECV_STATE_WAITING: ! 620: if (enet_rx_buffer.size>0) { ! 621: Statusbar_BlinkLed(DEVICE_LED_ENET); ! 622: Log_Printf(LOG_EN_LEVEL, "[newEN] Receiving packet from %02X:%02X:%02X:%02X:%02X:%02X", ! 623: enet_rx_buffer.data[6], enet_rx_buffer.data[7], enet_rx_buffer.data[8], ! 624: enet_rx_buffer.data[9], enet_rx_buffer.data[10], enet_rx_buffer.data[11]); ! 625: print_buf(enet_rx_buffer.data, enet_rx_buffer.size); ! 626: enet_rx_buffer.size+=4; ! 627: enet_rx_buffer.limit+=4; ! 628: rx_chain = false; ! 629: enet.rx_status&=~RXSTAT_PKT_OK; ! 630: if (enet_rx_buffer.size<ENET_FRAMESIZE_MIN && !(enet.rx_mode&RXMODE_ENA_SHORT)) { ! 631: Log_Printf(LOG_WARN, "[newEN] Received packet is short (%i byte)",enet_rx_buffer.size); ! 632: enet_rx_interrupt(RXSTAT_SHORT_PKT); ! 633: enet_rx_buffer.size = 0; ! 634: enet.tx_status &= ~TXSTAT_NET_BUSY; ! 635: break; /* Keep on waiting for a good packet */ ! 636: } else /* Fall through to receiving state */ ! 637: receiver_state = RECV_STATE_RECEIVING; ! 638: } else if (en_state == EN_THINWIRE || en_state == EN_TWISTEDPAIR) { ! 639: /* Receive from real world network */ ! 640: enet_output(); ! 641: break; ! 642: } else ! 643: break; ! 644: case RECV_STATE_RECEIVING: ! 645: if (enet_rx_buffer.size>0) { ! 646: old_size = enet_rx_buffer.size; ! 647: dma_enet_write_memory(rx_chain); ! 648: if (enet_rx_buffer.size==old_size) { ! 649: Log_Printf(LOG_WARN, "[newEN] Receiving packet: Error! Receiver overflow (DMA disabled)!"); ! 650: enet_rx_interrupt(RXSTAT_OVERFLOW); ! 651: rx_chain = false; ! 652: enet_rx_buffer.size = 0; ! 653: enet.tx_status &= ~TXSTAT_NET_BUSY; ! 654: receiver_state = RECV_STATE_WAITING; ! 655: break; /* Go back to waiting state */ ! 656: } ! 657: if (enet_rx_buffer.size>0) { ! 658: Log_Printf(LOG_WARN, "[newEN] Receiving packet: Transfer not complete!"); ! 659: rx_chain = true; ! 660: break; /* Loop in receiving state */ ! 661: } else { /* done */ ! 662: Log_Printf(LOG_EN_LEVEL, "[newEN] Receiving packet: Transfer complete."); ! 663: rx_chain = false; ! 664: enet_rx_interrupt(RXSTAT_PKT_OK); ! 665: if (en_state == EN_LOOPBACK) { ! 666: enet_tx_interrupt(TXSTAT_TX_RECVD); ! 667: } ! 668: enet.tx_status &= ~TXSTAT_NET_BUSY; ! 669: receiver_state = RECV_STATE_WAITING; ! 670: } ! 671: } ! 672: break; ! 673: ! 674: default: ! 675: break; ! 676: } ! 677: ! 678: /* Send packet */ ! 679: if (enet.tx_mode&TXMODE_ENABLE) { ! 680: if (en_state != EN_DISCONNECTED) { ! 681: if (enet.tx_status&TXSTAT_NET_BUSY) { ! 682: /* Wait until network is free */ ! 683: Log_Printf(LOG_WARN, "[EN] Network is busy. Transmission delayed."); ! 684: } else { ! 685: dma_enet_read_memory(); ! 686: if (enet_tx_buffer.size>0) { ! 687: Statusbar_BlinkLed(DEVICE_LED_ENET); ! 688: Log_Printf(LOG_EN_LEVEL, "[newEN] Sending packet to %02X:%02X:%02X:%02X:%02X:%02X", ! 689: enet_tx_buffer.data[0], enet_tx_buffer.data[1], enet_tx_buffer.data[2], ! 690: enet_tx_buffer.data[3], enet_tx_buffer.data[4], enet_tx_buffer.data[5]); ! 691: print_buf(enet_tx_buffer.data, enet_tx_buffer.size); ! 692: enet.tx_status &= ~TXSTAT_TX_RECVD; ! 693: if (en_state == EN_LOOPBACK) { ! 694: /* Loop back */ ! 695: Log_Printf(LOG_WARN, "[newEN] Loopback packet."); ! 696: enet_receive(enet_tx_buffer.data, enet_tx_buffer.size); ! 697: } else { ! 698: /* Send to real world network */ ! 699: enet_input(enet_tx_buffer.data,enet_tx_buffer.size); ! 700: /* Simultaneously receive packet on thin ethernet */ ! 701: if (en_state == EN_THINWIRE) { ! 702: enet_receive(enet_tx_buffer.data, enet_tx_buffer.size); ! 703: } ! 704: } ! 705: enet_tx_buffer.size=0; ! 706: enet_tx_interrupt(TXSTAT_READY); ! 707: } ! 708: } ! 709: } else { /* disconnected - strange, but required by ROM and 2.2 kernel */ ! 710: if (ConfigureParams.Ethernet.bEthernetConnected) { ! 711: if (!ConfigureParams.Ethernet.bTwistedPair) { ! 712: enet_tx_interrupt(TXSTAT_READY); ! 713: } ! 714: } ! 715: } ! 716: enet.tx_status |= TXSTAT_READY; /* really? */ ! 717: } ! 718: } ! 719: ! 720: void ENET_IO_Handler(void) { ! 721: CycInt_AcknowledgeInterrupt(); ! 722: ! 723: if (enet.reset&EN_RESET) { ! 724: Log_Printf(LOG_WARN, "Stopping Ethernet Transmitter/Receiver"); ! 725: enet_stopped=true; ! 726: /* Stop SLIRP/PCAP */ ! 727: if (ConfigureParams.Ethernet.bEthernetConnected) { ! 728: enet_stop(); ! 729: } ! 730: return; ! 731: } ! 732: ! 733: if (ConfigureParams.System.bTurbo) { ! 734: new_enet_io(); ! 735: } else { ! 736: enet_io(); ! 737: } ! 738: ! 739: CycInt_AddRelativeInterruptUs(receiver_state==RECV_STATE_WAITING?ENET_IO_DELAY:ENET_IO_SHORT, 0, INTERRUPT_ENET_IO); ! 740: } ! 741: ! 742: void enet_reset(void) { ! 743: if (enet.reset&EN_RESET) { ! 744: enet.tx_status=ConfigureParams.System.bTurbo?0:TXSTAT_READY; ! 745: } else if (enet_stopped==true) { ! 746: Log_Printf(LOG_WARN, "Starting Ethernet Transmitter/Receiver"); ! 747: enet_stopped=false; ! 748: CycInt_AddRelativeInterruptUs(ENET_IO_DELAY, 0, INTERRUPT_ENET_IO); ! 749: /* Start SLIRP/PCAP */ ! 750: if (ConfigureParams.Ethernet.bEthernetConnected) { ! 751: enet_start(enet.mac_addr); ! 752: } ! 753: } ! 754: } ! 755: ! 756: void Ethernet_Reset(bool hard) { ! 757: static int init_done = 0; ! 758: ! 759: if (hard) { ! 760: enet.reset=EN_RESET; ! 761: enet_stopped=true; ! 762: enet_rx_buffer.size=enet_tx_buffer.size=0; ! 763: enet_rx_buffer.limit=enet_tx_buffer.limit=64*1024; ! 764: enet.tx_status=ConfigureParams.System.bTurbo?0:TXSTAT_READY; ! 765: } ! 766: ! 767: if (init_done) { ! 768: /* Stop SLIRP/PCAP */ ! 769: enet_stop(); ! 770: } ! 771: #if HAVE_PCAP ! 772: if (ConfigureParams.Ethernet.nHostInterface == ENET_PCAP) { ! 773: enet_output = enet_pcap_queue_poll; ! 774: enet_input = enet_pcap_input; ! 775: enet_start = enet_pcap_start; ! 776: enet_stop = enet_pcap_stop; ! 777: } else ! 778: #endif ! 779: { ! 780: enet_output = enet_slirp_queue_poll; ! 781: enet_input = enet_slirp_input; ! 782: enet_start = enet_slirp_start; ! 783: enet_stop = enet_slirp_stop; ! 784: } ! 785: init_done = 1; ! 786: ! 787: if (ConfigureParams.Ethernet.bEthernetConnected && !(enet.reset&EN_RESET)) { ! 788: /* Start SLIRP/PCAP */ ! 789: enet_start(enet.mac_addr); ! 790: } else { ! 791: /* Stop SLIRP/PCAP */ ! 792: enet_stop(); ! 793: } ! 794: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.