iPXE
pcibridge.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2022 Michael Brown <mbrown@fensystems.co.uk>.
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License as
6  * published by the Free Software Foundation; either version 2 of the
7  * License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  * General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17  * 02110-1301, USA.
18  *
19  * You can also choose to distribute this program under the terms of
20  * the Unmodified Binary Distribution Licence (as given in the file
21  * COPYING.UBDL), provided that you have satisfied its requirements.
22  */
23 
24 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
25 
26 #include <stddef.h>
27 #include <stdint.h>
28 #include <errno.h>
29 #include <byteswap.h>
30 #include <ipxe/pci.h>
31 #include <ipxe/pcibridge.h>
32 
33 /** @file
34  *
35  * PCI-to-PCI bridge
36  *
37  */
38 
39 /** List of all PCI bridges */
40 static LIST_HEAD ( pcibridges );
41 
42 /**
43  * Find bridge attached to a PCI device
44  *
45  * @v pci PCI device
46  * @ret bridge PCI bridge, or NULL
47  */
48 struct pci_bridge * pcibridge_find ( struct pci_device *pci ) {
49  unsigned int bus = PCI_BUS ( pci->busdevfn );
50  struct pci_bridge *bridge;
51 
52  /* Find matching bridge */
53  list_for_each_entry ( bridge, &pcibridges, list ) {
54  if ( bus == bridge->secondary )
55  return bridge;
56  }
57 
58  return NULL;
59 }
60 
61 /**
62  * Probe PCI device
63  *
64  * @v pci PCI device
65  * @ret rc Return status code
66  */
67 static int pcibridge_probe ( struct pci_device *pci ) {
68  struct pci_bridge *bridge;
69  uint16_t base;
71  int rc;
72 
73  /* Allocate and initialise structure */
74  bridge = zalloc ( sizeof ( *bridge ) );
75  if ( ! bridge ) {
76  rc = -ENOMEM;
77  goto err_alloc;
78  }
79  bridge->pci = pci;
80 
81  /* Read configuration */
83  cpu_to_le32s ( &buses );
85  bridge->membase = ( ( base & ~PCI_MEM_MASK ) << 16 );
87  bridge->memlimit = ( ( ( ( limit | PCI_MEM_MASK ) + 1 ) << 16 ) - 1 );
88  DBGC ( bridge, "BRIDGE " PCI_FMT " bus %02x to [%02x,%02x) mem "
89  "[%08x,%08x)\n", PCI_ARGS ( pci ), bridge->primary,
90  bridge->secondary, bridge->subordinate, bridge->membase,
91  bridge->memlimit );
92 
93  /* Add to list of PCI bridges */
94  list_add ( &bridge->list, &pcibridges );
95 
96  pci_set_drvdata ( pci, bridge );
97  return 0;
98 
99  free ( bridge );
100  err_alloc:
101  return rc;
102 }
103 
104 /**
105  * Remove PCI device
106  *
107  * @v pci PCI device
108  */
109 static void pcibridge_remove ( struct pci_device *pci ) {
110  struct pci_bridge *bridge = pci_get_drvdata ( pci );
111 
112  /* Remove from list of bridges */
113  list_del ( &bridge->list );
114 
115  /* Free device */
116  free ( bridge );
117 }
118 
119 /** Bridge PCI device IDs */
120 static struct pci_device_id pcibridge_ids[] = {
121  PCI_ROM ( 0xffff, 0xffff, "bridge", "Bridge", 0 ),
122 };
123 
124 /** Bridge PCI driver */
125 struct pci_driver pcibridge_driver __pci_driver = {
126  .ids = pcibridge_ids,
127  .id_count = ( sizeof ( pcibridge_ids ) / sizeof ( pcibridge_ids[0] ) ),
129  PCI_ANY_ID ),
130  .probe = pcibridge_probe,
131  .remove = pcibridge_remove,
132 };
#define PCI_MEM_BASE
Memory base and limit.
Definition: pci.h:152
#define PCI_BUS(busdevfn)
Definition: pci.h:279
#define PCI_CLASS_ID(base, sub, progif)
Construct PCI class ID.
Definition: pci.h:198
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
unsigned short uint16_t
Definition: stdint.h:11
A PCI driver.
Definition: pci.h:247
static struct pci_device_id pcibridge_ids[]
Bridge PCI device IDs.
Definition: pcibridge.c:120
uint8_t subordinate
Subordinate bus.
Definition: pcibridge.h:30
#define PCI_MEM_MASK
Definition: pci.h:154
#define PCI_CLASS_BRIDGE
Definition: Pci22.h:183
#define list_add(new, head)
Add a new entry to the head of a list.
Definition: list.h:69
#define PCI_CLASS_BRIDGE_PCI
PCI-to-PCI bridge.
Definition: pci.h:132
Error codes.
static int pcibridge_probe(struct pci_device *pci)
Probe PCI device.
Definition: pcibridge.c:67
#define PCI_MEM_LIMIT
Definition: pci.h:153
struct pci_device_id * ids
PCI ID table.
Definition: pci.h:249
#define DBGC(...)
Definition: compiler.h:505
static void pcibridge_remove(struct pci_device *pci)
Remove PCI device.
Definition: pcibridge.c:109
FILE_LICENCE(GPL2_OR_LATER_OR_UBDL)
int pci_read_config_word(struct pci_device *pci, unsigned int where, uint16_t *value)
Read 16-bit word from PCI configuration space.
struct pci_driver pcibridge_driver __pci_driver
Bridge PCI driver.
Definition: pcibridge.c:125
#define list_del(list)
Delete an entry from a list.
Definition: list.h:119
static void pci_set_drvdata(struct pci_device *pci, void *priv)
Set PCI driver-private data.
Definition: pci.h:359
#define ENOMEM
Not enough space.
Definition: errno.h:534
static LIST_HEAD(pcibridges)
List of all PCI bridges.
struct pci_bridge * pcibridge_find(struct pci_device *pci)
Find bridge attached to a PCI device.
Definition: pcibridge.c:48
#define PCI_PRIMARY
Primary bus number.
Definition: pci.h:143
int pci_read_config_dword(struct pci_device *pci, unsigned int where, uint32_t *value)
Read 32-bit dword from PCI configuration space.
#define list_for_each_entry(pos, head, member)
Iterate over entries in a list.
Definition: list.h:420
struct pci_device * pci
PCI device.
Definition: pcibridge.h:19
#define cpu_to_le32s(ptr)
Definition: byteswap.h:119
uint16_t limit
Limit.
Definition: librm.h:250
static void(* free)(struct refcnt *refcnt))
Definition: refcnt.h:54
A PCI-to-PCI bridge.
Definition: pcibridge.h:17
void * zalloc(size_t size)
Allocate cleared memory.
Definition: malloc.c:624
#define PCI_FMT
PCI device debug message format.
Definition: pci.h:307
PCI bus.
A PCI device.
Definition: pci.h:206
uint8_t primary
Primary bus.
Definition: pcibridge.h:26
uint32_t memlimit
Memory limit.
Definition: pcibridge.h:36
uint8_t secondary
Secondary bus.
Definition: pcibridge.h:28
A PCI device ID list entry.
Definition: pci.h:170
uint16_t base
Base address.
Definition: edd.h:14
static void * pci_get_drvdata(struct pci_device *pci)
Get PCI driver-private data.
Definition: pci.h:369
uint32_t busdevfn
Segment, bus, device, and function (bus:dev.fn) number.
Definition: pci.h:233
struct list_head list
List of bridges.
Definition: pcibridge.h:38
uint32_t buses
Raw dword.
Definition: pcibridge.h:23
PCI-to-PCI bridge.
#define PCI_ARGS(pci)
PCI device debug message arguments.
Definition: pci.h:310
#define NULL
NULL pointer (VOID *)
Definition: Base.h:321
#define PCI_ROM(_vendor, _device, _name, _description, _data)
Definition: pci.h:303
uint8_t bus
Bus.
Definition: edd.h:14
uint32_t membase
Memory base.
Definition: pcibridge.h:34
#define PCI_ANY_ID
Match-anything ID.
Definition: pci.h:182