066588470dae91759e4cb16349c6873b46df7f9f
[pintos-anon] / src / devices / pci.c
1 #include <debug.h>
2 #include <list.h>
3 #include <stdbool.h>
4 #include <stdio.h>
5 #include "devices/pci.h"
6 #include "threads/io.h"
7 #include "threads/malloc.h"
8
9 struct list pci_dev_list;
10
11 static void scan_bus(uint8_t bus);
12
13 static uint32_t
14 pci_read_config (unsigned bus, unsigned dev, unsigned func, unsigned reg) 
15 {
16   ASSERT (bus < 256);
17   ASSERT (dev < 32);
18   ASSERT (func < 8);
19   ASSERT (reg < 64);
20
21   outl (0xcf8,
22         0x80000000 | (bus << 16) | (dev << 11) | (func << 8) | (reg << 2));
23   return inl (0xcfc);
24 }
25
26 static void
27 pci_dump_dev (struct pci_dev *dev) 
28 {
29   printf ("%04x:%02x:%02x.%x PCI device %04x:%04x\n", 
30           0, dev->bus_id, dev->devfn >> 4, dev->devfn & 0xf, 
31           dev->ven_id, dev->dev_id);
32   printf ("Class: %02x:%02x:%02x\n", 
33           dev->base_class, dev->sub_class, dev->interface);
34 }
35
36 static bool
37 scan_device (uint8_t bus, uint8_t dev, uint8_t func) 
38 {
39   uint32_t cfg[16];
40   uint8_t *byte_cfg;
41   int dev_id, vendor_id;
42   int line;
43   int reg;
44   struct pci_dev *new_pci_dev;
45
46   byte_cfg = (uint8_t *) cfg;
47
48   /* Read configuration space header */
49   for (reg = 0; reg < 16; reg++)
50     cfg[reg] = pci_read_config (bus, dev, func, reg);
51   
52   /* Get vendor and device ID */
53   dev_id = cfg[0] >> 16;
54   vendor_id = cfg[0] & 0xffff;
55
56   if (dev_id == 0 || dev_id == PCI_BAD_DEVICE || 
57       vendor_id == 0 || vendor_id == PCI_BAD_DEVICE)
58     return 0;
59
60   /* We have a valid PCI device, set it up */
61   new_pci_dev = malloc (sizeof *new_pci_dev);
62   if (!new_pci_dev)
63     PANIC ("couldn't allocate memory for PCI device");
64
65   new_pci_dev->bus_id = bus;
66   new_pci_dev->devfn = (dev << 4) | func;
67   new_pci_dev->ven_id = vendor_id;
68   new_pci_dev->dev_id = dev_id;
69   new_pci_dev->base_class = byte_cfg[PCI_REG_CLASS_BASE];
70   new_pci_dev->sub_class = byte_cfg[PCI_REG_CLASS_SUB];
71   new_pci_dev->interface = byte_cfg[PCI_REG_CLASS_INTERFACE];
72   list_push_front (&pci_dev_list, &new_pci_dev->elem);
73   
74   /* Debugging output */
75   pci_dump_dev(new_pci_dev);
76   for (line = 0; line < 16; line++) 
77     {
78       int byte;
79       
80       printf ("%02x:", line * 4);
81       for (byte = 3; byte >= 0; byte--)
82         printf (" %02x", byte_cfg[line * 4 + byte]);
83       printf ("\n");
84     }
85   printf ("\n");
86   
87   /* If device is PCI-to-PCI bridge, scan the bus behind it */
88   if (new_pci_dev->base_class == PCI_BRIDGE_BASE_CLASS &&
89       new_pci_dev->sub_class == PCI_BRIDGE_SUB_CLASS &&
90       (byte_cfg[PCI_REG_HEADER_TYPE] & 0x3f) == PCI_BRIDGE_HEADER_TYPE)
91     scan_bus(byte_cfg[PCI_BRIDGE_REG_SBUS]);
92   
93   return byte_cfg[PCI_REG_HEADER_TYPE] & 0x80;
94 }
95
96 static void
97 scan_bus(uint8_t bus)
98 {
99   uint8_t dev;
100
101   printf ("PCI: Scanning bus (%u)\n", bus);
102
103   for (dev = 0; dev < 32; dev++) 
104     {
105       /* Returns true if device is multi-function */
106       if (scan_device (bus, dev, 0)) 
107         {
108           int func;
109
110           for (func = 1; func < 8; func++)
111             scan_device (bus, dev, func);
112         }
113     }
114   printf ("PCI: Done (%u)\n", bus);
115 }
116
117 void
118 pci_init (void) 
119 {
120   printf ("PCI: Initializating\n");
121   list_init (&pci_dev_list);
122   scan_bus(0);  
123   printf ("PCI: Initialization done\n");
124 }
125
126 void
127 pci_dump (void)
128 {
129   struct list_elem *e;
130
131   for (e = list_begin (&pci_dev_list); e != list_end (&pci_dev_list);
132        e = list_next (e))
133     {
134       struct pci_dev *dev = list_entry (e, struct pci_dev, elem);
135       pci_dump_dev(dev);
136     }
137 }