예제 #1
0
파일: hd.c 프로젝트: wwssllabcd/myOS
/**
 * <Ring 1> This routine handles DEV_READ and DEV_WRITE message.
 *
 * @param p Message ptr.
 *****************************************************************************/
PRIVATE void hd_rdwt(MESSAGE * p)
{
    // p->DEVICE 為 0x20,也就是 hd2a
    int pDev = p->DEVICE;
    int drive = DRV_OF_DEV(p->DEVICE);
    u64 pos = p->POSITION;
    assert((pos >> SECTOR_SIZE_SHIFT) < (1 << 31));

    /**
     * We only allow to R/W from a SECTOR boundary:
     */
    assert((pos & 0x1FF) == 0);

    u32 sect_nr = (u32)(pos >> SECTOR_SIZE_SHIFT); /* pos / SECTOR_SIZE */

    //取出logic index
    int logidx = (p->DEVICE - MINOR_hd1a) % NR_SUB_PER_DRIVE;

    // 找出某個partition的LBA,
    // MAX_PRIM=9,代表Hd0~Hd9為primary的編號,超過9以上的編號都是logic
    sect_nr += p->DEVICE < MAX_PRIM ?
               hd_info[drive].primary[p->DEVICE].base :
               hd_info[drive].logical[logidx].base;

    ERIC_HD("\nHDRW=%x", sect_nr);

    struct hd_cmd cmd;
    cmd.features	= 0;
    cmd.count	= (p->CNT + SECTOR_SIZE - 1) / SECTOR_SIZE;
    cmd.lba_low	= sect_nr & 0xFF;
    cmd.lba_mid	= (sect_nr >>  8) & 0xFF;
    cmd.lba_high= (sect_nr >> 16) & 0xFF;
    cmd.device	= MAKE_DEVICE_REG(1, drive, (sect_nr >> 24) & 0xF);
    cmd.command	= (p->type == DEV_READ) ? ATA_READ : ATA_WRITE;

    hd_cmd_out(&cmd);

    int bytes_left = p->CNT;
    void * la = (void*)va2la(p->PROC_NR, p->BUF);

    while (bytes_left) {
        //一次只讀512 byte
        int bytes = min(SECTOR_SIZE, bytes_left);

        if (p->type == DEV_READ) {
            interrupt_wait();
            port_read(REG_DATA, hdbuf, SECTOR_SIZE);
            phys_copy(la, (void*)va2la(TASK_HD, hdbuf), bytes);
        }
        else {
            if (!waitfor(STATUS_DRQ, STATUS_DRQ, HD_TIMEOUT))
                panic("hd writing error.");

            port_write(REG_DATA, la, bytes);
            interrupt_wait();
        }
        bytes_left -= SECTOR_SIZE;
        la += SECTOR_SIZE;
    }
}
예제 #2
0
파일: hd.c 프로젝트: gtxx3600/mySimpleOS
/**
 * <Ring 1> Get the disk information.
 * 
 * @param drive  Drive Nr.
 *****************************************************************************/
PRIVATE void hd_identify(int drive)
{
	struct hd_cmd cmd;
	cmd.device  = MAKE_DEVICE_REG(0, drive, 0);
	cmd.command = ATA_IDENTIFY;
	hd_cmd_out(&cmd);
	interrupt_wait();
	port_read(REG_DATA, hdbuf, SECTOR_SIZE);

	print_identify_info((u16*)hdbuf);
}
예제 #3
0
파일: hd.c 프로젝트: cosail/lwos
/*
 * <ring 1> this routine handles DEV_READ and DEV_WRITE message.
 *
 * @param msg - message
 */
