8080#define PCI_ENUM_TYPE_64bit (0x1 << 1)
8181#define PCI_ENUM_TYPE_32bit (0x1)
8282#define PCI_ENUM_IS_PREFETCH (0x1 << 3)
83- #define PCI_ENUM_MM_BAR_MASK ~(0xf )
84- #define PCI_ENUM_IO_BAR_MASK ~(0x3 )
83+ #define PCI_ENUM_MM_BAR_MASK (~0xfU )
84+ #define PCI_ENUM_IO_BAR_MASK (~0x3U )
8585
8686#define CAPID0_A_0_0_0_PCI (0xE4)
8787#define DEVICE_ENABLE (0x54)
@@ -139,8 +139,8 @@ static uint32_t pci_align32_address(uint32_t addr, int *aligned)
139139static uint32_t pci_config_ecam_make_address (uint8_t bus , uint8_t dev ,
140140 uint8_t func , uint8_t off )
141141{
142- return ( PCI_ECAM_BASE +
143- ((bus & 0xff ) << 20 ) |
142+ return PCI_ECAM_BASE +
143+ ( ((bus & 0xff ) << 20 ) |
144144 ((dev & 0x1f ) << 15 ) |
145145 ((func & 0x07 ) << 12 ) |
146146 (off & 0xfff ));
@@ -198,11 +198,11 @@ static void pci_ecam_config_write16(uint8_t bus, uint8_t dev, uint8_t fun,
198198#define PCI_IO_CONFIG_ADDR (bus , dev , fn , off ) \
199199 (uint32_t)( \
200200 (1UL << PCI_CONFIG_ADDRESS_ENABLE_BIT_SHIFT) | \
201- (bus << PCI_CONFIG_ADDRESS_BUS_SHIFT) | \
202- (dev << PCI_CONFIG_ADDRESS_DEVICE_SHIFT) | \
203- (fn << PCI_CONFIG_ADDRESS_FUNCTION_SHIFT) | \
204- ((off & 0xF00) << 16) | \
205- (off & PCI_CONFIG_ADDRESS_OFFSET_MASK))
201+ (( bus) << PCI_CONFIG_ADDRESS_BUS_SHIFT) | \
202+ (( dev) << PCI_CONFIG_ADDRESS_DEVICE_SHIFT) | \
203+ ((fn) << PCI_CONFIG_ADDRESS_FUNCTION_SHIFT) | \
204+ ((( off) & 0xF00) << 16) | \
205+ (( off) & PCI_CONFIG_ADDRESS_OFFSET_MASK))
206206
207207static uint32_t pci_io_config_read32 (uint32_t bus , uint32_t dev , uint32_t func ,
208208 uint32_t off )
@@ -227,44 +227,44 @@ static void pci_io_config_write32(uint32_t bus, uint32_t dev, uint32_t func,
227227static uint16_t pci_io_config_read16 (uint32_t bus , uint32_t dev , uint32_t func ,
228228 uint32_t off )
229229{
230- uint32_t address = PCI_IO_CONFIG_ADDR (bus , dev , func , off );
231- uint32_t data = 0xffff ;
230+ uint32_t data ;
232231 int aligned32 ;
232+ uint32_t off_aligned ;
233233
234234 /* off must be 16 bit aligned */
235- if ((address & PCI_ADDR_16BIT_ALIGNED_MASK ) != 0 )
236- return data ;
235+ if ((off & PCI_ADDR_16BIT_ALIGNED_MASK ) != 0 )
236+ return 0xffff ;
237237
238- address = pci_align32_address (address , & aligned32 );
239- data = pci_io_config_read32 (bus , dev , func , address );
240- if (!aligned32 )
241- data >>= PCI_DATA_HI16_SHIFT ;
242- else
238+ off_aligned = pci_align32_address (off , & aligned32 );
239+ data = pci_io_config_read32 (bus , dev , func , off_aligned );
240+ if (aligned32 )
243241 data &= PCI_DATA_LO16_MASK ;
242+ else
243+ data >>= PCI_DATA_HI16_SHIFT ;
244244 return (uint16_t )data ;
245245}
246246
247247static void pci_io_config_write16 (uint32_t bus , uint32_t dev , uint32_t func ,
248248 uint32_t off , uint16_t val )
249249{
250- uint32_t dst_addr = PCI_IO_CONFIG_ADDR ( bus , dev , func , off ) ;
250+ uint32_t off_aligned ;
251251 uint32_t reg ;
252252 int aligned32 ;
253253
254254 /* off must be 16 bit aligned */
255- if ((dst_addr & PCI_ADDR_16BIT_ALIGNED_MASK ) != 0 )
255+ if ((off & PCI_ADDR_16BIT_ALIGNED_MASK ) != 0 )
256256 return ;
257257
258- dst_addr = pci_align32_address (dst_addr , & aligned32 );
259- reg = pci_io_config_read32 (bus , dev , func , dst_addr );
258+ off_aligned = pci_align32_address (off , & aligned32 );
259+ reg = pci_io_config_read32 (bus , dev , func , off_aligned );
260260 if (aligned32 ) {
261261 reg &= PCI_DATA_HI16_MASK ;
262262 reg |= val ;
263263 } else {
264264 reg &= PCI_DATA_LO16_MASK ;
265265 reg |= (val << PCI_DATA_HI16_SHIFT );
266266 }
267- pci_io_config_write32 (bus , dev , func , dst_addr , reg );
267+ pci_io_config_write32 (bus , dev , func , off_aligned , reg );
268268}
269269#endif /* PCI_USE_ECAM */
270270
@@ -337,35 +337,7 @@ uint8_t pci_config_read8(uint8_t bus, uint8_t dev, uint8_t fun, uint8_t off)
337337 return reg ;
338338}
339339
340- uint64_t pci_get_mmio_addr (uint8_t bus , uint8_t dev , uint8_t fun , uint8_t bar )
341- {
342- uint32_t reg ;
343- uint64_t addr = 0 ;
344340
345- if (bar >= PCI_ENUM_MAX_BARS )
346- {
347- return addr ;
348- }
349-
350- reg = pci_config_read32 (bus , dev , fun , PCI_BAR0_OFFSET + (bar * 8 ));
351- wolfBoot_printf ("BAR%d[0x%x] reg value = 0x%x\r\n" , bar , PCI_BAR0_OFFSET + (bar * 8 ), reg );
352-
353- if (!pci_enum_is_mmio (reg ))
354- {
355- return addr ;
356- }
357-
358- addr = reg & 0xFFFFFFF0 ;
359-
360- if (pci_enum_is_64bit (reg ))
361- {
362- reg = pci_config_read32 (bus , dev , fun , (PCI_BAR0_OFFSET + 4 ) + (bar * 8 ));
363- wolfBoot_printf ("BAR%d_HIGH[0x%x] reg value = 0x%x\r\n" , bar , (PCI_BAR0_OFFSET + 4 ) + (bar * 8 ), reg );
364- addr |= ((uint64_t )reg << 32 );
365- }
366-
367- return addr ;
368- }
369341
370342static int pci_enum_is_64bit (uint32_t value )
371343{
@@ -470,16 +442,23 @@ static int pci_program_bar(uint8_t bus, uint8_t dev, uint8_t fun,
470442 bar_align = bar_value & PCI_ENUM_MM_BAR_MASK ;
471443 is_prefetch = pci_enum_is_prefetch (bar_value );
472444 if (pci_enum_is_64bit (bar_value )) {
445+ * is_64bit = 1 ;
473446 orig_bar2 = pci_config_read32 (bus , dev , fun , bar_off + 4 );
447+
448+ /* rewrite 0xff..ff mask and re-read the first BAR value, specs
449+ * requires to write the mask on both registers before reading
450+ * the sizes back */
451+ pci_config_write32 (bus , dev , fun , bar_off , 0xffffffff );
474452 pci_config_write32 (bus , dev , fun , bar_off + 4 , 0xffffffff );
453+ bar_value = pci_config_read32 (bus , dev , fun , bar_off );
454+ bar_align = bar_value & PCI_ENUM_MM_BAR_MASK ;
475455 reg = pci_config_read32 (bus , dev , fun , bar_off + 4 );
476456 PCI_DEBUG_PRINTF ("bar high 32bit: %d\r\n" , reg );
477457 if (reg != 0xffffffff ) {
478458 PCI_DEBUG_PRINTF ("Device wants too much memory, skipping\r\n" );
479459 pci_config_write32 (bus , dev , fun , bar_off + 4 , orig_bar2 );
480460 goto restore_bar ;
481461 }
482- * is_64bit = 1 ;
483462 }
484463 if (is_prefetch ) {
485464 base = & info -> mem_pf ;
@@ -510,7 +489,7 @@ static int pci_program_bar(uint8_t bus, uint8_t dev, uint8_t fun,
510489 /* check max length */
511490 ret = pci_enum_next_aligned32 (* base , & bar_value , align , limit );
512491 if (ret != 0 ) {
513- wolfBoot_printf ("Not memory space for mapping the PCI device... skipping\r\n" );
492+ PCI_DEBUG_PRINTF ("Not memory space for mapping the PCI device... skipping\r\n" );
514493 goto restore_bar ;
515494 }
516495
@@ -526,7 +505,7 @@ static int pci_program_bar(uint8_t bus, uint8_t dev, uint8_t fun,
526505 return 0 ;
527506
528507restore_bar :
529- pci_config_write32 (bus , dev , fun , bar_idx , orig_bar );
508+ pci_config_write32 (bus , dev , fun , bar_off , orig_bar );
530509
531510 return ret ;
532511}
@@ -612,8 +591,17 @@ static int pci_program_bridge(uint8_t bus, uint8_t dev, uint8_t fun,
612591 uint32_t mem_start ;
613592 uint32_t io_start ;
614593 uint32_t orig_cmd ;
594+ uint8_t saved_bus ;
595+ uint32_t saved_mem ;
596+ uint32_t saved_pf ;
597+ uint32_t saved_io ;
615598 int ret ;
616599
600+ saved_bus = info -> curr_bus_number ;
601+ saved_mem = info -> mem ;
602+ saved_pf = info -> mem_pf ;
603+ saved_io = info -> io ;
604+
617605 orig_cmd = pci_config_read16 (bus , dev , fun , PCI_COMMAND_OFFSET );
618606 pci_config_write16 (bus , dev , fun , PCI_COMMAND_OFFSET , 0 );
619607
@@ -627,6 +615,8 @@ static int pci_program_bridge(uint8_t bus, uint8_t dev, uint8_t fun,
627615 * (curr_bus_number,0xff) to scan the bus behind the bridge */
628616 pci_config_write8 (bus , dev , fun , PCI_SUB_SEC_BUS , 0xff );
629617
618+ /* PCI bridge window registers enforce alignment constraints from the spec:
619+ * prefetch and MMIO windows are 1MB-aligned, IO windows are 4KB-aligned. */
630620 ret = pci_align_check_up (info -> mem_pf , ONE_MB ,
631621 info -> mem_pf_limit ,
632622 & prefetch_start );
@@ -655,7 +645,10 @@ static int pci_program_bridge(uint8_t bus, uint8_t dev, uint8_t fun,
655645 * bridge */
656646 pci_config_write8 (bus , dev , fun , PCI_SUB_SEC_BUS , info -> curr_bus_number );
657647
658- /* upate prefetch range */
648+ /* PCI bridge window registers enforce alignment constraints from the spec:
649+ * prefetch and MMIO windows are 1MB-aligned, IO windows are 4KB-aligned.
650+ * After enumeration, the end of each window must also be aligned up to meet
651+ * these granularity requirements. */
659652 if (prefetch_start != info -> mem_pf ) {
660653 ret = pci_align_check_up (info -> mem_pf , ONE_MB ,
661654 info -> mem_pf_limit ,
@@ -722,11 +715,18 @@ static int pci_program_bridge(uint8_t bus, uint8_t dev, uint8_t fun,
722715 return 0 ;
723716
724717 err :
718+ info -> curr_bus_number = saved_bus ;
719+ info -> mem = saved_mem ;
720+ info -> mem_pf = saved_pf ;
721+ info -> io = saved_io ;
722+ pci_config_write8 (bus , dev , fun , PCI_PRIMARY_BUS , 0 );
723+ pci_config_write8 (bus , dev , fun , PCI_SECONDARY_BUS , 0 );
724+ pci_config_write8 (bus , dev , fun , PCI_SUB_SEC_BUS , 0 );
725725 pci_config_write16 (bus , dev , fun , PCI_COMMAND_OFFSET , orig_cmd );
726726 return -1 ;
727727}
728728
729- uint32_t pci_enum_bus (uint8_t bus , struct pci_enum_info * info )
729+ int pci_enum_bus (uint8_t bus , struct pci_enum_info * info )
730730{
731731 uint16_t header_type ;
732732 uint32_t vd_code ;
@@ -781,16 +781,16 @@ int pci_pre_enum(void)
781781 uint32_t reg ;
782782
783783 reg = pci_config_read32 (0 , 0 , 0 , CAPID0_A_0_0_0_PCI );
784- wolfBoot_printf ("cap a %d\r\n" , reg );
785- wolfBoot_printf ("ddt disabled %d\r\n" , reg & DTT_DEVICE_DISABLE );
784+ PCI_DEBUG_PRINTF ("cap a %d\r\n" , reg );
785+ PCI_DEBUG_PRINTF ("ddt disabled %d\r\n" , reg & DTT_DEVICE_DISABLE );
786786 reg &= ~(DTT_DEVICE_DISABLE );
787787 pci_config_write32 (0 , 0 , 0 , CAPID0_A_0_0_0_PCI , reg );
788788 reg = pci_config_read32 (0 , 0 , 0 , DEVICE_ENABLE );
789- wolfBoot_printf ("device enable: %d\r\n" , reg );
789+ PCI_DEBUG_PRINTF ("device enable: %d\r\n" , reg );
790790 reg |= (1 << 7 );
791791 pci_config_write32 (0 , 0 , 0 , DEVICE_ENABLE , reg );
792792 reg = pci_config_read32 (0 , 0 , 0 , DEVICE_ENABLE );
793- wolfBoot_printf ("device enable: %d\r\n" , reg );
793+ PCI_DEBUG_PRINTF ("device enable: %d\r\n" , reg );
794794
795795 return 0 ;
796796}
@@ -817,11 +817,11 @@ void pci_dump(uint8_t bus, uint8_t dev, uint8_t fun)
817817 for (i = 0 ; i < 256 ; i ++ ) {
818818 if (i % 0x10 == 0x0 ) {
819819 if (i < 0x10 ) {
820- wolfBoot_printf ("0" );
820+ PCI_DEBUG_PRINTF ("0" );
821821 }
822- wolfBoot_printf ("%x: " , (int )i );
822+ PCI_DEBUG_PRINTF ("%x: " , (int )i );
823823 }
824- wolfBoot_printf ("%s%x%s" , (ptr [i ] < 0x10 ? "0" :"" ), (int )ptr [i ],
824+ PCI_DEBUG_PRINTF ("%s%x%s" , (ptr [i ] < 0x10 ? "0" :"" ), (int )ptr [i ],
825825 (i % 0x10 == 0xf ? "\r\n" :" " ));
826826 }
827827}
@@ -856,12 +856,12 @@ static void pci_dump_bus(uint8_t bus)
856856 }
857857
858858 if (bus < 0x10 )
859- wolfBoot_printf ("0" );
860- wolfBoot_printf ("%x:" , bus );
859+ PCI_DEBUG_PRINTF ("0" );
860+ PCI_DEBUG_PRINTF ("%x:" , bus );
861861 if (dev < 0x10 )
862- wolfBoot_printf ("0" );
863- wolfBoot_printf ("%x." , dev );
864- wolfBoot_printf ("%d \r\n" , fun );
862+ PCI_DEBUG_PRINTF ("0" );
863+ PCI_DEBUG_PRINTF ("%x." , dev );
864+ PCI_DEBUG_PRINTF ("%d \r\n" , fun );
865865 pci_dump (bus , dev , fun );
866866 header_type = pci_config_read16 (bus , dev , fun ,
867867 PCI_HEADER_TYPE_OFFSET );
@@ -906,7 +906,7 @@ int pci_enum_do(void)
906906
907907 ret = pci_pre_enum ();
908908 if (ret != 0 ) {
909- wolfBoot_printf ("pci_pre_enum error: %d\r\n" , ret );
909+ PCI_DEBUG_PRINTF ("pci_pre_enum error: %d\r\n" , ret );
910910 return ret ;
911911 }
912912
0 commit comments