1 #include "pci.h"
2 #include <common/kprint.h>
3 #include <mm/slab.h>
4 #include <debug/bug.h>
5 #include <common/errno.h>
6 
7 static uint count_device_list = 0;
8 static void pci_checkBus(uint8_t bus);
9 
10 /**
11  * @brief 将设备信息结构体加到链表里面
12  *
13  */
14 #define ADD_DEVICE_STRUCT_TO_LIST(ret)                                \
15     do                                                                \
16     {                                                                 \
17         if (count_device_list > 0)                                    \
18         {                                                             \
19             ++count_device_list;                                      \
20             list_add(pci_device_structure_list, &(ret->header.list)); \
21         }                                                             \
22         else                                                          \
23         {                                                             \
24             ++count_device_list;                                      \
25             list_init(&(ret->header.list));                           \
26             pci_device_structure_list = &(ret->header.list);          \
27         }                                                             \
28     } while (0)
29 
30 
31 /**
32  * @brief 从pci配置空间读取信息
33  *
34  * @param bus 总线号
35  * @param slot 设备号
36  * @param func 功能号
37  * @param offset 字节偏移量
38  * @return uint 寄存器值
39  */
pci_read_config(uchar bus,uchar slot,uchar func,uchar offset)40 uint32_t pci_read_config(uchar bus, uchar slot, uchar func, uchar offset)
41 {
42     uint lbus = (uint)bus;
43     uint lslot = (uint)slot;
44     uint lfunc = ((uint)func) & 7;
45 
46     // 构造pci配置空间地址
47     uint address = (uint)((lbus << 16) | (lslot << 11) | (lfunc << 8) | (offset & 0xfc) | ((uint)0x80000000));
48     io_out32(PORT_PCI_CONFIG_ADDRESS, address);
49     // 读取返回的数据
50     uint32_t ret = (uint)(io_in32(PORT_PCI_CONFIG_DATA));
51 
52     return ret;
53 }
54 
55 /**
56  * @brief 向pci配置空间写入信息
57  *
58  * @param bus 总线号
59  * @param slot 设备号
60  * @param func 功能号
61  * @param offset 字节偏移量
62  * @return uint 返回码
63  */
pci_write_config(uchar bus,uchar slot,uchar func,uchar offset,uint32_t data)64 uint pci_write_config(uchar bus, uchar slot, uchar func, uchar offset, uint32_t data)
65 {
66     uint lbus = (uint)bus;
67     uint lslot = (uint)slot;
68     uint lfunc = ((uint)func) & 7;
69 
70     // 构造pci配置空间地址
71     uint address = (uint)((lbus << 16) | (lslot << 11) | (lfunc << 8) | (offset & 0xfc) | ((uint)0x80000000));
72     io_out32(PORT_PCI_CONFIG_ADDRESS, address);
73 
74     // 写入数据
75     io_out32(PORT_PCI_CONFIG_DATA, data);
76 
77     return 0;
78 }
79 
80 /**
81  * @brief 读取type为0x0的pci设备的header
82  * 本函数只应被 pci_read_header()调用
83  * @param header 返回的header
84  * @param bus 总线号
85  * @param slot 插槽号
86  * @param func 功能号
87  */
pci_read_general_device_header(struct pci_device_structure_general_device_t * header,uchar bus,uchar slot,uchar func)88 static void pci_read_general_device_header(struct pci_device_structure_general_device_t *header, uchar bus, uchar slot, uchar func)
89 {
90     uint32_t tmp32;
91     header->BAR0 = pci_read_config(bus, slot, func, 0x10);
92     header->BAR1 = pci_read_config(bus, slot, func, 0x14);
93     header->BAR2 = pci_read_config(bus, slot, func, 0x18);
94     header->BAR3 = pci_read_config(bus, slot, func, 0x1c);
95     header->BAR4 = pci_read_config(bus, slot, func, 0x20);
96     header->BAR5 = pci_read_config(bus, slot, func, 0x24);
97     header->Cardbus_CIS_Pointer = pci_read_config(bus, slot, func, 0x28);
98 
99     tmp32 = pci_read_config(bus, slot, func, 0x2c);
100     header->Subsystem_Vendor_ID = tmp32 & 0xffff;
101     header->Subsystem_ID = (tmp32 >> 16) & 0xffff;
102 
103     header->Expansion_ROM_base_address = pci_read_config(bus, slot, func, 0x30);
104 
105     tmp32 = pci_read_config(bus, slot, func, 0x34);
106     header->Capabilities_Pointer = tmp32 & 0xff;
107     header->reserved0 = (tmp32 >> 8) & 0xff;
108     header->reserved1 = (tmp32 >> 16) & 0xffff;
109 
110     header->reserved2 = pci_read_config(bus, slot, func, 0x38);
111 
112     tmp32 = pci_read_config(bus, slot, func, 0x3c);
113     header->Interrupt_Line = tmp32 & 0xff;
114     header->Interrupt_PIN = (tmp32 >> 8) & 0xff;
115     header->Min_Grant = (tmp32 >> 16) & 0xff;
116     header->Max_Latency = (tmp32 >> 24) & 0xff;
117 }
118 
119 /**
120  * @brief 读取type为0x1的pci_to_pci_bridge的header
121  * 本函数只应被 pci_read_header()调用
122  * @param header 返回的header
123  * @param bus 总线号
124  * @param slot 插槽号
125  * @param func 功能号
126  */
pci_read_pci_to_pci_bridge_header(struct pci_device_structure_pci_to_pci_bridge_t * header,uchar bus,uchar slot,uchar func)127 static void pci_read_pci_to_pci_bridge_header(struct pci_device_structure_pci_to_pci_bridge_t *header, uchar bus, uchar slot, uchar func)
128 {
129     uint32_t tmp32;
130     header->BAR0 = pci_read_config(bus, slot, func, 0x10);
131     header->BAR1 = pci_read_config(bus, slot, func, 0x14);
132 
133     tmp32 = pci_read_config(bus, slot, func, 0x18);
134 
135     header->Primary_Bus_Number = tmp32 & 0xff;
136     header->Secondary_Bus_Number = (tmp32 >> 8) & 0xff;
137     header->Subordinate_Bus_Number = (tmp32 >> 16) & 0xff;
138     header->Secondary_Latency_Timer = (tmp32 >> 24) & 0xff;
139 
140     tmp32 = pci_read_config(bus, slot, func, 0x1c);
141     header->io_base = tmp32 & 0xff;
142     header->io_limit = (tmp32 >> 8) & 0xff;
143     header->Secondary_Status = (tmp32 >> 16) & 0xffff;
144 
145     tmp32 = pci_read_config(bus, slot, func, 0x20);
146     header->Memory_Base = tmp32 & 0xffff;
147     header->Memory_Limit = (tmp32 >> 16) & 0xffff;
148 
149     tmp32 = pci_read_config(bus, slot, func, 0x24);
150     header->Prefetchable_Memory_Base = tmp32 & 0xffff;
151     header->Prefetchable_Memory_Limit = (tmp32 >> 16) & 0xffff;
152 
153     header->Prefetchable_Base_Upper_32_Bits = pci_read_config(bus, slot, func, 0x28);
154     header->Prefetchable_Limit_Upper_32_Bits = pci_read_config(bus, slot, func, 0x2c);
155 
156     tmp32 = pci_read_config(bus, slot, func, 0x30);
157     header->io_Base_Upper_16_Bits = tmp32 & 0xffff;
158     header->io_Limit_Upper_16_Bits = (tmp32 >> 16) & 0xffff;
159 
160     tmp32 = pci_read_config(bus, slot, func, 0x34);
161     header->Capability_Pointer = tmp32 & 0xff;
162     header->reserved0 = (tmp32 >> 8) & 0xff;
163     header->reserved1 = (tmp32 >> 16) & 0xffff;
164 
165     header->Expansion_ROM_base_address = pci_read_config(bus, slot, func, 0x38);
166 
167     tmp32 = pci_read_config(bus, slot, func, 0x3c);
168     header->Interrupt_Line = tmp32 & 0xff;
169     header->Interrupt_PIN = (tmp32 >> 8) & 0xff;
170     header->Bridge_Control = (tmp32 >> 16) & 0xffff;
171 }
172 
173 /**
174  * @brief 读取type为0x2的pci_to_cardbus_bridge的header
175  * 本函数只应被 pci_read_header()调用
176  * @param header 返回的header
177  * @param bus 总线号
178  * @param slot 插槽号
179  * @param func 功能号
180  */
pci_read_pci_to_cardbus_bridge_header(struct pci_device_structure_pci_to_cardbus_bridge_t * header,uchar bus,uchar slot,uchar func)181 static void pci_read_pci_to_cardbus_bridge_header(struct pci_device_structure_pci_to_cardbus_bridge_t *header, uchar bus, uchar slot, uchar func)
182 {
183     uint32_t tmp32;
184 
185     header->CardBus_Socket_ExCa_base_address = pci_read_config(bus, slot, func, 0x10);
186 
187     tmp32 = pci_read_config(bus, slot, func, 0x14);
188     header->Offset_of_capabilities_list = tmp32 & 0xff;
189     header->Reserved = (tmp32 >> 8) & 0xff;
190     header->Secondary_status = (tmp32 >> 16) & 0xff;
191 
192     tmp32 = pci_read_config(bus, slot, func, 0x18);
193     header->PCI_bus_number = tmp32 & 0xff;
194     header->CardBus_bus_number = (tmp32 >> 8) & 0xff;
195     header->Subordinate_bus_number = (tmp32 >> 16) & 0xff;
196     header->CardBus_latency_timer = (tmp32 >> 24) & 0xff;
197 
198     header->Memory_Base_Address0 = pci_read_config(bus, slot, func, 0x1c);
199     header->Memory_Limit0 = pci_read_config(bus, slot, func, 0x20);
200     header->Memory_Base_Address1 = pci_read_config(bus, slot, func, 0x24);
201     header->Memory_Limit1 = pci_read_config(bus, slot, func, 0x28);
202 
203     header->IO_Base_Address0 = pci_read_config(bus, slot, func, 0x2c);
204     header->IO_Limit0 = pci_read_config(bus, slot, func, 0x30);
205     header->IO_Base_Address1 = pci_read_config(bus, slot, func, 0x34);
206     header->IO_Limit1 = pci_read_config(bus, slot, func, 0x38);
207 
208     tmp32 = pci_read_config(bus, slot, func, 0x3c);
209     header->Interrupt_Line = tmp32 & 0xff;
210     header->Interrupt_PIN = (tmp32 >> 8) & 0xff;
211     header->Bridge_Control = (tmp32 >> 16) & 0xffff;
212 
213     tmp32 = pci_read_config(bus, slot, func, 0x40);
214     header->Subsystem_Device_ID = tmp32 & 0xffff;
215     header->Subsystem_Vendor_ID = (tmp32 >> 16) & 0xffff;
216 
217     header->PC_Card_legacy_mode_base_address_16_bit = pci_read_config(bus, slot, func, 0x44);
218 }
219 
220 /**
221  * @brief 读取pci设备标头
222  *
223  * @param type 标头类型
224  * @param bus 总线号
225  * @param slot 插槽号
226  * @param func 功能号
227  * @param add_to_list 添加到链表
228  * @return 返回的header
229  */
pci_read_header(int * type,uchar bus,uchar slot,uchar func,bool add_to_list)230 void *pci_read_header(int *type, uchar bus, uchar slot, uchar func, bool add_to_list)
231 {
232     struct pci_device_structure_header_t *common_header = (struct pci_device_structure_header_t *)kmalloc(127, 0);
233     common_header->bus = bus;
234     common_header->device = slot;
235     common_header->func = func;
236 
237     uint32_t tmp32;
238     // 先读取公共header
239     tmp32 = pci_read_config(bus, slot, func, 0x0);
240     common_header->Vendor_ID = tmp32 & 0xffff;
241     common_header->Device_ID = (tmp32 >> 16) & 0xffff;
242 
243     tmp32 = pci_read_config(bus, slot, func, 0x4);
244     common_header->Command = tmp32 & 0xffff;
245     common_header->Status = (tmp32 >> 16) & 0xffff;
246 
247     tmp32 = pci_read_config(bus, slot, func, 0x8);
248     common_header->RevisionID = tmp32 & 0xff;
249     common_header->ProgIF = (tmp32 >> 8) & 0xff;
250     common_header->SubClass = (tmp32 >> 16) & 0xff;
251     common_header->Class_code = (tmp32 >> 24) & 0xff;
252 
253     tmp32 = pci_read_config(bus, slot, func, 0xc);
254     common_header->CacheLineSize = tmp32 & 0xff;
255     common_header->LatencyTimer = (tmp32 >> 8) & 0xff;
256     common_header->HeaderType = (tmp32 >> 16) & 0xff;
257     common_header->BIST = (tmp32 >> 24) & 0xff;
258 
259     void *ret;
260     if (common_header->Vendor_ID == 0xffff)
261     {
262         *type = -ENXIO;
263         kfree(common_header);
264         return NULL;
265     }
266 
267     // 根据公共头部,判断该结构所属的类型
268     switch (common_header->HeaderType)
269     {
270     case 0x0: // general device
271         ret = common_header;
272 
273         pci_read_general_device_header((struct pci_device_structure_general_device_t *)ret, bus, slot, func);
274         if (add_to_list)
275             ADD_DEVICE_STRUCT_TO_LIST(((struct pci_device_structure_general_device_t *)ret));
276 
277         *type = 0x0;
278         return ret;
279         break;
280     case 0x1:
281         ret = common_header;
282         pci_read_pci_to_pci_bridge_header((struct pci_device_structure_pci_to_pci_bridge_t *)ret, bus, slot, func);
283         if (add_to_list)
284             ADD_DEVICE_STRUCT_TO_LIST(((struct pci_device_structure_pci_to_pci_bridge_t *)ret));
285 
286         *type = 0x1;
287         return ret;
288         break;
289     case 0x2:
290         ret = common_header;
291         pci_read_pci_to_cardbus_bridge_header((struct pci_device_structure_pci_to_cardbus_bridge_t *)ret, bus, slot, func);
292         if (add_to_list)
293             ADD_DEVICE_STRUCT_TO_LIST(((struct pci_device_structure_pci_to_cardbus_bridge_t *)ret));
294 
295         *type = 0x2;
296         return ret;
297         break;
298     default: // 错误的头类型 这里不应该被执行
299         // kerror("PCI->pci_read_header(): Invalid header type.");
300         *type = -EINVAL;
301         // kerror("vendor id=%#010lx", common_header->Vendor_ID);
302         // kerror("header type = %d", common_header->HeaderType);
303         kfree(common_header);
304         return NULL;
305         break;
306     }
307 }
pci_checkFunction(uint8_t bus,uint8_t device,uint8_t function)308 static void pci_checkFunction(uint8_t bus, uint8_t device, uint8_t function)
309 {
310     int header_type;
311     struct pci_device_structure_header_t *header = pci_read_header(&header_type, bus, device, function, true);
312 
313     if (header_type == -EINVAL)
314     {
315         // kerror("pci_checkFunction(): wrong header type!");
316         //  此处内存已经在read header函数里面释放,不用重复释放
317         return;
318     }
319     // header = ((struct pci_device_structure_general_device_t *)raw_header)->header;
320 
321     if ((header->Class_code == 0x6) && (header->SubClass == 0x4))
322     {
323         uint8_t SecondaryBus = ((struct pci_device_structure_pci_to_pci_bridge_t *)header)->Secondary_Bus_Number;
324         pci_checkBus(SecondaryBus);
325     }
326 }
327 
pci_checkDevice(uint8_t bus,uint8_t device)328 static int pci_checkDevice(uint8_t bus, uint8_t device)
329 {
330     int header_type;
331 
332     struct pci_device_structure_header_t *header = pci_read_header(&header_type, bus, device, 0, false);
333     if (header_type == -EINVAL)
334     {
335         // 此处内存已经在read header函数里面释放,不用重复释放
336         return -EINVAL;
337     }
338     if (header_type == -ENXIO)
339     {
340         // kerror("DEVICE INVALID");
341         return -ENXIO;
342     }
343 
344     uint16_t vendorID = header->Vendor_ID;
345 
346     if (vendorID == 0xffff) // 设备不存在
347     {
348         kfree(header);
349         return -ENXIO;
350     }
351     pci_checkFunction(bus, device, 0);
352 
353     header_type = header->HeaderType;
354     if ((header_type & 0x80) != 0)
355     {
356         kdebug("Multi func device");
357         // 这是一个多function的设备,因此查询剩余的function
358         for (uint8_t func = 1; func < 8; ++func)
359         {
360             struct pci_device_structure_header_t *tmp_header;
361             tmp_header = (struct pci_device_structure_header_t *)pci_read_header(&header_type, bus, device, func, false);
362 
363             if (tmp_header->Vendor_ID != 0xffff)
364                 pci_checkFunction(bus, device, func);
365 
366             // 释放内存
367             kfree(tmp_header);
368         }
369     }
370 
371     kfree(header);
372     return 0;
373 }
374 
pci_checkBus(uint8_t bus)375 static void pci_checkBus(uint8_t bus)
376 {
377     for (uint8_t device = 0; device < 32; ++device)
378     {
379         pci_checkDevice(bus, device);
380     }
381 }
382 
383 /**
384  * @brief 扫描所有pci总线上的所有设备
385  *
386  */
pci_checkAllBuses()387 void pci_checkAllBuses()
388 {
389     kinfo("Checking all devices in PCI bus...");
390     int header_type;
391     struct pci_device_structure_header_t *header = pci_read_header(&header_type, 0, 0, 0, false);
392 
393     if (header_type == EINVAL)
394     {
395         kBUG("pci_checkAllBuses(): wrong header type!");
396         // 此处内存已经在read header函数里面释放,不用重复释放
397         return;
398     }
399 
400     header_type = header->HeaderType;
401 
402     if ((header_type & 0x80) == 0) // Single pci host controller
403     {
404         pci_checkBus(0);
405     }
406     else
407     {
408         // Multiple PCI host controller
409         // 那么总线0,设备0,功能1则是总线1的pci主机控制器,以此类推
410         struct pci_device_structure_header_t *tmp_header;
411         for (uint8_t func = 0; func < 8; ++func)
412         {
413             tmp_header = (struct pci_device_structure_header_t *)pci_read_header(&header_type, 0, 0, func, false);
414 
415             if (WARN_ON(header->Vendor_ID != 0xffff)) // @todo 这里的判断条件可能有点问题
416             {
417                 kfree(tmp_header);
418                 break;
419             }
420 
421             pci_checkBus(func);
422 
423             kfree(tmp_header);
424         }
425     }
426     kfree(header);
427 }
428 
pci_init()429 void pci_init()
430 {
431     kinfo("Initializing PCI bus...");
432     pci_checkAllBuses();
433     kinfo("Total pci device and function num = %d", count_device_list);
434 
435     struct pci_device_structure_header_t *ptr = container_of(pci_device_structure_list, struct pci_device_structure_header_t, list);
436     for (int i = 0; i < count_device_list; ++i)
437     {
438         if (ptr->HeaderType == 0x0)
439         {
440             if (ptr->Status & 0x10)
441             {
442                 kinfo("[ pci device %d ] class code = %d\tsubclass=%d\tstatus=%#010lx\tcap_pointer=%#010lx\tbar5=%#010lx, vendor=%#08x, device id=%#08x", i, ptr->Class_code, ptr->SubClass, ptr->Status, ((struct pci_device_structure_general_device_t *)ptr)->Capabilities_Pointer, ((struct pci_device_structure_general_device_t *)ptr)->BAR5,
443                                                                                                                                                             ptr->Vendor_ID, ptr->Device_ID);
444                 uint32_t tmp = pci_read_config(ptr->bus, ptr->device, ptr->func, ((struct pci_device_structure_general_device_t *)ptr)->Capabilities_Pointer);
445             }
446             else
447             {
448 
449                 kinfo("[ pci device %d ] class code = %d\tsubclass=%d\tstatus=%#010lx\t", i, ptr->Class_code, ptr->SubClass, ptr->Status);
450             }
451         }
452         else if (ptr->HeaderType == 0x1)
453         {
454             if (ptr->Status & 0x10)
455             {
456                 kinfo("[ pci device %d ] class code = %d\tsubclass=%d\tstatus=%#010lx\tcap_pointer=%#010lx", i, ptr->Class_code, ptr->SubClass, ptr->Status, ((struct pci_device_structure_pci_to_pci_bridge_t *)ptr)->Capability_Pointer);
457             }
458             else
459             {
460 
461                 kinfo("[ pci device %d ] class code = %d\tsubclass=%d\tstatus=%#010lx\t", i, ptr->Class_code, ptr->SubClass, ptr->Status);
462             }
463         }
464         else if (ptr->HeaderType == 0x2)
465         {
466             kinfo("[ pci device %d ] class code = %d\tsubclass=%d\tstatus=%#010lx\t", i, ptr->Class_code, ptr->SubClass, ptr->Status);
467         }
468 
469         ptr = container_of(list_next(&(ptr->list)), struct pci_device_structure_header_t, list);
470     }
471     kinfo("PCI bus initialized.");
472 }
473 
474 
475 /**
476  * @brief 获取 device structure
477  *
478  * @param class_code
479  * @param sub_class
480  * @param res 返回的结果数组
481  */
pci_get_device_structure(uint8_t class_code,uint8_t sub_class,struct pci_device_structure_header_t * res[],uint32_t * count_res)482 void pci_get_device_structure(uint8_t class_code, uint8_t sub_class, struct pci_device_structure_header_t *res[], uint32_t *count_res)
483 {
484 
485     struct pci_device_structure_header_t *ptr = container_of(pci_device_structure_list, struct pci_device_structure_header_t, list);
486     *count_res = 0;
487 
488     for (int i = 0; i < count_device_list; ++i)
489     {
490         if ((ptr->Class_code == class_code) && (ptr->SubClass == sub_class))
491         {
492             kdebug("[%d]  class_code=%d, sub_class=%d, progIF=%d, bar5=%#010lx", i, ptr->Class_code, ptr->SubClass, ptr->ProgIF, ((struct pci_device_structure_general_device_t *)ptr)->BAR5);
493 
494             res[*count_res] = ptr;
495             ++(*count_res);
496         }
497         ptr = container_of(list_next(&(ptr->list)), struct pci_device_structure_header_t, list);
498     }
499 }
500 
501 /**
502  * @brief 寻找符合指定类型的capability list
503  *
504  * @param pci_dev pci设备header
505  * @param cap_type c要寻找的capability类型
506  * @return uint64_t cap list的偏移量
507  */
pci_enumerate_capability_list(struct pci_device_structure_header_t * pci_dev,uint32_t cap_type)508 int32_t pci_enumerate_capability_list(struct pci_device_structure_header_t *pci_dev, uint32_t cap_type)
509 {
510     uint32_t cap_offset;
511     switch (pci_dev->HeaderType)
512     {
513     case 0x00:
514 
515         cap_offset = ((struct pci_device_structure_general_device_t *)pci_dev)->Capabilities_Pointer;
516         break;
517 
518     case 0x10:
519         cap_offset = ((struct pci_device_structure_pci_to_pci_bridge_t *)pci_dev)->Capability_Pointer;
520         break;
521     default:
522         // 不支持
523         return -ENOSYS;
524     }
525     uint32_t tmp;
526     while (1)
527     {
528         tmp = pci_read_config(pci_dev->bus, pci_dev->device, pci_dev->func, cap_offset);
529         if ((tmp & 0xff) != cap_type)
530         {
531             if (((tmp & 0xff00) >> 8))
532             {
533                 cap_offset = (tmp & 0xff00)>>8;
534                 continue;
535             }
536             else
537                 return -ENOSYS;
538         }
539 
540         return cap_offset;
541     }
542 }