static void hd_rdwt(MESSAGE *msg)
{
	int drive = DRV_OF_DEV(msg->DEVICE);

	u64 pos = msg->POSITION;
	assert((pos >> SECTOR_SIZE_SHIFT) < (1 << 31));

	assert((pos & 0x1ff) == 0);

	u32 sect_nr = (u32)(pos >> SECTOR_SIZE_SHIFT);
	int logidx = (msg->DEVICE - MINOR_hd1a) % NR_SUB_PER_DRIVE;
	sect_nr += msg->DEVICE < MAX_PRIM ?
		hd_info[drive].primary[msg->DEVICE].base :
		hd_info[drive].logical[logidx].base;

	struct hd_cmd cmd;
	cmd.features = 0;
	cmd.count = (msg->CNT + SECTOR_SIZE - 1) / SECTOR_SIZE;
	cmd.lba_low = sect_nr & 0xff;
	cmd.lba_mid = (sect_nr >> 8) & 0xff;
	cmd.lba_high = (sect_nr >> 16) & 0xff;
	cmd.device = MAKE_DEVICE_REG(1, drive, (sect_nr >> 24) & 0xf);
	cmd.command = (msg->type == DEV_READ) ? ATA_READ : ATA_WRITE;

	hd_cmd_out(&cmd);

	int bytes_left = msg->CNT;
	void *la = (void*)va2la(msg->PROC_NR, msg->BUF);

	while (bytes_left > 0)
	{
		int bytes = min(SECTOR_SIZE, bytes_left);
		if (msg->type == DEV_READ)
		{
			interrupt_wait();
			port_read(REG_DATA, hdbuf, SECTOR_SIZE);
			phys_copy(la, (void*)va2la(TASK_HD, hdbuf), bytes);
		}
		else
		{
			if (!waitfor(STATUS_DRQ, STATUS_DRQ, HD_TIMEOUT))
			{
				panic("hd writing error.");
			}

			port_write(REG_DATA, la, bytes);
			interrupt_wait();
		}

		bytes_left -= SECTOR_SIZE;
		la += SECTOR_SIZE;
	}
}
예제 #4
0
/* @param drive  When drive == 0, master is selected
		When drive == 1 slave is selected*/
PUBLIC void kernelHdIdentify(int drive)
{
	struct hd_cmd cmd;
	cmd.device = MAKE_DEVICE_REG(0, drive, 0);
	cmd.command = ATA_IDENTIFY;
	hd_cmd_out(&cmd);
	hdIdentifyBlockEip = p_proc_running - proc_table;
	kernelBlock();
	port_read(REG_DATA, hdbuf, SECTOR_SIZE);

	//analysis_identify_info((u16*)hdbuf);
}
예제 #5
0
파일: hd.c 프로젝트: cosail/lwos
/*
 *	<ring 1> get the disk information
 */
