From: AceVest Date: Mon, 30 Jun 2014 16:02:24 +0000 (+0800) Subject: support ide dma on my laptop. but not on qemu X-Git-Url: http://zhaoyanbai.com/repos/?a=commitdiff_plain;h=d3770981003dfafefd1c690691d98de191c02f7b;p=kernel.git support ide dma on my laptop. but not on qemu --- diff --git a/drivers/ide.c b/drivers/ide.c index 35f7f6f..b608564 100644 --- a/drivers/ide.c +++ b/drivers/ide.c @@ -26,9 +26,14 @@ unsigned int HD_CHL1_CTL_BASE = 0x376; typedef struct _ide_drv { pci_device_t *pci; - u32_t iobase; - unsigned long cmd_out_cnt; + unsigned long cmd_cnt; unsigned long irq_cnt; + + unsigned int iobase; + + unsigned int bus_cmd; + unsigned int bus_status; + unsigned int bus_prdt; } ide_drive_t; ide_drive_t drv; @@ -41,6 +46,8 @@ typedef struct prd unsigned int eot : 1; } prd_t; +unsigned char *data = 0; + void ide_pci_init(pci_device_t *pci) { unsigned int v; @@ -54,9 +61,11 @@ void ide_pci_init(pci_device_t *pci) unsigned int iobase = pci_read_config_long(pci_cmd(pci, PCI_BAR4)); printk(" ide pci Base IO Address Register %08x\n", iobase); iobase &= 0xFFFC; - drv.iobase = iobase; + drv.iobase = iobase; + drv.bus_cmd = iobase + PCI_IDE_CMD; + drv.bus_status = iobase + PCI_IDE_STATUS; + drv.bus_prdt = iobase + PCI_IDE_PRDT; - outb(0x20, drv.iobase+2); int i; printk(" BARS: "); @@ -74,16 +83,17 @@ void ide_pci_init(pci_device_t *pci) 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); + printd(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_printd() { - printd(MPL_IDE, "ide cmd cnt %d irq cnt %d", drv.cmd_out_cnt, drv.irq_cnt); + printd(MPL_IDE, "ide cmd cnt %d irq cnt %d", drv.cmd_cnt, drv.irq_cnt); } void ide_cmd_out(Dev dev, u32 nsect, u64 sect_nr, u32 cmd) { - drv.cmd_out_cnt++; + drv.cmd_cnt++; outb(0x00, REG_CTL(dev)); outb(0x40, REG_DEVSEL(dev)); @@ -109,7 +119,7 @@ void dump_pci_ide(); void ide_status() { u8_t idest = inb(REG_STATUS(0)); - u8_t pcist = inb(drv.iobase+PCI_IDE_STATUS); + u8_t pcist = inb(drv.bus_status); printk(" ide status %02x pci status %02x\n", idest, pcist); } @@ -135,6 +145,7 @@ void init_pci_controller(unsigned int vendor, unsigned int device) if(pci != 0) { printk("Found PCI Vendor %04x Device %04x Class %04x IntrLine %d\n", vendor, device, pci->classcode, pci->intr_line); + printd(17, "Found PCI Vendor %04x Device %04x Class %04x IntrLine %d", vendor, device, pci->classcode, pci->intr_line); ide_pci_init(pci); drv.pci = pci; } @@ -147,19 +158,21 @@ void ide_irq() drv.irq_cnt++; - status = inb(drv.iobase+PCI_IDE_STATUS); + status = inb(drv.bus_status); if(0 == (status & PCI_IDE_STATUS_INTR)) { return ; } status |= PCI_IDE_STATUS_INTR; - outb(status, drv.iobase+PCI_IDE_STATUS); - outb(0x00, drv.iobase+PCI_IDE_CMD); + outb(status, drv.bus_status); + outb(0x00, drv.bus_cmd); insl(REG_DATA(0), buf, (512>>2)); u16_t sig = *((u16_t *) (buf+510)); printk("hard disk data %04x\n", sig); + sig = *((u16_t *) (data+510)); + printk("hard disk data %04x\n", sig); ide_printd(); up(&mutex); @@ -230,12 +243,118 @@ void ide_read_identify() print_ide_identify(buf); } +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() +{ +#if 1 + memset((void *)&prd, 0, sizeof(prd)); + unsigned long addr = alloc_one_page(0); + data = (char *) addr; + memset(data, 0xBB, 512); + prd.addr = va2pa(addr); + prd.cnt = 512; + prd.eot = 1; + gprdt = va2pa(&prd); + + printd(16, "gprdt %08x &prdt %08x prd.addr %08x addr %08x", + gprdt, &prd, prd.addr, addr); + +#if 0 + pci_write_config_word(PCI_IDE_CMD_STOP, drv.bus_cmd); + unsigned char status; + status = pci_read_config_long(drv.bus_status); + pci_write_config_word(status | PCI_IDE_STATUS_INTR | PCI_IDE_STATUS_ERR, drv.bus_status); + pci_write_config_long(gprdt, drv.bus_prdt); + pci_write_config_word(PCI_IDE_CMD_WRITE, drv.bus_cmd); +#else + 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 +#endif + +#if 1 + 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_CMD_BASE+HD_DEVSEL); + DELAY400NS; + +#if 1 + while ( 1 ) + { + status = inb(HD_CHL0_CMD_BASE+HD_STATUS); + printk(" <%02x> ", status); + if((status & (HD_STATUS_BSY | HD_STATUS_DRQ)) == 0) + { + break; + } + } +#endif + + printd(16, "---------------------------------------"); + + 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(0x25, HD_CHL0_CMD_BASE+HD_CMD); + +#if 0 + pci_read_config_word(drv.bus_cmd); + pci_read_config_word(drv.bus_status); + pci_write_config_word(PCI_IDE_CMD_WRITE|PCI_IDE_CMD_START, drv.bus_cmd); + pci_read_config_word(drv.bus_cmd); + pci_read_config_word(drv.bus_status); +#else + 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); +#endif +} void ide_init() { memset((void *)&drv, 0, sizeof(drv)); init_pci_controller(PCI_VENDORID_INTEL, 0x2829); init_pci_controller(PCI_VENDORID_INTEL, 0x7010); +#if 0 ide_read_identify(); ide_printd(); +#endif } diff --git a/drivers/ide.h b/drivers/ide.h index 59edb92..99a8252 100644 --- a/drivers/ide.h +++ b/drivers/ide.h @@ -104,6 +104,15 @@ extern unsigned int HD_CHL1_CTL_BASE; #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_INTR 0x04 + #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 diff --git a/drivers/keyboard.c b/drivers/keyboard.c index 01d465a..d9d5e96 100644 --- a/drivers/keyboard.c +++ b/drivers/keyboard.c @@ -27,6 +27,7 @@ void ide_status(); void debug_sched(); void vga_dbg_toggle(); int debug_wait_queue_put(unsigned int v); +void ide_dma_pci_lba48(); unsigned long kbd_cnt = 0; void kbd_handler(unsigned int irq, pt_regs_t * regs, void *dev_id) @@ -41,6 +42,15 @@ void kbd_handler(unsigned int irq, pt_regs_t * regs, void *dev_id) printk("[%02x]", scan_code); + if(scan_code == 0x09) // 8 + ide_dma_pci_lba48(); + + if(scan_code == 0x0B) // 0 + { + asm("cli;"); + while(1); + } + if(scan_code == 0x13) // r ide_debug(); @@ -70,7 +80,8 @@ void kbd_handler(unsigned int irq, pt_regs_t * regs, void *dev_id) if(scan_code == 0x43); // F9 if(scan_code == 0x44); // F10 - if(scan_code == 0x57); // F11 + if(scan_code == 0x57) // F11 + poweroff(); if(scan_code == 0x58) // F12 vga_dbg_toggle(); diff --git a/drivers/vga.c b/drivers/vga.c index db2e656..d2dd435 100644 --- a/drivers/vga.c +++ b/drivers/vga.c @@ -34,6 +34,7 @@ typedef struct { #define TAB_ALIGN 4 #define TAB_MASK (TAB_ALIGN-1) + typedef struct { unsigned int id; vga_char_t *base; @@ -110,7 +111,7 @@ void vga_scroll_up(vga_screen_t *s) if(delta <= 0) return; - vga_char_t *base = s->base; //(vga_char_t *) VIDEO_ADDR; + vga_char_t *base = s->base; vga_char_t *head = base + delta*CHARS_PER_LINE; vga_char_t *empt = base + (LINES_PER_SCREEN-delta)*CHARS_PER_LINE; @@ -198,8 +199,6 @@ void vga_init() bvga = 1; } - - void vga_switch(unsigned int nr) { if(nr >= VGA_MAX_SCREEN_CNT) diff --git a/include/task.h b/include/task.h index 0215fd7..3873c0e 100644 --- a/include/task.h +++ b/include/task.h @@ -30,32 +30,34 @@ enum TASK_UNUSED, TASK_RUNNING, TASK_WAIT, - //TASK_UNINTERRUPTIBLE, - //TASK_INTERRUPTIBLE, TASK_EXITING }; +#define TASK_NAME_SIZE 32 + typedef union task_union { struct { - unsigned long preempt_cnt; + unsigned long preempt_cnt; - unsigned long esp0; /* kernel stack */ + unsigned long esp0; /* kernel stack */ /* for context switch */ - unsigned long esp; - unsigned long eip; + unsigned long esp; + unsigned long eip; - long weight; + long weight; - pid_t pid; - pid_t ppid; + pid_t pid; + pid_t ppid; unsigned int state; - long exit_code; + long exit_code; unsigned long cr3; - long tty; + long tty; + + char name[TASK_NAME_SIZE]; list_head_t list; diff --git a/kernel/cpuid.c b/kernel/cpuid.c index 4972dc5..13660ff 100644 --- a/kernel/cpuid.c +++ b/kernel/cpuid.c @@ -18,7 +18,7 @@ #define TEST_FEATURE(val,bit,fea)\ do{\ if( ISSET_BIT(val,bit) )\ - /*printk(" %s",fea)*/;\ + printk(" %s",fea);\ }while(0); typedef struct reg{ unsigned long eax,ebx,ecx,edx; }Reg,*pReg; @@ -72,7 +72,7 @@ void detect_cpu() memcpy(pbs + 36 , &r.ebx, 4); memcpy(pbs + 40 , &r.ecx, 4); memcpy(pbs + 44 , &r.edx, 4); - //printk("Model Name: %s\n",pbs); + printk("Model Name: %s\n",pbs); printk("%s", pbs); /**********************Get Number of Processors********************/ @@ -91,8 +91,8 @@ void detect_cpu() TEST_FEATURE(fv, 7, "mce") TEST_FEATURE(fv, 8, "cxs") TEST_FEATURE(fv, 9, "apic") - //TEST_FEATURE(fv, 10, "Reserved") - //TEST_FEATURE(fv, 11, "SYSENTER/SYSEXIT") + TEST_FEATURE(fv, 10, "Reserved") + TEST_FEATURE(fv, 11, "SYSENTER/SYSEXIT") TEST_FEATURE(fv, 12, "mttr") TEST_FEATURE(fv, 13, "pge") TEST_FEATURE(fv, 14, "mca") diff --git a/kernel/init.c b/kernel/init.c index 737d80e..b03b442 100644 --- a/kernel/init.c +++ b/kernel/init.c @@ -35,26 +35,19 @@ void init_task_entry() } } +void kernel_task(void *entry) +{ + pt_regs_t regs; + memset((void*)®s, 0, sizeof(regs)); + regs.edx = (unsigned long) entry; + int pid = do_fork(®s, FORK_KRNL); + printk("kernel task pid is %d\n", pid); +} void root_task_entry() { - { - pt_regs_t regs; - memset((void*)®s, 0, sizeof(regs)); - regs.edx = (unsigned long) init_task_entry; - int pid = do_fork(®s, FORK_KRNL); - printk("a pid is %d\n", pid); - } - - - { - pt_regs_t regs; - memset((void*)®s, 0, sizeof(regs)); - regs.edx = (unsigned long) init_task_entry; - int pid = do_fork(®s, FORK_KRNL); - printk("b pid is %d\n", pid); - } - + kernel_task(init_task_entry); + kernel_task(init_task_entry); int cnt = 0; while(1) diff --git a/kernel/sched.c b/kernel/sched.c index 59d8f11..fd9d475 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -61,6 +61,7 @@ void init_root_tsk() root_task.ppid = 0; root_task.state = TASK_RUNNING; root_task.weight = TASK_INIT_WEIGHT; + strcpy(root_task.name, "root_task"); INIT_LIST_HEAD(&root_task.list); for(i=0; i