⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ide_ata.c

📁 IDE 驱动程序对开发硬盘驱动很有用,对学习LINUX驱动开发有帮助
💻 C
📖 第 1 页 / 共 5 页
字号:
		OS_MsgQSend(msgQID, (char *)&msg, sizeof(msg), OS_WAIT_FOREVER, OS_MSG_PRI_NORMAL);
		
		// Wait for the semaphore to be released
		OS_SemTake(msg.cmd.ideCmd.semID, OS_WAIT_FOREVER);
		OS_SemGive(msg.cmd.ideCmd.semID);

		// modify for flash card hot plug
		return hdd_scheduler_get_cmd_ret(driveno);
		//return SUCCESS;
	}
#else
	return ide_exec(driveno, sector, buffer, count, reading, FALSE);
#endif
}

//------------------------------------------------------------------------
int ide_exec(
			  Uint8      driveno,
			  Uint32      sector,
			  void        *buffer,
			  Uint16      count,
			  Uint8       reading,
			  Boolean     use_cache
			  )
{
	Uint32  ltemp;
	Uint16  phys_disk;
	Uint8   ret_val = 0;

	setATAError(0);
	DEBUG_OUT("ide_exec: diskno: %d driveno[%d] drv_start[0x%x]\n", driveDesc[driveno].phys_disk, driveno, driveDesc[driveno].drv_start);
	if (!count)     /* Must have a count */
	{
		TRACE_ERROR("ide_exec fail 1\n");
        return SUCCESS;
	}

	if (!driveDesc[driveno].open_count)
	{
		TRACE_ERROR("ide_exec fail 2\n");
		return IDE_BADDRIVE;
	}

	phys_disk = driveDesc[driveno].phys_disk;   // 0 to NDISKS
	TRACE_48BIT("ide_exec driveno: %d phys_disk: %d\n", driveno, phys_disk);

	sector += driveDesc[driveno].drv_start;   /* Add in the start of partition */
	ltemp   = sector + count - 1;
	
	/* Check the partition end.*/
	if (ltemp > driveDesc[driveno].drv_end)
	{
		TRACE_ERROR("ide_exec fail 3\n");
		return IDE_BADPARM;
	}

    
	if (reading)
	{
	/*
		 if ( diskDesc[phys_disk].IsRemovableMediaDevice )
		{
			int i;
			for ( i = 0;  i < count; i++ )
				ret_val = ide_command_read_sectors((Uint8 *) buffer + (512 *i), phys_disk, sector + i, 1, use_cache);
		}
		else
	*/			
		{
			ret_val = ide_command_read_sectors((Uint8 *)buffer, phys_disk, sector, count, use_cache);
		}
	}
	else
	{
		if ( diskDesc[phys_disk].IsRemovableMediaDevice )
		{
			int i;
			for ( i = 0;  i < count; i++ )
				ret_val = ide_command_write_sectors((Uint8 *)buffer + (512 *i), phys_disk, sector + i, 1, use_cache);
		}
		else
		{
			ret_val = ide_command_write_sectors((Uint8 *)buffer, phys_disk, sector, count, use_cache);
		}
	}
	
	setATAError(ret_val);
	return (ret_val);
}


