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

📄 device_mgr.c

📁 newos is new operation system
💻 C
字号:
/*** Copyright 2002, Thomas Kurschel. All rights reserved.** Distributed under the terms of the NewOS License.*/#include <kernel/kernel.h>#include <kernel/heap.h>#include <kernel/vm.h>#include "ide_internal.h"#include "device_mgr.h"#include <kernel/bus/scsi/endian.h>#include <string.h>#include "queuing.h"#include "sync.h"#include "ide_sim.h"#include "ide_cmds.h"#include "basic_prot.h"#include "ata.h"#include "atapi.h"bool initialize_buffer( ide_device_info *device, size_t buffer_size ){	struct sg_elem *cur_elem;	uchar *cur_buffer;	size_t offset;	device->buffer = kmalloc( buffer_size );	if( device->buffer == NULL )		return false;	device->buffer_sg_list = kmalloc(		(buffer_size + (PAGE_SIZE - 1)) / PAGE_SIZE		* sizeof( struct sg_elem ));	if( device->buffer_sg_list == NULL )		return false;	device->buffer_size = buffer_size;	device->buffer_sglist_cnt = 0;	cur_elem = device->buffer_sg_list;	cur_buffer = device->buffer;	for( offset = 0; offset < buffer_size; ) {		int res;		res = vm_get_page_mapping( vm_get_kernel_aspace_id(), (addr_t)(&cur_buffer),			(addr_t *)&cur_elem->cam_sg_address );		if( res != NO_ERROR )			return false;		cur_elem->cam_sg_count = PAGE_SIZE -			((addr_t)cur_elem->cam_sg_address % PAGE_SIZE);		cur_buffer += cur_elem->cam_sg_count;		offset += cur_elem->cam_sg_count;		++cur_elem;		++device->buffer_sglist_cnt;	}	return true;}static void destroy_buffer( ide_device_info *device ){	if( device->buffer )		kfree( device->buffer );	if( device->buffer_sg_list )		kfree( device->buffer_sg_list );	device->buffer = NULL;	device->buffer_sg_list = NULL;	device->buffer_size = 0;}static void cleanup_device_links( ide_device_info *device ){	ide_bus_info *bus = device->bus;	bus->devices[device->is_device1] = NULL;	if( device->other_device ) {		if( device->other_device != device ) {			device->other_device->other_device = device->other_device;			bus->first_device = device->other_device;		} else			bus->first_device = NULL;	}	device->other_device = NULL;}static void destroy_device( ide_device_info *device ){	SHOW_FLOW0( 3, "" );	// paranoia	device->exec_io = NULL;	timer_cancel_event( &device->reconnect_timer );	cleanup_device_links( device );	destroy_qreq_array( device );	destroy_buffer( device );	uninit_synced_pc( &device->reconnect_timeout_synced_pc );	kfree( device );}static void setup_device_links( ide_bus_info *bus, ide_device_info *device ){	SHOW_FLOW0( 3, "" );	device->bus = bus;	bus->devices[device->is_device1] = device;	device->other_device = device;	if( device->is_device1 ) {		if( bus->devices[0] ) {			device->other_device = bus->devices[0];			bus->devices[0]->other_device = device;		}	} else {		if( bus->devices[1] ) {			device->other_device = bus->devices[1];			bus->devices[1]->other_device = device;		}	}	if( bus->first_device == NULL )		bus->first_device = device;}static ide_device_info *create_device( ide_bus_info *bus, bool is_device1 ){	ide_device_info *device;	SHOW_FLOW( 3, "is_device1=%i", (int)is_device1 );	device = kmalloc( sizeof( *device ));	if( device == NULL )		return NULL;	memset( device, 0, sizeof( *device ));	device->is_device1 = is_device1;	device->target_id = is_device1;	setup_device_links( bus, device );	device->DMA_failures = 0;	device->CQ_failures = 0;	device->combined_sense = 0;	device->num_running_reqs = 0;	device->no_reconnect_timeout = true;	timer_setup_timer( reconnect_timeout, device, &device->reconnect_timer );	init_synced_pc( &device->reconnect_timeout_synced_pc,		reconnect_timeout_worker );	if( xpt->alloc_dpc( &device->reconnect_timeout_dpc ) != NO_ERROR )		goto err;	device->total_sectors = 0;	return device;err:	destroy_device( device );	return NULL;}static void prep_infoblock( ide_device_info *device ){	ide_device_infoblock *infoblock = &device->infoblock;	swap16_multi( (uint16 *)infoblock->serial_number,		sizeof( infoblock->serial_number ) / 2 );	swap16_multi( (uint16 *)infoblock->firmware_version,		sizeof( infoblock->firmware_version ) / 2 );	swap16_multi( (uint16 *)infoblock->model_number,		sizeof( infoblock->model_number ) / 2 );	infoblock->LBA_total_sectors = letoh32( infoblock->LBA_total_sectors );	infoblock->LBA48_total_sectors = letoh64( infoblock->LBA48_total_sectors );}static bool scan_device_int( ide_device_info *device, bool atapi ){	ide_bus_info *bus = device->bus;	int dummy;	int status;	SHOW_FLOW0( 3, "" );	device->tf_param_mask = 0;	device->tf.write.command = atapi ? IDE_CMD_IDENTIFY_PACKET_DEVICE		: IDE_CMD_IDENTIFY_DEVICE;	// initialize device selection flags,	// this is the only place where this bit gets initialized	if( bus->controller->read_command_block_regs( bus->channel, &device->tf,		ide_mask_device_head ) != NO_ERROR )		return false;	device->tf.lba.device = device->is_device1;	if( !send_command( device, atapi ? false : true, 20000000, ide_state_sync_waiting ))		return false;	SHOW_FLOW0( 3, "1" );	// do a short wait first - if there's no device at all we could wait forever	if( sem_acquire_etc( bus->sync_wait_sem, 1, SEM_FLAG_TIMEOUT,		100000, &dummy ) == ERR_SEM_TIMED_OUT )	{		bool cont;		SHOW_FLOW0( 3, "no fast response to inquiry" );		// check the busy flag - if it's still set, there's probably no device		IDE_LOCK( bus );		status = bus->controller->get_altstatus( bus->channel );		SHOW_FLOW( 3, "status=%x", (int)status );		cont = (status & ide_status_bsy) == ide_status_bsy;		IDE_UNLOCK( bus );		if( !cont ) {			SHOW_FLOW0( 3, "no busy bit not set after 100ms - probably noone there" );			// no reaction -> abort waiting			cancel_irq_timeout( bus );			// timeout or irq may have been fired, reset semaphore just is case			sem_acquire_etc( bus->sync_wait_sem, 1, SEM_FLAG_TIMEOUT, 0, &dummy );			return false;		}		SHOW_FLOW0( 3, "busy bit set, give device more time" );		// there is something, so wait for it		sem_acquire( bus->sync_wait_sem, 1 );	}	if( bus->sync_wait_timeout )		return false;	SHOW_FLOW0( 3, "2" );	ide_wait( device, ide_status_drq, ide_status_bsy, true, 1000 );	status = bus->controller->get_altstatus( bus->channel );	if( (status & ide_status_err) != 0 ) {		// if there's no device, all bits including the error bit are set		SHOW_FLOW0( 3, "err set" );		return false;	}	SHOW_FLOW0( 3, "3" );	bus->controller->read_pio_16( bus->channel, (uint16 *)&device->infoblock,		sizeof( device->infoblock ) / sizeof( uint16 ), false );	SHOW_FLOW0( 3, "4" );	if( !wait_for_drqdown( device ))		return false;	SHOW_FLOW0( 3, "5" );	prep_infoblock( device );	return true;}void scan_device_worker( ide_bus_info *bus, void *arg ){	int is_device1 = (int)arg;	ide_device_info *device;	SHOW_FLOW0( 3, "" );	if( bus->devices[is_device1] )		destroy_device( bus->devices[is_device1] );	device = create_device( bus, is_device1 );	if( scan_device_int( device, false )) {		if( !prep_ata( device ))			goto err;	} else if( scan_device_int( device, true )) {		if( !prep_atapi( device ))			goto err;	} else		goto err;	bus->state = ide_state_idle;	sem_release( bus->scan_device_sem, 1 );	return;err:	destroy_device( device );	bus->state = ide_state_idle;	sem_release( bus->scan_device_sem, 1 );	return;}

⌨️ 快捷键说明

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