14#include "mass_debug.h"
15#include "usbhd_common.h"
18static struct SBP2Device SBP2Devices[MAX_DEVICES];
30static int sbp2_event_flag;
32static void ieee1394_callback(
int reason,
unsigned long int offset,
unsigned long int size);
33static void iLinkIntrCBHandlingThread(
void *arg);
34static int ieee1394_SendManagementORB(
int mode,
struct SBP2Device *dev);
35static int ieee1394_InitializeFetchAgent(
struct SBP2Device *dev);
36static inline int ieee1394_Sync_withTimeout(u32 n500mSecUnits);
41 unsigned char buffer[32];
44static void ieee1394_callback(
int reason,
unsigned long int offset,
unsigned long int size)
50 iLinkBufferOffset = offset;
51 iLinkTransferSize = size;
53 if (reason == iLink_CB_WRITE_REQUEST) {
54 u32 statusFIFO_result;
58 if (iLinkBufferOffset == (u32)&statusFIFO) {
59 statusFIFO_result = statusFIFO.status.status;
60 if (RESP_SRC(statusFIFO_result) != 0)
61 SetEventFlag(sbp2_event_flag, WRITE_REQ_INCOMING);
65 if (reason == iLink_CB_BUS_RESET) {
66 SetEventFlag(sbp2_event_flag, BUS_RESET_COMPLETE);
82int iLinkIntrCBThreadID;
84void init_ieee1394DiskDriver(
void)
88 for (i = 0; i < MAX_DEVICES; i++) {
89 SBP2Devices[i].IsConnected = 0;
90 SBP2Devices[i].nodeID = 0;
91 SBP2Devices[i].trContext = (-1);
94 sbp2_event_flag = CreateEventFlag(&evfp);
96 XPRINTF(
"Starting threads..\n");
98 threadData.thread = &iLinkIntrCBHandlingThread;
99 iLinkIntrCBThreadID = CreateThread(&threadData);
100 StartThread(iLinkIntrCBThreadID, NULL);
102 iLinkSetTrCallbackHandler(&ieee1394_callback);
104 XPRINTF(
"Threads created and started.\n");
109static int initConfigureSBP2Device(
struct SBP2Device *dev)
111 unsigned char retries;
115 if (ieee1394_SendManagementORB(SBP2_LOGIN_REQUEST, dev) < 0) {
116 XPRINTF(
"Error logging into the SBP-2 device.\n");
120 }
while (retries > 0);
122 XPRINTF(
"Failed to log into the SBP-2 device.\n");
126 if (ieee1394_InitializeFetchAgent(dev) < 0) {
127 XPRINTF(
"Error initializing the SBP-2 device's Fetch Agent.\n");
131 if (ConfigureSBP2Device(dev) < 0)
134 XPRINTF(
"Completed device initialization.\n");
139 u32 lSecStart, lUSecStart;
140 u32 lSecEnd, lUSecEnd, nbytes, i, rounds;
146 if ((buffer = malloc(nbytes)) == NULL)
147 printf(
"Unable to allocate memory. :(\n");
148 printf(
"Read test: %p.\n", buffer);
149 printf(
"Start reading data...\n");
151 GetSystemTime(&lTime);
152 SysClock2USec(&lTime, &lSecStart, &lUSecStart);
154 for (i = 0; i < rounds; i++) {
155 if ((result = scsiReadSector(dev, 16, buffer, nbytes / 512)) != 0) {
156 printf(
"Sector read error %d.\n", result);
162 GetSystemTime(&lTime);
163 SysClock2USec(&lTime, &lSecEnd, &lUSecEnd);
165 printf(
"Completed.\n");
167 printf(
"Done: %lu %lu/%lu %lu\n", lSecStart, lUSecStart, lSecEnd, lUSecEnd);
168 printf(
"KB: %lu, time: %lu, Approximate KB/s: %lu", (nbytes * rounds / 1024), (lSecEnd - lSecStart), (nbytes * rounds / 1024) / (lSecEnd - lSecStart));
175static inline int initSBP2Disk(
struct SBP2Device *dev)
177 void *managementAgentAddr = NULL;
178 unsigned int ConfigurationROMOffset, DirectorySize, i, LeafData, UnitDirectoryOffset;
181 UnitDirectoryOffset = 0;
186 XPRINTF(
"Reading configuration ROM for the unit directory offset of node 0x%08x\n", dev->nodeID);
189 ConfigurationROMOffset = 5;
191 if ((result = iLinkReadCROM(dev->nodeID, ConfigurationROMOffset, 1, &LeafData)) < 0) {
192 XPRINTF(
"Error reading the configuration ROM. Error %d.\n", result);
196 ConfigurationROMOffset++;
199 DirectorySize = LeafData >> 16;
200 for (i = 0; i < DirectorySize; i++) {
201 if ((result = iLinkReadCROM(dev->nodeID, ConfigurationROMOffset, 1, &LeafData)) < 0) {
202 XPRINTF(
"Error reading the configuration ROM. Error %d.\n", result);
206 if ((LeafData >> 24) == IEEE1394_CROM_UNIT_DIRECTORY) {
207 UnitDirectoryOffset = ConfigurationROMOffset + (LeafData & 0x00FFFFFF);
211 ConfigurationROMOffset++;
213 if (i == DirectorySize)
216 if ((result = iLinkReadCROM(dev->nodeID, UnitDirectoryOffset, 1, &LeafData)) < 0) {
217 XPRINTF(
"Error reading the configuration ROM. Error %d.\n", result);
221 DirectorySize = LeafData >> 16;
222 for (i = 0; i < DirectorySize; i++) {
224 if ((result = iLinkReadCROM(dev->nodeID, UnitDirectoryOffset + 1 + i, 1, &LeafData)) < 0) {
225 XPRINTF(
"Error reading the configuration ROM. Error %d.\n", result);
229 switch (LeafData >> 24) {
231 case IEEE1394_CROM_CSR_OFFSET:
232 managementAgentAddr = (
void *)(LeafData & 0x00FFFFFF);
233 XPRINTF(
"managementAgentAddr=0x%08lx.\n", (u32)managementAgentAddr * 4);
235 dev->ManagementAgent_low = (u32)managementAgentAddr * 4 + 0xf0000000;
236 dev->ManagementAgent_high = 0x0000ffff;
238 case IEEE1394_CROM_UNIT_CHARA:
239 dev->mgt_ORB_timeout = (LeafData & 0x0000FF00) >> 8;
240 dev->ORB_size = LeafData & 0x000000FF;
241 XPRINTF(
"mgt_ORB_timeout=%u; ORB_size=%u.\n", dev->mgt_ORB_timeout, dev->ORB_size);
243 case IEEE1394_CROM_LOGICAL_UNIT_NUM:
244 dev->LUN = LeafData & 0x0000FFFF;
245 XPRINTF(
"LUN=0x%08x.\n", dev->LUN);
254static void iLinkIntrCBHandlingThread(
void *arg)
256 int nNodes, i, targetDeviceID, nodeID, result;
257 static const unsigned char PayloadSizeLookupTable[] = {
266 WaitEventFlag(sbp2_event_flag, BUS_RESET_COMPLETE, WEF_AND | WEF_CLEAR, NULL);
269 for (i = 0; i < MAX_DEVICES; i++) {
270 if (SBP2Devices[i].trContext >= 0) {
271 releaseSBP2Device(&SBP2Devices[i]);
273 iLinkTrFree(SBP2Devices[i].trContext);
274 SBP2Devices[i].trContext = -1;
278 if ((nNodes = iLinkGetNodeCount()) < 0) {
279 XPRINTF(
"Critical error: Failure getting the number of nodes!\n");
282 XPRINTF(
"BUS RESET DETECTED. Nodes: %d\n", nNodes);
283 XPRINTF(
"Local Node: 0x%08x.\n", iLinkGetLocalNodeID());
289 for (i = 0; i < nNodes; i++) {
290 if (targetDeviceID >= MAX_DEVICES) {
291 XPRINTF(
"Warning! There are more devices that what can be connected to.\n");
295 XPRINTF(
"Attempting to initialize unit %d...\n", i);
298 if ((nodeID = iLinkFindUnit(i, 0x0609e, 0x010483)) < 0) {
299 XPRINTF(
"Error: Unit %d is not a valid SBP-2 device. Code: %d.\n", i, nodeID);
303 XPRINTF(
"Detected SBP-2 device.\n");
305 SBP2Devices[targetDeviceID].InitiatorNodeID = iLinkGetLocalNodeID();
307 XPRINTF(
"Local Node: 0x%08x.\n", SBP2Devices[targetDeviceID].InitiatorNodeID);
310 if (SBP2Devices[targetDeviceID].IsConnected) {
311 if (SBP2Devices[targetDeviceID].nodeID == nodeID) {
312 if (ieee1394_SendManagementORB(SBP2_RECONNECT_REQUEST, &SBP2Devices[i]) < 0) {
313 XPRINTF(
"Error reconnecting to the SBP-2 device %u.\n", nodeID);
315 XPRINTF(
"Successfully reconnected to SBP-2 device %u.", nodeID);
320 SBP2Devices[targetDeviceID].IsConnected = 0;
324 SBP2Devices[targetDeviceID].IsConnected = 0;
327 SBP2Devices[targetDeviceID].nodeID = nodeID;
328 if ((result = initSBP2Disk(&SBP2Devices[targetDeviceID])) < 0) {
329 XPRINTF(
"Error initializing the device. Code: %d.\n", result);
333 SBP2Devices[targetDeviceID].trContext = iLinkTrAlloc(nodeID, iLinkGetNodeMaxSpeed(nodeID));
335 if (SBP2Devices[targetDeviceID].trContext >= 0) {
336 XPRINTF(
"Connected device as node 0x%08x.\n", SBP2Devices[targetDeviceID].nodeID);
337 XPRINTF(
"Generation number: %d.\n", iLinkGetGenerationNumber());
339 SBP2Devices[targetDeviceID].speed = iLinkGetNodeTrSpeed(SBP2Devices[targetDeviceID].trContext);
340 XPRINTF(
"Current speed: %d.\n", SBP2Devices[targetDeviceID].speed);
342 SBP2Devices[targetDeviceID].max_payload = PayloadSizeLookupTable[SBP2Devices[targetDeviceID].speed];
344 if (initConfigureSBP2Device(&SBP2Devices[targetDeviceID]) >= 0) {
345 SBP2Devices[targetDeviceID].IsConnected = 1;
349 XPRINTF(
"Error allocating a transaction.\n");
353 for (; targetDeviceID < MAX_DEVICES; targetDeviceID++)
354 SBP2Devices[targetDeviceID].IsConnected = 0;
358static void ieee1394_ResetFetchAgent(
struct SBP2Device *dev)
360 unsigned long int dummy;
364 if ((result = iLinkTrWrite(dev->trContext, dev->CommandBlockAgent_high, dev->CommandBlockAgent_low + 0x04, &dummy, 4)) < 0) {
365 XPRINTF(
"Error writing to the Fetch Agent's AGENT_RESET register @ 0x%08lx %08lx. Code: %d.\n", dev->CommandBlockAgent_high, dev->CommandBlockAgent_low + 0x04, result);
369static int ieee1394_GetFetchAgentState(
struct SBP2Device *dev)
371 unsigned long int FetchAgentState;
374 if ((result = iLinkTrRead(dev->trContext, dev->CommandBlockAgent_high, dev->CommandBlockAgent_low, &FetchAgentState, 4)) < 0) {
375 XPRINTF(
"Error reading the Fetch Agent's AGENT_STATE register @ 0x%08lx %08lx. Code: %d.\n", dev->CommandBlockAgent_high, dev->CommandBlockAgent_low, result);
378 FetchAgentState = BSWAP32(FetchAgentState);
379 XPRINTF(
"Fetch Agent state: %lu.\n", FetchAgentState);
380 return FetchAgentState;
384static int ieee1394_InitializeFetchAgent(
struct SBP2Device *dev)
390 XPRINTF(
"Initializing fetch agent...");
392 dummy_ORB = malloc(dev->ORB_size * 4);
393 memset(dummy_ORB, 0, dev->ORB_size * 4);
395 ieee1394_ResetFetchAgent(dev);
398 address.low = (u32)dummy_ORB;
399 address.NodeID = dev->InitiatorNodeID;
404 ((
struct management_ORB *)dummy_ORB)->flags = (u32)(ORB_NOTIFY | ORB_REQUEST_FORMAT(3));
407 while ((result = iLinkTrWrite(dev->trContext, dev->CommandBlockAgent_high, dev->CommandBlockAgent_low + 0x08, &address, 8)) < 0) {
408 XPRINTF(
"Error writing to the Fetch Agent's ORB_POINTER register @ 0x%08lx %08lx. Code: %d.\n", dev->CommandBlockAgent_high, dev->CommandBlockAgent_low + 0x08, result);
409 ieee1394_ResetFetchAgent(dev);
416 result = ieee1394_Sync();
417 ieee1394_GetFetchAgentState(dev);
426static int ieee1394_SendManagementORB(
int mode,
struct SBP2Device *dev)
434 memset((
void *)&statusFIFO, 0,
sizeof(statusFIFO));
438 new_management_ORB.status_FIFO.low = (u32)&statusFIFO;
439 new_management_ORB.flags = (u32)(ORB_NOTIFY | ORB_REQUEST_FORMAT(0) | MANAGEMENT_ORB_FUNCTION(mode));
442 case SBP2_LOGIN_REQUEST:
444 new_management_ORB.flags |= (u32)(MANAGEMENT_ORB_RECONNECT(0) | MANAGEMENT_ORB_EXCLUSIVE(1) | MANAGEMENT_ORB_LUN(dev->LUN));
446 new_management_ORB.login.response.low = (u32)&login_result;
447 new_management_ORB.length = (MANAGEMENT_ORB_RESPONSE_LENGTH(
sizeof(
struct sbp2_login_response)) | MANAGEMENT_ORB_PASSWORD_LENGTH(0));
450 case SBP2_RECONNECT_REQUEST:
451 new_management_ORB.flags |= (u32)(MANAGEMENT_ORB_RECONNECT(4) | MANAGEMENT_ORB_LOGINID(dev->loginID));
455 XPRINTF(
"Warning! Unsupported management ORB type!\n");
458 address.NodeID = dev->InitiatorNodeID;
460 address.low = (u32)&new_management_ORB;
462 XPRINTF(
"Management ORB: %p. size=%d.\n", &new_management_ORB,
sizeof(
struct management_ORB));
463 XPRINTF(
"Address pointer: %p\n", &address);
465 if ((result = iLinkTrWrite(dev->trContext, dev->ManagementAgent_high, dev->ManagementAgent_low, &address, 8)) < 0) {
466 XPRINTF(
"Error writing to the Management Agent CSR @ 0x%08lx %08lx. Code: %d.\n", dev->ManagementAgent_high, dev->ManagementAgent_low, result);
470 XPRINTF(
"Waiting for ILINK...\n");
472 result = ieee1394_Sync_withTimeout(dev->mgt_ORB_timeout);
474 XPRINTF(
"statusFIFO= %p; [0]=%u.\n", &statusFIFO, statusFIFO.buffer[0]);
477 case SBP2_LOGIN_REQUEST:
478 XPRINTF(
"Done. command_block_agent= 0x%08x %08lx.\n", login_result.command_block_agent.high, login_result.command_block_agent.low);
482 dev->CommandBlockAgent_high = login_result.command_block_agent.high;
483 dev->CommandBlockAgent_low = login_result.command_block_agent.low;
485 dev->loginID = login_result.login_ID;
487 XPRINTF(
"Login response size: %u.", login_result.length);
488 XPRINTF(
"Signed into SBP-2 device node 0x%08x. Login ID: %u\n", dev->nodeID, dev->loginID);
491 case SBP2_RECONNECT_REQUEST:
496 XPRINTF(
"Warning! Unsupported management ORB type!\n");
500 if ((dev->CommandBlockAgent_low < 0xF0010000) || ((dev->CommandBlockAgent_high & 0xFFFF) != 0x0000FFFF))
512 memset((
void *)&statusFIFO, 0,
sizeof(statusFIFO));
514 address.low = (u32)firstCDB;
515 address.NodeID = dev->InitiatorNodeID;
521 while ((result = iLinkTrWrite(dev->trContext, dev->CommandBlockAgent_high, dev->CommandBlockAgent_low + 0x08, &address, 8)) < 0) {
522 XPRINTF(
"Error writing to the Fetch Agent's ORB_POINTER register @ 0x%08lx %08lx. Code: %d.\n", dev->CommandBlockAgent_high, dev->CommandBlockAgent_low + 0x08, result);
525 ieee1394_ResetFetchAgent(dev);
535 if ((result = iLinkTrWrite(dev->trContext, dev->CommandBlockAgent_high, dev->CommandBlockAgent_low + 0x10, &result, 4)) < 0) {
536 XPRINTF(
"Error writing to the Fetch Agent's DOORBELL register @ 0x%08lx %08lx. Code: %d.\n", dev->CommandBlockAgent_high, dev->CommandBlockAgent_low + 0x10, result);
549static int ProcessStatus(
void)
551 u32 statusFIFO_result;
552 unsigned char status, resp, dead, sense, len;
555 statusFIFO_result = statusFIFO.status.status;
556 status = RESP_SBP_STATUS(statusFIFO_result);
557 resp = RESP_RESP(statusFIFO_result);
558 dead = RESP_DEAD(statusFIFO_result);
559 len = RESP_LEN(statusFIFO_result);
560 sense = ((statusFIFO.status.data[0]) >> 16) & 0xF;
562 XPRINTF(
"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);
566 result = (((status == 0) || (status == 0x0B)) && (resp == 0) && (!dead) && (len == 1)) ? 0 : -sense;
569 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);
576static inline int ieee1394_Sync_withTimeout(u32 n500mSecUnits)
594 while (RESP_SRC(statusFIFO.status.status) == 0) {
595 if (i > n500mSecUnits * 10000) {
596 XPRINTF(
"-=Time out=-\n");
604 return (ProcessStatus());
607int ieee1394_Sync(
void)
611 while (RESP_SRC(statusFIFO.status.status) == 0) {
615 return (ProcessStatus());
618void DeinitIEEE1394(
void)
620 TerminateThread(iLinkIntrCBThreadID);
621 DeleteThread(iLinkIntrCBThreadID);
622 DeleteEventFlag(sbp2_event_flag);
625void *malloc(
int NumBytes)
631 buffer = AllocSysMemory(ALLOC_FIRST, NumBytes, NULL);
637void free(
void *buffer)
642 FreeSysMemory(buffer);
int CpuResumeIntr(int state)
int CpuSuspendIntr(int *state)