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

📄 ata.c

📁 newos is new operation system
💻 C
📖 第 1 页 / 共 2 页
字号:
/* ** Copyright 2002, Thomas Kurschel. All rights reserved.** Distributed under the terms of the NewOS License.*/#include "ide_internal.h"#include "ata.h"#include <kernel/debug.h>#include "ide_sim.h"#include "basic_prot.h"#include "sync.h"#include "PIO.h"#include "DMA.h"#include "ide_cmds.h"#include "queuing.h"static bool check_rw_status( ide_device_info *device, ide_qrequest *qrequest, bool drq_required ){	ide_bus_info *bus = device->bus;	int status;		status = bus->controller->get_altstatus( bus->channel );		if( (status & ide_status_bsy) != 0 ) {		set_sense( device, SCSIS_KEY_HARDWARE_ERROR, SCSIS_ASC_LUN_TIMEOUT );		return false;	}		if( drq_required != ((status & ide_status_drq) != 0) ) {		set_sense( device, SCSIS_KEY_HARDWARE_ERROR, SCSIS_ASC_INTERNAL_FAILURE );		return false;	}		return true;}void ata_dpc_PIO( ide_qrequest *qrequest ){	ide_device_info *device = qrequest->device;	bigtime_t timeout = qrequest->request->cam_timeout > 0 ? 		qrequest->request->cam_timeout : IDE_STD_TIMEOUT;		if( !check_rw_error( device, qrequest ) ||		!check_rw_status( device, qrequest,		qrequest->is_write ? device->left_blocks > 1 : true )) 	{		/*if( (device->sense.sense_key == SCSIS_KEY_ABORTED_COMMAND ||			 device->sense.ascq == SCSIS_ASC_UNREC_READ_ERR) &&			++qrequest->retries < MAX_PIO_RETRIES ) 		{			finish_rw_request( qrequest, ide_finish_rw_retry );		} else*/			finish_checksense( qrequest );					return;	}	if( qrequest->is_write ) {		if( device->left_blocks == 0 )			goto finish;					if( !wait_for_drq( device )) 			goto finish;					start_waiting_nolock( device->bus, timeout, ide_state_async_waiting );				// having a too short data buffer shouldn't happen here		// anyway - we are prepared		if( write_PIO_block( qrequest, 512 ) == ERR_GENERAL )			goto finish_cancel_timeout;					--device->left_blocks;	} else {		if( device->left_blocks > 0 )			start_waiting_nolock( device->bus, timeout, ide_state_async_waiting );				// see write		if( read_PIO_block( qrequest, 512 ) == ERR_GENERAL ) 			goto finish_cancel_timeout;					--device->left_blocks;				if( device->left_blocks == 0 ) {			wait_for_drqdown( device );			goto finish_cancel_timeout;		}	}		//start_waiting( device->bus );	return;	finish_cancel_timeout:	cancel_irq_timeout( device->bus );	finish:	finish_checksense( qrequest );	return;}void ata_dpc_DMA( ide_qrequest *qrequest ){	ide_device_info *device = qrequest->device;	//ide_bus_info *bus = device->bus;	bool dma_err, dev_err;		dma_err = finish_dma( device );	dev_err = check_rw_error( device, qrequest );		if( !dma_err && !dev_err ) {		device->DMA_failures = 0;		device->CQ_failures = 0;		qrequest->request->cam_resid = 0;		finish_checksense( qrequest );	} else {		if( ++device->DMA_failures == MAX_DMA_FAILURES ) {			device->DMA_enabled = false;			finish_reset_queue( qrequest );		} else {			finish_retry( qrequest );		}	}}uint8 cmd_48[2][2] = {	{ IDE_CMD_READ_SECTORS_EXT, IDE_CMD_WRITE_SECTORS_EXT },	{ IDE_CMD_READ_DMA_EXT, IDE_CMD_WRITE_DMA_EXT }};uint8 cmd_28[2][2] = {	{ IDE_CMD_READ_SECTORS, IDE_CMD_WRITE_SECTORS },	{ IDE_CMD_READ_DMA, IDE_CMD_WRITE_DMA }};static bool create_rw_taskfile( ide_device_info *device, ide_qrequest *qrequest, 	uint64 pos, size_t length, bool write ){	if( device->use_LBA ) {		if( device->use_48bits && 			(pos + length > 0xfffffff ||			length > 0x100 ))		{			if( length > 0xffff ) 				goto err;							if( qrequest->queuable ) {				device->tf_param_mask = 					ide_mask_features_48 |					ide_mask_sector_count |					ide_mask_LBA_low_48 |					ide_mask_LBA_mid_48	|					ide_mask_LBA_high_48;									device->tf.queued48.sector_count_0_7 = length & 0xff;				device->tf.queued48.sector_count_8_15 = (length >> 8) & 0xff;				device->tf.queued48.tag = qrequest->tag;				device->tf.queued48.lba_0_7 = pos & 0xff;				device->tf.queued48.lba_8_15 = (pos >> 8) & 0xff;				device->tf.queued48.lba_16_23 = (pos >> 16) & 0xff;				device->tf.queued48.lba_24_31 = (pos >> 24) & 0xff;				device->tf.queued48.lba_32_39 = (pos >> 32) & 0xff;				device->tf.queued48.lba_40_47 = (pos >> 40) & 0xff;				device->tf.queued48.command = write ? IDE_CMD_WRITE_DMA_QUEUED 					: IDE_CMD_READ_DMA_QUEUED;				return true;							} else {				device->tf_param_mask = 					ide_mask_sector_count_48 |					ide_mask_LBA_low_48 |					ide_mask_LBA_mid_48	|					ide_mask_LBA_high_48;				device->tf.lba48.sector_count_0_7 = length & 0xff;				device->tf.lba48.sector_count_8_15 = (length >> 8) & 0xff;				device->tf.lba48.lba_0_7 = pos & 0xff;				device->tf.lba48.lba_8_15 = (pos >> 8) & 0xff;				device->tf.lba48.lba_16_23 = (pos >> 16) & 0xff;				device->tf.lba48.lba_24_31 = (pos >> 24) & 0xff;				device->tf.lba48.lba_32_39 = (pos >> 32) & 0xff;				device->tf.lba48.lba_40_47 = (pos >> 40) & 0xff;				device->tf.lba48.command = cmd_48[qrequest->uses_dma][write];				return true;							}		} else {			if( length > 0x100 ) 				goto err;			if( qrequest->queuable ) {				device->tf_param_mask = 					ide_mask_features |					ide_mask_sector_count |					ide_mask_LBA_low |					ide_mask_LBA_mid |					ide_mask_LBA_high |					ide_mask_device_head;									device->tf.queued.sector_count = length & 0xff;				device->tf.queued.tag = qrequest->tag;				device->tf.queued.lba_0_7 = pos & 0xff;				device->tf.queued.lba_8_15 = (pos >> 8) & 0xff;				device->tf.queued.lba_16_23 = (pos >> 16) & 0xff;				device->tf.queued.lba_24_27 = (pos >> 24) & 0xf;				device->tf.queued.command = write ? IDE_CMD_WRITE_DMA_QUEUED 					: IDE_CMD_READ_DMA_QUEUED;				return true;							} else {				device->tf_param_mask = 					ide_mask_sector_count |					ide_mask_LBA_low |					ide_mask_LBA_mid |					ide_mask_LBA_high |					ide_mask_device_head;				device->tf.lba.sector_count = length & 0xff;				device->tf.lba.lba_0_7 = pos & 0xff;				device->tf.lba.lba_8_15 = (pos >> 8) & 0xff;				device->tf.lba.lba_16_23 = (pos >> 16) & 0xff;				device->tf.lba.lba_24_27 = (pos >> 24) & 0xf;				device->tf.lba.command = cmd_28[qrequest->uses_dma][write];				return true;							}		}	} else {		uint32 track_size, cylinder_offset, cylinder;		ide_device_infoblock *infoblock = &device->infoblock;				if( length > 0x100 ) 			goto err;				device->tf.chs.mode = ide_mode_chs;				device->tf_param_mask = 			ide_mask_sector_count |			ide_mask_sector_number |			ide_mask_cylinder_low |			ide_mask_cylinder_high |			ide_mask_device_head;					device->tf.chs.sector_count = length & 0xff;			track_size = infoblock->current_heads * infoblock->current_sectors;				if( track_size == 0 ) {			set_sense( device, 				SCSIS_KEY_MEDIUM_ERROR, SCSIS_ASC_MEDIUM_FORMAT_CORRUPTED );			return false;		}				cylinder = pos / track_size;		device->tf.chs.cylinder_0_7 = cylinder & 0xff;		device->tf.chs.cylinder_8_15 = (cylinder >> 8) & 0xff;		cylinder_offset = pos - cylinder * track_size;		device->tf.chs.sector_number = (cylinder_offset % infoblock->current_sectors + 1) & 0xff;		device->tf.chs.head = cylinder_offset / infoblock->current_sectors;				device->tf.chs.command = cmd_28[qrequest->uses_dma][write];		return true;	}	return true;	err:		set_sense( device, SCSIS_KEY_ILLEGAL_REQUEST, SCSIS_ASC_INV_CDB_FIELD );	return false;}void ata_send_rw( ide_device_info *device, ide_qrequest *qrequest,	uint64 pos, size_t length, bool write ){	ide_bus_info *bus = device->bus;	bigtime_t timeout;		qrequest->is_write = write;	qrequest->uses_dma = device->DMA_enabled;		if( qrequest->uses_dma ) {		if( !prepare_dma( device, qrequest )) {			// if command queueing is used and there is another command			// already running, PIO commands cannot be used -> declare			// command as not queuable and resubmit it			// (XXX this is not fine if the caller wants to recycle the CCB)			if( device->num_running_reqs > 1 ) {				qrequest->request->cam_tag_action = 0;				finish_retry( qrequest );				return;			}						qrequest->uses_dma = false;		}	}		if( !qrequest->uses_dma ) {		prep_PIO_transfer( device, qrequest );		device->left_blocks = length >> 9;	}	if( !create_rw_taskfile( device, qrequest, pos, length, write ))		goto err_setup;		timeout = qrequest->request->cam_timeout > 0 ? 		qrequest->request->cam_timeout : IDE_STD_TIMEOUT;		if( !send_command( device, !device->is_atapi, 		timeout,		!qrequest->uses_dma && !qrequest->is_write ? 			ide_state_async_waiting : ide_state_accessing )) 		goto err_send;		if( qrequest->uses_dma ) {			if( device->CQ_enabled ) {			qrequest->running = true;						if( !wait_for_drdy( device ))				goto err_send;						if( !check_rw_error( device, qrequest ))				goto err_send;						if( device_released_bus( device )) {				bus->active_qrequest = NULL;								timer_set_event( IDE_RELEASE_TIMEOUT, 					TIMER_MODE_ONESHOT, &device->reconnect_timer );	

⌨️ 快捷键说明

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