POK(kernelpart)
/home/jaouen/pok_official/pok/trunk/kernel/arch/x86/pci.c
Go to the documentation of this file.
00001 /*
00002  *                               POK header
00003  * 
00004  * The following file is a part of the POK project. Any modification should
00005  * made according to the POK licence. You CANNOT use this file or a part of
00006  * this file is this part of a file for your own project
00007  *
00008  * For more information on the POK licence, please see our LICENCE FILE
00009  *
00010  * Please follow the coding guidelines described in doc/CODING_GUIDELINES
00011  *
00012  *                                      Copyright (c) 2007-2009 POK team 
00013  *
00014  * Created by laurent on Mon Jun 08 11:01:12 2009 
00015  */
00016 
00017 #ifdef POK_NEEDS_PCI
00018 
00019 # include <libc.h>
00020 # include <arch/x86/pci.h>
00021 
00022 # include "gdt.h"
00023 # include "event.h"
00024 
00025 static inline
00026 unsigned int pci_read(unsigned int bus,
00027                       unsigned int dev,
00028                       unsigned int fun,
00029                       unsigned int reg)
00030 {
00031   unsigned int addr = (1 << 31) | (bus << 16) | (dev << 11) | (fun << 8) | (reg & 0xfc);
00032   unsigned int val = -1;
00033 
00034   outl(PCI_CONFIG_ADDRESS, addr);
00035   val = inl(PCI_CONFIG_DATA);
00036 
00037   return (val >> ((reg & 3) << 3));
00038 }
00039 
00040 static inline
00041 unsigned int pci_read_reg(s_pci_device* d,
00042                           unsigned int reg)
00043 {
00044   return (pci_read(d->bus, d->dev, d->fun, reg));
00045 }
00046 
00047 static inline
00048 int pci_open(s_pci_device* d)
00049 {
00050   unsigned int bus = 0;
00051   unsigned int dev = 0;
00052   unsigned int fun = 0;
00053 
00054   for (bus = 0; bus < PCI_BUS_MAX; bus++)
00055     for (dev = 0; dev < PCI_DEV_MAX; dev++)
00056       for (fun = 0; fun < PCI_FUN_MAX; fun++)
00057         if (((unsigned short) pci_read(bus, dev, fun, PCI_REG_VENDORID)) == d->vendorid &&
00058             ((unsigned short) pci_read(bus, dev, fun, PCI_REG_DEVICEID)) == d->deviceid)
00059         {
00060           // we do not handle type 1 or 2 PCI configuration spaces
00061           if (pci_read(bus, dev, fun, PCI_REG_HEADERTYPE) != 0)
00062             continue;
00063 
00064           d->bus = bus;
00065           d->dev = dev;
00066           d->fun = fun;
00067           d->bar[0] = pci_read(bus, dev, fun, PCI_REG_BAR0);
00068           d->irq_line = (unsigned char) pci_read_reg(d, PCI_REG_IRQLINE);
00069 
00070           return (0);
00071         }
00072 
00073   return (-1);
00074 }
00075 
00076 void pci_handler(void);
00077 
00078 void dummy_pci_handler(void)
00079 {
00080   __asm__ volatile
00081     (
00082      ".globl pci_handler\n"
00083      "pci_handler:\n"
00084      "push %eax\n"              // save restricted context
00085      "push %edx\n"
00086      "mov $0x20, %al\n"
00087      "mov $0xA0, %dx\n"         // ack slave pic
00088      "outb %al, %dx\n"
00089      "mov $0x20, %dx\n"         // ack master pic
00090      "outb %al, %dx\n"
00091      "pop %edx\n"               // restore retricted context
00092      "pop %eax\n"
00093      "iret\n"                   // return
00094     );
00095 }
00096 
00097 void* ne2000_dev = NULL;
00098 
00099 pok_ret_t pci_register(s_pci_device*    dev,
00100                        uint8_t          part_id)
00101 {
00102   if (pci_open(dev) != 0)
00103     return (-1);
00104 
00105   pok_partitions[part_id].io_min = (dev->bar[0] & (~0x1F));
00106   pok_partitions[part_id].io_max = (dev->bar[0] & (~0x1F)) + dev->io_range;
00107 
00108   pok_idt_set_gate(32 + dev->irq_line,
00109                    GDT_CORE_CODE_SEGMENT,
00110                    (uint32_t) pci_handler,
00111                    IDTE_INTERRUPT,
00112                    0);
00113 
00114   ne2000_dev = dev;
00115 
00116   return (0);
00117 }
00118 
00119 #endif /* POK_NEEDS_PCI */