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

📄 hd.c

📁 一个操作系统,用C语言实现开发的,我在一个浙江大学的操作系统实验网站找到.大家学习以下
💻 C
📖 第 1 页 / 共 2 页
字号:
		base = pointer-offset;
		byteoff = offset*DEF_SECTORSIZE;

		pItem = bufsAdd(pList, base, 0);
		if(!pItem) return DEVICE_MAKEERR(DEVERR_MEMORY);
		
		ret = bufsPrepare(pItem, dr_cmd==DR_READ ? BLP_READ : BLP_WRITE);
		if(ret!=ERR_SUCCESS) return ret;
		
		if(dr_cmd==DR_READ)
			l = bufsRead(pItem, byteoff, buffer, min(l0, pList->item_size-byteoff));
		else
			l = bufsWrite(pItem, byteoff, buffer, min(l0, pList->item_size-byteoff));
		l1 += l; l0 -= l; buffer += l;
		pointer += l/DEF_SECTORSIZE;
		if(len) *len = l1/DEF_SECTORSIZE;
	}
	return 0;
}

static long doSeek(HDEVICE hDevice, SEEKPACKET *sp, _u64 *final)
{
	_s32 block, delta;
	HDDEVICE *pDev = GetDeviceExtraMem(hDevice);
	// convert to sector-based
	block = (_s32)(sp->original/DEF_SECTORSIZE);
	delta = (_s32)(sp->delta/DEF_SECTORSIZE);
	switch(sp->mode)
	{
	case SEEK_SET:
		if(delta<0 || (_u32)delta>=pDev->length) return DEVICE_MAKEERR(DEVERR_NOTEXIST);
		*final = (_u64)(_u32)delta*DEF_SECTORSIZE;
		break;
	case SEEK_CUR:
		if(block+delta<0 || (_u32)(block+delta)>=pDev->length)
 			return DEVICE_MAKEERR(DEVERR_NOTEXIST);
		*final = (_u64)(_u32)(block+delta)*DEF_SECTORSIZE;
		break;
	case SEEK_END:
		if(delta>0 || (_u32)(-delta)>=pDev->length)
 			return DEVICE_MAKEERR(DEVERR_NOTEXIST);
		*final = (_u64)(_u32)((_s32)pDev->length-1+delta)*DEF_SECTORSIZE;
		break;
	}
	return 0;
}

static long doInitialize(HDEVICE hDevice, HDDEVICE *params)
{
	BUFFERLIST *pBufferList;
	HDDEVICE *pDev = GetDeviceExtraMem(hDevice);

	// save hd-device information
	if(!pDev || !params) return DEVICE_MAKEERR(DEVERR_PARAMS);
	memcpy(pDev, params, sizeof(HDDEVICE));

	// create buffer-list and request-queue
	pBufferList = bufsCreate(sizeof(HDEVICE), hd_buffers_proc, (_u32)hDevice);
	if(!pBufferList) return DEVICE_MAKEERR(DEVERR_INTERNAL);
	SetDeviceBufferList(hDevice, pBufferList);

	// load magic information for partitions
	if(pDev->partition!=0)
	{
		char buf[512];
		int r = hdd_read(pDev->drive, pDev->base, buf, 1);
		if(r!=0) return DEVICE_MAKEERR(DEVERR_INTERNAL|r);
		memcpy(pDev->magic, buf, 16);
	}
	return 0;
}

static long doIdentify(HDEVICE hDevice, char *buf, _u32 len, _u32 *t_len)
{
	if(!buf || len<4) return DEVICE_MAKEERR(DEVERR_PARAMS);
	*(_u32*)buf = ((HDDEVICE*)GetDeviceExtraMem(hDevice))->type;
	if(len>4)
	{
		len-=4;
		if(len>16) len = 16;
		memcpy(buf+4, ((HDDEVICE*)GetDeviceExtraMem(hDevice))->magic, len);
	}
	if(t_len) *t_len = len+4;
	return 0;
}

static long __syscall ioctrl(HDEVICE hDevice, _u32 cmd, void* in_buf, _u32 in_len, void* out_buf, _u32 out_len, _u32* trans_len)
{
	switch(cmd)
	{
	case DEV_IOCTRL_INITIALIZE: return doInitialize(hDevice, (HDDEVICE*)*(_u32*)in_buf);
	case DEV_IOCTRL_READ: return doTransfer(hDevice, (DDTPACKET*)in_buf, trans_len, DR_READ);
	case DEV_IOCTRL_WRITE: return doTransfer(hDevice, (DDTPACKET*)in_buf, trans_len, DR_WRITE);
	case DEV_IOCTRL_SEEK: return doSeek(hDevice, (SEEKPACKET*)in_buf, (_u64*)out_buf);
	case DEV_IOCTRL_IDENTIFY: return doIdentify(hDevice, (char*)out_buf, out_len, trans_len);
	}
	return DEVICE_MAKEERR(DEVERR_BADCMD);
}

