00001
00002
00011
00012
00013
00014
00015
00016
00017 #include <linux/config.h>
00018 #include <linux/proc_fs.h>
00019 #include <linux/ioport.h>
00020 #include <linux/pci.h>
00021 #include <linux/mm.h>
00022 #include <asm/io.h>
00023
00024
00025 #include <l4/util/macros.h>
00026 #include <l4/util/bitops.h>
00027
00028
00029 #ifdef USE_OSKIT
00030 #include <stdlib.h>
00031 #include <malloc.h>
00032 #else
00033
00034
00035 void *malloc(size_t size);
00036 void free(void *ptr);
00037 unsigned int strtol(const char *nptr, char **endptr, int base);
00038 #endif
00039
00040
00041 #include "pcilib.h"
00042
00043
00044 #include "io.h"
00045 #include "res.h"
00046
00047
00048 #define DO_DEBUG 0
00049
00050 #ifndef NO_DOX
00051
00052 void initcall_pci_proc_init(void);
00053 #endif
00054
00055
00056 #undef CONFIG_ALIGN_RESOURCES_TO_SUPERPAGE
00057
00058
00059 #undef FASTCALL
00060 #define FASTCALL(x) __attribute__((regparm(3))) x
00061
00079 struct resource ioport_resource = {
00080 "PCI IO",
00081 0x0000, IO_SPACE_LIMIT,
00082 IORESOURCE_IO
00083 };
00085 struct resource iomem_resource = {
00086 "PCI mem",
00087 0x00000000, 0xffffffff,
00088 IORESOURCE_MEM
00089 };
00092 unsigned long pci_mem_start = 0x80000000;
00093
00094
00095
00096
00097 static char * do_resource_list(struct resource *entry, const char *fmt, int offset, char *buf, char *end)
00098 {
00099 if (offset < 0)
00100 offset = 0;
00101
00102 while (entry)
00103 {
00104 const char *name = entry->name;
00105 unsigned long from, to;
00106
00107 if ((int) (end-buf) < 80)
00108 return buf;
00109
00110 from = entry->start;
00111 to = entry->end;
00112 if (!name)
00113 name = "<BAD>";
00114
00115 buf += sprintf(buf, fmt + offset, from, to, name);
00116 if (entry->child)
00117 buf = do_resource_list(entry->child, fmt, offset-2, buf, end);
00118 entry = entry->sibling;
00119 }
00120
00121 return buf;
00122 }
00123
00135 static struct resource *__request_resource(struct resource *root,
00136 struct resource *new)
00137 {
00138 unsigned long start = new->start;
00139 unsigned long end = new->end;
00140 struct resource *tmp, **p;
00141
00142 if (end < start)
00143 return root;
00144 if (start < root->start)
00145 return root;
00146 if (end > root->end)
00147 return root;
00148 p = &root->child;
00149 for (;;)
00150 {
00151 tmp = *p;
00152 if (!tmp || tmp->start > end)
00153 {
00154
00155 if (new->flags & IORESOURCE_BUSY)
00156 {
00157 struct resource *nr = root;
00158
00159
00160 while (nr->parent)
00161 nr = nr->parent;
00162
00163
00164 if (nr == &ioport_resource)
00165 {
00166 if (callback_request_region(start, end - start + 1))
00167 return root;
00168 }
00169 else if (nr == &iomem_resource)
00170 {
00171 if (callback_request_mem_region(start, end - start + 1))
00172 return root;
00173 }
00174 }
00175
00176 new->sibling = tmp;
00177 *p = new;
00178 new->parent = root;
00179 return NULL;
00180 }
00181 p = &tmp->sibling;
00182 if (tmp->end < start)
00183 continue;
00184 return tmp;
00185 }
00186 }
00187
00194 struct resource *__request_region(struct resource *parent,
00195 unsigned long start, unsigned long n,
00196 const char *name)
00197 {
00198 struct resource *res = kmalloc(sizeof(*res), GFP_KERNEL);
00199
00200 if (res)
00201 {
00202 memset(res, 0, sizeof(*res));
00203 res->name = name;
00204 res->start = start;
00205 res->end = start + n - 1;
00206 res->flags = IORESOURCE_BUSY;
00207
00208 for (;;)
00209 {
00210 struct resource *conflict;
00211
00212 conflict = __request_resource(parent, res);
00213 if (!conflict)
00214 break;
00215 if (conflict != parent)
00216 {
00217 parent = conflict;
00218 if (!(conflict->flags & IORESOURCE_BUSY))
00219 continue;
00220 }
00221
00222
00223 kfree(res);
00224 res = NULL;
00225 break;
00226 }
00227 }
00228 return res;
00229 }
00230
00231 void __release_region(struct resource *parent,
00232 unsigned long start, unsigned long n)
00233 {}
00234
00238 static int __find_resource(struct resource *root, struct resource *new,
00239 unsigned long size,
00240 unsigned long min, unsigned long max,
00241 unsigned long align,
00242 void (*alignf) (void *, struct resource *,
00243 unsigned long, unsigned long),
00244 void *alignf_data)
00245 {
00246 struct resource *this = root->child;
00247
00248 new->start = root->start;
00249 for (;;)
00250 {
00251 if (this)
00252 new->end = this->start;
00253 else
00254 new->end = root->end;
00255 if (new->start < min)
00256 new->start = min;
00257 if (new->end > max)
00258 new->end = max;
00259 new->start = (new->start + align - 1) & ~(align - 1);
00260 if (alignf)
00261 {
00262 alignf(alignf_data, new, size, align);
00263 }
00264 if (new->start < new->end && new->end - new->start + 1 >= size)
00265 {
00266 new->end = new->start + size - 1;
00267 return 0;
00268 }
00269 if (!this)
00270 break;
00271 new->start = this->end + 1;
00272 this = this->sibling;
00273 }
00274 return -EBUSY;
00275 }
00276
00286 int request_resource(struct resource *root, struct resource *new)
00287 {
00288 struct resource *conflict;
00289
00290 #ifdef CONFIG_ALIGN_RESOURCES_TO_SUPERPAGE
00291 int err;
00292 unsigned long size = new->end - new->start + 1;
00293 unsigned long min = pci_mem_start, max = -1;
00294 unsigned long align;
00295
00296 LOGd(DO_DEBUG, "REQ: <0x%08lx-0x%08lx>", new->start, new->end);
00297
00298
00299 if (new->flags & IORESOURCE_MEM)
00300 {
00301 align = l4util_bsr(size);
00302
00303 if (size > (1UL << align))
00304 align++;
00305
00306 if (align < L4_LOG2_SUPERPAGESIZE)
00307 align = L4_LOG2_SUPERPAGESIZE;
00308 align = 1UL << align;
00309
00310 LOGd(DO_DEBUG, "ALIGN: for 0x%08lx = 0x%08lx", size, align);
00311
00312 err = __find_resource(root, new, size, min, max, align, 0, 0);
00313 if (err)
00314 return err;
00315
00316
00317 LOGd(DO_DEBUG, "ALIGN: <0x%08lx-0x%08lx>", new->start, new->end);
00318
00319
00320 }
00321 #endif
00322 conflict = __request_resource(root, new);
00323
00324 return conflict ? -EBUSY : 0;
00325 }
00326
00333 int allocate_resource(struct resource *root, struct resource *new,
00334 unsigned long size,
00335 unsigned long min, unsigned long max,
00336 unsigned long align,
00337 void (*alignf) (void *, struct resource *,
00338 unsigned long, unsigned long),
00339 void *alignf_data)
00340 {
00341 int err;
00342
00343 err = __find_resource(root, new, size, min, max, align, alignf, alignf_data);
00344 if (err >= 0 && __request_resource(root, new))
00345 err = -EBUSY;
00346
00347 return err;
00348 }
00349
00363 int request_irq(unsigned int irq, void (*handler) (int, void *, struct pt_regs *),
00364 unsigned long flags, const char *name, void *id)
00365 {
00366
00367 return 0;
00368 }
00369
00376 void free_irq(unsigned int irq, void *id)
00377 {
00378 }
00379
00392 void dev_probe_lock(void)
00393 {
00394 }
00395
00397 void dev_probe_unlock(void)
00398 {
00399 }
00400
00406 long simple_strtol(const char *cp, char **endp, unsigned int base)
00407 {
00408 return strtol(cp, endp, base);
00409 }
00410
00412 signed long FASTCALL(schedule_timeout(signed long timeout))
00413 {
00414
00415 return 0;
00416 }
00417
00418 void __const_udelay(unsigned long usecs)
00419 {
00420
00421 }
00422
00423
00424 #include <asm/processor.h>
00425 struct cpuinfo_x86 boot_cpu_data;
00426
00427 int remap_page_range(unsigned long from, unsigned long to, unsigned long size,
00428 pgprot_t prot)
00429 {return 0;}
00430 void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size,
00431 dma_addr_t *dma_handle)
00432 {return (void*)0;}
00433 void pci_free_consistent(struct pci_dev *hwdev, size_t size,
00434 void *vaddr, dma_addr_t dma_handle)
00435 {}
00436 void FASTCALL(add_wait_queue(wait_queue_head_t *q, wait_queue_t * wait))
00437 {}
00438 void FASTCALL(remove_wait_queue(wait_queue_head_t *q, wait_queue_t * wait))
00439 {}
00440 void FASTCALL(__wake_up(wait_queue_head_t *q, unsigned int mode, int nr))
00441 {}
00454 void *kmalloc(size_t size, int gfp)
00455 {
00456
00457 return malloc(size);
00458 }
00459
00463 void kfree(const void *obj)
00464 {
00465
00466 free((void *) obj);
00467 }
00468
00477 unsigned long FASTCALL(__get_free_pages(unsigned int gfp, unsigned int order))
00478 {
00479 unsigned long something = 0;
00480
00481 return something;
00482 }
00483
00492 void FASTCALL(free_pages(unsigned long addr, unsigned int order))
00493 {
00494 LOGdL(DO_DEBUG, "(%#08lx, %i)", addr, order);
00495 }
00496
00506 int PCI_init(int list)
00507 {
00508 #ifdef CONFIG_ALIGN_RESOURCES_TO_SUPERPAGE
00509 struct list_head *list;
00510 #endif
00511 struct pci_dev *p;
00512
00513 pci_init();
00514
00515 pci_for_each_dev(p)
00516 {
00517 int i;
00518
00519
00520
00521
00522 if ((i = pci_enable_device(p)))
00523 LOG("WARNING: initial PCI device activation for %s failed (%d)\n",
00524 p->slot_name, i);
00525
00526
00527
00528 for (i = 0; i < 6; i++)
00529 {
00530 if (p->resource[i].flags & IORESOURCE_MEM)
00531 {
00532 #ifdef CONFIG_ALIGN_RESOURCES_TO_SUPERPAGE
00533
00534 pcibios_update_resource(p, &iomem_resource, &p->resource[i], i);
00535 #endif
00536
00537
00538 if (callback_handle_pci_device(p->vendor, p->device))
00539 callback_announce_mem_region(p->resource[i].start,
00540 p->resource[i].end-p->resource[i].start+1);
00541 else
00542 printf("Ignoring memory %08lx-%08lx for device %04x:%04x\n",
00543 p->resource[i].start,
00544 p->resource[i].end,
00545 p->vendor, p->device);
00546 }
00547 }
00548 }
00549
00550 if (list)
00551 {
00552 char *buf = malloc(4000);
00553 if (buf)
00554 {
00555 do_resource_list(&iomem_resource, " %08lx-%08lx : %s\n", 8, buf, &buf[3999]);
00556 printf("%s", buf);
00557 do_resource_list(&ioport_resource, " %04lx-%04lx : %s\n", 8, buf, &buf[3999]);
00558 printf("%s", buf);
00559 free(buf);
00560 }
00561 }
00562
00563 return 0;
00564 }
00565
00571 unsigned short PCI_linux_to_io(void *linux_pdev, void *l4io_pdev)
00572 {
00573 int i;
00574 l4io_pci_dev_t *l4io = (l4io_pci_dev_t *) l4io_pdev;
00575 struct pci_dev *linus = (struct pci_dev *) linux_pdev;
00576
00577 l4io->bus = (unsigned char)(linus->bus->number & 0xff);
00578 l4io->devfn = (unsigned char)(linus->devfn & 0xff);
00579 l4io->vendor = linus->vendor;
00580 l4io->device = linus->device;
00581 l4io->sub_vendor = linus->subsystem_vendor;
00582 l4io->sub_device = linus->subsystem_device;
00583 l4io->dev_class = linus->class;
00584
00585 l4io->irq = linus->irq;
00586 for (i = 0; i < 12; i++)
00587 {
00588 l4io->res[i].start = linus->resource[i].start;
00589 l4io->res[i].end = linus->resource[i].end;
00590 l4io->res[i].flags = linus->resource[i].flags;
00591 }
00592
00593 strcpy(&l4io->name[0], &linus->name[0]);
00594 strcpy(&l4io->slot_name[0], &linus->slot_name[0]);
00595
00596 return (l4io->bus<<8 | l4io->devfn);
00597 }