/*This class includes: - CFA TRANSLATE SECTOR - IDENTIFY DEVICE - IDENTIFY PACKET DEVICE - READ BUFFER - READ MULTIPLE - READ SECTOR(S) - SMART READ DATA*/ int ata_issue_pio_in_cmd(ATA_Device_t *ata_dev, unsigned long sector_cnt, unsigned char *data_buf) { int error, j; unsigned long i; unsigned char status, err_reg; unsigned short *word_buf; unsigned char *byte_buf; #ifdef CF_USE_PIO_DMA INT8U err; #endif error = ata_wait_status_bits(ATA_STATUS_BSY|ATA_STATUS_DRQ, 0, ATA_CMD_READY_TIMEOUT); if(error) return error; ata_write_reg(ATA_REATURES_REG, ata_dev->ata_param.Features); ata_write_reg(ATA_SECTOR_COUNT_REG, ata_dev->ata_param.Sector_Count); ata_write_reg(ATA_SECTOR_NUMBER_REG, ata_dev->ata_param.Sector_Number); ata_write_reg(ATA_CYLINDER_LOW_REG, ata_dev->ata_param.Cylinder_Low); ata_write_reg(ATA_CYLINDER_HIGH_REG, ata_dev->ata_param.Cylinder_High); ata_write_reg(ATA_DEVICE_HEAD_REG, ata_dev->ata_param.Device_Head); ata_write_reg(ATA_COMMAND_REG, ata_dev->ata_param.Command); ata_delay_100ns(ATA_CMD_ISSUE_DELAY); for(i=0; i<sector_cnt; i++) { if(ata_dma_buf != NULL && ata_dma_buf_size >= ATA_DRQ_BLK_LENGTH_BYTE) { word_buf = (void *)(ata_dma_buf); byte_buf = ata_dma_buf; } else { word_buf = (void *)ata_dev->ata_buf; byte_buf = ata_dev->ata_buf; } //This prevents polling host from reading status before it is valid. status = ata_read_reg(ATA_ALT_STATUS_REG); error = ata_wait_status_bits(ATA_STATUS_BSY|ATA_STATUS_DRQ, ATA_STATUS_DRQ, ATA_CMD_READY_TIMEOUT*3); if(error) { while(read_status_count--) { status = ata_read_reg(ATA_STATUS_REG); if((status & (ATA_STATUS_BSY|ATA_STATUS_DRQ)) == ATA_STATUS_DRQ) { read_status_count = 1; return error; } else ata_delay_ms(1); } if(status & ATA_STATUS_ERR) { err_reg = ata_read_reg(ATA_ERROR_REG); } return error; } #ifdef CF_USE_PIO_DMA atapi_dma_add_work( (unsigned)word_buf, // to/From data location in SDRAM 0, // Endian setting: 0,1,2 or 3 0, // Level on the Cable select pin during DMA 0, // set to 1 if transfering TO the ATAPI device 0, // Multi-DMA Mode: 0, 1, 2 or 3 (ignored for UDMA) 2, // Type: 0 = Standard DMA, 1 = Ultra DMA, 2 =PIO DMA (new feature) 0, // PIO Address: 0,1,..,15. Used for DMA to PIO address (new feature) ATA_DRQ_BLK_LENGTH_BYTE, // Number of bytes to transfer (must be divisible by 2) atapi_dma_done, // callback NULL); // callback arguments AVSemPend(atapi_dma_done_event, 0, &err); #else if (cf_special_flag) { if(ATA_EIGHT_BIT_ENABLED) { for(j=0; j<ATA_DRQ_BLK_LENGTH_BYTE; j++) { *(byte_buf + j) = ata_read_data(); status = ata_read_reg(ATA_STATUS_REG); } } else { for(j=0; j<ATA_DRQ_BLK_LENGTH_WORD; j++) { *(word_buf + j) = ata_read_data(); status = ata_read_reg(ATA_STATUS_REG); } } } else { if(ATA_EIGHT_BIT_ENABLED) { for(j=0; j<ATA_DRQ_BLK_LENGTH_BYTE; j++) { *(byte_buf + j) = ata_read_data(); } } else { for(j=0; j<ATA_DRQ_BLK_LENGTH_WORD; j++) { *(word_buf + j) = ata_read_data(); } } } #endif #ifdef AMLOGIC_CHIP_SUPPORT if((unsigned long)data_buf == 0x3400000) { for(j=0; j<ATA_DRQ_BLK_LENGTH_BYTE; j++) { WRITE_BYTE_TO_FIFO(*byte_buf++); } } else #endif { memcpy(data_buf, byte_buf, ATA_DRQ_BLK_LENGTH_BYTE); data_buf += ATA_DRQ_BLK_LENGTH_BYTE; } } //This prevents polling host from reading status before it is valid. status = ata_read_reg(ATA_ALT_STATUS_REG); //Status register is read to clear pending interupt. status = ata_read_reg(ATA_STATUS_REG); return ATA_NO_ERROR; }
int xd_sm_read_cycle2(unsigned char column_addr, unsigned long page_addr, unsigned char *data_buf, unsigned long data_cnt, unsigned char *redundant_buf) { int err; unsigned long data_nums = 0, data_offset = 0, read_cnt; if(xd_sm_page_size != XD_SM_SECTOR_SIZE) return XD_SM_ERROR_PARAMETER; xd_sm_cmd_input_cycle(XD_SM_READ2, XD_SM_WRITE_DISABLED); xd_sm_addr_input_cycle((page_addr << 8)|column_addr, xd_sm_buf->addr_cycles); #ifdef XD_CARD_SUPPORTED if(xd_sm_info->card_type == CARD_TYPE_XD) { xd_set_dat0_7_input(); xd_sm_delay_60ns(); // Tar2 = 50ns } #endif #ifdef SM_CARD_SUPPORTED if(xd_sm_info->card_type == CARD_TYPE_SM) { sm_set_dat0_7_input(); xd_sm_delay_100ns(2); // Tar2 = 150ns } #endif read_cnt = xd_sm_page_size - (XD_SM_SECTOR_SIZE/2 + column_addr); while(data_nums < data_cnt) { err = xd_sm_wait_ready(XD_BUSY_TIME_R); if(err) { #ifdef XD_CARD_SUPPORTED if(xd_sm_info->card_type == CARD_TYPE_XD) xd_set_ce_disable(); #endif #ifdef SM_CARD_SUPPORTED if(xd_sm_info->card_type == CARD_TYPE_SM) sm_set_ce_disable(); #endif return err; } xd_sm_delay_20ns(); // Trr = 20ns #ifdef XD_SM_ECC_CHECK xd_sm_serial_read_cycle(xd_sm_buf->page_buf, read_cnt, redundant_buf, xd_sm_redundant_size); err = xd_sm_check_page_ecc(xd_sm_buf->page_buf, redundant_buf); if(err) { if(err == ECC_ERROR_CORRECTED) { #ifdef XD_SM_DEBUG Debug_Printf("Data ECC error occured, but corrected!\n"); #endif } else { #ifdef XD_SM_DEBUG err = XD_SM_ERROR_ECC; Debug_Printf("#%s error occured in xd_sm_read_data()\n", xd_sm_error_to_string(err)); #endif } } #ifdef AMLOGIC_CHIP_SUPPORT if((unsigned long)data_buf == 0x3400000) { for(int i=0; i<read_cnt; i++) { WRITE_BYTE_TO_FIFO(xd_sm_buf->page_buf[i]); xd_sm_delay_100ns(1); } } else #endif { memcpy(data_buf+data_offset, xd_sm_buf->page_buf, read_cnt); } #else xd_sm_serial_read_cycle(data_buf+data_offset, read_cnt, redundant_buf, xd_sm_redundant_size); #endif #ifdef AMLOGIC_CHIP_SUPPORT data_offset += ((unsigned long)data_buf == 0x3400000 ? 0 : read_cnt); #else data_offset += read_cnt; #endif redundant_buf += xd_sm_redundant_size; data_nums += read_cnt; read_cnt = xd_sm_page_size; } #ifdef XD_CARD_SUPPORTED if(xd_sm_info->card_type == CARD_TYPE_XD) { xd_set_ce_disable(); xd_sm_delay_100ns(1); // Tceh = 100ns } #endif #ifdef SM_CARD_SUPPORTED if(xd_sm_info->card_type == CARD_TYPE_SM) { sm_set_ce_disable(); xd_sm_delay_100ns(3); // Tceh = 250ns } #endif err = xd_sm_wait_ready(BUSY_TIME_TCRY); return err; }