void macphy_reset(void) { spi_ss(0); spi_txrx(0xff); /* MAC/PHY soft reset */ spi_ss(1); }
u8 MSD_WriteBuffer(u8* pBuffer, u32 WriteAddr, u32 NumByteToWrite) { u32 i = 0, NbrOfBlock = 0, Offset = 0; u8 rvalue = MSD_RESPONSE_FAILURE; /* Calculate number of blocks to write */ NbrOfBlock = NumByteToWrite / BLOCK_SIZE; /* MSD chip select low */ spi_ss(_FLASH_NUM0,0); /* Data transfer */ while (NbrOfBlock --) { /* Send CMD24 (MSD_WRITE_BLOCK) to write blocks */ MSD_SendCmd(MSD_WRITE_BLOCK, WriteAddr + Offset, 0xFF); /* Check if the MSD acknowledged the write block command: R1 response (0x00: no errors) */ if (MSD_GetResponse(MSD_RESPONSE_NO_ERROR)) { return MSD_RESPONSE_FAILURE; } /* Send dummy byte */ spi_send(DUMMY); /* Send the data token to signify the start of the data */ spi_send(MSD_START_DATA_SINGLE_BLOCK_WRITE); /* Write the block data to MSD : write count data by block */ for (i = 0; i < BLOCK_SIZE; i++) { /* Send the pointed byte */ spi_send(*pBuffer); /* Point to the next location where the byte read will be saved */ pBuffer++; } /* Set next write address */ Offset += 512; /* Put CRC bytes (not really needed by us, but required by MSD) */ spi_send(DUMMY); spi_send(DUMMY); /* Read data response */ if (MSD_GetDataResponse() == MSD_DATA_OK) { /* Set response value to success */ rvalue = MSD_RESPONSE_NO_ERROR; } else { /* Set response value to failure */ rvalue = MSD_RESPONSE_FAILURE; } } /* MSD chip select high */ spi_ss(_FLASH_NUM0,1); /* Send dummy byte: 8 Clock pulses of delay */ spi_send(DUMMY); /* Returns the reponse */ return rvalue; }
void macphy_writereg(u8 reg, u8 val) { /* CAUTION: You must set the proper bank before calling this routine */ spi_ss(0); spi_txrx(CMD_WCR(reg)); spi_txrx(val); spi_ss(1); }
void macphy_clearbit(u8 reg, u8 val) { /* CAUTION: You must set the proper bank before calling this routine */ spi_ss(0); spi_txrx(CMD_BFC(reg)); spi_txrx(val); spi_ss(1); }
/******************************************************************************* * Function Name : MSD_ReadBuffer * Description : Reads multiple block of data from the MSD. * Input : - pBuffer : pointer to the buffer that receives the data read * from the MSD. * - ReadAddr : MSD's internal address to read from. * - NumByteToRead : number of bytes to read from the MSD. * Output : None * Return : The MSD Response: - MSD_RESPONSE_FAILURE: Sequence failed * - MSD_RESPONSE_NO_ERROR: Sequence succeed *******************************************************************************/ u8 MSD_ReadBuffer(u8* pBuffer, u32 ReadAddr, u32 NumByteToRead) { u32 i = 0, NbrOfBlock = 0, Offset = 0; u8 rvalue = MSD_RESPONSE_FAILURE; /* Calculate number of blocks to read */ NbrOfBlock = NumByteToRead / BLOCK_SIZE; /* MSD chip select low */ spi_ss(_FLASH_NUM0,0); /* Data transfer */ while (NbrOfBlock --) { /* Send CMD17 (MSD_READ_SINGLE_BLOCK) to read one block */ MSD_SendCmd(MSD_READ_SINGLE_BLOCK, ReadAddr + Offset, 0xFF); /* Check if the MSD acknowledged the read block command: R1 response (0x00: no errors) */ if (MSD_GetResponse(MSD_RESPONSE_NO_ERROR)) { return MSD_RESPONSE_FAILURE; } /* Now look for the data token to signify the start of the data */ if (!MSD_GetResponse(MSD_START_DATA_SINGLE_BLOCK_READ)) { /* Read the MSD block data : read NumByteToRead data */ for (i = 0; i < BLOCK_SIZE; i++) { /* Read the pointed data */ *pBuffer = spi_send(DUMMY); /* Point to the next location where the byte read will be saved */ pBuffer++; } /* Set next read address*/ Offset += 512; /* get CRC bytes (not really needed by us, but required by MSD) */ spi_send(DUMMY); spi_send(DUMMY); /* Set response value to success */ rvalue = MSD_RESPONSE_NO_ERROR; } else { /* Set response value to failure */ rvalue = MSD_RESPONSE_FAILURE; } } /* MSD chip select high */ spi_ss(_FLASH_NUM0,1); /* Send dummy byte: 8 Clock pulses of delay */ spi_send(DUMMY); /* Returns the reponse */ return rvalue; }
u8 macphy_eth_readreg(u8 reg) { u8 x; /* CAUTION: You must set the proper bank before calling this routine */ spi_ss(0); spi_txrx(CMD_RCR(reg)); x = spi_txrx(0xff); spi_ss(1); return x; }
/******************************************************************************* * Function Name : MSD_GetStatus * Description : Returns the MSD status. * Input : None * Output : None * Return : The MSD status. *******************************************************************************/ u16 MSD_GetStatus(void) { u16 Status = 0; /* MSD chip select low */ spi_ss(_FLASH_NUM0,0); /* Send CMD13 (MSD_SEND_STATUS) to get MSD status */ MSD_SendCmd(MSD_SEND_STATUS, 0, 0xFF); Status = spi_send(DUMMY); Status |= (u16)(spi_send(DUMMY) << 8); /* MSD chip select high */ spi_ss(_FLASH_NUM0,1); /* Send dummy byte 0xFF */ spi_send(DUMMY); return Status; }
/******************************************************************************* * Function Name : MSD_WriteBlock * Description : Writes a block on the MSD * Input : - pBuffer : pointer to the buffer containing the data to be * written on the MSD. * - WriteAddr : address to write on. * - NumByteToWrite: number of data to write * Output : None * Return : The MSD Response: - MSD_RESPONSE_FAILURE: Sequence failed * - MSD_RESPONSE_NO_ERROR: Sequence succeed *******************************************************************************/ u8 MSD_WriteBlock(u8* pBuffer, u32 WriteAddr, u16 NumByteToWrite) { u32 i = 0; u8 rvalue = MSD_RESPONSE_FAILURE; return 0; /* MSD chip select low */ spi_ss(_FLASH_NUM0,0); /* Send CMD24 (MSD_WRITE_BLOCK) to write multiple block */ MSD_SendCmd(MSD_WRITE_BLOCK, WriteAddr, 0xFF); /* Check if the MSD acknowledged the write block command: R1 response (0x00: no errors) */ if (!MSD_GetResponse(MSD_RESPONSE_NO_ERROR)) { /* Send a dummy byte */ spi_send(DUMMY); /* Send the data token to signify the start of the data */ spi_send(0xFE); /* Write the block data to MSD : write count data by block */ for (i = 0; i < NumByteToWrite; i++) { /* Send the pointed byte */ spi_send(*pBuffer); /* Point to the next location where the byte read will be saved */ pBuffer++; } /* Put CRC bytes (not really needed by us, but required by MSD) */ spi_send(DUMMY); spi_send(DUMMY); /* Read data response */ if (MSD_GetDataResponse() == MSD_DATA_OK) { rvalue = MSD_RESPONSE_NO_ERROR; } } /* MSD chip select high */ spi_ss(_FLASH_NUM0,1); /* Send dummy byte: 8 Clock pulses of delay */ spi_send(DUMMY); /* Returns the reponse */ return rvalue; }
/******************************************************************************* * Function Name : MSD_ReadBlock * Description : Reads a block of data from the MSD. * Input : - pBuffer : pointer to the buffer that receives the data read * from the MSD. * - ReadAddr : MSD's internal address to read from. * - NumByteToRead : number of bytes to read from the MSD. * Output : None * Return : The MSD Response: - MSD_RESPONSE_FAILURE: Sequence failed * - MSD_RESPONSE_NO_ERROR: Sequence succeed *******************************************************************************/ u8 MSD_ReadBlock(u8* pBuffer, u32 ReadAddr, u16 NumByteToRead) { u32 i = 0; u8 rvalue = MSD_RESPONSE_FAILURE; return 0; /* MSD chip select low */ spi_ss(_FLASH_NUM0,0); /* Send CMD17 (MSD_READ_SINGLE_BLOCK) to read one block */ MSD_SendCmd(MSD_READ_SINGLE_BLOCK, ReadAddr, 0xFF); /* Check if the MSD acknowledged the read block command: R1 response (0x00: no errors) */ if (!MSD_GetResponse(MSD_RESPONSE_NO_ERROR)) { /* Now look for the data token to signify the start of the data */ if (!MSD_GetResponse(MSD_START_DATA_SINGLE_BLOCK_READ)) { /* Read the MSD block data : read NumByteToRead data */ for (i = 0; i < NumByteToRead; i++) { /* Save the received data */ *pBuffer = spi_send(DUMMY); /* Point to the next location where the byte read will be saved */ pBuffer++; } /* Get CRC bytes (not really needed by us, but required by MSD) */ spi_send(DUMMY); spi_send(DUMMY); /* Set response value to success */ rvalue = MSD_RESPONSE_NO_ERROR; } } /* MSD chip select high */ spi_ss(_FLASH_NUM0,1); /* Send dummy byte: 8 Clock pulses of delay */ spi_send(DUMMY); /* Returns the reponse */ return rvalue; }
/******************************************************************************* * Function Name : MSD_GoIdleState * Description : Put MSD in Idle state. * Input : None * Output : None * Return : The MSD Response: - MSD_RESPONSE_FAILURE: Sequence failed * - MSD_RESPONSE_NO_ERROR: Sequence succeed *******************************************************************************/ u8 MSD_GoIdleState(void) { /* MSD chip select low */ spi_ss(_FLASH_NUM0,0); /* Send CMD0 (GO_IDLE_STATE) to put MSD in SPI mode */ MSD_SendCmd(MSD_GO_IDLE_STATE, 0, 0x95); /* Wait for In Idle State Response (R1 Format) equal to 0x01 */ if (MSD_GetResponse(MSD_IN_IDLE_STATE)) { /* No Idle State Response: return response failue */ return MSD_RESPONSE_FAILURE; } /*----------Activates the card initialization process-----------*/ do { /* MSD chip select high */ spi_ss(_FLASH_NUM0,1); /* Send Dummy byte 0xFF */ spi_send(DUMMY); /* MSD chip select low */ spi_ss(_FLASH_NUM0,0); /* Send CMD1 (Activates the card process) until response equal to 0x0 */ MSD_SendCmd(MSD_SEND_OP_COND, 0, 0xFF); /* Wait for no error Response (R1 Format) equal to 0x00 */ } while (MSD_GetResponse(MSD_RESPONSE_NO_ERROR)); /* MSD chip select high */ spi_ss(_FLASH_NUM0,1); /* Send dummy byte 0xFF */ spi_send(DUMMY); return MSD_RESPONSE_NO_ERROR; }
u8 MSD_Init(void) { u32 i = 0; /* Initialize SPI1 */ spi_init(); /* MSD chip select high */ spi_ss(_FLASH_NUM0,1); /* Send dummy byte 0xFF, 10 times with CS high*/ /* rise CS and MOSI for 80 clocks cycles */ for (i = 0; i <= 9; i++) { /* Send dummy byte 0xFF */ spi_send(DUMMY); } /*------------Put MSD in SPI mode--------------*/ /* MSD initialized and set to SPI mode properly */ return (MSD_GoIdleState()); }
/* Transfers packet to ENC28J60 and initiates packet transmission */ void macphy_sendpkt(void) { u16 i; u8 x; u8 rlo, rhi; u8 status[7]; //u8* ptr_uip_appdata; //ptr_uip_appdata = (u8 *)(uip_appdata); /* Everything we need is in bank 0 */ macphy_setbank(0); /* Retrieve the rx pointer location -- set it back after we're done */ rlo = macphy_eth_readreg(ERDPTL); rhi = macphy_eth_readreg(ERDPTH); macphy_clearbit(ESTAT, TXABRT); macphy_clearbit(ESTAT, LATECOL); /* This code catches a potential silicon errata with the ENC28J60 */ x = macphy_eth_readreg(ECON1); while (x & TXRTS) { x = macphy_eth_readreg(EIR); if (x & TXERIF) { /* Chip is stuck. Reset */ //cprintf(C" -> MAC TX is stuck. Reset. \r\n"); Serial_PrintString("MAC TX is stuck. Reset. \r\n"); macphy_setbit(ECON1, TXRST); macphy_clearbit(ECON1, TXRST); macphy_clearbit(EIR, TXERIF); } x = macphy_eth_readreg(ECON1); } /* Set the SPI write buffer pointer location */ macphy_writereg(EWRPTL, 0x00); macphy_writereg(EWRPTH, 0x10); //Serial_PrintString("macphy_sendpkt() uip_len="); //Serial_PrintNumber(uip_len); //Serial_PrintString("\r\n"); /* Write the link-layer header to the chip */ /* SPI Write Pointer Start (ETXSTL) already set by macphy_init() */ spi_ss(0); spi_txrx(CMD_WBM); spi_txrx(0x00); /* "options" byte header needed by the ENC chip */ for (i = 0; i < UIP_LLH_LEN; i++) { /* uip_buf starts at offset 6, first 6 bytes are from the old RX packet */ spi_txrx(pkt_buf[6+i]); } if (uip_len <= UIP_LLH_LEN + UIP_TCPIP_HLEN) { /* Probably an ARP update or somesuch. No need to send appdata */ for (i = 0; i < uip_len - UIP_LLH_LEN; i++) { spi_txrx(pkt_buf[6+UIP_LLH_LEN+i]); } } else { /* We have link-layer header, IP header, and appdata */ for (i = 0; i < UIP_TCPIP_HLEN; i++) { /* IP header */ spi_txrx(pkt_buf[6+UIP_LLH_LEN+i]); } for (i = 0; i < uip_len - UIP_TCPIP_HLEN - UIP_LLH_LEN; i++) { spi_txrx(((u8 *)uip_appdata)[i]); //spi_txrx(*ptr_uip_appdata); //ptr_uip_appdata++; } } spi_ss(1); /* Set the MAC TX end pointer */ macphy_writereg(ETXNDL, (0x1000 + uip_len) & 0x00ff); macphy_writereg(ETXNDH, (0x1000 + uip_len) >> 8); /* Fire and forget! */ macphy_setbit(ECON1, TXRTS); /* Just in case, clear the transmit abort and late collision flags */ macphy_clearbit(ESTAT, TXABRT); macphy_clearbit(ESTAT, LATECOL); }
/* Reads packet from the ENC28J60 and decrements pktcnt */ void macphy_readpkt(void) { u8 rlo, rhi; u32 i, plen, nxtpkt, rptr; macphy_setbank(0); /* Retrieve the rx pointer location */ rlo = macphy_eth_readreg(ERDPTL); rhi = macphy_eth_readreg(ERDPTH); rptr = (rhi << 8) + rlo; spi_ss(0); spi_txrx(CMD_RBM); pkt_buf[0] = spi_txrx(0xff); /* Next packet pointer LSB */ pkt_buf[1] = spi_txrx(0xff); /* Next packet pointer MSB */ pkt_buf[2] = spi_txrx(0xff); /* status[7:0] */ pkt_buf[3] = spi_txrx(0xff); /* status[15:8] */ pkt_buf[4] = spi_txrx(0xff); /* status[23:16] */ pkt_buf[5] = spi_txrx(0xff); /* status[31:24] */ /* Calculate the remaining length of this packet */ nxtpkt = plen = (pkt_buf[1] << 8) + pkt_buf[0]; if (nxtpkt < rptr) { /* Wrapping case */ /* Explanation: RX buffer ends at byte 0xfff, so bytes between rptr and 0x1000 are */ /* part of the packet, plus the stuff that wrapped around to nxtpkt. Since plen holds */ /* nxtpkt already, we just need to add in the bytes before the wrap */ plen += (0x1000 - rptr); } else { /* Normal case */ plen -= rptr; } if (plen > (MAX_ETH_FRAMELEN + 6 + 1)) { //cprintf(C" - !! - PACKET LENGTH CORRUPTION - !! -\r\n"); Serial_PrintString(" - !! - PACKET LENGTH CORRUPTION - !! -\r\n"); while (1); } /* Could be off by one here due to the word alignment. If so, go ahead and accept. */ if ((plen != ((pkt_buf[3] << 8) + pkt_buf[2] + 6)) && (plen != ((pkt_buf[3] << 8) + pkt_buf[2] + 7))) { //cprintf(C" - !! - PACKET LENGTH MISMATCH - !! -\r\n"); Serial_PrintString(" - !! - PACKET LENGTH MISMATCH - !! -\r\n"); //cprintf(C" Status Vector said 0x%02x%02x (+6/+7), plen = 0x%04x\r\n", pkt_buf[3], pkt_buf[2], plen); Serial_PrintString(" Status Vector said, plen= "); Serial_PrintNumber(plen); Serial_PrintString("\r\n pkt_buf[3]= "); Serial_PrintByte(pkt_buf[3], 1); Serial_PrintString("\r\n pkt_buf[2]= "); Serial_PrintByte(pkt_buf[2], 1); //cprintf(C" Next packet pointer = 0x%02x%02x\r\n", pkt_buf[1], pkt_buf[0]); Serial_PrintString("\r\n Next packet pointer : pkt_buf[1]= "); Serial_PrintByte(pkt_buf[1], 1); Serial_PrintString("pkt_buf[0]= "); Serial_PrintByte(pkt_buf[0], 1); //cprintf(C" SPI Read Pointer = 0x%04x\r\n", rptr); Serial_PrintString("\r\n SPI Read Pointer = "); Serial_PrintNumber(rptr); Serial_PrintString("\r\n"); macphy_readback(); } /* Ethernet frame follows here */ for (i = 6; i < plen; i++) { pkt_buf[i] = spi_txrx(0xff); } spi_ss(1); /* Free up space by moving ERXRDPT forward and setting the PKTDEC bit */ if (nxtpkt > 0xfff) { //cprintf(C" - !! - NEXT PACKET POINTER CORRUPTION - !! -\r\n"); Serial_PrintString(" - !! - NEXT PACKET POINTER CORRUPTION - !! -\r\n"); while (1); } nxtpkt -= 1; if (nxtpkt > 0xfff) { /* Wrap around. Fix up. */ nxtpkt = 0xfff; } macphy_writereg(ERXRDPTL, nxtpkt & 0xff); macphy_writereg(ERXRDPTH, nxtpkt >> 8); macphy_pktdec(); }
/******************************************************************************* * Function Name : MSD_GetCIDRegister * Description : Read the CID card register. * Reading the contents of the CID register in SPI mode * is a simple read-block transaction. * Input : - MSD_cid: pointer on an CID register structure * Output : None * Return : The MSD Response: - MSD_RESPONSE_FAILURE: Sequence failed * - MSD_RESPONSE_NO_ERROR: Sequence succeed *******************************************************************************/ u8 MSD_GetCIDRegister(sMSD_CID* MSD_cid) { u32 i = 0; u8 rvalue = MSD_RESPONSE_FAILURE; u8 CID_Tab[16]; /* MSD chip select low */ spi_ss(_FLASH_NUM0,0); /* Send CMD10 (CID register) */ MSD_SendCmd(MSD_SEND_CID, 0, 0xFF); /* Wait for response in the R1 format (0x00 is no errors) */ if (!MSD_GetResponse(MSD_RESPONSE_NO_ERROR)) { if (!MSD_GetResponse(MSD_START_DATA_SINGLE_BLOCK_READ)) { /* Store CID register value on CID_Tab */ for (i = 0; i < 16; i++) { CID_Tab[i] = spi_send(DUMMY); } } /* Get CRC bytes (not really needed by us, but required by MSD) */ spi_send(DUMMY); spi_send(DUMMY); /* Set response value to success */ rvalue = MSD_RESPONSE_NO_ERROR; } /* MSD chip select high */ spi_ss(_FLASH_NUM0,1); /* Send dummy byte: 8 Clock pulses of delay */ spi_send(DUMMY); /* Byte 0 */ MSD_cid->ManufacturerID = CID_Tab[0]; /* Byte 1 */ MSD_cid->OEM_AppliID = CID_Tab[1] << 8; /* Byte 2 */ MSD_cid->OEM_AppliID |= CID_Tab[2]; /* Byte 3 */ MSD_cid->ProdName1 = CID_Tab[3] << 24; /* Byte 4 */ MSD_cid->ProdName1 |= CID_Tab[4] << 16; /* Byte 5 */ MSD_cid->ProdName1 |= CID_Tab[5] << 8; /* Byte 6 */ MSD_cid->ProdName1 |= CID_Tab[6]; /* Byte 7 */ MSD_cid->ProdName2 = CID_Tab[7]; /* Byte 8 */ MSD_cid->ProdRev = CID_Tab[8]; /* Byte 9 */ MSD_cid->ProdSN = CID_Tab[9] << 24; /* Byte 10 */ MSD_cid->ProdSN |= CID_Tab[10] << 16; /* Byte 11 */ MSD_cid->ProdSN |= CID_Tab[11] << 8; /* Byte 12 */ MSD_cid->ProdSN |= CID_Tab[12]; /* Byte 13 */ MSD_cid->Reserved1 |= (CID_Tab[13] & 0xF0) >> 4; /* Byte 14 */ MSD_cid->ManufactDate = (CID_Tab[13] & 0x0F) << 8; /* Byte 15 */ MSD_cid->ManufactDate |= CID_Tab[14]; /* Byte 16 */ MSD_cid->CRC = (CID_Tab[15] & 0xFE) >> 1; MSD_cid->Reserved2 = 1; /* Return the reponse */ return rvalue; }
/******************************************************************************* * Function Name : MSD_GetCSDRegister * Description : Read the CSD card register. * Reading the contents of the CSD register in SPI mode * is a simple read-block transaction. * Input : - MSD_csd: pointer on an SCD register structure * Output : None * Return : The MSD Response: - MSD_RESPONSE_FAILURE: Sequence failed * - MSD_RESPONSE_NO_ERROR: Sequence succeed *******************************************************************************/ u8 MSD_GetCSDRegister(sMSD_CSD* MSD_csd) { u32 i = 0; u8 rvalue = MSD_RESPONSE_FAILURE; u8 CSD_Tab[16]; /* MSD chip select low */ spi_ss(_FLASH_NUM0,0); /* Send CMD9 (CSD register) or CMD10(CSD register) */ MSD_SendCmd(MSD_SEND_CSD, 0, 0xFF); /* Wait for response in the R1 format (0x00 is no errors) */ if (!MSD_GetResponse(MSD_RESPONSE_NO_ERROR)) { if (!MSD_GetResponse(MSD_START_DATA_SINGLE_BLOCK_READ)) { for (i = 0; i < 16; i++) { /* Store CSD register value on CSD_Tab */ CSD_Tab[i] = spi_send(DUMMY); } } /* Get CRC bytes (not really needed by us, but required by MSD) */ spi_send(DUMMY); spi_send(DUMMY); /* Set response value to success */ rvalue = MSD_RESPONSE_NO_ERROR; } /* MSD chip select high */ spi_ss(_FLASH_NUM0,1); /* Send dummy byte: 8 Clock pulses of delay */ spi_send(DUMMY); /* Byte 0 */ MSD_csd->CSDStruct = (CSD_Tab[0] & 0xC0) >> 6; MSD_csd->SysSpecVersion = (CSD_Tab[0] & 0x3C) >> 2; MSD_csd->Reserved1 = CSD_Tab[0] & 0x03; /* Byte 1 */ MSD_csd->TAAC = CSD_Tab[1] ; /* Byte 2 */ MSD_csd->NSAC = CSD_Tab[2]; /* Byte 3 */ MSD_csd->MaxBusClkFrec = CSD_Tab[3]; /* Byte 4 */ MSD_csd->CardComdClasses = CSD_Tab[4] << 4; /* Byte 5 */ MSD_csd->CardComdClasses |= (CSD_Tab[5] & 0xF0) >> 4; MSD_csd->RdBlockLen = CSD_Tab[5] & 0x0F; /* Byte 6 */ MSD_csd->PartBlockRead = (CSD_Tab[6] & 0x80) >> 7; MSD_csd->WrBlockMisalign = (CSD_Tab[6] & 0x40) >> 6; MSD_csd->RdBlockMisalign = (CSD_Tab[6] & 0x20) >> 5; MSD_csd->DSRImpl = (CSD_Tab[6] & 0x10) >> 4; MSD_csd->Reserved2 = 0; /* Reserved */ MSD_csd->DeviceSize = (CSD_Tab[6] & 0x03) << 10; /* Byte 7 */ MSD_csd->DeviceSize |= (CSD_Tab[7]) << 2; /* Byte 8 */ MSD_csd->DeviceSize |= (CSD_Tab[8] & 0xC0) >> 6; MSD_csd->MaxRdCurrentVDDMin = (CSD_Tab[8] & 0x38) >> 3; MSD_csd->MaxRdCurrentVDDMax = (CSD_Tab[8] & 0x07); /* Byte 9 */ MSD_csd->MaxWrCurrentVDDMin = (CSD_Tab[9] & 0xE0) >> 5; MSD_csd->MaxWrCurrentVDDMax = (CSD_Tab[9] & 0x1C) >> 2; MSD_csd->DeviceSizeMul = (CSD_Tab[9] & 0x03) << 1; /* Byte 10 */ MSD_csd->DeviceSizeMul |= (CSD_Tab[10] & 0x80) >> 7; MSD_csd->EraseGrSize = (CSD_Tab[10] & 0x7C) >> 2; MSD_csd->EraseGrMul = (CSD_Tab[10] & 0x03) << 3; /* Byte 11 */ MSD_csd->EraseGrMul |= (CSD_Tab[11] & 0xE0) >> 5; MSD_csd->WrProtectGrSize = (CSD_Tab[11] & 0x1F); /* Byte 12 */ MSD_csd->WrProtectGrEnable = (CSD_Tab[12] & 0x80) >> 7; MSD_csd->ManDeflECC = (CSD_Tab[12] & 0x60) >> 5; MSD_csd->WrSpeedFact = (CSD_Tab[12] & 0x1C) >> 2; MSD_csd->MaxWrBlockLen = (CSD_Tab[12] & 0x03) << 2; /* Byte 13 */ MSD_csd->MaxWrBlockLen |= (CSD_Tab[13] & 0xc0) >> 6; MSD_csd->WriteBlockPaPartial = (CSD_Tab[13] & 0x20) >> 5; MSD_csd->Reserved3 = 0; MSD_csd->ContentProtectAppli = (CSD_Tab[13] & 0x01); /* Byte 14 */ MSD_csd->FileFormatGrouop = (CSD_Tab[14] & 0x80) >> 7; MSD_csd->CopyFlag = (CSD_Tab[14] & 0x40) >> 6; MSD_csd->PermWrProtect = (CSD_Tab[14] & 0x20) >> 5; MSD_csd->TempWrProtect = (CSD_Tab[14] & 0x10) >> 4; MSD_csd->FileFormat = (CSD_Tab[14] & 0x0C) >> 2; MSD_csd->ECC = (CSD_Tab[14] & 0x03); /* Byte 15 */ MSD_csd->CRC = (CSD_Tab[15] & 0xFE) >> 1; MSD_csd->Reserved4 = 1; /* Return the reponse */ return rvalue; }