//-----------------------------------------------------------------------------
//  Function: ide_command_read_sectors
//
//  Description:
//   
//      Called by ide_io and ide_open
//
//-----------------------------------------------------------------------------
#if 1
static Int32 ide_command_read_sectors(
								Uint8 *address,	    // Destination address for the data
								Uint16 disk, 			// Drive number
								Uint32 blockno, 		// Block number to read
								Uint16 nblocks,			// Number of blocks (legal range: 1-256)
								Boolean use_cache
								)
{
	IDE_Cmd cmd;
	int     ret = 0, begin, end;

	/* Check against max_blocks. this is 256 for IDE. In real mode 80xx we limit
	it to 128 to eliminate segment wrap. */
	if (nblocks > MAX_BLOCKS)
	{
		ErrPrint(" IDE_INTERNAL nblocks=%d\n",nblocks);
		return IDE_INTERNAL;
	}
	
	if ( !diskDesc[disk].MediaDeviceBrand == MEDIADEVICE_BRAND_SAIN )
		if (!(diskDesc[disk].maxLBA)) /* Should be non zeroe if the disk was initialized */
		{
			ErrPrint(" IDE_INTERNAL diskDesc[%d].maxLBA=%d\n",disk,diskDesc[disk].maxLBA);
			return IDE_INTERNAL;
		}

	begin = 0;
	end   = nblocks;
	if ((use_cache == TRUE) && (address != NULL))
	{
		Uint32 index = 0;
		Boolean used_io = FALSE;

		if (nblocks > 1)
		{
			TRACE_CACHE("!!!!!!!!!!!!!! nblocks: %d\n", nblocks);
		}

		while (begin < end)
		{
			// Try to get a continuous stretch from the beginning in the cache
			for (index = begin; index < end; index++) 
			{
				ret = readFromCache(&ide_cache[disk], blockno + index, address + (index * HD_SECTOR_SIZE));
				if (ret == -1)
					break;
			}
			begin = index;
		
			if (begin < end) 
			{
				Uint8 *buf;
				// We did not find everything in the cache
				// Now we must bulk load from the smallest needed sector
				// The first sector that we don't have is blockno + begin
				// We always want to load up the maximum available
				Uint32 cache_load_size;
				Int32 ret;
				used_io = TRUE;
				cache_load_size = getCacheSize(&ide_cache[disk]);

				if (diskDesc[disk].currentMultipleTransfer == 0)
				{
					cache_load_size = 1;
				}
				/*else 
				{
					if (cache_load_size > diskDesc[disk].currentMultipleTransfer)
						cache_load_size = diskDesc[disk].currentMultipleTransfer;
				}*/
				
				TRACE_CACHE("!!!!!!!!!!!!!!! Bulk loading to cache starting sector: %d size: %d\n", (blockno + begin), cache_load_size);
				ret = bulkLoadToCache(&ide_cache[disk], (blockno + begin), cache_load_size, &buf);
				soft_assert(ret == 0);
				
				if (diskDesc[disk].supports48bitAddFeatureSet)
				{
					cmd.ext_cmd = TRUE;
					if (cache_load_size == 1)
						cmd.cmdCode = IDE_CMD_READS_EXT;
					else
						cmd.cmdCode = IDE_CMD_READM_EXT;
				}
				else
				{
					cmd.ext_cmd = FALSE;
					if (cache_load_size == 1)
						cmd.cmdCode = IDE_CMD_READS;
					else
						cmd.cmdCode = IDE_CMD_READM;
				}

				//Due to the size of sectorCntReg(Uint8), if (nblocks - i) == 256, sectorCntReg will be 0
				cmd.sectorCntReg    = cache_load_size;
				cmd.lba             = blockno + begin;
				cmd.driveID         = disk;
				if ((diskDesc[disk].IsRemovableMediaDevice ) && (diskDesc[disk].MediaDeviceBrand == MEDIADEVICE_BRAND_SAIN))
					cmd.featureReg  = 1;   
				else
					cmd.featureReg  = 0;
				cmd.pktCmd          = NULL;
				cmd.pktCmdSize      = 0;
				cmd.data            = buf;
				cmd.deviceReg       = LBA_MODE;
				cmd.readWrite       = IDE_CMD_READ;
				cmd.maxDataSize     = HD_SECTOR_SIZE * cache_load_size;

				TRACE_READ(" block %x sectorCntReg: %d driveID: %d data: 0x%x maxDataSize: %d\n",
					cmd.lba, cmd.sectorCntReg, cmd.driveID, cmd.data, cmd.maxDataSize);
				return (IDE_SendCmd(&cmd));			
			}
		}
		if (used_io == FALSE)
		{
			//TRACE_CACHE("!!!!!!!!!!!!!! Loaded completely from cache starting sector: %d size: %d\n", blockno, nblocks);
		}
	}
	else
	{
		if (diskDesc[disk].supports48bitAddFeatureSet)
		{
			cmd.ext_cmd = TRUE;
			if ((end - begin) == 1)
				cmd.cmdCode = IDE_CMD_READS_EXT;
			else
				cmd.cmdCode = IDE_CMD_READM_EXT;
		}
		else
		{
			cmd.ext_cmd = FALSE;
			if (((end - begin) == 1) || (diskDesc[disk].currentMultipleTransfer <= 1))
				cmd.cmdCode = IDE_CMD_READS;
			else
				cmd.cmdCode = IDE_CMD_READM;
		}
		
		//Due to the size of sectorCntReg(Uint8), if (nblocks - i) == 256, sectorCntReg will be 0
		cmd.sectorCntReg    = end - begin;
		cmd.lba             = blockno + begin;
		cmd.driveID         = disk;
		if ((diskDesc[disk].IsRemovableMediaDevice ) && (diskDesc[disk].MediaDeviceBrand == MEDIADEVICE_BRAND_SAIN))
			cmd.featureReg  = 1;   
		else
			cmd.featureReg  = 0;
		cmd.pktCmd          = NULL;
		cmd.pktCmdSize      = 0;
		cmd.data            = address + (begin * HD_SECTOR_SIZE);
		cmd.deviceReg       = LBA_MODE;
		cmd.readWrite       = IDE_CMD_READ;
		cmd.maxDataSize     = HD_SECTOR_SIZE * (end - begin);

		TRACE_READ(" block %x sectorCntReg: %d driveID: %d data: 0x%x maxDataSize: %d\n",
			cmd.lba, cmd.sectorCntReg, cmd.driveID, cmd.data, cmd.maxDataSize);
		return (IDE_SendCmd(&cmd));
	}
	return SUCCESS;
}
#else
static Int32 ide_command_read_sectors (
								Uint8 * address,	    // Destination address for the data
								Uint16 disk, 			// Drive number
								Uint32 blockno, 		// Block number to read
								Uint16 nblocks,			// Number of blocks (legal range: 1-256)
								Boolean use_cache
								)
{
	IDE_Cmd cmd;
	int ret=0, begin, end, j;

	/* Check against max_blocks. this is 256 for IDE. In real mode 80xx we limit
	it to 128 to eliminate segment wrap. */
	if (nblocks > MAX_BLOCKS)
	{
		ErrPrint(" IDE_INTERNAL \n");
        return IDE_INTERNAL;
	}

	if (!(diskDesc[disk].maxLBA)) /* Should be non zeroe if the disk was initialized */
	{
		ErrPrint(" IDE_INTERNAL \n");
        return IDE_INTERNAL;
	}

	begin = 0;
	if (use_cache == TRUE)
	{
		// Try to get a continuous stretch from the beginning in the cache
		for (begin=0; begin<nblocks; begin++) {
			ret = readFromCache(&ide_cache[disk], blockno+begin, address + (begin*HD_SECTOR_SIZE));
			if (ret == -1)
				break;
		}
	}
	end = nblocks;
	if (begin < nblocks) 
	{
		if (use_cache == TRUE)
		{
			// We did not find everything in the cache
			// Try to get a continous stretch from the end in the cache
			for (end=nblocks-1; end>begin; end--) 
			{
				ret = readFromCache(&ide_cache[disk], blockno+end, address + (end*HD_SECTOR_SIZE));
				if (ret == -1)
					break;
			}
			end++;
		}

		if ((end - begin) == 1)
			cmd.cmdCode = IDE_CMD_READS;
		else
			cmd.cmdCode = IDE_CMD_READM;
		
		//Due to the size of sectorCntReg(Uint8), if (nblocks - i) == 256, sectorCntReg will be 0
		cmd.sectorCntReg = end - begin;
		cmd.lba = blockno + begin;
		cmd.driveID = diskDesc[disk].driveID;
		cmd.featureReg = 0;
		cmd.pktCmd = NULL;
		cmd.pktCmdSize = 0;
		cmd.data = address + (begin*HD_SECTOR_SIZE);
		cmd.deviceReg = LBA_MODE;
		cmd.readWrite = IDE_CMD_READ;
		cmd.maxDataSize = HD_SECTOR_SIZE * (end-begin);

	        TRACE_READ(" block %x \n", 	cmd.lba);
		ret = IDE_SendCmd(&cmd);
		
		if (use_cache == TRUE)
		{
			for (j=begin; j<end; j++)
			{
				Int32 cache_ret;
				//DEBUG_OUT("read sectors after failed cache write on sector: %d disk: %d\n", (blockno + j), disk);
				cache_ret = loadToCache(&ide_cache[disk], blockno+j, address + (j*HD_SECTOR_SIZE));
				soft_assert(cache_ret == 0);
				// Since this is a write through cache no page will ever get dirty
				// since we are always writing straight to the HDD anyway 
				// This operation must succeed
			}
		}
		
		if (ret)
		{
			return  ( ATA_ReadRegister(diskDesc[disk].driveID, ATA_REG_ERROR) & 0xFF);
		}
		else
		{
			return SUCCESS;
		}
	}
	return SUCCESS;
}
#endif