static void hd_identify(int drive)
{
	struct hd_cmd cmd;
	cmd.device = MAKE_DEVICE_REG(0, drive, 0);
	cmd.command = ATA_INDENTIFY;
	hd_cmd_out(&cmd);
	interrupt_wait();
	port_read(REG_DATA, hdbuf, SECTOR_SIZE);

	print_identify_info((u16*)hdbuf);
	
	u16 * hdinfo = (u16*)hdbuf;
	hd_info[drive].primary[0].base = 0;
	hd_info[drive].primary[0].size = ((int)hdinfo[61] << 16) + hdinfo[60];
}
예제 #6
0
파일: hd.c 프로젝트: yankaifyyy/Owindy-S
PRIVATE void get_part_table(int drive, int sectnr, struct part_ent *entry)
{
    struct hd_cmd cmd;
    cmd.features = 0;
    cmd.count = 1;
    cmd.lba_low = sect_nr & 0xff;
    cmd.lba_mid = (sect_nr >> 8) & 0xff;
    cmd.lba_high = (sect_nr >> 16) & 0xff;
    cmd.device = MAKE_DEVICE_REG(1, drive, (sect_nr >> 24) & 0xf);
    cmd.command = ATA_READ;
    hd_cmd_out(&cmd);
    interrupt_wait();

    port_read(REG_DATA, hdbuf, SECTOR_SIZE);
    memcpy(entry, hdbuf + PARTITION_TABLE_OFFSET, sizeof (struct part_ent) * NR_PART_PER_DRIVE);
}
예제 #7
0
파일: hd.c 프로젝트: yankaifyyy/Owindy-S
PRIVAATE void hd_rdwt(MESSAGE *p)
{
    int drive = DRV_OF_DEV(p->DEVICE);
    
    u64_t pos = p->POSITION;
    
    u32_t sect_nr = (u32_t)(pos >> SECTOR_SIZE_SHIFT);

    int logidx = (p->DEVICE - MINOR_HD1a) % NR_SUB_PER_DRIVE;
    sect_nr += p->DEVICE < MAX_PRIM ?
        hd_info[drive].primary[p->DEVICE].base :
        hd_info[drive].logical[logidx].base;

    struct hd_cmd cmd;
    cmd.features = 0;
    cmd.count = (p->CNT + SECTOR_SIZE - 1) / SECTOR_SIZE;
    cmd.lba_low = sect_nr & 0xff;
    cmd.lba_mid = (sect_nr >> 8) & 0xff;
    cmd.lba_high = (sect_nr >> 16) & 0xff;
    cmd.device = MAKE_DEVICE_REG(1, drive, (sect_nr >> 24) & 0xf);
    cmd.command = (p->type == DEV_READ) ? ATA_READ : ATA_WRITE;
    hd_cmd_out(&cmd);

    int bytes_left = p->CNT;
    void *la = (void*)va2la(p->PROC_NR, p->BUF);

    while (bytes_left) {
        int bytes = min(SECTOR_SIZE, bytes_left);
        if (p->type == DEV_READ) {
            interrupt_wait();
            port_read(REG_DATA, hdbuf, SECTOR_SIZE);
            phys_copy(la, (void*)va2la(TASK_HD, hdbuf), bytes);
        } else {
            if (!waitfor(STATUS_DRQ, STATUS_DRQ, HD_TIMEOUT)) {
                kprintf("[KERNEL ERROR]hd writing error.\n");
                break;
            }
            port_write(REG_DATA, la, bytes);
            interrupt_wait();
        }
        bytes_left -= SECTOR_SIZE;
        la += SECTOR_SIZE;
    }
}
예제 #8
0
파일: hd.c 프로젝트: wwssllabcd/myOS
/**
 * <Ring 1> Get the disk information.
 *
 * @param drive  Drive Nr.
 *****************************************************************************/
