From: acevest Date: Tue, 9 Nov 2021 12:23:47 +0000 (+0800) Subject: 开始重写ATA硬盘驱动程序,目前已经获取硬盘基本信息,包括是否支持DMA和LBA48,还有硬盘大小 X-Git-Url: http://zhaoyanbai.com/repos/topojson.min.js?a=commitdiff_plain;h=cab29858a006e6d367a7a0bebb441b778fdf5b36;p=kernel.git 开始重写ATA硬盘驱动程序,目前已经获取硬盘基本信息,包括是否支持DMA和LBA48,还有硬盘大小 --- diff --git a/.bochsrc b/.bochsrc index 20bfd97..939539d 100644 --- a/.bochsrc +++ b/.bochsrc @@ -17,6 +17,7 @@ #======================================================================= #plugin_ctrl: unmapped=0, e1000=1 # unload 'unmapped' and load 'e1000' + #======================================================================= # CONFIG_INTERFACE # @@ -539,7 +540,7 @@ vga: extension=vbe, update_freq=5, realtime=1, ddc=builtin # mouse: type=serial, enabled=1 # mouse: enabled=0, toggle=ctrl+f10 #======================================================================= -mouse: enabled=0 +#mouse: enabled=1 #======================================================================= # PCI: @@ -760,7 +761,7 @@ ata3: enabled=0, ioaddr1=0x168, ioaddr2=0x360, irq=9 # ata3-master: type=disk, mode=flat, path=483M.sample, cylinders=1024, heads=15, spt=63 # ata3-slave: type=cdrom, path=iso.sample, status=inserted #======================================================================= -ata0-master: type=disk, mode=flat, path="HD.IMG" +ata0-master: type=disk, mode=flat, path="HD.IMG", model="Generic aBCd" #ata0-master: type=disk, mode=flat, path="30M.sample" #ata0-master: type=disk, mode=flat, path="30M.sample", cylinders=615, heads=6, spt=17 #ata0-master: type=disk, mode=flat, path="c.img", cylinders=0 # autodetect @@ -1190,6 +1191,9 @@ parport1: enabled=1, file="parport.out" #usb_uhci: port2=cdrom, options2="path:image.iso" #usb_uhci: port1=printer, options1="file:printdata.bin" #usb_uhci: port2=floppy, options2="path:vvfat:diskette, model:teac" +#usb_uhci: enabled=1 +#usb_uhci: port2=disk, options2=""path:uHD.IMG, sect_size:512" + #======================================================================= # USB_OHCI: diff --git a/drivers/ata.c b/drivers/ata.c new file mode 100644 index 0000000..085d7e7 --- /dev/null +++ b/drivers/ata.c @@ -0,0 +1,82 @@ +/* + * ------------------------------------------------------------------------ + * File Name: ata.c + * Author: Zhao Yanbai + * 2021-11-10 13:55:27 Wednesday CST + * Description: none + * ------------------------------------------------------------------------ + */ + +#include +#include +#include +#include + +// 本程序参考文档《AT Attachment with Packet Interface - 6》 + +// https://wiki.osdev.org/ATA_PIO_Mode +// To use the IDENTIFY command, select a target drive by sending 0xA0 for the master drive, or 0xB0 for the slave, +// to the "drive select" IO port. On the Primary bus, this would be port 0x1F6. Then set the Sectorcount, LBAlo, +// LBAmid, and LBAhi IO ports to 0 (port 0x1F2 to 0x1F5). Then send the IDENTIFY command (0xEC) to the Command IO +// port (0x1F7). +// Then read the Status port (0x1F7) again. If the value read is 0, the drive does not exist. For any +// other value: poll the Status port (0x1F7) until bit 7 (BSY, value = 0x80) clears. Because of some ATAPI drives +// that do not follow spec, at this point you need to check the LBAmid and LBAhi ports (0x1F4 and 0x1F5) to see if +// they are non-zero. If so, the drive is not ATA, and you should stop polling. Otherwise, continue polling one of +// the Status ports until bit 3 (DRQ, value = 8) sets, or until bit 0 (ERR, value = 1) sets. At that point, if ERR +// is clear, the data is ready to read from the Data port (0x1F0). Read 256 16-bit values, and store them. +// +// ATAPI的情况暂时不用考虑,因为不是硬盘相关的 +// https://wiki.osdev.org/ATAPI +// ATAPI refers to devices that use the Packet Interface of the ATA6 (or higher) standard command set. It is +// basically a way to issue SCSI commands to a CD-ROM, CD-RW, DVD, or tape drive, attached to the ATA bus. +// +// 总结来说,仅考虑ATA硬盘的情况 +// 一个IDE接口能接Master、Slave两个DRIVE。 +// 一个PC机上通常有两个IDE接口(IDE0, IDE1或ATA0, ATA1),通常称通道0、1 +// 对于同一个IDE通道的两个DRIVE,共享同一组寄存器,它们之间的区分是通过Device寄存器的第4个bit位来实现的。0为Master,1为Slave +// +// 使用IDENTIFY命令步骤: +// 1. 选择DRIVE,发送0xA0选择master,发送0xB0选择slave。(发送 0xE0 | (drive << 4)到Device寄存器) +// 2. 发送0到该DRIVE所在通道的寄存器NSECTOR, LBAL, LBAM, LBAH +// 3. 发送IDENTIFY(0xEC)命令到该通道的命令寄存器 +// 检查status寄存器: +// 1. 若为0,就认为没有IDE +// 2. 等到status的BSY位清除 +// 3. 等到status的DRQ位或ERR位设置 +u16 identify[256]; +void ata_read_identify(int dev) { // 这里所用的dev是逻辑编号 ATA0、ATA1下的Master、Salve的dev分别为0,1,2,3 + outb(0x00 | ((dev & 0x01) << 4), REG_DEVICE(dev)); // 根据文档P113,这里不用指定bit5, bit7,直接指示DRIVE就行 + outb(ATA_CMD_IDENTIFY, REG_CMD(dev)); + while (1) { + u8 status = inb(REG_STATUS(dev)); + printk("hard disk status: %x %x\n", status, REG_STATUS(dev)); + if ((status & ATA_STATUS_BSY) == 0 && (status & ATA_STATUS_DRQ) != 0) { + break; + } + } + + // u16 *identify = (u16 *)kmalloc(ATA_NSECTOR, 0); + insw(REG_DATA(dev), identify, 512 / sizeof(u16)); + + // 第49个word的第8个bit位表示是否支持DMA + // 第83个word的第10个bit位表示是否支持LBA48,为1表示支持。 + // 第100~103个word的八个字节表示user的LBA最大值 + printk("%04x %04x %d %d\n", identify[49], 1 << 8, identify[49] & (1 << 8), (identify[49] & (1 << 8)) != 0); + if ((identify[49] & (1 << 8)) != 0) { + printk("support DMA\n"); + } + + if ((identify[83] & (1 << 10)) != 0) { + printk("support LBA48\n"); + + u64 lba = *(u64 *)(identify + 100); + printk("hard disk size: %u MB\n", (lba * 512) >> 20); + } +} + +unsigned int ATA_CHL0_CMD_BASE = 0x1F0; +unsigned int ATA_CHL1_CMD_BASE = 0x170; + +unsigned int ATA_CHL0_CTL_BASE = 0x3F6; +unsigned int ATA_CHL1_CTL_BASE = 0x376; \ No newline at end of file diff --git a/drivers/ata.h b/drivers/ata.h new file mode 100644 index 0000000..3f9dcac --- /dev/null +++ b/drivers/ata.h @@ -0,0 +1,122 @@ +/* + * ------------------------------------------------------------------------ + * File Name: ata.h + * Author: Zhao Yanbai + * 2021-11-10 13:55:29 Wednesday CST + * Description: none + * ------------------------------------------------------------------------ + */ + +#pragma once + +extern unsigned int ATA_CHL0_CMD_BASE; +extern unsigned int ATA_CHL1_CMD_BASE; + +// CTL其实不用BASE,只有一个寄存器 +// 这么写纯粹是为了代码好看 +// DEVICE CONTROL REGISTER +// bit7: HOB High Order Byte (defined by 48-bit Address feature set). +// bit[3-6]: - +// bit2: SRST Software Reset +// bit1: IEN Interrupt Enable +// bit0: 0 +extern unsigned int ATA_CHL0_CTL_BASE; +extern unsigned int ATA_CHL1_CTL_BASE; + +#define ATA_DATA 0 +#define ATA_FEATURES 1 +#define ATA_ERR 1 +#define ATA_ERR_BB 0x80 +#define ATA_ERR_ECC 0x40 +#define ATA_ERR_ID 0x10 +#define ATA_ERR_AC 0x04 +#define ATA_ERR_TK 0x02 +#define ATA_ERR_DM 0x01 +#define ATA_NSECTOR 2 +#define ATA_LBAL 3 +#define ATA_LBAM 4 +#define ATA_LBAH 5 + +// DEVICE寄存器 +// bit7: 1 +// bit6: L 如果为1,LBA Mode +// bit5: 1 +// bit4: DRIVE +// bit[0, 3] HS 如果L为0就是磁头号Head Number,如果L为1,则为LBA的24-27位 +#define ATA_DEVICE 6 + +#define ATA_CMD 7 + +// bit7: BSY Busy. If BSY==1, no other bits in the register are valid +// bit6: DRDY Drive Ready. +// bit5: DF/SE Device Fault / Stream Error +// bit4: # Command dependent. (formerly DSC bit) +// bit3: DRQ Data Request. (ready to transfer data) +// bit2: - Obsolete +// bit1: - Obsolete +// bit0: ERR +#define ATA_STATUS 7 /* controller status */ +#define ATA_STATUS_BSY 0x80 /* controller busy */ +#define ATA_STATUS_RDY 0x40 /* drive ready */ +#define ATA_STATUS_WF 0x20 /* write fault */ +#define ATA_STATUS_SEEK_CMPT 0x10 /* seek complete */ +#define ATA_STATUS_DRQ 0x08 /* data transfer request */ +#define ATA_STATUS_CRD 0x04 /* correct data */ +#define ATA_STATUS_IDX 0x02 /* index pulse */ +#define ATA_STATUS_ERR 0x01 /* error */ + +#define ATA_CMD_IDLE 0x00 +#define ATA_CMD_RECALIBRATE 0x10 +#define ATA_CMD_READ_PIO 0x20 /* read data */ +#define ATA_CMD_READ_PIO_EXT 0x24 /* read data (LBA-48 bit)*/ +#define ATA_CMD_READ_DMA 0xC8 +#define ATA_CMD_READ_DMA_EXT 0x25 /* read data DMA LBA48 */ +#define ATA_CMD_WRITE_PIO 0x30 +#define ATA_CMD_WRITE_PIO_EXT 0x34 +#define ATA_CMD_WRITE_DMA 0xCA +#define ATA_CMD_WRITE_DMA_EXT 0X35 +#define ATA_CMD_READ_VERIFY 0x40 +#define ATA_CMD_FORMAT 0x50 +#define ATA_CMD_SEEK 0x70 +#define ATA_CMD_DIAG 0x90 +#define ATA_CMD_SPECIFY 0x91 +#define ATA_CMD_IDENTIFY_PACKET 0xA1 +#define ATA_CMD_IDENTIFY 0xEC + +#define ATA_CTL 0 +#define ATA_CTL_HOB 0x80 /* high order byte (LBA-48bit) */ +//#define ATA_CTL_NOECC 0x40 /* disable ecc retry */ +//#define ATA_CTL_EIGHTHEADS 0x08 /* more than 8 heads */ +#define ATA_CTL_SRST 0x04 /* soft reset controller */ +#define ATA_CTL_NIEN 0x02 /* disable interrupts */ + +#define ATA_GET_CHL(dev) (0) /* only support channel 0 */ +#define ATA_GET_DEV(dev) (0) /* only support one hard disk */ + +#define REG_CMD_BASE(dev, offset) (ATA_GET_CHL(dev) ? (ATA_CHL1_CMD_BASE + offset) : (ATA_CHL0_CMD_BASE + offset)) +#define REG_CTL_BASE(dev, offset) (ATA_GET_CHL(dev) ? (ATA_CHL1_CTL_BASE + offset) : (ATA_CHL0_CTL_BASE + offset)) + +#define REG_DATA(dev) REG_CMD_BASE(dev, ATA_DATA) +#define REG_ERR(dev) REG_CMD_BASE(dev, ATA_ERR) +#define REG_NSECTOR(dev) REG_CMD_BASE(dev, ATA_NSECTOR) +#define REG_LBAL(dev) REG_CMD_BASE(dev, ATA_LBAL) +#define REG_LBAM(dev) REG_CMD_BASE(dev, ATA_LBAM) +#define REG_LBAH(dev) REG_CMD_BASE(dev, ATA_LBAH) +#define REG_DEVICE(dev) REG_CMD_BASE(dev, ATA_DEVICE) +#define REG_STATUS(dev) REG_CMD_BASE(dev, ATA_STATUS) +#define REG_FEATURES(dev) REG_CMD_BASE(dev, ATA_FEATURES) + +#define REG_CMD(dev) REG_CMD_BASE(dev, ATA_CMD) +#define REG_CTL(dev) REG_CTL_BASE(dev, ATA_CTL) + +#define ATA_IDENT_DEVTYPE 0 +#define ATA_IDENT_CYLINDERS 2 +#define ATA_IDENT_HEADS 6 +#define ATA_IDENT_SECTORS 12 +#define ATA_IDENT_SERIAL 20 +#define ATA_IDENT_MODEL 54 +#define ATA_IDENT_CAPABILITIES 98 +#define ATA_IDENT_FIELDVALID 106 +#define ATA_IDENT_MAX_LBA 120 +#define ATA_IDENT_COMMANDSETS 164 +#define ATA_IDENT_MAX_LBA_EXT 200 diff --git a/drivers/blk_rw.c b/drivers/blk_rw.c index ce2fc36..0e74909 100644 --- a/drivers/blk_rw.c +++ b/drivers/blk_rw.c @@ -13,20 +13,20 @@ // only support read void blk_rw(dev_t dev, u64_t offset, u32_t size, char *buf) { - assert(DEV_MAJOR(dev) == DEV_MAJOR_HDA); - assert(offset % SECT_SIZE == 0); - assert(size % SECT_SIZE == 0); + // assert(DEV_MAJOR(dev) == DEV_MAJOR_HDA); + // assert(offset % SECT_SIZE == 0); + // assert(size % SECT_SIZE == 0); - const part_t *p = ide_get_part(dev); + // const part_t *p = ide_get_part(dev); - u64_t lba = p->lba_start; - lba += offset / SECT_SIZE; + // u64_t lba = p->lba_start; + // lba += offset / SECT_SIZE; - assert(lba < p->lba_end); + // assert(lba < p->lba_end); - u32_t scnt = size / SECT_SIZE; + // u32_t scnt = size / SECT_SIZE; - printd("%s lba %u scnt %u\n", __func__, (u32_t)lba, scnt); + // printd("%s lba %u scnt %u\n", __func__, (u32_t)lba, scnt); - ide_do_read(lba, scnt, buf); + // ide_do_read(lba, scnt, buf); } diff --git a/drivers/ide.c b/drivers/ide.c index 0e26f7f..4bc985d 100644 --- a/drivers/ide.c +++ b/drivers/ide.c @@ -7,438 +7,554 @@ * ------------------------------------------------------------------------ */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -typedef struct _ide_drv { - pci_device_t *pci; - unsigned long pio_cnt; - unsigned long dma_cnt; - unsigned long irq_cnt; - - unsigned int iobase; - - unsigned int bus_cmd; - unsigned int bus_status; - unsigned int bus_prdt; - - unsigned int read_mode; - - u64_t ext_lba_base; - part_t part[MAX_SUPPORT_PARTITION_CNT]; -} ide_drive_t; - -typedef struct prd { - unsigned int addr; - unsigned int cnt : 16; - unsigned int reserved : 15; - unsigned int eot : 1; -} prd_t; - -typedef struct { - u64_t lba; - u32_t scnt; - u32_t read_scnt; - char *buf; - bool finish; - wait_queue_head_t wait; -} ide_request_t; +// #include +// #include +// #include +// #include +// #include +// #include +// #include +// #include +// #include +// #include +// #include + +// typedef struct _ide_drv { +// pci_device_t *pci; +// unsigned long pio_cnt; +// unsigned long dma_cnt; +// unsigned long irq_cnt; + +// unsigned int iobase; + +// unsigned int bus_cmd; +// unsigned int bus_status; +// unsigned int bus_prdt; + +// unsigned int read_mode; + +// u64_t ext_lba_base; +// part_t part[MAX_SUPPORT_PARTITION_CNT]; +// } ide_drive_t; + +// typedef struct prd { +// unsigned int addr; +// unsigned int cnt : 16; +// unsigned int reserved : 15; +// unsigned int eot : 1; +// } prd_t; + +// typedef struct { +// u64_t lba; +// u32_t scnt; +// u32_t read_scnt; +// char *buf; +// bool finish; +// wait_queue_head_t wait; +// } ide_request_t; typedef void (*ide_intr_func_t)(); void ide_default_intr(); -ide_drive_t drv; -DECLARE_MUTEX(mutex); -ide_request_t ide_request; +// ide_drive_t drv; +// DECLARE_MUTEX(mutex); +// ide_request_t ide_request; ide_intr_func_t ide_intr_func = ide_default_intr; -unsigned char *dma_data = 0; +// unsigned char *dma_data = 0; -unsigned int HD_CHL0_CMD_BASE = 0x1F0; -unsigned int HD_CHL1_CMD_BASE = 0x170; +// unsigned int HD_CHL0_CMD_BASE = 0x1F0; +// unsigned int HD_CHL1_CMD_BASE = 0x170; -unsigned int HD_CHL0_CTL_BASE = 0x3F6; -unsigned int HD_CHL1_CTL_BASE = 0x376; +// unsigned int HD_CHL0_CTL_BASE = 0x3F6; +// unsigned int HD_CHL1_CTL_BASE = 0x376; -void ide_printl() { printl(MPL_IDE, "ide pio cnt %d dma cnt %d irq cnt %d", drv.pio_cnt, drv.dma_cnt, drv.irq_cnt); } +// void ide_printl() { printl(MPL_IDE, "ide pio cnt %d dma cnt %d irq cnt %d", drv.pio_cnt, drv.dma_cnt, drv.irq_cnt); } -void ide_cmd_out(dev_t dev, u32 sect_cnt, u64 sect_nr, u32 cmd) { - drv.pio_cnt++; - drv.read_mode = cmd; +// void ide_cmd_out(dev_t dev, u32 sect_cnt, u64 sect_nr, u32 cmd) { +// drv.pio_cnt++; +// drv.read_mode = cmd; - ide_printl(); +// ide_printl(); - outb(0x00, REG_CTL(dev)); - outb(0x40 | 0x00, REG_DEVSEL(dev)); +// outb(0x00, REG_CTL(dev)); +// outb(0x40 | 0x00, REG_DEVICE(dev)); - outb((u8)((sect_cnt >> 8) & 0xFF), REG_NSECTOR(dev)); // High - outb((u8)((sect_nr >> 24) & 0xFF), REG_LBAL(dev)); - outb((u8)((sect_nr >> 32) & 0xFF), REG_LBAM(dev)); - outb((u8)((sect_nr >> 40) & 0xFF), REG_LBAH(dev)); +// outb((u8)((sect_cnt >> 8) & 0xFF), REG_NSECTOR(dev)); // High +// outb((u8)((sect_nr >> 24) & 0xFF), REG_LBAL(dev)); +// outb((u8)((sect_nr >> 32) & 0xFF), REG_LBAM(dev)); +// outb((u8)((sect_nr >> 40) & 0xFF), REG_LBAH(dev)); - outb((u8)((sect_cnt >> 0) & 0xFF), REG_NSECTOR(dev)); // Low - outb((u8)((sect_nr >> 0) & 0xFF), REG_LBAL(dev)); - outb((u8)((sect_nr >> 8) & 0xFF), REG_LBAM(dev)); - outb((u8)((sect_nr >> 16) & 0xFF), REG_LBAH(dev)); +// outb((u8)((sect_cnt >> 0) & 0xFF), REG_NSECTOR(dev)); // Low +// outb((u8)((sect_nr >> 0) & 0xFF), REG_LBAL(dev)); +// outb((u8)((sect_nr >> 8) & 0xFF), REG_LBAM(dev)); +// outb((u8)((sect_nr >> 16) & 0xFF), REG_LBAH(dev)); - outb(cmd, REG_CMD(dev)); -} - -part_t *ide_get_part(dev_t dev) { - assert(DEV_MAJOR(dev) == DEV_MAJOR_HDA); - assert(DEV_MINOR(dev) < MAX_SUPPORT_PARTITION_CNT); - - return drv.part + DEV_MINOR(dev); -} - -void ide_do_read(u64_t lba, u32_t scnt, char *buf) { - bool finish = false; - unsigned long flags; - - ide_request_t *r = &ide_request; - - down(&mutex); - - r->lba = lba; - r->scnt = scnt; - r->read_scnt = 0; - r->buf = buf; - r->finish = false; - init_wait_queue(&r->wait); - - task_union *task = current; - DECLARE_WAIT_QUEUE(wait, task); - add_wait_queue(&r->wait, &wait); - - ide_cmd_out(0, scnt, lba, HD_CMD_READ_PIO_EXT); - - while (true) { - // printd("%s pid %d is going to wait\n", __func__, sysc_getpid()); - task->state = TASK_WAIT; - irq_save(flags); - finish = r->finish; - // printd("%s pid %d finish %u read_scnt %u scnt %u\n", __func__, sysc_getpid(), r->finish, r->read_scnt, - // r->scnt); - irq_restore(flags); - - if (finish) break; - - schedule(); - // printd("%s pid %d is running\n", __func__, sysc_getpid()); - } - - // printd("%s pid %d is really running\n", __func__, sysc_getpid()); - task->state = TASK_RUNNING; - del_wait_queue(&r->wait, &wait); -} - -unsigned int sys_clock(); - -void ide_pci_init(pci_device_t *pci) { - unsigned int v; - - v = pci_read_config_word(pci_cmd(pci, PCI_COMMAND)); - printk(" ide pci command %04x\n", v); - - v = pci_read_config_byte(pci_cmd(pci, PCI_PROGIF)); - printk(" ide pci program interface %02x\n", v); - - unsigned int iobase = pci_read_config_long(pci_cmd(pci, PCI_BAR4)); - printk(" ide pci Base IO Address Register %08x\n", iobase); - iobase &= 0xFFFC; // 最低为0是内存地址为1是端口地址 - drv.iobase = iobase; - drv.bus_cmd = iobase + PCI_IDE_CMD; - drv.bus_status = iobase + PCI_IDE_STATUS; - drv.bus_prdt = iobase + PCI_IDE_PRDT; - - int i; - printk(" BARS: "); - for (i = 0; i < BARS_CNT; ++i) { - printk("%08x ", pci->bars[i]); - pci->bars[i] &= (~1UL); - } - printk("\n"); - - HD_CHL0_CMD_BASE = pci->bars[0] ? pci->bars[0] : HD_CHL0_CMD_BASE; - HD_CHL0_CTL_BASE = pci->bars[1] ? pci->bars[1] : HD_CHL0_CTL_BASE; - - HD_CHL1_CMD_BASE = pci->bars[2] ? pci->bars[2] : HD_CHL1_CMD_BASE; - HD_CHL1_CTL_BASE = pci->bars[3] ? pci->bars[3] : HD_CHL1_CTL_BASE; - - printk("channel0: cmd %04x ctl %04x channel1: cmd %04x ctl %04x\n", HD_CHL0_CMD_BASE, HD_CHL0_CTL_BASE, - HD_CHL1_CMD_BASE, HD_CHL1_CTL_BASE); - // printl(18, "channel0: cmd %04x ctl %04x channel1: cmd %04x ctl %04x", HD_CHL0_CMD_BASE, HD_CHL0_CTL_BASE, - // HD_CHL1_CMD_BASE, HD_CHL1_CTL_BASE); -} - -void ide_status() { - u8_t idest = inb(REG_STATUS(0)); - u8_t pcist = inb(drv.bus_status); - printk(" ide status %02x pci status %02x\n", idest, pcist); -} +// outb(cmd, REG_CMD(dev)); +// } -void ide_debug() { - unsigned int nsect = 1; - char *buf = kmalloc(1 * SECT_SIZE, 0); - if (buf == 0) panic("out of memory"); +// part_t *ide_get_part(dev_t dev) { +// assert(DEV_MAJOR(dev) == DEV_MAJOR_HDA); +// assert(DEV_MINOR(dev) < MAX_SUPPORT_PARTITION_CNT); - ide_do_read(0, nsect, buf); +// return drv.part + DEV_MINOR(dev); +// } - u16_t sig = *((u16_t *)(buf + 510)); - printk("%s SIG: %04x\n", __func__, sig); +// void ide_do_read(u64_t lba, u32_t scnt, char *buf) { +// bool finish = false; +// unsigned long flags; - kfree(buf); -} - -void init_pci_controller(unsigned int classcode) { - pci_device_t *pci = pci_find_device_by_classcode(classcode); - if (pci != 0 && pci->intr_line < 16) { - printk("found pci vendor %04x device %04x class %04x intr %d\n", pci->vendor, pci->device, pci->classcode, - pci->intr_line); - // printl(17, "found pci vendor %04x device %04x class %04x intr %d", pci->vendor, pci->device, pci->classcode, - // pci->intr_line); - ide_pci_init(pci); - drv.pci = pci; - } -} - -void ide_default_intr() { - // printd("%s\n", __func__); - u8_t status = inb(REG_STATUS(0)); - - drv.irq_cnt++; - - status = inb(drv.bus_status); - if (0 == (status & PCI_IDE_STATUS_INTR)) { - return; - } - - status |= PCI_IDE_STATUS_INTR; - outb(status, drv.bus_status); - outb(0x00, drv.bus_cmd); +// ide_request_t *r = &ide_request; - u16_t sig = 0; - if (drv.read_mode == HD_CMD_READ_PIO_EXT) { - insl(REG_DATA(0), ide_request.buf + ide_request.read_scnt * (SECT_SIZE), (SECT_SIZE) >> 2); - ide_request.read_scnt++; - sig = *((u16_t *)(ide_request.buf + 510)); - } +// down(&mutex); - if (drv.read_mode == HD_CMD_READ_DMA_EXT) { - sig = *((u16_t *)(dma_data + 510)); - } +// r->lba = lba; +// r->scnt = scnt; +// r->read_scnt = 0; +// r->buf = buf; +// r->finish = false; +// init_wait_queue(&r->wait); + +// task_union *task = current; +// DECLARE_WAIT_QUEUE(wait, task); +// add_wait_queue(&r->wait, &wait); - ide_printl(); +// ide_cmd_out(0, scnt, lba, HD_CMD_READ_PIO_EXT); + +// while (true) { +// // printd("%s pid %d is going to wait\n", __func__, sysc_getpid()); +// task->state = TASK_WAIT; +// irq_save(flags); +// finish = r->finish; +// // printd("%s pid %d finish %u read_scnt %u scnt %u\n", __func__, sysc_getpid(), r->finish, r->read_scnt, +// // r->scnt); +// irq_restore(flags); + +// if (finish) break; + +// schedule(); +// // printd("%s pid %d is running\n", __func__, sysc_getpid()); +// } + +// // printd("%s pid %d is really running\n", __func__, sysc_getpid()); +// task->state = TASK_RUNNING; +// del_wait_queue(&r->wait, &wait); +// } + +// unsigned int sys_clock(); - // printd(" hard disk sig %04x read mode %x cnt %d\n", sig, drv.read_mode, drv.irq_cnt); - printl(MPL_IDE_INTR, "hard disk sig %x read mode %x cnt %d", sig, drv.read_mode, drv.irq_cnt); +// void ide_pci_init(pci_device_t *pci) { +// unsigned int v; - outb(PCI_IDE_CMD_STOP, drv.bus_cmd); +// v = pci_read_config_word(pci_cmd(pci, PCI_COMMAND)); +// printk(" ide pci command %04x\n", v); + +// v = pci_read_config_byte(pci_cmd(pci, PCI_PROGIF)); +// printk(" ide pci program interface %02x\n", v); + +// unsigned int iobase = pci_read_config_long(pci_cmd(pci, PCI_BAR4)); +// printk(" ide pci Base IO Address Register %08x\n", iobase); +// iobase &= 0xFFFC; // 最低为0是内存地址为1是端口地址 +// drv.iobase = iobase; +// drv.bus_cmd = iobase + PCI_IDE_CMD; +// drv.bus_status = iobase + PCI_IDE_STATUS; +// drv.bus_prdt = iobase + PCI_IDE_PRDT; - wake_up(&ide_request.wait); - if (drv.read_mode == HD_CMD_READ_PIO_EXT) { - if (ide_request.read_scnt == ide_request.scnt) ide_request.finish = true; - } - - up(&mutex); -} +// int i; +// printk(" BARS: "); +// for (i = 0; i < BARS_CNT; ++i) { +// printk("%08x ", pci->bars[i]); +// pci->bars[i] &= (~1UL); +// } +// printk("\n"); + +// HD_CHL0_CMD_BASE = pci->bars[0] ? pci->bars[0] : HD_CHL0_CMD_BASE; +// HD_CHL0_CTL_BASE = pci->bars[1] ? pci->bars[1] : HD_CHL0_CTL_BASE; + +// HD_CHL1_CMD_BASE = pci->bars[2] ? pci->bars[2] : HD_CHL1_CMD_BASE; +// HD_CHL1_CTL_BASE = pci->bars[3] ? pci->bars[3] : HD_CHL1_CTL_BASE; + +// printk("channel0: cmd %04x ctl %04x channel1: cmd %04x ctl %04x\n", HD_CHL0_CMD_BASE, HD_CHL0_CTL_BASE, +// HD_CHL1_CMD_BASE, HD_CHL1_CTL_BASE); +// // printl(18, "channel0: cmd %04x ctl %04x channel1: cmd %04x ctl %04x", HD_CHL0_CMD_BASE, HD_CHL0_CTL_BASE, +// // HD_CHL1_CMD_BASE, HD_CHL1_CTL_BASE); +// } + +// void ide_status() { +// u8_t idest = inb(REG_STATUS(0)); +// u8_t pcist = inb(drv.bus_status); +// printk(" ide status %02x pci status %02x\n", idest, pcist); +// } + +// void ide_debug() { +// unsigned int nsect = 1; +// char *buf = kmalloc(1 * SECT_SIZE, 0); +// if (buf == 0) panic("out of memory"); + +// ide_do_read(0, nsect, buf); + +// u16_t sig = *((u16_t *)(buf + 510)); +// printk("%s SIG: %04x\n", __func__, sig); + +// kfree(buf); +// } + +// void init_pci_controller(unsigned int classcode) { +// pci_device_t *pci = pci_find_device_by_classcode(classcode); +// if (pci != 0 && pci->intr_line < 16) { +// printk("found pci vendor %04x device %04x class %04x intr %d\n", pci->vendor, pci->device, pci->classcode, +// pci->intr_line); +// // printl(17, "found pci vendor %04x device %04x class %04x intr %d", pci->vendor, pci->device, +// pci->classcode, +// // pci->intr_line); +// ide_pci_init(pci); +// drv.pci = pci; +// } +// } +void ide_default_intr() {} +// void ide_default_intr() { +// // printd("%s\n", __func__); +// u8_t status = inb(REG_STATUS(0)); + +// drv.irq_cnt++; + +// status = inb(drv.bus_status); +// if (0 == (status & PCI_IDE_STATUS_INTR)) { +// return; +// } + +// status |= PCI_IDE_STATUS_INTR; +// outb(status, drv.bus_status); +// outb(0x00, drv.bus_cmd); + +// u16_t sig = 0; +// if (drv.read_mode == HD_CMD_READ_PIO_EXT) { +// insl(REG_DATA(0), ide_request.buf + ide_request.read_scnt * (SECT_SIZE), (SECT_SIZE) >> 2); +// ide_request.read_scnt++; +// sig = *((u16_t *)(ide_request.buf + 510)); +// } + +// if (drv.read_mode == HD_CMD_READ_DMA_EXT) { +// sig = *((u16_t *)(dma_data + 510)); +// } + +// ide_printl(); + +// // printd(" hard disk sig %04x read mode %x cnt %d\n", sig, drv.read_mode, drv.irq_cnt); +// printl(MPL_IDE_INTR, "hard disk sig %x read mode %x cnt %d", sig, drv.read_mode, drv.irq_cnt); + +// outb(PCI_IDE_CMD_STOP, drv.bus_cmd); + +// wake_up(&ide_request.wait); +// if (drv.read_mode == HD_CMD_READ_PIO_EXT) { +// if (ide_request.read_scnt == ide_request.scnt) ide_request.finish = true; +// } + +// up(&mutex); +// } void ide_irq() { ide_intr_func(); } -prd_t prd __attribute__((aligned(64 * 1024))); -unsigned long gprdt = 0; - -#define DELAY400NS \ - { \ - inb(HD_CHL0_CTL_BASE); \ - inb(HD_CHL0_CTL_BASE); \ - inb(HD_CHL0_CTL_BASE); \ - inb(HD_CHL0_CTL_BASE); \ - } - -void ide_dma_pci_lba48() { - drv.dma_cnt++; - drv.read_mode = HD_CMD_READ_DMA_EXT; -#if 1 - memset((void *)&prd, 0, sizeof(prd)); - unsigned long addr = alloc_one_page(0); - dma_data = (char *)addr; - memset(dma_data, 0xBB, 512); - prd.addr = va2pa(addr); - prd.cnt = 512; - prd.eot = 1; - gprdt = va2pa(&prd); - - printl(16, "gprdt %08x &prdt %08x prd.addr %08x addr %08x", gprdt, &prd, prd.addr, addr); - - outb(PCI_IDE_CMD_STOP, drv.bus_cmd); - unsigned short status = inb(drv.bus_status); - outb(status | PCI_IDE_STATUS_INTR | PCI_IDE_STATUS_ERR, drv.bus_status); - outl(gprdt, drv.bus_prdt); - outb(PCI_IDE_CMD_WRITE, drv.bus_cmd); -#endif - -#if 0 - while ( 1 ) - { - status = inb(HD_CHL0_CMD_BASE+HD_STATUS); - printk(" <%02x> ", status); - if((status & (HD_STATUS_BSY | HD_STATUS_DRQ)) == 0) - { - break; - } - } - - outb(0x00, HD_CHL0_CMD_BASE+HD_DEVSEL); - DELAY400NS; - - while ( 1 ) - { - status = inb(HD_CHL0_CMD_BASE+HD_STATUS); - printk(" <%02x> ", status); - if((status & (HD_STATUS_BSY | HD_STATUS_DRQ)) == 0) - { - break; - } - } -#endif - - outb(0x00, HD_CHL0_CTL_BASE); // Device Control - - outb(0x00, HD_CHL0_CMD_BASE + HD_FEATURES); - outb(0x00, HD_CHL0_CMD_BASE + HD_NSECTOR); - outb(0x00, HD_CHL0_CMD_BASE + HD_LBAL); - outb(0x00, HD_CHL0_CMD_BASE + HD_LBAM); - outb(0x00, HD_CHL0_CMD_BASE + HD_LBAH); - - outb(0x00, HD_CHL0_CMD_BASE + HD_FEATURES); - outb(0x01, HD_CHL0_CMD_BASE + HD_NSECTOR); - outb(0x00, HD_CHL0_CMD_BASE + HD_LBAL); - outb(0x00, HD_CHL0_CMD_BASE + HD_LBAM); - outb(0x00, HD_CHL0_CMD_BASE + HD_LBAH); - - outb(0x40, HD_CHL0_CMD_BASE + HD_DEVSEL); - - outb(HD_CMD_READ_DMA_EXT, HD_CHL0_CMD_BASE + HD_CMD); - - inb(drv.bus_cmd); - inb(drv.bus_status); - unsigned short w = inb(drv.bus_cmd); - outb(w | PCI_IDE_CMD_WRITE | PCI_IDE_CMD_START, drv.bus_cmd); - inb(drv.bus_cmd); - inb(drv.bus_status); -} - -typedef struct { - u8_t a; - u8_t b; - u16_t lbah; // lba high - u8_t type; - u8_t f; - u16_t scnth; // sector count high - u32_t lba; // lba low - u32_t scnt; // sector count -} hd_part_t; - -void ide_read_extended_partition(u64_t lba, unsigned int inx) { - if (inx >= MAX_SUPPORT_PARTITION_CNT) return; - - unsigned int i; - char *buf = kmalloc(512, 0); - if (buf == 0) panic("no memory"); - - ide_do_read(lba, 1, buf); - - u16_t sig = *((u16_t *)(buf + 510)); - if (sig != 0xAA55) panic("bad partition sect"); - - hd_part_t *p = (hd_part_t *)(buf + PARTITION_TABLE_OFFSET); - printd("%s:%d lba %d \n", __func__, __LINE__, lba); - - for (i = 0; i < PARTITION_CNT; ++i, ++p) { - if (p->type == 0) continue; - - // u64_t part_lba = lba + (p->lba|((p->lbah*1ULL)<<32)); - // u64_t part_scnt= p->scnt | ((p->scnth*1ULL)<<32); - u64_t part_lba = lba + p->lba; - u64_t part_scnt = p->scnt; - - if (p->type != 0x05) { - drv.part[inx].lba_start = part_lba; - drv.part[inx].lba_end = part_lba + part_scnt; - printk(" logic partition[%02d] [%02x] LBA base %10d end %10d\n", inx, p->type, - (unsigned int)(drv.part[inx].lba_start), (unsigned int)(drv.part[inx].lba_end - 1)); - } else { - part_lba = drv.ext_lba_base + p->lba; - printk(" extended [%02x] LBA base %10d end %10d\n", p->type, (unsigned int)(part_lba), - (unsigned int)(part_lba + part_scnt - 1)); - ide_read_extended_partition(part_lba, inx + 1); - } - } - - kfree(buf); -} - -void ide_read_partition() { - printk("reading partitions....\n"); - unsigned int i; - char *buf = kmalloc(512, 0); - if (buf == 0) panic("no memory"); - - ide_do_read(0, 1, buf); - - u16_t sig = *((u16_t *)(buf + 510)); - if (sig != 0xAA55) panic("bad partition sect"); - - hd_part_t *p = (hd_part_t *)(buf + PARTITION_TABLE_OFFSET); - - unsigned int ext_inx = ~0U; - - for (i = 0; i < PARTITION_CNT; ++i, ++p) { - if (p->type == 0) continue; - - // u64_t part_lba = p->lba|((p->lbah*1ULL)<<32); - // u64_t part_scnt= p->scnt | ((p->scnth*1ULL)<<32); - u64_t part_lba = p->lba; - u64_t part_scnt = p->scnt; - - drv.part[i].lba_start = part_lba; - drv.part[i].lba_end = part_lba + part_scnt; - - if (p->type == 0x05) { - if (drv.ext_lba_base == 0) { - drv.ext_lba_base = drv.part[i].lba_start; - ext_inx = i; - } - } - - printk("primary partition[%02d] [%02x] LBA base %10d end %10d\n", i, p->type, (unsigned int)(part_lba), - (unsigned int)(part_lba + part_scnt - 1)); - } - - kfree(buf); - - if (ext_inx != ~0U) ide_read_extended_partition(drv.part[ext_inx].lba_start, 4); -} - +// prd_t prd __attribute__((aligned(64 * 1024))); +// unsigned long gprdt = 0; + +// #define DELAY400NS \ +// { \ +// inb(HD_CHL0_CTL_BASE); \ +// inb(HD_CHL0_CTL_BASE); \ +// inb(HD_CHL0_CTL_BASE); \ +// inb(HD_CHL0_CTL_BASE); \ +// } + +// void ide_dma_pci_lba48() { +// drv.dma_cnt++; +// drv.read_mode = HD_CMD_READ_DMA_EXT; +// #if 1 +// memset((void *)&prd, 0, sizeof(prd)); +// unsigned long addr = alloc_one_page(0); +// dma_data = (char *)addr; +// memset(dma_data, 0xBB, 512); +// prd.addr = va2pa(addr); +// prd.cnt = 512; +// prd.eot = 1; +// gprdt = va2pa(&prd); + +// printl(16, "gprdt %08x &prdt %08x prd.addr %08x addr %08x", gprdt, &prd, prd.addr, addr); + +// outb(PCI_IDE_CMD_STOP, drv.bus_cmd); +// unsigned short status = inb(drv.bus_status); +// outb(status | PCI_IDE_STATUS_INTR | PCI_IDE_STATUS_ERR, drv.bus_status); +// outl(gprdt, drv.bus_prdt); +// outb(PCI_IDE_CMD_WRITE, drv.bus_cmd); +// #endif + +// #if 0 +// while ( 1 ) +// { +// status = inb(HD_CHL0_CMD_BASE+HD_STATUS); +// printk(" <%02x> ", status); +// if((status & (HD_STATUS_BSY | HD_STATUS_DRQ)) == 0) +// { +// break; +// } +// } + +// outb(0x00, HD_CHL0_CMD_BASE+HD_DEVICE); +// DELAY400NS; + +// while ( 1 ) +// { +// status = inb(HD_CHL0_CMD_BASE+HD_STATUS); +// printk(" <%02x> ", status); +// if((status & (HD_STATUS_BSY | HD_STATUS_DRQ)) == 0) +// { +// break; +// } +// } +// #endif + +// outb(0x00, HD_CHL0_CTL_BASE); // Device Control + +// outb(0x00, HD_CHL0_CMD_BASE + HD_FEATURES); +// outb(0x00, HD_CHL0_CMD_BASE + HD_NSECTOR); +// outb(0x00, HD_CHL0_CMD_BASE + HD_LBAL); +// outb(0x00, HD_CHL0_CMD_BASE + HD_LBAM); +// outb(0x00, HD_CHL0_CMD_BASE + HD_LBAH); + +// outb(0x00, HD_CHL0_CMD_BASE + HD_FEATURES); +// outb(0x01, HD_CHL0_CMD_BASE + HD_NSECTOR); +// outb(0x00, HD_CHL0_CMD_BASE + HD_LBAL); +// outb(0x00, HD_CHL0_CMD_BASE + HD_LBAM); +// outb(0x00, HD_CHL0_CMD_BASE + HD_LBAH); + +// outb(0x40, HD_CHL0_CMD_BASE + HD_DEVICE); + +// outb(HD_CMD_READ_DMA_EXT, HD_CHL0_CMD_BASE + HD_CMD); + +// inb(drv.bus_cmd); +// inb(drv.bus_status); +// unsigned short w = inb(drv.bus_cmd); +// outb(w | PCI_IDE_CMD_WRITE | PCI_IDE_CMD_START, drv.bus_cmd); +// inb(drv.bus_cmd); +// inb(drv.bus_status); +// } + +// typedef struct { +// u8_t a; +// u8_t b; +// u16_t lbah; // lba high +// u8_t type; +// u8_t f; +// u16_t scnth; // sector count high +// u32_t lba; // lba low +// u32_t scnt; // sector count +// } hd_part_t; + +// void ide_read_extended_partition(u64_t lba, unsigned int inx) { +// if (inx >= MAX_SUPPORT_PARTITION_CNT) return; + +// unsigned int i; +// char *buf = kmalloc(512, 0); +// if (buf == 0) panic("no memory"); + +// ide_do_read(lba, 1, buf); + +// u16_t sig = *((u16_t *)(buf + 510)); +// if (sig != 0xAA55) panic("bad partition sect"); + +// hd_part_t *p = (hd_part_t *)(buf + PARTITION_TABLE_OFFSET); +// printd("%s:%d lba %d \n", __func__, __LINE__, lba); + +// for (i = 0; i < PARTITION_CNT; ++i, ++p) { +// if (p->type == 0) continue; + +// // u64_t part_lba = lba + (p->lba|((p->lbah*1ULL)<<32)); +// // u64_t part_scnt= p->scnt | ((p->scnth*1ULL)<<32); +// u64_t part_lba = lba + p->lba; +// u64_t part_scnt = p->scnt; + +// if (p->type != 0x05) { +// drv.part[inx].lba_start = part_lba; +// drv.part[inx].lba_end = part_lba + part_scnt; +// printk(" logic partition[%02d] [%02x] LBA base %10d end %10d\n", inx, p->type, +// (unsigned int)(drv.part[inx].lba_start), (unsigned int)(drv.part[inx].lba_end - 1)); +// } else { +// part_lba = drv.ext_lba_base + p->lba; +// printk(" extended [%02x] LBA base %10d end %10d\n", p->type, (unsigned int)(part_lba), +// (unsigned int)(part_lba + part_scnt - 1)); +// ide_read_extended_partition(part_lba, inx + 1); +// } +// } + +// kfree(buf); +// } + +// void ide_read_partition() { +// printk("reading partitions....\n"); +// unsigned int i; +// char *buf = kmalloc(512, 0); +// if (buf == 0) panic("no memory"); + +// ide_do_read(0, 1, buf); + +// u16_t sig = *((u16_t *)(buf + 510)); +// if (sig != 0xAA55) panic("bad partition sect"); + +// hd_part_t *p = (hd_part_t *)(buf + PARTITION_TABLE_OFFSET); + +// unsigned int ext_inx = ~0U; + +// for (i = 0; i < PARTITION_CNT; ++i, ++p) { +// if (p->type == 0) continue; + +// // u64_t part_lba = p->lba|((p->lbah*1ULL)<<32); +// // u64_t part_scnt= p->scnt | ((p->scnth*1ULL)<<32); +// u64_t part_lba = p->lba; +// u64_t part_scnt = p->scnt; + +// drv.part[i].lba_start = part_lba; +// drv.part[i].lba_end = part_lba + part_scnt; + +// if (p->type == 0x05) { +// if (drv.ext_lba_base == 0) { +// drv.ext_lba_base = drv.part[i].lba_start; +// ext_inx = i; +// } +// } + +// printk("primary partition[%02d] [%02x] LBA base %10d end %10d\n", i, p->type, (unsigned int)(part_lba), +// (unsigned int)(part_lba + part_scnt - 1)); +// } + +// kfree(buf); + +// if (ext_inx != ~0U) ide_read_extended_partition(drv.part[ext_inx].lba_start, 4); +// } + +// u16 ide_identify_buf[256]; + +// static void ata_io_wait() { +// for (int i = 0; i < 128; i++) { +// inb(REG_CTL(0)); +// } +// } + +// // https://wiki.osdev.org/ATA_PIO_Mode +// // To use the IDENTIFY command, select a target drive by sending 0xA0 for the master drive, or 0xB0 for the +// slave, +// // to the "drive select" IO port. On the Primary bus, this would be port 0x1F6. Then set the Sectorcount, LBAlo, +// // LBAmid, and LBAhi IO ports to 0 (port 0x1F2 to 0x1F5). Then send the IDENTIFY command (0xEC) to the Command IO +// // port (0x1F7). +// // Then read the Status port (0x1F7) again. If the value read is 0, the drive does not exist. For any +// // other value: poll the Status port (0x1F7) until bit 7 (BSY, value = 0x80) clears. Because of some ATAPI drives +// // that do not follow spec, at this point you need to check the LBAmid and LBAhi ports (0x1F4 and 0x1F5) to see +// if +// // they are non-zero. If so, the drive is not ATA, and you should stop polling. Otherwise, continue polling one +// of +// // the Status ports until bit 3 (DRQ, value = 8) sets, or until bit 0 (ERR, value = 1) sets. At that point, if +// ERR +// // is clear, the data is ready to read from the Data port (0x1F0). Read 256 16-bit values, and store them. +// // +// // ATAPI的情况暂时不用考虑,因为不是硬盘相关的 +// // https://wiki.osdev.org/ATAPI +// // ATAPI refers to devices that use the Packet Interface of the ATA6 (or higher) standard command set. It is +// // basically a way to issue SCSI commands to a CD-ROM, CD-RW, DVD, or tape drive, attached to the ATA bus. +// // +// // 总结来说,仅考虑ATA硬盘的情况 +// // 一个IDE接口能接Master、Slave两个DRIVE。 +// // 一个PC机上通常有两个IDE接口(IDE0, IDE1或ATA0, ATA1),通常称通道0、1 +// // +// 对于同一个IDE通道的两个DRIVE,共享同一组寄存器,它们之间的区分是通过Device寄存器的第4个bit位来实现的。0为Master,1为Slave +// // +// // 使用IDENTIFY命令步骤: +// // 1. 选择DRIVE,发送0xA0选择master,发送0xB0选择slave。(发送 0xE0 | (drive << 4)到Device寄存器) +// // 2. 发送0到该DRIVE所在通道的寄存器NSECTOR, LBAL, LBAM, LBAH +// // 3. 发送IDENTIFY(0xEC)命令到该通道的命令寄存器 +// // 检查status寄存器: +// // 1. 若为0,就认为没有IDE +// // 2. 等到status的BSY位清除 +// // 3. 等到status的DRQ位或ERR位设置 +// void ide_read_identify() { +// int dev = 0; // 这里所用的dev是逻辑编号 ATA0、ATA1下的Master、Salve的dev分别为0,1,2,3 +// // outb(0xE0 | ((dev & 0x01) << 4), REG_DEVICE(dev)); // 这里可也可以发送(0xA0 | ((dev & 0x0ls1) << 4)) +// outb(0x00 | ((dev & 0x01) << 4), REG_DEVICE(dev)); // 这里可也可以发送(0xA0 | ((dev & 0x01) << 4)) +// outb(0x00, REG_NSECTOR(0)); +// outb(0x00, REG_LBAL(0)); +// outb(0x00, REG_LBAM(0)); +// outb(0x00, REG_LBAH(0)); +// outb(HD_CMD_IDENTIFY, REG_CMD(dev)); +// while (true) { +// u8_t status = inb(REG_STATUS(0)); +// if (status == 0) { +// panic("no hard drive"); +// } +// u8_t error = inb(REG_ERR(0)); +// printk("hd0 status: %x %x %x\n", status, error, REG_STATUS(0)); +// if ((status & HD_STATUS_BSY) == 0 && (status & HD_STATUS_DRQ) != 0) { +// break; +// } +// } + +// insw(REG_DATA(0), ide_identify_buf, 256); + +// // 第83个word(2bytes)的第10个bit位表示是否支持LBA48,为1表示支持。 + +// for (int i = 0; i < 256; i++) { +// if (i % 12 == 0) { +// printk("\n%d ", i); +// } +// printk("%04x ", ide_identify_buf[i]); +// } + +// struct iden_info { +// int idx; +// int len; +// char *desc; +// } infos[] = {{10, 20, "HD SN"}, {17, 8, "Firmware Revision"}, {27, 40, "HD Model"}}; + +// u16 *hdinfo = (u16 *)ide_identify_buf; +// char s[64]; +// for (int i = 0; i < sizeof(infos) / sizeof(infos[0]); i++) { +// char *p = (char *)&hdinfo[infos[i].idx]; +// int j = 0; +// for (j = 0; j < infos[i].len / 2; j++) { +// s[j * 2 + 1] = *p++; +// s[j * 2] = *p++; +// } +// s[j] = 0; +// printk("%s: %s\n", infos[i].desc, s); +// } +// } + +// void ide_detect() { +// // outb(HD_CTL_SRST, REG_CTL(0)); +// outb(0xA0 | 0x00, REG_DEVICE(dev)); +// ata_io_wait(); + +// unsigned cl = inb(REG_LBAM(0)); +// ata_io_wait(); +// unsigned ch = inb(REG_LBAH(0)); +// ata_io_wait(); +// printk("%02x %02x\n", cl, ch); +// } + +void ata_read_identify(int dev); void ide_init() { - memset((void *)&drv, 0, sizeof(drv)); + // memset((void *)&drv, 0, sizeof(drv)); + + // init_pci_controller(0x0106); + // init_pci_controller(0x0101); - init_pci_controller(0x0106); - init_pci_controller(0x0101); + // ide_detect(); + // return; + // ide_read_identify(); + ata_read_identify(0); + return; - ide_read_partition(); + // // 还没开启中断 + // ide_read_partition(); - ide_printl(); + // ide_printl(); } diff --git a/drivers/ide.h b/drivers/ide.h index 4859929..66b4e4e 100644 --- a/drivers/ide.h +++ b/drivers/ide.h @@ -9,124 +9,151 @@ #pragma once -#include - -extern unsigned int HD_CHL0_CMD_BASE; -extern unsigned int HD_CHL1_CMD_BASE; -extern unsigned int HD_CHL0_CTL_BASE; -extern unsigned int HD_CHL1_CTL_BASE; - -#define HD_DATA 0 -#define HD_FEATURES 1 -#define HD_ERR 1 -#define HD_ERR_BB 0x80 -#define HD_ERR_ECC 0x40 -#define HD_ERR_ID 0x10 -#define HD_ERR_AC 0x04 -#define HD_ERR_TK 0x02 -#define HD_ERR_DM 0x01 -#define HD_NSECTOR 2 -#define HD_LBAL 3 -#define HD_LBAM 4 -#define HD_LBAH 5 -#define HD_DEVSEL 6 -#define HD_CMD 7 -#define HD_STATUS 7 /* controller status */ -#define HD_STATUS_BSY 0x80 /* controller busy */ -#define HD_STATUS_RDY 0x40 /* drive ready */ -#define HD_STATUS_WF 0x20 /* write fault */ -#define HD_STATUS_SEEK_CMPT 0x10 /* seek complete */ -#define HD_STATUS_DRQ 0x08 /* data transfer request */ -#define HD_STATUS_CRD 0x04 /* correct data */ -#define HD_STATUS_IDX 0x02 /* index pulse */ -#define HD_STATUS_ERR 0x01 /* error */ - -#define HD_CMD_IDLE 0x00 -#define HD_CMD_RECALIBRATE 0x10 -#define HD_CMD_READ_PIO 0x20 /* read data */ -#define HD_CMD_READ_PIO_EXT 0x24 /* read data (LBA-48 bit)*/ -#define HD_CMD_READ_DMA 0xC8 -#define HD_CMD_READ_DMA_EXT 0x25 /* read data DMA LBA48 */ -#define HD_CMD_WRITE_PIO 0x30 -#define HD_CMD_WRITE_PIO_EXT 0x34 -#define HD_CMD_WRITE_DMA 0xCA -#define HD_CMD_WRITE_DMA_EXT 0X35 -#define HD_CMD_READ_VERIFY 0x40 -#define HD_CMD_FORMAT 0x50 -#define HD_CMD_SEEK 0x70 -#define HD_CMD_DIAG 0x90 -#define HD_CMD_SPECIFY 0x91 -#define HD_CMD_IDENTIFY_PACKET 0xA1 -#define HD_CMD_IDENTIFY 0xEC - -#define HD_CTL 0 -#define HD_CTL_HOB 0x80 /* high order byte (LBA-48bit) */ -//#define HD_CTL_NOECC 0x40 /* disable ecc retry */ -//#define HD_CTL_EIGHTHEADS 0x08 /* more than 8 heads */ -#define HD_CTL_SRST 0x04 /* soft reset controller */ -#define HD_CTL_NIEN 0x02 /* disable interrupts */ - -#define HD_GET_CHL(dev) (0) /* only support channel 0 */ -#define HD_GET_DEV(dev) (0) /* only support one hard disk */ - -#define REG_CMD_BASE(dev, offset) (HD_GET_CHL(dev) ? (HD_CHL1_CMD_BASE + offset) : (HD_CHL0_CMD_BASE + offset)) -#define REG_CTL_BASE(dev, offset) (HD_GET_CHL(dev) ? (HD_CHL1_CTL_BASE + offset) : (HD_CHL0_CTL_BASE + offset)) - -#define REG_DATA(dev) REG_CMD_BASE(dev, HD_DATA) -#define REG_ERR(dev) REG_CMD_BASE(dev, HD_ERR) -#define REG_NSECTOR(dev) REG_CMD_BASE(dev, HD_NSECTOR) -#define REG_LBAL(dev) REG_CMD_BASE(dev, HD_LBAL) -#define REG_LBAM(dev) REG_CMD_BASE(dev, HD_LBAM) -#define REG_LBAH(dev) REG_CMD_BASE(dev, HD_LBAH) -#define REG_DEVSEL(dev) REG_CMD_BASE(dev, HD_DEVSEL) -#define REG_STATUS(dev) REG_CMD_BASE(dev, HD_STATUS) -#define REG_FEATURES(dev) REG_CMD_BASE(dev, HD_FEATURES) -#define REG_CMD(dev) REG_CMD_BASE(dev, HD_CMD) -#define REG_CTL(dev) REG_CTL_BASE(dev, HD_CTL) - -#define SECT_SIZE 512 - -#define hd_rd_data(dev, buf, count) hd_rd_port(REG_DATA(dev), buf, count) - -#define hd_bsy(dev) ((inb(REG_STATUS(dev)) & HD_STATUS_BSY)) -#define hd_rdy(dev) ((inb(REG_STATUS(dev)) & HD_STATUS_RDY)) -#define hd_drq(dev) ((inb(REG_STATUS(dev)) & HD_STATUS_DRQ)) -#define hd_err(dev) ((inb(REG_STATUS(dev)) & HD_STATUS_ERR)) - -#define ATA_IDENT_DEVTYPE 0 -#define ATA_IDENT_CYLINDERS 2 -#define ATA_IDENT_HEADS 6 -#define ATA_IDENT_SECTORS 12 -#define ATA_IDENT_SERIAL 20 -#define ATA_IDENT_MODEL 54 -#define ATA_IDENT_CAPABILITIES 98 -#define ATA_IDENT_FIELDVALID 106 -#define ATA_IDENT_MAX_LBA 120 -#define ATA_IDENT_COMMANDSETS 164 -#define ATA_IDENT_MAX_LBA_EXT 200 - -#define PCI_IDE_CMD 0 -#define PCI_IDE_CMD_STOP 0x00 -#define PCI_IDE_CMD_READ 0x00 -#define PCI_IDE_CMD_START 0x01 -#define PCI_IDE_CMD_WRITE 0x08 -#define PCI_IDE_STATUS 2 -#define PCI_IDE_STATUS_ACT 0x01 -#define PCI_IDE_STATUS_ERR 0x02 -#define PCI_IDE_STATUS_INTR 0x04 -#define PCI_IDE_STATUS_DRV0 0x20 -#define PCI_IDE_STATUS_DRV1 0x40 -#define PCI_IDE_STATUS_SIMPLEX 0x80 -#define PCI_IDE_PRDT 4 - -#define PARTITION_CNT 4 -#define PARTITION_TABLE_OFFSET 0x1BE -#define MAX_SUPPORT_PARTITION_CNT 16 - -typedef struct { - u64_t lba_start; - u64_t lba_end; -} part_t; - -void ide_do_read(u64_t lba, u32_t scnt, char *buf); -part_t *ide_get_part(dev_t dev); +// #include + +// extern unsigned int HD_CHL0_CMD_BASE; +// extern unsigned int HD_CHL1_CMD_BASE; + +// // CTL其实不用BASE,只有一个寄存器 +// // 这么写纯粹是为了代码好看 +// // DEVICE CONTROL REGISTER +// // bit7: HOB High Order Byte (defined by 48-bit Address feature set). +// // bit[3-6]: - +// // bit2: SRST Software Reset +// // bit1: IEN Interrupt Enable +// // bit0: 0 +// extern unsigned int HD_CHL0_CTL_BASE; +// extern unsigned int HD_CHL1_CTL_BASE; + +// #define HD_DATA 0 +// #define HD_FEATURES 1 +// #define HD_ERR 1 +// #define HD_ERR_BB 0x80 +// #define HD_ERR_ECC 0x40 +// #define HD_ERR_ID 0x10 +// #define HD_ERR_AC 0x04 +// #define HD_ERR_TK 0x02 +// #define HD_ERR_DM 0x01 +// #define HD_NSECTOR 2 +// #define HD_LBAL 3 +// #define HD_LBAM 4 +// #define HD_LBAH 5 + +// // DEVICE寄存器 +// // bit7: 1 +// // bit6: L 如果为1,LBA Mode +// // bit5: 1 +// // bit4: DRIVE +// // bit[0, 3] HS 如果L为0就是磁头号Head Number,如果L为1,则为LBA的24-27位 +// #define HD_DEVICE 6 + +// #define HD_CMD 7 + +// // bit7: BSY Busy. If BSY==1, no other bits in the register are valid +// // bit6: DRDY Drive Ready. +// // bit5: DF/SE Device Fault / Stream Error +// // bit4: # Command dependent. (formerly DSC bit) +// // bit3: DRQ Data Request. (ready to transfer data) +// // bit2: - Obsolete +// // bit1: - Obsolete +// // bit0: ERR +// #define HD_STATUS 7 /* controller status */ +// #define HD_STATUS_BSY 0x80 /* controller busy */ +// #define HD_STATUS_RDY 0x40 /* drive ready */ +// #define HD_STATUS_WF 0x20 /* write fault */ +// #define HD_STATUS_SEEK_CMPT 0x10 /* seek complete */ +// #define HD_STATUS_DRQ 0x08 /* data transfer request */ +// #define HD_STATUS_CRD 0x04 /* correct data */ +// #define HD_STATUS_IDX 0x02 /* index pulse */ +// #define HD_STATUS_ERR 0x01 /* error */ + +// #define HD_CMD_IDLE 0x00 +// #define HD_CMD_RECALIBRATE 0x10 +// #define HD_CMD_READ_PIO 0x20 /* read data */ +// #define HD_CMD_READ_PIO_EXT 0x24 /* read data (LBA-48 bit)*/ +// #define HD_CMD_READ_DMA 0xC8 +// #define HD_CMD_READ_DMA_EXT 0x25 /* read data DMA LBA48 */ +// #define HD_CMD_WRITE_PIO 0x30 +// #define HD_CMD_WRITE_PIO_EXT 0x34 +// #define HD_CMD_WRITE_DMA 0xCA +// #define HD_CMD_WRITE_DMA_EXT 0X35 +// #define HD_CMD_READ_VERIFY 0x40 +// #define HD_CMD_FORMAT 0x50 +// #define HD_CMD_SEEK 0x70 +// #define HD_CMD_DIAG 0x90 +// #define HD_CMD_SPECIFY 0x91 +// #define HD_CMD_IDENTIFY_PACKET 0xA1 +// #define HD_CMD_IDENTIFY 0xEC + +// #define HD_CTL 0 +// #define HD_CTL_HOB 0x80 /* high order byte (LBA-48bit) */ +// //#define HD_CTL_NOECC 0x40 /* disable ecc retry */ +// //#define HD_CTL_EIGHTHEADS 0x08 /* more than 8 heads */ +// #define HD_CTL_SRST 0x04 /* soft reset controller */ +// #define HD_CTL_NIEN 0x02 /* disable interrupts */ + +// #define HD_GET_CHL(dev) (0) /* only support channel 0 */ +// #define HD_GET_DEV(dev) (0) /* only support one hard disk */ + +// #define REG_CMD_BASE(dev, offset) (HD_GET_CHL(dev) ? (HD_CHL1_CMD_BASE + offset) : (HD_CHL0_CMD_BASE + offset)) +// #define REG_CTL_BASE(dev, offset) (HD_GET_CHL(dev) ? (HD_CHL1_CTL_BASE + offset) : (HD_CHL0_CTL_BASE + offset)) + +// #define REG_DATA(dev) REG_CMD_BASE(dev, HD_DATA) +// #define REG_ERR(dev) REG_CMD_BASE(dev, HD_ERR) +// #define REG_NSECTOR(dev) REG_CMD_BASE(dev, HD_NSECTOR) +// #define REG_LBAL(dev) REG_CMD_BASE(dev, HD_LBAL) +// #define REG_LBAM(dev) REG_CMD_BASE(dev, HD_LBAM) +// #define REG_LBAH(dev) REG_CMD_BASE(dev, HD_LBAH) +// #define REG_DEVICE(dev) REG_CMD_BASE(dev, HD_DEVICE) +// #define REG_STATUS(dev) REG_CMD_BASE(dev, HD_STATUS) +// #define REG_FEATURES(dev) REG_CMD_BASE(dev, HD_FEATURES) + +// #define REG_CMD(dev) REG_CMD_BASE(dev, HD_CMD) +// #define REG_CTL(dev) REG_CTL_BASE(dev, HD_CTL) + +// #define SECT_SIZE 512 + +// #define hd_rd_data(dev, buf, count) hd_rd_port(REG_DATA(dev), buf, count) + +// #define hd_bsy(dev) ((inb(REG_STATUS(dev)) & HD_STATUS_BSY)) +// #define hd_rdy(dev) ((inb(REG_STATUS(dev)) & HD_STATUS_RDY)) +// #define hd_drq(dev) ((inb(REG_STATUS(dev)) & HD_STATUS_DRQ)) +// #define hd_err(dev) ((inb(REG_STATUS(dev)) & HD_STATUS_ERR)) + +// #define ATA_IDENT_DEVTYPE 0 +// #define ATA_IDENT_CYLINDERS 2 +// #define ATA_IDENT_HEADS 6 +// #define ATA_IDENT_SECTORS 12 +// #define ATA_IDENT_SERIAL 20 +// #define ATA_IDENT_MODEL 54 +// #define ATA_IDENT_CAPABILITIES 98 +// #define ATA_IDENT_FIELDVALID 106 +// #define ATA_IDENT_MAX_LBA 120 +// #define ATA_IDENT_COMMANDSETS 164 +// #define ATA_IDENT_MAX_LBA_EXT 200 + +// #define PCI_IDE_CMD 0 +// #define PCI_IDE_CMD_STOP 0x00 +// #define PCI_IDE_CMD_READ 0x00 +// #define PCI_IDE_CMD_START 0x01 +// #define PCI_IDE_CMD_WRITE 0x08 +// #define PCI_IDE_STATUS 2 +// #define PCI_IDE_STATUS_ACT 0x01 +// #define PCI_IDE_STATUS_ERR 0x02 +// #define PCI_IDE_STATUS_INTR 0x04 +// #define PCI_IDE_STATUS_DRV0 0x20 +// #define PCI_IDE_STATUS_DRV1 0x40 +// #define PCI_IDE_STATUS_SIMPLEX 0x80 +// #define PCI_IDE_PRDT 4 + +// #define PARTITION_CNT 4 +// #define PARTITION_TABLE_OFFSET 0x1BE +// #define MAX_SUPPORT_PARTITION_CNT 16 + +// typedef struct { +// u64_t lba_start; +// u64_t lba_end; +// } part_t; + +// void ide_do_read(u64_t lba, u32_t scnt, char *buf); +// part_t *ide_get_part(dev_t dev); diff --git a/drivers/keyboard.c b/drivers/keyboard.c index 098502c..56b368c 100644 --- a/drivers/keyboard.c +++ b/drivers/keyboard.c @@ -29,7 +29,7 @@ void ide_status(); void debug_sched(); void vga_dbg_toggle(); int debug_wait_queue_put(unsigned int v); -void ide_dma_pci_lba48(); +// void ide_dma_pci_lba48(); void vga_switch(unsigned int nr); void kbd_debug(unsigned char scan_code); @@ -99,10 +99,10 @@ void kbd_debug(unsigned char scan_code) { if (scan_code == 0x42) // F8 debug_wait_queue_put(7); - if (scan_code == 0x43) // F9 - ide_dma_pci_lba48(); - if (scan_code == 0x44) // F10 - ide_debug(); + // if (scan_code == 0x43) // F9 + // ide_dma_pci_lba48(); + // if (scan_code == 0x44) // F10 + // ide_debug(); if (scan_code == 0x57) // F11 { asm("cli;"); diff --git a/kernel/pci.c b/kernel/pci.c index 81c4a65..5ade796 100644 --- a/kernel/pci.c +++ b/kernel/pci.c @@ -59,13 +59,15 @@ void scan_pci_bus(int bus) { u32 cmd; u32 v; int i; - printk("scanning pci bus %d\n", bus); + // printk("scanning pci bus %d\n", bus); for (dev = 0; dev < 32; dev++) { for (devfn = 0; devfn < 8; devfn++) { cmd = PCI_CMD(bus, dev, devfn, PCI_VENDORID); v = pci_read_config_word(cmd); - if (v == 0xFFFF) continue; + if (v == 0xFFFF) { + continue; + } pci_device_t *pci = kmalloc(sizeof(pci_device_t), 0); if (0 == pci) { @@ -167,10 +169,10 @@ void dump_pci_dev() { break; } #else - for (int bar_inx = 0; bar_inx < BARS_CNT; bar_inx++) { - printk("%08x ", pci->bars[bar_inx]); - } - printk("\n"); + // for (int bar_inx = 0; bar_inx < BARS_CNT; bar_inx++) { + // printk("%08x ", pci->bars[bar_inx]); + // } + // printk("\n"); #endif } } diff --git a/kernel/setup.c b/kernel/setup.c index 8a9d81d..1c72a35 100644 --- a/kernel/setup.c +++ b/kernel/setup.c @@ -84,6 +84,9 @@ void setup_kernel() { setup_irqs(); setup_pci(); + + void ide_init(); + ide_init(); asm("cli;hlt;"); extern tty_t monitor_tty; // tty_switch(&monitor_tty); @@ -97,8 +100,6 @@ void setup_kernel() { // switch_printk_screen(); system_delay(); - void ide_init(); - ide_init(); system_delay();