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.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;
106 writeBuffer = malloc(XFER_BLOCK_SIZE);
108 sbp2_event_flag = CreateEventFlag(&evfp);
110 M_DEBUG(
"Starting threads..\n");
112 threadData.thread = &iLinkIntrCBHandlingThread;
113 iLinkIntrCBThreadID = CreateThread(&threadData);
114 StartThread(iLinkIntrCBThreadID, NULL);
116 iLinkSetTrCallbackHandler(&ieee1394_callback);
118 M_DEBUG(
"Threads created and started.\n");
123static int initConfigureSBP2Device(
struct SBP2Device *dev)
125 unsigned char retries;
130 if (ieee1394_SendManagementORB(SBP2_LOGIN_REQUEST, dev) >= 0)
137 DelayThread(200 * 1000);
141 M_DEBUG(
"Failed to log into the SBP-2 device.\n");
145 if (ieee1394_InitializeFetchAgent(dev) < 0) {
146 M_DEBUG(
"Error initializing the SBP-2 device's Fetch Agent.\n");
150 scsi_connect(&dev->scsi);
152 M_DEBUG(
"Completed device initialization.\n");
157static inline int initSBP2Disk(
struct SBP2Device *dev)
159 void *managementAgentAddr = NULL;
160 unsigned int ConfigurationROMOffset, DirectorySize, i, LeafData, UnitDirectoryOffset;
163 UnitDirectoryOffset = 0;
168 M_DEBUG(
"Reading configuration ROM for the unit directory offset of node 0x%08x\n", dev->nodeID);
171 ConfigurationROMOffset = 5;
173 if ((result = iLinkReadCROM(dev->nodeID, ConfigurationROMOffset, 1, &LeafData)) < 0) {
174 M_DEBUG(
"Error reading the configuration ROM. Error %d.\n", result);
178 ConfigurationROMOffset++;
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);
188 if ((LeafData >> 24) == IEEE1394_CROM_UNIT_DIRECTORY) {
189 UnitDirectoryOffset = ConfigurationROMOffset + (LeafData & 0x00FFFFFF);
193 ConfigurationROMOffset++;
195 if (i == DirectorySize)
198 if ((result = iLinkReadCROM(dev->nodeID, UnitDirectoryOffset, 1, &LeafData)) < 0) {
199 M_DEBUG(
"Error reading the configuration ROM. Error %d.\n", result);
203 DirectorySize = LeafData >> 16;
204 for (i = 0; i < DirectorySize; i++) {
206 if ((result = iLinkReadCROM(dev->nodeID, UnitDirectoryOffset + 1 + i, 1, &LeafData)) < 0) {
207 M_DEBUG(
"Error reading the configuration ROM. Error %d.\n", result);
211 switch (LeafData >> 24) {
213 case IEEE1394_CROM_CSR_OFFSET:
214 managementAgentAddr = (
void *)(LeafData & 0x00FFFFFF);
215 M_DEBUG(
"managementAgentAddr=0x%08lx.\n", (u32)managementAgentAddr * 4);
217 dev->ManagementAgent_low = (u32)managementAgentAddr * 4 + 0xf0000000;
218 dev->ManagementAgent_high = 0x0000ffff;
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);
225 case IEEE1394_CROM_LOGICAL_UNIT_NUM:
226 dev->LUN = LeafData & 0x0000FFFF;
227 M_DEBUG(
"LUN=0x%08x.\n", dev->LUN);
236static void iLinkIntrCBHandlingThread(
void *arg)
238 int nNodes, i, targetDeviceID, nodeID, result;
239 static const unsigned char PayloadSizeLookupTable[] = {
248 WaitEventFlag(sbp2_event_flag, BUS_RESET_COMPLETE, WEF_AND | WEF_CLEAR, NULL);
251 for (i = 0; i < MAX_DEVICES; i++) {
252 if (SBP2Devices[i].trContext >= 0) {
253 scsi_disconnect(&SBP2Devices[i].scsi);
255 iLinkTrFree(SBP2Devices[i].trContext);
256 SBP2Devices[i].trContext = -1;
260 if ((nNodes = iLinkGetNodeCount()) < 0) {
261 M_DEBUG(
"Critical error: Failure getting the number of nodes!\n");
264 M_PRINTF(
"BUS RESET DETECTED. Nodes: %d\n", nNodes);
265 M_PRINTF(
"Local Node: 0x%08x.\n", iLinkGetLocalNodeID());
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");
277 M_PRINTF(
"Attempting to initialize unit %d...\n", i);
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);
285 M_PRINTF(
"Detected SBP-2 device.\n");
287 SBP2Devices[targetDeviceID].InitiatorNodeID = iLinkGetLocalNodeID();
289 M_PRINTF(
"Local Node: 0x%08x.\n", SBP2Devices[targetDeviceID].InitiatorNodeID);
292 if (SBP2Devices[targetDeviceID].IsConnected) {
293 if (SBP2Devices[targetDeviceID].nodeID == nodeID) {
294 if (ieee1394_SendManagementORB(SBP2_RECONNECT_REQUEST, &SBP2Devices[i]) < 0) {
295 M_DEBUG(
"Error reconnecting to the SBP-2 device %u.\n", nodeID);
297 M_DEBUG(
"Successfully reconnected to SBP-2 device %u.", nodeID);
302 SBP2Devices[targetDeviceID].IsConnected = 0;
306 SBP2Devices[targetDeviceID].IsConnected = 0;
309 SBP2Devices[targetDeviceID].nodeID = nodeID;
310 if ((result = initSBP2Disk(&SBP2Devices[targetDeviceID])) < 0) {
311 M_DEBUG(
"Error initializing the device. Code: %d.\n", result);
315 SBP2Devices[targetDeviceID].trContext = iLinkTrAlloc(nodeID, iLinkGetNodeMaxSpeed(nodeID));
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());
321 SBP2Devices[targetDeviceID].speed = iLinkGetNodeTrSpeed(SBP2Devices[targetDeviceID].trContext);
322 M_PRINTF(
"Current speed: %d.\n", SBP2Devices[targetDeviceID].speed);
324 SBP2Devices[targetDeviceID].max_payload = PayloadSizeLookupTable[SBP2Devices[targetDeviceID].speed];
326 if (initConfigureSBP2Device(&SBP2Devices[targetDeviceID]) >= 0) {
327 SBP2Devices[targetDeviceID].IsConnected = 1;
331 M_DEBUG(
"Error allocating a transaction.\n");
335 for (; targetDeviceID < MAX_DEVICES; targetDeviceID++)
336 SBP2Devices[targetDeviceID].IsConnected = 0;
340static void ieee1394_ResetFetchAgent(
struct SBP2Device *dev)
342 unsigned long int dummy;
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);
351static int ieee1394_GetFetchAgentState(
struct SBP2Device *dev)
353 unsigned long int FetchAgentState;
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);
360 FetchAgentState = BSWAP32(FetchAgentState);
361 M_DEBUG(
"Fetch Agent state: %lu.\n", FetchAgentState);
362 return FetchAgentState;
366static int ieee1394_InitializeFetchAgent(
struct SBP2Device *dev)
372 M_DEBUG(
"Initializing fetch agent...");
374 dummy_ORB = malloc(dev->ORB_size * 4);
375 memset(dummy_ORB, 0, dev->ORB_size * 4);
377 ieee1394_ResetFetchAgent(dev);
380 address.low = (u32)dummy_ORB;
381 address.NodeID = dev->InitiatorNodeID;
386 ((
struct management_ORB *)dummy_ORB)->flags = (u32)(ORB_NOTIFY | ORB_REQUEST_FORMAT(3));
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);
398 result = ieee1394_Sync();
399 ieee1394_GetFetchAgentState(dev);
408static int ieee1394_SendManagementORB(
int mode,
struct SBP2Device *dev)
416 memset((
void *)&statusFIFO, 0,
sizeof(statusFIFO));
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));
424 case SBP2_LOGIN_REQUEST:
426 new_management_ORB.flags |= (u32)(MANAGEMENT_ORB_RECONNECT(0) | MANAGEMENT_ORB_EXCLUSIVE(1) | MANAGEMENT_ORB_LUN(dev->LUN));
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));
432 case SBP2_RECONNECT_REQUEST:
433 new_management_ORB.flags |= (u32)(MANAGEMENT_ORB_RECONNECT(4) | MANAGEMENT_ORB_LOGINID(dev->loginID));
437 M_DEBUG(
"Warning! Unsupported management ORB type!\n");
440 address.NodeID = dev->InitiatorNodeID;
442 address.low = (u32)&new_management_ORB;
444 M_DEBUG(
"Management ORB: %p. size=%d.\n", &new_management_ORB,
sizeof(
struct management_ORB));
445 M_DEBUG(
"Address pointer: %p\n", &address);
447 if ((result = iLinkTrWrite(dev->trContext, dev->ManagementAgent_high, dev->ManagementAgent_low, &address, 8)) < 0) {
448 M_DEBUG(
"Error writing to the Management Agent CSR @ 0x%08lx %08lx. Code: %d.\n", dev->ManagementAgent_high, dev->ManagementAgent_low, result);
452 M_DEBUG(
"Waiting for ILINK...\n");
454 result = ieee1394_Sync_withTimeout(dev->mgt_ORB_timeout);
456 M_DEBUG(
"statusFIFO= %p; [0]=%u.\n", &statusFIFO, statusFIFO.buffer[0]);
459 case SBP2_LOGIN_REQUEST:
460 M_DEBUG(
"Done. command_block_agent= 0x%08x %08lx.\n", login_result.command_block_agent.high, login_result.command_block_agent.low);
464 dev->CommandBlockAgent_high = login_result.command_block_agent.high;
465 dev->CommandBlockAgent_low = login_result.command_block_agent.low;
467 dev->loginID = login_result.login_ID;
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);
473 case SBP2_RECONNECT_REQUEST:
478 M_DEBUG(
"Warning! Unsupported management ORB type!\n");
482 if ((dev->CommandBlockAgent_low < 0xF0010000) || ((dev->CommandBlockAgent_high & 0xFFFF) != 0x0000FFFF))
494 memset((
void *)&statusFIFO, 0,
sizeof(statusFIFO));
496 address.low = (u32)firstCDB;
497 address.NodeID = dev->InitiatorNodeID;
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);
507 ieee1394_ResetFetchAgent(dev);
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);
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)
540 M_DEBUG(
"sbp2_queue_cmd(0x%02x)\n", cmd[0]);
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);
545 cdb.misc |= CDB_DATA_SIZE(data_len);
547 cdb.DataDescriptor.low = data_wr ? (u32)writeBuffer : (u32)data;
548 cdb.DataDescriptor.high = 0;
549 cdb.DataDescriptor.NodeID = dev->InitiatorNodeID;
551 cdb.NextOrb.high = 0;
553 cdb.NextOrb.reserved = NULL_POINTER;
556 for (i = 0; (
unsigned int)i < cmd_len / 4; i++)
557 ((
unsigned int *)cdb.CDBs)[i] = BSWAP32(((
unsigned int *)cmd)[i]);
559 if ((data_len > 0) && (data_wr == 1)) {
561 for (i = 0; (
unsigned int)i < data_len / 4; i++)
562 ((
unsigned int *)writeBuffer)[i] = BSWAP32(((
unsigned int *)data)[i]);
565 ieee1394_SendCommandBlockORB(dev, &cdb);
566 ret = ieee1394_Sync();
569 M_DEBUG(
"sbp2_queue_cmd error %d\n", ret);
570 }
else if ((data_len > 0) && (data_wr == 0)) {
572 for (i = 0; (
unsigned int)i < data_len / 4; i++)
573 ((
unsigned int *)data)[i] = BSWAP32(((
unsigned int *)data)[i]);
585static int ProcessStatus(
void)
587 u32 statusFIFO_result;
588 unsigned char status, resp, dead, sense, len;
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;
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);
602 result = (((status == 0) || (status == 0x0B)) && (resp == 0) && (!dead) && (len == 1)) ? 0 : -sense;
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);
612static inline int ieee1394_Sync_withTimeout(u32 n500mSecUnits)
630 while (RESP_SRC(statusFIFO.status.status) == 0) {
631 if (i > n500mSecUnits * 10000) {
632 M_DEBUG(
"-=Time out=-\n");
640 return (ProcessStatus());
643int ieee1394_Sync(
void)
647 while (RESP_SRC(statusFIFO.status.status) == 0) {
651 return (ProcessStatus());
654void DeinitIEEE1394(
void)
656 TerminateThread(iLinkIntrCBThreadID);
657 DeleteThread(iLinkIntrCBThreadID);
658 DeleteEventFlag(sbp2_event_flag);
661void *malloc(
int NumBytes)
667 buffer = AllocSysMemory(ALLOC_FIRST, NumBytes, NULL);
673void free(
void *buffer)
678 FreeSysMemory(buffer);
int CpuResumeIntr(int state)
int CpuSuspendIntr(int *state)