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