Beispiel #1
0
/**
 * <Ring 1> This routine is called when a device is opened. It reads the
 * partition table(s) and fills the hd_info struct.
 *
 * @param device Device nr.
 * @param style  P_PRIMARY or P_EXTENDED.
 *****************************************************************************/
PRIVATE void partition(int device, int style)
{
    int i;
    int drive = DRV_OF_DEV(device);
    struct hd_info * hdi = &hd_info[drive];
    struct part_ent part_tbl[NR_SUB_PER_DRIVE];

    if (style == P_PRIMARY) {

        get_part_table(drive, drive, part_tbl);

        int nr_prim_parts = 0;

        for (i = 0; i < NR_PART_PER_DRIVE; i++) { /* 0~3 */
            if (part_tbl[i].sys_id == NO_PART)
                continue;

            nr_prim_parts++;

            //dev_nr從1開始,因為0是整個hd, 見P346
            int dev_nr = i + 1;		  /* 1~4 */

            hdi->primary[dev_nr].base = part_tbl[i].start_sect;
            hdi->primary[dev_nr].size = part_tbl[i].nr_sects;

            // 如果是extend的話,還要再往下分析是否有其他logic partition
            if (part_tbl[i].sys_id == EXT_PART) /* extended */
                partition(device + dev_nr, P_EXTENDED);
        }

        assert(nr_prim_parts != 0);
    }
    else if (style == P_EXTENDED) {


        int j = device % NR_PRIM_PER_DRIVE; /* 1~4 */
        int ext_start_sect = hdi->primary[j].base;
        int s = ext_start_sect;
        int nr_1st_sub = (j - 1) * NR_SUB_PER_PART; /* 0/16/32/48 */

        for (i = 0; i < NR_SUB_PER_PART; i++) {
            int dev_nr = nr_1st_sub + i;/* 0~15/16~31/32~47/48~63 */

            get_part_table(drive, s, part_tbl);

            hdi->logical[dev_nr].base = s + part_tbl[0].start_sect;
            hdi->logical[dev_nr].size = part_tbl[0].nr_sects;

            s = ext_start_sect + part_tbl[1].start_sect;

            /* no more logical partitions
               in this extended partition */
            if (part_tbl[1].sys_id == NO_PART)
                break;
        }
    }
    else {
        assert(0);
    }
}
Beispiel #2
0
/**
 * <Ring 1> This routine handles DEV_CLOSE message. 
 * 
 * @param device The device to be opened.
 *****************************************************************************/
PRIVATE void hd_close(int device)
{
	int drive = DRV_OF_DEV(device);
	assert(drive == 0);	/* only one drive */

	hd_info[drive].open_cnt--;
}
Beispiel #3
0
Datei: hd.c Projekt: cosail/lwos
/*
 * <ring 1> this routine handles DEV_CLOSE message.
 *
 * @param device - the device to be close.
 */
static void hd_close(int device)
{
	int drive = DRV_OF_DEV(device);
	assert(drive == 0);

	hd_info[drive].open_cnt--;
}
Beispiel #4
0
Datei: hd.c Projekt: cosail/lwos
/*
 * <ring 1> this routine is called when a device is opened. It reads the
 * partition table and fills the hd_info struct.
 *
 * @param device - device number.
 * @param style - P_PRIMARY or P_EXTENDED.
 */