PRIVATE void hd_identify(int drive)
{
    struct hd_cmd cmd;
    cmd.device  = MAKE_DEVICE_REG(0, drive, 0);
    cmd.command = ATA_IDENTIFY;
    ERIC_DEBUG(",IdTB");
    hd_cmd_out(&cmd);
    interrupt_wait();

    ERIC_DEBUG(",ReadData");
    port_read(REG_DATA, hdbuf, SECTOR_SIZE);
    print_identify_info((u16*)hdbuf);

    u16* hdinfo = (u16*)hdbuf;

    hd_info[drive].primary[0].base = 0;
    /* Total Nr of User Addressable Sectors */
    hd_info[drive].primary[0].size = ((int)hdinfo[61] << 16) + hdinfo[60];
}
예제 #9
0
파일: hd.c 프로젝트: Zach41/OS
PRIVATE void hd_identify(int drive) {
    HD_CMD cmd;

    cmd.device  = MAKE_DEVICE_REG(0, drive, 0);
    cmd.command = ATA_IDENTIFY;	/* 向硬盘发送IDENTIFY指令 */

    hd_cmd_out(&cmd);
    interrupt_wait();

    /* 中断结束 */
    port_read(REG_DATA, hdbuf, SECTOR_SIZE);

    /* print_identify_info((u16*)hdbuf); */

    u16* hdinfo = (u16*)hdbuf;

    hd_info[drive].primary[0].base = 0;
    hd_info[drive].primary[0].size = ((int)hdinfo[61] << 16) + hdinfo[60];
}
예제 #10
0
파일: hd.c 프로젝트: Zach41/OS
PRIVATE void get_part_table(int drive, int sect_nr, PART_ENT* entry) {
    HD_CMD cmd;
    /* 设置命令 */
    cmd.features = 0;
    cmd.count    = 1;
    cmd.lba_low  = sect_nr & 0xFF;
    cmd.lba_mid  = (sect_nr >> 8) & 0xFF;
    cmd.lba_high = (sect_nr >> 16) & 0xFF;
    cmd.device   = MAKE_DEVICE_REG(1, drive, (sect_nr >> 24) & 0xF); /* LBA Mode */

    cmd.command  = ATA_READ;

    hd_cmd_out(&cmd);
    /* 等待中断发生 */
    interrupt_wait();
    /* 数据已经就绪 */
    port_read(REG_DATA, hdbuf, SECTOR_SIZE);
    /* 分区表的偏移为PARTITION_TABLE_OFFSET = 0x1BE */
    memcpy(entry, hdbuf + PARTITION_TABLE_OFFSET, sizeof(PART_ENT) * NR_PART_PER_DRIVE);
}
예제 #11
0
파일: hd.c 프로젝트: Zach41/OS
PRIVATE void hd_rdwt(MESSAGE* p_msg) {
    int drive = DRV_OF_DEV(p_msg -> DEVICE);
    u64 pos = p_msg -> POSITION;

    assert((pos & 0x1FF) == 0);	/* 只允许从扇区边界开始读 */

    u32 sect_nr = (u32)(pos >> SECTOR_SIZE_SHIFT);
    int logidx  = (p_msg -> DEVICE - MINOR_hd1a) % NR_SUB_PER_DRIVE;
    sect_nr    += p_msg -> DEVICE < MAX_PRIM ? hd_info[drive].primary[p_msg -> DEVICE].base : hd_info[drive].logical[logidx].base;
    
    HD_CMD cmd;
    cmd.features = 0;
    cmd.count    = (p_msg -> CNT + SECTOR_SIZE - 1) / SECTOR_SIZE;
    cmd.lba_low  = sect_nr & 0xFF;
    cmd.lba_mid  = (sect_nr >> 8) & 0xFF;
    cmd.lba_high = (sect_nr >> 16) & 0xFF;
    cmd.device   = MAKE_DEVICE_REG(1, drive, (sect_nr >> 24) & 0xF);
    cmd.command  = (p_msg -> type == DEV_READ) ? ATA_READ : ATA_WRITE;
    hd_cmd_out(&cmd);

    int bytes_left = p_msg -> CNT;
    void* la = (void*)va2la(p_msg -> PROC_NR, p_msg -> BUF);

    while (bytes_left > 0) {
	int bytes = min(bytes_left, SECTOR_SIZE);
	if (p_msg -> type == DEV_READ) {
	    /* 一次中断一个扇区 */
	    interrupt_wait();
	    port_read(REG_DATA, hdbuf, SECTOR_SIZE);
	    memcpy(la, (void*)va2la(TASK_HD, hdbuf), bytes);
	} else {
	    if (!waitfor(STATUS_DRQ, STATUS_DRQ, HD_TIMEOUT))
		panic("HD writing error");
	    port_write(REG_DATA, la, bytes);
	    interrupt_wait();
	}
	la += bytes;
	bytes_left -= bytes;
    }
}
예제 #12
0
/*****************************************************************************
 *                                get_part_table
 *****************************************************************************
 * <Ring 1> Get a partition table of a drive.
 * 
 * @param drive   Drive nr (0 for the 1st disk, 1 for the 2nd, ...)n
 * @param sect_nr The sector at which the partition table is located.
 * @param entry   Ptr to part_ent struct.
 *****************************************************************************/
PRIVATE void get_part_table(int drive, int sect_nr, struct part_ent * entry)
{
	struct hd_cmd cmd;
	cmd.features = 0;
	cmd.count = 1;
	cmd.lba_low = sect_nr & 0xFF;
	cmd.lba_mid = (sect_nr >> 8) & 0xFF;
	cmd.lba_high = (sect_nr >> 16) & 0xFF;
	cmd.device = MAKE_DEVICE_REG(1, /* LBA mode */
				     drive, 
				     (sect_nr >> 24) & 0xF);
	cmd.command = ATA_READ;
	hd_cmd_out(&cmd);
	hdIdentifyBlockEip = p_proc_running - proc_table;
	kernelBlock();
	asm("sti");
	
	port_read(REG_DATA, hdbuf, SECTOR_SIZE);
	memcpy(entry,
		hdbuf + PARTITION_TABLE_OFFSET, 
		sizeof(struct part_ent) * NR_PART_PER_DRIVE);
}
예제 #13
0
파일: hd.c 프로젝트: wwssllabcd/myOS
/**
 * <Ring 1> Get a partition table of a drive.
 *
 * @param drive   Drive nr (0 for the 1st disk, 1 for the 2nd, ...)n
 * @param sect_nr The sector at which the partition table is located.
 * @param entry   Ptr to part_ent struct.
 *****************************************************************************/
