CFLAGS = -g -c -fno-builtin -m32 -DBUILDER='"$(shell whoami)"'
+CFLAGS += -DNR_TTYS=3
CFLAGS += -DFIX_SYSENTER_ESP_MODE=1
#CFLAGS += -DENABLE_BOOT_WAIT=1
SYSTEMMAP = System.map
#include <string.h>
#include <system.h>
-extern ide_pci_controller_t ide_pci_controller;
+extern ide_pci_controller_t ide_pci_controller[];
-typedef struct _ide_drive {
- int present;
- int dma;
- uint64_t lba48;
- uint64_t max_lba;
-} ide_drive_t;
-
-#define MAX_IDE_DRIVE_CNT 4
ide_drive_t ide_drives[MAX_IDE_DRIVE_CNT];
#define ATA_TIMEOUT 10 // 10次时钟中断
-void ata_dma_read_ext(int dev, uint64_t pos, uint16_t count, void *dest);
-int ata_pio_read_ext(int dev, uint64_t pos, uint16_t count, int timeout, void *dest);
+void ata_dma_read_ext(int drv, uint64_t pos, uint16_t count, void *dest);
+int ata_pio_read_ext(int drv, uint64_t pos, uint16_t count, int timeout, void *dest);
void *mbr_buf;
void ata_test(uint64_t nr) {
// 2. 等到status的BSY位清除
// 3. 等到status的DRQ位或ERR位设置
u16 identify[256];
-void ata_send_read_identify_cmd(int dev) {}
+void ata_send_read_identify_cmd(int drv) {}
-void ata_read_data(int dev, int sect_cnt, void *dst) { insl(REG_DATA(dev), dst, (512 * sect_cnt) / sizeof(uint32_t)); }
+void ata_read_data(int drv, int sect_cnt, void *dst) { insl(REG_DATA(drv), dst, (512 * sect_cnt) / sizeof(uint32_t)); }
-// 这里所用的dev是逻辑编号 ATA0、ATA1下的Master、Salve的dev分别为0,1,2,3
-void ata_read_identify(int dev, int disable_intr) {
+// 这里所用的drv是逻辑编号 ATA0、ATA1下的Master、Salve的drv分别为0,1,2,3
+void ata_read_identify(int drv, int disable_intr) {
uint8_t ctlv = 0x00;
if (disable_intr != 0) {
ctlv |= ATA_CTL_NIEN;
}
- outb(ctlv, REG_CTL(dev));
- outb(0x00 | ((dev & 0x01) << 4), REG_DEVICE(dev)); // 根据文档P113,这里不用指定bit5, bit7,直接指示DRIVE就行
- outb(ATA_CMD_IDENTIFY, REG_CMD(dev));
+ outb(ctlv, REG_CTL(drv));
+ outb(0x00 | ((drv & 0x01) << 4), REG_DEVICE(drv)); // 根据文档P113,这里不用指定bit5, bit7,直接指示DRIVE就行
+ outb(ATA_CMD_IDENTIFY, REG_CMD(drv));
}
void ata_read_identity_string(const uint16_t *identify, int bgn, int end, char *buf) {
// 《AT Attachment 8 - ATA/ATAPI Command Set》
void ide_ata_init() {
for (int i = 0; i < MAX_IDE_DRIVE_CNT; i++) {
- int dev = i;
+ int drv_no = i;
memset(ide_drives + i, 0, sizeof(ide_drive_t));
+ ide_drive_t *drv = ide_drives + drv_no;
+
+ INIT_MUTEX(&drv->request_mutex);
+
+ drv->request_queue.count = 0;
+ INIT_LIST_HEAD(&drv->request_queue.list);
+ semaphore_init(&drv->request_queue.sem, 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,
// 2. 等到status的BSY位清除
// 3. 等到status的DRQ位或ERR位设置
- ata_read_identify(dev, 1);
+ ata_read_identify(drv_no, 1);
- uint8_t status = inb(REG_STATUS(dev));
+ uint8_t status = inb(REG_STATUS(drv_no));
if (status == 0 || (status & ATA_STATUS_ERR) || (status & ATA_STATUS_RDY == 0)) {
ide_drives[i].present = 0;
continue;
}
printk("ata[%d] status %x %s exists\n", i, status, ide_drives[i].present == 1 ? "" : "not");
- insl(REG_DATA(dev), identify, SECT_SIZE / sizeof(uint32_t));
+ insl(REG_DATA(drv_no), identify, SECT_SIZE / sizeof(uint32_t));
// 第49个word的第8个bit位表示是否支持DMA
// 第83个word的第10个bit位表示是否支持LBA48,为1表示支持。
}
}
+#if 0
void ata_init() {
// 初始化hard_disk与中断函数之间的信号量
disk_request_t r;
- r.dev = 0;
+ r.drv = 0;
r.buf = (void *)identify;
r.count = 1;
r.pos = 0;
printd("%04x.", p[i]);
}
}
+#endif
// ATA_CMD_READ_DMA_EXT
-void ata_dma_read_ext(int dev, uint64_t pos, uint16_t count, void *dest) {
+void ata_dma_read_ext(int drv, uint64_t pos, uint16_t count, void *dest) {
// Intel®
// 82801CA (ICH3), 82801BA
// (ICH2), 82801AA (ICH), and 82801AB
// by writing a 0 to this bit. This results in all state information being lost (i.e., master mode
// operation cannot be stopped and then resumed).
+ int channel = (drv >> 1) & 0x01;
+ assert(channel == 0 || channel == 1);
+ ide_pci_controller_t *pci = ide_pci_controller + channel;
+
// 停止DMA
- outb(PCI_IDE_CMD_STOP, ide_pci_controller.bus_cmd);
+ outb(PCI_IDE_CMD_STOP, pci->bus_cmd);
// 配置描述符表
unsigned long dest_paddr = va2pa(dest);
const uint32_t _64K = 1 << 16;
assert(((dest_paddr + size) & _64K) == (dest_paddr & _64K));
- ide_pci_controller.prdt[0].phys_addr = dest_paddr;
- ide_pci_controller.prdt[0].byte_count = size;
- ide_pci_controller.prdt[0].reserved = 0;
- ide_pci_controller.prdt[0].eot = 1;
- outl(va2pa(ide_pci_controller.prdt), ide_pci_controller.bus_prdt);
+ pci->prdt[0].phys_addr = dest_paddr;
+ pci->prdt[0].byte_count = size;
+ pci->prdt[0].reserved = 0;
+ pci->prdt[0].eot = 1;
+ outl(va2pa(pci->prdt), pci->bus_prdt);
- // printk("paddr: %x prdt: %x %x prdte %x %x\n", dest_paddr, ide_pci_controller.prdt,
- // va2pa(ide_pci_controller.prdt),
- // ide_pci_controller.prdt[0].phys_addr, *(((unsigned int *)ide_pci_controller.prdt) + 1));
+ // printk("paddr: %x prdt: %x %x prdte %x %x\n", dest_paddr, pci->prdt,
+ // va2pa(pci->prdt),
+ // pci->prdt[0].phys_addr, *(((unsigned int *)pci->prdt) + 1));
// 清除中断位和错误位
// 这里清除的方式是是设置1后清除
- outb(PCI_IDE_STATUS_INTR | PCI_IDE_STATUS_ERR, ide_pci_controller.bus_status);
+ outb(PCI_IDE_STATUS_INTR | PCI_IDE_STATUS_ERR, pci->bus_status);
// 不再设置nIEN,DMA需要中断
- outb(0x00, REG_CTL(dev));
+ outb(0x00, REG_CTL(drv));
// 等待硬盘不BUSY
- while (inb(REG_STATUS(dev)) & ATA_STATUS_BSY) {
+ while (inb(REG_STATUS(drv)) & ATA_STATUS_BSY) {
nop();
}
// 选择DRIVE
- outb(ATA_LBA48_DEVSEL(dev), REG_DEVICE(dev));
+ outb(ATA_LBA48_DEVSEL(drv), REG_DEVICE(drv));
// 先写扇区数的高字节
- outb((count >> 8) & 0xFF, REG_NSECTOR(dev));
+ outb((count >> 8) & 0xFF, REG_NSECTOR(drv));
// 接着写LBA48,高三个字节
- outb((pos >> 24) & 0xFF, REG_LBAL(dev));
- outb((pos >> 32) & 0xFF, REG_LBAM(dev));
- outb((pos >> 40) & 0xFF, REG_LBAH(dev));
+ outb((pos >> 24) & 0xFF, REG_LBAL(drv));
+ outb((pos >> 32) & 0xFF, REG_LBAM(drv));
+ outb((pos >> 40) & 0xFF, REG_LBAH(drv));
// 再写扇区数的低字节
- outb((count >> 0) & 0xFF, REG_NSECTOR(dev));
+ outb((count >> 0) & 0xFF, REG_NSECTOR(drv));
// 接着写LBA48,低三个字节
- outb((pos >> 0) & 0xFF, REG_LBAL(dev));
- outb((pos >> 8) & 0xFF, REG_LBAM(dev));
- outb((pos >> 16) & 0xFF, REG_LBAH(dev));
+ outb((pos >> 0) & 0xFF, REG_LBAL(drv));
+ outb((pos >> 8) & 0xFF, REG_LBAM(drv));
+ outb((pos >> 16) & 0xFF, REG_LBAH(drv));
// 等待硬盘READY
- while (inb(REG_STATUS(dev)) & ATA_STATUS_RDY == 0) {
+ while (inb(REG_STATUS(drv)) & ATA_STATUS_RDY == 0) {
nop();
}
- outb(ATA_CMD_READ_DMA_EXT, REG_CMD(dev));
+ outb(ATA_CMD_READ_DMA_EXT, REG_CMD(drv));
// 这一句非常重要,如果不加这一句
// 在qemu中用DMA的方式读数据就会读不到数据,而只触是发中断,然后寄存器(Bus Master IDE Status
// Register)的值会一直是5 也就是INTERRUPT和和ACTIVE位是1,正常应该是4,也就是只有INTERRUPT位为1
// 在bochs中则加不加这一句不会有影响,都能正常读到数据
- unsigned int v = pci_read_config_word(pci_cmd(ide_pci_controller.pci, PCI_COMMAND));
+ unsigned int v = pci_read_config_word(pci_cmd(pci->pci, PCI_COMMAND));
// printk(" ide pci command %04x\n", v);
- pci_write_config_word(v | PCI_COMMAND_MASTER, pci_cmd(ide_pci_controller.pci, PCI_COMMAND));
+ pci_write_config_word(v | PCI_COMMAND_MASTER, pci_cmd(pci->pci, PCI_COMMAND));
+ // pci_write_config_word(v, pci_cmd(pci->pci, PCI_COMMAND));
// 指定DMA操作为读取硬盘操作,内核用DMA读取,对硬盘而言是写出
// 并设置DMA的开始位,开始DMA
- outb(PCI_IDE_CMD_WRITE | PCI_IDE_CMD_START, ide_pci_controller.bus_cmd);
+ outb(PCI_IDE_CMD_WRITE | PCI_IDE_CMD_START, pci->bus_cmd);
}
// TODO
-int ata_dma_stop() {
- uint8_t x = inb(ide_pci_controller.bus_cmd);
+int ata_dma_stop(int channel) {
+ ide_pci_controller_t *pci = ide_pci_controller + channel;
+
+ uint8_t x = inb(pci->bus_cmd);
x &= ~PCI_IDE_CMD_START;
- outb(x, ide_pci_controller.bus_cmd);
+ outb(x, pci->bus_cmd);
- uint8_t status = inb(ide_pci_controller.bus_status);
- outb(status | PCI_IDE_STATUS_INTR | PCI_IDE_STATUS_ERR, ide_pci_controller.bus_status);
+ uint8_t status = inb(pci->bus_status);
+ outb(status | PCI_IDE_STATUS_INTR | PCI_IDE_STATUS_ERR, pci->bus_status);
// TODO
if (status & PCI_IDE_STATUS_ERR) {
}
// ATA_CMD_READ_PIO_EXT
-int ata_pio_read_ext(int dev, uint64_t pos, uint16_t count, int timeout, void *dest) {
+int ata_pio_read_ext(int drv, uint64_t pos, uint16_t count, int timeout, void *dest) {
// PIO读,禁用中断
- outb(ATA_CTL_NIEN, REG_CTL(dev));
+ outb(ATA_CTL_NIEN, REG_CTL(drv));
// 等待硬盘不BUSY
- while (inb(REG_STATUS(dev)) & ATA_STATUS_BSY) {
+ while (inb(REG_STATUS(drv)) & ATA_STATUS_BSY) {
nop();
}
// 选择DRIVE
- outb(ATA_LBA48_DEVSEL(dev), REG_DEVICE(dev));
+ outb(ATA_LBA48_DEVSEL(drv), REG_DEVICE(drv));
// 先写扇区数的高字节
- outb((count >> 8) & 0xFF, REG_NSECTOR(dev));
+ outb((count >> 8) & 0xFF, REG_NSECTOR(drv));
// 接着写LBA48,高三个字节q
- outb((pos >> 24) & 0xFF, REG_LBAL(dev));
- outb((pos >> 32) & 0xFF, REG_LBAM(dev));
- outb((pos >> 40) & 0xFF, REG_LBAH(dev));
+ outb((pos >> 24) & 0xFF, REG_LBAL(drv));
+ outb((pos >> 32) & 0xFF, REG_LBAM(drv));
+ outb((pos >> 40) & 0xFF, REG_LBAH(drv));
// 再写扇区数的低字节
- outb((count >> 0) & 0xFF, REG_NSECTOR(dev));
+ outb((count >> 0) & 0xFF, REG_NSECTOR(drv));
// 接着写LBA48,低三个字节
- outb((pos >> 0) & 0xFF, REG_LBAL(dev));
- outb((pos >> 8) & 0xFF, REG_LBAM(dev));
- outb((pos >> 16) & 0xFF, REG_LBAH(dev));
+ outb((pos >> 0) & 0xFF, REG_LBAL(drv));
+ outb((pos >> 8) & 0xFF, REG_LBAM(drv));
+ outb((pos >> 16) & 0xFF, REG_LBAH(drv));
- while (inb(REG_STATUS(dev)) & ATA_STATUS_RDY == 0) {
+ while (inb(REG_STATUS(drv)) & ATA_STATUS_RDY == 0) {
nop();
}
- outb(ATA_CMD_READ_PIO_EXT, REG_CMD(dev));
+ outb(ATA_CMD_READ_PIO_EXT, REG_CMD(drv));
while (timeout > 0) {
timeout--;
- u8 status = inb(REG_STATUS(dev));
+ u8 status = inb(REG_STATUS(drv));
if ((status & ATA_STATUS_BSY) == 0 && (status & ATA_STATUS_DRQ) != 0) {
break;
}
return -1;
}
- insl(REG_DATA(dev), dest, (SECT_SIZE * count) / sizeof(uint32_t));
+ insl(REG_DATA(drv), dest, (SECT_SIZE * count) / sizeof(uint32_t));
return 0;
}
-uint8_t ata_pci_bus_status() {
- uint8_t st = 0;
- st = inb(ide_pci_controller.bus_status);
-
- outb(PCI_IDE_STATUS_INTR, ide_pci_controller.bus_status);
-
- return st;
-}
+// uint8_t ata_pci_bus_status() {
+// uint8_t st = 0;
+// st = inb(ide_pci_controller.bus_status);
-unsigned int ATA_CHL0_CMD_BASE = 0x1F0;
-unsigned int ATA_CHL1_CMD_BASE = 0x170;
+// outb(PCI_IDE_STATUS_INTR, ide_pci_controller.bus_status);
-unsigned int ATA_CHL0_CTL_BASE = 0x3F6;
-unsigned int ATA_CHL1_CTL_BASE = 0x376;
+// return st;
+// }
#pragma once
-extern unsigned int ATA_CHL0_CMD_BASE;
-extern unsigned int ATA_CHL1_CMD_BASE;
+extern unsigned int IDE_CHL0_CMD_BASE;
+extern unsigned int IDE_CHL1_CMD_BASE;
// CTL其实不用BASE,只有一个寄存器
// 这么写纯粹是为了代码好看
// bit2: SRST Software Reset
// bit1: IEN disable Interrupt
// bit0: 0
-extern unsigned int ATA_CHL0_CTL_BASE;
-extern unsigned int ATA_CHL1_CTL_BASE;
+extern unsigned int IDE_CHL0_CTL_BASE;
+extern unsigned int IDE_CHL1_CTL_BASE;
#define ATA_DATA 0
// bit5: Obsolete
// bit4: DRIVE
// bit[0, 3] HS 如果L为0就是磁头号Head Number,如果L为1,则为LBA的24-27位
-#define ATA_LBA48_DEVSEL(dev) (0x40 | ((dev & 0x01) << 4))
+#define ATA_LBA48_DEVSEL(drv) (0x40 | ((drv & 0x01) << 4))
#define ATA_DEVICE 6
#define ATA_CMD 7
#define ATA_CTL_SRST 0x04 /* soft reset controller */
#define ATA_CTL_NIEN 0x02 /* disable interrupts */
-#define ATA_GET_CHL(dev) (((dev) >> 1) & 0x01)
-#define ATA_GET_DEV(dev) (((dev) >> 1) & 0x01)
+#define ATA_GET_CHL(drv) (((drv) >> 1) & 0x01)
+#define ATA_GET_DEV(drv) (((drv) >> 1) & 0x01)
-#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_CMD_BASE(drv, offset) (ATA_GET_CHL(drv) ? (IDE_CHL1_CMD_BASE + offset) : (IDE_CHL0_CMD_BASE + offset))
+#define REG_CTL_BASE(drv, offset) (ATA_GET_CHL(drv) ? (IDE_CHL1_CTL_BASE + offset) : (IDE_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_DATA(drv) REG_CMD_BASE(drv, ATA_DATA)
+#define REG_ERR(drv) REG_CMD_BASE(drv, ATA_ERR)
+#define REG_NSECTOR(drv) REG_CMD_BASE(drv, ATA_NSECTOR)
+#define REG_LBAL(drv) REG_CMD_BASE(drv, ATA_LBAL)
+#define REG_LBAM(drv) REG_CMD_BASE(drv, ATA_LBAM)
+#define REG_LBAH(drv) REG_CMD_BASE(drv, ATA_LBAH)
+#define REG_DEVICE(drv) REG_CMD_BASE(drv, ATA_DEVICE)
+#define REG_STATUS(drv) REG_CMD_BASE(drv, ATA_STATUS)
+#define REG_FEATURES(drv) REG_CMD_BASE(drv, ATA_FEATURES)
-#define REG_CMD(dev) REG_CMD_BASE(dev, ATA_CMD)
-#define REG_CTL(dev) REG_CTL_BASE(dev, ATA_CTL)
+#define REG_CMD(drv) REG_CMD_BASE(drv, ATA_CMD)
+#define REG_CTL(drv) REG_CTL_BASE(drv, ATA_CTL)
#define ATA_IDENT_DEVTYPE 0
#define ATA_IDENT_CYLINDERS 2
#include <task.h>
#include <wait.h>
-ide_pci_controller_t ide_pci_controller;
+ide_pci_controller_t ide_pci_controller[NR_IDE_CONTROLLER];
-extern unsigned int ATA_CHL0_CMD_BASE;
-extern unsigned int ATA_CHL1_CMD_BASE;
+unsigned int IDE_CHL0_CMD_BASE = 0x1F0;
+unsigned int IDE_CHL1_CMD_BASE = 0x170;
-extern unsigned int ATA_CHL0_CTL_BASE;
-extern unsigned int ATA_CHL1_CTL_BASE;
+unsigned int IDE_CHL0_CTL_BASE = 0x3F6;
+unsigned int IDE_CHL1_CTL_BASE = 0x376;
+// 《PCI IDE Controller Specification》
+// 《Programming Interface for Bus Master IDE Controller》
void ide_pci_init(pci_device_t *pci) {
unsigned int v;
// 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);
+ printd("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是端口地址
- ide_pci_controller.bus_iobase = iobase;
- ide_pci_controller.bus_cmd = iobase + PCI_IDE_CMD;
- ide_pci_controller.bus_status = iobase + PCI_IDE_STATUS;
- ide_pci_controller.bus_prdt = iobase + PCI_IDE_PRDT;
- ide_pci_controller.prdt = (prdte_t *)alloc_one_page(0);
-
- int i;
- printk(" BARS: ");
- for (i = 0; i < BARS_CNT; ++i) {
- printk("%08x ", pci->bars[i]);
- pci->bars[i] &= (~1UL);
- }
- printk("\n");
- ATA_CHL0_CMD_BASE = pci->bars[0] ? pci->bars[0] : ATA_CHL0_CMD_BASE;
- ATA_CHL0_CTL_BASE = pci->bars[1] ? pci->bars[1] : ATA_CHL0_CTL_BASE;
+ for (int i = 0; i < NR_IDE_CONTROLLER; i++) {
+ iobase += i * 8; // secondary channel 需要加8
+ printd("ide pci Base IO Address Register %08x\n", iobase);
+ iobase &= 0xFFFC; // 最低为0是内存地址为1是端口地址
+ ide_pci_controller[i].bus_iobase = iobase;
+ ide_pci_controller[i].bus_cmd = iobase + PCI_IDE_CMD;
+ ide_pci_controller[i].bus_status = iobase + PCI_IDE_STATUS;
+ ide_pci_controller[i].bus_prdt = iobase + PCI_IDE_PRDT;
+ ide_pci_controller[i].prdt = (prdte_t *)alloc_one_page(0);
+
+ printd("BARS: ");
+ for (int j = 0; j < BARS_CNT; ++j) {
+ printd("%08x ", pci->bars[j]);
+ pci->bars[j] &= (~1UL);
+ }
+ printd("\n");
+
+ ide_pci_controller[i].pci = pci;
+ }
- ATA_CHL1_CMD_BASE = pci->bars[2] ? pci->bars[2] : ATA_CHL1_CMD_BASE;
- ATA_CHL1_CTL_BASE = pci->bars[3] ? pci->bars[3] : ATA_CHL1_CTL_BASE;
+ IDE_CHL0_CMD_BASE = pci->bars[0] ? pci->bars[0] : IDE_CHL0_CMD_BASE;
+ IDE_CHL0_CTL_BASE = pci->bars[1] ? pci->bars[1] : IDE_CHL0_CTL_BASE;
- ide_pci_controller.pci = pci;
+ IDE_CHL1_CMD_BASE = pci->bars[2] ? pci->bars[2] : IDE_CHL1_CMD_BASE;
+ IDE_CHL1_CTL_BASE = pci->bars[3] ? pci->bars[3] : IDE_CHL1_CTL_BASE;
- printd("channel0: cmd %04x ctl %04x channel1: cmd %04x ctl %04x\n", ATA_CHL0_CMD_BASE, ATA_CHL0_CTL_BASE,
- ATA_CHL1_CMD_BASE, ATA_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);
+ printd("ide channel 0: cmd %04x ctl %04x\n", IDE_CHL0_CMD_BASE, IDE_CHL0_CTL_BASE);
+ printd("ide channel 1: cmd %04x ctl %04x\n", IDE_CHL1_CMD_BASE, IDE_CHL1_CTL_BASE);
}
// void ide_status() {
const char *pci_get_info(unsigned int classcode, unsigned int progif);
void init_pci_controller(unsigned int classcode) {
pci_device_t *pci = pci_find_device_by_classcode(classcode);
+ if (pci == NULL) {
+ printk("can not find pci classcode: %08x", classcode);
+ panic("can not find ide controller");
+ }
+ assert(pci->intr_line < 16);
if (pci != 0 && pci->intr_line < 16) {
printk("found pci %03d:%02d.%d #%02d %04X:%04X ProgIF %02x %s\n", pci->bus, pci->dev, pci->devfn,
pci->intr_line, pci->vendor, pci->device, pci->progif, pci_get_info(pci->classcode, pci->progif));
extern semaphore_t disk_intr_sem;
extern void *mbr_buf;
-extern ide_pci_controller_t ide_pci_controller;
extern uint32_t disk_request_cnt;
extern uint32_t disk_handled_cnt;
volatile uint32_t disk_inter_cnt = 0;
-void ide_irq_bh_handler() {
+void ata_dma_stop(int channel);
+void ide_irq_bh_handler(void *arg) {
disk_inter_cnt++;
+ int channel = (int)arg;
+
// printl(MPL_IDE, "disk req %u consumed %u irq %u", disk_request_cnt, disk_handled_cnt, disk_inter_cnt);
printlxy(MPL_IDE, MPO_IDE, "disk irq %u req %u consumed %u ", disk_inter_cnt, disk_request_cnt, disk_handled_cnt);
- ata_dma_stop();
+
// up里不会立即重新调度进程
up(&disk_intr_sem);
}
void ide_irq_handler(unsigned int irq, pt_regs_t *regs, void *devid) {
// printk("ide irq %d handler pci status: 0x%02x\n", irq, ata_pci_bus_status());
- add_irq_bh_handler(ide_irq_bh_handler);
+ int channel = irq == 14 ? 0 : 1;
+ ata_dma_stop(channel);
+
+ add_irq_bh_handler(ide_irq_bh_handler, &channel);
}
+void ide1_irq_handler(unsigned int irq, pt_regs_t *regs, void *devid) { panic("ide 0"); }
+
+void ide_ata_init();
void ide_init() {
- // memset((void *)&drv, 0, sizeof(drv));
- memset(&ide_pci_controller, 0, sizeof(ide_pci_controller));
+ memset(ide_pci_controller, 0, sizeof(ide_pci_controller[0]) * NR_IDE_CONTROLLER);
+
+ // 读PCI里 IDE相关寄存器的配置
+ // init_pci_controller(0x0106);
+ init_pci_controller(0x0101);
+ // init_pci_controller(0x7010);
- void ide_ata_init();
+ // 读IDE 硬盘的identity
ide_ata_init();
request_irq(0x0E, ide_irq_handler, "hard", "IDE");
- // init_pci_controller(0x0106);
- init_pci_controller(0x0101);
+ request_irq(0x0F, ide_irq_handler, "hard", "IDE");
}
#pragma once
+#include <disk.h>
#include <pci.h>
+#include <semaphore.h>
#include <system.h>
#include <task.h>
int done;
} ide_pci_controller_t;
+#define NR_IDE_CONTROLLER 2
+
+typedef struct _ide_drive {
+ int present;
+ int dma;
+ uint64_t lba48;
+ uint64_t max_lba;
+
+ semaphore_t request_mutex;
+
+ disk_request_queue_t request_queue;
+} ide_drive_t;
+
+#define MAX_IDE_DRIVE_CNT 4
+extern ide_drive_t ide_drives[MAX_IDE_DRIVE_CNT];
+
void sleep_on_ide();
-void wait_on_ide();
\ No newline at end of file
+void wait_on_ide();
// TODO 改造成环形缓冲区
uint8_t scan_code;
-void kbd_bh_handler() {
+void kbd_bh_handler(void *arg) {
kbd_debug(scan_code);
if (0x80 & scan_code) { // break code
return;
void kbd_handler(unsigned int irq, pt_regs_t *regs, void *dev_id) {
scan_code = inb(0x60);
- add_irq_bh_handler(kbd_bh_handler);
+ add_irq_bh_handler(kbd_bh_handler, NULL);
}
extern tty_t *const default_tty;
// pci->progif, pci->bus, pci->intr_line);
// printk("%s\n", pci_get_info(pci->classcode, pci->progif));
printk("PCI %03d:%02d.%d #%02d %04X:%04X %s\n", pci->bus, pci->dev, pci->devfn, pci->intr_line, pci->vendor,
- pci->device, pci_get_info(pci->classcode, pci->progif));
+ pci->classcode, pci_get_info(pci->classcode, pci->progif));
#if 0
switch (pci->hdr_type) {
case PCI_HDRTYPE_NORMAL:
}
dump_pci_dev();
+
+ // while (1)
+ // ;
}
typedef struct pci_info {
} disk_request_cmd_t;
typedef struct disk_request {
- int dev;
+ dev_t dev;
uint64_t pos; // 扇区号
uint16_t count; // 扇区数
void *buf; // 到的缓冲区
list_head_t list;
} disk_request_queue_t;
-void send_disk_request(disk_request_t *r);
\ No newline at end of file
+void send_disk_request(disk_request_t *r);
typedef struct irq_bh_action {
void (*handler)();
+ void *arg;
struct irq_bh_action *next;
} irq_bh_action_t;
// void (*handler)(pt_regs_t *, unsigned int),
void (*handler)(unsigned int, pt_regs_t *, void *), const char *devname, void *dev_id);
-void add_irq_bh_handler(void (*handler)());
+void add_irq_bh_handler(void (*handler)(), void *arg);
int open_irq(unsigned int irq);
int close_irq(unsigned int irq);
void up(semaphore_t *s);
#define DECLARE_MUTEX(name) semaphore_t name = SEMAPHORE_INITIALIZER(name, 1)
+
+#define INIT_MUTEX(ptr) \
+ do { \
+ (ptr)->cnt = 1; \
+ INIT_LIST_HEAD(&((ptr)->wait_list)); \
+ } while (0)
void mutex_lock(semaphore_t *);
void mutex_unlock(semaphore_t *);
u16 ss, _ss;
} __attribute__((packed)) pt_regs_t;
-typedef unsigned long dev_t;
+typedef uint32_t dev_t;
typedef struct system {
u32 mmap_addr;
void debug_print_all_tasks();
void dump_irq_nr_stack();
-void clk_bh_handler();
+void clk_bh_handler(void *arg);
+
void clk_handler(unsigned int irq, pt_regs_t *regs, void *dev_id) {
// if (jiffies % 100 == 0) {
// printl(MPL_CLOCK, "clock irq: %d", jiffies);
assert(current->ticks <= TASK_MAX_PRIORITY); // 防止ticks被减到0后再减溢出
- add_irq_bh_handler(clk_bh_handler);
+ add_irq_bh_handler(clk_bh_handler, NULL);
}
// 开中断执行这个函数
// 后续放到一个内核任务中去做,需要先把禁止内核抢占做了
const char *task_state(unsigned int state);
-void clk_bh_handler() {
+void clk_bh_handler(void *arg) {
task_union *p = 0;
list_head_t *t = 0;
list_head_t *pos = 0;
// printk("%s state: %s\n", p->name, task_state(p->state));
assert(p->state == TASK_WAIT);
assert(p->delay_jiffies != 0);
- if (jiffies > p->delay_jiffies) {
+ if (p->delay_jiffies > 0 && jiffies > p->delay_jiffies) {
list_del(&p->pend);
p->delay_jiffies = 0;
p->state = TASK_READY;
}
while (action != NULL) {
- action->handler();
+ action->handler(action->arg);
irq_bh_action_t *p = action;
action = action->next;
kfree(p);
return 0;
}
-void add_irq_bh_handler(void (*handler)()) {
+void add_irq_bh_handler(void (*handler)(), void *arg) {
// 只能在中断处理函数中调用
assert(irq_disabled());
assert(p != NULL);
p->handler = handler;
+ p->arg = arg;
if (irq_bh_actions_end == NULL) {
assert(irq_bh_actions == NULL);
irq_bh_actions = p;
irq_bh_actions_end = p;
-
} else {
assert(irq_bh_actions != NULL);
irq_bh_actions_end->next = p;
void debug_print_all_tasks() {
task_union *p = 0;
list_head_t *pos = 0, *t = 0;
- printl(MPL_TASK_TITLE, " NAME STATE TK/PI TURN SCHED KEEP");
+ printl(MPL_TASK_TITLE, " NAME STATE TK/PI TURN SCHED KEEP");
list_for_each_safe(pos, t, &all_tasks) {
p = list_entry(pos, task_union, list);
- printl(MPL_TASK_0 + p->pid, "%08x%s%4s:%u %s %02u/%02u %-10u %-10u %-10u", p,
+ printl(MPL_TASK_0 + p->pid, "%08x%s%-6s:%u %s %02u/%02u %-10u %-10u %-10u", p,
p->state == TASK_RUNNING ? ">" : " ", p->name, p->pid, task_state(p->state), p->ticks, p->priority,
p->turn, p->sched_cnt, p->sched_keep_cnt);
}
}
assert(current->state == TASK_RUNNING);
+
irq_restore(iflags);
}
boot_delay(DEFAULT_BOOT_DELAY_TICKS);
extern tty_t *const monitor_tty;
- // tty_switch(monitor_tty);
+ tty_switch(monitor_tty);
boot_delay(DEFAULT_BOOT_DELAY_TICKS);
void ide_init();
ide_init();
}
-
-// 在开中断的情况下继续初始化的内容
-void setup_under_irq() {
- void ata_init();
- ata_init();
- return;
- setup_fs();
-}
popfl // EFLAGS
addl $8, %esp // ESP SS
+ pushl %ecx
call *%edx
addl $4, %esp // CALL PUSH EIP
+ addl $4, %esp // ecx: arg
+
// TODO
// add exit here
request_irq(0x01, kbd_handler, "Intel 8042", "PS/2 Keyboard");
// request_irq(0x0E, default_ide_irq_handler, "hard", "IDE");
for (int i = 0; i < 16; i++) {
- if (i != 0 && i != 1 && i != 10 && i != 14) {
+ if (i != 0 && i != 1 && i != 10 && i != 14 && i != 15) {
request_irq(i, default_irq_handler, "default", "default");
}
}
open_irq(IRQ_CLOCK);
open_irq(IRQ_KEYBOARD);
open_irq(IRQ_DISK);
+ open_irq(15);
}
void boot_irq_handler();
#include <completion.h>
#include <disk.h>
+#include <ide.h>
#include <sched.h>
-disk_request_queue_t disk_request_queue;
-
// task disk与中断函数之间的信号量
semaphore_t disk_intr_sem;
-DECLARE_MUTEX(disk_request_mutex);
-
-void disk_init() {
- disk_request_queue.count = 0;
- INIT_LIST_HEAD(&disk_request_queue.list);
- // disk_request_queue.sem.cnt = 0;
- // INIT_LIST_HEAD(&disk_request_queue.sem.wait_list);
- semaphore_init(&disk_request_queue.sem, 0);
+// task disk 之间发送命令的互斥量
+DECLARE_MUTEX(disk_cmd_mutex);
- semaphore_init(&disk_intr_sem, 0);
-}
+void disk_init() { semaphore_init(&disk_intr_sem, 0); }
volatile uint32_t disk_request_cnt = 0;
volatile uint32_t disk_handled_cnt = 0;
+
void send_disk_request(disk_request_t *r) {
if (NULL == r) {
panic("null disk request");
}
+ // TODO: 转换
+ int drv_no = r->dev;
+ // assert(drv_no == 0);
+
+ assert(drv_no >= 0);
+ assert(drv_no <= MAX_IDE_DRIVE_CNT);
+
+ ide_drive_t *drv = ide_drives + drv_no;
+
+ assert(drv->present == 1);
+
// 这个用来让task_disk唤醒自己
semaphore_init(&r->sem, 0);
panic("disk DMA read cross 64K");
}
- mutex_lock(&disk_request_mutex);
+ mutex_lock(&drv->request_mutex);
disk_request_cnt++;
- list_add_tail(&r->list, &disk_request_queue.list);
- mutex_unlock(&disk_request_mutex);
+ list_add_tail(&r->list, &drv->request_queue.list);
+ mutex_unlock(&drv->request_mutex);
// 唤醒task_disk
- up(&disk_request_queue.sem);
+ up(&drv->request_queue.sem);
// 等待被task_disk唤醒
down(&r->sem);
}
-void disk_task_entry() {
+void disk_task_entry(int arg) {
int r_cnt = 0;
while (1) {
- // printk("wait for new hard disk request\n");
- down(&disk_request_queue.sem);
- // printk("hard disk request: %d\n", disk_request_queue.count++);
+ // 如果要改造成每个drive对应一个内核任务的话
+ // 就要注意共享disk_intr_sem的问题
+ // 目前只支持drv_no == 0
+ int drv_no = arg;
+ ide_drive_t *drv = ide_drives + drv_no;
+ if (drv->present == 0) {
+ panic("disk not present");
+ }
+
+ // 为了在DEBUG时看到RUNNING
+ for (int i = 0; i < 3; i++) {
+ asm("hlt;");
+ }
+
+ // printk("wait request for hard disk %d\n", drv_no);
+ down(&drv->request_queue.sem);
+ // printk("hard disk %d\n", drv_no);
- mutex_lock(&disk_request_mutex);
+ mutex_lock(&drv->request_mutex);
disk_request_t *r;
- r = list_first_entry(&disk_request_queue.list, disk_request_t, list);
+ r = list_first_entry(&drv->request_queue.list, disk_request_t, list);
if (NULL == r) {
panic("no disk request");
}
list_del(&r->list);
disk_handled_cnt++;
- mutex_unlock(&disk_request_mutex);
+ mutex_unlock(&drv->request_mutex);
+ // 目前这个disk_cmd_mutex是用于两个通道四个DRIVE之间互斥
+ // 目前还不确定两个通道之间能否同时执行
+ // 后续要把disk分成两个进程,分别负责channel 0 1
+ // 这里再视情况改写
+ mutex_lock(&disk_cmd_mutex);
switch (r->command) {
case DISK_REQ_IDENTIFY:
assert(r->count == 1);
- void ata_read_identify(int dev, int disable_intr);
- ata_read_identify(r->dev, 0);
+ void ata_read_identify(int drv, int disable_intr);
+ ata_read_identify(drv_no, 0);
break;
case DISK_REQ_READ:
assert(r->count > 0);
assert(r->buf != NULL);
- void ata_dma_read_ext(int dev, uint64_t pos, uint16_t count, void *dest);
- ata_dma_read_ext(r->dev, r->pos, r->count, r->buf);
+ void ata_dma_read_ext(int drv, uint64_t pos, uint16_t count, void *dest);
+ ata_dma_read_ext(drv_no, r->pos, r->count, r->buf);
break;
default:
break;
// 等待硬盘中断
down(&disk_intr_sem);
-
+ mutex_unlock(&disk_cmd_mutex);
// 读数据
if (DISK_REQ_IDENTIFY == r->command) {
- void ata_read_data(int dev, int sect_cnt, void *dst);
- ata_read_data(r->dev, 1, r->buf);
+ void ata_read_data(int drv_no, int sect_cnt, void *dst);
+ ata_read_data(drv_no, 1, r->buf);
}
// 唤醒等待该请求的进程
void init_task_entry() {
current->priority = 10;
- // 继续内核未完成的初始化
- // 这些初始化在开中断的情况下完成
- void setup_under_irq();
- setup_under_irq();
-
while (1) {
asm("sti;hlt;");
sysc_wait(2);
#define get_eflags(x) __asm__ __volatile__("pushfl; popl %0;" : "=g"(x)::"memory")
-void kernel_task(char *name, void *entry) {
+void kernel_task(char *name, void *entry, void *arg) {
pt_regs_t regs;
memset((void *)®s, 0, sizeof(regs));
// 内核任务入口
regs.edx = (unsigned long)entry;
+ // 参数
+ regs.ecx = (unsigned long)arg;
+
regs.eax = (u32)name;
// 创建内核任务的时候就直接指定其在fork后走的路径
memset(disk_buf1, 0, 512);
disk_request_t r;
+ r.dev = 0;
r.command = DISK_REQ_READ;
r.pos = sect_nr;
r.count = 1;
uint64_t sect_nr = get_next_deubug_sect_nr();
memset(disk_buf2, 0, 512);
disk_request_t r;
+ r.dev = 2;
r.command = DISK_REQ_READ;
r.pos = sect_nr;
r.count = 1;
r.buf = disk_buf2;
send_disk_request(&r);
- verify_hd_data(sect_nr, disk_buf2, current->name);
+ // verify_hd_data(sect_nr, disk_buf2, current->name);
for (int i = 0; i < 1; i++) {
asm("hlt;");
void disk_init();
disk_init();
- kernel_task("init", init_task_entry);
- kernel_task("disk", disk_task_entry);
- kernel_task("user", user_task_entry);
+ kernel_task("init", init_task_entry, NULL);
+ kernel_task("disk/0", disk_task_entry, (void *)0);
+ kernel_task("disk/2", disk_task_entry, (void *)2);
+ kernel_task("user", user_task_entry, NULL);
// for (int i = 0; i < 100; i++) {
// asm("hlt;");
// }
- kernel_task("tskA", taskA_entry);
- kernel_task("tskB", taskB_entry);
- kernel_task("tskC", taskC_entry);
+ kernel_task("tskA", taskA_entry, NULL);
+ kernel_task("tskB", taskB_entry, NULL);
+ kernel_task("tskC", taskC_entry, NULL);
current->priority = 1;
while (1) {
const uint32_t VADDR = (uint32_t)pa2va(PHY_VADDR);
#define TTY_VRAM_SIZE (0x1000)
-#define NR_TTYS 8
+#define MAX_NR_TTYS 8
tty_t ttys[NR_TTYS];
#define MAX_X 80
void init_tty(tty_t *tty, const char *name, unsigned long base) {
assert(0 != tty);
+ assert(NR_TTYS >= 1);
+ assert(NR_TTYS <= MAX_NR_TTYS);
strlcpy(tty->name, name, sizeof(tty->name));
qemu-system-i386 \
-device ich9-ahci,id=ahci \
-boot d \
- -drive file=HD.IMG,format=raw,index=0,media=disk \
+ -drive file=HDa.IMG,format=raw,index=0,media=disk \
-drive file=kernel.iso,index=1,media=cdrom \
+ -drive file=HDb.IMG,format=raw,index=2,media=disk \
-name kernel \
-s -S \
&