[142] | 1 | /* $Id: pci.c 153 2000-07-23 16:21:57Z sandervl $ */
|
---|
| 2 |
|
---|
| 3 | //******************************************************************************
|
---|
| 4 | // OS/2 IDC services (callback to 16 bits MMPM2 driver)
|
---|
| 5 | //
|
---|
| 6 | // Copyright 2000 Sander van Leeuwen (sandervl@xs4all.nl)
|
---|
| 7 | //
|
---|
| 8 | // Parts based on Linux kernel code (pci_read/write_*)
|
---|
| 9 | //
|
---|
| 10 | // This program is free software; you can redistribute it and/or
|
---|
| 11 | // modify it under the terms of the GNU General Public License as
|
---|
| 12 | // published by the Free Software Foundation; either version 2 of
|
---|
| 13 | // the License, or (at your option) any later version.
|
---|
| 14 | //
|
---|
| 15 | // This program is distributed in the hope that it will be useful,
|
---|
| 16 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
|
---|
| 17 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
---|
| 18 | // GNU General Public License for more details.
|
---|
| 19 | //
|
---|
| 20 | // You should have received a copy of the GNU General Public
|
---|
| 21 | // License along with this program; if not, write to the Free
|
---|
| 22 | // Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
|
---|
| 23 | // USA.
|
---|
| 24 | //
|
---|
| 25 | //******************************************************************************
|
---|
| 26 | #include "hwaccess.h"
|
---|
| 27 | #include <linux/init.h>
|
---|
| 28 | #include <linux/poll.h>
|
---|
| 29 | #include <asm/uaccess.h>
|
---|
| 30 | #include <asm/hardirq.h>
|
---|
[153] | 31 | #include <asm/io.h>
|
---|
[142] | 32 |
|
---|
| 33 | #define LINUX
|
---|
| 34 | #include <ossidc.h>
|
---|
| 35 | #include <stacktoflat.h>
|
---|
| 36 |
|
---|
| 37 | #define MAX_PCI_DEVICES 16
|
---|
| 38 | #define MAX_PCI_BUSSES 2
|
---|
| 39 |
|
---|
| 40 | static struct pci_dev pci_devices[MAX_PCI_DEVICES] = {0};
|
---|
| 41 | static struct pci_bus pci_busses[MAX_PCI_BUSSES] = {0};
|
---|
| 42 |
|
---|
| 43 | //******************************************************************************
|
---|
| 44 | //******************************************************************************
|
---|
| 45 | int pcidev_prepare(struct pci_dev *dev)
|
---|
| 46 | {
|
---|
| 47 | return 1; //todo: correct return value??
|
---|
| 48 | }
|
---|
| 49 | //******************************************************************************
|
---|
| 50 | //******************************************************************************
|
---|
| 51 | int pcidev_activate(struct pci_dev *dev)
|
---|
| 52 | {
|
---|
| 53 | return 1; //todo: correct return value??
|
---|
| 54 | }
|
---|
| 55 | //******************************************************************************
|
---|
| 56 | //******************************************************************************
|
---|
| 57 | int pcidev_deactivate(struct pci_dev *dev)
|
---|
| 58 | {
|
---|
| 59 | return 1; //todo: correct return value??
|
---|
| 60 | }
|
---|
| 61 | //******************************************************************************
|
---|
| 62 | //TODO: Doesn't completely fill in the pci_dev structure
|
---|
| 63 | //******************************************************************************
|
---|
| 64 | int FindPCIDevice(unsigned int vendor, unsigned int device, struct pci_dev near *pcidev)
|
---|
| 65 | {
|
---|
| 66 | IDC_RESOURCE idcres;
|
---|
| 67 | ULONG devid, pResource;
|
---|
| 68 | int i, residx = 0;
|
---|
| 69 |
|
---|
| 70 | pcidev->prepare = pcidev_prepare;
|
---|
| 71 | pcidev->activate = pcidev_activate;
|
---|
| 72 | pcidev->deactivate = pcidev_deactivate;
|
---|
| 73 | pcidev->active = 1;
|
---|
| 74 | pcidev->ro = 0;
|
---|
| 75 | pcidev->sibling = NULL;
|
---|
| 76 | pcidev->next = NULL;
|
---|
| 77 | pcidev->vendor = vendor;
|
---|
| 78 | pcidev->device = device;
|
---|
| 79 |
|
---|
[151] | 80 | devid = (device << 16) | vendor;
|
---|
[142] | 81 |
|
---|
| 82 | #ifdef KEE
|
---|
| 83 | pResource = __FlatToStack(&idcres);
|
---|
| 84 | #else
|
---|
| 85 | pResource = __Compress48Pointer((char FAR48 *)&idcres);
|
---|
| 86 | #endif
|
---|
| 87 | if(CallOSS16(IDC16_FIND_PCIDEVICE, devid, pResource) == FALSE) {
|
---|
| 88 | return FALSE;
|
---|
| 89 | }
|
---|
| 90 |
|
---|
| 91 | for(i=0;i<MAX_RES_IO;i++) {
|
---|
| 92 | if(idcres.io[i] != 0xffff) {
|
---|
| 93 | pcidev->resource[residx].name = 0;
|
---|
| 94 | pcidev->resource[residx].child = 0;
|
---|
| 95 | pcidev->resource[residx].sibling = 0;
|
---|
| 96 | pcidev->resource[residx].parent = 0;
|
---|
| 97 | pcidev->resource[residx].start = idcres.io[i];
|
---|
| 98 | pcidev->resource[residx].end = idcres.io[i] + idcres.iolength[i]; //inclusive??
|
---|
| 99 | pcidev->resource[residx].flags = IORESOURCE_IO | PCI_BASE_ADDRESS_SPACE_IO;
|
---|
| 100 |
|
---|
| 101 | residx++;
|
---|
| 102 | }
|
---|
| 103 | }
|
---|
| 104 | for(i=0;i<MAX_RES_MEM;i++) {
|
---|
| 105 | if(idcres.mem[i] != 0xffffffff) {
|
---|
| 106 | pcidev->resource[residx].name = 0;
|
---|
| 107 | pcidev->resource[residx].child = 0;
|
---|
| 108 | pcidev->resource[residx].sibling = 0;
|
---|
| 109 | pcidev->resource[residx].parent = 0;
|
---|
| 110 | pcidev->resource[residx].start = idcres.mem[i];
|
---|
| 111 | pcidev->resource[residx].end = idcres.mem[i] + idcres.memlength[i]; //inclusive??
|
---|
| 112 | pcidev->resource[residx].flags = IORESOURCE_MEM | IORESOURCE_MEM_WRITEABLE;
|
---|
| 113 |
|
---|
| 114 | residx++;
|
---|
| 115 | }
|
---|
| 116 | }
|
---|
| 117 | for(i=0;i<MAX_RES_DMA;i++) {
|
---|
| 118 | if(idcres.dma[i] != 0xffff) {
|
---|
| 119 | pcidev->dma_resource[i].name = 0;
|
---|
| 120 | pcidev->dma_resource[i].child = 0;
|
---|
| 121 | pcidev->dma_resource[i].sibling = 0;
|
---|
| 122 | pcidev->dma_resource[i].parent = 0;
|
---|
| 123 | pcidev->dma_resource[i].start = idcres.dma[i];
|
---|
| 124 | pcidev->dma_resource[i].end = idcres.dma[i];
|
---|
| 125 | //todo: 8/16 bits
|
---|
| 126 | pcidev->dma_resource[i].flags = IORESOURCE_DMA;
|
---|
| 127 | }
|
---|
| 128 | }
|
---|
| 129 | for(i=0;i<MAX_RES_IRQ;i++) {
|
---|
| 130 | if(idcres.irq[i] != 0xffff) {
|
---|
| 131 | pcidev->irq_resource[i].name = 0;
|
---|
| 132 | pcidev->irq_resource[i].child = 0;
|
---|
| 133 | pcidev->irq_resource[i].sibling = 0;
|
---|
| 134 | pcidev->irq_resource[i].parent = 0;
|
---|
| 135 | pcidev->irq_resource[i].start = idcres.irq[i];
|
---|
| 136 | pcidev->irq_resource[i].end = idcres.irq[i];
|
---|
| 137 | //todo: irq flags
|
---|
| 138 | pcidev->irq_resource[9].flags = IORESOURCE_IRQ;
|
---|
| 139 | }
|
---|
| 140 | }
|
---|
| 141 | pcidev->irq = pcidev->irq_resource[0].start;
|
---|
| 142 | pcidev->bus = &pci_busses[0];
|
---|
| 143 | return TRUE;
|
---|
| 144 | }
|
---|
| 145 | //******************************************************************************
|
---|
| 146 | //******************************************************************************
|
---|
| 147 | struct pci_dev *pci_find_device (unsigned int vendor, unsigned int device, struct pci_dev *from)
|
---|
| 148 | {
|
---|
| 149 | int i;
|
---|
| 150 |
|
---|
| 151 | if(from) {
|
---|
| 152 | //requesting 2nd device of the same type; don't support this for now
|
---|
| 153 | return 0;
|
---|
| 154 | }
|
---|
| 155 | for(i=0;i<MAX_PCI_DEVICES;i++) {
|
---|
| 156 | if(pci_devices[i].devfn == 0) {
|
---|
| 157 | if(FindPCIDevice(vendor, device, (struct pci_dev near *)&pci_devices[i]) == TRUE) {
|
---|
| 158 | return &pci_devices[i];
|
---|
| 159 | }
|
---|
| 160 | break;
|
---|
| 161 | }
|
---|
| 162 | }
|
---|
| 163 | return 0;
|
---|
| 164 | }
|
---|
| 165 | //******************************************************************************
|
---|
| 166 | #define CONFIG_CMD(dev, where) (0x80000000 | (dev->bus->number << 16) | (dev->devfn << 8) | (where & ~3))
|
---|
| 167 | //******************************************************************************
|
---|
| 168 | int pci_read_config_byte(struct pci_dev *dev, int where, u8 *value)
|
---|
| 169 | {
|
---|
| 170 | outl(CONFIG_CMD(dev,where), 0xCF8);
|
---|
| 171 | *value = inb(0xCFC + (where&3));
|
---|
| 172 | return PCIBIOS_SUCCESSFUL;
|
---|
| 173 | }
|
---|
| 174 | //******************************************************************************
|
---|
| 175 | //******************************************************************************
|
---|
| 176 | int pci_read_config_word(struct pci_dev *dev, int where, u16 *value)
|
---|
| 177 | {
|
---|
| 178 | outl(CONFIG_CMD(dev,where), 0xCF8);
|
---|
| 179 | *value = inw(0xCFC + (where&2));
|
---|
| 180 | return PCIBIOS_SUCCESSFUL;
|
---|
| 181 | }
|
---|
| 182 | //******************************************************************************
|
---|
| 183 | //******************************************************************************
|
---|
| 184 | int pci_read_config_dword(struct pci_dev *dev, int where, u32 *value)
|
---|
| 185 | {
|
---|
| 186 | outl(CONFIG_CMD(dev,where), 0xCF8);
|
---|
| 187 | *value = inl(0xCFC);
|
---|
| 188 | return PCIBIOS_SUCCESSFUL;
|
---|
| 189 | }
|
---|
| 190 | //******************************************************************************
|
---|
| 191 | //******************************************************************************
|
---|
| 192 | int pci_write_config_byte(struct pci_dev *dev, int where, u8 value)
|
---|
| 193 | {
|
---|
| 194 | outl(CONFIG_CMD(dev,where), 0xCF8);
|
---|
| 195 | outb(value, 0xCFC + (where&3));
|
---|
| 196 | return PCIBIOS_SUCCESSFUL;
|
---|
| 197 | }
|
---|
| 198 | //******************************************************************************
|
---|
| 199 | //******************************************************************************
|
---|
| 200 | int pci_write_config_word(struct pci_dev *dev, int where, u16 value)
|
---|
| 201 | {
|
---|
| 202 | outl(CONFIG_CMD(dev,where), 0xCF8);
|
---|
| 203 | outw(value, 0xCFC + (where&2));
|
---|
| 204 | return PCIBIOS_SUCCESSFUL;
|
---|
| 205 | }
|
---|
| 206 | //******************************************************************************
|
---|
| 207 | //******************************************************************************
|
---|
| 208 | int pci_write_config_dword(struct pci_dev *dev, int where, u32 value)
|
---|
| 209 | {
|
---|
| 210 | outl(CONFIG_CMD(dev,where), 0xCF8);
|
---|
| 211 | outl(value, 0xCFC);
|
---|
| 212 | return PCIBIOS_SUCCESSFUL;
|
---|
| 213 | }
|
---|
| 214 | //******************************************************************************
|
---|
| 215 | //******************************************************************************
|
---|
| 216 | int pcibios_present(void)
|
---|
| 217 | {
|
---|
| 218 | return 1;
|
---|
| 219 | }
|
---|
| 220 | //******************************************************************************
|
---|
| 221 | //******************************************************************************
|
---|
| 222 | struct pci_dev *pci_find_slot (unsigned int bus, unsigned int devfn)
|
---|
| 223 | {
|
---|
| 224 | return NULL;
|
---|
| 225 | }
|
---|
| 226 | //******************************************************************************
|
---|
| 227 | //******************************************************************************
|
---|
| 228 | int pci_dma_supported(struct pci_dev *dev, unsigned long mask)
|
---|
| 229 | {
|
---|
| 230 | return 1;
|
---|
| 231 | }
|
---|
| 232 | //******************************************************************************
|
---|
| 233 | //******************************************************************************
|
---|
| 234 | int pci_enable_device(struct pci_dev *dev)
|
---|
| 235 | {
|
---|
| 236 | return 0;
|
---|
| 237 | }
|
---|
| 238 | //******************************************************************************
|
---|
| 239 | struct pci_dev *sblivepcidev = NULL;
|
---|
| 240 | //******************************************************************************
|
---|
| 241 | int pci_register_driver(struct pci_driver *driver)
|
---|
| 242 | {
|
---|
| 243 | struct pci_dev *pcidev;
|
---|
| 244 |
|
---|
| 245 | pcidev = pci_find_device(driver->id_table->vendor, driver->id_table->device, NULL);
|
---|
| 246 | if(pcidev) {
|
---|
| 247 | if(driver->probe(pcidev, driver->id_table) == 0) {
|
---|
| 248 | sblivepcidev = pcidev;
|
---|
| 249 | return 0;
|
---|
| 250 | }
|
---|
| 251 | }
|
---|
| 252 | return 1;
|
---|
| 253 | }
|
---|
| 254 | //******************************************************************************
|
---|
| 255 | //******************************************************************************
|
---|
| 256 | int pci_unregister_driver(struct pci_driver *driver)
|
---|
| 257 | {
|
---|
| 258 | if(driver && sblivepcidev) {
|
---|
| 259 | driver->remove(sblivepcidev);
|
---|
| 260 | }
|
---|
| 261 | return 0;
|
---|
| 262 | }
|
---|
| 263 | //******************************************************************************
|
---|
| 264 | //******************************************************************************
|
---|
| 265 | void pci_set_master(struct pci_dev *dev)
|
---|
| 266 | {
|
---|
| 267 |
|
---|
| 268 | }
|
---|
| 269 | //******************************************************************************
|
---|
| 270 | //******************************************************************************
|
---|
[153] | 271 | int __compat_get_order(unsigned long size)
|
---|
| 272 | {
|
---|
| 273 | int order;
|
---|
| 274 |
|
---|
| 275 | size = (size-1) >> (PAGE_SHIFT-1);
|
---|
| 276 | order = -1;
|
---|
| 277 | do {
|
---|
| 278 | size >>= 1;
|
---|
| 279 | order++;
|
---|
| 280 | } while (size);
|
---|
| 281 | return order;
|
---|
| 282 | }
|
---|
| 283 | //******************************************************************************
|
---|
| 284 | //******************************************************************************
|
---|
| 285 | void *pci_alloc_consistent(struct pci_dev *hwdev,
|
---|
| 286 | size_t size, dma_addr_t *dma_handle) {
|
---|
| 287 | void *ret;
|
---|
| 288 | int gfp = GFP_ATOMIC;
|
---|
| 289 |
|
---|
| 290 | if (hwdev == NULL)
|
---|
| 291 | gfp |= GFP_DMA;
|
---|
| 292 | ret = (void *)__get_free_pages(gfp, __compat_get_order(size));
|
---|
| 293 |
|
---|
| 294 | if (ret != NULL) {
|
---|
| 295 | memset(ret, 0, size);
|
---|
| 296 | *dma_handle = virt_to_bus(ret);
|
---|
| 297 | }
|
---|
| 298 | return ret;
|
---|
| 299 | }
|
---|
| 300 | //******************************************************************************
|
---|
| 301 | //******************************************************************************
|
---|
| 302 | void pci_free_consistent(struct pci_dev *hwdev, size_t size,
|
---|
| 303 | void *vaddr, dma_addr_t dma_handle)
|
---|
| 304 | {
|
---|
| 305 | free_pages((unsigned long)vaddr, __compat_get_order(size));
|
---|
| 306 | }
|
---|
| 307 | //******************************************************************************
|
---|
| 308 | //******************************************************************************
|
---|