PS2SDK
PS2 Homebrew Libraries
Loading...
Searching...
No Matches
iLink.c
1/* iLink.c
2 * Purpose: Contains the main functions of the iLinkman driver.
3 * It contains functions that are exported for use by other modules, and contains the entry point function.
4 *
5 * Last Updated: 2012/02/29
6 * Programmer: SP193
7 */
8
9#include <dmacman.h>
10#include <errno.h>
11#include <ioman.h>
12#include <intrman.h>
13#include <irx.h>
14#include <loadcore.h>
15#include <stdio.h>
16#include <thbase.h>
17#include <thevent.h>
18#include <thsemap.h>
19#include <sysmem.h>
20#include <sysclib.h>
21
22#include "iLinkman.h"
23#include "iLink_internal.h"
24
25#define MODNAME "iLINK_HW_Manager"
26IRX_ID(MODNAME, 0x00, 0x98);
27
28/* Global variables. */
29extern struct irx_export_table _exp_iLinkman;
30
31struct ILINKMemMap *ILINKRegisterBase = (struct ILINKMemMap *)ILINK_REGISTER_BASE;
32extern struct TransactionContextData TransactionContexts[MAX_CONCURRENT_TRANSACTIONS];
33extern unsigned int *ConfigurationROM;
34void (*CallBackFunction)(int reason, unsigned int offset, unsigned int size);
35
36u64 ConsoleGUID;
37char ConsoleModelName[32];
38
39unsigned short int LocalNodeID;
40
41extern int GenerationNumber;
42extern int nNodes;
43extern int NodeCapabilities;
44
45int IntrEventFlag, UBUFTxSema, UBUFThreadID;
46
47extern unsigned char IsBusRoot;
48
49static iop_event_t EventFlagData = {
50 2, /* evfp.attr=EA_MULTI */
51 0, /* evfp.option */
52 0 /* evfp.bits */
53};
54
55/* SP193: Get the console's BIOS version, and refuse to load if the console is a iLink-free console.
56 Although Sony seems to have included the iLink controller in my SCPH-77006 console, it seems like DMAC #3 is missing from it's usual spot, and rom0:DMACMAN doesn't even know about the change.
57 Doing anything with DMAC #3 resulted in bus errors. Strangely, DMAC #3 can be disabled at the startup of rom0:DMACMAN... I wonder why. Maybe I'm wrong, and DMACMAN doesn't disable the channels of DMAC #3 on my SCPH-77006 at bootup.
58*/
59#ifdef REQ_CHECK_CONSOLE_VERSION
60static inline unsigned int GetBIOSVersion(void)
61{
62 char romver_str[5];
63 int fd;
64
65 fd = open("rom0:ROMVER", O_RDONLY);
66 read(fd, romver_str, 4);
67 close(fd);
68
69 romver_str[4] = '\0';
70 return strtoul(romver_str, NULL, 16);
71}
72#endif
73
74int _start(int argc, char *argv[])
75{
76 int i, result;
77 iop_thread_t ThreadData;
78
79 (void)argc;
80 (void)argv;
81
82 DEBUG_PRINTF("iLink driver version 0.98H\n");
83
84#ifdef REQ_CHECK_CONSOLE_VERSION
85 if (GetBIOSVersion() > 0x160) {
86 printf("Unsupported console detected. Not loading.\n");
87 return MODULE_NO_RESIDENT_END;
88 }
89#endif
90
91 iLinkDisableIntr();
92
93 if ((result = iLinkResetHW()) < 0) {
94 DEBUG_PRINTF("Error occurred while resetting i.Link hardware. Code: %d\n", result);
95 return MODULE_NO_RESIDENT_END;
96 }
97
98 iLinkHWInitialize();
99
100 DEBUG_PRINTF("Initializing Configuration ROM...\n");
101
102 memset(ConsoleModelName, 0, sizeof(ConsoleModelName));
103 ConsoleGUID = 0;
104 GetConsoleIDs(&ConsoleGUID, ConsoleModelName);
105 DEBUG_PRINTF("Console GUID: 0x%08lx %08lx, ModelName: %s.\n", (u32)(ConsoleGUID >> 32), (u32)ConsoleGUID, ConsoleModelName);
106
107 InitializeConfigurationROM();
108
109 CallBackFunction = NULL;
110 IntrEventFlag = CreateEventFlag(&EventFlagData);
111 UBUFTxSema = CreateMutex(IOP_MUTEX_UNLOCKED);
112
113 ThreadData.attr = TH_C;
114 ThreadData.option = 0;
115 ThreadData.thread = &UBUFThread;
116 ThreadData.stacksize = 0x350;
117 ThreadData.priority = 0x60;
118
119 StartThread(UBUFThreadID = CreateThread(&ThreadData), NULL);
120
121 RegisterIntrHandler(IOP_IRQ_ILINK, 1, &iLinkIntrHandler, NULL);
122 EnableIntr(IOP_IRQ_ILINK);
123
124 for (i = 0; i < MAX_CONCURRENT_TRANSACTIONS; i++)
125 TransactionContexts[i].IsConnected = 0;
126
127 DEBUG_PRINTF("Initialization complete.\n");
128
129 return ((RegisterLibraryEntries(&_exp_iLinkman) != 0) ? MODULE_NO_RESIDENT_END : MODULE_RESIDENT_END);
130}
131
132int _exit(int argc, char *argv[])
133{
134 int result;
135
136 (void)argc;
137 (void)argv;
138
139 /* Shutdown the hardware and unregister all registered library exports. */
140 ReleaseLibraryEntries(&_exp_iLinkman);
141 DisableIntr(IOP_IRQ_ILINK, &result);
142 ReleaseIntrHandler(IOP_IRQ_ILINK);
143 TerminateThread(UBUFThreadID);
144 DeleteThread(UBUFThreadID);
145 DeleteSema(UBUFTxSema);
146 DeleteEventFlag(IntrEventFlag);
147 iLinkShutdownHW();
148
149 FreeSysMemory(ConfigurationROM); /* Free the memory allocated for storing the configuration ROM. */
150
151 return MODULE_RESIDENT_END;
152}
153
154int iLinkTrAlloc(unsigned short int NodeID, unsigned char speed)
155{
156 int result;
157
158 if (NodeID != LocalNodeID) {
159 unsigned int i;
160
161 for (i = 0; i < MAX_CONCURRENT_TRANSACTIONS; i++) {
162 if (TransactionContexts[i].IsConnected == 0) {
163 TransactionContexts[i].NodeID = NodeID;
164 TransactionContexts[i].GenerationNumber = GenerationNumber;
165 TransactionContexts[i].IsConnected = 1;
166 iLinkSetNodeTrSpeed(i, speed);
167 break;
168 }
169 }
170
171 result = (i == MAX_CONCURRENT_TRANSACTIONS) ? (unsigned int)(-1002) : i;
172 } else
173 result = -1;
174
175 return result;
176}
177
178void iLinkTrFree(int trContext)
179{
180 TransactionContexts[trContext].IsConnected = 0;
181}
182
183int iLinkTrWrite(int trContext, unsigned short int offset_high, unsigned int offset_low, void *buffer, unsigned int nBytes)
184{
185 return ((nBytes == 4) ? iLinkWriteReq(&TransactionContexts[trContext], offset_high, offset_low, buffer, nBytes) : iLinkWritePHTReq(&TransactionContexts[trContext], offset_high, offset_low, buffer, nBytes));
186}
187
188int iLinkTrRead(int trContext, unsigned short int offset_high, unsigned int offset_low, void *buffer, unsigned int nBytes)
189{
190 return ((nBytes == 4) ? iLinkReadReq(&TransactionContexts[trContext], offset_high, offset_low, buffer, nBytes) : iLinkReadPHTReq(&TransactionContexts[trContext], offset_high, offset_low, buffer, nBytes));
191}
192
193unsigned int iLinkSetNodeCapabilities(unsigned int capabilities)
194{
195 NodeCapabilities = capabilities;
196
197 /* Enable the enabled iLink features. */
198 if (NodeCapabilities & iLink_NODE_CMC)
199 iLinkEnableCMaster();
200
201 InitializeConfigurationROM();
202 return (NodeCapabilities);
203}
204
205int iLinkGetGenerationNumber(void)
206{
207 return (GenerationNumber);
208}
209
210int iLinkGetLocalNodeID(void)
211{
212 return (LocalNodeID);
213}
214
215int iLinkGetNodeCount(void)
216{
217 return (nNodes);
218}
219
220void iLinkEnableSBus(void)
221{
222 iLinkPHY_SetLCTRL(1);
223 iLinkBusEnable();
224 iLinkResetSBus();
225}
226
227void iLinkDisableSBus(void)
228{
229 ILINKRegisterBase->ctrl0 &= ~(iLink_CTRL0_RxEn | iLink_CTRL0_TxEn); /* CTL0: ~(TxEn | RxEn) */
230}
231
232void iLinkResetSBus(void)
233{
234 ClearEventFlag(IntrEventFlag, ~(iLinkEventBusReady | iLinkEventGotSELFIDs));
235
236 DEBUG_PRINTF("-=Reseting bus=-\n");
237
238 iLinkPHYBusReset();
239
240 DEBUG_PRINTF("-=Waiting for the serial bus to be ready=-\n");
241 WaitEventFlag(IntrEventFlag, iLinkEventBusReady | iLinkEventGotSELFIDs, WEF_AND, NULL); /* Wait for the bus to be completely reset. */
242 DEBUG_PRINTF("-=Bus reset and ready=-\n");
243}
244
245void *iLinkSetTrCallbackHandler(void *function)
246{
247 void *cb_function;
248
249 cb_function = CallBackFunction;
250 CallBackFunction = function;
251
252 return cb_function;
253}
254
255static const unsigned char speeds[3] = {
256 0, /* S100 */
257 2, /* S200 */
258 4 /* S400 */
259};
260
261int iLinkGetNodeTrSpeed(int trContext)
262{
263 int CurrentSpeed, i;
264
265 CurrentSpeed = -1;
266 for (i = 0; i < 3; i++) {
267 if (speeds[i] == TransactionContexts[trContext].speed) {
268 CurrentSpeed = i;
269 break;
270 }
271 }
272
273 return CurrentSpeed;
274}
275
276int iLinkSetNodeTrSpeed(int trContext, unsigned char speed)
277{
278 int result;
279
280 result = iLinkGetNodeTrSpeed(trContext);
281
282 /* !!HACK!! Due to a chip bug (?) in the iLink hardware of most consoles, limit the speed to S100 mode whenever the console is the root node
283 (Read the README file for more details on this bug). */
284 if (IsBusRoot)
285 speed = S100;
286
287 /* Assign the specified speed to the specified transaction. Assign the maxium allowed speed if the specified speed is above the maximum value. */
288 TransactionContexts[trContext].speed = (speed > (sizeof(speeds) - 1)) ? speeds[sizeof(speeds) - 1] : speeds[speed];
289
290 return result;
291}
292
293u64 iLinkGetLocalNodeEUI64(void)
294{
295 return ConsoleGUID;
296}
int RegisterIntrHandler(int irq, int mode, int(*handler)(void *), void *arg)
Definition intrman.c:125
int ReleaseIntrHandler(int irq)
Definition intrman.c:167
int DisableIntr(int irq, int *res)
Definition intrman.c:395
int EnableIntr(int irq)
Definition intrman.c:346