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