/*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;
}
Ejemplo n.º 2
0
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;
}