uint8_t sdmmc_readSector(uint32_t pSectorNum, char* pOutput) { SET_CS(); // Send command 17 (READ_SINGLE_BLOCK) if (sdmmc_writeCommand(SDMMC_READ_SINGLE_BLOCK, SECTOR_TO_BYTE(pSectorNum), SDMMC_DEFAULT_CRC) != 0) { CLEAR_CS(); return FALSE; } uint8_t response = 0; uint8_t retry = 0; // Wait for start-byte while(response != 0xFE) { response = spi_readByte(); if (retry++ == 0xFF) { CLEAR_CS(); return FALSE; } } // Read the block for (uint16_t i = 0; i < fBlockLength; i++) { pOutput[i] = spi_readByte(); } // Ignore the CRC checksum spi_readByte(); spi_readByte(); CLEAR_CS(); return TRUE; }
uint8_t sdmmc_writeSector(uint32_t pSectorNum, char* pInput) { SET_CS(); // Send command 24 (WRITE_BLOCK) if (sdmmc_writeCommand(SDMMC_WRITE_BLOCK, SECTOR_TO_BYTE(pSectorNum), SDMMC_DEFAULT_CRC) != 0) { CLEAR_CS(); return FALSE; } // Send some dummy clocks for(uint8_t i = 0; i < 100; i++) { spi_readByte(); } // Send start-byte spi_writeByte(0xFE); // Send data for(uint16_t i = 0; i < fBlockLength; i++) { spi_writeByte(pInput[i]); } // Send dummy CRC checksum (won't be checked in SPI mode) spi_writeByte(0xFF); spi_writeByte(0xFF); // Get response if ((spi_readByte() & 0x1F) != 0x05) { CLEAR_CS(); return FALSE; } // Wait until memory card is ready for new commands while (spi_readByte() != 0xFF) { // burn energy } CLEAR_CS(); return TRUE; }
void hpt_rebuild_data_block(IAL_ADAPTER_T *pAdapter, PVDevice pArray, UCHAR flags) { ULONG capacity = pArray->VDeviceCapacity / (pArray->u.array.bArnMember-1); PCommand pCmd; UINT result; int needsync=0, retry=0, needdelete=0; void *buffer = NULL; _VBUS_INST(&pAdapter->VBus) if (pArray->u.array.rf_broken==1 || pArray->u.array.RebuildSectors>=capacity) return; mtx_lock(&pAdapter->lock); switch(flags) { case DUPLICATE: case REBUILD_PARITY: if(pArray->u.array.rf_rebuilding == 0) { pArray->u.array.rf_rebuilding = 1; hpt_printk(("Rebuilding started.\n")); ioctl_ReportEvent(ET_REBUILD_STARTED, pArray); } break; case INITIALIZE: if(pArray->u.array.rf_initializing == 0) { pArray->u.array.rf_initializing = 1; hpt_printk(("Initializing started.\n")); ioctl_ReportEvent(ET_INITIALIZE_STARTED, pArray); } break; case VERIFY: if(pArray->u.array.rf_verifying == 0) { pArray->u.array.rf_verifying = 1; hpt_printk(("Verifying started.\n")); ioctl_ReportEvent(ET_VERIFY_STARTED, pArray); } break; } retry_cmd: pCmd = AllocateCommand(_VBUS_P0); HPT_ASSERT(pCmd); pCmd->cf_control = 1; End_Job = 0; if (pArray->VDeviceType==VD_RAID_1) { #define MAX_REBUILD_SECTORS 0x40 /* take care for discontinuous buffer in R1ControlSgl */ buffer = malloc(SECTOR_TO_BYTE(MAX_REBUILD_SECTORS), M_DEVBUF, M_NOWAIT); if(!buffer) { FreeCommand(_VBUS_P pCmd); hpt_printk(("can't allocate rebuild buffer\n")); goto fail; } switch(flags) { case DUPLICATE: pCmd->uCmd.R1Control.Command = CTRL_CMD_REBUILD; pCmd->uCmd.R1Control.nSectors = MAX_REBUILD_SECTORS; break; case VERIFY: pCmd->uCmd.R1Control.Command = CTRL_CMD_VERIFY; pCmd->uCmd.R1Control.nSectors = MAX_REBUILD_SECTORS/2; break; case INITIALIZE: pCmd->uCmd.R1Control.Command = CTRL_CMD_REBUILD; pCmd->uCmd.R1Control.nSectors = MAX_REBUILD_SECTORS; break; } pCmd->uCmd.R1Control.Lba = pArray->u.array.RebuildSectors; if (capacity - pArray->u.array.RebuildSectors < pCmd->uCmd.R1Control.nSectors) pCmd->uCmd.R1Control.nSectors = capacity - pArray->u.array.RebuildSectors; pCmd->uCmd.R1Control.Buffer = buffer; pCmd->pfnBuildSgl = R1ControlSgl; } else if (pArray->VDeviceType==VD_RAID_5) { switch(flags) { case DUPLICATE: case REBUILD_PARITY: pCmd->uCmd.R5Control.Command = CTRL_CMD_REBUILD; break; case VERIFY: pCmd->uCmd.R5Control.Command = CTRL_CMD_VERIFY; break; case INITIALIZE: pCmd->uCmd.R5Control.Command = CTRL_CMD_INIT; break; } pCmd->uCmd.R5Control.StripeLine=pArray->u.array.RebuildSectors>>pArray->u.array.bArBlockSizeShift; } else
int HPTLIBAPI R1ControlSgl(_VBUS_ARG PCommand pCmd, FPSCAT_GATH pSgTable, int logical) { ULONG bufferSize = SECTOR_TO_BYTE(pCmd->uCmd.R1Control.nSectors); if (pCmd->uCmd.R1Control.Command==CTRL_CMD_VERIFY) bufferSize<<=1; if (logical) { pSgTable->dSgAddress = (ULONG_PTR)pCmd->uCmd.R1Control.Buffer; pSgTable->wSgSize = (USHORT)bufferSize; pSgTable->wSgFlag = SG_FLAG_EOT; } else { /* build physical SG table for pCmd->uCmd.R1Control.Buffer */ ADDRESS dataPointer, v, nextpage, currvaddr, nextvaddr, currphypage, nextphypage; ULONG length; int idx = 0; v = pCmd->uCmd.R1Control.Buffer; dataPointer = (ADDRESS)fOsPhysicalAddress(v); if ((ULONG_PTR)dataPointer & 0x1) return FALSE; #define ON64KBOUNDARY(x) (((ULONG_PTR)(x) & 0xFFFF) == 0) #define NOTNEIGHBORPAGE(highvaddr, lowvaddr) ((ULONG_PTR)(highvaddr) - (ULONG_PTR)(lowvaddr) != PAGE_SIZE) do { if (idx >= MAX_SG_DESCRIPTORS) return FALSE; pSgTable[idx].dSgAddress = fOsPhysicalAddress(v); currvaddr = v; currphypage = (ADDRESS)fOsPhysicalAddress((void*)trunc_page((ULONG_PTR)currvaddr)); do { nextpage = (ADDRESS)trunc_page(((ULONG_PTR)currvaddr + PAGE_SIZE)); nextvaddr = (ADDRESS)MIN(((ULONG_PTR)v + bufferSize), (ULONG_PTR)(nextpage)); if (nextvaddr == (ADDRESS)((ULONG_PTR)v + bufferSize)) break; nextphypage = (ADDRESS)fOsPhysicalAddress(nextpage); if (NOTNEIGHBORPAGE(nextphypage, currphypage) || ON64KBOUNDARY(nextphypage)) { nextvaddr = nextpage; break; } currvaddr = nextvaddr; currphypage = nextphypage; }while (1); length = (ULONG_PTR)nextvaddr - (ULONG_PTR)v; v = nextvaddr; bufferSize -= length; pSgTable[idx].wSgSize = (USHORT)length; pSgTable[idx].wSgFlag = (bufferSize)? 0 : SG_FLAG_EOT; idx++; }while (bufferSize); } return 1; }