/** * <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); } }
/** * <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--; }
/* * <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--; }
/* * <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); } }
/** * <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; } }
PUBLIC void kernelHdClose(u32 device) { int drive = DRV_OF_DEV(device); if(drive != 0) disp_str("drive != 0"); hd_info[drive].open_cnt--; }
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]); } }
/* * <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; } }
/* 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]); */ } }
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"); }
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"); } }
/* * @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); } }
/***************************************************************************** * 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"); }
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]); }
/** * <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]); } }
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"); } }
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; } }
/* * <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); } }
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; } }
/* 关闭硬盘 */ PRIVATE void hd_close(int device) { int drive = DRV_OF_DEV(device); assert(drive == 0); /* 只有一块硬盘 */ hd_info[drive].open_cnt--; /* 打开次数减一 */ }
PRIVATE void hd_close(int device) { int drive = DRV_OF_DEV(device); hd_info[drive].open_cnt--; }
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; } }
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); } }