// Installation routines
static int hdd_identify(int pri_sec, int drive, void *buf)
{
	int drv = ((drive<<4)&0x10)|0xa0;
	_outb(pri_sec+HDPA_HEAD, drv);
	if((wait_ide(pri_sec)&0x50)!=0x50) return 0;
	_outb(pri_sec+HDPA_HEAD, drv);
	_outb(pri_sec+HDPA_CMD, 0xec);
	if((wait_ide(pri_sec)&0x58)!=0x58) return 0;

	_insw(pri_sec, buf, 256);
	return 1;
}

static void swapb(char *buf, int len)
{
	int i, b;
	for(i=0; i<len; i+=2)
	{ b = buf[i]; buf[i] = buf[i+1]; buf[i+1] = (char)b; }
}

static void detect_hdd(int pri_sec)
{
	char buf[512];
	int i;

	_outb(pri_sec+HDPA_CMD, 0x08);	// reset device
	if(wait_ide(pri_sec)&0x80) return;

	kprintf("Detecting %s IDE controler...", pri_sec==IDE_PRIMARY?"primary":"secondary");

	for(i=0; i<2; i++)
	{
		if(hdd_identify(pri_sec, i, buf))
		{
			int id = (pri_sec==IDE_PRIMARY?0:2)+i;
			_hdd_drives[id].port_base		= pri_sec;
			_hdd_drives[id].drive_id		= i;
			_hdd_drives[id].n_cylinders 	= *(_u16*)(buf+0x02);
			_hdd_drives[id].n_heads			= *(_u16*)(buf+0x06);
			_hdd_drives[id].n_sectors		= *(_u16*)(buf+0x0c);
			_hdd_drives[id].capbilities 	= *(_u16*)(buf+0x62);
			_hdd_drives[id].n_multimax		= *(_u16*)(buf+0x5e);
			_hdd_drives[id].n_dwtrans		= *(_u16*)(buf+0x60);
			_hdd_drives[id].n_LBAsectors 	= _hdd_drives[id].capbilities&HDC_LBA ? *(_u32*)(buf+0x78)
													: chs_to_lba(id, _hdd_drives[id].n_cylinders-1,
																 _hdd_drives[id].n_heads-1,
														 		 _hdd_drives[id].n_sectors);
			strncpy(_hdd_drives[id].serial_number, buf+0x14, 20);
			_hdd_drives[id].serial_number[20]=0;
			strncpy(_hdd_drives[id].model_number, buf+0x36, 40);
			_hdd_drives[id].model_number[40]=0;
			swapb(_hdd_drives[id].model_number, 40);
			TrimRight(_hdd_drives[id].serial_number, ' ');
			TrimRight(_hdd_drives[id].model_number, ' ');
			kprintf("\r%s %s drive found: %s (%s, %s, %s)\n",
					pri_sec==IDE_PRIMARY?"Primary":"Secondary",
					i==0?"master":"slave",
					_hdd_drives[id].model_number,
					_hdd_drives[id].n_LBAsectors?"LBA":"CHS",
					_hdd_drives[id].capbilities&HDC_DMA?"DMA":"PIO",
					_hdd_drives[id].n_dwtrans?"D":"W");
		}
	}
	kprintf("\r                                                \r");
}

static int register_drive(int id, int partition, int type, _u32 base, _u32 len)
{
	char name[8];
	HDDEVICE hddev;

	if(partition) ksprintf(name, "hd%c%d", id+'a', partition);
	else ksprintf(name, "hd%c", id+'a');
	memset(&hddev, 0, sizeof(hddev));
	hddev.drive = id;
	hddev.partition = partition;
	hddev.type = type;
	hddev.base = base;
	hddev.length = len;
	if(!RegisterDevice(_this_driver, DEV_TYPE_BLOCK, DEV_SEEKING, DEF_SECTORSIZE, name, ioctrl,
					   sizeof(HDDEVICE), (_u32)&hddev))
	{ kprintf("%s: device registering failed\n", name); return 0; }
	return 1;
}

