int ata_sw_reset_dev(ATA_Device_t *ata_dev) { int error; #ifdef ATA_DEBUG Debug_Printf("ATA reset processing...\n"); #endif ata_write_reg(ATA_DEVICE_CONTROL_REG, ATA_DEV_CTL_nIEN | ATA_DEV_CTL_SRST); ata_delay_ms(2); ata_write_reg(ATA_DEVICE_CONTROL_REG, ATA_DEV_CTL_nIEN); ata_delay_ms(2); ata_write_reg(ATA_DEVICE_HEAD_REG, ata_dev->current_dev ? ATA_DRIVE1_MASK : ATA_DRIVE0_MASK); ata_delay_100ns(ATA_CMD_ISSUE_DELAY); error = ata_wait_status_bits(ATA_STATUS_BSY|ATA_STATUS_DRDY, ATA_STATUS_DRDY, ATA_CMD_INIT_TIMEOUT); if(error) return error; ata_write_reg(ATA_DEVICE_HEAD_REG, ata_dev->current_dev? ATA_DRIVE1_MASK : ATA_DRIVE0_MASK); ata_delay_100ns(ATA_CMD_ISSUE_DELAY); return ATA_NO_ERROR; }
void cf_hw_reset() { /* if(ata_cf_info->ata_cf_reset) // { ata_cf_info->ata_cf_reset(1); } else { cf_set_reset_output(); cf_set_reset_high(); } */ #ifdef CF_POWER_CONTROL cf_power_off(); #endif ata_delay_ms(200); #ifdef CF_POWER_CONTROL cf_power_on(); ata_delay_ms(300); #endif if(ata_cf_info->ata_cf_reset) { ata_cf_info->ata_cf_reset(0); } else { cf_set_reset_output(); cf_set_reset_low(); } ata_delay_ms(100); if(ata_cf_info->ata_cf_reset) { ata_cf_info->ata_cf_reset(1); } else { cf_set_reset_output(); cf_set_reset_high(); } ata_delay_ms(200); }
int ata_wait_status_bits(unsigned char bits_mask, unsigned char bits_value, unsigned long timeout) { unsigned long cnt = 0; unsigned char status; while(cnt++ < timeout) { status = ata_read_reg(ATA_STATUS_REG); if((status & bits_mask) == bits_value) return ATA_NO_ERROR; else { #ifdef CONFIG_CF if(!cf_check_insert()) return ATA_ERROR_NO_DEVICE; #endif ata_delay_ms(1); } } return ATA_ERROR_TIMEOUT; }
void cf_power_on(void) { ata_delay_ms(cf_power_delay+1); if(card_share_ins_pwr_flag[CARD_MODULE_CF]) card_power_off_flag[CARD_COMPACT_FLASH] = 1; #ifdef CF_POWER_CONTROL if(ata_cf_info->ata_cf_power) { if(cf_check_insert()) { ata_cf_info->ata_cf_power(1); } } else { if(cf_check_insert()) { cf_set_enable(); } } #endif }
int ata_init_device(ATA_Device_t *ata_dev) { /*_phymem_node_t *memmap = Am_GetSystemMem(MEMMAP_DEFAULT, MEMITEM_DMA_DRAM); if(memmap != NULL) { ata_dma_buf = (void *)(memmap->start); ata_dma_buf_size = memmap->end - memmap->start + 1; }*/ //memset(ata_dev, 0, sizeof(ATA_Device_t)); int error = ATA_NO_ERROR, dev, dev_existed = 0; unsigned char reg_data, device_head = 0; ata_dev->master_disabled = ATA_MASTER_DISABLED; ata_dev->slave_enabled = ATA_SLAVE_ENABLED; #ifdef ATA_DEBUG Debug_Printf("Start to poll ATA status, wait BUSY cleared to zero...\n"); #endif ata_write_reg(ATA_DEVICE_CONTROL_REG, ATA_DEV_CTL_nIEN); ata_delay_100ns(ATA_CMD_ISSUE_DELAY); for(dev=0; dev<2; dev++) { if(!dev && ata_dev->master_disabled) continue; else if(dev && !ata_dev->slave_enabled) continue; if(ata_dev->device_info[dev].device_existed) { dev_existed = 1; continue; } reg_data = dev ? ATA_DRIVE1_MASK : ATA_DRIVE0_MASK; ata_write_reg(ATA_DEVICE_HEAD_REG, reg_data); ata_delay_ms(2); error = ata_wait_status_bits(ATA_STATUS_BSY|ATA_STATUS_DRDY, ATA_STATUS_DRDY, ATA_CMD_INIT_TIMEOUT); if(error) { ata_dev->device_info[dev].device_inited = 0; continue; } ata_write_reg(ATA_SECTOR_COUNT_REG, 0x55); ata_delay_100ns(ATA_CMD_ISSUE_DELAY); reg_data = ata_read_reg(ATA_SECTOR_COUNT_REG); if(reg_data != 0x55) { ata_dev->device_info[dev].device_inited = 0; error = ATA_ERROR_HARDWARE_FAILURE; continue; } ata_write_reg(ATA_SECTOR_NUMBER_REG, 0xAA); ata_delay_100ns(ATA_CMD_ISSUE_DELAY); reg_data = ata_read_reg(ATA_SECTOR_NUMBER_REG); if(reg_data != 0xAA) { ata_dev->device_info[dev].device_inited = 0; error = ATA_ERROR_HARDWARE_FAILURE; continue; } ata_dev->device_info[dev].device_existed = 1; dev_existed = 1; if(ATA_EIGHT_BIT_ENABLED) { device_head = dev ? ATA_DRIVE1_MASK : ATA_DRIVE0_MASK; ata_dev->ata_param.Device_Head = device_head; ata_dev->ata_param.Features = 0x01; ata_dev->ata_param.Command = ATA_SET_FEATURES; error = ata_set_features(ata_dev); if(error) return error; } } if(dev_existed) { #if ((defined CF_USE_PIO_DMA) || (defined HD_USE_DMA)) atapi_dma_init(); if (!atapi_dma_done_event) atapi_dma_done_event = AVSemCreate(0); #endif return ATA_NO_ERROR; } else return error; }
/*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; }