2 * $Id: generic.c,v 1.5 1999/07/07 11:23:09 mj Exp $
4 * The PCI Library -- Generic Direct Access Functions
6 * Copyright (c) 1997--1999 Martin Mares <mj@atrey.karlin.mff.cuni.cz>
8 * Can be freely distributed and used under the terms of the GNU GPL.
16 pci_generic_scan_bus(struct pci_access
*a
, byte
*busmap
, int bus
)
19 struct pci_dev
*t
= pci_alloc_dev(a
);
21 a
->debug("Scanning bus %02x for devices...\n", bus
);
24 a
->warning("Bus %02x seen twice (firmware bug). Ignored.", bus
);
29 for(dev
=0; dev
<32; dev
++)
33 for(t
->func
=0; t
->func
<8; t
->func
++)
35 u32 vd
= pci_read_long(t
, PCI_VENDOR_ID
);
38 if (!vd
|| vd
== 0xffffffff)
40 ht
= pci_read_byte(t
, PCI_HEADER_TYPE
);
48 d
->vendor_id
= vd
& 0xffff;
49 d
->device_id
= vd
>> 16U;
50 d
->known_fields
= PCI_FILL_IDENT
;
55 case PCI_HEADER_TYPE_NORMAL
:
57 case PCI_HEADER_TYPE_BRIDGE
:
58 case PCI_HEADER_TYPE_CARDBUS
:
59 pci_generic_scan_bus(a
, busmap
, pci_read_byte(t
, PCI_SECONDARY_BUS
));
62 a
->debug("Device %02x:%02x.%d has unknown header type %02x.\n", d
->bus
, d
->dev
, d
->func
, ht
);
71 pci_generic_scan(struct pci_access
*a
)
75 bzero(busmap
, sizeof(busmap
));
76 pci_generic_scan_bus(a
, busmap
, 0);
80 pci_generic_fill_info(struct pci_dev
*d
, int flags
)
82 struct pci_access
*a
= d
->access
;
84 if (flags
& PCI_FILL_IDENT
)
86 d
->vendor_id
= pci_read_word(d
, PCI_VENDOR_ID
);
87 d
->device_id
= pci_read_word(d
, PCI_DEVICE_ID
);
89 if (flags
& PCI_FILL_IRQ
)
90 d
->irq
= pci_read_byte(d
, PCI_INTERRUPT_LINE
);
91 if (flags
& PCI_FILL_BASES
)
94 bzero(d
->base_addr
, sizeof(d
->base_addr
));
97 case PCI_HEADER_TYPE_NORMAL
:
100 case PCI_HEADER_TYPE_BRIDGE
:
103 case PCI_HEADER_TYPE_CARDBUS
:
109 u16 cmd
= pci_read_word(d
, PCI_COMMAND
);
112 u32 x
= pci_read_long(d
, PCI_BASE_ADDRESS_0
+ i
*4);
113 if (!x
|| x
== (u32
) ~0)
116 if (x
& PCI_BASE_ADDRESS_SPACE_IO
)
118 if (!a
->buscentric
&& !(cmd
& PCI_COMMAND_IO
))
121 else if (a
->buscentric
|| (cmd
& PCI_COMMAND_MEMORY
))
123 if ((x
& PCI_BASE_ADDRESS_MEM_TYPE_MASK
) == PCI_BASE_ADDRESS_MEM_TYPE_64
)
126 a
->warning("%02x:%02x.%d: Invalid 64-bit address seen.", d
->bus
, d
->dev
, d
->func
);
129 u32 y
= pci_read_long(d
, PCI_BASE_ADDRESS_0
+ (++i
)*4);
130 #ifdef HAVE_64BIT_ADDRESS
131 d
->base_addr
[i
-1] |= ((pciaddr_t
) y
) << 32;
135 a
->warning("%02x:%02x.%d 64-bit device address ignored.", d
->bus
, d
->dev
, d
->func
);
136 d
->base_addr
[i
-1] = 0;
147 if (flags
& PCI_FILL_ROM_BASE
)
150 d
->rom_base_addr
= 0;
153 case PCI_HEADER_TYPE_NORMAL
:
154 reg
= PCI_ROM_ADDRESS
;
156 case PCI_HEADER_TYPE_BRIDGE
:
157 reg
= PCI_ROM_ADDRESS1
;
162 u32 a
= pci_read_long(d
, reg
);
163 if (a
& PCI_ROM_ADDRESS_ENABLE
)
164 d
->rom_base_addr
= a
;
167 return flags
& ~PCI_FILL_SIZES
;
171 pci_generic_block_op(struct pci_dev
*d
, int pos
, byte
*buf
, int len
,
172 int (*r
)(struct pci_dev
*d
, int pos
, byte
*buf
, int len
))
174 if ((pos
& 1) && len
>= 1)
176 if (!r(d
, pos
, buf
, 1))
180 if ((pos
& 3) && len
>= 2)
182 if (!r(d
, pos
, buf
, 2))
184 pos
+= 2; buf
+= 2; len
-= 2;
188 if (!r(d
, pos
, buf
, 4))
190 pos
+= 4; buf
+= 4; len
-= 4;
194 if (!r(d
, pos
, buf
, 2))
196 pos
+= 2; buf
+= 2; len
-= 2;
198 if (len
&& !r(d
, pos
, buf
, 1))
204 pci_generic_block_read(struct pci_dev
*d
, int pos
, byte
*buf
, int len
)
206 return pci_generic_block_op(d
, pos
, buf
, len
, d
->access
->methods
->read
);
210 pci_generic_block_write(struct pci_dev
*d
, int pos
, byte
*buf
, int len
)
212 return pci_generic_block_op(d
, pos
, buf
, len
, d
->access
->methods
->write
);