PS2SDK
PS2 Homebrew Libraries
Loading...
Searching...
No Matches
iLink_crom.c
1/* iLink_crom.c
2 * Purpose: Contains the functions related to configuration ROM access/management.
3 * !!!NOTE!!! All data accessible by external IEEE1394 nodes are usually in Big-Endian!!!
4 *
5 * Last Updated: 2011/11/21
6 * Programmer: SP193
7 */
8
9#include <stdio.h>
10#include <sysclib.h>
11#include <sysmem.h>
12#include <thbase.h>
13
14#include "iLinkman.h"
15#include "iLink_CROM.h"
16#include "iLink_internal.h"
17
18extern u64 ConsoleGUID;
19extern char ConsoleModelName[32];
20extern unsigned short int LocalNodeID;
21extern int nNodes;
22
23static void *ExtraCROMUnits[16];
24static unsigned int ExtraCROMUnitsSize[16];
25static unsigned int nExtraCROMUnits;
26unsigned int *ConfigurationROM;
27unsigned int ConfigurationROMSize;
28static unsigned char LinkSpeed, CycleClkAcc, Max_Rec;
29
30extern int NodeCapabilities;
31extern unsigned int NodeData[63];
32
33/* Function prototypes. */
34static void ieee1394Swab32(void *dest, void *src, unsigned int nQuads);
35static void BuildConfigurationROM(void);
36
37static void ieee1394Swab32(void *dest, void *src, unsigned int nQuads)
38{
39 register unsigned int i;
40
41 for (i = 0; i < nQuads; i++)
42 ((unsigned int *)dest)[i] = BSWAP32(((unsigned int *)src)[i]);
43}
44
45unsigned short int iLinkCalculateCRC16(void *data, unsigned int nQuads)
46{
47 int i, lShift;
48 unsigned int lSum;
49 unsigned short int lCRC = 0;
50
51 for (i = 0; (unsigned int)i < nQuads; ++i) {
52 unsigned int lData;
53
54 lData = ((unsigned int *)data)[i];
55 for (lShift = 28; lShift >= 0; lShift -= 4) {
56 lSum = ((lCRC >> 12) ^ (lData >> lShift)) & 15;
57 lCRC = (lCRC << 4) ^ (lSum << 12) ^ (lSum << 5) ^ lSum;
58 } /* end for */
59 lCRC &= 0xFFFF;
60 } /* end for */
61
62 return lCRC;
63}
64
65int iLinkAddCROMUnit(unsigned int *data, unsigned int nQuads)
66{
67 unsigned int i, CROM_EntrySizeInBytes;
68 int result;
69
70 result = -1002;
71 for (i = 0; i < 16; i++) {
72 if (ExtraCROMUnits[i] == NULL) {
73 CROM_EntrySizeInBytes = nQuads * 4;
74 if ((ExtraCROMUnits[i] = malloc(CROM_EntrySizeInBytes)) != NULL) {
75 ExtraCROMUnitsSize[i] = CROM_EntrySizeInBytes;
76
77 ieee1394Swab32(ExtraCROMUnits[i], data, nQuads);
78 nExtraCROMUnits++;
79
80 BuildConfigurationROM();
81
82 result = i;
83 }
84
85 break;
86 }
87 }
88
89 return result;
90}
91
92void iLinkDeleteCROMUnit(unsigned int id)
93{
94 free(ExtraCROMUnits[id]);
95 ExtraCROMUnits[id] = NULL;
96 BuildConfigurationROM();
97
98 nExtraCROMUnits--;
99}
100
101int iLinkGetNodeCapabilities(unsigned short NodeID)
102{
103 int result;
104 unsigned int data;
105
106 if (NodeID == LocalNodeID)
107 return NodeCapabilities;
108
109 result = iLinkReadCROM(NodeID, 8, 1, &data);
110 result = (result < 0) ? (-1) : (int)(data >> 27);
111
112 return result;
113}
114
115int iLinkGetNodeMaxSpeed(unsigned short int NodeID)
116{
117 unsigned int i;
118 int result;
119
120 result = -1;
121 for (i = 0; i < (unsigned int)nNodes; i++) {
122 if (SELF_ID_NODEID(NodeData[i]) == (NodeID & 0x3F)) {
123 result = SELF_ID_SPEED(NodeData[i]);
124 break;
125 }
126 }
127
128 return result;
129}
130
131static inline int ParseUnitCROM(unsigned short NodeID, unsigned int *UnitSpec, unsigned int *UnitSW_Version)
132{
133 unsigned int data, UnitDirectoryOffset, CROMOffset;
134 int result, i;
135 unsigned short int DirectoryLength;
136
137 CROMOffset = 0x14 >> 2;
138 UnitDirectoryOffset = 0;
139
140 /* Search the root directory for the unit directory key. */
141 if ((result = iLinkReadCROM(NodeID, CROMOffset, 1, &data)) < 0)
142 return (result);
143 DirectoryLength = (unsigned short int)(data >> 16);
144
145 CROMOffset++;
146
147 for (i = 0; i < DirectoryLength; i++) {
148 if ((result = iLinkReadCROM(NodeID, CROMOffset, 1, &data)) < 0)
149 return (result);
150
151 if ((data >> 24) == IEEE1394_CROM_UNIT_DIRECTORY) {
152 UnitDirectoryOffset = data & 0x00FFFFFF;
153 break;
154 }
155
156 CROMOffset++;
157 }
158 if (i == DirectoryLength)
159 return -1;
160
161 CROMOffset += UnitDirectoryOffset;
162 DEBUG_PRINTF("CROMOffset=0x%08x.\n", CROMOffset);
163
164 /* Search the unit directory for the unit spec and unit SW keys. */
165 if ((result = iLinkReadCROM(NodeID, CROMOffset, 1, &data)) < 0)
166 return result;
167 DirectoryLength = (unsigned short int)(data >> 16);
168
169 CROMOffset++;
170
171 for (i = 0; i < DirectoryLength; i++) {
172 if ((result = iLinkReadCROM(NodeID, CROMOffset, 1, &data)) < 0)
173 return (result);
174
175 CROMOffset++;
176
177 if ((data >> 24) == IEEE1394_CROM_UNIT_SPEC) {
178 *UnitSpec = data & 0x00FFFFFF;
179 } else if ((data >> 24) == IEEE1394_CROM_UNIT_SW_VERSION) {
180 *UnitSW_Version = data & 0x00FFFFFF;
181 }
182
183 if ((*UnitSpec != 0) && (*UnitSW_Version != 0))
184 return 1;
185 }
186
187 return -1;
188}
189
190int iLinkFindUnit(int UnitInList, unsigned int UnitSpec, unsigned int UnitSW_Version)
191{
192 int result;
193 unsigned int CurrentUnitSW_Version, CurrentUnitSpec;
194
195 DEBUG_PRINTF("iLinkFindUnit() %d UnitSpec: 0x%08x; UnitSW Version: 0x%08x.\n", UnitInList, UnitSpec, UnitSW_Version);
196
197 result = -1;
198 if (UnitInList < nNodes) {
199 unsigned short int NodeID;
200
201 NodeID = (unsigned short int)SELF_ID_NODEID(NodeData[UnitInList]) | (LocalNodeID & 0xFFC0);
202 CurrentUnitSW_Version = CurrentUnitSpec = 0;
203
204 if ((result = ParseUnitCROM(NodeID, &CurrentUnitSpec, &CurrentUnitSW_Version)) >= 0) {
205 result = ((CurrentUnitSW_Version == UnitSW_Version) && (CurrentUnitSpec == UnitSpec)) ? NodeID : (-1);
206 }
207 }
208
209 return result;
210}
211
212int iLinkReadCROM(unsigned short int NodeID, unsigned int Offset, unsigned int nQuads, unsigned int *buffer)
213{
214 unsigned int i;
215 int result, trContext;
216
217 DEBUG_PRINTF("Reading CROM of node 0x%04x, offset: %u, nquads: %u.\n", NodeID, Offset, nQuads);
218
219 result = -1;
220 if ((trContext = iLinkTrAlloc(NodeID, S100)) < 0)
221 return trContext;
222
223 for (i = 0; i < nQuads; i++) {
224 int retries;
225
226 retries = 10;
227 do {
228 if ((result = iLinkTrRead(trContext, 0x0000FFFF, 0xF0000400 + (Offset << 2), buffer, 4)) >= 0) {
229 *buffer = BSWAP32(*buffer);
230 buffer++;
231 Offset++;
232 } else {
233 DelayThread(100000);
234 retries--;
235 }
236 } while ((result < 0) && (retries > 0));
237 if (retries == 0)
238 break;
239 }
240
241 iLinkTrFree(trContext);
242
243 return result;
244}
245
246void InitializeConfigurationROM(void)
247{
248 register unsigned int i;
249
250 for (i = 0; i < 16; i++)
251 ExtraCROMUnits[i] = NULL;
252 nExtraCROMUnits = 0;
253 ConfigurationROM = NULL;
254
255 LinkSpeed = 4;
256 CycleClkAcc = ~0;
257 Max_Rec = 10;
258
259 BuildConfigurationROM();
260}
261
262static void BuildConfigurationROM(void)
263{
264 unsigned char *CROM_Buffer;
265 unsigned int CROMSize, CurrentOffset;
266
267 struct BusInformationBlock *BusInfoBlk;
268 struct Root_Directory *RootDirectory;
269 struct Module_Vendor_Id *ModuleVendorID;
271 struct Module_Vendor_ID_Texual_Descriptor *ModuleTexualDescriptor;
272 struct Node_Unique_Id *NodeUniqueID;
273 struct ModelID_Textual_Descriptor *ModelName;
274
275 unsigned int i, TotalExtraCROMUnitSize;
276 unsigned short int TotalRootDirectorySizeInQuads;
277
278 TotalExtraCROMUnitSize = 0;
279 for (i = 0; i < 16; i++)
280 if (ExtraCROMUnits[i] != NULL)
281 TotalExtraCROMUnitSize += ExtraCROMUnitsSize[i];
282
283 TotalRootDirectorySizeInQuads = (sizeof(struct Root_Directory) + TotalExtraCROMUnitSize) / 4;
284
285 CROMSize = sizeof(struct BusInformationBlockHeader) + sizeof(struct BusInformationBlock);
286 CROMSize = CROMSize + sizeof(struct DirectoryHeader) + sizeof(struct Root_Directory) + TotalExtraCROMUnitSize;
287 CROMSize = CROMSize + sizeof(struct DirectoryHeader) + sizeof(struct Module_Vendor_ID_Texual_Descriptor);
288 CROMSize = CROMSize + sizeof(struct DirectoryHeader) + sizeof(struct Module_Vendor_Id);
289 CROMSize = CROMSize + sizeof(struct DirectoryHeader) + sizeof(struct ModelID_Textual_Descriptor);
290 CROMSize = CROMSize + sizeof(struct DirectoryHeader) + sizeof(struct Node_Unique_Id);
291
292 ConfigurationROMSize = CROMSize;
293
294 if ((CROM_Buffer = malloc(CROMSize)) == NULL)
295 return;
296
297 CurrentOffset = sizeof(struct BusInformationBlockHeader) + sizeof(struct BusInformationBlock);
298 /* Fill in the fields in the Root Directory (Exists immediately after the Bus Information block). */
299 DirectoryHeader = (struct DirectoryHeader *)&CROM_Buffer[CurrentOffset];
300 RootDirectory = (struct Root_Directory *)((unsigned char *)DirectoryHeader + sizeof(struct DirectoryHeader));
301 RootDirectory->Module_Vendor_ID_Texual_Descriptor_Offset = (IEEE1394_CROM_VENDOR << 24) | (sizeof(struct DirectoryHeader) * 2 / 4 + TotalRootDirectorySizeInQuads - 2 + sizeof(struct Module_Vendor_Id) / 4); /* Calculate the relative offset (In quadlets!!). */
302 RootDirectory->Node_Capabilities = (IEEE1394_CROM_NODE_CAPS << 24) | 0x0C0083C0;
303 RootDirectory->Node_Unique_ID_Offset = (IEEE1394_CROM_NODE_UID << 24) | (sizeof(struct DirectoryHeader) * 3 / 4 + TotalRootDirectorySizeInQuads - 2 + sizeof(struct Module_Vendor_Id) / 4 + sizeof(struct Module_Vendor_ID_Texual_Descriptor) / 4);
304 RootDirectory->Module_Vendor_ID_Offset = (IEEE1394_CROM_MODULE_VENDOR_ID << 24) | (nExtraCROMUnits + 1);
305
306 ieee1394Swab32(RootDirectory, RootDirectory, sizeof(struct Root_Directory) / 4); /* Convert this block of data to Big-endian data. */
307
308 CurrentOffset = CurrentOffset + sizeof(struct DirectoryHeader) + sizeof(struct Root_Directory);
309
310 for (i = 0; i < 16; i++) {
311 if (ExtraCROMUnits[i] != NULL) {
312 memcpy(&CROM_Buffer[CurrentOffset], ExtraCROMUnits[i], ExtraCROMUnitsSize[i]); /* Append the extra records to the end of the Root Directory. */
313 CurrentOffset += ExtraCROMUnitsSize[i];
314 }
315 }
316
317 DirectoryHeader->Directory_length = TotalRootDirectorySizeInQuads;
318 DirectoryHeader->CRC16 = BSWAP16(iLinkCalculateCRC16(RootDirectory, DirectoryHeader->Directory_length));
319 DirectoryHeader->Directory_length = BSWAP16(DirectoryHeader->Directory_length);
320
321 /* Fill in the fields of the Module Vendor ID record. */
322 ModuleVendorID = (struct Module_Vendor_Id *)&CROM_Buffer[CurrentOffset + sizeof(struct DirectoryHeader)];
323 ModuleVendorID->Textual_Descriptor = (IEEE1394_CROM_MODEL_ID << 24) | ((sizeof(struct DirectoryHeader) * 2 / 4 + sizeof(struct Module_Vendor_ID_Texual_Descriptor) + sizeof(struct Node_Unique_Id)) / 4);
324
325 ieee1394Swab32(ModuleVendorID, ModuleVendorID, sizeof(struct Module_Vendor_Id) / 4); /* Convert this block of data to Big-endian data. */
326
327 DirectoryHeader = (struct DirectoryHeader *)&CROM_Buffer[CurrentOffset];
328 DirectoryHeader->Directory_length = 1;
329 DirectoryHeader->CRC16 = BSWAP16(iLinkCalculateCRC16(ModuleVendorID, DirectoryHeader->Directory_length));
330 DirectoryHeader->Directory_length = BSWAP16(DirectoryHeader->Directory_length);
331
332 CurrentOffset = CurrentOffset + sizeof(struct Module_Vendor_Id) + sizeof(struct DirectoryHeader);
333
334 /* Fill in the fields of the Textual_Descriptor */
335 DirectoryHeader = (struct DirectoryHeader *)&CROM_Buffer[CurrentOffset];
336 ModuleTexualDescriptor = (struct Module_Vendor_ID_Texual_Descriptor *)((unsigned char *)DirectoryHeader + sizeof(struct DirectoryHeader));
337 ModuleTexualDescriptor->Specifier_ID = 0x00000000;
338 ModuleTexualDescriptor->Language_ID = 0x00000000;
339
340 ieee1394Swab32(ModuleTexualDescriptor, ModuleTexualDescriptor, sizeof(struct Module_Vendor_ID_Texual_Descriptor) / 4); /* Convert this block of data to Big-endian data. */
341
342 memcpy(ModuleTexualDescriptor->Vendor_Name, "Sony", 4); /* Don't flop the "Sony" text. */
343
344 DirectoryHeader->Directory_length = 3;
345 DirectoryHeader->CRC16 = BSWAP16(iLinkCalculateCRC16(ModuleTexualDescriptor, DirectoryHeader->Directory_length));
346 DirectoryHeader->Directory_length = BSWAP16(DirectoryHeader->Directory_length);
347
348 CurrentOffset = CurrentOffset + sizeof(struct Module_Vendor_ID_Texual_Descriptor) + sizeof(struct DirectoryHeader);
349
350 /* Fill in the fields in the Node Unique ID section. */
351 DirectoryHeader = (struct DirectoryHeader *)&CROM_Buffer[CurrentOffset];
352 NodeUniqueID = (struct Node_Unique_Id *)((unsigned char *)DirectoryHeader + sizeof(struct DirectoryHeader));
353
354 NodeUniqueID->HardwareID = BSWAP32((ConsoleGUID >> 32));
355 NodeUniqueID->Chip_ID_Low = BSWAP32((ConsoleGUID & 0xFFFFFFFF));
356
357 DirectoryHeader->Directory_length = sizeof(struct Node_Unique_Id) / 4;
358 DirectoryHeader->CRC16 = BSWAP16(iLinkCalculateCRC16(NodeUniqueID, DirectoryHeader->Directory_length));
359 DirectoryHeader->Directory_length = BSWAP16(DirectoryHeader->Directory_length);
360
361 CurrentOffset = CurrentOffset + sizeof(struct DirectoryHeader) + sizeof(struct Node_Unique_Id);
362
363 /* Fill in the fields in the modelname block. */
364 DirectoryHeader = (struct DirectoryHeader *)&CROM_Buffer[CurrentOffset];
365 ModelName = (struct ModelID_Textual_Descriptor *)((unsigned char *)DirectoryHeader + sizeof(struct DirectoryHeader));
366
367 ModelName->Specifier_ID = 0x00000000;
368 ModelName->Language_ID = 0x00000000;
369
370 memcpy(ModelName->Model_Name, ConsoleModelName, sizeof(ModelName->Model_Name));
371
372 DirectoryHeader->Directory_length = sizeof(struct ModelID_Textual_Descriptor) / 4;
373 DirectoryHeader->CRC16 = BSWAP16(iLinkCalculateCRC16(ModelName, DirectoryHeader->Directory_length));
374 DirectoryHeader->Directory_length = BSWAP16(DirectoryHeader->Directory_length);
375
376 CurrentOffset = sizeof(struct BusInformationBlockHeader);
377
378 /* Fill in the fields in the Bus Information Block. */
379 BusInfoBlk = (struct BusInformationBlock *)&CROM_Buffer[CurrentOffset];
380 memcpy(BusInfoBlk->BusName, "1394", 4);
381 BusInfoBlk->capabilities = NodeCapabilities << 3;
382 BusInfoBlk->Cyc_Clk_Acc = CycleClkAcc;
383 BusInfoBlk->Max_Rec = Max_Rec << 4;
384 BusInfoBlk->misc = LinkSpeed;
385 BusInfoBlk->HardwareID = NodeUniqueID->HardwareID;
386 BusInfoBlk->Chip_ID_Low = NodeUniqueID->Chip_ID_Low;
387
388 /* Fill in the fields in the Bus Information Block Header. */
389 ((struct BusInformationBlockHeader *)CROM_Buffer)->Bus_info_length = 4; /* According to the standard. */
390 ((struct BusInformationBlockHeader *)CROM_Buffer)->CRC_length = sizeof(struct BusInformationBlock) / 4;
391 ((struct BusInformationBlockHeader *)CROM_Buffer)->ROM_CRC_value = BSWAP16(iLinkCalculateCRC16(BusInfoBlk, sizeof(struct BusInformationBlock) / 4));
392
393 if (ConfigurationROM != NULL)
394 free(ConfigurationROM);
395 ConfigurationROM = (unsigned int *)CROM_Buffer;
396}