static void partition(int device, int style)
{
	int i;
	int drive = DRV_OF_DEV(device);
	struct hd_info *hdi = &hd_info[drive];

	struct part_ent part_tbl[NR_SUB_PER_DRIVE];

	if (style == P_PRIMARY)
	{
		get_part_table(drive, drive, part_tbl);

		int nr_prim_parts = 0;
		for (i = 0; i< NR_PART_PER_DRIVE; i++)
		{
			if (part_tbl[i].sys_id == NO_PART)
			{
				continue;
			}

			nr_prim_parts++;
			int dev_nr = i + 1;
			hdi->primary[dev_nr].base = part_tbl[i].start_sect;
			hdi->primary[dev_nr].size = part_tbl[i].nr_sects;

			if (part_tbl[i].sys_id == EXT_PART)
				partition(device + dev_nr, P_EXTENDED);
		}
		
		assert(nr_prim_parts != 0);
	}
	else if (style == P_EXTENDED)
	{
		int j = device % NR_PRIM_PER_DRIVE;
		int ext_start_sect = hdi->primary[j].base;
		int s = ext_start_sect;
		int nr_1st_sub = (j - 1) * NR_SUB_PER_PART;

		for (i = 0; i < NR_SUB_PER_PART; i++)
		{
			int dev_nr = nr_1st_sub + i;

			get_part_table(drive, s, part_tbl);

			hdi->logical[dev_nr].base = s + part_tbl[0].start_sect;
			hdi->logical[dev_nr].size = part_tbl[0].nr_sects;

			s = ext_start_sect + part_tbl[1].start_sect;

			if (part_tbl[1].sys_id == NO_PART)
			{
				break;
			}
		}
	}
	else
	{
		assert(0);
	}
}
Beispiel #5
0
/**
 * <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;
    }
}
Beispiel #6
0
PUBLIC void kernelHdClose(u32 device)
{
	int drive = DRV_OF_DEV(device);
	if(drive != 0)
		disp_str("drive != 0");
	
	hd_info[drive].open_cnt--;
	
}
Beispiel #7
0
PRIVATE void hd_open(int device)
{
    int drive = DRV_OF_DEV(device);

    hd_identify(drive);

    if (hd_info[drive].open_cnt++ == 0) {
        partition(drive * (NR_PART_PER_DRIVE + 1), P_PRIMARY);
        print_hdinfo(&hd_info[drive]);
    }
}
Beispiel #8
0
Datei: hd.c Projekt: 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;
	}
}
Beispiel #9
0
Datei: hd.c Projekt: Zach41/OS
/* identify hard drive and print partition table */
PRIVATE void hd_open(int device) {
    int drive = DRV_OF_DEV(device);
    assert(drive == 0);	/* 系统上只有一个硬盘 */

    hd_identify(drive);

    if (hd_info[drive].open_cnt++ == 0) {
	/* 第一次打开硬盘 */
	partition(drive * (NR_PART_PER_DRIVE + 1), P_PRIMARY);
	/* print_hdinfo(&hd_info[drive]); */
    }
}
Beispiel #10
0
PUBLIC void kernelHdIoctl(u32 device, u32 request, char* buf)
{
	int drive = DRV_OF_DEV(device);

	struct hd_info * hdi = &hd_info[drive];

	if(request == DIOCTL_GET_GEO){
		memcpy(buf, 
			device < MAX_PRIM ? &hdi->primary[device] : &hdi->logical[(device - MINOR_hd1a) % NR_SUB_PER_DRIVE],
			sizeof(struct part_info));
	}
	else
		disp_str("no such command\n");
}
Beispiel #11
0
Datei: hd.c Projekt: Zach41/OS
PRIVATE void hd_ioctl(MESSAGE* p_msg) {
    int device = p_msg -> DEVICE;
    int drive  = DRV_OF_DEV(device);

    HD_INFO* hdi = &hd_info[drive];

    if (p_msg -> REQUEST == DIOCTL_GET_GEO) {
	void* dst = va2la(p_msg -> PROC_NR, p_msg -> BUF);
	void* src = va2la(TASK_HD, device < MAX_PRIM ? &hdi->primary[drive] : &hdi->logical[(device - MINOR_hd1a) % NR_SUB_PER_DRIVE]);
	memcpy(dst, src, sizeof(PART_ENT));
    } else {
	spin("HD No IO CTL");
    }
}
Beispiel #12
0
Datei: hd.c Projekt: Zach41/OS
/* 
 * @param device Device number
 * @param style  Primary or extended
 */
PRIVATE void partition(int device, int style) {
    int drive = DRV_OF_DEV(device);
    HD_INFO *hdi = &hd_info[drive];

    PART_ENT part_tbl[NR_SUB_PER_DRIVE];
    if (style == P_PRIMARY) {
	/* 如果是主分区 */
	get_part_table(drive, drive, part_tbl);
	int nr_prim_parts = 0;
	for (int i=0; i<NR_PART_PER_DRIVE; i++) {
	    if (part_tbl[i].sys_id == NO_PART) {
		continue;
	    }

	    nr_prim_parts++;

	    int dev_nr = i+1;
	    hdi -> primary[dev_nr].base = part_tbl[i].start_sect;
	    hdi -> primary[dev_nr].size = part_tbl[i].nr_sects;

	    if (part_tbl[i].sys_id == EXT_PART) {
		partition(device + dev_nr, P_EXTENDED);
	    }
	}
	assert(nr_prim_parts);
    } else if (style == P_EXTENDED) {
	/* 如果是扩展分区 */
	int j = device % NR_PRIM_PER_DRIVE; /* drive number */
	int ext_start_sect = hdi -> primary[j].base;
	int start = ext_start_sect;

	int nr_1st_sub = (j-1)*NR_SUB_PER_PART; /* 第一个逻辑分区号 */

	for(int i=0; i<NR_SUB_PER_PART; i++) {
	    int dev_nr = nr_1st_sub + i; /* 逻辑分区次设备号 */
	    get_part_table(drive, start, part_tbl);

	    hdi -> logical[dev_nr].base = start + part_tbl[0].start_sect;
	    hdi -> logical[dev_nr].size = part_tbl[0].nr_sects;

	    start = ext_start_sect + part_tbl[1].start_sect;

	    if (part_tbl[1].sys_id == NO_PART)
		break;
	}
    } else {
	assert(0);
    }
}
Beispiel #13
0
/*****************************************************************************
 *                                partition
 *****************************************************************************
 * <Ring 1> This routine is called when a device is opened. It reads the
 * partition table(s) and fills the hd_info struct.
 * 
 * @param device Device nr.
 * @param style  P_PRIMARY or P_EXTENDED.
 *****************************************************************************/
