PS2SDK
PS2 Homebrew Libraries
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
18 static struct SBP2Device SBP2Devices[MAX_DEVICES];
19 static u8 *writeBuffer = NULL;
20 
21 /* Thread creation data. */
22 static 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;
31 static int sbp2_event_flag;
32 
33 static void ieee1394_callback(int reason, unsigned long int offset, unsigned long int size);
34 static void iLinkIntrCBHandlingThread(void *arg);
35 static int ieee1394_SendManagementORB(int mode, struct SBP2Device *dev);
36 static int ieee1394_InitializeFetchAgent(struct SBP2Device *dev);
37 static inline int ieee1394_Sync_withTimeout(u32 n500mSecUnits);
38 void free(void *buffer);
39 void *malloc(int NumBytes);
40 
41 static volatile union
42 {
43  struct sbp2_status status;
44  unsigned char buffer[32]; /* Maximum 32 bytes. */
45 } statusFIFO;
46 
47 static 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. */
79 static iop_event_t evfp = {
80  2, /* evfp.attr=EA_MULTI */
81  0, /* evfp.option */
82  0 /* evfp.bits */
83 };
84 
85 int iLinkIntrCBThreadID;
86 static int sbp2_get_max_lun(struct scsi_interface *scsi);
87 static 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 
89 void 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 
123 static 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 
157 static 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. */
236 static 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 
340 static 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 
351 static 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 
366 static 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 
408 static 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 
489 int 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 
526 static int sbp2_get_max_lun(struct scsi_interface *scsi)
527 {
528  (void)scsi;
529 
530  return 0;
531 }
532 
533 static 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  memset(&cdb, 0, sizeof(cdb));
540 
541  M_DEBUG("sbp2_queue_cmd(0x%02x)\n", cmd[0]);
542 
543  cdb.misc = ORB_NOTIFY | ORB_REQUEST_FORMAT(0) | CDB_MAX_PAYLOAD(dev->max_payload) | CDB_SPEED(dev->speed);
544  cdb.misc |= data_wr ? CDB_DIRECTION(READ_TRANSACTION) : CDB_DIRECTION(WRITE_TRANSACTION); // flipped
545  if (data_len > 0)
546  cdb.misc |= CDB_DATA_SIZE(data_len);
547 
548  cdb.DataDescriptor.low = data_wr ? (u32)writeBuffer : (u32)data;
549  cdb.DataDescriptor.high = 0;
550  cdb.DataDescriptor.NodeID = dev->InitiatorNodeID;
551 
552  cdb.NextOrb.high = 0;
553  cdb.NextOrb.low = 0;
554  cdb.NextOrb.reserved = NULL_POINTER;
555 
556  // Copy and BSWAP32 the SCSI command
557  for (i = 0; (unsigned int)i < cmd_len / 4; i++)
558  ((unsigned int *)cdb.CDBs)[i] = BSWAP32(((unsigned int *)cmd)[i]);
559 
560  if ((data_len > 0) && (data_wr == 1)) {
561  // BSWAP32 all data we write
562  for (i = 0; (unsigned int)i < data_len / 4; i++)
563  ((unsigned int *)writeBuffer)[i] = BSWAP32(((unsigned int *)data)[i]);
564  }
565 
566  ieee1394_SendCommandBlockORB(dev, &cdb);
567  ret = ieee1394_Sync();
568 
569  if (ret != 0) {
570  M_DEBUG("sbp2_queue_cmd error %d\n", ret);
571  } else if ((data_len > 0) && (data_wr == 0)) {
572  // BSWAP32 all data we read
573  for (i = 0; (unsigned int)i < data_len / 4; i++)
574  ((unsigned int *)data)[i] = BSWAP32(((unsigned int *)data)[i]);
575  }
576 
577  return ret;
578 }
579 
580 /* static unsigned int alarm_cb(void *arg)
581 {
582  iSetEventFlag(sbp2_event_flag, ERROR_TIME_OUT);
583  return 0;
584 } */
585 
586 static int ProcessStatus(void)
587 {
588  u32 statusFIFO_result;
589  unsigned char status, resp, dead, sense, len;
590  int result;
591 
592  statusFIFO_result = statusFIFO.status.status;
593  status = RESP_SBP_STATUS(statusFIFO_result);
594  resp = RESP_RESP(statusFIFO_result);
595  dead = RESP_DEAD(statusFIFO_result);
596  len = RESP_LEN(statusFIFO_result);
597  sense = ((statusFIFO.status.data[0]) >> 16) & 0xF;
598 
599  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);
600  if (sense == 0)
601  sense = 1; /* Workaround for faulty firmwares: The sense code is 0 or was not sent when it's supposed to be sent. */
602 
603  result = (((status == 0) || (status == 0x0B)) && (resp == 0) && (!dead) && (len == 1)) ? 0 : -sense;
604 
605  if (result < 0) {
606  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);
607  }
608 
609  return result;
610 }
611 
612 /* This is declared as inline as there is only one call to it. */
613 static inline int ieee1394_Sync_withTimeout(u32 n500mSecUnits)
614 {
615  /* iop_sys_clock_t timeout_clk;
616  u32 ef_result;
617 
618  USec2SysClock(n500mSecUnits * 500000, &timeout_clk);
619 
620  SetAlarm(&timeout_clk, &alarm_cb, NULL);
621  WaitEventFlag(sbp2_event_flag, WRITE_REQ_INCOMING | ERROR_TIME_OUT, WEF_OR | WEF_CLEAR, &ef_result);
622 
623  if (ef_result & ERROR_TIME_OUT) {
624  M_DEBUG("-=Time out=-\n");
625  return (-1);
626  } else
627  CancelAlarm(&alarm_cb, NULL); */
628 
629  unsigned int i = 0;
630 
631  while (RESP_SRC(statusFIFO.status.status) == 0) {
632  if (i > n500mSecUnits * 10000) {
633  M_DEBUG("-=Time out=-\n");
634  return (-1);
635  }
636 
637  DelayThread(50);
638  i++;
639  };
640 
641  return (ProcessStatus());
642 }
643 
644 int ieee1394_Sync(void)
645 {
646  // WaitEventFlag(sbp2_event_flag, WRITE_REQ_INCOMING, WEF_AND | WEF_CLEAR, NULL);
647 
648  while (RESP_SRC(statusFIFO.status.status) == 0) {
649  DelayThread(50);
650  };
651 
652  return (ProcessStatus());
653 }
654 
655 void DeinitIEEE1394(void)
656 {
657  TerminateThread(iLinkIntrCBThreadID);
658  DeleteThread(iLinkIntrCBThreadID);
659  DeleteEventFlag(sbp2_event_flag);
660 }
661 
662 void *malloc(int NumBytes)
663 {
664  int OldState;
665  void *buffer;
666 
667  CpuSuspendIntr(&OldState);
668  buffer = AllocSysMemory(ALLOC_FIRST, NumBytes, NULL);
669  CpuResumeIntr(OldState);
670 
671  return buffer;
672 }
673 
674 void free(void *buffer)
675 {
676  int OldState;
677 
678  CpuSuspendIntr(&OldState);
679  FreeSysMemory(buffer);
680  CpuResumeIntr(OldState);
681 }
management_ORB
Definition: sbp2_disk.h:96
sbp2_login_response
Definition: sbp2_disk.h:87
thbase.h
CommandDescriptorBlock
Definition: sbp2_disk.h:116
sysclib.h
CpuSuspendIntr
int CpuSuspendIntr(int *state)
Definition: intrman.c:195
usbhdfsd-common.h
loadcore.h
sbp2_pointer
Definition: sbp2_disk.h:73
sbp2_status
Definition: sbp2_disk.h:66
stdio.h
_iop_thread
Definition: thbase.h:39
CpuResumeIntr
int CpuResumeIntr(int state)
Definition: intrman.c:217
sbp2_ORB_pointer
Definition: sbp2_disk.h:80
sysmem.h
intrman.h
SBP2Device
Definition: sbp2_disk.h:125
iop_event_t
Definition: thevent.h:37
scsi_interface
Definition: scsi.h:4
thevent.h