PRIVATE void get_part_table(int drive, int sect_nr, struct part_ent * entry)
{
    ERIC_HD("\nGetPTable=%x", sect_nr);

    struct hd_cmd cmd;
    // ata read cmd ( 0x20 )
    cmd.features	= 0;
    cmd.count	= 1;
    cmd.lba_low	= sect_nr & 0xFF;
    cmd.lba_mid	= (sect_nr >>  8) & 0xFF;
    cmd.lba_high	= (sect_nr >> 16) & 0xFF;
    cmd.device	= MAKE_DEVICE_REG(1, /* LBA mode*/
                                  drive,
                                  (sect_nr >> 24) & 0xF);
    cmd.command	= ATA_READ;
    hd_cmd_out(&cmd);
    interrupt_wait();

    port_read(REG_DATA, hdbuf, SECTOR_SIZE);
    memcpy(entry,
           hdbuf + PARTITION_TABLE_OFFSET,
           sizeof(struct part_ent) * NR_PART_PER_DRIVE);
}
예제 #14
0
PUBLIC void kernelHdRead(u32 device, u64 position, u32 count, char* buf)
{
//	hd_status = in_byte(REG_STATUS);
//	disp_str("before hd_status=");
//	disp_int(hd_status);
//	disp_str("\n");
	device = 0;
	int drive = DRV_OF_DEV(device);
//	disp_str("hdRead position: ");
//	disp_int(position);
//	if((position & 0x1FF) != 0)
//		disp_str("we only allow to R/W from a SECTOR boundary\n");
	int offset_in_block = position & 0x1FF;
	
	u32 sect_nr = (u32)(position >> SECTOR_SIZE_SHIFT);
	int logidx = (device - MINOR_hd1a) % NR_SUB_PER_DRIVE;
	sect_nr += device < MAX_PRIM ?
			hd_info[drive].primary[device].base :
			hd_info[drive].logical[logidx].base;
	
	struct hd_cmd cmd;
	cmd.features = 0;
	cmd.count = (offset_in_block + count + SECTOR_SIZE - 1) / SECTOR_SIZE;
	cmd.lba_low = sect_nr & 0xFF;
	cmd.lba_mid = (sect_nr >> 8) & 0xFF;
	cmd.lba_high = (sect_nr >> 16) & 0xFF;
	cmd.device = MAKE_DEVICE_REG(1, drive, (sect_nr >> 24) & 0xF);
	cmd.command = ATA_READ;
	hd_cmd_out(&cmd);
	asm("cli");
	int bytes_left = count;
//	disp_int(count);
	char** pbuf = &buf;
	char blockBuf[SECTOR_SIZE] = {'\0'};
	int firstFlag = 1;

	while(bytes_left > 0){
//		disp_str("in hd loop@@@");	
//		disp_str("hd, byte_lefs=");
//		disp_int(bytes_left);
		int bytes = ((SECTOR_SIZE - offset_in_block) < bytes_left )? (SECTOR_SIZE - offset_in_block) : bytes_left;
//		disp_str("hd loop,bytes=");
//		disp_int(bytes);
//
//		disp_str("hd loop,beytes_left=");
//		disp_int(bytes_left);

		hdIdentifyBlockEip = p_proc_running - proc_table;
		kernelBlock();

		port_read(REG_DATA, blockBuf, SECTOR_SIZE);
		if(!firstFlag)
			offset_in_block = 0;
		else
			firstFlag = 0;
			
		memcpy(*pbuf, &(blockBuf[offset_in_block]), bytes);

		bytes_left -= bytes;
		*pbuf += bytes;
//		disp_str("hd loop,beytes_left=");
//		disp_int(bytes_left);
	}
}
예제 #15
0
PUBLIC void kernelHdWrite(u32 device, u64 position, u32 count, char* buf)
{

//	disp_int((void*) kernelHdWrite);
//	hd_status = hd_status & 0xf7;
//	disp_str("after hd_status=");
//	disp_int(hd_status);
//	disp_str("\n");
//	out_byte(REG_STATUS, hd_status);
//	hd_status = in_byte(REG_STATUS);

//	int drive = DRV_OF_DEV(device);
//
//
//	if((position & 0x1FF) != 0)
//	{
//		disp_str("we only allow to R/W from a SECTOR boundary\n");
//	}
//	
//	u32 sect_nr = (u32)(position >> SECTOR_SIZE_SHIFT);
//	int logidx = (device - MINOR_hd1a) % NR_SUB_PER_DRIVE;
//	sect_nr += device < MAX_PRIM ?
//			hd_info[drive].primary[device].base :
//			hd_info[drive].logical[logidx].base;
//	
//	struct hd_cmd cmd;
//	cmd.features = 0;
//	cmd.count = (count + SECTOR_SIZE - 1) / SECTOR_SIZE;
//	disp_str("count: ");
//	disp_int(cmd.count);
//	cmd.lba_low = sect_nr & 0xFF;
//	disp_str("\nlba_low: ");
//	disp_int(cmd.lba_low);
//	cmd.lba_mid = (sect_nr >> 8) & 0xFF;
//	disp_str("\nlba_mid: ");
//	disp_int(cmd.lba_mid);
//	cmd.lba_high = (sect_nr >> 16) & 0xFF;
//	disp_str("\nlba_high: ");
//	disp_int(cmd.lba_high);
//	cmd.device = MAKE_DEVICE_REG(1, drive, (sect_nr >> 24) & 0xF);
//	disp_str("\ndevice: ");
//	disp_int(cmd.device);
//	cmd.command = ATA_WRITE;
//	disp_str("\ncommand: ");
//	disp_int(cmd.command);
//	disp_str("\n");
//	hd_cmd_out(&cmd);
//	asm("sti");
//	
//	disp_str("cmd out");
//	int bytes_left = count;
//	while(bytes_left > 0){
//		int bytes = (SECTOR_SIZE <  bytes_left) ? SECTOR_SIZE : bytes_left;
//
//		if(!waitfor(STATUS_DRQ, STATUS_DRQ, HD_TIMEOUT))
//			disp_str("hd writing error.\n");
//
//		port_write(REG_DATA, buf, bytes);
//		hdIdentifyBlockEip = p_proc_running - proc_table;
//		disp_int(hdIdentifyBlockEip);
//		disp_str("before block!\n");
//		asm("cli");
//		kernelBlock();
//		asm("sti");
//		disp_str("after block!\n");
//		bytes_left -= bytes;
//		buf += bytes;
//	}
	int drive = DRV_OF_DEV(device);

	u64 pos = position;

	u32 sect_nr = (u32)(pos >> SECTOR_SIZE_SHIFT);
	int logidx = (device - MINOR_hd1a) % NR_SUB_PER_DRIVE;
	sect_nr += device < MAX_PRIM ?
		hd_info[drive].primary[device].base :
		hd_info[drive].logical[logidx].base;
	
	struct hd_cmd cmd;
	cmd.features = 0;
	cmd.count = (count + SECTOR_SIZE - 1) / SECTOR_SIZE;
	cmd.lba_low = sect_nr & 0xFF;
	cmd.lba_mid = (sect_nr >> 8) & 0xFF;
	cmd.lba_high = (sect_nr >> 16) & 0xFF;
	cmd.device = MAKE_DEVICE_REG(1, drive, (sect_nr >> 24) & 0xF);
	cmd.command = ATA_WRITE;
	hd_cmd_out(&cmd);

	int bytes_left = count;
	while(bytes_left > 0){
		int bytes = (SECTOR_SIZE < bytes_left) ? SECTOR_SIZE : bytes_left;

		if(!waitfor(STATUS_DRQ, STATUS_DRQ, HD_TIMEOUT))
			disp_str("hd writing error.\n");

		port_write(REG_DATA, buf, bytes);
		hdIdentifyBlockEip = p_proc_running - proc_table;
		kernelBlock();
		
		bytes_left -= bytes;
		buf += bytes;
	}
}