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 sceInetPrintf("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 sceInetPrintf("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 unsigned int SmapConfiguration_old;
201 u16 anar_old;
202
203 SmapConfiguration_old = SmapConfiguration;
204 _smap_write_phy(SmapDrivPrivData->emac3_regbase, SMAP_DsPHYTER_BMCR, 0);
205 value = _smap_read_phy(SmapDrivPrivData->emac3_regbase, SMAP_DsPHYTER_BMSR);
206 if (!(value & 0x4000))
207 SmapConfiguration = SmapConfiguration & 0xFFFFFEFF; /* 100Base-TX FDX */
208 if (!(value & 0x2000))
209 SmapConfiguration = SmapConfiguration & 0xFFFFFF7F; /* 100Base-TX HDX */
210 if (!(value & 0x1000))
211 SmapConfiguration = SmapConfiguration & 0xFFFFFFBF; /* 10Base-TX FDX */
212 if (!(value & 0x0800))
213 SmapConfiguration = SmapConfiguration & 0xFFFFFFDF; /* 10Base-TX HDX */
214
215 DEBUG_PRINTF("no strap mode (conf=0x%x->0x%x, bmsr=0x%x)\n", SmapConfiguration_old, SmapConfiguration, value);
216
217 value = _smap_read_phy(SmapDrivPrivData->emac3_regbase, SMAP_DsPHYTER_ANAR);
218 anar_old = value;
219 value = (SmapConfiguration & 0x5E0) | (value & 0x1F);
220 DEBUG_PRINTF("anar=0x%x->0x%x\n", anar_old, value);
221 _smap_write_phy(SmapDrivPrivData->emac3_regbase, SMAP_DsPHYTER_ANAR, value);
222 _smap_write_phy(SmapDrivPrivData->emac3_regbase, SMAP_DsPHYTER_BMCR, SMAP_PHY_BMCR_ANEN | SMAP_PHY_BMCR_RSAN);
223 } else {
224 if (!(_smap_read_phy(SmapDrivPrivData->emac3_regbase, SMAP_DsPHYTER_BMCR) & SMAP_PHY_BMCR_ANEN)) {
225 goto WaitLink;
226 }
227 }
228
229 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));
230
231 RepeatAutoNegoProcess:
232 for (AutoNegoRetries = 0; AutoNegoRetries < 3; AutoNegoRetries++) {
233 for (i = 0; i < 3; i++) {
234 DelayThread(1000000);
235 if (SmapDrivPrivData->NetDevStopFlag)
236 return 0;
237 }
238
239 value = _smap_read_phy(SmapDrivPrivData->emac3_regbase, SMAP_DsPHYTER_BMSR);
240 if ((value & (SMAP_PHY_BMSR_ANCP | 0x10)) == SMAP_PHY_BMSR_ANCP) { /* 0x30: SMAP_PHY_BMSR_ANCP and Remote fault. */
241 /* This seems to be checking for the link-up status. */
242 for (i = 0; !(_smap_read_phy(SmapDrivPrivData->emac3_regbase, SMAP_DsPHYTER_BMSR) & SMAP_PHY_BMSR_LINK); i++) {
243 DelayThread(200000);
244 if (SmapDrivPrivData->NetDevStopFlag)
245 return 0;
246 if (i >= 20)
247 break;
248 }
249
250 if (i < 20) {
251 /* Auto negotiaton completed successfully. */
252 SmapDrivPrivData->LinkStatus = 1;
253 break;
254 } else
255 RestartAutoNegotiation(SmapDrivPrivData->emac3_regbase, value);
256 } else
257 RestartAutoNegotiation(SmapDrivPrivData->emac3_regbase, value);
258 }
259
260 /* If automatic negotiation fails, manually figure out which speed and duplex mode to use. */
261 if (AutoNegoRetries >= 3) {
262 if (EnableVerboseOutput)
263 DEBUG_PRINTF("waiting valid link for 100Mbps Half-Duplex\n");
264
265 _smap_write_phy(SmapDrivPrivData->emac3_regbase, SMAP_DsPHYTER_BMCR, SMAP_PHY_BMCR_100M);
266 DelayThread(1000000);
267 if (SmapDrivPrivData->NetDevStopFlag)
268 return 0;
269
270 for (i = 0; !(_smap_read_phy(SmapDrivPrivData->emac3_regbase, SMAP_DsPHYTER_BMSR) & SMAP_PHY_BMSR_LINK); i++) {
271 DelayThread(100000);
272 if (SmapDrivPrivData->NetDevStopFlag)
273 return 0;
274 if (i >= 30)
275 break;
276 }
277
278 if (i >= 30) {
279 if (EnableVerboseOutput)
280 DEBUG_PRINTF("waiting valid link for 10Mbps Half-Duplex\n");
281
282 _smap_write_phy(SmapDrivPrivData->emac3_regbase, SMAP_DsPHYTER_BMCR, SMAP_PHY_BMCR_10M);
283 DelayThread(1000000);
284 if (SmapDrivPrivData->NetDevStopFlag)
285 return 0;
286
287 for (i = 0; !(_smap_read_phy(SmapDrivPrivData->emac3_regbase, SMAP_DsPHYTER_BMSR) & SMAP_PHY_BMSR_LINK); i++) {
288 DelayThread(100000);
289 if (SmapDrivPrivData->NetDevStopFlag)
290 return 0;
291 if (i >= 30)
292 break;
293 }
294
295 if (i >= 0x1E)
296 goto RepeatAutoNegoProcess;
297 else
298 SmapDrivPrivData->LinkStatus = 1;
299 } else
300 SmapDrivPrivData->LinkStatus = 1;
301 }
302 }
303
304 for (i = 0; i < 6; i++)
305 RegDump[i] = _smap_read_phy(SmapDrivPrivData->emac3_regbase, i);
306
307 if (EnableVerboseOutput)
308 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]);
309
310 /* Special initialization for the National Semiconductor DP83846A PHY. */
311 if (RegDump[SMAP_DsPHYTER_PHYIDR1] == SMAP_PHY_IDR1_VAL && (RegDump[SMAP_DsPHYTER_PHYIDR2] & SMAP_PHY_IDR2_MSK) == SMAP_PHY_IDR2_VAL) {
312 if (EnableAutoNegotiation) {
313 _smap_read_phy(SmapDrivPrivData->emac3_regbase, SMAP_DsPHYTER_FCSCR);
314 _smap_read_phy(SmapDrivPrivData->emac3_regbase, SMAP_DsPHYTER_RECR);
315 DelayThread(500000);
316 value = _smap_read_phy(SmapDrivPrivData->emac3_regbase, SMAP_DsPHYTER_FCSCR);
317 value2 = _smap_read_phy(SmapDrivPrivData->emac3_regbase, SMAP_DsPHYTER_RECR);
318 if ((value2 != 0) || (value >= 0x11)) {
319 if (EnableVerboseOutput)
320 DEBUG_PRINTF("FCSCR=%d RECR=%d\n", value, value2);
321 _smap_write_phy(SmapDrivPrivData->emac3_regbase, SMAP_DsPHYTER_BMCR, 0);
322 goto WaitLink;
323 }
324 }
325
326 DEBUG_PRINTF("PHY chip: DP83846A%d\n", (RegDump[SMAP_DsPHYTER_PHYIDR2] & SMAP_PHY_IDR2_REV_MSK) + 1);
327
328 /* If operating in 10Mbit mode, disable the 10Mb/s Loopback mode. */
329 if (!EnableAutoNegotiation) {
330 if ((RegDump[SMAP_DsPHYTER_BMCR] & (SMAP_PHY_BMCR_DUPM | SMAP_PHY_BMCR_100M)) == 0)
331 _smap_write_phy(SmapDrivPrivData->emac3_regbase, SMAP_DsPHYTER_10BTSCR, SMAP_PHY_10BTSCR_LOOPBACK_10_DIS | SMAP_PHY_10BTSCR_2);
332 } else {
334 _smap_write_phy(SmapDrivPrivData->emac3_regbase, SMAP_DsPHYTER_10BTSCR, SMAP_PHY_10BTSCR_LOOPBACK_10_DIS | SMAP_PHY_10BTSCR_2);
335 }
336
337 if ((RegDump[SMAP_DsPHYTER_PHYIDR2] & SMAP_PHY_IDR2_REV_MSK) == 0) {
338 _smap_write_phy(SmapDrivPrivData->emac3_regbase, 0x13, 1);
339 _smap_write_phy(SmapDrivPrivData->emac3_regbase, SMAP_DsPHYTER_PHYCTRL, 0x1898);
340 _smap_write_phy(SmapDrivPrivData->emac3_regbase, 0x1F, 0);
341 _smap_write_phy(SmapDrivPrivData->emac3_regbase, 0x1D, 0x5040);
342 _smap_write_phy(SmapDrivPrivData->emac3_regbase, 0x1E, 0x8C);
343 _smap_write_phy(SmapDrivPrivData->emac3_regbase, 0x13, 0);
344 }
345 }
346
347 /* Determine what was negotiated for. */
348 FlowControlEnabled = 0;
349 if (RegDump[SMAP_DsPHYTER_BMCR] & SMAP_PHY_BMCR_ANEN) {
350 value = RegDump[SMAP_DsPHYTER_ANAR] & RegDump[SMAP_DsPHYTER_ANLPAR];
351 LinkSpeed100M = 0 < (value & 0x180);
352 LinkFDX = 0 < (value & 0x140);
353 if (LinkFDX)
354 FlowControlEnabled = 0 < (value & 0x400);
355 } else {
356 LinkSpeed100M = RegDump[SMAP_DsPHYTER_BMCR] >> 13 & 1;
357 LinkFDX = RegDump[SMAP_DsPHYTER_BMCR] >> 8 & 1;
358 FlowControlEnabled = SmapConfiguration >> 10 & 1;
359 }
360
361 if (LinkSpeed100M)
362 result = LinkFDX ? 8 : 4;
363 else
364 result = LinkFDX ? 2 : 1;
365
366 SmapDrivPrivData->LinkMode = result;
367 if (FlowControlEnabled)
368 SmapDrivPrivData->LinkMode |= 0x40;
369
370 DEBUG_PRINTF("%s %s Duplex Mode %s Flow Control\n", LinkSpeed100M ? "100BaseTX" : "10BaseT", LinkFDX ? "Full" : "Half", FlowControlEnabled ? "with" : "without");
371
372 emac3_regbase = SmapDrivPrivData->emac3_regbase;
373 emac3_value = SMAP_EMAC3_GET32(SMAP_R_EMAC3_MODE1) & 0x67FFFFFF;
374 if (LinkFDX)
375 emac3_value |= SMAP_E3_FDX_ENABLE;
376 if (FlowControlEnabled)
378 SMAP_EMAC3_SET32(SMAP_R_EMAC3_MODE1, emac3_value);
379
380 return 0;
381}
382
383// This timer callback starts the Ethernet link check event.
384static unsigned int LinkCheckTimerCB(struct SmapDriverData *SmapDrivPrivData)
385{
386 iSetEventFlag(SmapDrivPrivData->Dev9IntrEventFlag, SMAP_EVENT_LINK_CHECK);
387 return SmapDrivPrivData->LinkCheckTimer.lo;
388}
389
390static int HandleTxIntr(struct SmapDriverData *SmapDrivPrivData)
391{
392 int result, i;
393 USE_SMAP_TX_BD;
394 u16 ctrl_stat;
395
396 result = 0;
397 while (SmapDrivPrivData->NumPacketsInTx > 0) {
398 ctrl_stat = tx_bd[SmapDrivPrivData->TxDNVBDIndex % SMAP_BD_MAX_ENTRY].ctrl_stat;
399 if (!(ctrl_stat & SMAP_BD_TX_READY)) {
401 for (i = 0; i < 16; i++)
402 if ((ctrl_stat >> i) & 1) {
403 SmapDrivPrivData->RuntimeStats.TxErrorCount++;
404#ifdef BUILDING_SMAP_NETDEV
405 SmapDrivPrivData->RuntimeStats_NetDev.m_TxErrorVarious[i] += 1;
406#endif
407 }
408
409 SmapDrivPrivData->RuntimeStats.TxDroppedFrameCount++;
410#ifdef BUILDING_SMAP_NETDEV
411 SmapDrivPrivData->RuntimeStats_NetDev.m_Tx_Errors += 1;
412#endif
413 if (ctrl_stat & SMAP_BD_TX_LOSSCR) {
414 SmapDrivPrivData->RuntimeStats.TxFrameLOSSCRCount++;
415#ifdef BUILDING_SMAP_NETDEV
416 SmapDrivPrivData->RuntimeStats_NetDev.m_Tx_Carrier_Er += 1;
417#endif
418 }
419 if (ctrl_stat & SMAP_BD_TX_EDEFER) {
420 SmapDrivPrivData->RuntimeStats.TxFrameEDEFERCount++;
421#ifdef BUILDING_SMAP_NETDEV
422 SmapDrivPrivData->RuntimeStats_NetDev.m_Tx_Window_Er += 1;
423#endif
424 }
426 SmapDrivPrivData->RuntimeStats.TxFrameCollisionCount++;
427#ifdef BUILDING_SMAP_NETDEV
428 SmapDrivPrivData->RuntimeStats_NetDev.m_Collisions += 1;
429#endif
430 }
431 if (ctrl_stat & SMAP_BD_TX_UNDERRUN) {
432 SmapDrivPrivData->RuntimeStats.TxFrameUnderrunCount++;
433#ifdef BUILDING_SMAP_NETDEV
434 SmapDrivPrivData->RuntimeStats_NetDev.m_Tx_Fifo_Er += 1;
435#endif
436 }
437 }
438 } else
439 break;
440
441 result++;
442 SmapDrivPrivData->TxBufferSpaceAvailable += (tx_bd[SmapDrivPrivData->TxDNVBDIndex & (SMAP_BD_MAX_ENTRY - 1)].length + 3) & ~3;
443 SmapDrivPrivData->TxDNVBDIndex++;
444 SmapDrivPrivData->NumPacketsInTx--;
445 }
446
447 return result;
448}
449
450#ifdef BUILDING_SMAP_NETDEV
451static void ClearPacketQueue(struct SmapDriverData *SmapDrivPrivData);
452#endif
453
454// Checks the status of the Ethernet link
455static void CheckLinkStatus(struct SmapDriverData *SmapDrivPrivData)
456{
457 if (!(_smap_read_phy(SmapDrivPrivData->emac3_regbase, SMAP_DsPHYTER_BMSR) & SMAP_PHY_BMSR_LINK)) {
458 // Link lost
459 SmapDrivPrivData->LinkStatus = 0;
460 SMapCommonLinkStateDown(SmapDrivPrivData);
461 InitPHY(SmapDrivPrivData);
462#ifdef BUILDING_SMAP_NETDEV
463 ClearPacketQueue(SmapDrivPrivData);
464#endif
465
466 // Link established
467 if (SmapDrivPrivData->LinkStatus)
468 SMapCommonLinkStateUp(SmapDrivPrivData);
469 }
470}
471
472#ifdef SMAP_RX_PACKETS_POLLING_MODE
473static unsigned int RxIntrPollingTimerCB(struct SmapDriverData *SmapDrivPrivData)
474{
475 iSetEventFlag(SmapDrivPrivData->Dev9IntrEventFlag, SMAP_EVENT_INTR);
476 return 0;
477}
478#endif
479
480static void IntrHandlerThread(struct SmapDriverData *SmapDrivPrivData)
481{
482 unsigned int PacketCount, IntrReg;
483 u32 EFBits;
484 int counter;
485 volatile u8 *smap_regbase, *emac3_regbase;
486 USE_SPD_REGS;
487
488 counter = 3;
489 emac3_regbase = SmapDrivPrivData->emac3_regbase;
490 smap_regbase = SmapDrivPrivData->smap_regbase;
491
492 SmapDrivPrivData->TxBufferSpaceAvailable = SMAP_TX_BUFSIZE;
493 SmapDrivPrivData->NumPacketsInTx = 0;
494 SmapDrivPrivData->TxBDIndex = 0;
495 SmapDrivPrivData->TxDNVBDIndex = 0;
496 SmapDrivPrivData->RxBDIndex = 0;
497 SmapDrivPrivData->packetToSend = NULL;
498
499 while (1) {
500 int result;
501
502 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) {
503 DEBUG_PRINTF("WaitEventFlag -> %d\n", result);
504 break;
505 }
506
507 if (EFBits & SMAP_EVENT_STOP) {
508 if (SmapDrivPrivData->SmapIsInitialized) {
509 SpdIntrDisable(DEV9_SMAP_INTR_MASK2);
510 SMAP_EMAC3_SET32(SMAP_R_EMAC3_MODE0, 0);
511 SmapDrivPrivData->NetDevStopFlag = 0;
512 SmapDrivPrivData->LinkStatus = 0;
513 SmapDrivPrivData->SmapIsInitialized = 0;
514 SmapDrivPrivData->SmapDriverStarting = 0;
515 SMapCommonLinkStateDown(SmapDrivPrivData);
516 }
517 }
518 if (EFBits & SMAP_EVENT_START) {
519 if (!SmapDrivPrivData->SmapIsInitialized) {
520 SmapDrivPrivData->SmapDriverStarting = 1;
521 SpdIntrEnable(DEV9_SMAP_INTR_MASK2);
522 if ((result = InitPHY(SmapDrivPrivData)) != 0)
523 break;
524 if (SmapDrivPrivData->NetDevStopFlag) {
525 SmapDrivPrivData->NetDevStopFlag = 0;
526 SmapDrivPrivData->SmapDriverStarting = 0;
527 continue;
528 }
529
530 SMAP_EMAC3_SET32(SMAP_R_EMAC3_MODE0, SMAP_E3_TXMAC_ENABLE | SMAP_E3_RXMAC_ENABLE);
531 DelayThread(10000);
532 SmapDrivPrivData->SmapIsInitialized = 1;
533 SmapDrivPrivData->SmapDriverStarting = 0;
534
535 SMapCommonLinkStateUp(SmapDrivPrivData);
536
537 if (!SmapDrivPrivData->EnableLinkCheckTimer) {
538 USec2SysClock(1000000, &SmapDrivPrivData->LinkCheckTimer);
539 SetAlarm(&SmapDrivPrivData->LinkCheckTimer, (void *)&LinkCheckTimerCB, SmapDrivPrivData);
540 SmapDrivPrivData->EnableLinkCheckTimer = 1;
541 }
542 }
543 }
544
545 if (SmapDrivPrivData->SmapIsInitialized) {
546 PacketCount = 0;
547 if (EFBits & SMAP_EVENT_INTR) {
548 if ((IntrReg = SPD_REG16(SPD_R_INTR_STAT) & DEV9_SMAP_INTR_MASK) != 0) {
549 /* Original order/priority:
550 1. EMAC3
551 2. RXEND
552 3. RXDNV
553 4. TXDNV */
554 if (IntrReg & SMAP_INTR_EMAC3) {
555 SMAP_REG16(SMAP_R_INTR_CLR) = SMAP_INTR_EMAC3;
556 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);
557 }
558 if (IntrReg & SMAP_INTR_RXEND) {
559 SMAP_REG16(SMAP_R_INTR_CLR) = SMAP_INTR_RXEND;
560 PacketCount = HandleRxIntr(SmapDrivPrivData);
561 }
562 if (IntrReg & SMAP_INTR_RXDNV) {
563 SMAP_REG16(SMAP_R_INTR_CLR) = SMAP_INTR_RXDNV;
564 SmapDrivPrivData->RuntimeStats.RxFrameOverrunCount++;
565#ifdef BUILDING_SMAP_NETDEV
566 SmapDrivPrivData->RuntimeStats_NetDev.m_Rx_Over_Er += 1;
567#endif
568 }
569 if (IntrReg & SMAP_INTR_TXDNV) {
570 SMAP_REG16(SMAP_R_INTR_CLR) = SMAP_INTR_TXDNV;
571 HandleTxIntr(SmapDrivPrivData);
572 EFBits |= SMAP_EVENT_XMIT;
573 }
574 }
575 }
576
577 if (EFBits & SMAP_EVENT_XMIT)
578 HandleTxReqs(SmapDrivPrivData);
579 // This was added in later versions.
580 HandleTxIntr(SmapDrivPrivData);
581
582 // TXDNV is not enabled here, but only when frames are transmitted.
583#ifdef SMAP_RX_PACKETS_POLLING_MODE
584 SpdIntrEnable(SMAP_INTR_EMAC3 | SMAP_INTR_RXDNV);
585
586 if (PacketCount >= 1) {
587 // Receive packets in polling mode
588
589 // We're receiving packets at a maximum rate of 100 bits/us or 12.5 bytes/us
590#define ETH_KB_TO_US(B) (B * 80)
591
592 USec2SysClock(ETH_KB_TO_US(12), &SmapDrivPrivData->RxIntrPollingTimer);
593#undef ETH_KB_TO_US
594 SetAlarm(&SmapDrivPrivData->RxIntrPollingTimer, (void *)&RxIntrPollingTimerCB, SmapDrivPrivData);
595 } else {
596 // Receive packets in interrupt mode
597 SpdIntrEnable(SMAP_INTR_RXEND);
598 }
599#else
600 SpdIntrEnable(DEV9_SMAP_INTR_MASK2);
601#endif
602
603 // If there are frames to send out, let Tx channel 0 know and enable TXDNV.
604 if (SmapDrivPrivData->NumPacketsInTx > 0) {
605 SMAP_EMAC3_SET32(SMAP_R_EMAC3_TxMODE0, SMAP_E3_TX_GNP_0);
606 SpdIntrEnable(SMAP_INTR_TXDNV);
607 }
608
609 // Do the link check, only if there has not been any incoming traffic in a while.
610 if (PacketCount) {
611 counter = 3;
612 continue;
613 }
614
615 if (EFBits & SMAP_EVENT_LINK_CHECK) {
616 if (--counter <= 0)
617 CheckLinkStatus(SmapDrivPrivData);
618 }
619 }
620 }
621}
622
623static int Dev9IntrCb(int flag)
624{
625#if USE_GP_REGISTER
626 void *OldGP;
627
628 OldGP = SetModuleGP();
629#endif
630
631 (void)flag;
632
633 SpdIntrDisable(DEV9_SMAP_ALL_INTR_MASK);
634 iSetEventFlag(SmapDriverData.Dev9IntrEventFlag, SMAP_EVENT_INTR);
635
636#if USE_GP_REGISTER
637 SetGP(OldGP);
638#endif
639
640 return 0;
641}
642
643static void Dev9PreDmaCbHandler(int bcr, int dir)
644{
645 // cppcheck-suppress constVariablePointer
646 volatile u8 *smap_regbase;
647 u16 SliceCount;
648
649 smap_regbase = SmapDriverData.smap_regbase;
650 SliceCount = bcr >> 16;
651 if (dir != DMAC_TO_MEM) {
652 SMAP_REG16(SMAP_R_TXFIFO_SIZE) = SliceCount;
653 SMAP_REG8(SMAP_R_TXFIFO_CTRL) = SMAP_TXFIFO_DMAEN;
654 } else {
655 SMAP_REG16(SMAP_R_RXFIFO_SIZE) = SliceCount;
656 SMAP_REG8(SMAP_R_RXFIFO_CTRL) = SMAP_RXFIFO_DMAEN;
657 }
658}
659
660static void Dev9PostDmaCbHandler(int bcr, int dir)
661{
662 // cppcheck-suppress constVariablePointer
663 volatile u8 *smap_regbase;
664
665 (void)bcr;
666
667 smap_regbase = SmapDriverData.smap_regbase;
668 if (dir != DMAC_TO_MEM) {
669 while (SMAP_REG8(SMAP_R_TXFIFO_CTRL) & SMAP_TXFIFO_DMAEN) {};
670 } else {
671 while (SMAP_REG8(SMAP_R_RXFIFO_CTRL) & SMAP_RXFIFO_DMAEN) {};
672 }
673}
674
675#ifdef BUILDING_SMAP_PS2IP
676// For the initial startup, as legacy programs expect the Ethernet interface to be ready once SMAP finishes initialization.
677int SMAPInitStart(void)
678{
679 // cppcheck-suppress constVariablePointer
680 volatile u8 *emac3_regbase;
681
682#if USE_GP_REGISTER
683 void *OldGP;
684
685 OldGP = SetModuleGP();
686#endif
687
688 if (!SmapDriverData.SmapIsInitialized) {
689 emac3_regbase = SmapDriverData.emac3_regbase;
690
691 SpdIntrEnable(DEV9_SMAP_INTR_MASK2);
692 if (InitPHY(&SmapDriverData) == 0 && !SmapDriverData.NetDevStopFlag) {
693 SMAP_EMAC3_SET32(SMAP_R_EMAC3_MODE0, SMAP_E3_TXMAC_ENABLE | SMAP_E3_RXMAC_ENABLE);
694 DelayThread(10000);
695 SmapDriverData.SmapIsInitialized = 1;
696
697 SMapCommonLinkStateUp(&SmapDriverData);
698
699 if (!SmapDriverData.EnableLinkCheckTimer) {
700 USec2SysClock(1000000, &SmapDriverData.LinkCheckTimer);
701 SetAlarm(&SmapDriverData.LinkCheckTimer, (void *)&LinkCheckTimerCB, &SmapDriverData);
702 SmapDriverData.EnableLinkCheckTimer = 1;
703 }
704 } else
705 SmapDriverData.NetDevStopFlag = 0;
706 }
707
708#if USE_GP_REGISTER
709 SetGP(OldGP);
710#endif
711
712 return 0;
713}
714#endif
715
716#if defined(BUILDING_SMAP_NETMAN) || defined(BUILDING_SMAP_NETDEV)
717#ifdef BUILDING_SMAP_NETDEV
718static int SMAPStart(void *priv, int flags)
719#else
720static int SMAPStart(void)
721#endif
722{
723 struct SmapDriverData *SmapDrivPrivData;
724#if USE_GP_REGISTER
725 void *OldGP;
726
727 OldGP = SetModuleGP();
728#endif
729
730#ifdef BUILDING_SMAP_NETDEV
731 (void)flags;
732
733 SmapDrivPrivData = (struct SmapDriverData *)priv;
734#else
735 SmapDrivPrivData = &SmapDriverData;
736#endif
737
738 SetEventFlag(SmapDrivPrivData->Dev9IntrEventFlag, SMAP_EVENT_START);
739
740#if USE_GP_REGISTER
741 SetGP(OldGP);
742#endif
743
744 return 0;
745}
746
747#ifdef BUILDING_SMAP_NETDEV
748static int SMAPStop(void *priv, int flags)
749#else
750static void SMAPStop(void)
751#endif
752{
753 struct SmapDriverData *SmapDrivPrivData;
754#if USE_GP_REGISTER
755 void *OldGP;
756
757 OldGP = SetModuleGP();
758#endif
759
760#ifdef BUILDING_SMAP_NETDEV
761 (void)flags;
762
763 SmapDrivPrivData = (struct SmapDriverData *)priv;
764#else
765 SmapDrivPrivData = &SmapDriverData;
766#endif
767
768 SetEventFlag(SmapDrivPrivData->Dev9IntrEventFlag, SMAP_EVENT_STOP);
769 SmapDrivPrivData->NetDevStopFlag = 1;
770
771#if USE_GP_REGISTER
772 SetGP(OldGP);
773#endif
774
775#ifdef BUILDING_SMAP_NETDEV
776 return 0;
777#endif
778}
779#endif
780
781static void ClearPacketQueue(struct SmapDriverData *SmapDrivPrivData)
782{
783 int OldState;
784 void *data;
785 void *pbuf;
786
787 data = NULL;
788 CpuSuspendIntr(&OldState);
789 pbuf = SmapDrivPrivData->packetToSend;
790 SmapDrivPrivData->packetToSend = NULL;
791 CpuResumeIntr(OldState);
792
793 while (pbuf != NULL) {
794#ifdef BUILDING_SMAP_NETDEV
795 SmapDrivPrivData->RuntimeStats_NetDev.m_Tx_Dropped += 1;
796#endif
797 if (SMAPCommonTxPacketNext(SmapDrivPrivData, &data, &pbuf) <= 0)
798 break;
799 SMAPCommonTxPacketDeQ(SmapDrivPrivData, &data, &pbuf);
800 }
801}
802
803#ifdef BUILDING_SMAP_NETDEV
804static int SMAPXmit_NetDev(void *priv, int flags)
805#else
806void SMAPXmit(void)
807#endif
808{
809 struct SmapDriverData *SmapDrivPrivData;
810#if USE_GP_REGISTER
811 void *OldGP;
812
813 OldGP = SetModuleGP();
814#endif
815
816#ifdef BUILDING_SMAP_NETDEV
817 (void)flags;
818
819 SmapDrivPrivData = (struct SmapDriverData *)priv;
820#else
821 SmapDrivPrivData = &SmapDriverData;
822#endif
823
824 if (SmapDriverData.LinkStatus) {
825 if (QueryIntrContext())
826 iSetEventFlag(SmapDrivPrivData->Dev9IntrEventFlag, SMAP_EVENT_XMIT);
827 else
828 SetEventFlag(SmapDrivPrivData->Dev9IntrEventFlag, SMAP_EVENT_XMIT);
829 } else {
830 // No link. Clear the packet queue.
831 ClearPacketQueue(SmapDrivPrivData);
832 }
833
834#if USE_GP_REGISTER
835 SetGP(OldGP);
836#endif
837#ifdef BUILDING_SMAP_NETDEV
838 return 0;
839#endif
840}
841
842#ifdef BUILDING_SMAP_NETDEV
843void SMAPXmit(void)
844{
845 SMAPXmit_NetDev(&SmapDriverData, 0);
846}
847#endif
848
849#ifdef BUILDING_SMAP_NETMAN
850static int SMAPGetLinkMode(void)
851{
852 u16 value;
853 int result;
854
855 result = -1;
856 if (SmapDriverData.SmapIsInitialized && SmapDriverData.LinkStatus) {
857 value = SmapDriverData.LinkMode;
858 if (value & 0x08)
859 result = NETMAN_NETIF_ETH_LINK_MODE_100M_FDX; /* 100Base-TX FDX */
860 if (value & 0x04)
861 result = NETMAN_NETIF_ETH_LINK_MODE_100M_HDX; /* 100Base-TX HDX */
862 if (value & 0x02)
863 result = NETMAN_NETIF_ETH_LINK_MODE_10M_FDX; /* 10Base-TX FDX */
864 if (value & 0x01)
865 result = NETMAN_NETIF_ETH_LINK_MODE_10M_HDX; /* 10Base-TX HDX */
866 if (!(value & 0x40))
868 }
869
870 return result;
871}
872
873static int SMAPSetLinkMode(int mode)
874{
875 int result;
876
877 if (SmapDriverData.SmapIsInitialized) {
878 int baseMode;
879
880 baseMode = mode & (~NETMAN_NETIF_ETH_LINK_DISABLE_PAUSE);
881
882 if (baseMode != NETMAN_NETIF_ETH_LINK_MODE_AUTO) {
883 EnableAutoNegotiation = 0;
884
885 switch (baseMode) {
887 SmapConfiguration = 0x020;
888 result = 0;
889 break;
891 SmapConfiguration = 0x040;
892 result = 0;
893 break;
895 SmapConfiguration = 0x080;
896 result = 0;
897 break;
899 SmapConfiguration = 0x0100;
900 result = 0;
901 break;
902 default:
903 result = -1;
904 }
905 } else {
906 SmapConfiguration = 0x1E0;
907 EnableAutoNegotiation = 1;
908 result = 0;
909 }
910
911 if (result == 0) {
913 SmapConfiguration |= 0x400; // Enable flow control.
914
915 SetEventFlag(SmapDriverData.Dev9IntrEventFlag, SMAP_EVENT_STOP | SMAP_EVENT_START);
916 SmapDriverData.NetDevStopFlag = 1;
917 }
918 } else
919 result = -ENXIO;
920
921 return result;
922}
923
924static inline int SMAPGetLinkStatus(void)
925{
926 return ((SmapDriverData.SmapIsInitialized && SmapDriverData.LinkStatus) ? NETMAN_NETIF_ETH_LINK_STATE_UP : NETMAN_NETIF_ETH_LINK_STATE_DOWN);
927}
928#endif
929
930#ifdef BUILDING_SMAP_NETDEV
931static int do_set_multicast_list_helper(const struct SmapDriverData *SmapDrivPrivData, u8 *in_out_ptr, int in_out_len)
932{
933 // cppcheck-suppress constVariablePointer
934 volatile u8 *emac3_regbase;
935 int i;
936 u16 group_hash[4];
937
938 emac3_regbase = SmapDrivPrivData->emac3_regbase;
939 bzero(group_hash, sizeof(group_hash));
940 if (in_out_len >= 0) {
941 int length_div_6;
942
943 length_div_6 = in_out_len / 6;
944 if (in_out_len != 6 * length_div_6) {
945 return -512;
946 }
947 if (in_out_ptr) {
948 int k;
949
950 for (k = 0; k < length_div_6; k += 1) {
951 if ((*in_out_ptr & 1) != 0) {
952 unsigned int cur_group_1;
953 unsigned int cur_group_2;
954
955 cur_group_1 = (unsigned int)-1;
956 for (i = 0; i < 4; i += 1) {
957 u8 cur_item;
958 int j;
959
960 cur_item = *in_out_ptr++;
961 // This is crc32
962 for (j = 0; j < 6; j += 1) {
963 cur_group_2 = cur_group_1 << 1;
964 if (((((cur_group_1 & 0x80000000) != 0) ^ cur_item) & 1) != 0)
965 cur_group_2 ^= 0x4C11DB7u;
966 cur_group_1 = cur_group_2;
967 cur_item >>= 1;
968 }
969 }
970 group_hash[cur_group_2 >> 30] |= 1 << ((cur_group_2 >> 26) & 0xF);
971 } else {
972 in_out_ptr += 6;
973 }
974 }
975 }
976 } else {
977 if (in_out_ptr)
978 return -512;
979 for (i = 0; i < 4; i += 1) {
980 group_hash[i] = -1;
981 }
982 }
983 SMAP_EMAC3_SET32(SMAP_R_EMAC3_GROUP_HASH1, group_hash[3]);
984 SMAP_EMAC3_SET32(SMAP_R_EMAC3_GROUP_HASH2, group_hash[2]);
985 SMAP_EMAC3_SET32(SMAP_R_EMAC3_GROUP_HASH3, group_hash[1]);
986 SMAP_EMAC3_SET32(SMAP_R_EMAC3_GROUP_HASH4, group_hash[0]);
987 return 0;
988}
989#endif
990
991#if defined(BUILDING_SMAP_NETMAN) || defined(BUILDING_SMAP_NETDEV)
992#ifdef BUILDING_SMAP_NETDEV
993static int SMAPIoctl(void *priv, int command, void *in_out_ptr, int in_out_len)
994#else
995static int SMAPIoctl(unsigned int command, void *args, unsigned int args_len, void *output, unsigned int length)
996#endif
997{
998 int result;
999#ifdef BUILDING_SMAP_NETDEV
1000 struct SmapDriverData *SmapDrivPrivData;
1001 const void *tmpoutptr;
1002 int bufasint;
1003#endif
1004#if USE_GP_REGISTER
1005 void *OldGP;
1006
1007 OldGP = SetModuleGP();
1008#endif
1009
1010#ifdef BUILDING_SMAP_NETDEV
1011 SmapDrivPrivData = (struct SmapDriverData *)priv;
1012 bufasint = 0;
1013 result = -512;
1014 tmpoutptr = NULL;
1015 switch (command) {
1016 case sceInetNDCC_GET_IF_TYPE:
1017 result = sceInetNDIFT_ETHERNET;
1018 break;
1019 case sceInetNDCC_GET_NEGO_STATUS: {
1020 result = 0;
1021 if ((int)(SmapDrivPrivData->LinkStatus) > 0)
1022 result = SmapDrivPrivData->LinkMode;
1023 break;
1024 }
1025 case sceInetNDCC_GET_LINK_STATUS:
1026 result = SmapDrivPrivData->LinkStatus;
1027 break;
1028 case sceInetNDCC_GET_THPRI:
1029 result = ThreadPriority;
1030 break;
1031 case sceInetNDCC_SET_THPRI: {
1032 if (in_out_ptr && in_out_len == 4) {
1033 result = -403;
1034 memcpy(&bufasint, in_out_ptr, 4);
1035 if ((unsigned int)(bufasint - 9) < 0x73) {
1036 ThreadPriority = bufasint;
1037 result = ChangeThreadPriority(SmapDrivPrivData->IntrHandlerThreadID, bufasint);
1038 }
1039 }
1040 break;
1041 }
1042 case sceInetNDCC_GET_NEGO_MODE: {
1043 bufasint = 0;
1044 if (EnableAutoNegotiation != 0)
1045 bufasint |= sceInetNDNEGO_AUTO;
1046 if ((SmapConfiguration & 0x400) != 0)
1047 bufasint |= sceInetNDNEGO_PAUSE;
1048 if ((SmapConfiguration & 0x100) != 0)
1049 bufasint |= sceInetNDNEGO_TX_FD;
1050 if ((SmapConfiguration & 0x80) != 0)
1051 bufasint |= sceInetNDNEGO_TX;
1052 if ((SmapConfiguration & 0x40) != 0)
1053 bufasint |= sceInetNDNEGO_10_FD;
1054 if ((SmapConfiguration & 0x20) != 0)
1055 bufasint |= sceInetNDNEGO_10;
1056 tmpoutptr = &bufasint;
1057 break;
1058 }
1059 case sceInetNDCC_SET_NEGO_MODE: {
1060 if (in_out_ptr && in_out_len == 4) {
1061 int tmpconfig;
1062
1063 tmpconfig = 0;
1064 memcpy(&bufasint, in_out_ptr, 4);
1065 EnableAutoNegotiation = ((bufasint & sceInetNDNEGO_AUTO) != 0 ? 1 : 0);
1066 if ((bufasint & sceInetNDNEGO_PAUSE) != 0)
1067 tmpconfig |= 0x400;
1068 if ((bufasint & sceInetNDNEGO_TX_FD) != 0)
1069 tmpconfig |= 0x100;
1070 if ((bufasint & sceInetNDNEGO_TX) != 0)
1071 tmpconfig |= 0x80;
1072 if ((bufasint & sceInetNDNEGO_10_FD) != 0)
1073 tmpconfig |= 0x40;
1074 if ((bufasint & sceInetNDNEGO_10) != 0)
1075 tmpconfig |= 0x20;
1076 SmapConfiguration = tmpconfig;
1077 result = 0;
1078 }
1079 break;
1080 }
1081 case sceInetNDCC_GET_MULTICAST:
1082 tmpoutptr = &SmapDrivPrivData->RuntimeStats_NetDev.m_Multicast;
1083 break;
1084 case sceInetNDCC_GET_COLLISIONS:
1085 tmpoutptr = &SmapDrivPrivData->RuntimeStats_NetDev.m_Collisions;
1086 break;
1087 case sceInetNDCC_GET_RX_LENGTH_ER:
1088 tmpoutptr = &SmapDrivPrivData->RuntimeStats_NetDev.m_Rx_Length_Er;
1089 break;
1090 case sceInetNDCC_GET_RX_OVER_ER:
1091 tmpoutptr = &SmapDrivPrivData->RuntimeStats_NetDev.m_Rx_Over_Er;
1092 break;
1093 case sceInetNDCC_GET_RX_CRC_ER:
1094 tmpoutptr = &SmapDrivPrivData->RuntimeStats_NetDev.m_Rx_Crc_Er;
1095 break;
1096 case sceInetNDCC_GET_RX_FRAME_ER:
1097 tmpoutptr = &SmapDrivPrivData->RuntimeStats_NetDev.m_Rx_Frame_Er;
1098 break;
1099 case sceInetNDCC_GET_RX_FIFO_ER:
1100 tmpoutptr = &SmapDrivPrivData->RuntimeStats_NetDev.m_Rx_Fifo_Er;
1101 break;
1102 case sceInetNDCC_GET_RX_MISSED_ER:
1103 tmpoutptr = &SmapDrivPrivData->RuntimeStats_NetDev.m_Rx_Missed_Er;
1104 break;
1105 case sceInetNDCC_GET_TX_ABORTED_ER:
1106 tmpoutptr = &SmapDrivPrivData->RuntimeStats_NetDev.m_Tx_Aborted_Er;
1107 break;
1108 case sceInetNDCC_GET_TX_CARRIER_ER:
1109 tmpoutptr = &SmapDrivPrivData->RuntimeStats_NetDev.m_Tx_Carrier_Er;
1110 break;
1111 case sceInetNDCC_GET_TX_FIFO_ER:
1112 tmpoutptr = &SmapDrivPrivData->RuntimeStats_NetDev.m_Tx_Fifo_Er;
1113 break;
1114 case sceInetNDCC_GET_TX_HEARTBEAT_ER:
1115 tmpoutptr = &SmapDrivPrivData->RuntimeStats_NetDev.m_Tx_Heartbeat_Er;
1116 break;
1117 case sceInetNDCC_GET_TX_WINDOW_ER:
1118 tmpoutptr = &SmapDrivPrivData->RuntimeStats_NetDev.m_Tx_Window_Er;
1119 break;
1120 case sceInetNDCC_GET_RX_PACKETS:
1121 tmpoutptr = &SmapDrivPrivData->RuntimeStats_NetDev.m_Rx_Packets;
1122 break;
1123 case sceInetNDCC_GET_TX_PACKETS:
1124 tmpoutptr = &SmapDrivPrivData->RuntimeStats_NetDev.m_Tx_Packets;
1125 break;
1126 case sceInetNDCC_GET_RX_BYTES:
1127 tmpoutptr = &SmapDrivPrivData->RuntimeStats_NetDev.m_Rx_Bytes;
1128 break;
1129 case sceInetNDCC_GET_TX_BYTES:
1130 tmpoutptr = &SmapDrivPrivData->RuntimeStats_NetDev.m_Tx_Bytes;
1131 break;
1132 case sceInetNDCC_GET_RX_ERRORS:
1133 tmpoutptr = &SmapDrivPrivData->RuntimeStats_NetDev.m_Rx_Errors;
1134 break;
1135 case sceInetNDCC_GET_TX_ERRORS:
1136 tmpoutptr = &SmapDrivPrivData->RuntimeStats_NetDev.m_Tx_Errors;
1137 break;
1138 case sceInetNDCC_GET_RX_DROPPED:
1139 tmpoutptr = &SmapDrivPrivData->RuntimeStats_NetDev.m_Rx_Dropped;
1140 break;
1141 case sceInetNDCC_GET_TX_DROPPED:
1142 tmpoutptr = &SmapDrivPrivData->RuntimeStats_NetDev.m_Tx_Dropped;
1143 break;
1144 case sceInetNDCC_GET_RX_BROADCAST_PACKETS:
1145 tmpoutptr = &SmapDrivPrivData->RuntimeStats_NetDev.m_Rx_Broadcast_Packets;
1146 break;
1147 case sceInetNDCC_GET_TX_BROADCAST_PACKETS:
1148 tmpoutptr = &SmapDrivPrivData->RuntimeStats_NetDev.m_Tx_Broadcast_Packets;
1149 break;
1150 case sceInetNDCC_GET_RX_BROADCAST_BYTES:
1151 tmpoutptr = &SmapDrivPrivData->RuntimeStats_NetDev.m_Rx_Broadcast_Bytes;
1152 break;
1153 case sceInetNDCC_GET_TX_BROADCAST_BYTES:
1154 tmpoutptr = &SmapDrivPrivData->RuntimeStats_NetDev.m_Tx_Broadcast_Bytes;
1155 break;
1156 case sceInetNDCC_GET_RX_MULTICAST_PACKETS:
1157 tmpoutptr = &SmapDrivPrivData->RuntimeStats_NetDev.m_Rx_Multicast_Packets;
1158 break;
1159 case sceInetNDCC_GET_TX_MULTICAST_PACKETS:
1160 tmpoutptr = &SmapDrivPrivData->RuntimeStats_NetDev.m_Tx_Multicast_Packets;
1161 break;
1162 case sceInetNDCC_GET_RX_MULTICAST_BYTES:
1163 tmpoutptr = &SmapDrivPrivData->RuntimeStats_NetDev.m_Rx_Multicast_Bytes;
1164 break;
1165 case sceInetNDCC_GET_TX_MULTICAST_BYTES:
1166 tmpoutptr = &SmapDrivPrivData->RuntimeStats_NetDev.m_Tx_Multicast_Bytes;
1167 break;
1168 case sceInetNDCC_SET_MULTICAST_LIST:
1169 result = do_set_multicast_list_helper(SmapDrivPrivData, in_out_ptr, in_out_len);
1170 break;
1171 default:
1172 break;
1173 }
1174
1175 if (tmpoutptr && in_out_ptr && in_out_len == 4) {
1176 memcpy(in_out_ptr, tmpoutptr, in_out_len);
1177 result = 0;
1178 }
1179#else
1180 (void)args_len;
1181 (void)length;
1182
1183 switch (command) {
1185 result = SMAPGetMACAddress(output);
1186 break;
1187 case NETMAN_NETIF_IOCTL_ETH_GET_LINK_MODE:
1188 result = SMAPGetLinkMode();
1189 break;
1190 case NETMAN_NETIF_IOCTL_GET_LINK_STATUS:
1191 result = SMAPGetLinkStatus();
1192 break;
1193 case NETMAN_NETIF_IOCTL_GET_TX_DROPPED_COUNT:
1194 result = SmapDriverData.RuntimeStats.TxDroppedFrameCount;
1195 break;
1196 case NETMAN_NETIF_IOCTL_GET_RX_DROPPED_COUNT:
1197 result = SmapDriverData.RuntimeStats.RxDroppedFrameCount;
1198 break;
1199 case NETMAN_NETIF_IOCTL_ETH_GET_RX_EOVERRUN_CNT:
1200 result = SmapDriverData.RuntimeStats.RxFrameOverrunCount;
1201 break;
1202 case NETMAN_NETIF_IOCTL_ETH_GET_RX_EBADLEN_CNT:
1203 result = SmapDriverData.RuntimeStats.RxFrameBadLengthCount;
1204 break;
1205 case NETMAN_NETIF_IOCTL_ETH_GET_RX_EBADFCS_CNT:
1206 result = SmapDriverData.RuntimeStats.RxFrameBadFCSCount;
1207 break;
1208 case NETMAN_NETIF_IOCTL_ETH_GET_RX_EBADALIGN_CNT:
1209 result = SmapDriverData.RuntimeStats.RxFrameBadAlignmentCount;
1210 break;
1211 case NETMAN_NETIF_IOCTL_ETH_GET_TX_ELOSSCR_CNT:
1212 result = SmapDriverData.RuntimeStats.TxFrameLOSSCRCount;
1213 break;
1214 case NETMAN_NETIF_IOCTL_ETH_GET_TX_EEDEFER_CNT:
1215 result = SmapDriverData.RuntimeStats.TxFrameEDEFERCount;
1216 break;
1217 case NETMAN_NETIF_IOCTL_ETH_GET_TX_ECOLL_CNT:
1218 result = SmapDriverData.RuntimeStats.TxFrameCollisionCount;
1219 break;
1220 case NETMAN_NETIF_IOCTL_ETH_GET_TX_EUNDERRUN_CNT:
1221 result = SmapDriverData.RuntimeStats.TxFrameUnderrunCount;
1222 break;
1224 result = SMAPSetLinkMode(*(int *)args);
1225 break;
1226 case NETMAN_NETIF_IOCTL_ETH_GET_STATUS:
1227 ((struct NetManEthStatus *)output)->LinkMode = SMAPGetLinkMode();
1228 ((struct NetManEthStatus *)output)->LinkStatus = SMAPGetLinkStatus();
1229 memcpy(&(((struct NetManEthStatus *)output)->stats), &(SmapDriverData.RuntimeStats), sizeof(SmapDriverData.RuntimeStats));
1230 result = 0;
1231 break;
1232 default:
1233 result = -1;
1234 }
1235#endif
1236
1237#if USE_GP_REGISTER
1238 SetGP(OldGP);
1239#endif
1240
1241 return result;
1242}
1243#endif
1244
1245void SMAPOutputDebugInformation(void)
1246{
1247#ifdef SMAP_ENABLE_DEBUG_INFORMATION
1248 USE_SMAP_EMAC3_REGS;
1249 USE_SMAP_REGS;
1250 USE_SMAP_RX_BD;
1251 int i;
1252 char bdidx;
1253
1254 DEBUG_PRINTF("SMAP_R_RXFIFO_CTRL: 0x%x\n", SMAP_REG8(SMAP_R_RXFIFO_CTRL));
1255 DEBUG_PRINTF("SMAP_R_RXFIFO_RD_PTR: 0x%x\n", SMAP_REG16(SMAP_R_RXFIFO_RD_PTR));
1256 DEBUG_PRINTF("SMAP_R_RXFIFO_SIZE: %d\n", SMAP_REG16(SMAP_R_RXFIFO_SIZE));
1257 DEBUG_PRINTF("SMAP_R_RXFIFO_FRAME_CNT: %d\n", SMAP_REG8(SMAP_R_RXFIFO_FRAME_CNT));
1258 DEBUG_PRINTF("SMAP_R_RXFIFO_FRAME_DEC: %d\n", SMAP_REG8(SMAP_R_RXFIFO_FRAME_DEC));
1259 DEBUG_PRINTF("SMAP_R_EMAC3_RxMODE: 0x%x\n", (unsigned int)SMAP_EMAC3_GET32(SMAP_R_EMAC3_RxMODE));
1260 DEBUG_PRINTF("SMAP_R_EMAC3_INTR_STAT: 0x%x\n", (unsigned int)SMAP_EMAC3_GET32(SMAP_R_EMAC3_INTR_STAT));
1261 DEBUG_PRINTF("SMAP_R_EMAC3_INTR_ENABLE: 0x%x\n", (unsigned int)SMAP_EMAC3_GET32(SMAP_R_EMAC3_INTR_ENABLE));
1262 bdidx = SmapDriverData.RxBDIndex % SMAP_BD_MAX_ENTRY;
1263 for (i = 0; i < SMAP_BD_MAX_ENTRY; i += 1) {
1264 if (rx_bd[i].ctrl_stat != SMAP_BD_RX_EMPTY ||
1265 rx_bd[i].reserved != 0 ||
1266 rx_bd[i].length != 0 ||
1267 rx_bd[i].pointer != 0 ||
1268 i == bdidx) {
1269 if (i == bdidx)
1270 DEBUG_PRINTF(" - 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);
1271 else
1272 DEBUG_PRINTF(" - 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);
1273 }
1274 }
1275
1276 DEBUG_PRINTF("RxDroppedFrameCount: %d\n", (int)SmapDriverData.RuntimeStats.RxDroppedFrameCount);
1277 DEBUG_PRINTF("RxErrorCount: %d\n", (int)SmapDriverData.RuntimeStats.RxErrorCount);
1278 DEBUG_PRINTF("RxFrameOverrunCount: %d\n", SmapDriverData.RuntimeStats.RxFrameOverrunCount);
1279 DEBUG_PRINTF("RxFrameBadLengthCount: %d\n", SmapDriverData.RuntimeStats.RxFrameBadLengthCount);
1280 DEBUG_PRINTF("RxFrameBadFCSCount: %d\n", SmapDriverData.RuntimeStats.RxFrameBadFCSCount);
1281 DEBUG_PRINTF("RxFrameBadAlignmentCount: %d\n", SmapDriverData.RuntimeStats.RxFrameBadAlignmentCount);
1282 DEBUG_PRINTF("TxDroppedFrameCount: %d\n", (int)SmapDriverData.RuntimeStats.TxDroppedFrameCount);
1283 DEBUG_PRINTF("TxErrorCount: %d\n", (int)SmapDriverData.RuntimeStats.TxErrorCount);
1284 DEBUG_PRINTF("TxFrameLOSSCRCount: %d\n", SmapDriverData.RuntimeStats.TxFrameLOSSCRCount);
1285 DEBUG_PRINTF("TxFrameEDEFERCount: %d\n", SmapDriverData.RuntimeStats.TxFrameEDEFERCount);
1286 DEBUG_PRINTF("TxFrameCollisionCount: %d\n", SmapDriverData.RuntimeStats.TxFrameCollisionCount);
1287 DEBUG_PRINTF("TxFrameUnderrunCount: %d\n", SmapDriverData.RuntimeStats.TxFrameUnderrunCount);
1288 DEBUG_PRINTF("RxAllocFail: %d\n", SmapDriverData.RuntimeStats.RxAllocFail);
1289#endif
1290}
1291
1292#ifdef BUILDING_SMAP_MODULAR
1293int SMapRegisterHook(const SmapModularHookTable_t *hooktbl, int priority)
1294{
1295 // Only 0 priority is supported at this time
1296 if (priority != 0) {
1297 return 1;
1298 }
1299 // Check version of hook table
1300 if (hooktbl != NULL) {
1301 if (hooktbl->Version != 1) {
1302 return 1;
1303 }
1304 }
1305 SmapDriverData.HookTable[priority] = hooktbl;
1306 return 0;
1307}
1308
1310 .Version = 1,
1311 .GetMACAddress = &SMAPGetMACAddress,
1312 .Xmit = &SMAPXmit,
1313 .OutputDebugInformation = &SMAPOutputDebugInformation,
1314 .RegisterHook = &SMapRegisterHook,
1315 .RxBDIndexPtr = &(SmapDriverData.RxBDIndex),
1316 .RuntimeStatsPtr = (SmapModularRuntimeStats_t *)&(SmapDriverData.RuntimeStats),
1317};
1318
1319const SmapModularExportTable_t *SmapModularGetExportTable(void)
1320{
1321 return &SmapModularExportTable;
1322}
1323#endif
1324
1325static inline int SetupNetDev(void)
1326{
1327 int result;
1328 iop_event_t EventFlagData;
1329 iop_thread_t ThreadData;
1330#ifdef BUILDING_SMAP_NETDEV
1331 u32 mac_address_lo, mac_address_hi;
1332 // cppcheck-suppress constVariablePointer
1333 volatile u8 *emac3_regbase;
1334#endif
1335#ifdef BUILDING_SMAP_NETMAN
1336 static struct NetManNetIF device = {
1337 "SMAP",
1338 0,
1339 0,
1340 &SMAPStart,
1341 &SMAPStop,
1342 &SMAPXmit,
1343 &SMAPIoctl,
1344 0,
1345 };
1346#endif
1347
1348#ifdef BUILDING_SMAP_NETDEV
1349 emac3_regbase = SmapDriverData.emac3_regbase;
1350
1351 SmapDriverData.m_devops.module_name = "smap";
1352 SmapDriverData.m_devops.vendor_name = "SCE";
1353 SmapDriverData.m_devops.device_name = "Ethernet (Network Adaptor)";
1354 SmapDriverData.m_devops.bus_type = sceInetBus_NIC;
1355 SmapDriverData.m_devops.prot_ver = sceInetDevProtVer;
1356 SmapDriverData.m_devops.flags = sceInetDevF_ARP | sceInetDevF_Multicast | sceInetDevF_NIC;
1357 SmapDriverData.m_devops.start = &SMAPStart;
1358 SmapDriverData.m_devops.stop = &SMAPStop;
1359 SmapDriverData.m_devops.xmit = &SMAPXmit_NetDev;
1360 SmapDriverData.m_devops.impl_ver = 0;
1361 SmapDriverData.m_devops.priv = &SmapDriverData;
1362 SmapDriverData.m_devops.control = &SMAPIoctl;
1363 SmapDriverData.m_devops.mtu = 1500;
1364
1365 mac_address_hi = SMAP_EMAC3_GET32(SMAP_R_EMAC3_ADDR_HI);
1366 mac_address_lo = SMAP_EMAC3_GET32(SMAP_R_EMAC3_ADDR_LO);
1367
1368 SmapDriverData.m_devops.hw_addr[0] = mac_address_hi >> 8;
1369 SmapDriverData.m_devops.hw_addr[1] = mac_address_hi;
1370 SmapDriverData.m_devops.hw_addr[2] = mac_address_lo >> 24;
1371 SmapDriverData.m_devops.hw_addr[3] = mac_address_lo >> 16;
1372 SmapDriverData.m_devops.hw_addr[4] = mac_address_lo >> 8;
1373 SmapDriverData.m_devops.hw_addr[5] = mac_address_lo;
1374#endif
1375
1376 EventFlagData.attr = 0;
1377 EventFlagData.option = 0;
1378 EventFlagData.bits = 0;
1379
1380 if ((result = SmapDriverData.Dev9IntrEventFlag = CreateEventFlag(&EventFlagData)) < 0) {
1381 DEBUG_PRINTF("CreateEventFlag -> %d\n", result);
1382 return -6;
1383 }
1384
1385 ThreadData.attr = TH_C;
1386 ThreadData.thread = (void *)&IntrHandlerThread;
1387 ThreadData.option = 0;
1388 ThreadData.priority = ThreadPriority;
1389 ThreadData.stacksize = ThreadStackSize;
1390 if ((result = SmapDriverData.IntrHandlerThreadID = CreateThread(&ThreadData)) < 0) {
1391 DEBUG_PRINTF("CreateThread -> %d\n", result);
1392 DeleteEventFlag(SmapDriverData.Dev9IntrEventFlag);
1393 return result;
1394 }
1395
1396 if ((result = StartThread(SmapDriverData.IntrHandlerThreadID, &SmapDriverData)) < 0) {
1397 sceInetPrintf("smap: StartThread -> %d\n", result);
1398 DeleteThread(SmapDriverData.IntrHandlerThreadID);
1399 DeleteEventFlag(SmapDriverData.Dev9IntrEventFlag);
1400 return result;
1401 }
1402
1403#ifdef BUILDING_SMAP_NETMAN
1404 if ((SmapDriverData.NetIFID = NetManRegisterNetIF(&device)) < 0) {
1405 sceInetPrintf("smap: NetManRegisterNetIF -> %d\n", result);
1406 TerminateThread(SmapDriverData.IntrHandlerThreadID);
1407 DeleteThread(SmapDriverData.IntrHandlerThreadID);
1408 DeleteEventFlag(SmapDriverData.Dev9IntrEventFlag);
1409 return -6;
1410 }
1411#endif
1412
1413#ifdef BUILDING_SMAP_NETDEV
1414 if ((result = sceInetRegisterNetDevice(&SmapDriverData.m_devops)) < 0) {
1415 sceInetPrintf("smap: sceInetRegisterNetDevice -> %d\n", result);
1416 TerminateThread(SmapDriverData.IntrHandlerThreadID);
1417 DeleteThread(SmapDriverData.IntrHandlerThreadID);
1418 DeleteEventFlag(SmapDriverData.Dev9IntrEventFlag);
1419 return -6;
1420 }
1421#endif
1422
1423 return 0;
1424}
1425
1426static int ParseSmapConfiguration(const char *cmd, unsigned int *configuration)
1427{
1428 const char *CmdStart, *DigitStart;
1429 unsigned int result, base, character, value;
1430
1431 DigitStart = CmdStart = cmd;
1432 base = 10;
1433
1434 if (CmdStart[0] == '0') {
1435 if (CmdStart[1] != '\0') {
1436 if (CmdStart[1] == 'x') {
1437 DigitStart += 2;
1438 base = 16;
1439 } else {
1440 DigitStart++;
1441 }
1442 }
1443 }
1444 if (DigitStart[0] == '\0') {
1445 goto fail_end;
1446 }
1447
1448 result = 0;
1449 character = DigitStart[0];
1450 do {
1451 if (character - '0' < 10) {
1452 value = character - '0';
1453 } else if (character - 'a' < 6) {
1454 value = character - 'a' - 0x57;
1455 } else
1456 goto fail_end;
1457
1458 if (value >= base)
1459 goto fail_end;
1460
1461 result = result * base + value;
1462 } while ((character = *(++DigitStart)) != '\0');
1463 *configuration = result;
1464
1465 return 0;
1466fail_end:
1467 sceInetPrintf("smap: %s: %s - invalid digit\n", "scan_number", CmdStart);
1468 return -1;
1469}
1470
1471int smap_init(int argc, char *argv[])
1472{
1473 int result, i;
1474 const char *CmdString;
1475 u16 eeprom_data[4], checksum16;
1476 u32 mac_address;
1477 USE_SPD_REGS;
1478 USE_SMAP_REGS;
1479 USE_SMAP_EMAC3_REGS;
1480 USE_SMAP_TX_BD;
1481 USE_SMAP_RX_BD;
1482
1483 checksum16 = 0;
1484#if defined(BUILDING_SMAP_NETMAN) || defined(BUILDING_SMAP_NETDEV)
1485 argc--;
1486 argv++;
1487#endif
1488 SmapDriverData.LinkStatus = -1;
1489 while (argc > 0) {
1490 if (strcmp("-help", *argv) == 0) {
1491 return DisplayHelpMessage();
1492 } else if (strcmp("-version", *argv) == 0) {
1493 return DisplayBanner();
1494 } else if (strcmp("-verbose", *argv) == 0) {
1495 EnableVerboseOutput = 1;
1496 } else if (strcmp("-auto", *argv) == 0) {
1497 EnableAutoNegotiation = 1;
1498 } else if (strcmp("-no_auto", *argv) == 0) {
1499 EnableAutoNegotiation = 0;
1500 } else if (strcmp("-strap", *argv) == 0) {
1501 EnablePinStrapConfig = 1;
1502 } else if (strcmp("-no_strap", *argv) == 0) {
1503 EnablePinStrapConfig = 0;
1504 } else if (strncmp("thpri=", *argv, 6) == 0) {
1505 CmdString = &(*argv)[6];
1506 if (isdigit(CmdString[0])) {
1507 ThreadPriority = strtoul(&(*argv)[6], NULL, 10);
1508 if (ThreadPriority - 9 >= 0x73) {
1509 return DisplayHelpMessage();
1510 }
1511
1512 if ((*argv)[6] != '\0') {
1513 while (isdigit(*CmdString)) {
1514 CmdString++;
1515 }
1516 if (*CmdString != '\0')
1517 return DisplayHelpMessage();
1518 }
1519 } else
1520 return DisplayHelpMessage();
1521 } else if (strncmp("thstack=", *argv, 8) == 0) {
1522 CmdString = &(*argv)[8];
1523 if (isdigit(CmdString[0])) {
1524 ThreadStackSize = strtoul(&(*argv)[8], NULL, 10);
1525 if ((*argv)[8] != '\0') {
1526 while (isdigit(*CmdString)) {
1527 CmdString++;
1528 }
1529 }
1530
1531 if (strcmp(CmdString, "KB") == 0)
1532 ThreadStackSize <<= 10;
1533 } else
1534 return DisplayHelpMessage();
1535 } else {
1536 if (ParseSmapConfiguration(*argv, &SmapConfiguration) != 0)
1537 return DisplayHelpMessage();
1538 }
1539
1540 argc--;
1541 argv++;
1542 }
1543
1544 if (argc != 0)
1545 return DisplayHelpMessage();
1546
1547 SmapDriverData.smap_regbase = smap_regbase;
1548 SmapDriverData.emac3_regbase = emac3_regbase;
1549 if ((SPD_REG16(SPD_R_REV_3) & SPD_CAPS_SMAP) == 0)
1550 return -1;
1551 if (SPD_REG16(SPD_R_REV_1) < 0x11)
1552 return -6; // Minimum: revision 17, ES2.
1553
1554 SpdIntrDisable(DEV9_SMAP_ALL_INTR_MASK);
1555
1556 /* Reset FIFOs. */
1557 SMAP_REG8(SMAP_R_TXFIFO_CTRL) = SMAP_TXFIFO_RESET;
1558 for (i = 9; SMAP_REG8(SMAP_R_TXFIFO_CTRL) & SMAP_TXFIFO_RESET; i--) {
1559 if (i <= 0)
1560 return -2;
1561 DelayThread(1000);
1562 }
1563
1564 SMAP_REG8(SMAP_R_RXFIFO_CTRL) = SMAP_RXFIFO_RESET;
1565 for (i = 9; SMAP_REG8(SMAP_R_RXFIFO_CTRL) & SMAP_RXFIFO_RESET; i--) {
1566 if (i <= 0)
1567 return -3;
1568 DelayThread(1000);
1569 }
1570
1571 SMAP_EMAC3_SET32(SMAP_R_EMAC3_MODE0, SMAP_E3_SOFT_RESET);
1572 for (i = 9; SMAP_EMAC3_GET32(SMAP_R_EMAC3_MODE0) & SMAP_E3_SOFT_RESET; i--) {
1573 if (i <= 0)
1574 return -4;
1575 DelayThread(1000);
1576 }
1577
1578 SMAP_REG8(SMAP_R_BD_MODE) = 0;
1579 for (i = 0; i < SMAP_BD_MAX_ENTRY; i++) {
1580 tx_bd[i].ctrl_stat = 0;
1581 tx_bd[i].reserved = 0;
1582 tx_bd[i].length = 0;
1583 tx_bd[i].pointer = 0;
1584 }
1585
1586 for (i = 0; i < SMAP_BD_MAX_ENTRY; i++) {
1587 rx_bd[i].ctrl_stat = SMAP_BD_RX_EMPTY;
1588 rx_bd[i].reserved = 0;
1589 rx_bd[i].length = 0;
1590 rx_bd[i].pointer = 0;
1591 }
1592
1593 SMAP_REG16(SMAP_R_INTR_CLR) = DEV9_SMAP_ALL_INTR_MASK;
1594
1595 /* Retrieve the MAC address and verify it's integrity. */
1596 bzero(eeprom_data, 8);
1597 if ((result = SpdGetEthernetID(eeprom_data)) < 0) {
1598 return (result == -1 ? -7 : -4);
1599 }
1600
1601 for (i = 0; i < 3; i++)
1602 checksum16 += eeprom_data[i];
1603 if (eeprom_data[0] == 0 && eeprom_data[1] == 0 && eeprom_data[2] == 0) {
1604 return -5;
1605 }
1606 if (checksum16 != eeprom_data[3])
1607 return -5;
1608
1609 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);
1610 // Tx FIFO request priority. Low: 7*8=56, urgent: 15*8=120.
1611 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);
1612 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);
1613 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);
1614 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);
1615
1616 mac_address = (u16)(eeprom_data[0] >> 8 | eeprom_data[0] << 8);
1617 SMAP_EMAC3_SET32(SMAP_R_EMAC3_ADDR_HI, mac_address);
1618
1619 mac_address = ((u16)(eeprom_data[1] >> 8 | eeprom_data[1] << 8) << 16) | (u16)(eeprom_data[2] >> 8 | eeprom_data[2] << 8);
1620 SMAP_EMAC3_SET32(SMAP_R_EMAC3_ADDR_LO, mac_address);
1621
1622 SMAP_EMAC3_SET32(SMAP_R_EMAC3_PAUSE_TIMER, 0xFFFF);
1623 SMAP_EMAC3_SET32(SMAP_R_EMAC3_GROUP_HASH1, 0);
1624 SMAP_EMAC3_SET32(SMAP_R_EMAC3_GROUP_HASH2, 0);
1625 SMAP_EMAC3_SET32(SMAP_R_EMAC3_GROUP_HASH3, 0);
1626 SMAP_EMAC3_SET32(SMAP_R_EMAC3_GROUP_HASH4, 0);
1627
1628 SMAP_EMAC3_SET32(SMAP_R_EMAC3_INTER_FRAME_GAP, 4);
1629 // Tx threshold, (12+1)*64=832.
1630 SMAP_EMAC3_SET32(SMAP_R_EMAC3_TX_THRESHOLD, (12 & SMAP_E3_TX_THRESHLD_MSK) << SMAP_E3_TX_THRESHLD_BITSFT);
1631 // Rx watermark, low: 16*8=128, high: 128*8=1024.
1632 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);
1633
1634 // Register the interrupt handlers for all SMAP events.
1635 for (i = 2; i < 7; i++)
1636 SpdRegisterIntrHandler(i, &Dev9IntrCb);
1637
1638 dev9RegisterPreDmaCb(1, &Dev9PreDmaCbHandler);
1639 dev9RegisterPostDmaCb(1, &Dev9PostDmaCbHandler);
1640
1641 return SetupNetDev();
1642}
1643
1644#ifdef BUILDING_SMAP_NETDEV
1645int smap_deinit(void)
1646{
1647 int i;
1648 // cppcheck-suppress constVariablePointer
1649 volatile u8 *emac3_regbase;
1650
1651 if ((SmapDriverData.SmapDriverStarting || SmapDriverData.SmapIsInitialized) && !SmapDriverData.NetDevStopFlag) {
1652 sceInetPrintf("smap: can't unload (busy)\n");
1653 return 2;
1654 }
1655
1656 emac3_regbase = SmapDriverData.emac3_regbase;
1657
1658 sceInetUnregisterNetDevice(&SmapDriverData.m_devops);
1659 TerminateThread(SmapDriverData.IntrHandlerThreadID);
1660 DeleteThread(SmapDriverData.IntrHandlerThreadID);
1661 DeleteEventFlag(SmapDriverData.Dev9IntrEventFlag);
1662 if (SmapDriverData.packetToSend)
1663 sceInetFreePkt(&SmapDriverData.m_devops, (sceInetPkt_t *)SmapDriverData.packetToSend);
1664 if (SmapDriverData.EnableLinkCheckTimer)
1665 CancelAlarm((unsigned int (*)(void *))LinkCheckTimerCB, &SmapDriverData);
1666 dev9RegisterPreDmaCb(1, NULL);
1667 dev9RegisterPostDmaCb(1, NULL);
1668 for (i = 2; i < 7; i++) {
1669 dev9RegisterIntrCb(i, NULL);
1670 }
1671 dev9IntrDisable(DEV9_SMAP_INTR_MASK2);
1672 SMAP_EMAC3_SET32(SMAP_R_EMAC3_MODE0, 0);
1673 return 1;
1674}
1675#endif
1676
1677int SMAPGetMACAddress(u8 *buffer)
1678{
1679 u32 mac_address_lo, mac_address_hi;
1680 // cppcheck-suppress constVariablePointer
1681 volatile u8 *emac3_regbase;
1682 int OldState;
1683
1684 emac3_regbase = SmapDriverData.emac3_regbase;
1685
1686 CpuSuspendIntr(&OldState);
1687
1688 mac_address_hi = SMAP_EMAC3_GET32(SMAP_R_EMAC3_ADDR_HI);
1689 mac_address_lo = SMAP_EMAC3_GET32(SMAP_R_EMAC3_ADDR_LO);
1690
1691 CpuResumeIntr(OldState);
1692
1693 buffer[0] = mac_address_hi >> 8;
1694 buffer[1] = mac_address_hi;
1695 buffer[2] = mac_address_lo >> 24;
1696 buffer[3] = mac_address_lo >> 16;
1697 buffer[4] = mac_address_lo >> 8;
1698 buffer[5] = mac_address_lo;
1699
1700 return 0;
1701}
#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
Definition tcpip.h:230