123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124 |
- /*
- * pci.c
- *
- * Copyright (C) 2016 Aleksandar Andrejevic <theflash@sdf.lonestar.org>
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
- #include <pci.h>
- #include <log.h>
- #include <heap.h>
- #include <irq.h>
- const char *pci_device_classes[] = {
- "Legacy Device",
- "Mass Storage Controller",
- "Network Controller",
- "Display Controller",
- "Multimedia Controller",
- "Memory Controller",
- "Bridge Device",
- "Simple Communication Controller",
- "Base System Peripheral",
- "Input Device",
- "Docking Station",
- "Processor",
- "Serial Bus Controller",
- "Wireless Controller"
- };
- static DECLARE_LIST(pci_device_list);
- static inline bool_t pci_device_exists(dword_t bus, dword_t slot, dword_t func)
- {
- pci_device_t device = {
- .bus = bus,
- .slot = slot,
- .function = func
- };
- return PCI_READ_VALUE(&device, pci_header_t, vendor_id) != 0xFFFF;
- }
- dword_t pci_read(pci_device_t *device, dword_t reg)
- {
- cpu_write_port_dword(0x0CF8,
- 0x80000000
- | ((device->bus & 0xFF) << 16)
- | ((device->slot & 0x1F) << 11)
- | ((device->function & 0x07) << 8)
- | ((reg & 0x3F) << 2));
- return cpu_read_port_dword(0x0CFC);
- }
- void pci_write(pci_device_t *device, dword_t reg, dword_t data)
- {
- cpu_write_port_dword(0x0CF8,
- 0x80000000
- | ((device->bus & 0xFF) << 16)
- | ((device->slot & 0x1F) << 11)
- | ((device->function & 0x07) << 8)
- | ((reg & 0x3F) << 2));
- cpu_write_port_dword(0x0CFC, data);
- }
- list_entry_t *get_pci_device_list_head(void)
- {
- return &pci_device_list;
- }
- void pci_init(void)
- {
- byte_t buses[256] = {0};
- size_t num_buses = 1;
- int i, j, k;
- for (i = 0; i < num_buses; i++)
- {
- for (j = 0; j < 32; j++) for (k = 0; k < 8; k++)
- {
- if (!pci_device_exists(buses[i], j, k)) continue;
- pci_device_t *device = (pci_device_t*)malloc(sizeof(pci_device_t));
- if (device == NULL) continue;
- device->bus = buses[i];
- device->slot = j;
- device->function = k;
- dword_t reg2 = pci_read(device, 2);
- device->class = (reg2 >> 24) & 0xFF;
- device->subclass = (reg2 >> 16) & 0xFF;
- device->prog_if = (reg2 >> 8) & 0xFF;
- device->in_use = FALSE;
- if (device->class == PCI_BRIDGE_DEVICE)
- {
- if (device->subclass == 0)
- {
- if (device->function) buses[num_buses++] = device->function;
- }
- else if (device->subclass == 4 || device->subclass == 9)
- {
- buses[num_buses++] = PCI_READ_VALUE(device, pci_bridge_header_t, secondary_bus_num);
- }
- }
- log_write(LOG_NORMAL, "PCI bus #%u, slot #%u, function #%u: %s\n", buses[i], j, k, pci_device_classes[device->class]);
- list_append(&pci_device_list, &device->list);
- if (k == 0 && !(PCI_READ_VALUE(device, pci_header_t, header_type) & 0x80)) break;
- }
- }
- }
|