//-----------------------------------------------------------------------------
//  Function: ide_command_write_sectors
//
//  Description:
//
//      Called by ide_do_block
//
//      This routine is portable
//
//-----------------------------------------------------------------------------

Int32 ide_command_write_sectors(
								 Uint8 * address, 	// Source address for the data
								 Uint16 disk, 			// Disk number (0 or 1)
								 Uint32 blockno, 		// Block number to read
								 Uint16 nblocks,			// Number of blocks (legal range: 1-256)
								 Boolean use_cache
								 )
{
	IDE_Cmd cmd;
	int     i;

	//TRACE_WRITE("write sectors called\n");
	/* Check against max_blocks. this is 256 for IDE. In real mode 80xx we limit
	it to 128 to eliminate segment wrap. */
	if (nblocks > MAX_BLOCKS)
	{
		TRACE_ERROR("write sectors fail 1\n");
		return IDE_INTERNAL;
	}

	if (!(diskDesc[disk].maxLBA) && !diskDesc[disk].IsRemovableMediaDevice) /* Should be non zeroe if the disk was initialized */
	{
		TRACE_ERROR("write sectors fail 2\n");
		return IDE_INTERNAL;
	}

	/* write through cache */
	for (i = 0; i < nblocks; i++) 
	{
		//DEBUG_OUT("write sectors writing to cache to sectors: %d\n", (blockno+i));
		//writeToCache(&ide_cache[disk], blockno+i, address + (i*HD_SECTOR_SIZE)); 
		//updateCache(&ide_cache[disk], blockno+i, address + (i*HD_SECTOR_SIZE));
		invalidateCache(&ide_cache[disk], blockno + i);
	}
	
	/* Call the CMD processing routine! */

	if (address == NULL)
	{

		if (diskDesc[disk].supports48bitAddFeatureSet)
		{
			cmd.ext_cmd = TRUE;
#ifdef RIO_PIO_MODE
			if (nblocks == 1)
				cmd.cmdCode = IDE_CMD_WRITES_EXT;
			else
				cmd.cmdCode = IDE_CMD_WRITEM_EXT;
#else
			cmd.cmdCode = IDE_CMD_WRITEDMA_EXT;
			cmd.ext_cmd = TRUE;
#endif
		}
		else
		{
#ifdef RIO_PIO_MODE
			if (nblocks == 1)
				cmd.cmdCode = IDE_CMD_WRITES;
			else
				cmd.cmdCode = IDE_CMD_WRITEM;
#else
			cmd.cmdCode = IDE_CMD_WRITEDMA;
			cmd.ext_cmd = FALSE;
#endif
		}

	}
	else
	{
		if (diskDesc[disk].supports48bitAddFeatureSet)
		{
			cmd.ext_cmd = TRUE;
			if (nblocks == 1)
				cmd.cmdCode = IDE_CMD_WRITES_EXT;
			else
				cmd.cmdCode = IDE_CMD_WRITEM_EXT;
		}
		else
		{
			cmd.ext_cmd = FALSE;
			if (nblocks == 1)
				cmd.cmdCode = IDE_CMD_WRITES;
			else
				cmd.cmdCode = IDE_CMD_WRITEM;
		}
	}
	//Due to the size of sectorCntReg(Uint8), if nblocks == 256, sectorCntReg will be 0
	cmd.sectorCntReg    = nblocks;
	cmd.lba             = blockno;
	cmd.driveID         = disk;
	cmd.featureReg      = 0;
	cmd.pktCmd          = NULL;
	cmd.pktCmdSize      = 0;
	cmd.data            = address;
	cmd.deviceReg       = LBA_MODE;
	cmd.readWrite       = IDE_CMD_WRITE;
	cmd.maxDataSize     = 512 * nblocks;

	return	(IDE_SendCmd(&cmd));
}


Int32 writeMBR(Uint8 diskno, Uint32 addr, Uint32 disk_lba_size)
{
	PTABLE  ppart;
	Uint8  end_sec;
	Uint16 end_cyl;
	Uint8  *buf;
	
	Uint8 bootLoaderCode[0x1be] = {
		0x33, 0xC0, 0x8E, 0xD0, 0xBC, 0x00, 0x7C, 0xFB, 0x50, 0x07, 0x50, 0x1F, 0xFC, 0xBE, 0x1B, 0x7C,
		0xBF, 0x1B, 0x06, 0x50, 0x57, 0xB9, 0xE5, 0x01, 0xF3, 0xA4, 0xCB, 0xBD, 0xBE, 0x07, 0xB1, 0x04,
		0x38, 0x6E, 0x00, 0x7C, 0x09, 0x75, 0x13, 0x83, 0xC5, 0x10, 0xE2, 0xF4, 0xCD, 0x18, 0x8B, 0xF5,
		0x83, 0xC6, 0x10, 0x49, 0x74, 0x19, 0x3

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -