1 #include <linux/sched.h>
3 #include <linux/uaccess.h>
4 #include <linux/mmzone.h>
5 #include <linux/ioport.h>
6 #include <linux/seq_file.h>
7 #include <linux/console.h>
8 #include <linux/init.h>
10 #include <linux/dmi.h>
11 #include <linux/pfn.h>
12 #include <linux/pci.h>
13 #include <linux/export.h>
15 #include <asm/pci-direct.h>
17 #include <asm/mmzone.h>
18 #include <asm/setup.h>
19 #include <asm/sections.h>
21 #include <asm/setup_arch.h>
23 static struct resource system_rom_resource
= {
27 .flags
= IORESOURCE_BUSY
| IORESOURCE_READONLY
| IORESOURCE_MEM
30 static struct resource extension_rom_resource
= {
31 .name
= "Extension ROM",
34 .flags
= IORESOURCE_BUSY
| IORESOURCE_READONLY
| IORESOURCE_MEM
37 static struct resource adapter_rom_resources
[] = { {
38 .name
= "Adapter ROM",
41 .flags
= IORESOURCE_BUSY
| IORESOURCE_READONLY
| IORESOURCE_MEM
43 .name
= "Adapter ROM",
46 .flags
= IORESOURCE_BUSY
| IORESOURCE_READONLY
| IORESOURCE_MEM
48 .name
= "Adapter ROM",
51 .flags
= IORESOURCE_BUSY
| IORESOURCE_READONLY
| IORESOURCE_MEM
53 .name
= "Adapter ROM",
56 .flags
= IORESOURCE_BUSY
| IORESOURCE_READONLY
| IORESOURCE_MEM
58 .name
= "Adapter ROM",
61 .flags
= IORESOURCE_BUSY
| IORESOURCE_READONLY
| IORESOURCE_MEM
63 .name
= "Adapter ROM",
66 .flags
= IORESOURCE_BUSY
| IORESOURCE_READONLY
| IORESOURCE_MEM
69 static struct resource video_rom_resource
= {
73 .flags
= IORESOURCE_BUSY
| IORESOURCE_READONLY
| IORESOURCE_MEM
76 /* does this oprom support the given pci device, or any of the devices
77 * that the driver supports?
79 static bool match_id(struct pci_dev
*pdev
, unsigned short vendor
, unsigned short device
)
81 struct pci_driver
*drv
= pdev
->driver
;
82 const struct pci_device_id
*id
;
84 if (pdev
->vendor
== vendor
&& pdev
->device
== device
)
87 for (id
= drv
? drv
->id_table
: NULL
; id
&& id
->vendor
; id
++)
88 if (id
->vendor
== vendor
&& id
->device
== device
)
91 return id
&& id
->vendor
;
94 static bool probe_list(struct pci_dev
*pdev
, unsigned short vendor
,
95 const unsigned char *rom_list
)
97 unsigned short device
;
100 if (probe_kernel_address(rom_list
, device
) != 0)
103 if (device
&& match_id(pdev
, vendor
, device
))
112 static struct resource
*find_oprom(struct pci_dev
*pdev
)
114 struct resource
*oprom
= NULL
;
117 for (i
= 0; i
< ARRAY_SIZE(adapter_rom_resources
); i
++) {
118 struct resource
*res
= &adapter_rom_resources
[i
];
119 unsigned short offset
, vendor
, device
, list
, rev
;
120 const unsigned char *rom
;
125 rom
= isa_bus_to_virt(res
->start
);
126 if (probe_kernel_address(rom
+ 0x18, offset
) != 0)
129 if (probe_kernel_address(rom
+ offset
+ 0x4, vendor
) != 0)
132 if (probe_kernel_address(rom
+ offset
+ 0x6, device
) != 0)
135 if (match_id(pdev
, vendor
, device
)) {
140 if (probe_kernel_address(rom
+ offset
+ 0x8, list
) == 0 &&
141 probe_kernel_address(rom
+ offset
+ 0xc, rev
) == 0 &&
143 probe_list(pdev
, vendor
, rom
+ offset
+ list
)) {
152 void *pci_map_biosrom(struct pci_dev
*pdev
)
154 struct resource
*oprom
= find_oprom(pdev
);
159 return ioremap(oprom
->start
, resource_size(oprom
));
161 EXPORT_SYMBOL(pci_map_biosrom
);
163 void pci_unmap_biosrom(void __iomem
*image
)
167 EXPORT_SYMBOL(pci_unmap_biosrom
);
169 size_t pci_biosrom_size(struct pci_dev
*pdev
)
171 struct resource
*oprom
= find_oprom(pdev
);
173 return oprom
? resource_size(oprom
) : 0;
175 EXPORT_SYMBOL(pci_biosrom_size
);
177 #define ROMSIGNATURE 0xaa55
179 static int __init
romsignature(const unsigned char *rom
)
181 const unsigned short * const ptr
= (const unsigned short *)rom
;
184 return probe_kernel_address(ptr
, sig
) == 0 && sig
== ROMSIGNATURE
;
187 static int __init
romchecksum(const unsigned char *rom
, unsigned long length
)
189 unsigned char sum
, c
;
191 for (sum
= 0; length
&& probe_kernel_address(rom
++, c
) == 0; length
--)
193 return !length
&& !sum
;
196 void __init
probe_roms(void)
198 const unsigned char *rom
;
199 unsigned long start
, length
, upper
;
204 upper
= adapter_rom_resources
[0].start
;
205 for (start
= video_rom_resource
.start
; start
< upper
; start
+= 2048) {
206 rom
= isa_bus_to_virt(start
);
207 if (!romsignature(rom
))
210 video_rom_resource
.start
= start
;
212 if (probe_kernel_address(rom
+ 2, c
) != 0)
215 /* 0 < length <= 0x7f * 512, historically */
218 /* if checksum okay, trust length byte */
219 if (length
&& romchecksum(rom
, length
))
220 video_rom_resource
.end
= start
+ length
- 1;
222 request_resource(&iomem_resource
, &video_rom_resource
);
226 start
= (video_rom_resource
.end
+ 1 + 2047) & ~2047UL;
231 request_resource(&iomem_resource
, &system_rom_resource
);
232 upper
= system_rom_resource
.start
;
234 /* check for extension rom (ignore length byte!) */
235 rom
= isa_bus_to_virt(extension_rom_resource
.start
);
236 if (romsignature(rom
)) {
237 length
= resource_size(&extension_rom_resource
);
238 if (romchecksum(rom
, length
)) {
239 request_resource(&iomem_resource
, &extension_rom_resource
);
240 upper
= extension_rom_resource
.start
;
244 /* check for adapter roms on 2k boundaries */
245 for (i
= 0; i
< ARRAY_SIZE(adapter_rom_resources
) && start
< upper
; start
+= 2048) {
246 rom
= isa_bus_to_virt(start
);
247 if (!romsignature(rom
))
250 if (probe_kernel_address(rom
+ 2, c
) != 0)
253 /* 0 < length <= 0x7f * 512, historically */
256 /* but accept any length that fits if checksum okay */
257 if (!length
|| start
+ length
> upper
|| !romchecksum(rom
, length
))
260 adapter_rom_resources
[i
].start
= start
;
261 adapter_rom_resources
[i
].end
= start
+ length
- 1;
262 request_resource(&iomem_resource
, &adapter_rom_resources
[i
]);
264 start
= adapter_rom_resources
[i
++].end
& ~2047UL;