📄 ide.c
字号:
return 0;}int ide_select_drive(int drive){ unsigned short select = g_ideinfo[drive].select.all; unsigned int status; OUT_BYTE(drive, select, IDE_SELECT_REG); if (ide_wait_stat(drive, BUSY_STAT, 0, 1)) return 1; if ((IN_BYTE(drive, IDE_SELECT_REG) & 0xff) != select) return 1; status = IN_BYTE(drive, IDE_STATUS_REG); return (status & READY_STAT) ? 0 : 1;}void ide_input_data(int drive, unsigned int *buf, unsigned int wcount){ unsigned short *ptr = (unsigned short *) buf; // read data while (wcount-- > 0) { *ptr++ = IN_WORD(drive, IDE_DATA_REG); *ptr++ = IN_WORD(drive, IDE_DATA_REG); }}void ide_output_data(int drive, unsigned int *buf, unsigned int wcount){ unsigned short *ptr = (unsigned short *) buf; // write data while (wcount-- > 0) { OUT_WORD(drive, *ptr++, IDE_DATA_REG); OUT_WORD(drive, *ptr++, IDE_DATA_REG); }}void ide_fixstring(unsigned char *s, const int bytecount, const int byteswap){ unsigned char *p = s, *end = &s[bytecount & ~1]; /* bytecount must be even */ if (byteswap) { /* convert from big-endian to host unsigned char order */ for (p = end ; p != s;) { unsigned short *pp = (unsigned short *) (p -= 2); *pp = ntohs(*pp); } } /* strip leading blanks */ while (s != end && *s == ' ') ++s; /* compress internal blanks and strip trailing blanks */ while (s != end && *s) { if (*s++ != ' ' || (s != end && *s && *s != ' ')) *p++ = *(s-1); } /* wipe out trailing garbage */ while (p != end) *p++ = '\0';}//// IDE Identify//static int ide_identify_cmd(int cmd, int drive, struct hd_driveid *pid);ide_info_t *ide_identify(int drive){ ide_info_t *pideinfo = g_ideinfo + drive; struct hd_driveid *pid = &pideinfo->id; pideinfo->type = IDE_NONE; if (ide_identify_cmd(WIN_IDENTIFY, drive, pid) == 0) { pideinfo->type = IDE_ATA; pideinfo->cyls = pid->cyls; pideinfo->heads = pid->heads; pideinfo->sectors = pid->sectors; // C/H/S = 16383/16/63 : LBA if (pid->cyls == 16383 && pid->heads == 16 && pid->sectors == 63) { pideinfo->lba = 1; pideinfo->nsectors = pid->lba_capacity; pideinfo->select.b.lba = 1; pideinfo->heads = 255; pideinfo->sectors = 63; pideinfo->cyls = pideinfo->nsectors / (255 * 63); } else { pideinfo->lba = 0; pideinfo->nsectors = pid->cyls * pid->heads * pid->sectors; pideinfo->select.b.lba = 0; } pideinfo->cap_dma = (pideinfo->id.capability & 1) ? 1 : 0; pideinfo->cap_udma = (pideinfo->id.field_valid & 0x04) ? 1 : 0; pideinfo->size = pideinfo->nsectors >> 11; } else if (ide_identify_cmd(WIN_PIDENTIFY, drive, pid) == 0) { pideinfo->type = IDE_ATAPI; } return pideinfo;}int ide_identify_cmd(int cmd, int drive, struct hd_driveid *pid){ if (ide_command(cmd, drive, 0, 0, 0, 0, 0, pid, SECTOR_WORDS) == 0) { ide_fixstring(pid->model, sizeof(pid->model), 1); ide_fixstring(pid->fw_rev, sizeof(pid->fw_rev), 1); ide_fixstring(pid->serial_no, sizeof(pid->serial_no), 1); return 0; } else return 1;}//// Other commands//int ide_set_drive_speed(int drive, int speed){ return ide_command(WIN_SETFEATURES, drive, SETFEATURES_XFER, 0, 0, 0, speed, NULL, 0);}//// IDE read/write//static int ide_chs_rw(int read, int dma, int drive, unsigned int block, unsigned char *buf, int nsector);static int ide_lbs_28_rw(int read, int dma, int drive, unsigned int block, unsigned char *buf, int nsector);int ide_rw_sector(int read, int dma, int drive, int cyl, int head, int sector, unsigned char *buf){ return ide_command(read ? (dma ? WIN_READDMA : WIN_READ) : (dma ? WIN_WRITEDMA : WIN_WRITE), drive, 0, cyl, head, sector, 1, buf, SECTOR_SIZE);}#define SECTOR_CHUNKS 8int ide_rw_block(int read, int dma, int drive, int block, unsigned char *buf, int nsector){ ide_info_t *pideinfo = g_ideinfo + drive; int nsector_transfer; if (pideinfo->type == IDE_NONE) return 1; while (nsector > 0) { nsector_transfer = (nsector >= SECTOR_CHUNKS) ? SECTOR_CHUNKS : nsector; if (pideinfo->lba) { if (ide_lbs_28_rw(read, dma, drive, block, buf, nsector_transfer)) return 1; } else { if (ide_chs_rw(read, dma, drive, block, buf, nsector_transfer)) return 1; } block += nsector_transfer; nsector -= nsector_transfer; buf += SECTOR_SIZE * nsector_transfer; } return 0;}int ide_chs_rw(int read, int dma, int drive, unsigned int block, unsigned char *buf, int nsector){ ide_info_t *pideinfo = g_ideinfo + drive; unsigned int track, sector, head, cyl; track = block / pideinfo->sectors; sector = block % pideinfo->sectors + 1; cyl = track / pideinfo->heads; head = track % pideinfo->heads; return ide_command(read ? (dma ? WIN_READDMA : WIN_READ) : (dma ? WIN_WRITEDMA : WIN_WRITE), drive, 0, cyl, head, sector, nsector, buf, SECTOR_SIZE * nsector);}int ide_lbs_28_rw(int read, int dma, int drive, unsigned int block, unsigned char *buf, int nsector){ int head, cyl, sector; sector = block & 0xff; cyl = (block >> 8) & 0xffff; head = (block >> 24) & 0xff; return ide_command(read ? (dma ? WIN_READDMA : WIN_READ) : (dma ? WIN_WRITEDMA : WIN_WRITE), drive, 0, cyl, head, sector, nsector, buf, SECTOR_SIZE * nsector);}//// partition table translation//#define MSDOS_LABEL_MAGIC1 0x55#define MSDOS_LABEL_MAGIC2 0xAAstruct partition { unsigned char boot_ind; /* 0x80 - active */ unsigned char head; /* starting head */ unsigned char sector; /* starting sector */ unsigned char cyl; /* starting cylinder */ unsigned char sys_ind; /* What partition type */ unsigned char end_head; /* end head */ unsigned char end_sector; /* end sector */ unsigned char end_cyl; /* end cylinder */ unsigned int start_sect; /* starting sector counting from 0 */ unsigned int nr_sects; /* nr of sectors in partition */} __attribute__((packed));static int msdos_magic_present(unsigned char *p){ return (p[0] == MSDOS_LABEL_MAGIC1 && p[1] == MSDOS_LABEL_MAGIC2);}int ide_read_partition(int drive, int *sectors, int showlist){ int i, npart = 0; unsigned char buf[SECTOR_SIZE]; struct partition *part; int sector_start, cyl_start, sector_end, cyl_end; if (ide_rw_block(1, 0, drive, 0, buf, 1)) return 0; if (!msdos_magic_present(buf + 510)) { printk("Invalid partition table\n"); return 0; } part = (struct partition *) (buf + 0x1be); if (showlist) printk("# : A TYPE [ CYL / HEAD / SEC - CYL / HEAD / SEC ] (#SECT)\n"); for (i = 0; i < 4; ++i) { if (part[i].nr_sects > 0) { if (sectors) sectors[i] = part[i].start_sect; ++npart; if (showlist) { sector_start = part[i].sector & 0x3f; cyl_start = ((part[i].sector & 0xc0) << 2) + part[i].cyl; sector_end = part[i].end_sector & 0x3f; cyl_end = ((part[i].end_sector & 0xc0) << 2) + part[i].end_cyl; printk("%d : %c %02x [ %4d / %4d / %3d - %4d / %4d / %3d ] (%d, %d = %dMB)\n", i, part[i].boot_ind & 0x80 ? 'A' : ' ', part[i].sys_ind, cyl_start, part[i].head, sector_start, cyl_end, part[i].end_head, sector_end, part[i].start_sect, part[i].nr_sects, part[i].nr_sects >> 11); } } else { if (sectors) sectors[i] = -1; } } return npart;}int ide_rw_block_partition(int read, int dma, int drive, int partition, int block, unsigned char *buf, int nsector){ int npart, part[MAX_PARTITIONS]; if ((npart = ide_read_partition(drive, part, 0)) < 0) return 1; if (partition < 0 || partition >= npart || part[partition] < 0) return 2; if (dma) return 1; // return ide_rw_dma_block(read, drive, part[partition] + block, buf, nsector); else return ide_rw_block(read, 0, drive, part[partition] + block, buf, nsector);}//// kernel image or filesystem in IDE device//int ide_probe_image(int drive, int *ppart, void *pinfo) { int i, npart, part[MAX_PARTITIONS]; int type; if ((npart = ide_read_partition(drive, part, 0)) < 0) return IMAGE_TYPE_NONE; for (i = 0; i < npart; ++i) { if ((type = ide_check_image(drive, i, pinfo)) != IMAGE_TYPE_NONE) { *ppart = i; return type; } } return IMAGE_TYPE_NONE;}int ide_check_image(int drive, int part, void *pinfo) { image_infoblock_t info; if (ide_rw_block_partition(1, 0, drive, part, 0, (unsigned char *) &info, 1)) return IMAGE_TYPE_NONE; if (pinfo) memcpy(pinfo, &info, sizeof info); if (strcmp(info.u.signature, IMAGE_SIGNATURE) != 0) return IMAGE_TYPE_NONE; if (strcmp(info.u.id, IMAGE_ID_KERNEL) == 0) return IMAGE_TYPE_KERNEL; else if (strcmp(info.u.id, IMAGE_ID_ROMFS) == 0) return IMAGE_TYPE_ROMFS; else return IMAGE_TYPE_NONE;}int ide_read_image(int type, int drive, int part, unsigned char *buf){ image_infoblock_t info; int foundtype = ide_check_image(drive, part, &info); if (type != IMAGE_TYPE_NONE && type != foundtype) return 1; return (ide_rw_block_partition(1, 0, drive, part, 1, buf, (info.u.len + SECTOR_SIZE - 1) / SECTOR_SIZE)) ? 1 : 0;}int ide_write_image(int type, int drive, int part, unsigned char *buf, int len){ image_infoblock_t info; memset(&info, 0, sizeof info); strcpy(info.u.signature, IMAGE_SIGNATURE); if (type == IMAGE_TYPE_KERNEL) strcpy(info.u.id, IMAGE_ID_KERNEL); else if (type == IMAGE_TYPE_ROMFS) strcpy(info.u.id, IMAGE_ID_ROMFS); else return 1; info.u.major = 1; info.u.minor = 0; info.u.len = len; if (ide_rw_block_partition(0, 0, drive, part, 0, (unsigned char *) &info, 1)) return 1; return (ide_rw_block_partition(0, 0, drive, part, 1, buf, (info.u.len + SECTOR_SIZE - 1) / SECTOR_SIZE)) ? 1 : 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -