rendered paste bodyIndex: pci.cpp===================================================================--- pci.cpp (revision 319)+++ pci.cpp (working copy)@@ -37,6 +37,7 @@ case 0xffff: return "NONE"; case 0x1013: return "Cirrus Logic"; case 0x10ec: return "Realtek Semiconductor";+ case 0x80ee: return "VirtualBox"; default: return vendor_unknown; } }Index: Makefile===================================================================--- Makefile (revision 315)+++ Makefile (working copy)@@ -10,7 +10,7 @@ all: barebones tty2.o FS_MODULES = fs/ramdisk.o fs/cpiofs.o fs/devfs.o fs/fs.o fs/sink.o-MODULES= loader.o heap.o task.o newpipe.o kbd.o sched.o start.o exception.o lowlevel.o gdt.o isr.o idt.o interrupts.o timer.o syscall.o std_streams.o multiboot.o vm2.o elf.o tty2.o terminal.o list.o kernelpokes.o $(FS_MODULES)+MODULES= loader.o heap.o task.o newpipe.o kbd.o sched.o start.o exception.o lowlevel.o gdt.o isr.o idt.o interrupts.o timer.o syscall.o std_streams.o ata.o ata2.o multiboot.o vm2.o elf.o tty2.o terminal.o list.o kernelpokes.o $(FS_MODULES) barebones.img: barebones bootfloppy.img menu.cfg cp bootfloppy.img $@@@ -25,6 +25,8 @@ $(CXX) $(CXXFLAGS) -c $< %.o: %.asm $(ASM) $(ASMFLAGS) -l $<.lst $<+%.S: %.cpp+ $(CXX) $(CXXFLAGS) -S $< .PHONY: clean wc: wc -l `find -name "*.asm"` `find -name "*.c"` `find -name "*.h"` `find -name "*.cpp"` `find -name "*.hpp"`Index: start.cpp===================================================================--- start.cpp (revision 309)+++ start.cpp (working copy)@@ -21,6 +21,7 @@ #include "std_streams.h" #include "sched.h" #include "heap.h"+#include "ata.h" // the virtual address of the console. #define VIDMEM ((unsigned short *)0xC00B8000) @@ -28,7 +29,7 @@ Console console(VIDMEM); Terminal con_inst(&console); Terminal* con(&con_inst);-+void ide_initialize(u32,u32,u32,u32,u32); // tasks we're going to create Task initial_task,idle_task; // stacks@@ -89,6 +90,8 @@ devfs.register_device("null",&dnull); devfs.register_device("zero",&dzero); }++ void _main(UNUSED multiboot_t* mbd,UNUSED unsigned int magic ){ MultiBoot mb(mbd); //physmem.set_kernel_usage(u32(&__end)-KERNEL_BASE_ADDRESS);@@ -160,7 +163,8 @@ con->printf("Starting initial task \"%s\"...\n\n",PROGRAM_NAME); parseElf(fstestfd,&initial_task,USER_MODE); scheduler.addTask(&initial_task);-+// ide_initialize(0x1F0, 0x3F4, 0x170, 0x374, 0x000);+ ide_initialize(0,0,0,0,0); // tss_flush(); // con->putval("Sizeof(Task):",sizeof(Task)); // con_inst.print("Enabling interrupts...\n");Index: vm2.cpp===================================================================--- vm2.cpp (revision 322)+++ vm2.cpp (working copy)@@ -283,9 +283,10 @@ //pt[virt&0xfff].set(phys,user,writable); invalidate_addr((void*)virt); }+#define PAGE_ALIGN(x) ((x)&0xFFFFE000) bool AddressSpace::verify_range(u32 start,u32 len,bool user,bool writable) {- u32 curr=start;- u32 end=start+len;+ u32 curr=PAGE_ALIGN(start);+ u32 end=PAGE_ALIGN(start+len); if(end<curr) return true; while(curr<=end) { directory_entry& dirent=get_dir_entry(curr);Index: rebuild===================================================================--- rebuild (revision 216)+++ rebuild (working copy)@@ -11,4 +11,5 @@ sync sync #bochs -f bochs.conf-qemu -fda bootfloppy.img+./run +#qemu -fda bootfloppy.imgIndex: terminal.h===================================================================--- terminal.h (revision 278)+++ terminal.h (working copy)@@ -21,4 +21,8 @@ Console*con; }; extern Terminal *con;+extern "C" void printk(const char* fmt,...);++// #define printk con->printf+ #endifIndex: ata2.asm===================================================================--- ata2.asm (revision 0)+++ ata2.asm (revision 0)@@ -0,0 +1,372 @@+; base port register+%define BASE_IO_PORT 0x1f0+%define BASE_CMD_PORT 0x3f4++%define ATA_SR_BSY 0x80+%define ATA_SR_DRDY 0x40+%define ATA_SR_DF 0x20+%define ATA_SR_DSC 0x10+%define ATA_SR_DRQ 0x08+%define ATA_SR_CORR 0x04+%define ATA_SR_IDX 0x02+%define ATA_SR_ERR 0x01+%define ATA_ER_BBK 0x80+%define ATA_ER_UNC 0x40+%define ATA_ER_MC 0x20+%define ATA_ER_IDNF 0x10+%define ATA_ER_MCR 0x08+%define ATA_ER_ABRT 0x04+%define ATA_ER_TK0NF 0x02+%define ATA_ER_AMNF 0x01++%define ATA_CMD_READ_PIO 0x20+%define ATA_CMD_READ_PIO_EXT 0x24+%define ATA_CMD_READ_DMA 0xC8+%define ATA_CMD_READ_DMA_EXT 0x25+%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_CACHE_FLUSH 0xE7+%define ATA_CMD_CACHE_FLUSH_EXT 0xEA+%define ATA_CMD_PACKET 0xA0+%define ATA_CMD_IDENTIFY_PACKET 0xA1+%define ATA_CMD_IDENTIFY 0xEC+%define ATA_MODE 0xe+; * Data Register: BAR0 + 0; // Read-Write+; * Error Register: BAR0 + 1; // Read Only+; * Features Register: BAR0 + 1; // Write Only+; * SECCOUNT0: BAR0 + 2; // Read-Write+; * LBA0: BAR0 + 3; // Read-Write+; * LBA1: BAR0 + 4; // Read-Write+; * LBA2: BAR0 + 5; // Read-Write+; * HDDEVSEL: BAR0 + 6; // Read-Write, used to select a drive in the channel.+; * Command Register: BAR0 + 7; // Write Only.+; * Status Register: BAR0 + 7; // Read Only.+; * Alternate Status Register: BAR1 + 2; // Read Only.+; * Control Register: BAR1 + 2; // Write Only.+; * DEVADDRESS: BAR1 + 2; // I don't know what is the benefit from this register.+%define ATA_REG_DATA BASE_IO_PORT+0x00+%define ATA_REG_ERROR BASE_IO_PORT+0x01+%define ATA_REG_FEATURES BASE_IO_PORT+0x01+%define ATA_REG_SECCOUNT0 BASE_IO_PORT+0x02+%define ATA_REG_LBA0 BASE_IO_PORT+0x03+%define ATA_REG_LBA1 BASE_IO_PORT+0x04+%define ATA_REG_LBA2 BASE_IO_PORT+0x05+%define ATA_REG_HDDEVSEL BASE_IO_PORT+0x06+%define ATA_REG_COMMAND BASE_IO_PORT+0x07+%define ATA_REG_STATUS BASE_IO_PORT+0x07+; %define ATA_REG_SECCOUNT1 BASE_IO_PORT+0x08+; %define ATA_REG_LBA3 BASE_IO_PORT+0x09+; %define ATA_REG_LBA4 BASE_IO_PORT+0x0A+; %define ATA_REG_LBA5 BASE_IO_PORT+0x0B+%define ATA_REG_CONTROL BASE_CMD_PORT+0x02+%define ATA_REG_ALTSTATUS BASE_CMD_PORT+0x02+; %define ATA_REG_DEVADDRESS BASE_CMD_PORT+0x02++%define high_io [ebx+4]+%define low_io [ebx]+cursor: dd 0xc00b8040+putch:+push ebx+and ax,0x00ff+or ax,0x7000+mov ebx,[cursor]+add bx,2+mov [ebx],ax+mov [cursor],ebx+pop ebx+ret+%macro GETSTATUS 0+xor eax,eax+; mov edx,high_io ; mov dx,ATA_REG_ALTSTATUS+; add dx,2+mov edx,[ebx]+add dx,7+in al,dx+%endmacro++%macro PRINTSTATUS 0+GETSTATUS+push eax+call printstatus+pop eax+%endmacro++wait_for_busy:+GETSTATUS++test ax,ATA_SR_BSY+jz .end+inc word [0xc00b8002]+jmp wait_for_busy+.end:+ret+wait_for_drq:+GETSTATUS+; push eax+; call printstatus+; pop eax++test ax,ATA_SR_DRQ++jnz .end+inc word [0xc00b8012]+jmp wait_for_drq+.end:+ret+wait_for_ready:+GETSTATUS+test ax,ATA_SR_DRDY+jnz .end+inc word [0xc00b8004]+jmp wait_for_ready+.end:+ret+; %macro GETADDRESS+global ata_issue_identify+global ata_read_buffer+global ata_28bit_operation+global ata_read_test+extern printstatus+; param 1, drive no.+; param 2, buffer+; param 3, low io port+; param 4, high io port+; return 1 if not present, 0 otherwise++ata_issue_identify:+push ebp+mov ebp,esp+push ebx+mov ebx,ebp+add ebx,16+; select drive+mov edx,[ebx] ; mov dx,ATA_REG_HDDEVSEL+add edx, 6++mov eax, [ebp+8]+and al,1 ; do the bit twiddling+shl al,4+or al,ATA_MODE+out dx,al+; PRINTSTATUS+GETSTATUS ; pause a bit+GETSTATUS+GETSTATUS+++call wait_for_busy+; wait for rdy+; PRINTSTATUS+; GETSTATUS+; test al,ATA_SR_ERR+; jz .noerror+; xor eax,eax+; ret+; .noerror:+GETSTATUS+test al,ATA_SR_DRDY+jnz .noerror2+xor eax,eax+pop ebx+pop ebp+ret+.noerror2:+; call wait_for_ready+; now issue the identify command.+mov ax, ATA_CMD_IDENTIFY+mov edx,low_io ; mov dx,ATA_REG_COMMAND+add dx,7+out dx,al+; wait a few ticks+GETSTATUS+GETSTATUS+GETSTATUS+GETSTATUS+++; wait for !bsy and drq+call wait_for_busy+call wait_for_drq++; param 1, buffer (fixed at 512b len)+; param 2, low io port+; param 3, high io port+++push dword [ebx+4]+push dword [ebx]+mov eax,[ebp+12]+push eax ; buffer ad.+call ata_read_buffer+add esp,12+; read into the buffer+; it's possible a string instruction is incorrect though... it works///+; mov edx,[ebx] ; data reg, no offset+; mov edi, [ebp+12] ; destination buf+; mov ecx,128 ; count (128 dwords = 512b)+; cld+; rep insd+; ;++pop ebx+pop ebp+ret+++; param 1, buffer (fixed at 512b len)+; param 2, low io port+; param 3, high io port+ata_read_buffer:+push ebx+mov ebx,esp+add ebx,12+push edi+GETSTATUS+test al,ATA_SR_BSY|ATA_SR_ERR+jnz .end+test al,ATA_SR_DRQ+jz .end+++; read into the buffer+; it's possible a string instruction is incorrect though... it works///+mov edx,[ebx] ; data reg, no offset+mov edi, [ebx-4] ; destination buf+mov ecx,128 ; count (128 dwords = 512b)+cld+rep insd+;++.end:+pop edi+pop ebx+ret+extern ide_buf+; param 1 low io+; param 2 high+ata_read_test:+push ebp+mov ebp,esp+push ebx+mov ebx,ebp+add ebx,8+push dword 0 ; loop counter+push dword 0 ; read it+push dword 1 ; sector+push dword [ebx+4] ; high io+push dword [ebx] ; low io+push dword ide_buf ; buffer+push dword 0 ; drive number+.loop1:+mov [ide_buf],dword 0+mov eax,[esp+24]+and eax,0xf+shl eax,18+mov [esp+16],eax+inc word [0xc00b8024]++call ata_28bit_operation+call wait_for_busy+call wait_for_drq+GETSTATUS+test eax,ATA_SR_ERR+jz .noerror+PRINTSTATUS+.noerror:++push dword [ebx+4] ; high io+push dword [ebx] ; low io+push dword ide_buf ; buffer+call ata_read_buffer+add esp,12++mov al, [ide_buf]+call putch+mov al, [ide_buf+1]+call putch+mov al, [ide_buf+2]+call putch++; mov [0xc00b8040],eax+inc dword [esp+24]+mov eax,[esp+24]+cmp eax,1<<16+; jle .loop1+add esp,28+pop ebx+pop ebp++ret+; param 1, drive no.+; param 2, buffer+; param 3, low io port+; param 4, high io port+; param 5, sector number+; param 6, direction 1=write,0=read+; return 1 if not present, 0 otherwise++ata_28bit_operation:+push ebp+mov ebp,esp+push ebx+mov ebx,ebp+add ebx,16 ; param block+sub esp,4+mov eax,[ebx+8]+mov [esp],al ; lba_0+shr eax,8+mov [esp+1],al ; lba 1+shr eax,8+mov [esp+2],al ; lba 2+shr eax,8; eax=head address+and al,0xf ; should be unnecessary+mov [esp+3],al++call wait_for_busy+; PRINTSTATUS+; select drive+mov edx,[ebx] ; mov dx,ATA_REG_HDDEVSEL+add edx, 6++mov eax, [ebp+8]+and al,1 ; do the bit twiddling+shl al,4+or al,0xe0+or al,[esp+3] ; head count+out dx,al++mov edx,[ebx]+add dx,2+mov al,1+out dx,al ; sector count+inc dx+mov al,[esp]+out dx,al ; lba0+inc dx+mov al,[esp+1]+out dx,al ; lba1+inc dx+mov al,[esp+2]+out dx,al ; lba2++; mov eax,[ebx+8]+; test eax,eax+; jnz .writecmd+mov al,ATA_CMD_READ_PIO+; jmp .afterdecision+; .writecmd:+; mov al,ATA_CMD_WRITE_PIO+; .afterdecision:+mov edx,[ebx]+add dx,7 ; command register+out dx,al+; PRINTSTATUS+; prologue+add esp,4+pop ebx+pop ebp++ret+Index: bochs.conf===================================================================--- bochs.conf (revision 315)+++ bochs.conf (working copy)@@ -10,6 +10,7 @@ floppya: type=1_44, 1_44="bootfloppy.img", status=inserted # no floppyb ata0: enabled=1, ioaddr1=0x1f0, ioaddr2=0x3f0, irq=14+ata0-master: type=disk, mode=flat, translation=auto, path="hdd", cylinders=0, heads=0, spt=0, biosdetect=auto, model="Generic 1234" ata1: enabled=1, ioaddr1=0x170, ioaddr2=0x370, irq=15 ata2: enabled=0 ata3: enabled=0Index: ata.h===================================================================--- ata.h (revision 0)+++ ata.h (revision 0)@@ -0,0 +1,14 @@++#ifndef ATA_HEADER+#define ATA_HEADER+#include "types.h"+extern "C" {+ u32 ata_issue_identify(u32 id,void *buf,u16 low,u16 high);+ u32 ata_read_buffer(void*,u16 low,u16 high);+ u32 ata_28bit_operation(u32 id,void*,u16 low,u16 high,u32 sector,u32 dir);+ void printstatus(u8 val);+ void ide_initialize(u32 BAR0, u32 BAR1, u32 BAR2, u32 BAR3,u32 BAR4);+ u32 ata_read_test(u16 low,u16 high);+}++#endifIndex: interrupts.cpp===================================================================--- interrupts.cpp (revision 315)+++ interrupts.cpp (working copy)@@ -32,7 +32,7 @@ if(code<32) { PANIC("Unhandled exception (and it wasn't done by the exceptionhandler)\n"); } else if(regs->int_no<48) {- return;+// return; code-=32; con->printf("Unhandled IRQ (%d) - %s\n",code,IrqTargets[code]); } else {Index: lowlevel.asm===================================================================--- lowlevel.asm (revision 290)+++ lowlevel.asm (working copy)@@ -102,3 +102,24 @@ pop ebx ; Get the original value of EBX back. ret++++ ; printk trampoline:+; this is a stub to let me call con->printf from C and asm.+; not going to stay with c++ so will write new code to call printk+; also, typing con->printf is cumbersome. Once i figure out how to+;do naked functions in GCC I'll move it into a header. atm google+; doesn't turn up anything.+ global printk+ extern con+ extern _ZN8Terminal6printfEPKcz+ ; very much non-reentrant+ printktemp: dd 0+printk:+ pop dword [printktemp]+ push dword [con]+ call _ZN8Terminal6printfEPKcz+ pop dword [con]+ push dword [printktemp]+ retIndex: lowlevel.h===================================================================--- lowlevel.h (revision 319)+++ lowlevel.h (working copy)@@ -42,6 +42,16 @@ //asm volatile ("XCHG %BX, %BX"); }+#define insl(port, buf, nr) \+__asm__ ("cld;rep;insl\n\t" \+::"d"(port), "D"(buf), "c"(nr))++#define outsl(buf, nr, port) \+__asm__ ("cld;rep;outsl\n\t" \+::"d"(port), "S" (buf), "c" (nr))+inline void insw(u16 port,int count,u32 dest) {+ asm("rep insw" : : "c"(count), "d"(port), "D"(dest)); // Receive Data.+} inline void outb(u16 port, u8 value) { asm volatile ("outb %1, %0" : : "dN" (port), "a" (value));Index: ata.cpp===================================================================--- ata.cpp (revision 0)+++ ata.cpp (revision 0)@@ -0,0 +1,492 @@+#define ATA_SR_BSY 0x80+#define ATA_SR_DRDY 0x40+#define ATA_SR_DF 0x20+#define ATA_SR_DSC 0x10+#define ATA_SR_DRQ 0x08+#define ATA_SR_CORR 0x04+#define ATA_SR_IDX 0x02+#define ATA_SR_ERR 0x01+#define ATA_ER_BBK 0x80+#define ATA_ER_UNC 0x40+#define ATA_ER_MC 0x20+#define ATA_ER_IDNF 0x10+#define ATA_ER_MCR 0x08+#define ATA_ER_ABRT 0x04+#define ATA_ER_TK0NF 0x02+#define ATA_ER_AMNF 0x01++#define ATA_CMD_READ_PIO 0x20+#define ATA_CMD_READ_PIO_EXT 0x24+#define ATA_CMD_READ_DMA 0xC8+#define ATA_CMD_READ_DMA_EXT 0x25+#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_CACHE_FLUSH 0xE7+#define ATA_CMD_CACHE_FLUSH_EXT 0xEA+#define ATA_CMD_PACKET 0xA0+#define ATA_CMD_IDENTIFY_PACKET 0xA1+#define ATA_CMD_IDENTIFY 0xEC++#define ATAPI_CMD_READ 0xA8+#define ATAPI_CMD_EJECT 0x1B++#define ATA_IDENT_DEVICETYPE 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 IDE_ATA 0x00+#define IDE_ATAPI 0x01++#define ATA_MASTER 0x00+#define ATA_SLAVE 0x01++#define ATA_REG_DATA 0x00+#define ATA_REG_ERROR 0x01+#define ATA_REG_FEATURES 0x01+#define ATA_REG_SECCOUNT0 0x02+#define ATA_REG_LBA0 0x03+#define ATA_REG_LBA1 0x04+#define ATA_REG_LBA2 0x05+#define ATA_REG_HDDEVSEL 0x06+#define ATA_REG_COMMAND 0x07+#define ATA_REG_STATUS 0x07+#define ATA_REG_SECCOUNT1 0x08+#define ATA_REG_LBA3 0x09+#define ATA_REG_LBA4 0x0A+#define ATA_REG_LBA5 0x0B+#define ATA_REG_CONTROL 0x0C+#define ATA_REG_ALTSTATUS 0x0C+#define ATA_REG_DEVADDRESS 0x0D++// Channels:+#define ATA_PRIMARY 0x00+#define ATA_SECONDARY 0x01++// Directions:+#define ATA_READ 0x00+#define ATA_WRITE 0x01+#include "terminal.h"+#include "lowlevel.h"+#include "ata.h"++++// inline void insl(u16 port,void* dest,int count) {+// asm("rep insl" : : "c"(count), "d"(port), "D"(dest)); // Receive Data.+// }+inline void io_delay(int n=4) {+ for(int i=0;i<n*50;++i)+ inb(0);+}+struct IDEChannelRegisters {+ unsigned short base; // I/O Base.+ unsigned short ctrl; // Control Base+ unsigned short bmide; // Bus Master IDE+ unsigned char nIEN; // nIEN (No Interrupt);+} channels[2];+++unsigned char ide_buf[2048] = {0};+unsigned static char ide_irq_invoked = 0;+UNUSED unsigned static char atapi_packet[12] = {0xA8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};++struct ide_device {+ unsigned char reserved; // 0 (Empty) or 1 (This Drive really exists).+ unsigned char channel; // 0 (Primary Channel) or 1 (Secondary Channel).+ unsigned char drive; // 0 (Master Drive) or 1 (Slave Drive).+ unsigned short type; // 0: ATA, 1:ATAPI.+ unsigned short signature; // Drive Signature+ unsigned short capabilities;// Features.+ unsigned int commandSets; // Command Sets Supported.+ unsigned int size; // Size in Sectors.+ unsigned char model[41]; // Model in string.+} ide_devices[4];+unsigned char ide_read(unsigned char channel, unsigned char reg);+void ide_write(unsigned char channel, unsigned char reg, unsigned char data);+void ide_read_buffer(unsigned char channel, unsigned char reg, void* buffer,unsigned int quads);+// read an IDE register+unsigned char ide_read(unsigned char channel, unsigned char reg) {+ unsigned char result=0;+// printk("Reading ide channel: %X reg %X\n",channel,reg);+ if (reg > 0x07 && reg < 0x0C)+ ide_write(channel, ATA_REG_CONTROL, 0x80 | channels[channel].nIEN);+ if (reg < 0x08)+ result = inb(channels[channel].base + reg - 0x00);+ else if (reg < 0x0C)+ result = inb(channels[channel].base + reg - 0x06);+ else if (reg < 0x0E)+ result = inb(channels[channel].ctrl + reg - 0x0A);+ else if (reg < 0x16)+ result = inb(channels[channel].bmide + reg - 0x0E);+ if (reg > 0x07 && reg < 0x0C)+ ide_write(channel, ATA_REG_CONTROL, channels[channel].nIEN);+ return result;+}++void ide_write(unsigned char channel, unsigned char reg, unsigned char data) {+ if (reg > 0x07 && reg < 0x0C)+ ide_write(channel, ATA_REG_CONTROL, 0x80 | channels[channel].nIEN);+ if (reg < 0x08)+ outb(data, channels[channel].base + reg - 0x00);+ else if (reg < 0x0C)+ outb(data, channels[channel].base + reg - 0x06);+ else if (reg < 0x0E)+ outb(data, channels[channel].ctrl + reg - 0x0A);+ else if (reg < 0x16)+ outb(data, channels[channel].bmide + reg - 0x0E);+ if (reg > 0x07 && reg < 0x0C)+ ide_write(channel, ATA_REG_CONTROL, channels[channel].nIEN);+}++void printstatus(u8 val) {+ if(val&ATA_SR_BSY)+ con->print("BSY ");+ if(val&ATA_SR_DRDY)+ con->print("DRDY ");+ if(val&ATA_SR_DF)+ con->print("DF ");+ if(val&ATA_SR_DSC)+ con->print("DSC ");+ if(val&ATA_SR_DRQ)+ con->print("DRQ ");+ if(val&ATA_SR_CORR)+ con->print("CORR ");+ if(val&ATA_SR_IDX)+ con->print("IDX ");+ if(val&ATA_SR_ERR)+ con->print("ERR ");+ con->print("\n");+}+void ide_read_buffer(unsigned char channel, unsigned char reg, void* buffer,unsigned int quads) {+ if (reg > 0x07 && reg < 0x0C)+ ide_write(channel, ATA_REG_CONTROL, 0x80 | channels[channel].nIEN);+ asm("pushw %es; movw %ds, %ax; movw %ax, %es");+ if (reg < 0x08)+// ide_read_buffer(chan, ATA_REG_DATA, ide_buf, 128);++ insl(channels[channel].base + reg - 0x00, buffer, quads);+ else if (reg < 0x0C)+ insl(channels[channel].base + reg - 0x06, buffer, quads);+ else if (reg < 0x0E)+ insl(channels[channel].ctrl + reg - 0x0A, buffer, quads);+ else if (reg < 0x16)+ insl(channels[channel].bmide + reg - 0x0E, buffer, quads);+ asm("popw %es;");+ if (reg > 0x07 && reg < 0x0C)+ ide_write(channel, ATA_REG_CONTROL, channels[channel].nIEN);+}++unsigned char ide_print_error(unsigned int drive, unsigned char err) {+ if (err == 0)+ return err;++ printk("IDE:");+ if (err == 1) {printk("- Device Fault\n "); err = 19;}+ else if (err == 2) {+ unsigned char st = ide_read(ide_devices[drive].channel, ATA_REG_ERROR);+ if (st & ATA_ER_AMNF) {printk("- No Address Mark Found\n "); err = 7;}+ if (st & ATA_ER_TK0NF) {printk("- No Media or Media Error\n "); err = 3;}+ if (st & ATA_ER_ABRT) {printk("- Command Aborted\n "); err = 20;}+ if (st & ATA_ER_MCR) {printk("- No Media or Media Error\n "); err = 3;}+ if (st & ATA_ER_IDNF) {printk("- ID mark not Found\n "); err = 21;}+ if (st & ATA_ER_MC) {printk("- No Media or Media Error\n "); err = 3;}+ if (st & ATA_ER_UNC) {printk("- Uncorrectable Data Error\n "); err = 22;}+ if (st & ATA_ER_BBK) {printk("- Bad Sectors\n "); err = 13;}+ } else if (err == 3) {printk("- Reads Nothing\n "); err = 23;}+ else if (err == 4) {printk("- Write Protected\n "); err = 8;}+ printk("- [%s %s] %s\n",+ (const char *[]){"Primary", "Secondary"}[ide_devices[drive].channel], // Use the channel as an index into the array+ (const char *[]){"Master", "Slave"}[ide_devices[drive].drive], // Same as above, using the drive+ ide_devices[drive].model);++ return err;+}+void waitbusy(int i) {+ for(;;) {+ u8 status = ide_read(i, ATA_REG_ALTSTATUS);+ if (!(status & ATA_SR_BSY))+ break; // Everything is right.+ }+}+void print_disk_info(ide_device* d);+void ide_initialize(unsigned int BAR0, unsigned int BAR1, unsigned int BAR2, unsigned int BAR3,+unsigned int BAR4) {+ int k, count = 0;++ memset(ide_devices,0,sizeof(ide_devices));+ memset(channels,0,sizeof(channels));+ // 1- Detect I/O Ports which interface IDE Controller:+ channels[ATA_PRIMARY ].base = (BAR0 & 0xFFFFFFFC) + 0x1F0 * (!BAR0);+ printk("Channel 0 base: %X\n",channels[ATA_PRIMARY ].base);++ channels[ATA_PRIMARY ].ctrl = (BAR1 & 0xFFFFFFFC) + 0x3F4 * (!BAR1);+ printk("Channel 0 ctl: %X\n",channels[ATA_PRIMARY ].ctrl);+ channels[ATA_SECONDARY].base = (BAR2 & 0xFFFFFFFC) + 0x170 * (!BAR2);+ channels[ATA_SECONDARY].ctrl = (BAR3 & 0xFFFFFFFC) + 0x374 * (!BAR3);+ printk("Channel 1 ctl: %X\n",channels[ATA_SECONDARY].ctrl);+ channels[ATA_PRIMARY ].bmide = (BAR4 & 0xFFFFFFFC) + 0; // Bus Master IDE+ channels[ATA_SECONDARY].bmide = (BAR4 & 0xFFFFFFFC) + 8; // Bus Master IDE+ ide_write(ATA_PRIMARY , ATA_REG_CONTROL, 6);+ ide_write(ATA_SECONDARY, ATA_REG_CONTROL, 6);+ io_delay(5000);+// ide_write(ATA_PRIMARY , ATA_REG_CONTROL, 2);+ // 2- Disable IRQs:+ ide_write(ATA_PRIMARY , ATA_REG_CONTROL, 2);+ ide_write(ATA_SECONDARY, ATA_REG_CONTROL, 2);++ // 3- Detect ATA-ATAPI Devices:+ for (int i = 0; i < 2; i++)+ for (int j = 0; j < 2; j++) {+// printk("HASHDHAHADSHDAH\n");++ UNUSED unsigned char err = 0, type = IDE_ATA, status;+ ide_devices[count].reserved = 0; // Assuming that no drive here.+status= ata_issue_identify(j,ide_buf,channels[i].base,channels[i].ctrl);+// printk("xxx\n");+/* // (I) Select Drive:+ ide_write(i, ATA_REG_HDDEVSEL,0xa| (j << 4)); // Select Drive.++ io_delay(100); // Wait 1ms for drive select to work.+// printk("status of %d,%d, after select: ",i,j);+// printstatus(ide_read(i, ATA_REG_ALTSTATUS));+// printk("\n");+// waitbusy(i);++ // (II) Send ATA Identify Command:+// ide_write(i, ATA_REG_COMMAND, ATA_CMD_IDENTIFY);+// io_delay(10); // This function should be implemented in your OS. which waits for 1 ms.+ // it is based on System Timer Device Driver.+ ide_write(i, ATA_REG_COMMAND, ATA_CMD_IDENTIFY);+ io_delay(100);+status=ide_read(i, ATA_REG_STATUS);+// printk("status of %d,%d, after identify: ",i,j);+// printstatus(status);+// printk("\n");+ // (III) Polling:*/+ if (status == 0) {++ continue; // If Status = 0, No Device.+ }+ printk("Got drive on %d,%d, status: ",i,j);+ printstatus(ide_read(i, ATA_REG_ALTSTATUS));+// printk("\n");++ // (IV) Probe for ATAPI Devices:+++// io_delay(1000);+// for(int t=0;t<50000;++t) {+/*+ status = ide_read(i, ATA_REG_STATUS);+ if ((status & ATA_SR_ERR)) {err = 1; break;} // If Err, Device is not ATA.+ if (!(status & ATA_SR_BSY))+ if(status & ATA_SR_DRQ)+ break; // Everything is right.+ io_delay(10);+// con->print("Status: ");+// printstatus(status);+// printk("\n");+// printk("IDE status poll: %X\n",status);+// printstatus(status);+ }*/+// if((status&ATA_SR_DRQ)==0) {+// printk("No drive\n"); continue;+// }+// con->print("Status: ");+// printstatus(status);+ // (V) Read Identification Space of the Device:+// ide_read_buffer(i, ATA_REG_DATA, ide_buf, 128);++ // (VI) Read Device Parameters:+ ide_devices[count].reserved = 1;+ ide_devices[count].type = type;+ ide_devices[count].channel = i;+ ide_devices[count].drive = j;+ ide_devices[count].signature = *((unsigned short *)(ide_buf + ATA_IDENT_DEVICETYPE));+ ide_devices[count].capabilities = *((unsigned short *)(ide_buf + ATA_IDENT_CAPABILITIES));+ ide_devices[count].commandSets = *((unsigned int *)(ide_buf + ATA_IDENT_COMMANDSETS));++ // (VII) Get Size:+ if (ide_devices[count].commandSets & (1 << 26))+ // Device uses 48-Bit Addressing:+ ide_devices[count].size = *((unsigned int *)(ide_buf + ATA_IDENT_MAX_LBA_EXT));+ else+ // Device uses CHS or 28-bit Addressing:+ ide_devices[count].size = *((unsigned int *)(ide_buf + ATA_IDENT_MAX_LBA));++ // (VIII) String indicates model of device (like Western Digital HDD and SONY DVD-RW...):+ for(k = 0; k < 40; k+=2) {+ ide_devices[count].model[k] = ide_buf[ATA_IDENT_MODEL + k + 1];+ ide_devices[count].model[k+1] = ide_buf[ATA_IDENT_MODEL + k];+ }+ u8* it=ide_devices[count].model+39;+// printk("char=%d\n",ide_devices[count].model[38]);+ while(*it==32) {+ *it=0;+ --it;+ }+ ide_devices[count].model[40] = 0; // Terminate String.+// printk("Got model: %s, %dKB\n",ide_devices[count].model,ide_devices[count].size/2);+// PANIC("4");+ count++;+ }++ // 4- Print Summary:+ for (int i = 0; i < 4; i++)+ if (ide_devices[i].reserved == 1) {+ print_disk_info(ide_devices+i);+// printk(" Found %s Drive %dMB - %s\n",ide_devices[i].type==0?"ATA":"ATAPI",+// ide_devices[i].size >>21, /* Size */+// ide_devices[i].model);+// (ide_devices[i].capabilities & 0x200)?"LBA":"CHS"+ }+}+void print_disk_info(ide_device* d){+ printk(" Found %s Drive %dMB - %s using %s %s\n",d->type==0?"ATA":"ATAPI",+ d->size >>11, /* Size */+ d->model,+ (d->commandSets&(1<<26))?"48 bit":"28 bit",+ (d->capabilities & 0x200)?"LBA":"CHS"+ );+}++unsigned char ide_ata_access(unsigned char direction, unsigned char drive, unsigned int lba,+ unsigned char numsects, unsigned short selector, unsigned int edi) {++ unsigned char lba_mode /* 0: CHS, 1:LBA28, 2: LBA48 */, dma /* 0: No DMA, 1: DMA */, cmd;+ unsigned char lba_io[6];+ unsigned int channel = ide_devices[drive].channel; // Read the Channel.+ unsigned int slavebit = ide_devices[drive].drive; // Read the Drive [Master/Slave]+ unsigned int bus = channels[channel].base; // Bus Base, like 0x1F0 which is also data port.+ unsigned int words = 256; // Almost every ATA drive has a sector-size of 512-byte.+ unsigned short cyl, i;+ unsigned char head, sect, err=0;+ ide_write(channel, ATA_REG_CONTROL, channels[channel].nIEN = (ide_irq_invoked = 0x0) + 0x02);+ // (I) Select one from LBA28, LBA48 or CHS;+ if (lba >= 0x10000000) { // Sure Drive should support LBA in this case, or you are+ // giving a wrong LBA.+ // LBA48:+ lba_mode = 2;+ lba_io[0] = (lba & 0x000000FF) >> 0;+ lba_io[1] = (lba & 0x0000FF00) >> 8;+ lba_io[2] = (lba & 0x00FF0000) >> 16;+ lba_io[3] = (lba & 0xFF000000) >> 24;+ lba_io[4] = 0; // LBA28 is integer, so 32-bits are enough to access 2TB.+ lba_io[5] = 0; // LBA28 is integer, so 32-bits are enough to access 2TB.+ head = 0; // Lower 4-bits of HDDEVSEL are not used here.+ } else if (ide_devices[drive].capabilities & 0x200) { // Drive supports LBA?+ // LBA28:+ lba_mode = 1;+ lba_io[0] = (lba & 0x00000FF) >> 0;+ lba_io[1] = (lba & 0x000FF00) >> 8;+ lba_io[2] = (lba & 0x0FF0000) >> 16;+ lba_io[3] = 0; // These Registers are not used here.+ lba_io[4] = 0; // These Registers are not used here.+ lba_io[5] = 0; // These Registers are not used here.+ head = (lba & 0xF000000) >> 24;+ } else {+ // CHS:+ lba_mode = 0;+ sect = (lba % 63) + 1;+ cyl = (lba + 1 - sect) / (16 * 63);+ lba_io[0] = sect;+ lba_io[1] = (cyl >> 0) & 0xFF;+ lba_io[2] = (cyl >> 8) & 0xFF;+ lba_io[3] = 0;+ lba_io[4] = 0;+ lba_io[5] = 0;+ head = (lba + 1 - sect) % (16 * 63) / (63); // Head number is written to HDDEVSEL lower 4-bits.+ }+ // (II) See if drive supports DMA or not;+ dma = 0; // We don't support DMA+ // (III) Wait if the drive is busy;+ while (ide_read(channel, ATA_REG_ALTSTATUS) & ATA_SR_BSY)+ ; // Wait if busy.++ // (IV) Select Drive from the controller;+ if (lba_mode == 0)+ ide_write(channel, ATA_REG_HDDEVSEL, 0xA0 | (slavebit << 4) | head); // Drive & CHS.+ else+ ide_write(channel, ATA_REG_HDDEVSEL, 0xE0 | (slavebit << 4) | head); // Drive & LBA+ // (V) Write Parameters;+ if (lba_mode == 2) {+ ide_write(channel, ATA_REG_SECCOUNT1, 0);+ ide_write(channel, ATA_REG_LBA3, lba_io[3]);+ ide_write(channel, ATA_REG_LBA4, lba_io[4]);+ ide_write(channel, ATA_REG_LBA5, lba_io[5]);+ }+ ide_write(channel, ATA_REG_SECCOUNT0, numsects);+ ide_write(channel, ATA_REG_LBA0, lba_io[0]);+ ide_write(channel, ATA_REG_LBA1, lba_io[1]);+ ide_write(channel, ATA_REG_LBA2, lba_io[2]);+ // (VI) Select the command and send it;+ // Routine that is followed:+ // If ( DMA & LBA48) DO_DMA_EXT;+ // If ( DMA & LBA28) DO_DMA_LBA;+ // If ( DMA & LBA28) DO_DMA_CHS;+ // If (!DMA & LBA48) DO_PIO_EXT;+ // If (!DMA & LBA28) DO_PIO_LBA;+ // If (!DMA & !LBA#) DO_PIO_CHS;++// There isn't a command for doing CHS with DMA.++ if (lba_mode == 0 && dma == 0 && direction == 0) cmd = ATA_CMD_READ_PIO;+ if (lba_mode == 1 && dma == 0 && direction == 0) cmd = ATA_CMD_READ_PIO;+ if (lba_mode == 2 && dma == 0 && direction == 0) cmd = ATA_CMD_READ_PIO_EXT;+ if (lba_mode == 0 && dma == 1 && direction == 0) cmd = ATA_CMD_READ_DMA;+ if (lba_mode == 1 && dma == 1 && direction == 0) cmd = ATA_CMD_READ_DMA;+ if (lba_mode == 2 && dma == 1 && direction == 0) cmd = ATA_CMD_READ_DMA_EXT;+ if (lba_mode == 0 && dma == 0 && direction == 1) cmd = ATA_CMD_WRITE_PIO;+ if (lba_mode == 1 && dma == 0 && direction == 1) cmd = ATA_CMD_WRITE_PIO;+ if (lba_mode == 2 && dma == 0 && direction == 1) cmd = ATA_CMD_WRITE_PIO_EXT;+ if (lba_mode == 0 && dma == 1 && direction == 1) cmd = ATA_CMD_WRITE_DMA;+ if (lba_mode == 1 && dma == 1 && direction == 1) cmd = ATA_CMD_WRITE_DMA;+ if (lba_mode == 2 && dma == 1 && direction == 1) cmd = ATA_CMD_WRITE_DMA_EXT;+ ide_write(channel, ATA_REG_COMMAND, cmd); // Send the Command.++ if (dma) {+ if (direction == 0) {+ // DMA Read.+ } else {+ // DMA Write.+ }+ } else {+ if (direction == 0) {+ // PIO Read.+ for (i = 0; i < numsects; i++) {+// if ((err = ide_polling(channel, 1)))+ return err; // Polling, set error and exit if there is.+ asm("pushw %es");+ asm("mov %%ax, %%es" : : "a"(selector));+ asm("rep insw" : : "c"(words), "d"(bus), "D"(edi)); // Receive Data.+ asm("popw %es");+ edi += (words*2);+ }+ }else {+ // PIO Write.+ for (i = 0; i < numsects; i++) {+// ide_polling(channel, 0); // Polling.+ asm("pushw %ds");+ asm("mov %%ax, %%ds"::"a"(selector));+ asm("rep outsw"::"c"(words), "d"(bus), "S"(edi)); // Send Data+ asm("popw %ds");+ edi += (words*2);+ }+ ide_write(channel, ATA_REG_COMMAND, (char []) { ATA_CMD_CACHE_FLUSH,+ ATA_CMD_CACHE_FLUSH,+ ATA_CMD_CACHE_FLUSH_EXT}[lba_mode]);+// ide_polling(channel, 0); // Polling.+ }+ }+ return 0; // Easy, isn't it?+}\ No newline at end of fileIndex: kernelpokes.cpp===================================================================--- kernelpokes.cpp (revision 319)+++ kernelpokes.cpp (working copy)@@ -10,6 +10,7 @@ KPOKE(settimer); KPOKE(pcicheck); KPOKE(vsync);+KPOKE(diskread); #include "pci.cpp" int init_graph_vga(int width, int height,int chain4); #define SWITCHMODE 0@@ -17,6 +18,7 @@ #define VSYNC 2 #define SETTIMER 3 #define PCICHECK 4+#define DISKREAD 5 /** * This is for low level testing stuff. * Meant to be disabled in final version.@@ -34,6 +36,8 @@ return POKEK(settimer); case PCICHECK: return POKEK(pcicheck);+ case DISKREAD:+ return POKEK(diskread); default: return -Errno::ENOSYS; }@@ -43,6 +47,10 @@ timer.set(i1); return 0; }+#include "ata.h"+KPOKE(diskread) {+ return ata_read_test(0x170,0x374);+} KPOKE( vgamode ){ u32 r=init_graph_vga(i1,i2,i3); if(r) { return r; }