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

📄 isa_ide_bus.c

📁 newos is new operation system
💻 C
字号:
#include "ide_bus.h"#include "isa_ide_bus.h"#include "ide_drive.h"#include <kernel/arch/cpu.h>#include <kernel/debug.h>#include <kernel/heap.h>#include <kernel/vfs.h>#include <kernel/sem.h>#include <kernel/int.h>#include <kernel/vm.h>#define CB_DC_HD15   0x08  // bit should always be set to one#define CB_DC_SRST   0x04  // soft reset#define CB_DC_NIEN   0x02  // disable interrupts#define CB_DH_DEV0 0xa0    // select device 0#define CB_DH_DEV1 0xb0    // select device 1#define CB_STAT_BSY  0x80  // busy#define CB_STAT_RDY  0x40  // ready#define CB_STAT_DF   0x20  // device fault#define CB_STAT_WFT  0x20  // write fault (old name)#define CB_STAT_SKC  0x10  // seek complete#define CB_STAT_SERV 0x10  // service#define CB_STAT_DRQ  0x08  // data request#define CB_STAT_CORR 0x04  // corrected#define CB_STAT_IDX  0x02  // index#define CB_STAT_ERR  0x01  // error (ATA)#define CB_STAT_CHK  0x01  // check (ATAPI)#define DMA_SEL5 0x01#define DMA_SEL6 0x02#define DMA_SEL7 0x03#define DMA_TC5 0x02#define DMA_TC6 0x04#define DMA_TC7 0x08#define DMA_MODE_DEMAND 0x00     // modeByte bits for various dma modes#define DMA_MODE_BLOCK  0x80#define DMA_MODE_SINGLE 0x40#define DMA_MODE_MEMR 0x08       // modeByte memory read or write#define DMA_MODE_MEMW 0x04#define DMA_MASK_ENABLE  0x00    // bits for enable/disable#define DMA_MASK_DISABLE 0x04extern	void	init_ide_struct(int bus,int device,int partition_id);#define IDE_TRACE 1#if IDE_TRACE#define TRACE(x) dprintf x#else#define TRACE(x)#endiftypedef	struct{	int		base_reg;	int		status_reg;	ide_drive	*drives[2];	void		*drive_cookie[2];	unsigned int 	pio_reg_addrs[10];	int		channel;	bool		dma_supported;	sem_id		bus_semaphore;}isa_bus_cookie;static	int	ide_raw_init(isa_bus_cookie *cookie){   cookie->pio_reg_addrs[ CB_DATA ] = cookie->base_reg + 0;  // 0   cookie->pio_reg_addrs[ CB_FR   ] = cookie->base_reg + 1;  // 1   cookie->pio_reg_addrs[ CB_SC   ] = cookie->base_reg + 2;  // 2   cookie->pio_reg_addrs[ CB_SN   ] = cookie->base_reg + 3;  // 3   cookie->pio_reg_addrs[ CB_CL   ] = cookie->base_reg + 4;  // 4   cookie->pio_reg_addrs[ CB_CH   ] = cookie->base_reg + 5;  // 5   cookie->pio_reg_addrs[ CB_DH   ] = cookie->base_reg + 6;  // 6   cookie->pio_reg_addrs[ CB_CMD  ] = cookie->base_reg + 7;  // 7   cookie->pio_reg_addrs[ CB_DC   ] = cookie->status_reg + 6;  // 8   cookie->pio_reg_addrs[ CB_DA   ] = cookie->status_reg + 7;  // 9   return 0;}static int ide_interrupt_handler(void* data){  TRACE(("in ide interrupt handler %p\n",data));  isa_bus_cookie	*cookie = data;  TRACE(("drive = %p drive_cookie=%p\n",cookie->drives[0],cookie->drive_cookie[0]));  TRACE(("drive = %p drive_cookie=%p\n",cookie->drives[1],cookie->drive_cookie[1]));	if(cookie->drives[0]!=NULL)		cookie->drives[0]->signal_interrupt(cookie,cookie->drive_cookie[0]);	if(cookie->drives[1]!=NULL)  		cookie->drives[1]->signal_interrupt(cookie,cookie->drive_cookie[1]);  return  INT_RESCHEDULE;}static	int	init(int channel){	char 		temp[64];	isa_bus_cookie	*current_cookie = kmalloc(sizeof(isa_bus_cookie));	bus_cookies[channel] = current_cookie;	current_cookie->channel = channel;	current_cookie->dma_supported = false;	sprintf(temp, "isa_ide_sem%d", channel);	current_cookie->bus_semaphore =  sem_create(1, temp);    	if(current_cookie->bus_semaphore < 0)      	{		kfree(current_cookie);		return -1;      	}	TRACE(("trying to discover devices on channel %d\n",channel));	if(channel==0)	{		current_cookie->base_reg = 0x1f0;		current_cookie->status_reg = 0x3f0;	}	else	{		current_cookie->base_reg = 0x170;		current_cookie->status_reg = 0x370;	}	if(ide_raw_init(current_cookie)==0)	{		int	current_drive;		for(current_drive=0;current_drive<2;current_drive++)		{			int		i = 0;			current_cookie->drives[current_drive] = NULL;			TRACE(("trying to discover device %d/%d\n",channel,current_drive));			while(ide_drives[i]!=NULL)			{				void	*drive_cookie = ide_drives[i]->init_drive(&isa_bus,current_cookie,channel,current_drive);				if(drive_cookie!=NULL)				{					TRACE(("trying to discover device %d/%d is a %s\n",channel,current_drive,ide_drives[i]->device_name));					current_cookie->drives[current_drive] = ide_drives[i];					current_cookie->drive_cookie[current_drive] = drive_cookie;					init_ide_struct(channel,current_drive,-1);      					TRACE(("done discovering device\n"));    					TRACE(("Cookie for interrupt is %p\n",current_cookie));					int_set_io_interrupt_handler(14+channel,&ide_interrupt_handler, current_cookie);					break;				}				i++;			}		}		return 0;	}	return -1;}static	int	read_block(void *cookie,int drive,long block,void *buffer,size_t size){	isa_bus_cookie	*bus_cookie;	ide_drive	*thedrive;	if(drive<0 || drive>1)		return -1;	bus_cookie = cookie;	thedrive = bus_cookie->drives[drive];	if(thedrive==NULL)		return -1;	return thedrive->read_block(bus_cookie,bus_cookie->drive_cookie[drive],block,buffer,size);}static	int	write_block(void *cookie,int drive,long block,void *buffer,size_t size){	isa_bus_cookie	*bus_cookie;	ide_drive	*thedrive;	if(drive<0 || drive>1)		return -1;	bus_cookie = cookie;	thedrive = bus_cookie->drives[drive];	if(thedrive==NULL)		return -1;	return thedrive->write_block(bus_cookie,bus_cookie->drive_cookie[drive],block,buffer,size);}static	int	setup_dma(void *cookie,int dir, long size, uint8 *buffer ){	return 	-1;}static	int	start_dma(void *cookie){	return -1;}static	int	finish_dma(void *cookie){	return -1;}static	int	write_register(void *cookie,int reg,uint8 value){	isa_bus_cookie	*bus_cookie = cookie;	uint16	reg_addr = bus_cookie->pio_reg_addrs[reg];	out8(value,reg_addr);	return 0;}static	int	write_register16(void *cookie,int reg,uint16 value){	isa_bus_cookie	*bus_cookie = cookie;	uint16	reg_addr = bus_cookie->pio_reg_addrs[reg];	out16(value,reg_addr);	return 0;}static	uint8	read_register(void *cookie,int reg){	isa_bus_cookie	*bus_cookie = cookie;  	uint16	reg_addr = bus_cookie->pio_reg_addrs[reg];  	return in8(reg_addr);}static	uint16	read_register16(void *cookie,int reg){	isa_bus_cookie	*bus_cookie = cookie;  	uint16	reg_addr = bus_cookie->pio_reg_addrs[reg];  	return in16(reg_addr);}static	uint8	get_alt_value(void *cookie){	return read_register( cookie,CB_ASTAT );}static	int	transfer_buffer(void *cookie,int reg,void *buffer,size_t size,bool fromMemory){	isa_bus_cookie	*bus_cookie = cookie;  	uint16		reg_addr = bus_cookie->pio_reg_addrs[reg];  	if(fromMemory==false)  	{  		__asm__ __volatile__    		(     			"rep ; outsw" : "=S" (buffer), "=c" (size) : "d" (reg_addr),"0" (buffer),"1" (size)     		);	} 	else 	{  		__asm__ __volatile__    		(     			"rep ; insw" : "=D" (buffer), "=c" (size) : "d" (reg_addr),"0" (buffer),"1" (size)     		);	}	return 0;}static	int	select_drive(void *cookie,int drive){	if(drive==0)		isa_bus.write_register( cookie,CB_DH, CB_DH_DEV0 );	else		isa_bus.write_register( cookie,CB_DH, CB_DH_DEV1 );	return 0;}static	int	delay_on_bus(void *cookie){	isa_bus.get_alt_status(cookie); isa_bus.get_alt_status(cookie);	isa_bus.get_alt_status(cookie); isa_bus.get_alt_status(cookie);	return 0;}static	int	reset_bus(void *cookie,int default_drive){  unsigned char	status;  unsigned char devCtrl;  devCtrl = CB_DC_HD15 | ( CB_DC_NIEN );  isa_bus.write_register(cookie,CB_DC, devCtrl | CB_DC_SRST );  isa_bus.delay_on_bus(cookie);  isa_bus.write_register(cookie,CB_DC, devCtrl );  isa_bus.delay_on_bus(cookie);  if(isa_bus.wait_busy(cookie)==-1)    return -1;  isa_bus.select_drive( cookie,default_drive );  isa_bus.delay_on_bus(cookie);  return 0;}static	int	wait_busy(void *cookie){	int		iterations = 0;	uint8	status; 	while ( 1 )  	{      		status = isa_bus.get_alt_status(cookie);      		if ( ( status & CB_STAT_BSY ) == 0 && ( status & CB_STAT_DRQ ) == 0)         		return 0;      		if ( iterations>10000 )      		{         		return -1;      		}     		iterations++;  	}  	return 0;}static	void	*get_nth_cookie(int channel){	return	bus_cookies[channel];}static	bool	support_dma(void *cookie){	isa_bus_cookie	*bus_cookie = cookie;	return bus_cookie->dma_supported;}static	int	lock(void *cookie){	isa_bus_cookie	*bus_cookie = cookie;	return sem_acquire(bus_cookie->bus_semaphore,1);}static	int	unlock(void *cookie){	isa_bus_cookie	*bus_cookie = cookie;	return sem_release(bus_cookie->bus_semaphore,1);}static	void *get_attached_drive(void *cookie,int drive){	isa_bus_cookie	*bus_cookie = cookie;	return	bus_cookie->drives[drive];}static	void 	*get_attached_drive_cookie(void *cookie,int drive){	isa_bus_cookie	*bus_cookie = cookie;	return	bus_cookie->drive_cookie[drive];}ide_bus	isa_bus ={	"ISA_BUS",	&init,	&read_block,	&write_block,	&setup_dma,	&start_dma,	&finish_dma,	&write_register16,	&write_register,	&read_register16,	&read_register,	&get_alt_value,	&transfer_buffer,	&select_drive,	&reset_bus,	&delay_on_bus,	&wait_busy,	&get_nth_cookie,	&get_attached_drive,	&get_attached_drive_cookie,	&support_dma,	&lock,	&unlock,};

⌨️ 快捷键说明

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