1 /* pci.c - Generic PCI interfaces. */
3 * GRUB -- GRand Unified Bootloader
4 * Copyright (C) 2007,2009 Free Software Foundation, Inc.
6 * GRUB is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * GRUB is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
23 #include <grub/misc.h>
24 #include <grub/mm_private.h>
25 #include <grub/cache.h>
27 GRUB_MOD_LICENSE ("GPLv3+");
29 /* FIXME: correctly support 64-bit architectures. */
30 /* #if GRUB_TARGET_SIZEOF_VOID_P == 4 */
31 struct grub_pci_dma_chunk
*
32 grub_memalign_dma32 (grub_size_t align
, grub_size_t size
)
37 size
= ALIGN_UP (size
, align
);
38 ret
= grub_memalign (align
, size
);
39 #if GRUB_CPU_SIZEOF_VOID_P == 8
40 if ((grub_addr_t
) ret
>> 32)
42 /* Shouldn't happend since the only platform in this case is
43 x86_64-efi and it skips any regions > 4GiB because
44 of EFI bugs anyway. */
45 grub_error (GRUB_ERR_BUG
, "allocation outside 32-bit range");
51 grub_arch_sync_dma_caches (ret
, size
);
57 grub_dma_free (struct grub_pci_dma_chunk
*ch
)
59 grub_size_t size
= (((struct grub_mm_header
*) ch
) - 1)->size
* GRUB_MM_ALIGN
;
60 grub_arch_sync_dma_caches (ch
, size
);
65 #ifdef GRUB_MACHINE_MIPS_LOONGSON
67 grub_dma_get_virt (struct grub_pci_dma_chunk
*ch
)
69 return (void *) ((((grub_uint32_t
) ch
) & 0x1fffffff) | 0xa0000000);
73 grub_dma_get_phys (struct grub_pci_dma_chunk
*ch
)
75 return (((grub_uint32_t
) ch
) & 0x1fffffff) | 0x80000000;
80 grub_dma_get_virt (struct grub_pci_dma_chunk
*ch
)
86 grub_dma_get_phys (struct grub_pci_dma_chunk
*ch
)
88 return (grub_uint32_t
) (grub_addr_t
) ch
;
94 grub_pci_make_address (grub_pci_device_t dev
, int reg
)
96 return (1 << 31) | (dev
.bus
<< 16) | (dev
.device
<< 11)
97 | (dev
.function
<< 8) | reg
;
101 grub_pci_iterate (grub_pci_iteratefunc_t hook
, void *hook_data
)
103 grub_pci_device_t dev
;
104 grub_pci_address_t addr
;
108 for (dev
.bus
= 0; dev
.bus
< GRUB_PCI_NUM_BUS
; dev
.bus
++)
110 for (dev
.device
= 0; dev
.device
< GRUB_PCI_NUM_DEVICES
; dev
.device
++)
112 for (dev
.function
= 0; dev
.function
< 8; dev
.function
++)
114 addr
= grub_pci_make_address (dev
, GRUB_PCI_REG_PCI_ID
);
115 id
= grub_pci_read (addr
);
117 /* Check if there is a device present. */
118 if (id
>> 16 == 0xFFFF)
120 if (dev
.function
== 0)
121 /* Devices are required to implement function 0, so if
122 it's missing then there is no device here. */
128 if (hook (dev
, id
, hook_data
))
131 /* Probe only func = 0 if the device if not multifunction */
132 if (dev
.function
== 0)
134 addr
= grub_pci_make_address (dev
, GRUB_PCI_REG_CACHELINE
);
135 hdr
= grub_pci_read (addr
);
136 if (!(hdr
& 0x800000))
145 grub_pci_find_capability (grub_pci_device_t dev
, grub_uint8_t cap
)
147 grub_uint8_t pos
= 0x34;
153 grub_pci_address_t addr
;
155 addr
= grub_pci_make_address (dev
, pos
);
156 pos
= grub_pci_read_byte (addr
);
162 addr
= grub_pci_make_address (dev
, pos
);
163 id
= grub_pci_read_byte (addr
);