void sgd_test() { sgd_tbl_t SgTbl1 = {0,}; sgd_tbl_t SgTbl2 = {0,}; sgd_tbl_t SgTbl3 = {0,}; sgd_t Entries1[32]; sgd_t Entries2[32]; sgd_t Entries3[32]; SgTbl1.Max_Entry_Count = sizeof(Entries1)/sizeof(Entries1[0]); SgTbl1.Entry_Ptr = Entries1; SgTbl2.Max_Entry_Count = sizeof(Entries2)/sizeof(Entries2[0]); SgTbl2.Entry_Ptr = Entries2; SgTbl3.Max_Entry_Count = sizeof(Entries3)/sizeof(Entries3[0]); SgTbl3.Entry_Ptr = Entries3; int i; for( i = 0; i < 32; i++ ) { sgdt_append( &SgTbl2, 0x80000000+i*0x1000, 0x90000000, 0x1000 ); } sgdt_dump( &SgTbl2, " " ); sgdt_append_reftbl( &SgTbl1, &SgTbl2, 0x3800, 0x1000*10 ); sgdt_append_virtual( &SgTbl1, (MV_PVOID)0x40000, (MV_PVOID)0x60000, 0x1000*10 ); sgdt_append_vp( &SgTbl1, (MV_PVOID)0x80000, 0x1000*10, 0x4000, 0 ); sgdt_dump( &SgTbl1, " " ); MV_PRINT( "Walking through the table:\n" ); MV_U32 index = 0; sgd_table_walk( &SgTbl1, SgVisitor, &index ); sgd_iter_t iter; sgd_t sg[2]; sgd_iter_init( &iter, SgTbl1.Entry_Ptr, 0, SgTbl1.Byte_Count ); MV_PRINT( "Walking through the table in another way:\n" ); i = 0; while( sgd_iter_get_next( &iter, sg ) ) { sgd_dump( sg, NULL ); } sgdt_dump( &SgTbl1, " " ); sgd_t* sgd = SgTbl1.Entry_Ptr; MV_U32 off = 0x1000; sgdt_copy_partial( &SgTbl3, &sgd, &off, 0x1000 ); sgdt_copy_partial( &SgTbl3, &sgd, &off, 0x9000 ); sgdt_copy_partial( &SgTbl3, &sgd, &off, 0x9000 ); sgdt_copy_partial( &SgTbl3, &sgd, &off, 0x1000 ); sgdt_copy_partial( &SgTbl3, &sgd, &off, 0x1000 ); sgdt_dump( &SgTbl3, " " ); }
/***************************************************************************** * * mv_phyCheckStatusChange -- checks for significant changes in PHY state. * * A "significant change" is: * dropped link (e.g. ethernet cable unplugged) OR * autonegotiation completed + link (e.g. ethernet cable plugged in) */ void mv_phyCheckStatusChange(int ethUnit) { int phyUnit; UINT16 phyHwStatus; mvPhyInfo_t *lastStatus; int linkCount = 0; int lostLinks = 0; int gainedLinks = 0; UINT32 phyBase; UINT32 phyAddr; for (phyUnit=0; phyUnit < MV_PHY_MAX; phyUnit++) { if (!MV_IS_ETHUNIT(phyUnit, ethUnit)) { continue; } phyBase = MV_PHYBASE(phyUnit); phyAddr = MV_PHYADDR(phyUnit); lastStatus = &mvPhyInfo[phyUnit]; phyHwStatus = phyRegRead(phyBase, phyAddr, MV_PHY_SPECIFIC_STATUS); if (lastStatus->isPhyAlive) { /* last known link status was ALIVE */ /* See if we've lost link */ if (phyHwStatus & MV_STATUS_REAL_TIME_LINK_UP) { linkCount++; } else { lostLinks++; mv_flushATUDB(phyUnit); MV_PRINT(MV_DEBUG_PHYCHANGE,("\neth%d port%d down\n", ethUnit, phyUnit)); lastStatus->isPhyAlive = FALSE; } } else { /* last known link status was DEAD */ /* Check for AutoNegotiation complete */ if (MV_AUTONEG_DONE(phyHwStatus)) { gainedLinks++; linkCount++; MV_PRINT(MV_DEBUG_PHYCHANGE,("\neth%d port%d up\n", ethUnit, phyUnit)); lastStatus->isPhyAlive = TRUE; } } } if (linkCount == 0) { if (lostLinks) { /* We just lost the last link for this MAC */ phyLinkLost(ethUnit); } } else { if (gainedLinks == linkCount) { /* We just gained our first link(s) for this MAC */ phyLinkGained(ethUnit); } } }
void sgdt_dump(sgd_tbl_t *SgTbl, char* prefix) { sgd_t* sg = SgTbl->Entry_Ptr; MV_PRINT( "%s %p %u of %u 0x%x bytes\n" , prefix ? prefix : " " , SgTbl , SgTbl->Valid_Entry_Count , SgTbl->Max_Entry_Count , SgTbl->Byte_Count ); if( !SgTbl->Valid_Entry_Count ) return; #if 0 sgdl_dump(sg, NULL); #else while(1) { sgd_dump(sg,NULL); if( sgd_eot(sg) ) break; sgd_inc(sg); } #endif }
/****************************************************************************** * * mv_phySetup - reset and setup the PHY switch. * * Resets each PHY port. * * RETURNS: * TRUE --> at least 1 PHY with LINK * FALSE --> no LINKs on this ethernet unit */ BOOL mv_phySetup(int ethUnit, UINT32 phyBase) { int phyUnit; int liveLinks = 0; BOOL foundPhy = FALSE; UINT32 phyAddr; UINT16 atuControl; /* * See if there's any configuration data for this enet, * and set up phyBase in table. */ for (phyUnit=0; phyUnit < MV_PHY_MAX; phyUnit++) { if (MV_ETHUNIT(phyUnit) != ethUnit) { continue; } MV_PHYBASE(phyUnit) = phyBase; foundPhy = TRUE; } if (!foundPhy) { return FALSE; /* No PHY's configured for this ethUnit */ } /* Verify that the switch is what we think it is, and that it's ready */ mv_verifyReady(ethUnit); /* Initialize global switch settings */ atuControl = MV_ATUCTRL_AGE_TIME_DEFAULT << MV_ATUCTRL_AGE_TIME_SHIFT; atuControl |= MV_ATUCTRL_ATU_SIZE_DEFAULT << MV_ATUCTRL_ATU_SIZE_SHIFT; phyRegWrite(phyBase, MV_SWITCH_GLOBAL_ADDR, MV_ATU_CONTROL, atuControl); /* Reset PHYs and start autonegoation on each. */ for (phyUnit=0; phyUnit < MV_PHY_MAX; phyUnit++) { if (MV_ETHUNIT(phyUnit) != ethUnit) { continue; } phyBase = MV_PHYBASE(phyUnit); phyAddr = MV_PHYADDR(phyUnit); phyRegWrite(phyBase, phyAddr, MV_PHY_CONTROL, MV_CTRL_SOFTWARE_RESET | MV_CTRL_AUTONEGOTIATION_ENABLE); } #if 0 /* Don't wait -- we'll detect shortly after the link comes up */ { int timeout; UINT16 phyHwStatus; /* * Wait 5 seconds for ALL associated PHYs to finish autonegotiation. */ timeout=50; for (phyUnit=0; (phyUnit < MV_PHY_MAX) && (timeout > 0); phyUnit++) { if (!MV_IS_ETHUNIT(phyUnit, ethUnit)) { continue; } for (;;) { phyBase = MV_PHYBASE(phyUnit); phyAddr = MV_PHYADDR(phyUnit); phyHwStatus = phyRegRead(phyBase, phyAddr, MV_PHY_SPECIFIC_STATUS); if (MV_AUTONEG_DONE(phyHwStatus)) { break; } if (--timeout == 0) { break; } sysMsDelay(100); } } } #endif /* * All PHYs have had adequate time to autonegotiate. * Now initialize software status. * * It's possible that some ports may take a bit longer * to autonegotiate; but we can't wait forever. They'll * get noticed by mv_phyCheckStatusChange during regular * polling activities. */ for (phyUnit=0; phyUnit < MV_PHY_MAX; phyUnit++) { if (!MV_IS_ETHUNIT(phyUnit, ethUnit)) { continue; } if (mv_phyIsLinkAlive(phyUnit)) { liveLinks++; MV_IS_PHY_ALIVE(phyUnit) = TRUE; } else { MV_IS_PHY_ALIVE(phyUnit) = FALSE; } MV_PRINT(MV_DEBUG_PHYSETUP, ("eth%d: Phy Status=%4.4x\n", ethUnit, phyRegRead(MV_PHYBASE(phyUnit), MV_PHYADDR(phyUnit), MV_PHY_SPECIFIC_STATUS))); } mv_VLANInit(ethUnit); mv_enableConfiguredPorts(ethUnit); return (liveLinks > 0); }
/****************************************************************************** * * mv_verifyReady - validates that we're dealing with the device * we think we're dealing with, and that it's ready. */ LOCAL void mv_verifyReady(int ethUnit) { int phyUnit; UINT16 globalStatus; UINT32 phyBase = 0; UINT32 phyAddr; UINT32 switchPortAddr; UINT16 phyID1; UINT16 phyID2; UINT16 switchID; /* * The first read to the Phy port registers always fails and * returns 0. So get things started with a bogus read. */ for (phyUnit=0; phyUnit < MV_PHY_MAX; phyUnit++) { if (!MV_IS_ETHUNIT(phyUnit, ethUnit)) { continue; } phyBase = MV_PHYBASE(phyUnit); phyAddr = MV_PHYADDR(phyUnit); (void)phyRegRead(phyBase, phyAddr, MV_PHY_ID1); /* returns 0 */ break; } for (phyUnit=0; phyUnit < MV_PHY_MAX; phyUnit++) { if (!MV_IS_ETHUNIT(phyUnit, ethUnit)) { continue; } /*******************/ /* Verify phy port */ /*******************/ phyBase = MV_PHYBASE(phyUnit); phyAddr = MV_PHYADDR(phyUnit); phyID1 = phyRegRead(phyBase, phyAddr, MV_PHY_ID1); if (phyID1 != MV_PHY_ID1_EXPECTATION) { MV_PRINT(MV_DEBUG_PHYSETUP, ("Invalid PHY ID1 for eth%d port%d. Expected 0x%04x, read 0x%04x\n", ethUnit, phyUnit, MV_PHY_ID1_EXPECTATION, phyID1)); return; } phyID2 = phyRegRead(phyBase, phyAddr, MV_PHY_ID2); if ((phyID2 & MV_OUI_LSB_MASK) != MV_OUI_LSB_EXPECTATION) { MV_PRINT(MV_DEBUG_PHYSETUP, ("Invalid PHY ID2 for eth%d port %d. Expected 0x%04x, read 0x%04x\n", ethUnit, phyUnit, MV_OUI_LSB_EXPECTATION, phyID2)); return; } MV_PRINT(MV_DEBUG_PHYSETUP, ("Found PHY eth%d port%d: model 0x%x revision 0x%x\n", ethUnit, phyUnit, (phyID2 & MV_MODEL_NUM_MASK) >> MV_MODEL_NUM_SHIFT, (phyID2 & MV_REV_NUM_MASK) >> MV_REV_NUM_SHIFT)); /**********************/ /* Verify switch port */ /**********************/ switchPortAddr = MV_SWITCH_PORT_ADDR(phyUnit); switchID = phyRegRead(phyBase, switchPortAddr, MV_SWITCH_ID); if ((switchID & MV_SWITCH_ID_DEV_MASK) != MV_SWITCH_ID_DEV_EXPECTATION) { MV_PRINT(MV_DEBUG_PHYSETUP, ("Invalid switch ID for eth%d port %d. Expected 0x%04x, read 0x%04x\n", ethUnit, phyUnit, MV_SWITCH_ID_DEV_EXPECTATION, switchID)); return; } MV_PRINT(MV_DEBUG_PHYSETUP, ("Found PHY switch for enet %d port %d deviceID 0x%x revision 0x%x\n", ethUnit, phyUnit, (switchID & MV_SWITCH_ID_DEV_MASK) >> MV_SWITCH_ID_DEV_SHIFT, (switchID & MV_SWITCH_ID_REV_MASK) >> MV_SWITCH_ID_REV_SHIFT)) } /*******************************/ /* Verify that switch is ready */ /*******************************/ if (phyBase) { globalStatus = phyRegRead(phyBase, MV_SWITCH_GLOBAL_ADDR, MV_SWITCH_GLOBAL_STATUS); if (!(globalStatus & MV_SWITCH_STATUS_READY_MASK)) { MV_PRINT(MV_DEBUG_PHYSETUP, ("PHY switch for eth%d NOT ready!\n", ethUnit)); } } else { MV_PRINT(MV_DEBUG_PHYSETUP, ("No ports configured for eth%d\n", ethUnit)); } }
MV_BOOLEAN mvui_init_param( MV_PVOID This, pHBA_Info_Page pHBA_Info_Param) { // MV_U32 nsize = FLASH_PARAM_SIZE; MV_U32 param_flash_addr=PARAM_OFFSET,i = 0; // MV_U16 my_ds=0; PCore_Driver_Extension pCore; AdapterInfo AI; if (!This) return MV_FALSE; pCore = (PCore_Driver_Extension)This; AI.bar[2] = pCore->Base_Address[2]; if (-1 == OdinSPI_Init(&AI)) return MV_FALSE; /* step 1 read param from flash offset = 0x3FFF00 */ OdinSPI_ReadBuf( &AI, param_flash_addr, (MV_PU8)pHBA_Info_Param, FLASH_PARAM_SIZE); /* step 2 check the signature first */ if(pHBA_Info_Param->Signature[0] == 'M'&& \ pHBA_Info_Param->Signature[1] == 'R'&& \ pHBA_Info_Param->Signature[2] == 'V'&& \ pHBA_Info_Param->Signature[3] == 'L' && \ (!mvVerifyChecksum((MV_PU8)pHBA_Info_Param,FLASH_PARAM_SIZE))) { if(pHBA_Info_Param->HBA_Flag == 0xFFFFFFFFL) { pHBA_Info_Param->HBA_Flag = 0; pHBA_Info_Param->HBA_Flag |= HBA_FLAG_INT13_ENABLE; pHBA_Info_Param->HBA_Flag &= ~HBA_FLAG_SILENT_MODE_ENABLE; } for(i=0;i<8;i++) { if(pHBA_Info_Param->PHY_Rate[i]>0x1) /* phy host link rate */ pHBA_Info_Param->PHY_Rate[i] = 0x1; // validate phy tuning //pHBA_Info_Param->PHY_Tuning[i].Reserved[0] = 0; //pHBA_Info_Param->PHY_Tuning[i].Reserved[1] = 0; } } else { MV_FillMemory((MV_PVOID)pHBA_Info_Param, FLASH_PARAM_SIZE, 0xFF); pHBA_Info_Param->Signature[0] = 'M'; pHBA_Info_Param->Signature[1] = 'R'; pHBA_Info_Param->Signature[2] = 'V'; pHBA_Info_Param->Signature[3] = 'L'; // Set BIOS Version pHBA_Info_Param->Minor = NVRAM_DATA_MAJOR_VERSION; pHBA_Info_Param->Major = NVRAM_DATA_MINOR_VERSION; // Set SAS address for(i=0;i<MAX_PHYSICAL_PORT_NUMBER;i++) { pHBA_Info_Param->SAS_Address[i].b[0]= 0x50; pHBA_Info_Param->SAS_Address[i].b[1]= 0x05; pHBA_Info_Param->SAS_Address[i].b[2]= 0x04; pHBA_Info_Param->SAS_Address[i].b[3]= 0x30; pHBA_Info_Param->SAS_Address[i].b[4]= 0x11; pHBA_Info_Param->SAS_Address[i].b[5]= 0xab; pHBA_Info_Param->SAS_Address[i].b[6]= 0x00; pHBA_Info_Param->SAS_Address[i].b[7]= 0x00; /*+(MV_U8)i; - All ports' WWN has to be same */ } /* init phy link rate */ for(i=0;i<8;i++) { /* phy host link rate */ pHBA_Info_Param->PHY_Rate[i] = 0x1;//Default is 3.0G; } MV_PRINT("pHBA_Info_Param->HBA_Flag = 0x%x \n",pHBA_Info_Param->HBA_Flag); /* init setting flags */ pHBA_Info_Param->HBA_Flag = 0; pHBA_Info_Param->HBA_Flag |= HBA_FLAG_INT13_ENABLE; pHBA_Info_Param->HBA_Flag &= ~HBA_FLAG_SILENT_MODE_ENABLE; /* write to flash and save it now */ if(OdinSPI_SectErase( &AI, param_flash_addr) != -1) MV_PRINT("FLASH ERASE SUCCESS\n"); else MV_PRINT("FLASH ERASE FAILED\n"); pHBA_Info_Param->Check_Sum = 0; pHBA_Info_Param->Check_Sum=mvCaculateChecksum((MV_PU8)pHBA_Info_Param,sizeof(HBA_Info_Page)); /* init the parameter in ram */ OdinSPI_WriteBuf( &AI, param_flash_addr, (MV_PU8)pHBA_Info_Param, FLASH_PARAM_SIZE); } return MV_TRUE; }
MV_BOOLEAN ATAPI_CDB2TaskFile( IN PDomain_Device pDevice, IN PMV_Request pReq, OUT PATA_TaskFile pTaskFile ) { MV_ZeroMemory(pTaskFile, sizeof(ATA_TaskFile)); /* At the same time, set the command category as well. */ switch ( pReq->Cdb[0] ) { case SCSI_CMD_MARVELL_SPECIFIC: /* This request should be for core module */ if ( pReq->Cdb[1]!=CDB_CORE_MODULE ) return MV_FALSE; switch ( pReq->Cdb[2] ) { case CDB_CORE_IDENTIFY: pTaskFile->Command = ATA_CMD_IDENTIFY_ATAPI; break; case CDB_CORE_SET_UDMA_MODE: pTaskFile->Command = ATA_CMD_SET_FEATURES; pTaskFile->Features = ATA_CMD_SET_TRANSFER_MODE; if ( pReq->Cdb[4]==MV_TRUE ) pTaskFile->Sector_Count = 0x20 | pReq->Cdb[3]; /* MDMA mode */ else pTaskFile->Sector_Count = 0x40 | pReq->Cdb[3]; /* UDMA mode*/ //TBD: Check the 80-conductor cable in order to enable UDMA greater than 2. break; case CDB_CORE_SET_PIO_MODE: pTaskFile->Command = ATA_CMD_SET_FEATURES; pTaskFile->Features = ATA_CMD_SET_TRANSFER_MODE; pTaskFile->Sector_Count = 0x08 | pReq->Cdb[3]; break; default: return MV_FALSE; } break; case SCSI_CMD_READ_DISC_INFO: /* unimplemented SCSI cmds */ /* return MV_FALSE; */ case SCSI_CMD_READ_10: case SCSI_CMD_READ_12: case SCSI_CMD_WRITE_10: case SCSI_CMD_VERIFY_10: case SCSI_CMD_INQUIRY: case SCSI_CMD_READ_CAPACITY_10: case SCSI_CMD_TEST_UNIT_READY: case SCSI_CMD_MODE_SENSE_10: case SCSI_CMD_MODE_SELECT_10: case SCSI_CMD_PREVENT_MEDIUM_REMOVAL: case SCSI_CMD_READ_TOC: case SCSI_CMD_START_STOP_UNIT: case SCSI_CMD_SYNCHRONIZE_CACHE_10: case SCSI_CMD_REQUEST_SENSE: default: /* * Use packet command */ /* Features: DMA, OVL, DMADIR */ #if defined(USE_DMA_FOR_ALL_PACKET_COMMAND) if ( !(pReq->Cmd_Flag&CMD_FLAG_NON_DATA) ) { pTaskFile->Features |= MV_BIT(0); } #else if ( pReq->Cmd_Flag&CMD_FLAG_DMA ) { //if ( SCSI_IS_READ(pReq->Cdb[0]) || SCSI_IS_WRITE(pReq->Cdb[0]) ) pTaskFile->Features |= MV_BIT(0); if ((pReq->Cdb[0] != SCSI_CMD_READ_10) && (pReq->Cdb[0] != SCSI_CMD_READ_12) && (pReq->Cdb[0] != SCSI_CMD_WRITE_10)) MV_PRINT("[BERLIN A0]DMA transfer for prohibited command 0x%02x\n", pReq->Cdb[0]); } #endif //TBD: OVL: overlapped. //TBD: DMADIR in IDENTIFY PACKET DEVICE word 62 //TBD: Sector Count: Tag /* Byte count low and byte count high */ if ( pReq->Data_Transfer_Length>0xFFFF ) { pTaskFile->LBA_Mid = 0xFF; pTaskFile->LBA_High = 0xFF; } else { pTaskFile->LBA_Mid = (MV_U8)pReq->Data_Transfer_Length; pTaskFile->LBA_High = (MV_U8)(pReq->Data_Transfer_Length>>8); } pTaskFile->Command = ATA_CMD_PACKET; break; } return MV_TRUE; }
MV_BOOLEAN ATA_CDB2TaskFile( IN PDomain_Device pDevice, IN PMV_Request pReq, IN MV_U8 tag, OUT PATA_TaskFile pTaskFile ) { MV_ZeroMemory(pTaskFile, sizeof(ATA_TaskFile)); switch ( pReq->Cdb[0] ) { case SCSI_CMD_READ_10: case SCSI_CMD_WRITE_10: { /* * The OS maximum tranfer length is set to 128K. * For ATA_CMD_READ_DMA and ATA_CMD_WRITE_DMA, * the max size they can handle is 256 sectors. * And Sector_Count==0 means 256 sectors. * If OS request max lenght>128K, for 28 bit device, we have to split requests. */ MV_DASSERT( ( (((MV_U16)pReq->Cdb[7])<<8) | (pReq->Cdb[8]) ) <= 256 ); #if 1 { if ( ( (((MV_U16)pReq->Cdb[7])<<8) | (pReq->Cdb[8]) ) > MV_MAX_TRANSFER_SECTOR ) { printk("READ10/WRITE10 error: sector count 0x%xlimited.\n", (((MV_U16)pReq->Cdb[7])<<8) | (pReq->Cdb[8])); } } #endif /* * 24 bit LBA can express 128GB. * 4 bytes LBA like SCSI_CMD_READ_10 can express 2TB. */ /* Make sure Cmd_Flag has set already. */ if ( pReq->Cmd_Flag&CMD_FLAG_NCQ ) { //MV_DASSERT( pReq->Cmd_Flag&CMD_FLAG_48BIT ); //TBD: Do we need set 48bit for NCQ pTaskFile->Features = pReq->Cdb[8]; pTaskFile->Feature_Exp = pReq->Cdb[7]; pTaskFile->Sector_Count = tag<<3; pTaskFile->LBA_Low = pReq->Cdb[5]; pTaskFile->LBA_Mid = pReq->Cdb[4]; pTaskFile->LBA_High = pReq->Cdb[3]; pTaskFile->LBA_Low_Exp = pReq->Cdb[2]; pTaskFile->Device = MV_BIT(6); if ( pReq->Cdb[0]==SCSI_CMD_READ_10 ) pTaskFile->Command = ATA_CMD_READ_FPDMA_QUEUED; else if ( pReq->Cdb[0]==SCSI_CMD_WRITE_10 ) pTaskFile->Command = ATA_CMD_WRITE_FPDMA_QUEUED; } else if ( pReq->Cmd_Flag&CMD_FLAG_48BIT ) { MV_DASSERT( !(pReq->Cmd_Flag&CMD_FLAG_NCQ) ); pTaskFile->Sector_Count = pReq->Cdb[8]; pTaskFile->Sector_Count_Exp = pReq->Cdb[7]; pTaskFile->LBA_Low = pReq->Cdb[5]; pTaskFile->LBA_Mid = pReq->Cdb[4]; pTaskFile->LBA_High = pReq->Cdb[3]; pTaskFile->LBA_Low_Exp = pReq->Cdb[2]; pTaskFile->Device = MV_BIT(6); if ( pReq->Cdb[0]==SCSI_CMD_READ_10 ) pTaskFile->Command = ATA_CMD_READ_DMA_EXT; else if ( pReq->Cdb[0]==SCSI_CMD_WRITE_10 ) pTaskFile->Command = ATA_CMD_WRITE_DMA_EXT; } else { /* 28 bit DMA */ pTaskFile->Sector_Count = pReq->Cdb[8]; /* Could be zero */ pTaskFile->LBA_Low = pReq->Cdb[5]; pTaskFile->LBA_Mid = pReq->Cdb[4]; pTaskFile->LBA_High = pReq->Cdb[3]; pTaskFile->Device = MV_BIT(6) | (pReq->Cdb[2]&0xF); MV_DASSERT( (pReq->Cdb[2]&0xF0)==0 ); if ( pReq->Cdb[0]==SCSI_CMD_READ_10 ) pTaskFile->Command = ATA_CMD_READ_DMA; else if ( pReq->Cdb[0]==SCSI_CMD_WRITE_10 ) pTaskFile->Command = ATA_CMD_WRITE_DMA; } break; } case SCSI_CMD_VERIFY_10: /* * For verify command, the size may need use two MV_U8, especially Windows. * For 28 bit device, we have to split the request. * For 48 bit device, we use ATA_CMD_VERIFY_EXT. */ if ( pDevice->Capacity&DEVICE_CAPACITY_48BIT_SUPPORTED ) { pTaskFile->Sector_Count = pReq->Cdb[8]; pTaskFile->Sector_Count_Exp = pReq->Cdb[7]; pTaskFile->LBA_Low = pReq->Cdb[5]; pTaskFile->LBA_Mid = pReq->Cdb[4]; pTaskFile->LBA_High = pReq->Cdb[3]; pTaskFile->LBA_Low_Exp = pReq->Cdb[2]; pTaskFile->Device = MV_BIT(6); pTaskFile->Command = ATA_CMD_VERIFY_EXT; } else { //TBD: If the device doesn't support 48 bit LBA. We have to split this request. //ATA_CMD_VERIFY //MV_ASSERT(MV_FALSE); //Sorry here I didn't do the verify exact as the OS required. //It need effort to split request. Currently I just pretect I've fulfilled the request. pTaskFile->Sector_Count = pReq->Cdb[8]; pTaskFile->LBA_Low = pReq->Cdb[5]; pTaskFile->LBA_Mid = pReq->Cdb[4]; pTaskFile->LBA_High = pReq->Cdb[3]; pTaskFile->Device = MV_BIT(6) | (pReq->Cdb[2]&0xF); MV_DASSERT( (pReq->Cdb[2]&0xF0)==0 ); pTaskFile->Command = ATA_CMD_VERIFY; } break; case SCSI_CMD_MARVELL_SPECIFIC: { /* This request should be for core module */ if ( pReq->Cdb[1]!=CDB_CORE_MODULE ) return MV_FALSE; switch ( pReq->Cdb[2] ) { case CDB_CORE_IDENTIFY: pTaskFile->Command = ATA_CMD_IDENTIFY_ATA; break; case CDB_CORE_SET_UDMA_MODE: pTaskFile->Command = ATA_CMD_SET_FEATURES; pTaskFile->Features = ATA_CMD_SET_TRANSFER_MODE; pTaskFile->Sector_Count = 0x40 | pReq->Cdb[3]; MV_DASSERT( pReq->Cdb[4]==MV_FALSE ); /* Use UDMA mode */ //TBD: Check the 80-conductor cable in order to enable UDMA greater than 2. break; case CDB_CORE_SET_PIO_MODE: pTaskFile->Command = ATA_CMD_SET_FEATURES; pTaskFile->Features = ATA_CMD_SET_TRANSFER_MODE; pTaskFile->Sector_Count = 0x08 | pReq->Cdb[3]; break; case CDB_CORE_ENABLE_WRITE_CACHE: pTaskFile->Command = ATA_CMD_SET_FEATURES; pTaskFile->Features = ATA_CMD_ENABLE_WRITE_CACHE; break; case CDB_CORE_DISABLE_WRITE_CACHE: pTaskFile->Command = ATA_CMD_SET_FEATURES; pTaskFile->Features = ATA_CMD_DISABLE_WRITE_CACHE; break; case CDB_CORE_ENABLE_SMART: pTaskFile->Command = ATA_CMD_SMART; pTaskFile->Features = ATA_CMD_ENABLE_SMART; pTaskFile->LBA_Mid = 0x4F; pTaskFile->LBA_High = 0xC2; break; case CDB_CORE_DISABLE_SMART: pTaskFile->Command = ATA_CMD_SMART; pTaskFile->Features = ATA_CMD_DISABLE_SMART; pTaskFile->LBA_Mid = 0x4F; pTaskFile->LBA_High = 0xC2; break; case CDB_CORE_SMART_RETURN_STATUS: pTaskFile->Command = ATA_CMD_SMART; pTaskFile->Features = ATA_CMD_SMART_RETURN_STATUS; pTaskFile->LBA_Mid = 0x4F; pTaskFile->LBA_High = 0xC2; break; case CDB_CORE_SHUTDOWN: if ( pDevice->Capacity&DEVICE_CAPACITY_48BIT_SUPPORTED ) pTaskFile->Command = ATA_CMD_FLUSH_EXT; else pTaskFile->Command = ATA_CMD_FLUSH; break; case CDB_CORE_ENABLE_READ_AHEAD: pTaskFile->Command = ATA_CMD_SET_FEATURES; pTaskFile->Features = ATA_CMD_ENABLE_READ_LOOK_AHEAD; break; case CDB_CORE_DISABLE_READ_AHEAD: pTaskFile->Command = ATA_CMD_SET_FEATURES; pTaskFile->Features = ATA_CMD_DISABLE_READ_LOOK_AHEAD; break; case CDB_CORE_READ_LOG_EXT: pTaskFile->Command = ATA_CMD_READ_LOG_EXT; pTaskFile->Sector_Count = 1; /* Read one sector */ pTaskFile->LBA_Low = 0x10; /* Page 10h */ break; default: return MV_FALSE; } break; } case SCSI_CMD_SYNCHRONIZE_CACHE_10: if ( pDevice->Capacity&DEVICE_CAPACITY_48BIT_SUPPORTED ) pTaskFile->Command = ATA_CMD_FLUSH_EXT; else pTaskFile->Command = ATA_CMD_FLUSH; pTaskFile->Device = MV_BIT(6); break; case SCSI_CMD_START_STOP_UNIT: if (pReq->Cdb[4] & MV_BIT(0)) { pTaskFile->Command = ATA_CMD_SEEK; pTaskFile->Device = MV_BIT(6); } else { pTaskFile->Command = ATA_CMD_STANDBY_IMMEDIATE; } break; case SCSI_CMD_REQUEST_SENSE: case SCSI_CMD_MODE_SELECT_10: case SCSI_CMD_MODE_SENSE_10: default: MV_PRINT("[Galois]ATA_CDB2TaskFile error: Unknown request: 0x%x.\n", pReq->Cdb[0]); return MV_FALSE; } return MV_TRUE; }
void sgd_dump(sgd_t* sg, char* prefix) { MV_U32 sz; sgd_getsz(sg,sz); if( prefix ) { #ifndef _OS_LINUX MV_PRINT(prefix); #endif } if( sg->flags & SGD_VIRTUAL ) { MV_PVOID vaddr, xctx; sgd_get_vaddr(sg,vaddr); sgd_get_xctx(sg,xctx); MV_PRINT( "\tV %p T %p %08x F %08x\n" , vaddr , xctx , sz , sg->flags ); } else if( sg->flags & (SGD_REFTBL|SGD_REFSGD) ) { MV_PVOID ref; MV_U32 refOff; sgd_get_ref(sg,ref); sgd_get_refoff(sg,refOff); MV_PRINT( "\tR %p O %08x %08x F %08x\n" , ref , refOff , sz , sg->flags ); } else if( sg->flags & SGD_NEXT_TBL ) { MV_PVOID nexttbl; sgd_get_nexttbl(sg, nexttbl); MV_PRINT( "\tN %p F %08x\n" , nexttbl, sg->flags ); } else if( sg->flags & SGD_VP ) { sgd_vp_t* vp = (sgd_vp_t*) sg; MV_PRINT( "\tX %08x_%08x %p F %08x\n" , vp->baseAddr.parts.high , vp->baseAddr.parts.low , vp->u.vaddr , sg->flags ); } else if( sg->flags & SGD_VWOXCTX ) { sgd_v_t* vp = (sgd_v_t*) sg; MV_PRINT( "\tV %p T %p %08x F %08x\n" , vp->u.vaddr , (MV_PVOID)0 , sz , sg->flags ); } else if( sg->flags & SGD_PCTX ) { sgd_pctx_t* p = (sgd_pctx_t*) sg; MV_PRINT( "\tP %08x_%08x %08x F %08x X %p\n" , p->baseAddr.parts.high, p->baseAddr.parts.low, p->size, p->flags , p->u.xctx ); } else { MV_PRINT( "\tP %08x_%08x %08x F %08x\n" , sg->baseAddr.parts.high, sg->baseAddr.parts.low, sz, sg->flags ); } }