添加硬盘驱动 - 读磁盘


修改System_call.S中的hd_interrupt函数,主要功能就是重设EOI,判断do_hd是否为空,空报错,不为空调用回调函数。

hd_interrupt:
	pushl %eax
	pushl %ecx
	pushl %edx
	push %ds
	push %es
	push %fs
	movl $0x10,%eax
	mov %ax,%ds
	mov %ax,%es
	movl $0x17,%eax
	mov %ax,%fs
	movb $0x20,%al
	outb %al,$0xA0		# EOI to interrupt controller #1
	jmp 1f			# give port chance to breathe
1:	jmp 1f
1:	xorl %edx,%edx
	xchgl do_hd,%edx
	testl %edx,%edx
	jne 1f
	movl $unexpected_hd_interrupt,%edx
1:	outb %al,$0x20
	call *%edx		# "interesting" way of handling intr.
	pop %fs
	pop %es
	pop %ds
	popl %edx
	popl %ecx
	popl %eax
	iret

完整的hd.c

#include <linux/head.h>
#include <linux/sched.h>
#include <linux/kernel.h>
#include <linux/hdreg.h>
#include <asm/system.h>
#include <asm/io.h>

extern void hd_interrupt(void);
#define NULL ((void *) 0)
int cylinders;//柱面数
int heads;//磁头数
int sect_per_track;//每个磁道的扇区数
int dev=0;//
void (*do_hd)(void) = NULL;
#define port_read(port,buf,nr) \
__asm__("cld;rep;insw"::"d" (port),"D" (buf),"c" (nr):)

#define port_write(port,buf,nr) \
__asm__("cld;rep;outsw"::"d" (port),"S" (buf),"c" (nr):)
static int controller_ready(void)
{
	int retries=10000;

	while (--retries && (inb_p(HD_STATUS)&0x80));
	return (retries);
}

void unexpected_hd_interrupt(void)
{
	printk("Unexpected HD interrupt\n\r");
}
#define LBA
#ifdef LBA//LBA模式
/*
*drive-硬盘号(0或1)
*nsect-要读写的扇区数
*lba -起始扇区
*cmd  -命令码
*intr_addr- 回调函数的函数指针
*/
static void hd_out(unsigned int drive,unsigned int nsect,unsigned int lba,unsigned int cmd,void (*intr_addr)(void))
{
	register int port asm("dx");
	
	if (drive>1)
		printk("Trying to write bad sector");
	if (!controller_ready())
		printk("HD controller not ready");
		
	do_hd = intr_addr;
	outb_p(0,HD_CMD);
	port=HD_DATA;
	outb_p(0,++port);
	outb_p(nsect,++port);
	outb_p(lba&0xff,++port);
	outb_p((lba>>8)&0xff,++port);
	outb_p((lba>>16)&0xff,++port);
	outb_p(0xE0|(drive<<4)|((lba>>24)&0xf),++port);
	outb(cmd,++port);
}
#else//CHS模式
/*
*drive-硬盘号(0或1)
*nsect-要读写的扇区数
*sect -起始扇区
*head -磁头号
*cyl  -柱面号
*cmd  -命令码
*intr_addr- 回调函数的函数指针
*/
static void hd_out(unsigned int drive,unsigned int nsect,unsigned int sect,
		unsigned int head,unsigned int cyl,unsigned int cmd,void (*intr_addr)(void))
{
	register int port asm("dx");

	if (drive>1 || head>15)
		printk("Trying to write bad sector");
	if (!controller_ready())
		printk("HD controller not ready");

	do_hd = intr_addr;
	outb_p(0,HD_CMD);
	port=HD_DATA;
	outb_p(0,++port);
	outb_p(nsect,++port);
	outb_p(sect,++port);
	outb_p(cyl,++port);
	outb_p(cyl>>8,++port);
	outb_p(0xA0|(drive<<4)|head,++port);
	outb(cmd,++port);
}
#endif

#define SECTOR_SIZE		512
u8	hdbuf[SECTOR_SIZE * 2];
void hd_init(void)
{
	//blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
	set_intr_gate(0x2E,&hd_interrupt);
	outb_p(inb_p(0x21)&0xfb,0x21);
	outb(inb_p(0xA1)&0xbf,0xA1);
}
void print_identify_info()
{
	int i, k;
	char s[64];
	port_read(HD_DATA, hdbuf, SECTOR_SIZE);
	u16* hdinfo = hdbuf;
	//看手册77页这张表
	printk("Number of logical cylinders:%x\n",hdinfo[1]);
	printk("Number of logical heads:%x\n",hdinfo[3]);
	printk("sectors per track:%x\n",hdinfo[6]);
	hdinfo[20]='\0';
	printk("Serial number:%s\n",&hdinfo[10]);
	printk("obsolete:%x\n",hdinfo[22]);

        //cylinders=hdinfo[54];
	//heads=hdinfo[55];
	//sect_per_track=hdinfo[56];
}


void hd_identify(int drive)

{
	//读identify
	#ifdef LBA
	hd_out(0,0,0,0xEC,&print_identify_info);
	#else
	hd_out(0,0,0,0,0,0xEC,&print_identify_info);
	#endif
}

void read_intr(void)
{
	int i;
	port_read(HD_DATA,hdbuf,512);
	for(i=0x1be;i<512;i++)
		printk("hdbuf=%x ; \n",hdbuf[i]);
}


#define WIN_READ		0x20
void read(void)
{
	#ifdef LBA//LBA模式
	//读硬盘0的0扇区(第一个扇区),读一个扇区,回调函数为read_intr
	hd_out(0,1,0,WIN_READ,&read_intr);
	#else			//CHS模式
	//读硬盘0的0磁头0柱面1扇区(第一个扇区),读一个扇区,回调函数为read_intr
	hd_out(0,1,1,0,0,WIN_READ,&read_intr);
	#endif	
}



mian.c中调用read();函数,然后就是准备要读取的数据了,这一点我们可以用pc机来做

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值