static int register_extension(int id, _u32 base, _u32 len, int part)
{
	int r, cnt = 0;
	char buf[512], name[8];
	_u32 p, next = base;

	while(next)
	{
		ksprintf(name, "hd%c%d", id+'a', part+cnt);
		r = hdd_read(id, next, buf, 1);
		if(r!=0)
		{ kprintf("%s: sector 0 read error: %04X\n", name, r); break; }
		if(*(_u16*)(buf+0x1fe)!=0xaa55)
		{ kprintf("%s: bad extended partition chain\n", name); break; }

		register_drive(id, part+cnt, (_u8)buf[0x1be +4], *(_u32*)(buf+0x1be +8), *(_u32*)(buf+0x1be +12));
		cnt++;
		p = buf[0x1be +20] ? base+*(_u32*)(buf+0x1be +24) : 0;
		if(p && p<=next)
		{ kprintf("%s: logic-lock found\n", name); break; }
		next = p;
	}
	return cnt;
}

static void register_hdd(void)
{
	int i, j, r;
	char name[8], buf[512], ch;

	for(i=0; i<4; i++)
		if(DRIVE_VALID(_hdd_drives[i]))
		{
			ksprintf(name, "hd%c", i+'a');
			if(!register_drive(i, 0, 0, 0, _hdd_drives[i].n_LBAsectors)) continue;

			r = hdd_read(i, 0, buf, 1);
			if(r!=0)
			{ kprintf("%s: sector 0 read error: %04X\n", name, r); continue; }

			if(*(_u16*)(buf+0x1fe)!=0xaa55)
			{ kprintf("%s: bad MBR\n", name); continue; }

			r = 5;
			for(j=0; j<4; j++)
			{
				ch = buf[0x1be +j*16+4];
				if(ch==0x0f || ch==0x05)
					r+=register_extension(i, *(_u32*)(buf+0x1be +j*16+8), *(_u32*)(buf+0x1be +j*16+12), r);
				else if(ch)
					register_drive(i, j+1, ch, *(_u32*)(buf+0x1be +j*16+8), *(_u32*)(buf+0x1be +j*16+12));
			}
		}
}

static long OnLoad(HDRIVER hDriver)
{
	_this_driver = hDriver;
	memset(_hdd_drives, 0, sizeof(DRIVE)*4);
	rqInitialize(&_hdd_requestqueue, 0, 0, sizeof(DEVREQUEST), NULL, hd_queue_proc, 0);
	return 0;
}

static long OnUnload(void)
{
	return 0;
}

void onHD(void)
{
	REQUEST *r;
	SysLock();
	r = rqGetPendingRequest(&_hdd_requestqueue);
	if(r)
	{
		DEVREQUEST *dr = rqGetRequestExtraMem(r);
		int id, port, c;

		KASSERT(dr, "onHD: null dr");
		KASSERT(r->status==RS_PENDING, "onHD: request not pending");
		
		id = ((HDDEVICE*)GetDeviceExtraMem(dr->device))->drive;
		port = _hdd_drives[id].port_base;
		c = wait_ide(port);

		if(c==0x58)
		{
			if(_hdd_drives[id].n_dwtrans)	// use dword transfer
			{
				if((dr->flags&DR_CMDMASK)==DR_READ)
					_insl(port, dr->buffer, dr->blocks*DEF_SECTORSIZE/4);
				else
					_outsl(port, dr->buffer, dr->blocks*DEF_SECTORSIZE/4);				
			}
			else
			{
				if((dr->flags&DR_CMDMASK)==DR_READ)
					_insw(port, dr->buffer, dr->blocks*DEF_SECTORSIZE/2);
				else
					_outsw(port, dr->buffer, dr->blocks*DEF_SECTORSIZE/2);
			}
			dr->errcode = 0;			
		}
		else
		{
			dr->errcode = HDE_TIMEOUT|c;
		}
		r->status = RS_COMPLETE;
		rqMoveNext(&_hdd_requestqueue);
		SignalBottomHalfProc(0xe, 1);
	}
	else KTRACE("onHD: no request\n");
	SysUnlock();
}

static void doHDBH(int todo)
{
	if(SysIsItemLocked(LOCK_TASK)) return;
	
	SignalBottomHalfProc(0xe, 0);	
	SysLock();
	rqNext(&_hdd_requestqueue);
	SysUnlock();
	SignalReschedule();
}

static long OnInstallDevices(void)
{
	// Detect IDE drives
	detect_hdd(IDE_PRIMARY);
	detect_hdd(IDE_SECONDARY);

	// Register logical drives
	register_hdd();

	// Install hdd interrupt
	RegisterBottomHalfProc(0xe, doHDBH);
	SetIRQ(0xe, (_u32)irq_hd);
	return 0;
}

long __syscall drvDefaultIDE(_u32 cmd, _u32 param1, _u32 param2)
{
	switch(cmd)
	{
	case DRV_SVC_LOAD: return OnLoad((HDRIVER)param1);
	case DRV_SVC_UNLOAD: return OnUnload();
	case DRV_SVC_INSTALLDEVICES:
		return OnInstallDevices();
	}
	return 0;
}

⌨️ 快捷键说明

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