15#include "module_debug.h"
18static struct SBP2Device SBP2Devices[MAX_DEVICES];
19static u8 *writeBuffer = NULL;
31static int sbp2_event_flag;
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);
44 unsigned char buffer[32];
47static void ieee1394_callback(
int reason,
unsigned long int offset,
unsigned long int size)
53 iLinkBufferOffset = offset;
54 iLinkTransferSize = size;
56 if (reason == iLink_CB_WRITE_REQUEST) {
57 u32 statusFIFO_result;
61 if (iLinkBufferOffset == (u32)&statusFIFO) {
62 statusFIFO_result = statusFIFO.status.status;
63 if (RESP_SRC(statusFIFO_result) != 0)
64 SetEventFlag(sbp2_event_flag, WRITE_REQ_INCOMING);
68 if (reason == iLink_CB_BUS_RESET) {
69 SetEventFlag(sbp2_event_flag, BUS_RESET_COMPLETE);
85int iLinkIntrCBThreadID;
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);
89void init_ieee1394DiskDriver(
void)
93 for (i = 0; i < MAX_DEVICES; i++) {
94 SBP2Devices[i].IsConnected = 0;
95 SBP2Devices[i].nodeID = 0;
96 SBP2Devices[i].trContext = (-1);
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;
105 writeBuffer = malloc(XFER_BLOCK_SIZE);
107 sbp2_event_flag = CreateEventFlag(&evfp);
109 M_DEBUG(
"Starting threads..\n");
111 threadData.thread = &iLinkIntrCBHandlingThread;
112 iLinkIntrCBThreadID = CreateThread(&threadData);
113 StartThread(iLinkIntrCBThreadID, NULL);
115 iLinkSetTrCallbackHandler(&ieee1394_callback);
117 M_DEBUG(
"Threads created and started.\n");
122static int initConfigureSBP2Device(
struct SBP2Device *dev)
124 unsigned char retries;
129 if (ieee1394_SendManagementORB(SBP2_LOGIN_REQUEST, dev) >= 0)
136 DelayThread(200 * 1000);
140 M_DEBUG(
"Failed to log into the SBP-2 device.\n");
144 if (ieee1394_InitializeFetchAgent(dev) < 0) {
145 M_DEBUG(
"Error initializing the SBP-2 device's Fetch Agent.\n");
149 scsi_connect(&dev->scsi);
151 M_DEBUG(
"Completed device initialization.\n");
156static inline int initSBP2Disk(
struct SBP2Device *dev)
158 void *managementAgentAddr = NULL;
159 unsigned int ConfigurationROMOffset, DirectorySize, i, LeafData, UnitDirectoryOffset;
162 UnitDirectoryOffset = 0;
167 M_DEBUG(
"Reading configuration ROM for the unit directory offset of node 0x%08x\n", dev->nodeID);
170 ConfigurationROMOffset = 5;
172 if ((result = iLinkReadCROM(dev->nodeID, ConfigurationROMOffset, 1, &LeafData)) < 0) {
173 M_DEBUG(
"Error reading the configuration ROM. Error %d.\n", result);
177 ConfigurationROMOffset++;
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);
187 if ((LeafData >> 24) == IEEE1394_CROM_UNIT_DIRECTORY) {
188 UnitDirectoryOffset = ConfigurationROMOffset + (LeafData & 0x00FFFFFF);
192 ConfigurationROMOffset++;
194 if (i == DirectorySize)
197 if ((result = iLinkReadCROM(dev->nodeID, UnitDirectoryOffset, 1, &LeafData)) < 0) {
198 M_DEBUG(
"Error reading the configuration ROM. Error %d.\n", result);
202 DirectorySize = LeafData >> 16;
203 for (i = 0; i < DirectorySize; i++) {
205 if ((result = iLinkReadCROM(dev->nodeID, UnitDirectoryOffset + 1 + i, 1, &LeafData)) < 0) {
206 M_DEBUG(
"Error reading the configuration ROM. Error %d.\n", result);
210 switch (LeafData >> 24) {
212 case IEEE1394_CROM_CSR_OFFSET:
213 managementAgentAddr = (
void *)(LeafData & 0x00FFFFFF);
214 M_DEBUG(
"managementAgentAddr=0x%08lx.\n", (u32)managementAgentAddr * 4);
216 dev->ManagementAgent_low = (u32)managementAgentAddr * 4 + 0xf0000000;
217 dev->ManagementAgent_high = 0x0000ffff;
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);
224 case IEEE1394_CROM_LOGICAL_UNIT_NUM:
225 dev->LUN = LeafData & 0x0000FFFF;
226 M_DEBUG(
"LUN=0x%08x.\n", dev->LUN);
235static void iLinkIntrCBHandlingThread(
void *arg)
237 int nNodes, i, targetDeviceID, nodeID, result;
238 static const unsigned char PayloadSizeLookupTable[] = {
247 WaitEventFlag(sbp2_event_flag, BUS_RESET_COMPLETE, WEF_AND | WEF_CLEAR, NULL);
250 for (i = 0; i < MAX_DEVICES; i++) {
251 if (SBP2Devices[i].trContext >= 0) {
252 scsi_disconnect(&SBP2Devices[i].scsi);
254 iLinkTrFree(SBP2Devices[i].trContext);
255 SBP2Devices[i].trContext = -1;
259 if ((nNodes = iLinkGetNodeCount()) < 0) {
260 M_DEBUG(
"Critical error: Failure getting the number of nodes!\n");
263 M_PRINTF(
"BUS RESET DETECTED. Nodes: %d\n", nNodes);
264 M_PRINTF(
"Local Node: 0x%08x.\n", iLinkGetLocalNodeID());
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");
276 M_PRINTF(
"Attempting to initialize unit %d...\n", i);
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);
284 M_PRINTF(
"Detected SBP-2 device.\n");
286 SBP2Devices[targetDeviceID].InitiatorNodeID = iLinkGetLocalNodeID();
288 M_PRINTF(
"Local Node: 0x%08x.\n", SBP2Devices[targetDeviceID].InitiatorNodeID);
291 if (SBP2Devices[targetDeviceID].IsConnected) {
292 if (SBP2Devices[targetDeviceID].nodeID == nodeID) {
293 if (ieee1394_SendManagementORB(SBP2_RECONNECT_REQUEST, &SBP2Devices[i]) < 0) {
294 M_DEBUG(
"Error reconnecting to the SBP-2 device %u.\n", nodeID);
296 M_DEBUG(
"Successfully reconnected to SBP-2 device %u.", nodeID);
301 SBP2Devices[targetDeviceID].IsConnected = 0;
305 SBP2Devices[targetDeviceID].IsConnected = 0;
308 SBP2Devices[targetDeviceID].nodeID = nodeID;
309 if ((result = initSBP2Disk(&SBP2Devices[targetDeviceID])) < 0) {
310 M_DEBUG(
"Error initializing the device. Code: %d.\n", result);
314 SBP2Devices[targetDeviceID].trContext = iLinkTrAlloc(nodeID, iLinkGetNodeMaxSpeed(nodeID));
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());
320 SBP2Devices[targetDeviceID].speed = iLinkGetNodeTrSpeed(SBP2Devices[targetDeviceID].trContext);
321 M_PRINTF(
"Current speed: %d.\n", SBP2Devices[targetDeviceID].speed);
323 SBP2Devices[targetDeviceID].max_payload = PayloadSizeLookupTable[SBP2Devices[targetDeviceID].speed];
325 if (initConfigureSBP2Device(&SBP2Devices[targetDeviceID]) >= 0) {
326 SBP2Devices[targetDeviceID].IsConnected = 1;
330 M_DEBUG(
"Error allocating a transaction.\n");
334 for (; targetDeviceID < MAX_DEVICES; targetDeviceID++)
335 SBP2Devices[targetDeviceID].IsConnected = 0;
339static void ieee1394_ResetFetchAgent(
struct SBP2Device *dev)
341 unsigned long int dummy;
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);
350static int ieee1394_GetFetchAgentState(
struct SBP2Device *dev)
352 unsigned long int FetchAgentState;
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);
359 FetchAgentState = BSWAP32(FetchAgentState);
360 M_DEBUG(
"Fetch Agent state: %lu.\n", FetchAgentState);
361 return FetchAgentState;
365static int ieee1394_InitializeFetchAgent(
struct SBP2Device *dev)
371 M_DEBUG(
"Initializing fetch agent...");
373 dummy_ORB = malloc(dev->ORB_size * 4);
374 memset(dummy_ORB, 0, dev->ORB_size * 4);
376 ieee1394_ResetFetchAgent(dev);
379 address.low = (u32)dummy_ORB;
380 address.NodeID = dev->InitiatorNodeID;
385 ((
struct management_ORB *)dummy_ORB)->flags = (u32)(ORB_NOTIFY | ORB_REQUEST_FORMAT(3));
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);
397 result = ieee1394_Sync();
398 ieee1394_GetFetchAgentState(dev);
407static int ieee1394_SendManagementORB(
int mode,
struct SBP2Device *dev)
415 memset((
void *)&statusFIFO, 0,
sizeof(statusFIFO));
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));
423 case SBP2_LOGIN_REQUEST:
425 new_management_ORB.flags |= (u32)(MANAGEMENT_ORB_RECONNECT(0) | MANAGEMENT_ORB_EXCLUSIVE(1) | MANAGEMENT_ORB_LUN(dev->LUN));
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));
431 case SBP2_RECONNECT_REQUEST:
432 new_management_ORB.flags |= (u32)(MANAGEMENT_ORB_RECONNECT(4) | MANAGEMENT_ORB_LOGINID(dev->loginID));
436 M_DEBUG(
"Warning! Unsupported management ORB type!\n");
439 address.NodeID = dev->InitiatorNodeID;
441 address.low = (u32)&new_management_ORB;
443 M_DEBUG(
"Management ORB: %p. size=%d.\n", &new_management_ORB,
sizeof(
struct management_ORB));
444 M_DEBUG(
"Address pointer: %p\n", &address);
446 if ((result = iLinkTrWrite(dev->trContext, dev->ManagementAgent_high, dev->ManagementAgent_low, &address, 8)) < 0) {
447 M_DEBUG(
"Error writing to the Management Agent CSR @ 0x%08lx %08lx. Code: %d.\n", dev->ManagementAgent_high, dev->ManagementAgent_low, result);
451 M_DEBUG(
"Waiting for ILINK...\n");
453 result = ieee1394_Sync_withTimeout(dev->mgt_ORB_timeout);
455 M_DEBUG(
"statusFIFO= %p; [0]=%u.\n", &statusFIFO, statusFIFO.buffer[0]);
458 case SBP2_LOGIN_REQUEST:
459 M_DEBUG(
"Done. command_block_agent= 0x%08x %08lx.\n", login_result.command_block_agent.high, login_result.command_block_agent.low);
463 dev->CommandBlockAgent_high = login_result.command_block_agent.high;
464 dev->CommandBlockAgent_low = login_result.command_block_agent.low;
466 dev->loginID = login_result.login_ID;
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);
472 case SBP2_RECONNECT_REQUEST:
477 M_DEBUG(
"Warning! Unsupported management ORB type!\n");
481 if ((dev->CommandBlockAgent_low < 0xF0010000) || ((dev->CommandBlockAgent_high & 0xFFFF) != 0x0000FFFF))
493 memset((
void *)&statusFIFO, 0,
sizeof(statusFIFO));
495 address.low = (u32)firstCDB;
496 address.NodeID = dev->InitiatorNodeID;
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);
506 ieee1394_ResetFetchAgent(dev);
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);
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)
539 M_DEBUG(
"sbp2_queue_cmd(0x%02x)\n", cmd[0]);
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);
544 cdb.misc |= CDB_DATA_SIZE(data_len);
546 cdb.DataDescriptor.low = data_wr ? (u32)writeBuffer : (u32)data;
547 cdb.DataDescriptor.high = 0;
548 cdb.DataDescriptor.NodeID = dev->InitiatorNodeID;
550 cdb.NextOrb.high = 0;
552 cdb.NextOrb.reserved = NULL_POINTER;
555 for (i = 0; (
unsigned int)i < cmd_len / 4; i++)
556 ((
unsigned int *)cdb.CDBs)[i] = BSWAP32(((
unsigned int *)cmd)[i]);
558 if ((data_len > 0) && (data_wr == 1)) {
560 for (i = 0; (
unsigned int)i < data_len / 4; i++)
561 ((
unsigned int *)writeBuffer)[i] = BSWAP32(((
unsigned int *)data)[i]);
564 ieee1394_SendCommandBlockORB(dev, &cdb);
565 ret = ieee1394_Sync();
568 M_DEBUG(
"sbp2_queue_cmd error %d\n", ret);
569 }
else if ((data_len > 0) && (data_wr == 0)) {
571 for (i = 0; (
unsigned int)i < data_len / 4; i++)
572 ((
unsigned int *)data)[i] = BSWAP32(((
unsigned int *)data)[i]);
584static int ProcessStatus(
void)
586 u32 statusFIFO_result;
587 unsigned char status, resp, dead, sense, len;
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;
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);
601 result = (((status == 0) || (status == 0x0B)) && (resp == 0) && (!dead) && (len == 1)) ? 0 : -sense;
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);
611static inline int ieee1394_Sync_withTimeout(u32 n500mSecUnits)
629 while (RESP_SRC(statusFIFO.status.status) == 0) {
630 if (i > n500mSecUnits * 10000) {
631 M_DEBUG(
"-=Time out=-\n");
639 return (ProcessStatus());
642int ieee1394_Sync(
void)
646 while (RESP_SRC(statusFIFO.status.status) == 0) {
650 return (ProcessStatus());
653void DeinitIEEE1394(
void)
655 TerminateThread(iLinkIntrCBThreadID);
656 DeleteThread(iLinkIntrCBThreadID);
657 DeleteEventFlag(sbp2_event_flag);
660void *malloc(
int NumBytes)
666 buffer = AllocSysMemory(ALLOC_FIRST, NumBytes, NULL);
672void free(
void *buffer)
677 FreeSysMemory(buffer);
int CpuResumeIntr(int state)
int CpuSuspendIntr(int *state)