PS2SDK
PS2 Homebrew Libraries
Loading...
Searching...
No Matches
smap.c
1
2#include <errno.h>
3#include <stdio.h>
4#include <defs.h>
5#include <dmacman.h>
6#include <dev9.h>
7#include <intrman.h>
8#include <loadcore.h>
9#include <modload.h>
10#include <stdio.h>
11#include <sysclib.h>
12#include <ctype.h>
13#include <thbase.h>
14#include <thevent.h>
15#include <thsemap.h>
16#include <irx.h>
17
18#include <smapregs.h>
19#include <speedregs.h>
20
21#include "main.h"
22#include "xfer.h"
23#include "ipstack.h"
24
25/* There is a difference in how the transmissions are made,
26 between this driver and the SONY original.
27
28 SONY:
29 1. NETDEV calls SMAP's xmit callback.
30 2. SMAP's xmit event handler issues that XMIT event (for the main thread).
31 3. XMIT event copies the frames to the Tx buffer and sets up the BDs.
32 4. Tx DNV handler is called (always, regardless of what event it is being handled!).
33 5. Interrupts are re-enabled, except for TXDNV.
34 6. If there are frames to transmit, write to TX_GNP_0 and enable the TXDNV interrupt
35
36 The TXDNV interrupt is hence always disabled, but only enabled when a frame(s) is sent.
37 Perhaps there is a lack of a check on the TXEND interrupt because it is polling on the TX BDs before every transmission.
38 Might be related to the TXEND/RXEND event race condition that was documented within the PS2Linux SMAP driver.
39
40 I don't know how to test this, but it seems like the TXDNV interrupt is asserted for as long as
41 there is no valid frame to transmit, hence this design by SONY.
42
43 Homebrew:
44 1. Network stack calls SMAPSendPacket().
45 2. If there is either insufficient space or no BD available, wait.
46 3. Frame is copied into the Tx buffer and a BD is set up.
47 4. SMAPSendPacket issues the XMIT event (for the main thread)
48 5. Tx DNV handler is called (always, regardless of what event it is being handled!).
49 6. Interrupts are re-enabled, except for TXDNV.
50 7. If there are frames to transmit, write to TX_GNP_0 and enable the TXDNV interrupt */
51
52#define DEV9_SMAP_ALL_INTR_MASK (SMAP_INTR_EMAC3 | SMAP_INTR_RXEND | SMAP_INTR_TXEND | SMAP_INTR_RXDNV | SMAP_INTR_TXDNV)
53#define DEV9_SMAP_INTR_MASK (SMAP_INTR_EMAC3 | SMAP_INTR_RXEND | SMAP_INTR_RXDNV | SMAP_INTR_TXDNV)
54// The Tx interrupt events are handled separately
55#define DEV9_SMAP_INTR_MASK2 (SMAP_INTR_EMAC3 | SMAP_INTR_RXEND | SMAP_INTR_RXDNV)
56
58
59static const char VersionString[] = "Version 2.26.0";
60static unsigned int ThreadPriority = 0x28;
61static unsigned int ThreadStackSize = 0x1000;
62static unsigned int EnableVerboseOutput = 0;
63static unsigned int EnableAutoNegotiation = 1;
64static unsigned int EnablePinStrapConfig = 0;
65static unsigned int SmapConfiguration = 0x5E0;
66
67int DisplayBanner(void)
68{
69 printf("SMAP (%s)\n", VersionString);
70 return MODULE_NO_RESIDENT_END;
71}
72
73static void _smap_write_phy(volatile u8 *emac3_regbase, unsigned int address, u16 value)
74{
75 u32 PHYRegisterValue;
76 unsigned int i;
77
78 PHYRegisterValue = (address & SMAP_E3_PHY_REG_ADDR_MSK) | SMAP_E3_PHY_WRITE | ((SMAP_DsPHYTER_ADDRESS & SMAP_E3_PHY_ADDR_MSK) << SMAP_E3_PHY_ADDR_BITSFT);
79 PHYRegisterValue |= ((u32)value) << SMAP_E3_PHY_DATA_BITSFT;
80
81 i = 0;
82 SMAP_EMAC3_SET32(SMAP_R_EMAC3_STA_CTRL, PHYRegisterValue);
83
84 for (; !(SMAP_EMAC3_GET32(SMAP_R_EMAC3_STA_CTRL) & SMAP_E3_PHY_OP_COMP); i++) {
85 DelayThread(1000);
86 if (i >= 100)
87 break;
88 }
89
90 if (i >= 100)
91 printf("smap: %s: > %u ms\n", "_smap_write_phy", i);
92}
93
94static u16 _smap_read_phy(volatile u8 *emac3_regbase, unsigned int address)
95{
96 unsigned int i;
97 u32 value, PHYRegisterValue;
98 u16 result;
99
100 PHYRegisterValue = (address & SMAP_E3_PHY_REG_ADDR_MSK) | SMAP_E3_PHY_READ | ((SMAP_DsPHYTER_ADDRESS & SMAP_E3_PHY_ADDR_MSK) << SMAP_E3_PHY_ADDR_BITSFT);
101
102 i = 0;
103 result = 0;
104 SMAP_EMAC3_SET32(SMAP_R_EMAC3_STA_CTRL, PHYRegisterValue);
105
106 do {
107 if (SMAP_EMAC3_GET32(SMAP_R_EMAC3_STA_CTRL) & SMAP_E3_PHY_OP_COMP) {
108 if (SMAP_EMAC3_GET32(SMAP_R_EMAC3_STA_CTRL) & SMAP_E3_PHY_OP_COMP) {
109 if ((value = SMAP_EMAC3_GET32(SMAP_R_EMAC3_STA_CTRL)) & SMAP_E3_PHY_OP_COMP) {
110 result = (u16)(value >> SMAP_E3_PHY_DATA_BITSFT);
111 break;
112 }
113 }
114 }
115
116 DelayThread(1000);
117 i++;
118 } while (i < 100);
119
120 if (i >= 100)
121 printf("SMAP: %s: > %u ms\n", "_smap_read_phy", i);
122
123 return result;
124}
125
126static int DisplayHelpMessage(void)
127{
128 DisplayBanner();
129
130 printf("Usage: smap [<option>] [thpri=<prio>] [thstack=<stack>] [<conf>]\n"
131 " <option>:\n"
132 " -verbose display verbose messages\n"
133 " -auto auto nego enable [default]\n"
134 " -no_auto fixed mode\n"
135 " -strap use pin-strap config\n"
136 " -no_strap do not use pin-strap config [default]\n");
137
138 return 2;
139}
140
141static inline void RestartAutoNegotiation(volatile u8 *emac3_regbase, u16 bmsr)
142{
143 if (EnableVerboseOutput)
144 DEBUG_PRINTF("restarting auto nego (BMCR=0x%x, BMSR=0x%x)\n", _smap_read_phy(emac3_regbase, SMAP_DsPHYTER_BMCR), bmsr);
145 _smap_write_phy(emac3_regbase, SMAP_DsPHYTER_BMCR, SMAP_PHY_BMCR_ANEN | SMAP_PHY_BMCR_RSAN);
146}
147
148static int InitPHY(struct SmapDriverData *SmapDrivPrivData)
149{
150 int i, result;
151 unsigned int LinkSpeed100M, LinkFDX, FlowControlEnabled, AutoNegoRetries;
152 u32 emac3_value;
153 u16 RegDump[6], value, value2;
154 volatile u8 *emac3_regbase;
155
156 LinkSpeed100M = 0;
157 if (EnableVerboseOutput != 0)
158 DEBUG_PRINTF("Resetting PHY\n");
159
160 _smap_write_phy(SmapDrivPrivData->emac3_regbase, SMAP_DsPHYTER_BMCR, SMAP_PHY_BMCR_RST);
161 for (i = 0; _smap_read_phy(SmapDrivPrivData->emac3_regbase, SMAP_DsPHYTER_BMCR) & SMAP_PHY_BMCR_RST; i++) {
162 if (i <= 0) {
163 DEBUG_PRINTF("PHY reset error\n");
164 return -1;
165 }
166 if (SmapDrivPrivData->NetDevStopFlag)
167 return 0;
168
169 DelayThread(1000);
170 }
171
172 if (!EnableAutoNegotiation) {
173 if (EnableVerboseOutput != 0)
174 DEBUG_PRINTF("no auto mode (conf=0x%x)\n", SmapConfiguration);
175
176 LinkSpeed100M = 0 < (SmapConfiguration & 0x180); /* Toggles between SMAP_PHY_BMCR_10M and SMAP_PHY_BMCR_100M. */
177 value = LinkSpeed100M << 13;
178 if (SmapConfiguration & 0x140)
179 value |= SMAP_PHY_BMCR_DUPM;
180 _smap_write_phy(SmapDrivPrivData->emac3_regbase, SMAP_DsPHYTER_BMCR, value);
181
182 WaitLink:
183 DEBUG_PRINTF("Waiting Valid Link for %dMbps\n", LinkSpeed100M ? 100 : 10);
184
185 i = 0;
186 while (1) {
187 DelayThread(200000);
188 if (SmapDrivPrivData->NetDevStopFlag)
189 return 0;
190 i++;
191 if (_smap_read_phy(SmapDrivPrivData->emac3_regbase, SMAP_DsPHYTER_BMSR) & SMAP_PHY_BMSR_LINK)
192 break;
193 if (i >= 5)
194 SmapDrivPrivData->LinkStatus = 0;
195 }
196
197 SmapDrivPrivData->LinkStatus = 1;
198 } else {
199 if (!EnablePinStrapConfig) {
200 _smap_write_phy(SmapDrivPrivData->emac3_regbase, SMAP_DsPHYTER_BMCR, 0);
201 value = _smap_read_phy(SmapDrivPrivData->emac3_regbase, SMAP_DsPHYTER_BMSR);
202 if (!(value & 0x4000))
203 SmapConfiguration = SmapConfiguration & 0xFFFFFEFF; /* 100Base-TX FDX */
204 if (!(value & 0x2000))
205 SmapConfiguration = SmapConfiguration & 0xFFFFFF7F; /* 100Base-TX HDX */
206 if (!(value & 0x1000))
207 SmapConfiguration = SmapConfiguration & 0xFFFFFFBF; /* 10Base-TX FDX */
208 if (!(value & 0x0800))
209 SmapConfiguration = SmapConfiguration & 0xFFFFFFDF; /* 10Base-TX HDX */
210
211 DEBUG_PRINTF("no strap mode (conf=0x%x, bmsr=0x%x)\n", SmapConfiguration, value);
212
213 value = _smap_read_phy(SmapDrivPrivData->emac3_regbase, SMAP_DsPHYTER_ANAR);
214 value = (SmapConfiguration & 0x5E0) | (value & 0x1F);
215 DEBUG_PRINTF("anar=0x%x\n", value);
216 _smap_write_phy(SmapDrivPrivData->emac3_regbase, SMAP_DsPHYTER_ANAR, value);
217 _smap_write_phy(SmapDrivPrivData->emac3_regbase, SMAP_DsPHYTER_BMCR, SMAP_PHY_BMCR_ANEN | SMAP_PHY_BMCR_RSAN);
218 } else {
219 if (!(_smap_read_phy(SmapDrivPrivData->emac3_regbase, SMAP_DsPHYTER_BMCR) & SMAP_PHY_BMCR_ANEN)) {
220 goto WaitLink;
221 }
222 }
223
224 DEBUG_PRINTF("auto mode (BMCR=0x%x ANAR=0x%x)\n", _smap_read_phy(SmapDrivPrivData->emac3_regbase, SMAP_DsPHYTER_BMCR), _smap_read_phy(SmapDrivPrivData->emac3_regbase, SMAP_DsPHYTER_ANAR));
225
226 RepeatAutoNegoProcess:
227 for (AutoNegoRetries = 0; AutoNegoRetries < 3; AutoNegoRetries++) {
228 for (i = 0; i < 3; i++) {
229 DelayThread(1000000);
230 if (SmapDrivPrivData->NetDevStopFlag)
231 return 0;
232 }
233
234 value = _smap_read_phy(SmapDrivPrivData->emac3_regbase, SMAP_DsPHYTER_BMSR);
235 if ((value & (SMAP_PHY_BMSR_ANCP | 0x10)) == SMAP_PHY_BMSR_ANCP) { /* 0x30: SMAP_PHY_BMSR_ANCP and Remote fault. */
236 /* This seems to be checking for the link-up status. */
237 for (i = 0; !(_smap_read_phy(SmapDrivPrivData->emac3_regbase, SMAP_DsPHYTER_BMSR) & SMAP_PHY_BMSR_LINK); i++) {
238 DelayThread(200000);
239 if (SmapDrivPrivData->NetDevStopFlag)
240 return 0;
241 if (i >= 20)
242 break;
243 }
244
245 if (i < 20) {
246 /* Auto negotiaton completed successfully. */
247 SmapDrivPrivData->LinkStatus = 1;
248 break;
249 } else
250 RestartAutoNegotiation(SmapDrivPrivData->emac3_regbase, value);
251 } else
252 RestartAutoNegotiation(SmapDrivPrivData->emac3_regbase, value);
253 }
254
255 /* If automatic negotiation fails, manually figure out which speed and duplex mode to use. */
256 if (AutoNegoRetries >= 3) {
257 if (EnableVerboseOutput)
258 DEBUG_PRINTF("waiting valid link for 100Mbps Half-Duplex\n");
259
260 _smap_write_phy(SmapDrivPrivData->emac3_regbase, SMAP_DsPHYTER_BMCR, SMAP_PHY_BMCR_100M);
261 DelayThread(1000000);
262 if (SmapDrivPrivData->NetDevStopFlag)
263 return 0;
264
265 for (i = 0; !(_smap_read_phy(SmapDrivPrivData->emac3_regbase, SMAP_DsPHYTER_BMSR) & SMAP_PHY_BMSR_LINK); i++) {
266 DelayThread(100000);
267 if (SmapDrivPrivData->NetDevStopFlag)
268 return 0;
269 if (i >= 30)
270 break;
271 }
272
273 if (i >= 30) {
274 if (EnableVerboseOutput)
275 DEBUG_PRINTF("waiting valid link for 10Mbps Half-Duplex\n");
276
277 _smap_write_phy(SmapDrivPrivData->emac3_regbase, SMAP_DsPHYTER_BMCR, SMAP_PHY_BMCR_10M);
278 DelayThread(1000000);
279 if (SmapDrivPrivData->NetDevStopFlag)
280 return 0;
281
282 for (i = 0; !(_smap_read_phy(SmapDrivPrivData->emac3_regbase, SMAP_DsPHYTER_BMSR) & SMAP_PHY_BMSR_LINK); i++) {
283 DelayThread(100000);
284 if (SmapDrivPrivData->NetDevStopFlag)
285 return 0;
286 if (i >= 30)
287 break;
288 }
289
290 if (i >= 0x1E)
291 goto RepeatAutoNegoProcess;
292 else
293 SmapDrivPrivData->LinkStatus = 1;
294 } else
295 SmapDrivPrivData->LinkStatus = 1;
296 }
297 }
298
299 for (i = 0; i < 6; i++)
300 RegDump[i] = _smap_read_phy(SmapDrivPrivData->emac3_regbase, i);
301
302 if (EnableVerboseOutput)
303 DEBUG_PRINTF("PHY: %04x %04x %04x %04x %04x %04x\n", RegDump[SMAP_DsPHYTER_BMCR], RegDump[SMAP_DsPHYTER_BMSR], RegDump[SMAP_DsPHYTER_PHYIDR1], RegDump[SMAP_DsPHYTER_PHYIDR2], RegDump[SMAP_DsPHYTER_ANAR], RegDump[SMAP_DsPHYTER_ANLPAR]);
304
305 /* Special initialization for the National Semiconductor DP83846A PHY. */
306 if (RegDump[SMAP_DsPHYTER_PHYIDR1] == SMAP_PHY_IDR1_VAL && (RegDump[SMAP_DsPHYTER_PHYIDR2] & SMAP_PHY_IDR2_MSK) == SMAP_PHY_IDR2_VAL) {
307 if (EnableAutoNegotiation) {
308 _smap_read_phy(SmapDrivPrivData->emac3_regbase, SMAP_DsPHYTER_FCSCR);
309 _smap_read_phy(SmapDrivPrivData->emac3_regbase, SMAP_DsPHYTER_RECR);
310 DelayThread(500000);
311 value = _smap_read_phy(SmapDrivPrivData->emac3_regbase, SMAP_DsPHYTER_FCSCR);
312 value2 = _smap_read_phy(SmapDrivPrivData->emac3_regbase, SMAP_DsPHYTER_RECR);
313 if ((value2 != 0) || (value >= 0x11)) {
314 if (EnableVerboseOutput)
315 DEBUG_PRINTF("FCSCR=%d RECR=%d\n", value, value2);
316 _smap_write_phy(SmapDrivPrivData->emac3_regbase, SMAP_DsPHYTER_BMCR, 0);
317 goto WaitLink;
318 }
319 }
320
321 DEBUG_PRINTF("PHY chip: DP83846A%d\n", (RegDump[SMAP_DsPHYTER_PHYIDR2] & SMAP_PHY_IDR2_REV_MSK) + 1);
322
323 /* If operating in 10Mbit mode, disable the 10Mb/s Loopback mode. */
324 if (!EnableAutoNegotiation) {
325 if ((RegDump[SMAP_DsPHYTER_BMCR] & (SMAP_PHY_BMCR_DUPM | SMAP_PHY_BMCR_100M)) == 0)
326 _smap_write_phy(SmapDrivPrivData->emac3_regbase, SMAP_DsPHYTER_10BTSCR, SMAP_PHY_10BTSCR_LOOPBACK_10_DIS | SMAP_PHY_10BTSCR_2);
327 } else {
329 _smap_write_phy(SmapDrivPrivData->emac3_regbase, SMAP_DsPHYTER_10BTSCR, SMAP_PHY_10BTSCR_LOOPBACK_10_DIS | SMAP_PHY_10BTSCR_2);
330 }
331
332 if ((RegDump[SMAP_DsPHYTER_PHYIDR2] & SMAP_PHY_IDR2_REV_MSK) == 0) {
333 _smap_write_phy(SmapDrivPrivData->emac3_regbase, 0x13, 1);
334 _smap_write_phy(SmapDrivPrivData->emac3_regbase, SMAP_DsPHYTER_PHYCTRL, 0x1898);
335 _smap_write_phy(SmapDrivPrivData->emac3_regbase, 0x1F, 0);
336 _smap_write_phy(SmapDrivPrivData->emac3_regbase, 0x1D, 0x5040);
337 _smap_write_phy(SmapDrivPrivData->emac3_regbase, 0x1E, 0x8C);
338 _smap_write_phy(SmapDrivPrivData->emac3_regbase, 0x13, 0);
339 }
340 }
341
342 /* Determine what was negotiated for. */
343 FlowControlEnabled = 0;
344 if (RegDump[SMAP_DsPHYTER_BMCR] & SMAP_PHY_BMCR_ANEN) {
345 value = RegDump[SMAP_DsPHYTER_ANAR] & RegDump[SMAP_DsPHYTER_ANLPAR];
346 LinkSpeed100M = 0 < (value & 0x180);
347 LinkFDX = 0 < (value & 0x140);
348 if (LinkFDX)
349 FlowControlEnabled = 0 < (value & 0x400);
350 } else {
351 LinkSpeed100M = RegDump[SMAP_DsPHYTER_BMCR] >> 13 & 1;
352 LinkFDX = RegDump[SMAP_DsPHYTER_BMCR] >> 8 & 1;
353 FlowControlEnabled = SmapConfiguration >> 10 & 1;
354 }
355
356 if (LinkSpeed100M)
357 result = LinkFDX ? 8 : 4;
358 else
359 result = LinkFDX ? 2 : 1;
360
361 SmapDrivPrivData->LinkMode = result;
362 if (FlowControlEnabled)
363 SmapDrivPrivData->LinkMode |= 0x40;
364
365 DEBUG_PRINTF("%s %s Duplex Mode %s Flow Control\n", LinkSpeed100M ? "100BaseTX" : "10BaseT", LinkFDX ? "Full" : "Half", FlowControlEnabled ? "with" : "without");
366
367 emac3_regbase = SmapDrivPrivData->emac3_regbase;
368 emac3_value = SMAP_EMAC3_GET32(SMAP_R_EMAC3_MODE1) & 0x67FFFFFF;
369 if (LinkFDX)
370 emac3_value |= SMAP_E3_FDX_ENABLE;
371 if (FlowControlEnabled)
373 SMAP_EMAC3_SET32(SMAP_R_EMAC3_MODE1, emac3_value);
374
375 return 0;
376}
377
378// This timer callback starts the Ethernet link check event.
379static unsigned int LinkCheckTimerCB(struct SmapDriverData *SmapDrivPrivData)
380{
381 iSetEventFlag(SmapDrivPrivData->Dev9IntrEventFlag, SMAP_EVENT_LINK_CHECK);
382 return SmapDrivPrivData->LinkCheckTimer.lo;
383}
384
385static int HandleTxIntr(struct SmapDriverData *SmapDrivPrivData)
386{
387 int result, i;
388 USE_SMAP_TX_BD;
389 u16 ctrl_stat;
390
391 result = 0;
392 while (SmapDrivPrivData->NumPacketsInTx > 0) {
393 ctrl_stat = tx_bd[SmapDrivPrivData->TxDNVBDIndex % SMAP_BD_MAX_ENTRY].ctrl_stat;
394 if (!(ctrl_stat & SMAP_BD_TX_READY)) {
396 for (i = 0; i < 16; i++)
397 if ((ctrl_stat >> i) & 1)
398 SmapDrivPrivData->RuntimeStats.TxErrorCount++;
399
400 SmapDrivPrivData->RuntimeStats.TxDroppedFrameCount++;
401 if (ctrl_stat & SMAP_BD_TX_LOSSCR)
402 SmapDrivPrivData->RuntimeStats.TxFrameLOSSCRCount++;
403 if (ctrl_stat & SMAP_BD_TX_EDEFER)
404 SmapDrivPrivData->RuntimeStats.TxFrameEDEFERCount++;
406 SmapDrivPrivData->RuntimeStats.TxFrameCollisionCount++;
407 if (ctrl_stat & SMAP_BD_TX_UNDERRUN)
408 SmapDrivPrivData->RuntimeStats.TxFrameUnderrunCount++;
409 }
410 } else
411 break;
412
413 result++;
414 SmapDrivPrivData->TxBufferSpaceAvailable += (tx_bd[SmapDrivPrivData->TxDNVBDIndex & (SMAP_BD_MAX_ENTRY - 1)].length + 3) & ~3;
415 SmapDrivPrivData->TxDNVBDIndex++;
416 SmapDrivPrivData->NumPacketsInTx--;
417 }
418
419 return result;
420}
421
422// Checks the status of the Ethernet link
423static void CheckLinkStatus(struct SmapDriverData *SmapDrivPrivData)
424{
425 if (!(_smap_read_phy(SmapDrivPrivData->emac3_regbase, SMAP_DsPHYTER_BMSR) & SMAP_PHY_BMSR_LINK)) {
426 // Link lost
427 SmapDrivPrivData->LinkStatus = 0;
428 SMapCommonLinkStateDown(SmapDrivPrivData);
429 InitPHY(SmapDrivPrivData);
430
431 // Link established
432 if (SmapDrivPrivData->LinkStatus)
433 SMapCommonLinkStateUp(SmapDrivPrivData);
434 }
435}
436
437#ifdef SMAP_RX_PACKETS_POLLING_MODE
438static unsigned int RxIntrPollingTimerCB(struct SmapDriverData *SmapDrivPrivData)
439{
440 iSetEventFlag(SmapDrivPrivData->Dev9IntrEventFlag, SMAP_EVENT_INTR);
441 return 0;
442}
443#endif
444
445static void IntrHandlerThread(struct SmapDriverData *SmapDrivPrivData)
446{
447 unsigned int PacketCount, IntrReg;
448 u32 EFBits;
449 int counter;
450 volatile u8 *smap_regbase, *emac3_regbase;
451 USE_SPD_REGS;
452
453 counter = 3;
454 emac3_regbase = SmapDrivPrivData->emac3_regbase;
455 smap_regbase = SmapDrivPrivData->smap_regbase;
456 while (1) {
457 int result;
458
459 if ((result = WaitEventFlag(SmapDrivPrivData->Dev9IntrEventFlag, SMAP_EVENT_START | SMAP_EVENT_STOP | SMAP_EVENT_INTR | SMAP_EVENT_XMIT | SMAP_EVENT_LINK_CHECK, WEF_OR | WEF_CLEAR, &EFBits)) != 0) {
460 DEBUG_PRINTF("WaitEventFlag -> %d\n", result);
461 break;
462 }
463
464 if (EFBits & SMAP_EVENT_STOP) {
465 if (SmapDrivPrivData->SmapIsInitialized) {
466 SpdIntrDisable(DEV9_SMAP_INTR_MASK2);
467 SMAP_EMAC3_SET32(SMAP_R_EMAC3_MODE0, 0);
468 SmapDrivPrivData->NetDevStopFlag = 0;
469 SmapDrivPrivData->LinkStatus = 0;
470 SmapDrivPrivData->SmapIsInitialized = 0;
471 SmapDrivPrivData->SmapDriverStarted = 0;
472 SMapCommonLinkStateDown(SmapDrivPrivData);
473 }
474 }
475 if (EFBits & SMAP_EVENT_START) {
476 if (!SmapDrivPrivData->SmapIsInitialized) {
477 SmapDrivPrivData->SmapDriverStarted = 1;
478 SpdIntrEnable(DEV9_SMAP_INTR_MASK2);
479 if ((result = InitPHY(SmapDrivPrivData)) != 0)
480 break;
481 if (SmapDrivPrivData->NetDevStopFlag) {
482 SmapDrivPrivData->NetDevStopFlag = 0;
483 continue;
484 }
485
486 SMAP_EMAC3_SET32(SMAP_R_EMAC3_MODE0, SMAP_E3_TXMAC_ENABLE | SMAP_E3_RXMAC_ENABLE);
487 DelayThread(10000);
488 SmapDrivPrivData->SmapIsInitialized = 1;
489
490 SMapCommonLinkStateUp(SmapDrivPrivData);
491
492 if (!SmapDrivPrivData->EnableLinkCheckTimer) {
493 USec2SysClock(1000000, &SmapDrivPrivData->LinkCheckTimer);
494 SetAlarm(&SmapDrivPrivData->LinkCheckTimer, (void *)&LinkCheckTimerCB, SmapDrivPrivData);
495 SmapDrivPrivData->EnableLinkCheckTimer = 1;
496 }
497 }
498 }
499
500 if (SmapDrivPrivData->SmapIsInitialized) {
501 PacketCount = 0;
502 if (EFBits & SMAP_EVENT_INTR) {
503 if ((IntrReg = SPD_REG16(SPD_R_INTR_STAT) & DEV9_SMAP_INTR_MASK) != 0) {
504 /* Original order/priority:
505 1. EMAC3
506 2. RXEND
507 3. RXDNV
508 4. TXDNV */
509 if (IntrReg & SMAP_INTR_EMAC3) {
510 SMAP_REG16(SMAP_R_INTR_CLR) = SMAP_INTR_EMAC3;
511 SMAP_EMAC3_SET32(SMAP_R_EMAC3_INTR_STAT, SMAP_E3_INTR_TX_ERR_0 | SMAP_E3_INTR_SQE_ERR_0 | SMAP_E3_INTR_DEAD_0);
512 }
513 if (IntrReg & SMAP_INTR_RXEND) {
514 SMAP_REG16(SMAP_R_INTR_CLR) = SMAP_INTR_RXEND;
515 PacketCount = HandleRxIntr(SmapDrivPrivData);
516 }
517 if (IntrReg & SMAP_INTR_RXDNV) {
518 SMAP_REG16(SMAP_R_INTR_CLR) = SMAP_INTR_RXDNV;
519 SmapDrivPrivData->RuntimeStats.RxFrameOverrunCount++;
520 }
521 if (IntrReg & SMAP_INTR_TXDNV) {
522 SMAP_REG16(SMAP_R_INTR_CLR) = SMAP_INTR_TXDNV;
523 HandleTxIntr(SmapDrivPrivData);
524 EFBits |= SMAP_EVENT_XMIT;
525 }
526 }
527 }
528
529 if (EFBits & SMAP_EVENT_XMIT)
530 HandleTxReqs(SmapDrivPrivData);
531 // This was added in later versions.
532 HandleTxIntr(SmapDrivPrivData);
533
534 // TXDNV is not enabled here, but only when frames are transmitted.
535#ifdef SMAP_RX_PACKETS_POLLING_MODE
536 SpdIntrEnable(SMAP_INTR_EMAC3 | SMAP_INTR_RXDNV);
537
538 if (PacketCount >= 1) {
539 // Receive packets in polling mode
540
541 // We're receiving packets at a maximum rate of 100 bits/us or 12.5 bytes/us
542#define ETH_KB_TO_US(B) (B * 80)
543
544 USec2SysClock(ETH_KB_TO_US(12), &SmapDrivPrivData->RxIntrPollingTimer);
545#undef ETH_KB_TO_US
546 SetAlarm(&SmapDrivPrivData->RxIntrPollingTimer, (void *)&RxIntrPollingTimerCB, SmapDrivPrivData);
547 } else {
548 // Receive packets in interrupt mode
549 SpdIntrEnable(SMAP_INTR_RXEND);
550 }
551#else
552 SpdIntrEnable(DEV9_SMAP_INTR_MASK2);
553#endif
554
555 // If there are frames to send out, let Tx channel 0 know and enable TXDNV.
556 if (SmapDrivPrivData->NumPacketsInTx > 0) {
557 SMAP_EMAC3_SET32(SMAP_R_EMAC3_TxMODE0, SMAP_E3_TX_GNP_0);
558 SpdIntrEnable(SMAP_INTR_TXDNV);
559 }
560
561 // Do the link check, only if there has not been any incoming traffic in a while.
562 if (PacketCount) {
563 counter = 3;
564 continue;
565 }
566
567 if (EFBits & SMAP_EVENT_LINK_CHECK) {
568 if (--counter <= 0)
569 CheckLinkStatus(SmapDrivPrivData);
570 }
571 }
572 }
573}
574
575static int Dev9IntrCb(int flag)
576{
577#if USE_GP_REGISTER
578 void *OldGP;
579
580 OldGP = SetModuleGP();
581#endif
582
583 (void)flag;
584
585 SpdIntrDisable(DEV9_SMAP_ALL_INTR_MASK);
586 iSetEventFlag(SmapDriverData.Dev9IntrEventFlag, SMAP_EVENT_INTR);
587
588#if USE_GP_REGISTER
589 SetGP(OldGP);
590#endif
591
592 return 0;
593}
594
595static void Dev9PreDmaCbHandler(int bcr, int dir)
596{
597 volatile u8 *smap_regbase;
598 u16 SliceCount;
599
600 smap_regbase = SmapDriverData.smap_regbase;
601 SliceCount = bcr >> 16;
602 if (dir != DMAC_TO_MEM) {
603 SMAP_REG16(SMAP_R_TXFIFO_SIZE) = SliceCount;
604 SMAP_REG8(SMAP_R_TXFIFO_CTRL) = SMAP_TXFIFO_DMAEN;
605 } else {
606 SMAP_REG16(SMAP_R_RXFIFO_SIZE) = SliceCount;
607 SMAP_REG8(SMAP_R_RXFIFO_CTRL) = SMAP_RXFIFO_DMAEN;
608 }
609}
610
611static void Dev9PostDmaCbHandler(int bcr, int dir)
612{
613 volatile u8 *smap_regbase;
614
615 (void)bcr;
616
617 smap_regbase = SmapDriverData.smap_regbase;
618 if (dir != DMAC_TO_MEM) {
619 while (SMAP_REG8(SMAP_R_TXFIFO_CTRL) & SMAP_TXFIFO_DMAEN) {};
620 } else {
621 while (SMAP_REG8(SMAP_R_RXFIFO_CTRL) & SMAP_RXFIFO_DMAEN) {};
622 }
623}
624
625#ifdef BUILDING_SMAP_PS2IP
626// For the initial startup, as legacy programs expect the Ethernet interface to be ready once SMAP finishes initialization.
627int SMAPInitStart(void)
628{
629 volatile u8 *emac3_regbase;
630
631#if USE_GP_REGISTER
632 void *OldGP;
633
634 OldGP = SetModuleGP();
635#endif
636
637 if (!SmapDriverData.SmapIsInitialized) {
638 emac3_regbase = SmapDriverData.emac3_regbase;
639
640 SpdIntrEnable(DEV9_SMAP_INTR_MASK2);
641 if (InitPHY(&SmapDriverData) == 0 && !SmapDriverData.NetDevStopFlag) {
642 SMAP_EMAC3_SET32(SMAP_R_EMAC3_MODE0, SMAP_E3_TXMAC_ENABLE | SMAP_E3_RXMAC_ENABLE);
643 DelayThread(10000);
644 SmapDriverData.SmapIsInitialized = 1;
645
646 SMapCommonLinkStateUp(&SmapDriverData);
647
648 if (!SmapDriverData.EnableLinkCheckTimer) {
649 USec2SysClock(1000000, &SmapDriverData.LinkCheckTimer);
650 SetAlarm(&SmapDriverData.LinkCheckTimer, (void *)&LinkCheckTimerCB, &SmapDriverData);
651 SmapDriverData.EnableLinkCheckTimer = 1;
652 }
653 } else
654 SmapDriverData.NetDevStopFlag = 0;
655 }
656
657#if USE_GP_REGISTER
658 SetGP(OldGP);
659#endif
660
661 return 0;
662}
663#endif
664
665int SMAPStart(void)
666{
667#if USE_GP_REGISTER
668 void *OldGP;
669
670 OldGP = SetModuleGP();
671#endif
672
673 SetEventFlag(SmapDriverData.Dev9IntrEventFlag, SMAP_EVENT_START);
674
675#if USE_GP_REGISTER
676 SetGP(OldGP);
677#endif
678
679 return 0;
680}
681
682void SMAPStop(void)
683{
684#if USE_GP_REGISTER
685 void *OldGP;
686
687 OldGP = SetModuleGP();
688#endif
689
690 SetEventFlag(SmapDriverData.Dev9IntrEventFlag, SMAP_EVENT_STOP);
691 SmapDriverData.NetDevStopFlag = 1;
692
693#if USE_GP_REGISTER
694 SetGP(OldGP);
695#endif
696}
697
698static void ClearPacketQueue(struct SmapDriverData *SmapDrivPrivData)
699{
700 int OldState;
701 void *pkt;
702
703 CpuSuspendIntr(&OldState);
704 pkt = SmapDrivPrivData->packetToSend;
705 SmapDrivPrivData->packetToSend = NULL;
706 CpuResumeIntr(OldState);
707
708 if (pkt != NULL) {
709 while (SMAPCommonTxPacketNext(SmapDrivPrivData, &pkt) > 0)
710 SMAPCommonTxPacketDeQ(SmapDrivPrivData, &pkt);
711 }
712}
713
714void SMAPXmit(void)
715{
716#if USE_GP_REGISTER
717 void *OldGP;
718
719 OldGP = SetModuleGP();
720#endif
721
722 if (SmapDriverData.LinkStatus) {
723 if (QueryIntrContext())
724 iSetEventFlag(SmapDriverData.Dev9IntrEventFlag, SMAP_EVENT_XMIT);
725 else
726 SetEventFlag(SmapDriverData.Dev9IntrEventFlag, SMAP_EVENT_XMIT);
727 } else {
728 // No link. Clear the packet queue.
729 ClearPacketQueue(&SmapDriverData);
730 }
731
732#if USE_GP_REGISTER
733 SetGP(OldGP);
734#endif
735}
736
737#ifdef BUILDING_SMAP_NETMAN
738static int SMAPGetLinkMode(void)
739{
740 u16 value;
741 int result;
742
743 result = -1;
744 if (SmapDriverData.SmapIsInitialized && SmapDriverData.LinkStatus) {
745 value = SmapDriverData.LinkMode;
746 if (value & 0x08)
747 result = NETMAN_NETIF_ETH_LINK_MODE_100M_FDX; /* 100Base-TX FDX */
748 if (value & 0x04)
749 result = NETMAN_NETIF_ETH_LINK_MODE_100M_HDX; /* 100Base-TX HDX */
750 if (value & 0x02)
751 result = NETMAN_NETIF_ETH_LINK_MODE_10M_FDX; /* 10Base-TX FDX */
752 if (value & 0x01)
753 result = NETMAN_NETIF_ETH_LINK_MODE_10M_HDX; /* 10Base-TX HDX */
754 if (!(value & 0x40))
756 }
757
758 return result;
759}
760
761static int SMAPSetLinkMode(int mode)
762{
763 int result;
764
765 if (SmapDriverData.SmapIsInitialized) {
766 int baseMode;
767
768 baseMode = mode & (~NETMAN_NETIF_ETH_LINK_DISABLE_PAUSE);
769
770 if (baseMode != NETMAN_NETIF_ETH_LINK_MODE_AUTO) {
771 EnableAutoNegotiation = 0;
772
773 switch (baseMode) {
775 SmapConfiguration = 0x020;
776 result = 0;
777 break;
779 SmapConfiguration = 0x040;
780 result = 0;
781 break;
783 SmapConfiguration = 0x080;
784 result = 0;
785 break;
787 SmapConfiguration = 0x0100;
788 result = 0;
789 break;
790 default:
791 result = -1;
792 }
793 } else {
794 SmapConfiguration = 0x1E0;
795 EnableAutoNegotiation = 1;
796 result = 0;
797 }
798
799 if (result == 0) {
801 SmapConfiguration |= 0x400; // Enable flow control.
802
803 SetEventFlag(SmapDriverData.Dev9IntrEventFlag, SMAP_EVENT_STOP | SMAP_EVENT_START);
804 SmapDriverData.NetDevStopFlag = 1;
805 }
806 } else
807 result = -ENXIO;
808
809 return result;
810}
811
812static inline int SMAPGetLinkStatus(void)
813{
814 return ((SmapDriverData.SmapIsInitialized && SmapDriverData.LinkStatus) ? NETMAN_NETIF_ETH_LINK_STATE_UP : NETMAN_NETIF_ETH_LINK_STATE_DOWN);
815}
816
817int SMAPIoctl(unsigned int command, void *args, unsigned int args_len, void *output, unsigned int length)
818{
819 int result;
820#if USE_GP_REGISTER
821 void *OldGP;
822
823 OldGP = SetModuleGP();
824#endif
825
826 (void)args_len;
827 (void)length;
828
829 switch (command) {
831 result = SMAPGetMACAddress(output);
832 break;
833 case NETMAN_NETIF_IOCTL_ETH_GET_LINK_MODE:
834 result = SMAPGetLinkMode();
835 break;
836 case NETMAN_NETIF_IOCTL_GET_LINK_STATUS:
837 result = SMAPGetLinkStatus();
838 break;
839 case NETMAN_NETIF_IOCTL_GET_TX_DROPPED_COUNT:
840 result = SmapDriverData.RuntimeStats.TxDroppedFrameCount;
841 break;
842 case NETMAN_NETIF_IOCTL_GET_RX_DROPPED_COUNT:
843 result = SmapDriverData.RuntimeStats.RxDroppedFrameCount;
844 break;
845 case NETMAN_NETIF_IOCTL_ETH_GET_RX_EOVERRUN_CNT:
846 result = SmapDriverData.RuntimeStats.RxFrameOverrunCount;
847 break;
848 case NETMAN_NETIF_IOCTL_ETH_GET_RX_EBADLEN_CNT:
849 result = SmapDriverData.RuntimeStats.RxFrameBadLengthCount;
850 break;
851 case NETMAN_NETIF_IOCTL_ETH_GET_RX_EBADFCS_CNT:
852 result = SmapDriverData.RuntimeStats.RxFrameBadFCSCount;
853 break;
854 case NETMAN_NETIF_IOCTL_ETH_GET_RX_EBADALIGN_CNT:
855 result = SmapDriverData.RuntimeStats.RxFrameBadAlignmentCount;
856 break;
857 case NETMAN_NETIF_IOCTL_ETH_GET_TX_ELOSSCR_CNT:
858 result = SmapDriverData.RuntimeStats.TxFrameLOSSCRCount;
859 break;
860 case NETMAN_NETIF_IOCTL_ETH_GET_TX_EEDEFER_CNT:
861 result = SmapDriverData.RuntimeStats.TxFrameEDEFERCount;
862 break;
863 case NETMAN_NETIF_IOCTL_ETH_GET_TX_ECOLL_CNT:
864 result = SmapDriverData.RuntimeStats.TxFrameCollisionCount;
865 break;
866 case NETMAN_NETIF_IOCTL_ETH_GET_TX_EUNDERRUN_CNT:
867 result = SmapDriverData.RuntimeStats.TxFrameUnderrunCount;
868 break;
870 result = SMAPSetLinkMode(*(int *)args);
871 break;
872 case NETMAN_NETIF_IOCTL_ETH_GET_STATUS:
873 ((struct NetManEthStatus *)output)->LinkMode = SMAPGetLinkMode();
874 ((struct NetManEthStatus *)output)->LinkStatus = SMAPGetLinkStatus();
875 memcpy(&(((struct NetManEthStatus *)output)->stats), &(SmapDriverData.RuntimeStats), sizeof(SmapDriverData.RuntimeStats));
876 result = 0;
877 break;
878 default:
879 result = -1;
880 }
881
882#if USE_GP_REGISTER
883 SetGP(OldGP);
884#endif
885
886 return result;
887}
888#endif
889
890void SMAPOutputDebugInformation(void)
891{
892#ifdef SMAP_ENABLE_DEBUG_INFORMATION
893 USE_SMAP_EMAC3_REGS;
894 USE_SMAP_REGS;
895 USE_SMAP_RX_BD;
896 int i;
897 char bdidx;
898
899 DEBUG_PRINTF("SMAP_R_RXFIFO_CTRL: 0x%x\n", SMAP_REG8(SMAP_R_RXFIFO_CTRL));
900 DEBUG_PRINTF("SMAP_R_RXFIFO_RD_PTR: 0x%x\n", SMAP_REG16(SMAP_R_RXFIFO_RD_PTR));
901 DEBUG_PRINTF("SMAP_R_RXFIFO_SIZE: %d\n", SMAP_REG16(SMAP_R_RXFIFO_SIZE));
902 DEBUG_PRINTF("SMAP_R_RXFIFO_FRAME_CNT: %d\n", SMAP_REG8(SMAP_R_RXFIFO_FRAME_CNT));
903 DEBUG_PRINTF("SMAP_R_RXFIFO_FRAME_DEC: %d\n", SMAP_REG8(SMAP_R_RXFIFO_FRAME_DEC));
904 DEBUG_PRINTF("SMAP_R_EMAC3_RxMODE: 0x%x\n", (unsigned int)SMAP_EMAC3_GET32(SMAP_R_EMAC3_RxMODE));
905 DEBUG_PRINTF("SMAP_R_EMAC3_INTR_STAT: 0x%x\n", (unsigned int)SMAP_EMAC3_GET32(SMAP_R_EMAC3_INTR_STAT));
906 DEBUG_PRINTF("SMAP_R_EMAC3_INTR_ENABLE: 0x%x\n", (unsigned int)SMAP_EMAC3_GET32(SMAP_R_EMAC3_INTR_ENABLE));
907 bdidx = SmapDriverData.RxBDIndex % SMAP_BD_MAX_ENTRY;
908 for (i = 0; i < SMAP_BD_MAX_ENTRY; i += 1) {
909 if (rx_bd[i].ctrl_stat != SMAP_BD_RX_EMPTY ||
910 rx_bd[i].reserved != 0 ||
911 rx_bd[i].length != 0 ||
912 rx_bd[i].pointer != 0 ||
913 i == bdidx) {
914 if (i == bdidx)
915 DEBUG_PRINTF()
916 (" - rx_bd[%d]: 0x%x / 0x%x / %d / 0x%x <--\n", i, rx_bd[i].ctrl_stat, rx_bd[i].reserved, rx_bd[i].length, rx_bd[i].pointer);
917 else
918 DEBUG_PRINTF()
919 (" - rx_bd[%d]: 0x%x / 0x%x / %d / 0x%x\n", i, rx_bd[i].ctrl_stat, rx_bd[i].reserved, rx_bd[i].length, rx_bd[i].pointer);
920 }
921 }
922
923 DEBUG_PRINTF("RxDroppedFrameCount: %d\n", (int)SmapDriverData.RuntimeStats.RxDroppedFrameCount);
924 DEBUG_PRINTF("RxErrorCount: %d\n", (int)SmapDriverData.RuntimeStats.RxErrorCount);
925 DEBUG_PRINTF("RxFrameOverrunCount: %d\n", SmapDriverData.RuntimeStats.RxFrameOverrunCount);
926 DEBUG_PRINTF("RxFrameBadLengthCount: %d\n", SmapDriverData.RuntimeStats.RxFrameBadLengthCount);
927 DEBUG_PRINTF("RxFrameBadFCSCount: %d\n", SmapDriverData.RuntimeStats.RxFrameBadFCSCount);
928 DEBUG_PRINTF("RxFrameBadAlignmentCount: %d\n", SmapDriverData.RuntimeStats.RxFrameBadAlignmentCount);
929 DEBUG_PRINTF("TxDroppedFrameCount: %d\n", (int)SmapDriverData.RuntimeStats.TxDroppedFrameCount);
930 DEBUG_PRINTF("TxErrorCount: %d\n", (int)SmapDriverData.RuntimeStats.TxErrorCount);
931 DEBUG_PRINTF("TxFrameLOSSCRCount: %d\n", SmapDriverData.RuntimeStats.TxFrameLOSSCRCount);
932 DEBUG_PRINTF("TxFrameEDEFERCount: %d\n", SmapDriverData.RuntimeStats.TxFrameEDEFERCount);
933 DEBUG_PRINTF("TxFrameCollisionCount: %d\n", SmapDriverData.RuntimeStats.TxFrameCollisionCount);
934 DEBUG_PRINTF("TxFrameUnderrunCount: %d\n", SmapDriverData.RuntimeStats.TxFrameUnderrunCount);
935 DEBUG_PRINTF("RxAllocFail: %d\n", SmapDriverData.RuntimeStats.RxAllocFail);
936#endif
937}
938
939#ifdef BUILDING_SMAP_MODULAR
940int SMapRegisterHook(const SmapModularHookTable_t *hooktbl, int priority)
941{
942 // Only 0 priority is supported at this time
943 if (priority != 0) {
944 return 1;
945 }
946 // Check version of hook table
947 if (hooktbl != NULL) {
948 if (hooktbl->Version != 1) {
949 return 1;
950 }
951 }
952 SmapDriverData.HookTable[priority] = hooktbl;
953 return 0;
954}
955
957 .Version = 1,
958 .GetMACAddress = &SMAPGetMACAddress,
959 .Xmit = &SMAPXmit,
960 .OutputDebugInformation = &SMAPOutputDebugInformation,
961 .RegisterHook = &SMapRegisterHook,
962 .RxBDIndexPtr = &(SmapDriverData.RxBDIndex),
963 .RuntimeStatsPtr = (SmapModularRuntimeStats_t *)&(SmapDriverData.RuntimeStats),
964};
965
966const SmapModularExportTable_t *SmapModularGetExportTable(void)
967{
969}
970#endif
971
972static inline int SetupNetDev(void)
973{
974 int result;
975 iop_event_t EventFlagData;
976 iop_thread_t ThreadData;
977#ifdef BUILDING_SMAP_NETMAN
978 static struct NetManNetIF device = {
979 "SMAP",
980 0,
981 0,
982 &SMAPStart,
983 &SMAPStop,
984 &SMAPXmit,
985 &SMAPIoctl,
986 0,
987 };
988#endif
989
990 EventFlagData.attr = 0;
991 EventFlagData.option = 0;
992 EventFlagData.bits = 0;
993
994 if ((result = SmapDriverData.Dev9IntrEventFlag = CreateEventFlag(&EventFlagData)) < 0) {
995 DEBUG_PRINTF("CreateEventFlag -> %d\n", result);
996 return -6;
997 }
998
999 ThreadData.attr = TH_C;
1000 ThreadData.thread = (void *)&IntrHandlerThread;
1001 ThreadData.option = 0;
1002 ThreadData.priority = ThreadPriority;
1003 ThreadData.stacksize = ThreadStackSize;
1004 if ((result = SmapDriverData.IntrHandlerThreadID = CreateThread(&ThreadData)) < 0) {
1005 DEBUG_PRINTF("CreateThread -> %d\n", result);
1006 DeleteEventFlag(SmapDriverData.Dev9IntrEventFlag);
1007 return result;
1008 }
1009
1010 if ((result = StartThread(SmapDriverData.IntrHandlerThreadID, &SmapDriverData)) < 0) {
1011 printf("smap: StartThread -> %d\n", result);
1012 DeleteThread(SmapDriverData.IntrHandlerThreadID);
1013 DeleteEventFlag(SmapDriverData.Dev9IntrEventFlag);
1014 return result;
1015 }
1016
1017#ifdef BUILDING_SMAP_NETMAN
1018 if ((SmapDriverData.NetIFID = NetManRegisterNetIF(&device)) < 0) {
1019 printf("smap: NetManRegisterNetIF -> %d\n", result);
1020 TerminateThread(SmapDriverData.IntrHandlerThreadID);
1021 DeleteThread(SmapDriverData.IntrHandlerThreadID);
1022 DeleteEventFlag(SmapDriverData.Dev9IntrEventFlag);
1023 return -6;
1024 }
1025#endif
1026
1027 return 0;
1028}
1029
1030static int ParseSmapConfiguration(const char *cmd, unsigned int *configuration)
1031{
1032 const char *CmdStart, *DigitStart;
1033 unsigned int result, base, character, value;
1034
1035 DigitStart = CmdStart = cmd;
1036 base = 10;
1037
1038 if (CmdStart[0] == '0') {
1039 if (CmdStart[1] != '\0') {
1040 if (CmdStart[1] == 'x') {
1041 DigitStart += 2;
1042 base = 16;
1043 } else {
1044 DigitStart++;
1045 }
1046 }
1047 }
1048 if (DigitStart[0] == '\0') {
1049 goto fail_end;
1050 }
1051
1052 result = 0;
1053 character = DigitStart[0];
1054 do {
1055 if (character - '0' < 10) {
1056 value = character - '0';
1057 } else if (character - 'a' < 6) {
1058 value = character - 'a' - 0x57;
1059 } else
1060 goto fail_end;
1061
1062 if (value >= base)
1063 goto fail_end;
1064
1065 result = result * base + value;
1066 } while ((character = *(++DigitStart)) != '\0');
1067 *configuration = result;
1068
1069 return 0;
1070fail_end:
1071 printf("smap: %s: %s - invalid digit\n", "scan_number", CmdStart);
1072 return -1;
1073}
1074
1075int smap_init(int argc, char *argv[])
1076{
1077 int result, i;
1078 const char *CmdString;
1079 u16 eeprom_data[4], checksum16;
1080 u32 mac_address;
1081 USE_SPD_REGS;
1082 USE_SMAP_REGS;
1083 USE_SMAP_EMAC3_REGS;
1084 USE_SMAP_TX_BD;
1085 USE_SMAP_RX_BD;
1086
1087 checksum16 = 0;
1088#ifdef BUILDING_SMAP_NETMAN
1089 argc--;
1090 argv++;
1091#endif
1092 while (argc > 0) {
1093 if (strcmp("-help", *argv) == 0) {
1094 return DisplayHelpMessage();
1095 } else if (strcmp("-version", *argv) == 0) {
1096 return DisplayBanner();
1097 } else if (strcmp("-verbose", *argv) == 0) {
1098 EnableVerboseOutput = 1;
1099 } else if (strcmp("-auto", *argv) == 0) {
1100 EnableAutoNegotiation = 1;
1101 } else if (strcmp("-no_auto", *argv) == 0) {
1102 EnableAutoNegotiation = 0;
1103 } else if (strcmp("-strap", *argv) == 0) {
1104 EnablePinStrapConfig = 1;
1105 } else if (strcmp("-no_strap", *argv) == 0) {
1106 EnablePinStrapConfig = 0;
1107 } else if (strncmp("thpri=", *argv, 6) == 0) {
1108 CmdString = &(*argv)[6];
1109 if (isdigit(CmdString[0])) {
1110 ThreadPriority = strtoul(&(*argv)[6], NULL, 10);
1111 if (ThreadPriority - 9 >= 0x73) {
1112 return DisplayHelpMessage();
1113 }
1114
1115 if ((*argv)[6] != '\0') {
1116 while (isdigit(*CmdString)) {
1117 CmdString++;
1118 }
1119 if (*CmdString != '\0')
1120 return DisplayHelpMessage();
1121 }
1122 } else
1123 return DisplayHelpMessage();
1124 } else if (strncmp("thstack=", *argv, 8) == 0) {
1125 CmdString = &(*argv)[8];
1126 if (isdigit(CmdString[0])) {
1127 ThreadStackSize = strtoul(&(*argv)[8], NULL, 10);
1128 if ((*argv)[8] != '\0') {
1129 while (isdigit(*CmdString)) {
1130 CmdString++;
1131 }
1132 }
1133
1134 if (strcmp(CmdString, "KB") == 0)
1135 ThreadStackSize <<= 10;
1136 } else
1137 return DisplayHelpMessage();
1138 } else {
1139 if (ParseSmapConfiguration(*argv, &SmapConfiguration) != 0)
1140 return DisplayHelpMessage();
1141 }
1142
1143 argc--;
1144 argv++;
1145 }
1146
1147 if (argc != 0)
1148 return DisplayHelpMessage();
1149
1150 SmapDriverData.smap_regbase = smap_regbase;
1151 SmapDriverData.emac3_regbase = emac3_regbase;
1152 if ((SPD_REG16(SPD_R_REV_3) & SPD_CAPS_SMAP) == 0)
1153 return -1;
1154 if (SPD_REG16(SPD_R_REV_1) < 0x11)
1155 return -6; // Minimum: revision 17, ES2.
1156
1157 SpdIntrDisable(DEV9_SMAP_ALL_INTR_MASK);
1158
1159 /* Reset FIFOs. */
1160 SMAP_REG8(SMAP_R_TXFIFO_CTRL) = SMAP_TXFIFO_RESET;
1161 for (i = 9; SMAP_REG8(SMAP_R_TXFIFO_CTRL) & SMAP_TXFIFO_RESET; i--) {
1162 if (i <= 0)
1163 return -2;
1164 DelayThread(1000);
1165 }
1166
1167 SMAP_REG8(SMAP_R_RXFIFO_CTRL) = SMAP_RXFIFO_RESET;
1168 for (i = 9; SMAP_REG8(SMAP_R_RXFIFO_CTRL) & SMAP_RXFIFO_RESET; i--) {
1169 if (i <= 0)
1170 return -3;
1171 DelayThread(1000);
1172 }
1173
1174 SMAP_EMAC3_SET32(SMAP_R_EMAC3_MODE0, SMAP_E3_SOFT_RESET);
1175 for (i = 9; SMAP_EMAC3_GET32(SMAP_R_EMAC3_MODE0) & SMAP_E3_SOFT_RESET; i--) {
1176 if (i <= 0)
1177 return -4;
1178 DelayThread(1000);
1179 }
1180
1181 SMAP_REG8(SMAP_R_BD_MODE) = 0;
1182 for (i = 0; i < SMAP_BD_MAX_ENTRY; i++) {
1183 tx_bd[i].ctrl_stat = 0;
1184 tx_bd[i].reserved = 0;
1185 tx_bd[i].length = 0;
1186 tx_bd[i].pointer = 0;
1187 }
1188
1189 for (i = 0; i < SMAP_BD_MAX_ENTRY; i++) {
1190 rx_bd[i].ctrl_stat = SMAP_BD_RX_EMPTY;
1191 rx_bd[i].reserved = 0;
1192 rx_bd[i].length = 0;
1193 rx_bd[i].pointer = 0;
1194 }
1195
1196 SmapDriverData.TxBufferSpaceAvailable = SMAP_TX_BUFSIZE;
1197
1198 SMAP_REG16(SMAP_R_INTR_CLR) = DEV9_SMAP_ALL_INTR_MASK;
1199
1200 /* Retrieve the MAC address and verify it's integrity. */
1201 bzero(eeprom_data, 8);
1202 if ((result = SpdGetEthernetID(eeprom_data)) < 0) {
1203 return (result == -1 ? -7 : -4);
1204 }
1205
1206 for (i = 0; i < 3; i++)
1207 checksum16 += eeprom_data[i];
1208 if (eeprom_data[0] == 0 && eeprom_data[1] == 0 && eeprom_data[2] == 0) {
1209 return -5;
1210 }
1211 if (checksum16 != eeprom_data[3])
1212 return -5;
1213
1214 SMAP_EMAC3_SET32(SMAP_R_EMAC3_MODE1, SMAP_E3_FDX_ENABLE | SMAP_E3_IGNORE_SQE | SMAP_E3_MEDIA_100M | SMAP_E3_RXFIFO_2K | SMAP_E3_TXFIFO_1K | SMAP_E3_TXREQ0_MULTI | SMAP_E3_TXREQ1_SINGLE);
1215 // Tx FIFO request priority. Low: 7*8=56, urgent: 15*8=120.
1216 SMAP_EMAC3_SET32(SMAP_R_EMAC3_TxMODE1, (7 & SMAP_E3_TX_LOW_REQ_MSK) << SMAP_E3_TX_LOW_REQ_BITSFT | (15 & SMAP_E3_TX_URG_REQ_MSK) << SMAP_E3_TX_URG_REQ_BITSFT);
1217 SMAP_EMAC3_SET32(SMAP_R_EMAC3_RxMODE, SMAP_E3_RX_STRIP_PAD | SMAP_E3_RX_STRIP_FCS | SMAP_E3_RX_INDIVID_ADDR | SMAP_E3_RX_BCAST | SMAP_E3_RX_MCAST);
1218 SMAP_EMAC3_SET32(SMAP_R_EMAC3_INTR_STAT, SMAP_E3_INTR_TX_ERR_0 | SMAP_E3_INTR_SQE_ERR_0 | SMAP_E3_INTR_DEAD_0);
1219 SMAP_EMAC3_SET32(SMAP_R_EMAC3_INTR_ENABLE, SMAP_E3_INTR_TX_ERR_0 | SMAP_E3_INTR_SQE_ERR_0 | SMAP_E3_INTR_DEAD_0);
1220
1221 mac_address = (u16)(eeprom_data[0] >> 8 | eeprom_data[0] << 8);
1222 SMAP_EMAC3_SET32(SMAP_R_EMAC3_ADDR_HI, mac_address);
1223
1224 mac_address = ((u16)(eeprom_data[1] >> 8 | eeprom_data[1] << 8) << 16) | (u16)(eeprom_data[2] >> 8 | eeprom_data[2] << 8);
1225 SMAP_EMAC3_SET32(SMAP_R_EMAC3_ADDR_LO, mac_address);
1226
1227 SMAP_EMAC3_SET32(SMAP_R_EMAC3_PAUSE_TIMER, 0xFFFF);
1228 SMAP_EMAC3_SET32(SMAP_R_EMAC3_GROUP_HASH1, 0);
1229 SMAP_EMAC3_SET32(SMAP_R_EMAC3_GROUP_HASH2, 0);
1230 SMAP_EMAC3_SET32(SMAP_R_EMAC3_GROUP_HASH3, 0);
1231 SMAP_EMAC3_SET32(SMAP_R_EMAC3_GROUP_HASH4, 0);
1232
1233 SMAP_EMAC3_SET32(SMAP_R_EMAC3_INTER_FRAME_GAP, 4);
1234 // Tx threshold, (12+1)*64=832.
1235 SMAP_EMAC3_SET32(SMAP_R_EMAC3_TX_THRESHOLD, (12 & SMAP_E3_TX_THRESHLD_MSK) << SMAP_E3_TX_THRESHLD_BITSFT);
1236 // Rx watermark, low: 16*8=128, high: 128*8=1024.
1237 SMAP_EMAC3_SET32(SMAP_R_EMAC3_RX_WATERMARK, (16 & SMAP_E3_RX_LO_WATER_MSK) << SMAP_E3_RX_LO_WATER_BITSFT | (128 & SMAP_E3_RX_HI_WATER_MSK) << SMAP_E3_RX_HI_WATER_BITSFT);
1238
1239 // Register the interrupt handlers for all SMAP events.
1240 for (i = 2; i < 7; i++)
1241 SpdRegisterIntrHandler(i, &Dev9IntrCb);
1242
1243 dev9RegisterPreDmaCb(1, &Dev9PreDmaCbHandler);
1244 dev9RegisterPostDmaCb(1, &Dev9PostDmaCbHandler);
1245
1246 return SetupNetDev();
1247}
1248
1249int SMAPGetMACAddress(u8 *buffer)
1250{
1251 u32 mac_address_lo, mac_address_hi;
1252 volatile u8 *emac3_regbase;
1253 int OldState;
1254
1255 emac3_regbase = SmapDriverData.emac3_regbase;
1256
1257 CpuSuspendIntr(&OldState);
1258
1259 mac_address_hi = SMAP_EMAC3_GET32(SMAP_R_EMAC3_ADDR_HI);
1260 mac_address_lo = SMAP_EMAC3_GET32(SMAP_R_EMAC3_ADDR_LO);
1261
1262 CpuResumeIntr(OldState);
1263
1264 buffer[0] = mac_address_hi >> 8;
1265 buffer[1] = mac_address_hi;
1266 buffer[2] = mac_address_lo >> 24;
1267 buffer[3] = mac_address_lo >> 16;
1268 buffer[4] = mac_address_lo >> 8;
1269 buffer[5] = mac_address_lo;
1270
1271 return 0;
1272}
#define ENXIO
Definition errno.h:31
int CpuResumeIntr(int state)
Definition intrman.c:227
int QueryIntrContext(void)
int CpuSuspendIntr(int *state)
Definition intrman.c:205
@ NETMAN_NETIF_ETH_LINK_MODE_100M_HDX
Definition netman.h:63
@ NETMAN_NETIF_ETH_LINK_MODE_10M_FDX
Definition netman.h:61
@ NETMAN_NETIF_ETH_LINK_MODE_10M_HDX
Definition netman.h:59
@ NETMAN_NETIF_ETH_LINK_MODE_AUTO
Definition netman.h:57
@ NETMAN_NETIF_ETH_LINK_MODE_100M_FDX
Definition netman.h:65
@ NETMAN_NETIF_IOCTL_ETH_GET_MAC
Definition netman.h:78
@ NETMAN_NETIF_IOCTL_ETH_SET_LINK_MODE
Definition netman.h:93
#define NETMAN_NETIF_ETH_LINK_DISABLE_PAUSE
Definition netman.h:53
#define SMAP_BD_TX_ECOLL
Definition smapregs.h:339
#define SMAP_BD_TX_EDEFER
Definition smapregs.h:337
#define SMAP_E3_TX_URG_REQ_BITSFT
Definition smapregs.h:169
#define SMAP_BD_TX_UNDERRUN
Definition smapregs.h:347
#define SMAP_PHY_ANAR_10_FD
Definition smapregs.h:441
#define SMAP_BD_TX_MCOLL
Definition smapregs.h:343
#define SMAP_PHY_BMSR_ANCP
Definition smapregs.h:415
#define SMAP_E3_FLOWCTRL_ENABLE
Definition smapregs.h:122
#define SMAP_PHY_ANAR_TX
Definition smapregs.h:439
#define SMAP_E3_ALLOW_PF
Definition smapregs.h:124
#define SMAP_E3_PHY_OP_COMP
Definition smapregs.h:256
#define SMAP_BD_TX_READY
Definition smapregs.h:313
#define SMAP_BD_TX_SCOLL
Definition smapregs.h:345
#define SMAP_BD_RX_EMPTY
Definition smapregs.h:356
#define SMAP_PHY_ANAR_10
Definition smapregs.h:443
#define SMAP_PHY_ANAR_TX_FD
Definition smapregs.h:437
#define SMAP_BD_TX_LCOLL
Definition smapregs.h:341
#define SMAP_E3_TX_URG_REQ_MSK
Definition smapregs.h:167
#define SMAP_PHY_10BTSCR_LOOPBACK_10_DIS
Definition smapregs.h:491
#define SMAP_PHY_BMSR_LINK
Definition smapregs.h:417
#define SMAP_PHY_10BTSCR_2
Definition smapregs.h:503
#define SMAP_E3_TX_LOW_REQ_BITSFT
Definition smapregs.h:165
#define SMAP_BD_TX_LOSSCR
Definition smapregs.h:335
#define SMAP_E3_TX_LOW_REQ_MSK
Definition smapregs.h:163
#define SMAP_E3_TX_GNP_0
Definition smapregs.h:154