static int scsiTestUnitReady(struct SBP2Device* dev){ struct CommandDescriptorBlock cdb; XPRINTF("IEEE1394_disk: scsiTestUnitReady.\n"); cdb.misc=(u32)(ORB_NOTIFY | ORB_REQUEST_FORMAT(0) | CDB_MAX_PAYLOAD(dev->max_payload) | CDB_DIRECTION(WRITE_TRANSACTION) | CDB_SPEED(dev->speed)); cdb.DataDescriptor.low=cdb.DataDescriptor.high=0; cdb.DataDescriptor.NodeID=dev->InitiatorNodeID; cdb.NextOrb.high=cdb.NextOrb.low=0; cdb.NextOrb.reserved=NULL_POINTER; //scsi command packet cdb.CDBs[3] = 0x00; //test unit ready operation code cdb.CDBs[2] = 0; //reserved cdb.CDBs[1] = 0; //reserved cdb.CDBs[0] = 0; //reserved cdb.CDBs[7] = 0; //reserved cdb.CDBs[6] = 0; //reserved cdb.CDBs[5] = 0; //reserved cdb.CDBs[4] = 0; //reserved cdb.CDBs[11] = 0; //reserved cdb.CDBs[10] = 0; //reserved cdb.CDBs[9] = 0; //reserved cdb.CDBs[8] = 0; //reserved ieee1394_SendCommandBlockORB(dev, &cdb); return(ieee1394_Sync()); }
static int scsiReadCapacity(struct SBP2Device* dev, void *buffer, int size) { struct CommandDescriptorBlock cdb; XPRINTF("IEEE1394_disk: scsiReadCapacity.\n"); cdb.misc=(ORB_NOTIFY | ORB_REQUEST_FORMAT(0) | CDB_MAX_PAYLOAD(dev->max_payload) | CDB_DIRECTION(WRITE_TRANSACTION) | CDB_SPEED(dev->speed) | CDB_DATA_SIZE(size)); cdb.DataDescriptor.low=(u32)buffer; cdb.DataDescriptor.high=0; cdb.DataDescriptor.NodeID=dev->InitiatorNodeID; cdb.NextOrb.high=cdb.NextOrb.low=0; cdb.NextOrb.reserved=NULL_POINTER; //scsi command packet cdb.CDBs[3] = 0x25; //read capacity operation code cdb.CDBs[2] = 0; //reserved cdb.CDBs[1] = 0; //LBA 1 cdb.CDBs[0] = 0; //LBA 2 cdb.CDBs[7] = 0; //LBA 3 cdb.CDBs[6] = 0; //LBA 4 cdb.CDBs[5] = 0; //Reserved cdb.CDBs[4] = 0; //Reserved cdb.CDBs[11] = 0; //Reserved cdb.CDBs[10] = 0; //reserved cdb.CDBs[9] = 0; //reserved cdb.CDBs[8] = 0; //reserved ieee1394_SendCommandBlockORB(dev, &cdb); return(ieee1394_Sync()); }
static int scsiStartStopUnit(struct SBP2Device* dev) { struct CommandDescriptorBlock cdb; XPRINTF("IEEE1394_disk: scsiStartStopUnit.\n"); cdb.misc=(ORB_NOTIFY | ORB_REQUEST_FORMAT(0) | CDB_MAX_PAYLOAD(dev->max_payload) | CDB_DIRECTION(WRITE_TRANSACTION) | CDB_SPEED(dev->speed)); cdb.DataDescriptor.low=cdb.DataDescriptor.high=0; cdb.DataDescriptor.NodeID=dev->InitiatorNodeID; cdb.NextOrb.high=cdb.NextOrb.low=0; cdb.NextOrb.reserved=NULL_POINTER; //scsi command packet cdb.CDBs[3] = 0x1B; //start stop unit operation code cdb.CDBs[2] = 1; //reserved/immed cdb.CDBs[1] = 0; //reserved cdb.CDBs[0] = 0; //reserved cdb.CDBs[7] = 1; //POWER CONDITIONS/reserved/LoEj/Start "Start the media and acquire the format type" cdb.CDBs[6] = 0; //reserved cdb.CDBs[5] = 0; //reserved cdb.CDBs[4] = 0; //reserved cdb.CDBs[11] = 0; //reserved cdb.CDBs[10] = 0; //reserved cdb.CDBs[9] = 0; //reserved cdb.CDBs[8] = 0; //reserved ieee1394_SendCommandBlockORB(dev, &cdb); return(ieee1394_Sync()); }
static int scsiInquiry(struct SBP2Device* dev, void *buffer, int size) { int ret; struct CommandDescriptorBlock cdb; unsigned int i; XPRINTF("IEEE1394_disk: scsiInquiry. buffer: %p\n", buffer); cdb.misc=(ORB_NOTIFY | ORB_REQUEST_FORMAT(0) | CDB_MAX_PAYLOAD(dev->max_payload) | CDB_DIRECTION(WRITE_TRANSACTION) | CDB_SPEED(dev->speed) | CDB_DATA_SIZE(size)); cdb.DataDescriptor.low=(u32)buffer; cdb.DataDescriptor.high=0; cdb.DataDescriptor.NodeID=dev->InitiatorNodeID; cdb.NextOrb.high=cdb.NextOrb.low=0; cdb.NextOrb.reserved=NULL_POINTER; //scsi command packet cdb.CDBs[3] = 0x12; //inquiry operation code cdb.CDBs[2] = 0; //reserved cdb.CDBs[1] = 0; //page code cdb.CDBs[0] = 0; //reserved cdb.CDBs[7] = size; //inquiry reply length cdb.CDBs[6] = 0; //reserved cdb.CDBs[5] = 0; //reserved cdb.CDBs[4] = 0; //reserved cdb.CDBs[11] = 0; //reserved cdb.CDBs[10] = 0; //reserved cdb.CDBs[9] = 0; //reserved cdb.CDBs[8] = 0; //reserved ieee1394_SendCommandBlockORB(dev, &cdb); ret=ieee1394_Sync(); if(ret != 0) XPRINTF("IEEE1394_disk: scsiInquiry error %d\n", ret); else{ for(i=0; i<size/4; i++) ((unsigned int *)buffer)[i]=BSWAP32(((unsigned int *)buffer)[i]); } return ret; }
static int ieee1394_InitializeFetchAgent(struct SBP2Device *dev){ int result, retries; void *dummy_ORB; struct sbp2_pointer address; XPRINTF("Initializing fetch agent..."); dummy_ORB=malloc(dev->ORB_size*4); memset(dummy_ORB, 0, dev->ORB_size*4); ieee1394_ResetFetchAgent(dev); /* Write the address of the dummy ORB to the fetch agent's ORB_POINTER register. */ address.low=(u32)dummy_ORB; address.NodeID=dev->InitiatorNodeID; address.high=0; ((struct sbp2_ORB_pointer *)dummy_ORB)->reserved=NULL_POINTER; ((struct sbp2_ORB_pointer *)dummy_ORB)->high=((struct sbp2_ORB_pointer *)dummy_ORB)->low=0; ((struct management_ORB *)dummy_ORB)->flags=(u32)(ORB_NOTIFY|ORB_REQUEST_FORMAT(3)); retries=0; while((result=iLinkTrWrite(dev->trContext, dev->CommandBlockAgent_high, dev->CommandBlockAgent_low+0x08, &address, 8))<0){ 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); ieee1394_ResetFetchAgent(dev); retries++; if(retries>3) return(-1); } result=ieee1394_Sync(); ieee1394_GetFetchAgentState(dev); free(dummy_ORB); XPRINTF("done!\n"); return 1; }
static int scsiRequestSense(struct SBP2Device* dev, void *buffer, int size) { int ret; struct CommandDescriptorBlock cdb; XPRINTF("IEEE1394_disk: scsiRequestSense.\n"); cdb.misc=(ORB_NOTIFY | ORB_REQUEST_FORMAT(0) | CDB_MAX_PAYLOAD(dev->max_payload) | CDB_DIRECTION(WRITE_TRANSACTION) | CDB_SPEED(dev->speed) | CDB_DATA_SIZE(size)); cdb.DataDescriptor.low=(u32)buffer; cdb.DataDescriptor.high=0; cdb.DataDescriptor.NodeID=dev->InitiatorNodeID; cdb.NextOrb.high=cdb.NextOrb.low=0; cdb.NextOrb.reserved=NULL_POINTER; //scsi command packet cdb.CDBs[3] = 0x03; //request sense operation code cdb.CDBs[2] = 0; //reserved cdb.CDBs[1] = 0; //reserved cdb.CDBs[0] = 0; //reserved cdb.CDBs[7] = size; //allocation length cdb.CDBs[6] = 0; //reserved cdb.CDBs[5] = 0; //reserved cdb.CDBs[4] = 0; //reserved cdb.CDBs[11] = 0; //reserved cdb.CDBs[10] = 0; //reserved cdb.CDBs[9] = 0; //reserved cdb.CDBs[8] = 0; //reserved ieee1394_SendCommandBlockORB(dev, &cdb); ret=ieee1394_Sync(); if(ret!=0) XPRINTF("IEEE1394_disk: scsiRequestSense error: %d\n", ret); return ret; }
static int ieee1394_SendManagementORB(int mode, struct SBP2Device *dev){ int result; struct sbp2_pointer address; struct sbp2_login_response login_result; struct management_ORB new_management_ORB; memset((unsigned char *)statusFIFO, 0, sizeof(statusFIFO)); memset(&login_result, 0, sizeof(struct sbp2_login_response)); memset(&new_management_ORB, 0, sizeof(struct management_ORB)); new_management_ORB.status_FIFO.low=(u32)statusFIFO; ((struct login_req *)&new_management_ORB)->flags=(u32)(ORB_NOTIFY | ORB_REQUEST_FORMAT(0) |MANAGEMENT_ORB_FUNCTION(mode)); switch(mode){ case SBP2_LOGIN_REQUEST: /* Login. */ /* 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. */ ((struct login_req *)&new_management_ORB)->flags|=(u32)(MANAGEMENT_ORB_RECONNECT(0) | MANAGEMENT_ORB_EXCLUSIVE(1) | MANAGEMENT_ORB_LUN(dev->LUN)); ((struct login_req *)&new_management_ORB)->login_response.low=(u32)&login_result; ((struct login_req *)&new_management_ORB)->length=(MANAGEMENT_ORB_RESPONSE_LENGTH(sizeof(struct sbp2_login_response))|MANAGEMENT_ORB_PASSWORD_LENGTH(0)); break; #if 0 case SBP2_RECONNECT_REQUEST: /* Reconnect. */ ((struct login_req *)&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. :( */ break; #endif default: XPRINTF("Warning! Unsupported management ORB type!\n"); } address.NodeID=dev->InitiatorNodeID; address.high=0; address.low=(u32)&new_management_ORB; XPRINTF("Management ORB: %p. size=%d.\n", &new_management_ORB, sizeof(struct management_ORB)); XPRINTF("Address pointer: %p\n", &address); 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. */ XPRINTF("Error writing to the Management Agent CSR @ 0x%08lx %08lx. Code: %d.\n", dev->ManagementAgent_high, dev->ManagementAgent_low, result); return(result); } XPRINTF("Waiting for ILINK...\n"); result=ieee1394_Sync_withTimeout(dev->mgt_ORB_timeout); XPRINTF("statusFIFO= %p; [0]=%u.\n", statusFIFO, statusFIFO[0]); if(result>=0){ switch(mode){ case SBP2_LOGIN_REQUEST: /* Login. */ XPRINTF("Done. command_block_agent= 0x%08x %08lx.\n", login_result.command_block_agent.high, login_result.command_block_agent.low); /* Store the address to the target's command block agent. */ dev->CommandBlockAgent_high=login_result.command_block_agent.high; dev->CommandBlockAgent_low=login_result.command_block_agent.low; dev->loginID=login_result.login_ID; /* Store the login ID. */ XPRINTF("Login response size: %u.", login_result.length); XPRINTF("Signed into SBP-2 device node 0x%08x. Login ID: %u\n", dev->nodeID, dev->loginID); break; #if 0 case SBP2_RECONNECT_REQUEST: /* Reconnect. */ /* Just return the result from ieee1394_Sync(). */ break; #endif default: XPRINTF("Warning! Unsupported management ORB type!\n"); } /* Validate the fetch agent's CSR address. */ if((dev->CommandBlockAgent_low<0xF0010000)||((dev->CommandBlockAgent_high&0xFFFF)!=0x0000FFFF)) result=(-1); } return result; }
int scsiWriteSector(struct SBP2Device *dev, unsigned long int lba, void* buffer, int sectorCount) { unsigned int nOrbs, OrbsRemaining, i, sectorsToRead, sectorsRemaining, SectorsPerBlock; unsigned long int startingLBA; void *bufferPtr; int result, max_payload; XPRINTF("IEEE1394_disk: scsiWriteSector.\n"); SectorsPerBlock=XFER_BLOCK_SIZE/dev->sectorSize; OrbsRemaining=sectorCount/SectorsPerBlock; if((sectorCount%SectorsPerBlock)!=0) OrbsRemaining++; startingLBA=lba; sectorsRemaining=sectorCount; bufferPtr=buffer; max_payload=(dev->max_payload>7)?7:dev->max_payload; /* Do not allow the maximum payload to exceed 512 bytes (Actually, is this necessary?). */ result=0; for(; (OrbsRemaining>0) && (result==0); OrbsRemaining-=nOrbs){ nOrbs=(OrbsRemaining>MAX_ORBS)?MAX_ORBS:OrbsRemaining; for(i=0; i<nOrbs; i++){ sectorsToRead=(sectorsRemaining>SectorsPerBlock)?SectorsPerBlock:sectorsRemaining; cdb[i].misc=(ORB_NOTIFY | ORB_REQUEST_FORMAT(0) | CDB_MAX_PAYLOAD(max_payload) | CDB_DIRECTION(READ_TRANSACTION) | CDB_SPEED(dev->speed) | CDB_DATA_SIZE((dev->sectorSize * sectorsToRead))); cdb[i].DataDescriptor.low=(u32)bufferPtr; cdb[i].DataDescriptor.high=0; cdb[i].DataDescriptor.NodeID=dev->InitiatorNodeID; if(i>0){ cdb[i-1].NextOrb.high=0; cdb[i-1].NextOrb.low=(u32)&cdb[i]; cdb[i-1].NextOrb.reserved=0; } //scsi command packet cdb[i].CDBs[3] = 0x2A; //write operation code cdb[i].CDBs[2] = 0; //Reserved cdb[i].CDBs[1] = (startingLBA & 0xFF000000) >> 24; //lba 1 (MSB) cdb[i].CDBs[0] = (startingLBA & 0xFF0000) >> 16; //lba 2 cdb[i].CDBs[7] = (startingLBA & 0xFF00) >> 8; //lba 3 cdb[i].CDBs[6] = (startingLBA & 0xFF); //lba 4 (LSB) cdb[i].CDBs[5] = 0; //Reserved cdb[i].CDBs[4] = (sectorsToRead & 0xFF00) >> 8; //Transfer length MSB cdb[i].CDBs[11] = (sectorsToRead & 0xFF); //Transfer length LSB cdb[i].CDBs[10] = 0; //reserved cdb[i].CDBs[9] = 0; //reserved cdb[i].CDBs[8] = 0; //reserved startingLBA+=sectorsToRead; sectorsRemaining-=sectorsToRead; bufferPtr+=dev->sectorSize * sectorsToRead; } /* NULL terminate the last ORB. */ cdb[i-1].NextOrb.high=cdb[i-1].NextOrb.low=0; cdb[i-1].NextOrb.reserved=NULL_POINTER; ieee1394_SendCommandBlockORB(dev, cdb); result=ieee1394_Sync(); } return result; }
int scsiReadSector(struct SBP2Device *dev, unsigned long int lba, void *buffer, int sectorCount) { unsigned int nOrbs, OrbsRemaining, i, sectorsToRead, sectorsRemaining, SectorsPerBlock, BlockNum; unsigned long int startingLBA; void *bufferPtr, *PreviousReqBufferPtr; int result; XPRINTF("IEEE1394_disk: scsiReadSector. buffer: %p, lba: 0x%08lx, numsectors: %d.\n", buffer, lba, sectorCount); SectorsPerBlock=XFER_BLOCK_SIZE/dev->sectorSize; OrbsRemaining=sectorCount/SectorsPerBlock; if((sectorCount%SectorsPerBlock)!=0) OrbsRemaining++; XPRINTF("NumOrbs=%d cdb: %p.\n", OrbsRemaining, cdb); startingLBA=lba; sectorsRemaining=sectorCount; bufferPtr=buffer; result=0; for(PreviousReqBufferPtr=NULL, BlockNum=0, sectorsToRead=0; (OrbsRemaining>0) && (result==0); OrbsRemaining-=nOrbs, BlockNum++){ nOrbs=(OrbsRemaining>MAX_ORBS)?MAX_ORBS:OrbsRemaining; if(BlockNum>0){ /* While waiting for the read request that was just sent to be processed, byte-swap the previously read in data. */ for(i=0; i<sectorsToRead<<7; i++) ((unsigned int *)PreviousReqBufferPtr)[i]=BSWAP32(((unsigned int *)PreviousReqBufferPtr)[i]); result=ieee1394_Sync(); /* Only sync if a read request is being processed. Otherwise, it'll wait eternally.. */ } /* Save the current pointer to the buffer, so that the code above can byte-swap the payload of the request below that will be read in, when this loop loops around. */ PreviousReqBufferPtr=bufferPtr; for(i=0; i<nOrbs; i++){ sectorsToRead=(sectorsRemaining>SectorsPerBlock)?SectorsPerBlock:sectorsRemaining; cdb[i].misc=(ORB_NOTIFY | ORB_REQUEST_FORMAT(0) | CDB_MAX_PAYLOAD(dev->max_payload) | CDB_DIRECTION(WRITE_TRANSACTION) | CDB_SPEED(dev->speed) | CDB_DATA_SIZE((dev->sectorSize * sectorsToRead))); cdb[i].DataDescriptor.low=(u32)bufferPtr; cdb[i].DataDescriptor.high=0; cdb[i].DataDescriptor.NodeID=dev->InitiatorNodeID; if(i>0){ cdb[i-1].NextOrb.high=0; cdb[i-1].NextOrb.low=(u32)&cdb[i]; cdb[i-1].NextOrb.reserved=0; } //scsi command packet cdb[i].CDBs[3] = 0x28; //read operation code cdb[i].CDBs[2] = 0; //Reserved cdb[i].CDBs[1] = (startingLBA & 0xFF000000) >> 24; //lba 1 (MSB) cdb[i].CDBs[0] = (startingLBA & 0xFF0000) >> 16; //lba 2 cdb[i].CDBs[7] = (startingLBA & 0xFF00) >> 8; //lba 3 cdb[i].CDBs[6] = (startingLBA & 0xFF); //lba 4 (LSB) cdb[i].CDBs[5] = 0; //Reserved cdb[i].CDBs[4] = (sectorsToRead & 0xFF00) >> 8; //Transfer length MSB cdb[i].CDBs[11] = (sectorsToRead & 0xFF); //Transfer length LSB cdb[i].CDBs[10] = 0; //reserved cdb[i].CDBs[9] = 0; //reserved cdb[i].CDBs[8] = 0; //reserved startingLBA+=sectorsToRead; sectorsRemaining-=sectorsToRead; bufferPtr+=dev->sectorSize * sectorsToRead; } /* NULL terminate the last ORB. */ cdb[i-1].NextOrb.high=cdb[i-1].NextOrb.low=0; cdb[i-1].NextOrb.reserved=NULL_POINTER; ieee1394_SendCommandBlockORB(dev, cdb); } /* Sync and byte-swap the last block. */ result=ieee1394_Sync(); for(i=0; i<sectorsToRead<<7; i++) ((unsigned int *)PreviousReqBufferPtr)[i]=BSWAP32(((unsigned int *)PreviousReqBufferPtr)[i]); XPRINTF("IEEE1394_disk: scsiReadSector done.\n"); return result; }