PRIVATE void partition(int device, int style)
{
	int i;
	int drive = DRV_OF_DEV(device);
	struct hd_info* hdi = &hd_info[drive];

	struct part_ent part_table[NR_SUB_PER_DRIVE];

	if(style == P_PRIMARY){
		get_part_table(drive, drive, part_table);

		int nr_prim_parts = 0;
		for(i = 0; i < NR_PART_PER_DRIVE; i++){
			if(part_table[i].sys_id == NO_PART)
				continue;

			nr_prim_parts++;
			int dev_nr = i + 1;			/* 1~4*/
			hdi->primary[dev_nr].base = part_table[i].start_sect;
			hdi->primary[dev_nr].size = part_table[i].nr_sects;

			if(part_table[i].sys_id == EXT_PART)	/* extended */
				partition(device + dev_nr, P_EXTENDED);
		}
	}
	else if(style == P_EXTENDED){
		int j = device % NR_PRIM_PER_DRIVE;	/* 1~4 */
		int ext_start_sect = hdi->primary[j].base;
		int s = ext_start_sect;
		int nr_1st_sub = (j - 1) * NR_SUB_PER_PART; /* 0/16/32/48 */

		for(i = 0; i < NR_SUB_PER_PART; i++){
			int dev_nr = nr_1st_sub + i;/* 0~15/16~31/32~47/48~63 */

			get_part_table(drive, s, part_table);

			hdi->logical[dev_nr].base = s + part_table[0].start_sect;
			hdi->logical[dev_nr].size = part_table[0].nr_sects;

			s = ext_start_sect + part_table[1].start_sect;

			if(part_table[1].sys_id == NO_PART)
				break;
		}
	}
	else
		disp_str("con't hadle such TYPE of partition\n");
}
Beispiel #14
0
PUBLIC struct hd_info* kernelHdOpen(int device)
{
	int drive = DRV_OF_DEV(device);
	if(drive != 0)
	{
		disp_str("hd open error\n");
	}

	kernelHdIdentify(drive);

	if(hd_info[drive].open_cnt++ == 0){
		partition(drive * (NR_PART_PER_DRIVE + 1), P_PRIMARY);
		//print_hdinfo(&hd_info[drive]);
	}

	return &(hd_info[0]);
}
Beispiel #15
0
/**
 * <Ring 1> This routine handles DEV_OPEN message. It identify the drive
 * of the given device and read the partition table of the drive if it
 * has not been read.
 *
 * @param device The device to be opened.
 *****************************************************************************/
PRIVATE void hd_open(int device)
{
    int drive = DRV_OF_DEV(device);

    ERIC_HD("\nHD_open=%x",drive);

    assert(drive == 0);	/* only one drive */

    hd_identify(drive);

    // ++的優先權很高, 而 == 號優先權約在中間,所以要小心
    if (hd_info[drive].open_cnt++ == 0) {
        //列印主分區,每個hd都只有4個主分區
        partition(drive * (NR_PART_PER_DRIVE + 1), P_PRIMARY);
        print_hdinfo(&hd_info[drive]);
    }
}
Beispiel #16
0
PRIVATE void hd_ioctl(MESSAGE *p)
{
    int device = p->DEVICE;
    int drive = DRV_OF_DEV(device);

    struct hd_info *hdi = &hdinfo[drive];

    if (p->REQUEST == DIOCTL_GET_GEO) {
        void *dst = va2la(p->PROC_NR, p->BUF);
        void *src = va2la(TASK_HD,
                device < MAX_PRIM ?
                &hdi->primary[device] :
                &hdi->logical[(device - MINOR_hd1a) % NR_SUB_PER_DRIVE]);
        phys_copy(dst, src, sizeof (struct part_info));
    } else {
        kprintf("[KERNEL ERROR]error ioctl cmd\n");
    }
}
Beispiel #17
0
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;
    }
}
Beispiel #18
0
Datei: hd.c Projekt: cosail/lwos
/*
 * <ring 1> this routine handles the DEV_IOCTL messge.
 *
 * @param msg - message.
 */
static void hd_ioctl(MESSAGE *msg)
{
	int device = msg->DEVICE;
	int drive = DRV_OF_DEV(device);

	struct hd_info *hdi = &hd_info[drive];

	if (msg->REQUEST == DIOCTL_GET_GEO)
	{
		void *dst = va2la(msg->PROC_NR, msg->BUF);
		void *src = va2la(TASK_HD, device < MAX_PRIM ?
			&hdi->primary[device] :
			&hdi->logical[(device - MINOR_hd1a) % NR_SUB_PER_DRIVE]);
		phys_copy(dst, src, sizeof(struct part_info));
	}
	else
	{
		assert(0);
	}
}
Beispiel #19
0
Datei: hd.c Projekt: 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;
    }
}
Beispiel #20
0
Datei: hd.c Projekt: Zach41/OS
/* 关闭硬盘 */
PRIVATE void hd_close(int device) {
    int drive = DRV_OF_DEV(device);
    assert(drive == 0);		/* 只有一块硬盘 */
    hd_info[drive].open_cnt--;	/* 打开次数减一 */
}
Beispiel #21
0
PRIVATE void hd_close(int device)
{
    int drive = DRV_OF_DEV(device);

    hd_info[drive].open_cnt--;
}
Beispiel #22
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;
	}
}
Beispiel #23
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);
	}
}