diff options
| author | Michal Idziorek <m.i@gmx.at> | 2014-08-20 15:55:03 +0200 |
|---|---|---|
| committer | Michal Idziorek <m.i@gmx.at> | 2014-08-20 15:55:03 +0200 |
| commit | dc164927e71d760a41494ab1edf8e3deeda401db (patch) | |
| tree | 65253b4a5e443c599341d5972b58449388a4b2b1 | |
| parent | 46063e75f3f81dfb532fa5772c88e9027a0faebd (diff) | |
started implementing floppy driver etc.
| -rw-r--r-- | Makefile | 8 | ||||
| -rw-r--r-- | README.md | 4 | ||||
| -rw-r--r-- | boot/mbr.asm | 2 | ||||
| -rw-r--r-- | kernel/console.c | 1 | ||||
| -rw-r--r-- | kernel/floppy.c | 426 | ||||
| -rw-r--r-- | kernel/interrupts.c | 10 | ||||
| -rw-r--r-- | kernel/kernel.c | 24 | ||||
| -rw-r--r-- | kernel/kernel.h | 6 | ||||
| -rw-r--r-- | kernel/keyboard.c | 6 | ||||
| -rw-r--r-- | kernel/mem.c | 1 | ||||
| -rw-r--r-- | kernel/shell.c | 4 | ||||
| -rw-r--r-- | kernel/syslog.h | 6 | ||||
| -rw-r--r-- | kernel/timer.c | 17 | ||||
| -rw-r--r-- | kernel/x86.c | 38 | ||||
| -rw-r--r-- | kernel/x86.h | 43 |
15 files changed, 525 insertions, 71 deletions
@@ -32,6 +32,12 @@ kernel_entry.o: boot/kernel_entry.asm kernel.o: kernel/kernel.c kernel/console.h gcc -ffreestanding -m32 -o $@ -c $< -fno-asynchronous-unwind-tables -O0 +x86.o: kernel/x86.c + gcc -ffreestanding -m32 -o $@ -c $< -fno-asynchronous-unwind-tables -O0 + +floppy.o: kernel/floppy.c + gcc -ffreestanding -m32 -o $@ -c $< -fno-asynchronous-unwind-tables -O0 + vmem.o: kernel/vmem.c gcc -ffreestanding -m32 -o $@ -c $< -fno-asynchronous-unwind-tables -O0 @@ -59,7 +65,7 @@ timer.o: kernel/timer.c shell.o: kernel/shell.c gcc -ffreestanding -m32 -o $@ -c $< -fno-asynchronous-unwind-tables -O0 -kernel.bin: kernel_entry.o kernel.o console.o interrupts.o keyboard.o timer.o shell.o mem.o vmem.o pci.o e1000.o +kernel.bin: kernel_entry.o kernel.o console.o interrupts.o keyboard.o timer.o floppy.o x86.o shell.o mem.o vmem.o pci.o e1000.o ld -o $@ -Ttext 0x1000 --oformat binary -melf_i386 $^ -O0 @@ -28,8 +28,8 @@ Issues * memory map may be larger than mbr, but 0x0000 is used to check for end. * memory map location is hardcoded -* ~4 first 4mb of physical mem are reserved by mem manager (hardcoded) -* bootloader loads only 15sectors of kernel into mem. ~7KB? +* the first ~4mb of physical mem are reserved by mem manager (hardcoded) +* bootloader loads only 50 sectors of kernel into mem. 25KB! * Makefile is hardcoded and contains some mistakes too! * size of bitmap to track free blocks of physical memory is hardcoded to max. * physical memory manager allocator naively implemented. diff --git a/boot/mbr.asm b/boot/mbr.asm index fd13a76..2d87c20 100644 --- a/boot/mbr.asm +++ b/boot/mbr.asm @@ -107,7 +107,7 @@ boot_16: ;Load the KERNEL mov bx,KERNEL_OFFSET - mov dh, 15 + mov dh, 50 mov dl, [BOOT_DRIVE] call disk_load diff --git a/kernel/console.c b/kernel/console.c index 77b5fc1..42dc5d0 100644 --- a/kernel/console.c +++ b/kernel/console.c @@ -99,6 +99,7 @@ void scr_nextline() void scr_put_char(char ch,char col) { + print_char_col(posx,posy,ch,SCR_WHITE); posx++; if(posx>=SCR_WIDTH)scr_nextline(); diff --git a/kernel/floppy.c b/kernel/floppy.c new file mode 100644 index 0000000..2c71cdb --- /dev/null +++ b/kernel/floppy.c @@ -0,0 +1,426 @@ +#include "x86.h" + +#define FLPY_SECTORS_PER_TRACK 80 +static volatile int _CurrentDrive=0; +static volatile uint8_t _FloppyDiskIRQ = 0; + +// temporary dma hack +//! initialize DMA to use phys addr 1k-64k +void flpydsk_initialize_dma () { + + scr_put_string_nl("dma: initialize direct memory access"); + x86_outb (0x0a,0x06); //mask dma channel 2 + x86_outb (0xd8,0xff); //reset master flip-flop + + //changed to 0x000 (Address) + x86_outb (0x04, 0x0); //low + x86_outb (0x04, 0xa0); //high + + x86_outb (0xd8, 0xff); //reset master flip-flop + x86_outb (0x05, 0xff); //count to 0x23ff (number of bytes in a 3.5" floppy disk track) + x86_outb (0x05, 0x23); + x86_outb (0x80, 0); //external page register = 0 + x86_outb (0x0a, 0x02); //unmask dma channel 2 +} + +//! prepare the DMA for read transfer +void flpydsk_dma_read () { + + x86_outb (0x0a, 0x06); //mask dma channel 2 + x86_outb (0x0b, 0x56); //single transfer, address increment, autoinit, read, channel 2 + x86_outb (0x0a, 0x02); //unmask dma channel 2 + scr_put_string_nl("dma: configured for reading"); +} + +//! prepare the DMA for write transfer +void flpydsk_dma_write () { + + x86_outb (0x0a, 0x06); //mask dma channel 2 + x86_outb (0x0b, 0x5a); //single transfer, address increment, autoinit, write, channel 2 + x86_outb (0x0a, 0x02); //unmask dma channel 2 + scr_put_string_nl("dma: configured for writing"); +} +// +// + +enum FLPYDSK_IO { + + FLPYDSK_DOR = 0x3f2, + FLPYDSK_MSR = 0x3f4, + FLPYDSK_FIFO = 0x3f5, //data register + FLPYDSK_CTRL = 0x3f7 +}; + +enum FLPYDSK_DOR_MASK { + + FLPYDSK_DOR_MASK_DRIVE0 = 0, //00000000 = here for completeness sake + FLPYDSK_DOR_MASK_DRIVE1 = 1, //00000001 + FLPYDSK_DOR_MASK_DRIVE2 = 2, //00000010 + FLPYDSK_DOR_MASK_DRIVE3 = 3, //00000011 + FLPYDSK_DOR_MASK_RESET = 4, //00000100 + FLPYDSK_DOR_MASK_DMA = 8, //00001000 + FLPYDSK_DOR_MASK_DRIVE0_MOTOR = 16, //00010000 + FLPYDSK_DOR_MASK_DRIVE1_MOTOR = 32, //00100000 + FLPYDSK_DOR_MASK_DRIVE2_MOTOR = 64, //01000000 + FLPYDSK_DOR_MASK_DRIVE3_MOTOR = 128 //10000000 +}; + +enum FLPYDSK_MSR_MASK { + + FLPYDSK_MSR_MASK_DRIVE1_POS_MODE = 1, //00000001 + FLPYDSK_MSR_MASK_DRIVE2_POS_MODE = 2, //00000010 + FLPYDSK_MSR_MASK_DRIVE3_POS_MODE = 4, //00000100 + FLPYDSK_MSR_MASK_DRIVE4_POS_MODE = 8, //00001000 + FLPYDSK_MSR_MASK_BUSY = 16, //00010000 + FLPYDSK_MSR_MASK_DMA = 32, //00100000 + FLPYDSK_MSR_MASK_DATAIO = 64, //01000000 + FLPYDSK_MSR_MASK_DATAREG = 128 //10000000 +}; + +enum FLPYDSK_CMD { + + FDC_CMD_READ_TRACK = 2, + FDC_CMD_SPECIFY = 3, + FDC_CMD_CHECK_STAT = 4, + FDC_CMD_WRITE_SECT = 5, + FDC_CMD_READ_SECT = 6, + FDC_CMD_CALIBRATE = 7, + FDC_CMD_CHECK_INT = 8, + FDC_CMD_WRITE_DEL_S = 9, + FDC_CMD_READ_ID_S = 0xa, + FDC_CMD_READ_DEL_S = 0xc, + FDC_CMD_FORMAT_TRACK = 0xd, + FDC_CMD_SEEK = 0xf +}; + +enum FLPYDSK_CMD_EXT { + + FDC_CMD_EXT_SKIP = 0x20, //00100000 + FDC_CMD_EXT_DENSITY = 0x40, //01000000 + FDC_CMD_EXT_MULTITRACK = 0x80 //10000000 +}; + +enum FLPYDSK_GAP3_LENGTH { + + FLPYDSK_GAP3_LENGTH_STD = 42, + FLPYDSK_GAP3_LENGTH_5_14= 32, + FLPYDSK_GAP3_LENGTH_3_5= 27 +}; + +enum FLPYDSK_SECTOR_DTL { + + FLPYDSK_SECTOR_DTL_128 = 0, + FLPYDSK_SECTOR_DTL_256 = 1, + FLPYDSK_SECTOR_DTL_512 = 2, + FLPYDSK_SECTOR_DTL_1024 = 4 +}; + +void flpydsk_write_dor (uint8_t val ) { + + //! write the digital output register + x86_outb (FLPYDSK_DOR, val); + +} + +void flpydsk_write_ccr (uint8_t val) { + + //! write the configuation control + x86_outb (FLPYDSK_CTRL, val); +} + +void sleep(int i) +{ + i*=1000000; + for(;i>0;i--) + { + + } +} + +void flpydsk_motor_on() +{ + scr_put_string("floppy: starting motor..."); + x86_outb (FLPYDSK_DOR, FLPYDSK_DOR_MASK_DRIVE0_MOTOR | FLPYDSK_DOR_MASK_RESET); + sleep(20); + scr_put_string_nl("ok"); +} +void flpydsk_motor_off() +{ + scr_put_string("floppy: stopping motor..."); + x86_outb (FLPYDSK_DOR,FLPYDSK_DOR_MASK_RESET); + scr_put_string_nl("ok"); +} + +int flpydsk_calibrate (uint32_t drive) { + + uint32_t st0, cyl; + + if (drive >= 4) + { + + scr_put_string_nl("floppy: ERROR"); + return -2; + } + + //! turn on the motor + flpydsk_motor_on(); + + int i; + for (i = 0; i < 10; i++) { + + scr_put_string_nl("floppy: calibrate"); + //! send command + flpydsk_send_command ( FDC_CMD_CALIBRATE ); + flpydsk_send_command ( drive ); + flpydsk_wait_irq (); + flpydsk_check_int ( &st0, &cyl); + + //! did we fine cylinder 0? if so, we are done + if (!cyl) { + + // flpydsk_control_motor (false); + flpydsk_motor_off(); + return 0; + } + } + +// flpydsk_control_motor (false); + flpydsk_motor_off(); + return -1; +} + + + +void flpydsk_disable_controller () { + + flpydsk_write_dor (0); +} + +void flpydsk_enable_controller () { + + flpydsk_write_dor ( FLPYDSK_DOR_MASK_RESET | FLPYDSK_DOR_MASK_DMA); +} + + +uint8_t flpydsk_read_status () { + + //! just return main status register + return x86_inb (FLPYDSK_MSR); +} + +uint8_t flpydsk_read_data () { + + //! same as above function but returns data register for reading + int i; + for (i = 0; i < 500; i++ ) + if ( flpydsk_read_status () & FLPYDSK_MSR_MASK_DATAREG ) + return x86_inb (FLPYDSK_FIFO); +} +void flpydsk_send_command (uint8_t cmd) { + + //! wait until data register is ready. We send commands to the data register + int i; + for (i = 0; i < 500; i++ ) + if ( flpydsk_read_status () & FLPYDSK_MSR_MASK_DATAREG ) + { + x86_outb(FLPYDSK_FIFO, cmd); + return; + } +} + +void flpydsk_drive_data (uint32_t stepr, uint32_t loadt, uint32_t unloadt, int nondma ) { + + uint32_t data = 0; + + flpydsk_send_command (FDC_CMD_SPECIFY); + + data = ( (stepr & 0xf) << 4) | (unloadt & 0xf); + flpydsk_send_command (data); + + data = (loadt) << 1 | nondma; + flpydsk_send_command (data); +} + +void flpydsk_reset() +{ + uint32_t st0, cyl; + + //! reset the controller + scr_put_string_nl("floppy: reset controller"); + flpydsk_disable_controller (); + flpydsk_enable_controller (); + flpydsk_wait_irq (); + + //! send CHECK_INT/SENSE INTERRUPT command to all drives + int i; + for (i=0; i<4; i++) + flpydsk_check_int (&st0,&cyl); + + //! transfer speed 500kb/s + flpydsk_write_ccr (0); + + //! pass mechanical drive info. steprate=3ms, unload time=240ms, load time=16ms + flpydsk_drive_data (3,16,240,0); + + //! calibrate the disk + flpydsk_calibrate ( _CurrentDrive ); +} + +void floppy_init() +{ + // init dma + flpydsk_initialize_dma (); + + _CurrentDrive=0; + _FloppyDiskIRQ = 0; + + scr_put_string_nl("floppy: init floppy driver."); + + flpydsk_reset (); + flpydsk_drive_data (13, 1, 0xf, 0); + +} + +void int_floppy_handler() +{ + + X86_IRQ_BEGIN + _FloppyDiskIRQ=1; + X86_IRQ_END + +} + +void flpydsk_wait_irq() +{ + scr_put_string_nl("floppy: wait for irq6"); + while ( _FloppyDiskIRQ == 0); + _FloppyDiskIRQ = 0; + scr_put_string_nl("floppy: ok received "); +} + +void flpydsk_check_int (uint32_t* st0, uint32_t* cyl) { + + flpydsk_send_command (FDC_CMD_CHECK_INT); + + *st0 = flpydsk_read_data (); + *cyl = flpydsk_read_data (); +} + +void flpydsk_read_sector_imp (uint8_t head, uint8_t track, uint8_t sector) { + + //! set the DMA for read transfer + flpydsk_dma_read (); + + flpydsk_drive_data (13, 1, 0xf, 0); + scr_put_string_nl("floppy: reading sector (2)"); + + uint32_t st0, cyl; + + + //! read in a sector + flpydsk_send_command ( + FDC_CMD_READ_SECT | FDC_CMD_EXT_MULTITRACK | + FDC_CMD_EXT_SKIP | FDC_CMD_EXT_DENSITY); + flpydsk_send_command ( head << 2 | _CurrentDrive ); + flpydsk_send_command ( track); + flpydsk_send_command ( head); + flpydsk_send_command ( sector); + flpydsk_send_command ( FLPYDSK_SECTOR_DTL_512 ); + flpydsk_send_command ( + ( ( sector + 1 ) >= FLPY_SECTORS_PER_TRACK ) + ? FLPY_SECTORS_PER_TRACK : sector + 1 ); + flpydsk_send_command ( FLPYDSK_GAP3_LENGTH_3_5 ); + flpydsk_send_command ( 0xff ); + + //! wait for irq + //flpydsk_wait_irq (); + + //! read status info + int j; + for (j=0; j<7; j++) + flpydsk_read_data (); + + //! let FDC know we handled interrupt + flpydsk_check_int (&st0,&cyl); +} + +int flpydsk_seek ( uint32_t cyl, uint32_t head ) +{ + + uint32_t st0, cyl0; + + if (_CurrentDrive >= 4) + return -1; + + int i; + for (i = 0; i < 10; i++ ) { + + scr_put_string("floppy: seeking (cyl/head) : "); + scr_put_hex(cyl); + scr_put_string("/"); + scr_put_hex(head); + scr_put_string_nl(""); + + //! send the command + flpydsk_send_command (FDC_CMD_SEEK); + flpydsk_send_command ( (head) << 2 | _CurrentDrive); + flpydsk_send_command (cyl); + + //! wait for the results phase IRQ + //flpydsk_wait_irq (); + + flpydsk_check_int (&st0,&cyl0); + + //! found the cylinder? + if ( cyl0 == cyl) + return 0; + } + + return -1; +} + +void flpydsk_lba_to_chs (int lba,int *head,int *track,int *sector) { + + *head = ( lba % ( FLPY_SECTORS_PER_TRACK * 2 ) ) / ( FLPY_SECTORS_PER_TRACK ); + *track = lba / ( FLPY_SECTORS_PER_TRACK * 2 ); + *sector = lba % FLPY_SECTORS_PER_TRACK + 1; +} + + +uint8_t* flpydsk_read_sector (int sectorLBA) { + + sectorLBA=0x10; + + scr_put_string("floppy: reading sector:"); + scr_put_hex(sectorLBA); + scr_put_string_nl("."); + + + if (_CurrentDrive >= 4) + return 0; + + //! convert LBA sector to CHS + int head=0, track=0, sector=1; + flpydsk_lba_to_chs (sectorLBA, &head, &track, §or); + + + //! turn motor on and seek to track +// flpydsk_control_motor (true); + // start motor + flpydsk_motor_on(); + + if (flpydsk_seek (track, head) != 0) + return 0; + + //! read sector and turn motor off + flpydsk_read_sector_imp (head, track, sector); + // flpydsk_control_motor (false); + flpydsk_motor_off(); + + + //! warning: this is a bit hackish + //return (uint8_t*) DMA_BUFFER; + return (uint8_t*) 0x0; +} + + diff --git a/kernel/interrupts.c b/kernel/interrupts.c index a07cfef..944103d 100644 --- a/kernel/interrupts.c +++ b/kernel/interrupts.c @@ -1,4 +1,5 @@ #include "interrupts.h" +#include "x86.h" // the interrupt descriptor table static struct int_desc @@ -41,17 +42,12 @@ void int_generate88() } void int_def_handler() { - __asm__("pusha"); + X86_IRQ_BEGIN int_unhandled++; - // send EOI to primary PIC - __asm__("mov $0x20, %al"); - __asm__("out %al, $0x20"); + X86_IRQ_END - __asm__("popa"); - __asm__("leave"); - __asm__("iret"); } diff --git a/kernel/kernel.c b/kernel/kernel.c index b0bf71d..964a8f5 100644 --- a/kernel/kernel.c +++ b/kernel/kernel.c @@ -1,25 +1,28 @@ #include "kernel.h" // general kernel config & includes #include "console.h" // this will allow us to write to screen +#include "x86.h" // TODO: cleanup . how can i compile it without the includes!?? /////// -void int_kb_handler(); +void int_def_handler(); void int_clock_handler(); +void int_kb_handler(); +void int_floppy_handler(); + ////////// KERNEL MAIN///// ///// // // test handler void int_test_handler() { - __asm__("pusha"); + X86_IRQ_BEGIN scr_put_string("inside software interrupt handler 88"); - __asm__("popa"); - __asm__("leave"); - __asm__("iret"); + X86_IRQ_END + } @@ -50,15 +53,20 @@ void kernel_main() // setup custom interrupts // remember that we shifted all interrupts with the pic by 32 // so clock = 32 (irq 0) - // keyboard = 22 (irq 1) + // keyboard = 33 (irq 1) + // floppy = 38 (irq 6) // etc.. + // install PIT interrupt handler int_install_ir(32, 0b10001110, 0x08,&int_clock_handler); // install keyboard interrupt handler int_install_ir(33, 0b10001110, 0x08,&int_kb_handler); + // install floppy interrupt handler + int_install_ir(38, 0b10001110, 0x08,&int_floppy_handler); + // install test software interrupt handler int_install_ir(88, 0b10001110, 0x08,&int_test_handler); @@ -68,8 +76,12 @@ void kernel_main() // pci pci_init(); + + // floppy + floppy_init(); scr_put_string_nl(""); + //init shell shell_init(); diff --git a/kernel/kernel.h b/kernel/kernel.h index 6281fb6..5d10738 100644 --- a/kernel/kernel.h +++ b/kernel/kernel.h @@ -1,9 +1,9 @@ -#ifndef KERNEL_H -#define KERNEL_H +#ifndef FOOLOS_KERNEL_H +#define FOOLOS_KERNEL_H #include <stdint.h> //needed for uint16_t -#define KERNEL_HELLO_MESSAGE "FoolOs 0.0.4" +#define KERNEL_HELLO_MESSAGE "FoolOs 0.0.5" // #define DEBUG #endif diff --git a/kernel/keyboard.c b/kernel/keyboard.c index cdc557e..9b81682 100644 --- a/kernel/keyboard.c +++ b/kernel/keyboard.c @@ -124,13 +124,15 @@ void keyboard_handle(uint8_t in) } -void int_kb_handler() +__attribute__((interrupt( irq ))) void int_kb_handler() { - static uint8_t kb_in; __asm__("pusha"); __asm__("in $0x60, %al"); + + static uint8_t kb_in; + __asm__("mov %%al, %0"::"m" (kb_in)); // scr_nextline(); diff --git a/kernel/mem.c b/kernel/mem.c index 9b04cff..28e05eb 100644 --- a/kernel/mem.c +++ b/kernel/mem.c @@ -1,3 +1,4 @@ +#define MEM_PRINT_MEMORYMAP #include "kernel.h" //! 8 blocks per byte diff --git a/kernel/shell.c b/kernel/shell.c index 6839ec8..ebbeb51 100644 --- a/kernel/shell.c +++ b/kernel/shell.c @@ -66,6 +66,10 @@ void shell_execute() { int_generate88(); } + else if(1==strcmp(command,"READ")) + { + uint8_t *read= flpydsk_read_sector (10); + } else { scr_put_string(" unsupported command, sorry!"); diff --git a/kernel/syslog.h b/kernel/syslog.h new file mode 100644 index 0000000..921702c --- /dev/null +++ b/kernel/syslog.h @@ -0,0 +1,6 @@ +#ifndef FOOLOS_SYSLOG_H +#define FOOLOS_SYSLOG_H + +void syslog(char *sys, int level, char *str); + +#endif diff --git a/kernel/timer.c b/kernel/timer.c index da62f78..b4787b9 100644 --- a/kernel/timer.c +++ b/kernel/timer.c @@ -32,6 +32,7 @@ */ #include "kernel.h" +#include "x86.h" static uint64_t timer64=0; static uint8_t timer8=0; @@ -40,12 +41,10 @@ uint16_t timer16=0; // clock handler void int_clock_handler() { - __asm__("pusha"); - + X86_IRQ_BEGIN; timer64++; - #ifdef DEBUG timer8++; @@ -64,17 +63,7 @@ void int_clock_handler() timer8=0; } - // todo also the other pic!// TODO - __asm__("mov $0x20, %al"); - __asm__("out %al, $0x20"); - // - - __asm__("popa"); - __asm__("leave"); - __asm__("iret"); - __asm__("popa"); - __asm__("leave"); - __asm__("iret"); + X86_IRQ_END; } diff --git a/kernel/x86.c b/kernel/x86.c new file mode 100644 index 0000000..ee38599 --- /dev/null +++ b/kernel/x86.c @@ -0,0 +1,38 @@ +#include "x86.h" + +void x86_outb(int port, uint8_t data) +{ + __asm __volatile("outb %0,%w1" : : "a" (data), "d" (port)); +} + +uint8_t x86_inb(int port) +{ + uint8_t data; + __asm __volatile("inb %w1,%0" : "=a" (data) : "d" (port)); + return data; +} + +void x86_outw(int port, uint16_t data) +{ + __asm __volatile("outw %0,%w1" : : "a" (data), "d" (port)); +} + +uint16_t x86_inw(int port) +{ + uint16_t data; + __asm __volatile("inw %w1,%0" : "=a" (data) : "d" (port)); + return data; +} + +void x86_outl(int port, uint32_t data) +{ + __asm __volatile("outl %0,%w1" : : "a" (data), "d" (port)); +} + +uint32_t x86_inl(int port) +{ + uint32_t data; + __asm __volatile("inl %w1,%0" : "=a" (data) : "d" (port)); + return data; +} + diff --git a/kernel/x86.h b/kernel/x86.h index 1f2179d..425ab38 100644 --- a/kernel/x86.h +++ b/kernel/x86.h @@ -3,40 +3,13 @@ #include "kernel.h" -void x86_outb(int port, uint8_t data) -{ - __asm __volatile("outb %0,%w1" : : "a" (data), "d" (port)); -} - -uint8_t x86_inb(int port) -{ - uint8_t data; - __asm __volatile("inb %w1,%0" : "=a" (data) : "d" (port)); - return data; -} - -void x86_outw(int port, uint16_t data) -{ - __asm __volatile("outw %0,%w1" : : "a" (data), "d" (port)); -} - -uint16_t x86_inw(int port) -{ - uint16_t data; - __asm __volatile("inw %w1,%0" : "=a" (data) : "d" (port)); - return data; -} - -void x86_outl(int port, uint32_t data) -{ - __asm __volatile("outl %0,%w1" : : "a" (data), "d" (port)); -} - -uint32_t x86_inl(int port) -{ - uint32_t data; - __asm __volatile("inl %w1,%0" : "=a" (data) : "d" (port)); - return data; -} +#define X86_IRQ_BEGIN asm("cli\npusha"); +#define X86_IRQ_END asm("mov $0x20, %al\nout %al, $0x20\npopa\nsti\nleave\niret"); +void x86_outb(int port, uint8_t data); +uint8_t x86_inb(int port); +void x86_outw(int port, uint16_t data); +uint16_t x86_inw(int port); +void x86_outl(int port, uint32_t data); +uint32_t x86_inl(int port); #endif |
