diff --git a/arch/x86_64/src/common/x86_64_pci.c b/arch/x86_64/src/common/x86_64_pci.c index d603d8999b..a84bc73898 100644 --- a/arch/x86_64/src/common/x86_64_pci.c +++ b/arch/x86_64/src/common/x86_64_pci.c @@ -35,39 +35,41 @@ * Pre-processor Definitions ****************************************************************************/ -#define PCI_CFG_ADDR 0xcf8 -#define PCI_DATA_ADDR 0xcfc -#define PCI_CFG_EN (1 << 31) +#define PCI_CFG_ADDR 0xcf8 +#define PCI_DATA_ADDR 0xcfc +#define PCI_CFG_EN (1 << 31) /**************************************************************************** * Private Functions Definitions ****************************************************************************/ -static void x86_64_pci_cfg_write(struct pci_dev_s *dev, int reg, - uint32_t val, int width); -static uint32_t x86_64_pci_cfg_read(struct pci_dev_s *dev, int reg, - int width); -static int x86_64_pci_map_bar(uint64_t addr, uint64_t len); -static uint32_t x86_64_pci_io_read(const volatile void *addr, int width); -static void x86_64_pci_io_write(const volatile void *addr, uint32_t val, - int width); +static int x86_64_pci_write(struct pci_bus_s *bus, unsigned int devfn, + int where, int size, uint32_t val); +static int x86_64_pci_read(struct pci_bus_s *bus, unsigned int devfn, + int where, int size, uint32_t *val); +static uintptr_t x86_64_pci_map(struct pci_bus_s *bus, uintptr_t start, + uintptr_t end); +static int x86_64_pci_read_io(struct pci_bus_s *bus, uintptr_t addr, + int size, uint32_t *val); +static int x86_64_pci_write_io(struct pci_bus_s *bus, uintptr_t addr, + int size, uint32_t val); /**************************************************************************** * Private Data ****************************************************************************/ -static const struct pci_bus_ops_s g_x86_64_pci_bus_ops = +static const struct pci_ops_s g_x86_64_pci_ops = { - .pci_cfg_write = x86_64_pci_cfg_write, - .pci_cfg_read = x86_64_pci_cfg_read, - .pci_map_bar = x86_64_pci_map_bar, - .pci_io_read = x86_64_pci_io_read, - .pci_io_write = x86_64_pci_io_write, + .write = x86_64_pci_write, + .read = x86_64_pci_read, + .map = x86_64_pci_map, + .read_io = x86_64_pci_read_io, + .write_io = x86_64_pci_write_io, }; -static struct pci_bus_s g_x86_64_pci_bus = +static struct pci_controller_s g_x86_64_pci = { - .ops = &g_x86_64_pci_bus_ops, + .ops = &g_x86_64_pci_ops }; /**************************************************************************** @@ -75,135 +77,208 @@ static struct pci_bus_s g_x86_64_pci_bus = ****************************************************************************/ /**************************************************************************** - * Name: x86_64_pci_cfg_write + * Name: x86_64_pci_write * * Description: - * Write 8, 16, 32, 64 bits data to PCI-E configuration space of device + * Write 8, 16, 32, 64 bits data to PCI configuration space of device * specified by dev * * Input Parameters: - * bdf - Device private data - * reg - A pointer to the read-only buffer of data to be written - * size - The number of bytes to send from the buffer + * bus - Bus that PCI device resides + * devfn - The device and function bit field of bdf + * where - Offset in the specify PCI device cfg address space + * size - The number of bytes to send from the buffer + * val - The value to write * * Returned Value: * 0: success, <0: A negated errno * ****************************************************************************/ -static void x86_64_pci_cfg_write(struct pci_dev_s *dev, int reg, - uint32_t val, int width) +static int x86_64_pci_write(struct pci_bus_s *bus, unsigned int devfn, + int where, int size, uint32_t val) { - uint8_t offset_mask = (4 - width); + uint8_t offset_mask = (4 - size); - outl(PCI_CFG_EN | (dev->bdf << 8) | reg, PCI_CFG_ADDR); - switch (width) + outl(PCI_CFG_EN | (bus->number << 16) | (devfn << 8) | where, + PCI_CFG_ADDR); + + switch (size) { case 1: - outb(val, PCI_DATA_ADDR + (reg & offset_mask)); - return; + outb(val, PCI_DATA_ADDR + (where & offset_mask)); + break; case 2: - outw(val, PCI_DATA_ADDR + (reg & offset_mask)); - return; + outw(val, PCI_DATA_ADDR + (where & offset_mask)); + break; case 4: outl(val, PCI_DATA_ADDR); - return; + break; default: - pcierr("Invalid cfg write width %d\n", width); + pcierr("Invalid cfg write size %d\n", size); + return -EINVAL; } + + return 0; } /**************************************************************************** - * Name: x86_64_pci_cfg_read + * Name: x86_64_pci_read * * Description: - * Read 8, 16, 32, 64 bits data from PCI-E configuration space of device + * Read 8, 16, 32, 64 bits data from PCI configuration space of device * specified by dev * * Input Parameters: - * dev - Device private data - * buffer - A pointer to a buffer to receive the data from the device + * bus - Bus that PCI device resides + * devfn - The device and function bit field of bdf + * where - Offset in the specify PCI device cfg address space * size - The requested number of bytes to be read + * val - A pointer to a buffer to receive the data from the device * * Returned Value: * 0: success, <0: A negated errno * ****************************************************************************/ -static uint32_t x86_64_pci_cfg_read(struct pci_dev_s *dev, int reg, - int width) +static int x86_64_pci_read(struct pci_bus_s *bus, unsigned int devfn, + int where, int size, uint32_t *val) { - uint32_t ret; - uint8_t offset_mask = 4 - width; + uint8_t offset_mask = 4 - size; - outl(PCI_CFG_EN | (dev->bdf << 8) | reg, PCI_CFG_ADDR); + outl(PCI_CFG_EN | (bus->number << 16) | (devfn << 8) | where, + PCI_CFG_ADDR); - switch (width) + switch (size) { case 1: - ret = inb(PCI_DATA_ADDR + (reg & offset_mask)); - return ret; - + *val = inb(PCI_DATA_ADDR + (where & offset_mask)); + break; case 2: - ret = inw(PCI_DATA_ADDR + (reg & offset_mask)); - return ret; + *val = inw(PCI_DATA_ADDR + (where & offset_mask)); + break; case 4: - ret = inl(PCI_DATA_ADDR); - return ret; + *val = inl(PCI_DATA_ADDR); + break; default: - pcierr("Invalid cfg read width %d\n", width); + *val = 0; + pcierr("Invalid cfg read size %d\n", size); + return -EINVAL; } - return 0; + return OK; } -static uint32_t x86_64_pci_io_read(const volatile void *addr, int width) -{ - uint16_t portaddr = (uint16_t)(intptr_t)addr; +/**************************************************************************** + * Name: x86_64_pci_read_io + * + * Description: + * Read 8, 16, 32, 64 bits data from PCI io address space of x86 64 device + * + * Input Parameters: + * bus - Bus that PCI device resides + * addr - The address to received data + * size - The requested number of bytes to be read + * val - A pointer to a buffer to receive the data from the device + * + * Returned Value: + * 0: success, <0: A negated errno + * + ****************************************************************************/ - switch (width) +static int x86_64_pci_read_io(struct pci_bus_s *bus, uintptr_t addr, + int size, uint32_t *val) +{ + uint16_t portaddr = (uint16_t)addr; + + switch (size) { case 1: - return (uint32_t)inb(portaddr); + *val = (uint32_t)inb(portaddr); + break; case 2: - return (uint32_t)inw(portaddr); + *val = (uint32_t)inw(portaddr); + break; case 4: - return (uint32_t)inl(portaddr); + *val = (uint32_t)inl(portaddr); + break; default: - pcierr("Invalid read width %d\n", width); + *val = 0; + pcierr("Invalid read size %d\n", size); DEBUGPANIC(); + return -EINVAL; } - return 0; + return OK; } -static void x86_64_pci_io_write(const volatile void *addr, uint32_t val, - int width) -{ - uint16_t portaddr = (uint16_t)(intptr_t)addr; +/**************************************************************************** + * Name: x86_64_pci_write_io + * + * Description: + * Write 8, 16, 32, 64 bits data to PCI io address space of x86 64 device + * + * Input Parameters: + * bus - Bus that PCI device resides + * addr - The address to write data + * size - The requested number of bytes to be write + * val - The value to write + * + * Returned Value: + * 0: success, <0: A negated errno + * + ****************************************************************************/ - switch (width) +static int x86_64_pci_write_io(struct pci_bus_s *bus, uintptr_t addr, + int size, uint32_t val) +{ + uint16_t portaddr = (uint16_t)addr; + + switch (size) { case 1: outb((uint8_t)val, portaddr); - return; + break; case 2: outw((uint16_t)val, portaddr); - return; + break; case 4: outl((uint32_t)val, portaddr); - return; + break; default: - pcierr("Invalid write width %d\n", width); + pcierr("Invalid write size %d\n", size); DEBUGPANIC(); + return -EINVAL; } + + return OK; } -static int x86_64_pci_map_bar(uint64_t addr, uint64_t len) +/**************************************************************************** + * Name: x86_64_pci_map + * + * Description: + * Map a memory region + * + * Input Parameters: + * bus - Bus that PCI device resides + * start - The start address to map + * end - The end address to map + * + * Returned Value: + * >0: success, 0: A positive value errno + * + ****************************************************************************/ + +static uintptr_t x86_64_pci_map(struct pci_bus_s *bus, uintptr_t start, + uintptr_t end) { - up_map_region((void *)(uintptr_t)addr, len, - X86_PAGE_WR | X86_PAGE_PRESENT | X86_PAGE_NOCACHE | X86_PAGE_GLOBAL); - return OK; + int ret; + + ret = up_map_region((void *)start, end - start + 1, X86_PAGE_WR | + X86_PAGE_PRESENT | X86_PAGE_NOCACHE | X86_PAGE_GLOBAL); + + return ret < 0 ? 0 : start; } /**************************************************************************** @@ -214,12 +289,11 @@ static int x86_64_pci_map_bar(uint64_t addr, uint64_t len) * Name: x86_64_pci_init * * Description: - * Initialize the PCI-E bus + * Initialize the PCI bus * ****************************************************************************/ void x86_64_pci_init(void) { - pciinfo("Initializing PCI Bus\n"); - pci_initialize(&g_x86_64_pci_bus); + pci_register_controller(&g_x86_64_pci); } diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index adcb05da3c..35b4ac0056 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -74,6 +74,36 @@ return ret; \ } +#define PCI_BUS_READ_IO(len, type, size) \ + int pci_bus_read_io_##len(FAR struct pci_bus_s *bus, uintptr_t where, \ + FAR type *value) \ + { \ + int ret = -EINVAL; \ + uint32_t data = 0; \ + \ + if (!PCI_##len##_BAD) \ + { \ + ret = bus->ctrl->ops->read_io(bus, where, size, &data); \ + } \ + \ + *value = (type)data; \ + return ret; \ + } + +#define PCI_BUS_WRITE_IO(len, type, size) \ + int pci_bus_write_io_##len(FAR struct pci_bus_s *bus, uintptr_t where, \ + type value) \ + { \ + int ret = -EINVAL; \ + \ + if (!PCI_##len##_BAD) \ + { \ + ret = bus->ctrl->ops->write_io(bus, where, size, value); \ + } \ + \ + return ret; \ + } + #define pci_match_one_device(id, dev) \ (((id)->vendor == PCI_ANY_ID || (id)->vendor == (dev)->vendor) && \ ((id)->device == PCI_ANY_ID || (id)->device == (dev)->device) && \ @@ -1171,3 +1201,9 @@ PCI_BUS_READ_CONFIG(dword, uint32_t, 4) PCI_BUS_WRITE_CONFIG(byte, uint8_t, 1) PCI_BUS_WRITE_CONFIG(word, uint16_t, 2) PCI_BUS_WRITE_CONFIG(dword, uint32_t, 4) +PCI_BUS_READ_IO(byte, uint8_t, 1) +PCI_BUS_READ_IO(word, uint16_t, 2) +PCI_BUS_READ_IO(dword, uint32_t, 4) +PCI_BUS_WRITE_IO(byte, uint8_t, 1) +PCI_BUS_WRITE_IO(word, uint16_t, 2) +PCI_BUS_WRITE_IO(dword, uint32_t, 4) \ No newline at end of file diff --git a/include/nuttx/pci/pci.h b/include/nuttx/pci/pci.h index 917ea81d92..f6835e8c81 100644 --- a/include/nuttx/pci/pci.h +++ b/include/nuttx/pci/pci.h @@ -152,6 +152,24 @@ #define pci_write_config_dword(dev, where, val) \ pci_bus_write_config_dword((dev)->bus, (dev)->devfn, where, val) +#define pci_read_io_byte(dev, addr, val) \ + pci_bus_read_io_byte((dev)->bus, addr, val) + +#define pci_read_io_word(dev, addr, val) \ + pci_bus_read_io_word((dev)->bus, addr, val) + +#define pci_read_io_dword(dev, addr, val) \ + pci_bus_read_io_dword((dev)->bus, addr, val) + +#define pci_write_io_byte(dev, addr, val) \ + pci_bus_write_io_byte((dev)->bus, addr, val) + +#define pci_write_io_word(dev, addr, val) \ + pci_bus_write_io_word((dev)->bus, addr, val) + +#define pci_write_io_dword(dev, addr, val) \ + pci_bus_write_io_dword((dev)->bus, addr, val) + /**************************************************************************** * Public Types ****************************************************************************/ @@ -232,6 +250,10 @@ struct pci_ops_s CODE uintptr_t (*map)(FAR struct pci_bus_s *bus, uintptr_t start, uintptr_t end); + CODE int (*read_io)(FAR struct pci_bus_s *bus, uintptr_t addr, + int size, FAR uint32_t *val); + CODE int (*write_io)(FAR struct pci_bus_s *bus, uintptr_t addr, + int size, uint32_t val); }; /* Each pci channel is a top-level PCI bus seem by CPU. A machine with