PS2SDK
PS2 Homebrew Libraries
Loading...
Searching...
No Matches
sbp2_driver.c
1#include <intrman.h>
2#include <loadcore.h>
3#include <stdio.h>
4#include <sysclib.h>
5#include <sysmem.h>
6#include <thbase.h>
7#include <thevent.h>
8
9#include "iLinkman.h"
10#include "sbp2_disk.h"
11#include "scsi.h"
12#include "usbhdfsd-common.h"
13
14// #define DEBUG //comment out this line when not debugging
15#include "module_debug.h"
16
17#define MAX_DEVICES 5
18static struct SBP2Device SBP2Devices[MAX_DEVICES];
19static u8 *writeBuffer = NULL;
20
21/* Thread creation data. */
22static iop_thread_t threadData = {
23 TH_C, /* attr */
24 0, /* option */
25 NULL, /* thread */
26 0x1000, /* stacksize */
27 0x30 /* priority */
28};
29
30// static unsigned long int iLinkBufferOffset, iLinkTransferSize;
31static int sbp2_event_flag;
32
33static void ieee1394_callback(int reason, unsigned long int offset, unsigned long int size);
34static void iLinkIntrCBHandlingThread(void *arg);
35static int ieee1394_SendManagementORB(int mode, struct SBP2Device *dev);
36static int ieee1394_InitializeFetchAgent(struct SBP2Device *dev);
37static inline int ieee1394_Sync_withTimeout(u32 n500mSecUnits);
38void free(void *buffer);
39void *malloc(int NumBytes);
40
41static volatile union
42{
43 struct sbp2_status status;
44 unsigned char buffer[32]; /* Maximum 32 bytes. */
45} statusFIFO;
46
47static void ieee1394_callback(int reason, unsigned long int offset, unsigned long int size)
48{
49 (void)offset;
50 (void)size;
51
52#if 0
53 iLinkBufferOffset = offset;
54 iLinkTransferSize = size;
55
56 if (reason == iLink_CB_WRITE_REQUEST) {
57 u32 statusFIFO_result;
58
59 // M_DEBUG("Write request: Offset: 0x%08lx; size: 0x%08lx.\n", iLinkBufferOffset, iLinkTransferSize);
60
61 if (iLinkBufferOffset == (u32)&statusFIFO) { /* Check to be sure that we don't signal ieee1394_Sync() too early; Some transactions are transactions involving multiple ORBs. */
62 statusFIFO_result = statusFIFO.status.status;
63 if (RESP_SRC(statusFIFO_result) != 0)
64 SetEventFlag(sbp2_event_flag, WRITE_REQ_INCOMING); /* Signal ieee1394_Sync() only after the last ORB was read. */
65 }
66 } else
67#endif
68 if (reason == iLink_CB_BUS_RESET) {
69 SetEventFlag(sbp2_event_flag, BUS_RESET_COMPLETE);
70 }
71#if 0
72 else {
73 // M_DEBUG("Read request: Offset: 0x%08lx; size: 0x%08lx;\n", iLinkBufferOffset, iLinkTransferSize);
74 }
75#endif
76}
77
78/* Event flag creation data. */
79static iop_event_t evfp = {
80 2, /* evfp.attr=EA_MULTI */
81 0, /* evfp.option */
82 0 /* evfp.bits */
83};
84
85int iLinkIntrCBThreadID;
86static int sbp2_get_max_lun(struct scsi_interface *scsi);
87static int sbp2_queue_cmd(struct scsi_interface *scsi, const unsigned char *cmd, unsigned int cmd_len, unsigned char *data, unsigned int data_len, unsigned int data_wr);
88
89void init_ieee1394DiskDriver(void)
90{
91 int i;
92
93 for (i = 0; i < MAX_DEVICES; i++) {
94 SBP2Devices[i].IsConnected = 0;
95 SBP2Devices[i].nodeID = 0;
96 SBP2Devices[i].trContext = (-1);
97
98 SBP2Devices[i].scsi.priv = &SBP2Devices[i];
99 SBP2Devices[i].scsi.name = "sd";
100 SBP2Devices[i].scsi.devNr = i;
101 SBP2Devices[i].scsi.max_sectors = XFER_BLOCK_SIZE / 512;
102 SBP2Devices[i].scsi.get_max_lun = sbp2_get_max_lun;
103 SBP2Devices[i].scsi.queue_cmd = sbp2_queue_cmd;
104 }
105
106 writeBuffer = malloc(XFER_BLOCK_SIZE);
107
108 sbp2_event_flag = CreateEventFlag(&evfp);
109
110 M_DEBUG("Starting threads..\n");
111
112 threadData.thread = &iLinkIntrCBHandlingThread;
113 iLinkIntrCBThreadID = CreateThread(&threadData);
114 StartThread(iLinkIntrCBThreadID, NULL);
115
116 iLinkSetTrCallbackHandler(&ieee1394_callback);
117
118 M_DEBUG("Threads created and started.\n");
119
120 iLinkEnableSBus();
121}
122
123static int initConfigureSBP2Device(struct SBP2Device *dev)
124{
125 unsigned char retries;
126
127 // Try 5 x 200ms to login (same as Linux: drivers/firewire/sbp2.c)
128 retries = 5;
129 while (1) {
130 if (ieee1394_SendManagementORB(SBP2_LOGIN_REQUEST, dev) >= 0)
131 break;
132
133 retries--;
134 if (retries == 0)
135 break;
136
137 DelayThread(200 * 1000); // 200ms
138 }
139
140 if (retries == 0) {
141 M_DEBUG("Failed to log into the SBP-2 device.\n");
142 return -1;
143 }
144
145 if (ieee1394_InitializeFetchAgent(dev) < 0) {
146 M_DEBUG("Error initializing the SBP-2 device's Fetch Agent.\n");
147 return -2;
148 }
149
150 scsi_connect(&dev->scsi);
151
152 M_DEBUG("Completed device initialization.\n");
153
154 return 0;
155}
156
157static inline int initSBP2Disk(struct SBP2Device *dev)
158{
159 void *managementAgentAddr = NULL;
160 unsigned int ConfigurationROMOffset, DirectorySize, i, LeafData, UnitDirectoryOffset;
161 int result;
162
163 UnitDirectoryOffset = 0;
164
165 /* !! NOTE !! sce1394CrRead() reads data starting from the start of the target device's configuration ROM (0x400),
166 and the offset and data to be read is specified in quadlets (Groups of 4 bytes)!!!!! */
167
168 M_DEBUG("Reading configuration ROM for the unit directory offset of node 0x%08x\n", dev->nodeID);
169
170 /* Offset in quadlets: 0x14 / 4 = 5 */
171 ConfigurationROMOffset = 5;
172
173 if ((result = iLinkReadCROM(dev->nodeID, ConfigurationROMOffset, 1, &LeafData)) < 0) {
174 M_DEBUG("Error reading the configuration ROM. Error %d.\n", result);
175 return (result);
176 }
177
178 ConfigurationROMOffset++;
179
180 /* Get the Unit Directory's offset from the root directory. */
181 DirectorySize = LeafData >> 16;
182 for (i = 0; i < DirectorySize; i++) {
183 if ((result = iLinkReadCROM(dev->nodeID, ConfigurationROMOffset, 1, &LeafData)) < 0) {
184 M_DEBUG("Error reading the configuration ROM. Error %d.\n", result);
185 return (result);
186 }
187
188 if ((LeafData >> 24) == IEEE1394_CROM_UNIT_DIRECTORY) {
189 UnitDirectoryOffset = ConfigurationROMOffset + (LeafData & 0x00FFFFFF);
190 break;
191 }
192
193 ConfigurationROMOffset++;
194 }
195 if (i == DirectorySize)
196 return -1;
197
198 if ((result = iLinkReadCROM(dev->nodeID, UnitDirectoryOffset, 1, &LeafData)) < 0) {
199 M_DEBUG("Error reading the configuration ROM. Error %d.\n", result);
200 return (result);
201 }
202
203 DirectorySize = LeafData >> 16;
204 for (i = 0; i < DirectorySize; i++) {
205 /* Get the offset in the configuration ROM of the unit record. */
206 if ((result = iLinkReadCROM(dev->nodeID, UnitDirectoryOffset + 1 + i, 1, &LeafData)) < 0) {
207 M_DEBUG("Error reading the configuration ROM. Error %d.\n", result);
208 return (result);
209 }
210
211 switch (LeafData >> 24) {
212 /* Now get the address of the Management Agent CSR. */
213 case IEEE1394_CROM_CSR_OFFSET:
214 managementAgentAddr = (void *)(LeafData & 0x00FFFFFF); /* Mask off the bits that represent the Management Agent key. */
215 M_DEBUG("managementAgentAddr=0x%08lx.\n", (u32)managementAgentAddr * 4);
216
217 dev->ManagementAgent_low = (u32)managementAgentAddr * 4 + 0xf0000000;
218 dev->ManagementAgent_high = 0x0000ffff;
219 break;
220 case IEEE1394_CROM_UNIT_CHARA:
221 dev->mgt_ORB_timeout = (LeafData & 0x0000FF00) >> 8;
222 dev->ORB_size = LeafData & 0x000000FF;
223 M_DEBUG("mgt_ORB_timeout=%u; ORB_size=%u.\n", dev->mgt_ORB_timeout, dev->ORB_size);
224 break;
225 case IEEE1394_CROM_LOGICAL_UNIT_NUM:
226 dev->LUN = LeafData & 0x0000FFFF;
227 M_DEBUG("LUN=0x%08x.\n", dev->LUN);
228 break;
229 }
230 }
231
232 return 1;
233}
234
235/* Hardware event handling threads. */
236static void iLinkIntrCBHandlingThread(void *arg)
237{
238 int nNodes, i, targetDeviceID, nodeID, result;
239 static const unsigned char PayloadSizeLookupTable[] = {
240 7, /* S100; 2^(7+2)=512 */
241 8, /* S200; 2^(8+2)=1024 */
242 9, /* S400; 2^(9+2)=2048 */
243 };
244
245 (void)arg;
246
247 while (1) {
248 WaitEventFlag(sbp2_event_flag, BUS_RESET_COMPLETE, WEF_AND | WEF_CLEAR, NULL);
249
250 /* Disconnect all currently connected nodes. */
251 for (i = 0; i < MAX_DEVICES; i++) {
252 if (SBP2Devices[i].trContext >= 0) {
253 scsi_disconnect(&SBP2Devices[i].scsi);
254
255 iLinkTrFree(SBP2Devices[i].trContext);
256 SBP2Devices[i].trContext = -1;
257 }
258 }
259
260 if ((nNodes = iLinkGetNodeCount()) < 0) {
261 M_DEBUG("Critical error: Failure getting the number of nodes!\n"); /* Error. */
262 }
263
264 M_PRINTF("BUS RESET DETECTED. Nodes: %d\n", nNodes);
265 M_PRINTF("Local Node: 0x%08x.\n", iLinkGetLocalNodeID());
266
267 // DelayThread(500000); /* Give the devices on the bus some time to initialize themselves (The SBP-2 standard states that a maximum of 5 seconds may be given). */
268
269 targetDeviceID = 0;
270
271 for (i = 0; i < nNodes; i++) {
272 if (targetDeviceID >= MAX_DEVICES) {
273 M_DEBUG("Warning! There are more devices that what can be connected to.\n");
274 break;
275 }
276
277 M_PRINTF("Attempting to initialize unit %d...\n", i);
278
279 /* 16-bit node ID = BUS NUMBER (Upper 10 bits) followed by the NODE ID (Lower 6 bits). */
280 if ((nodeID = iLinkFindUnit(i, 0x0609e, 0x010483)) < 0) {
281 M_DEBUG("Error: Unit %d is not a valid SBP-2 device. Code: %d.\n", i, nodeID);
282 continue;
283 }
284
285 M_PRINTF("Detected SBP-2 device.\n");
286
287 SBP2Devices[targetDeviceID].InitiatorNodeID = iLinkGetLocalNodeID();
288
289 M_PRINTF("Local Node: 0x%08x.\n", SBP2Devices[targetDeviceID].InitiatorNodeID);
290
291#if 0
292 if (SBP2Devices[targetDeviceID].IsConnected) { /* Already connected to the device. */
293 if (SBP2Devices[targetDeviceID].nodeID == nodeID) { /* Make sure that we're attempting to re-connect to the same device. */
294 if (ieee1394_SendManagementORB(SBP2_RECONNECT_REQUEST, &SBP2Devices[i]) < 0) {
295 M_DEBUG("Error reconnecting to the SBP-2 device %u.\n", nodeID);
296 } else {
297 M_DEBUG("Successfully reconnected to SBP-2 device %u.", nodeID);
298 targetDeviceID++;
299 continue;
300 }
301 } else
302 SBP2Devices[targetDeviceID].IsConnected = 0;
303 }
304#endif
305
306 SBP2Devices[targetDeviceID].IsConnected = 0;
307
308 /* Attempt a login into the device. */
309 SBP2Devices[targetDeviceID].nodeID = nodeID;
310 if ((result = initSBP2Disk(&SBP2Devices[targetDeviceID])) < 0) {
311 M_DEBUG("Error initializing the device. Code: %d.\n", result);
312 continue;
313 }
314
315 SBP2Devices[targetDeviceID].trContext = iLinkTrAlloc(nodeID, iLinkGetNodeMaxSpeed(nodeID));
316
317 if (SBP2Devices[targetDeviceID].trContext >= 0) {
318 M_PRINTF("Connected device as node 0x%08x.\n", SBP2Devices[targetDeviceID].nodeID);
319 M_PRINTF("Generation number: %d.\n", iLinkGetGenerationNumber());
320
321 SBP2Devices[targetDeviceID].speed = iLinkGetNodeTrSpeed(SBP2Devices[targetDeviceID].trContext);
322 M_PRINTF("Current speed: %d.\n", SBP2Devices[targetDeviceID].speed);
323
324 SBP2Devices[targetDeviceID].max_payload = PayloadSizeLookupTable[SBP2Devices[targetDeviceID].speed];
325
326 if (initConfigureSBP2Device(&SBP2Devices[targetDeviceID]) >= 0) {
327 SBP2Devices[targetDeviceID].IsConnected = 1;
328 targetDeviceID++;
329 }
330 } else {
331 M_DEBUG("Error allocating a transaction.\n");
332 }
333 }
334
335 for (; targetDeviceID < MAX_DEVICES; targetDeviceID++)
336 SBP2Devices[targetDeviceID].IsConnected = 0; /* Mark the unused device slots as being unused. */
337 }
338}
339
340static void ieee1394_ResetFetchAgent(struct SBP2Device *dev)
341{
342 unsigned long int dummy;
343 int result;
344
345 /* Reset the Fetch Agent. */
346 if ((result = iLinkTrWrite(dev->trContext, dev->CommandBlockAgent_high, dev->CommandBlockAgent_low + 0x04, &dummy, 4)) < 0) {
347 M_DEBUG("Error writing to the Fetch Agent's AGENT_RESET register @ 0x%08lx %08lx. Code: %d.\n", dev->CommandBlockAgent_high, dev->CommandBlockAgent_low + 0x04, result);
348 }
349}
350
351static int ieee1394_GetFetchAgentState(struct SBP2Device *dev)
352{
353 unsigned long int FetchAgentState;
354 int result;
355
356 if ((result = iLinkTrRead(dev->trContext, dev->CommandBlockAgent_high, dev->CommandBlockAgent_low, &FetchAgentState, 4)) < 0) {
357 M_DEBUG("Error reading the Fetch Agent's AGENT_STATE register @ 0x%08lx %08lx. Code: %d.\n", dev->CommandBlockAgent_high, dev->CommandBlockAgent_low, result);
358 return -1;
359 } else {
360 FetchAgentState = BSWAP32(FetchAgentState);
361 M_DEBUG("Fetch Agent state: %lu.\n", FetchAgentState);
362 return FetchAgentState;
363 }
364}
365
366static int ieee1394_InitializeFetchAgent(struct SBP2Device *dev)
367{
368 int result, retries;
369 void *dummy_ORB;
370 struct sbp2_pointer address;
371
372 M_DEBUG("Initializing fetch agent...");
373
374 dummy_ORB = malloc(dev->ORB_size * 4);
375 memset(dummy_ORB, 0, dev->ORB_size * 4);
376
377 ieee1394_ResetFetchAgent(dev);
378
379 /* Write the address of the dummy ORB to the fetch agent's ORB_POINTER register. */
380 address.low = (u32)dummy_ORB;
381 address.NodeID = dev->InitiatorNodeID;
382 address.high = 0;
383
384 ((struct sbp2_ORB_pointer *)dummy_ORB)->reserved = NULL_POINTER;
385 ((struct sbp2_ORB_pointer *)dummy_ORB)->high = ((struct sbp2_ORB_pointer *)dummy_ORB)->low = 0;
386 ((struct management_ORB *)dummy_ORB)->flags = (u32)(ORB_NOTIFY | ORB_REQUEST_FORMAT(3));
387
388 retries = 0;
389 while ((result = iLinkTrWrite(dev->trContext, dev->CommandBlockAgent_high, dev->CommandBlockAgent_low + 0x08, &address, 8)) < 0) {
390 M_DEBUG("Error writing to the Fetch Agent's ORB_POINTER register @ 0x%08lx %08lx. Code: %d.\n", dev->CommandBlockAgent_high, dev->CommandBlockAgent_low + 0x08, result);
391 ieee1394_ResetFetchAgent(dev);
392
393 retries++;
394 if (retries > 3)
395 return (-1);
396 }
397
398 result = ieee1394_Sync();
399 ieee1394_GetFetchAgentState(dev);
400
401 free(dummy_ORB);
402
403 M_DEBUG("done!\n");
404
405 return 1;
406}
407
408static int ieee1394_SendManagementORB(int mode, struct SBP2Device *dev)
409{
410 int result;
411 struct sbp2_pointer address;
412
413 struct sbp2_login_response login_result;
414 struct management_ORB new_management_ORB;
415
416 memset((void *)&statusFIFO, 0, sizeof(statusFIFO));
417 memset(&login_result, 0, sizeof(struct sbp2_login_response));
418 memset(&new_management_ORB, 0, sizeof(struct management_ORB));
419
420 new_management_ORB.status_FIFO.low = (u32)&statusFIFO;
421 new_management_ORB.flags = (u32)(ORB_NOTIFY | ORB_REQUEST_FORMAT(0) | MANAGEMENT_ORB_FUNCTION(mode));
422
423 switch (mode) {
424 case SBP2_LOGIN_REQUEST: /* Login. */
425 /* The reconnect timeout is now set to 0, since the mechanism that determines whether the initiator was already logged into the target or not was not accurate. */
426 new_management_ORB.flags |= (u32)(MANAGEMENT_ORB_RECONNECT(0) | MANAGEMENT_ORB_EXCLUSIVE(1) | MANAGEMENT_ORB_LUN(dev->LUN));
427
428 new_management_ORB.login.response.low = (u32)&login_result;
429 new_management_ORB.length = (MANAGEMENT_ORB_RESPONSE_LENGTH(sizeof(struct sbp2_login_response)) | MANAGEMENT_ORB_PASSWORD_LENGTH(0));
430 break;
431#if 0
432 case SBP2_RECONNECT_REQUEST: /* Reconnect. */
433 new_management_ORB.flags |= (u32)(MANAGEMENT_ORB_RECONNECT(4) | MANAGEMENT_ORB_LOGINID(dev->loginID)); /* loginID was stored as a big endian number, so it has to be converted into little endian first. :( */
434 break;
435#endif
436 default:
437 M_DEBUG("Warning! Unsupported management ORB type!\n");
438 }
439
440 address.NodeID = dev->InitiatorNodeID;
441 address.high = 0;
442 address.low = (u32)&new_management_ORB;
443
444 M_DEBUG("Management ORB: %p. size=%d.\n", &new_management_ORB, sizeof(struct management_ORB));
445 M_DEBUG("Address pointer: %p\n", &address);
446
447 if ((result = iLinkTrWrite(dev->trContext, dev->ManagementAgent_high, dev->ManagementAgent_low, &address, 8)) < 0) { /* Write the Login ORB address to the target's Management Agent CSR. */
448 M_DEBUG("Error writing to the Management Agent CSR @ 0x%08lx %08lx. Code: %d.\n", dev->ManagementAgent_high, dev->ManagementAgent_low, result);
449 return (result);
450 }
451
452 M_DEBUG("Waiting for ILINK...\n");
453
454 result = ieee1394_Sync_withTimeout(dev->mgt_ORB_timeout);
455
456 M_DEBUG("statusFIFO= %p; [0]=%u.\n", &statusFIFO, statusFIFO.buffer[0]);
457 if (result >= 0) {
458 switch (mode) {
459 case SBP2_LOGIN_REQUEST: /* Login. */
460 M_DEBUG("Done. command_block_agent= 0x%08x %08lx.\n", login_result.command_block_agent.high, login_result.command_block_agent.low);
461
462 /* Store the address to the target's command block agent. */
463
464 dev->CommandBlockAgent_high = login_result.command_block_agent.high;
465 dev->CommandBlockAgent_low = login_result.command_block_agent.low;
466
467 dev->loginID = login_result.login_ID; /* Store the login ID. */
468
469 M_DEBUG("Login response size: %u.", login_result.length);
470 M_DEBUG("Signed into SBP-2 device node 0x%08x. Login ID: %u\n", dev->nodeID, dev->loginID);
471 break;
472#if 0
473 case SBP2_RECONNECT_REQUEST: /* Reconnect. */
474 /* Just return the result from ieee1394_Sync(). */
475 break;
476#endif
477 default:
478 M_DEBUG("Warning! Unsupported management ORB type!\n");
479 }
480
481 /* Validate the fetch agent's CSR address. */
482 if ((dev->CommandBlockAgent_low < 0xF0010000) || ((dev->CommandBlockAgent_high & 0xFFFF) != 0x0000FFFF))
483 result = (-1);
484 }
485
486 return result;
487}
488
489int ieee1394_SendCommandBlockORB(struct SBP2Device *dev, struct CommandDescriptorBlock *firstCDB)
490{
491 int result, retries;
492 struct sbp2_pointer address;
493
494 memset((void *)&statusFIFO, 0, sizeof(statusFIFO));
495
496 address.low = (u32)firstCDB;
497 address.NodeID = dev->InitiatorNodeID;
498 address.high = 0;
499
500 retries = 0;
501
502 /* Write the pointer to the first ORB in the fetch agent's NEXT_ORB register. */
503 while ((result = iLinkTrWrite(dev->trContext, dev->CommandBlockAgent_high, dev->CommandBlockAgent_low + 0x08, &address, 8)) < 0) {
504 M_DEBUG("Error writing to the Fetch Agent's ORB_POINTER register @ 0x%08lx %08lx. Code: %d.\n", dev->CommandBlockAgent_high, dev->CommandBlockAgent_low + 0x08, result);
505
506 DelayThread(200000);
507 ieee1394_ResetFetchAgent(dev);
508
509 retries++;
510 if (retries > 3)
511 return (-1);
512 }
513
514#if 0
515 /* Write a value to the fetch agent's DOORBELL register. */
516 result = 1;
517 if ((result = iLinkTrWrite(dev->trContext, dev->CommandBlockAgent_high, dev->CommandBlockAgent_low + 0x10, &result, 4)) < 0) {
518 M_DEBUG("Error writing to the Fetch Agent's DOORBELL register @ 0x%08lx %08lx. Code: %d.\n", dev->CommandBlockAgent_high, dev->CommandBlockAgent_low + 0x10, result);
519 return -2;
520 }
521#endif
522
523 return 1;
524}
525
526static int sbp2_get_max_lun(struct scsi_interface *scsi)
527{
528 (void)scsi;
529
530 return 0;
531}
532
533static int sbp2_queue_cmd(struct scsi_interface *scsi, const unsigned char *cmd, unsigned int cmd_len, unsigned char *data, unsigned int data_len, unsigned int data_wr)
534{
535 struct SBP2Device *dev = (struct SBP2Device *)scsi->priv;
536 int i;
537 int ret;
538 struct CommandDescriptorBlock cdb;
539
540 M_DEBUG("sbp2_queue_cmd(0x%02x)\n", cmd[0]);
541
542 cdb.misc = ORB_NOTIFY | ORB_REQUEST_FORMAT(0) | CDB_MAX_PAYLOAD(dev->max_payload) | CDB_SPEED(dev->speed);
543 cdb.misc |= data_wr ? CDB_DIRECTION(WRITE_TRANSACTION) : CDB_DIRECTION(READ_TRANSACTION);
544 if (data_len > 0)
545 cdb.misc |= CDB_DATA_SIZE(data_len);
546
547 cdb.DataDescriptor.low = data_wr ? (u32)writeBuffer : (u32)data;
548 cdb.DataDescriptor.high = 0;
549 cdb.DataDescriptor.NodeID = dev->InitiatorNodeID;
550
551 cdb.NextOrb.high = 0;
552 cdb.NextOrb.low = 0;
553 cdb.NextOrb.reserved = NULL_POINTER;
554
555 // Copy and BSWAP32 the SCSI command
556 for (i = 0; (unsigned int)i < cmd_len / 4; i++)
557 ((unsigned int *)cdb.CDBs)[i] = BSWAP32(((unsigned int *)cmd)[i]);
558
559 if ((data_len > 0) && (data_wr == 1)) {
560 // BSWAP32 all data we write
561 for (i = 0; (unsigned int)i < data_len / 4; i++)
562 ((unsigned int *)writeBuffer)[i] = BSWAP32(((unsigned int *)data)[i]);
563 }
564
565 ieee1394_SendCommandBlockORB(dev, &cdb);
566 ret = ieee1394_Sync();
567
568 if (ret != 0) {
569 M_DEBUG("sbp2_queue_cmd error %d\n", ret);
570 } else if ((data_len > 0) && (data_wr == 0)) {
571 // BSWAP32 all data we read
572 for (i = 0; (unsigned int)i < data_len / 4; i++)
573 ((unsigned int *)data)[i] = BSWAP32(((unsigned int *)data)[i]);
574 }
575
576 return ret;
577}
578
579/* static unsigned int alarm_cb(void *arg)
580{
581 iSetEventFlag(sbp2_event_flag, ERROR_TIME_OUT);
582 return 0;
583} */
584
585static int ProcessStatus(void)
586{
587 u32 statusFIFO_result;
588 unsigned char status, resp, dead, sense, len;
589 int result;
590
591 statusFIFO_result = statusFIFO.status.status;
592 status = RESP_SBP_STATUS(statusFIFO_result);
593 resp = RESP_RESP(statusFIFO_result);
594 dead = RESP_DEAD(statusFIFO_result);
595 len = RESP_LEN(statusFIFO_result);
596 sense = ((statusFIFO.status.data[0]) >> 16) & 0xF;
597
598 M_DEBUG("result: 0x%08lx; status: 0x%02x; RESP: 0x%02x; Dead: %u; len: 0x%02x; sense: 0x%02x.\n", statusFIFO_result, status, resp, dead, len, sense);
599 if (sense == 0)
600 sense = 1; /* Workaround for faulty firmwares: The sense code is 0 or was not sent when it's supposed to be sent. */
601
602 result = (((status == 0) || (status == 0x0B)) && (resp == 0) && (!dead) && (len == 1)) ? 0 : -sense;
603
604 if (result < 0) {
605 M_PRINTF("result: 0x%08lx; status: 0x%02x; RESP: 0x%02x; Dead: %u; len: 0x%02x; sense: 0x%02x.\n", statusFIFO_result, status, resp, dead, len, sense);
606 }
607
608 return result;
609}
610
611/* This is declared as inline as there is only one call to it. */
612static inline int ieee1394_Sync_withTimeout(u32 n500mSecUnits)
613{
614 /* iop_sys_clock_t timeout_clk;
615 u32 ef_result;
616
617 USec2SysClock(n500mSecUnits * 500000, &timeout_clk);
618
619 SetAlarm(&timeout_clk, &alarm_cb, NULL);
620 WaitEventFlag(sbp2_event_flag, WRITE_REQ_INCOMING | ERROR_TIME_OUT, WEF_OR | WEF_CLEAR, &ef_result);
621
622 if (ef_result & ERROR_TIME_OUT) {
623 M_DEBUG("-=Time out=-\n");
624 return (-1);
625 } else
626 CancelAlarm(&alarm_cb, NULL); */
627
628 unsigned int i = 0;
629
630 while (RESP_SRC(statusFIFO.status.status) == 0) {
631 if (i > n500mSecUnits * 10000) {
632 M_DEBUG("-=Time out=-\n");
633 return (-1);
634 }
635
636 DelayThread(50);
637 i++;
638 };
639
640 return (ProcessStatus());
641}
642
643int ieee1394_Sync(void)
644{
645 // WaitEventFlag(sbp2_event_flag, WRITE_REQ_INCOMING, WEF_AND | WEF_CLEAR, NULL);
646
647 while (RESP_SRC(statusFIFO.status.status) == 0) {
648 DelayThread(50);
649 };
650
651 return (ProcessStatus());
652}
653
654void DeinitIEEE1394(void)
655{
656 TerminateThread(iLinkIntrCBThreadID);
657 DeleteThread(iLinkIntrCBThreadID);
658 DeleteEventFlag(sbp2_event_flag);
659}
660
661void *malloc(int NumBytes)
662{
663 int OldState;
664 void *buffer;
665
666 CpuSuspendIntr(&OldState);
667 buffer = AllocSysMemory(ALLOC_FIRST, NumBytes, NULL);
668 CpuResumeIntr(OldState);
669
670 return buffer;
671}
672
673void free(void *buffer)
674{
675 int OldState;
676
677 CpuSuspendIntr(&OldState);
678 FreeSysMemory(buffer);
679 CpuResumeIntr(OldState);
680}
int CpuResumeIntr(int state)
Definition intrman.c:227
int CpuSuspendIntr(int *state)
Definition intrman.c:205