linux/arch/m68knommu/kernel/comempci.c
<<
>>
Prefs
   1/*****************************************************************************/
   2
   3/*
   4 *      comemlite.c -- PCI access code for embedded CO-MEM Lite PCI controller.
   5 *
   6 *      (C) Copyright 1999-2003, Greg Ungerer (gerg@snapgear.com).
   7 *      (C) Copyright 2000, Lineo (www.lineo.com)
   8 */
   9
  10/*****************************************************************************/
  11
  12#include <linux/kernel.h>
  13#include <linux/types.h>
  14#include <linux/pci.h>
  15#include <linux/ptrace.h>
  16#include <linux/spinlock.h>
  17#include <linux/interrupt.h>
  18#include <linux/sched.h>
  19#include <asm/coldfire.h>
  20#include <asm/mcfsim.h>
  21#include <asm/irq.h>
  22#include <asm/anchor.h>
  23
  24#ifdef CONFIG_eLIA
  25#include <asm/elia.h>
  26#endif
  27
  28/*****************************************************************************/
  29
  30/*
  31 *      Debug configuration defines. DEBUGRES sets debugging output for
  32 *      the resource allocation phase. DEBUGPCI traces on pcibios_ function
  33 *      calls, and DEBUGIO traces all accesses to devices on the PCI bus.
  34 */
  35/*#define       DEBUGRES        1*/
  36/*#define       DEBUGPCI        1*/
  37/*#define       DEBUGIO         1*/
  38
  39/*****************************************************************************/
  40
  41/*
  42 *      PCI markers for bus present and active slots.
  43 */
  44int             pci_bus_is_present = 0;
  45unsigned long   pci_slotmask = 0;
  46
  47/*
  48 *      We may or may not need to swap the bytes of PCI bus tranfers.
  49 *      The endianess is re-roder automatically by the CO-MEM, but it
  50 *      will get the wrong byte order for a pure data stream.
  51 */
  52#define pci_byteswap    0
  53
  54
  55/*
  56 *      Resource tracking. The CO-MEM part creates a virtual address
  57 *      space that all the PCI devices live in - it is not in any way
  58 *      directly mapped into the ColdFire address space. So we can
  59 *      really assign any resources we like to devices, as long as
  60 *      they do not clash with other PCI devices.
  61 */
  62unsigned int    pci_iobase = PCIBIOS_MIN_IO;    /* Arbitrary start address */
  63unsigned int    pci_membase = PCIBIOS_MIN_MEM;  /* Arbitrary start address */
  64
  65#define PCI_MINIO       0x100                   /* 256 byte minimum I/O */
  66#define PCI_MINMEM      0x00010000              /* 64k minimum chunk */
  67
  68/*
  69 *      The CO-MEM's shared memory segment is visible inside the PCI
  70 *      memory address space. We need to keep track of the address that
  71 *      this is mapped at, to setup the bus masters pointers.
  72 */
  73unsigned int    pci_shmemaddr;
  74
  75/*****************************************************************************/
  76
  77void    pci_interrupt(int irq, void *id, struct pt_regs *fp);
  78
  79/*****************************************************************************/
  80
  81/*
  82 *      Some platforms have custom ways of reseting the PCI bus.
  83 */
  84
  85void pci_resetbus(void)
  86{
  87#ifdef CONFIG_eLIA
  88        int     i;
  89
  90#ifdef DEBUGPCI
  91        printk(KERN_DEBUG "pci_resetbus()\n");
  92#endif
  93
  94        *((volatile unsigned short *) (MCF_MBAR+MCFSIM_PADDR)) |= eLIA_PCIRESET;
  95        for (i = 0; (i < 1000); i++) {
  96                *((volatile unsigned short *) (MCF_MBAR + MCFSIM_PADAT)) = 
  97                        (ppdata | eLIA_PCIRESET);
  98        }
  99
 100
 101        *((volatile unsigned short *) (MCF_MBAR + MCFSIM_PADAT)) = ppdata;
 102#endif
 103}
 104
 105/*****************************************************************************/
 106
 107int pcibios_assign_resource_slot(int slot)
 108{
 109        volatile unsigned long  *rp;
 110        volatile unsigned char  *ip;
 111        unsigned int            idsel, addr, val, align, i;
 112        int                     bar;
 113
 114#ifdef DEBUGPCI
 115        printk(KERN_INFO "pcibios_assign_resource_slot(slot=%x)\n", slot);
 116#endif
 117
 118        rp = (volatile unsigned long *) COMEM_BASE;
 119        idsel = COMEM_DA_ADDR(0x1 << (slot + 16));
 120
 121        /* Try to assign resource to each BAR */
 122        for (bar = 0; (bar < 6); bar++) {
 123                addr = COMEM_PCIBUS + PCI_BASE_ADDRESS_0 + (bar * 4);
 124                rp[LREG(COMEM_DAHBASE)] = COMEM_DA_CFGRD | idsel;
 125                val = rp[LREG(addr)];
 126#ifdef DEBUGRES
 127                printk(KERN_DEBUG "-----------------------------------"
 128                        "-------------------------------------\n");
 129                printk(KERN_DEBUG "BAR[%d]: read=%08x ", bar, val);
 130#endif
 131
 132                rp[LREG(COMEM_DAHBASE)] = COMEM_DA_CFGWR | idsel;
 133                rp[LREG(addr)] = 0xffffffff;
 134
 135                rp[LREG(COMEM_DAHBASE)] = COMEM_DA_CFGRD | idsel;
 136                val = rp[LREG(addr)];
 137#ifdef DEBUGRES
 138                printk(KERN_DEBUG "write=%08x ", val);
 139#endif
 140                if (val == 0) {
 141#ifdef DEBUGRES
 142                        printk(KERN_DEBUG "\n");
 143#endif
 144                        continue;
 145                }
 146
 147                /* Determine space required by BAR */
 148                /* FIXME: this should go backwords from 0x80000000... */
 149                for (i = 0; (i < 32); i++) {
 150                        if ((0x1 << i) & (val & 0xfffffffc))
 151                                break;
 152                }
 153
 154#ifdef DEBUGRES
 155                printk(KERN_DEBUG "size=%08x(%d)\n", (0x1 << i), i);
 156#endif
 157                i = 0x1 << i;
 158
 159                /* Assign a resource */
 160                if (val & PCI_BASE_ADDRESS_SPACE_IO) {
 161                        if (i < PCI_MINIO)
 162                                i = PCI_MINIO;
 163#ifdef DEBUGRES
 164                        printk(KERN_DEBUG "BAR[%d]: IO size=%08x iobase=%08x\n",
 165                                bar, i, pci_iobase);
 166#endif
 167                        if (i > 0xffff) {
 168                                /* Invalid size?? */
 169                                val = 0 | PCI_BASE_ADDRESS_SPACE_IO;
 170#ifdef DEBUGRES
 171                                printk(KERN_DEBUG "BAR[%d]: too big for IO??\n", bar);
 172#endif
 173                        } else {
 174                                /* Check for un-alignment */
 175                                if ((align = pci_iobase % i))
 176                                        pci_iobase += (i - align);
 177                                val = pci_iobase | PCI_BASE_ADDRESS_SPACE_IO;
 178                                pci_iobase += i;
 179                        }
 180                } else {
 181                        if (i < PCI_MINMEM)
 182                                i = PCI_MINMEM;
 183#ifdef DEBUGRES
 184                        printk(KERN_DEBUG "BAR[%d]: MEMORY size=%08x membase=%08x\n",
 185                                bar, i, pci_membase);
 186#endif
 187                        /* Check for un-alignment */
 188                        if ((align = pci_membase % i))
 189                                pci_membase += (i - align);
 190                        val = pci_membase | PCI_BASE_ADDRESS_SPACE_MEMORY;
 191                        pci_membase += i;
 192                }
 193
 194                /* Write resource back into BAR register */
 195                rp[LREG(COMEM_DAHBASE)] = COMEM_DA_CFGWR | idsel;
 196                rp[LREG(addr)] = val;
 197#ifdef DEBUGRES
 198                printk(KERN_DEBUG "BAR[%d]: assigned bar=%08x\n", bar, val);
 199#endif
 200        }
 201
 202#ifdef DEBUGRES
 203        printk(KERN_DEBUG "-----------------------------------"
 204                        "-------------------------------------\n");
 205#endif
 206
 207        /* Assign IRQ if one is wanted... */
 208        ip = (volatile unsigned char *) (COMEM_BASE + COMEM_PCIBUS);
 209        rp[LREG(COMEM_DAHBASE)] = COMEM_DA_CFGRD | idsel;
 210
 211        addr = (PCI_INTERRUPT_PIN & 0xfc) + (~PCI_INTERRUPT_PIN & 0x03);
 212        if (ip[addr]) {
 213                rp[LREG(COMEM_DAHBASE)] = COMEM_DA_CFGWR | idsel;
 214                addr = (PCI_INTERRUPT_LINE & 0xfc)+(~PCI_INTERRUPT_LINE & 0x03);
 215                ip[addr] = 25;
 216#ifdef DEBUGRES
 217                printk(KERN_DEBUG "IRQ LINE=25\n");
 218#endif
 219        }
 220
 221        return(0);
 222}
 223
 224/*****************************************************************************/
 225
 226int pcibios_enable_slot(int slot)
 227{
 228        volatile unsigned long  *rp;
 229        volatile unsigned short *wp;
 230        unsigned int            idsel, addr;
 231        unsigned short          cmd;
 232
 233#ifdef DEBUGPCI
 234        printk(KERN_DEBUG "pcibios_enbale_slot(slot=%x)\n", slot);
 235#endif
 236
 237        rp = (volatile unsigned long *) COMEM_BASE;
 238        wp = (volatile unsigned short *) COMEM_BASE;
 239        idsel = COMEM_DA_ADDR(0x1 << (slot + 16));
 240
 241        /* Get current command settings */
 242        addr = COMEM_PCIBUS + PCI_COMMAND;
 243        addr = (addr & ~0x3) + (~addr & 0x02);
 244        rp[LREG(COMEM_DAHBASE)] = COMEM_DA_CFGRD | idsel;
 245        cmd = wp[WREG(addr)];
 246        /*val = ((val & 0xff) << 8) | ((val >> 8) & 0xff);*/
 247
 248        /* Enable I/O and memory accesses to this device */
 249        rp[LREG(COMEM_DAHBASE)] = COMEM_DA_CFGWR | idsel;
 250        cmd |= PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER;
 251        wp[WREG(addr)] = cmd;
 252
 253        return(0);
 254}
 255
 256/*****************************************************************************/
 257
 258void pcibios_assign_resources(void)
 259{
 260        volatile unsigned long  *rp;
 261        unsigned long           sel, id;
 262        int                     slot;
 263
 264        rp = (volatile unsigned long *) COMEM_BASE;
 265
 266        /*
 267         *      Do a quick scan of the PCI bus and see what is here.
 268         */
 269        for (slot = COMEM_MINDEV; (slot <= COMEM_MAXDEV); slot++) {
 270                sel = COMEM_DA_CFGRD | COMEM_DA_ADDR(0x1 << (slot + 16));
 271                rp[LREG(COMEM_DAHBASE)] = sel;
 272                rp[LREG(COMEM_PCIBUS)] = 0; /* Clear bus */
 273                id = rp[LREG(COMEM_PCIBUS)];
 274                if ((id != 0) && ((id & 0xffff0000) != (sel & 0xffff0000))) {
 275                        printk(KERN_INFO "PCI: slot=%d id=%08x\n", slot, (int) id);
 276                        pci_slotmask |= 0x1 << slot;
 277                        pcibios_assign_resource_slot(slot);
 278                        pcibios_enable_slot(slot);
 279                }
 280        }
 281}
 282
 283/*****************************************************************************/
 284
 285int pcibios_init(void)
 286{
 287        volatile unsigned long  *rp;
 288        unsigned long           sel, id;
 289        int                     slot;
 290
 291#ifdef DEBUGPCI
 292        printk(KERN_DEBUG "pcibios_init()\n");
 293#endif
 294
 295        pci_resetbus();
 296
 297        /*
 298         *      Do some sort of basic check to see if the CO-MEM part
 299         *      is present... This works ok, but I think we really need
 300         *      something better...
 301         */
 302        rp = (volatile unsigned long *) COMEM_BASE;
 303        if ((rp[LREG(COMEM_LBUSCFG)] & 0xff) != 0x50) {
 304                printk(KERN_INFO "PCI: no PCI bus present\n");
 305                return(0);
 306        }
 307
 308#ifdef COMEM_BRIDGEDEV
 309        /*
 310         *      Setup the PCI bridge device first. It needs resources too,
 311         *      so that bus masters can get to its shared memory.
 312         */
 313        slot = COMEM_BRIDGEDEV;
 314        sel = COMEM_DA_CFGRD | COMEM_DA_ADDR(0x1 << (slot + 16));
 315        rp[LREG(COMEM_DAHBASE)] = sel;
 316        rp[LREG(COMEM_PCIBUS)] = 0; /* Clear bus */
 317        id = rp[LREG(COMEM_PCIBUS)];
 318        if ((id == 0) || ((id & 0xffff0000) == (sel & 0xffff0000))) {
 319                printk(KERN_INFO "PCI: no PCI bus bridge present\n");
 320                return(0);
 321        }
 322
 323        printk(KERN_INFO "PCI: bridge device at slot=%d id=%08x\n", slot, (int) id);
 324        pci_slotmask |= 0x1 << slot;
 325        pci_shmemaddr = pci_membase;
 326        pcibios_assign_resource_slot(slot);
 327        pcibios_enable_slot(slot);
 328#endif
 329
 330        pci_bus_is_present = 1;
 331
 332        /* Get PCI irq for local vectoring */
 333        if (request_irq(COMEM_IRQ, pci_interrupt, 0, "PCI bridge", NULL)) {
 334                printk(KERN_WARNING "PCI: failed to acquire interrupt %d\n", COMEM_IRQ);
 335        } else {
 336                mcf_autovector(COMEM_IRQ);
 337        }
 338
 339        pcibios_assign_resources();
 340
 341        return(0);
 342}
 343
 344/*****************************************************************************/
 345
 346char *pcibios_setup(char *option)
 347{
 348        /* Nothing for us to handle. */
 349        return(option);
 350}
 351/*****************************************************************************/
 352
 353void pcibios_fixup_bus(struct pci_bus *b)
 354{
 355}
 356
 357/*****************************************************************************/
 358
 359void pcibios_align_resource(void *data, struct resource *res,
 360                                resource_size_t size, resource_size_t align)
 361{
 362}
 363
 364/*****************************************************************************/
 365
 366int pcibios_enable_device(struct pci_dev *dev, int mask)
 367{
 368        int slot;
 369
 370        slot = PCI_SLOT(dev->devfn);
 371        if ((dev->bus == 0) && (pci_slotmask & (1 << slot)))
 372                pcibios_enable_slot(slot);
 373        return(0);
 374}
 375
 376/*****************************************************************************/
 377
 378/*
 379 *      Local routines to interrcept the standard I/O and vector handling
 380 *      code. Don't include this 'till now - initialization code above needs
 381 *      access to the real code too.
 382 */
 383#include <asm/mcfpci.h>
 384
 385/*****************************************************************************/
 386
 387void pci_outb(unsigned char val, unsigned int addr)
 388{
 389        volatile unsigned long  *rp;
 390        volatile unsigned char  *bp;
 391
 392#ifdef DEBUGIO
 393        printk(KERN_DEBUG "pci_outb(val=%02x,addr=%x)\n", val, addr);
 394#endif
 395
 396        rp = (volatile unsigned long *) COMEM_BASE;
 397        bp = (volatile unsigned char *) COMEM_BASE;
 398        rp[LREG(COMEM_DAHBASE)] = COMEM_DA_IOWR | COMEM_DA_ADDR(addr);
 399        addr = (addr & ~0x3) + (~addr & 0x03);
 400        bp[(COMEM_PCIBUS + COMEM_DA_OFFSET(addr))] = val;
 401}
 402
 403/*****************************************************************************/
 404
 405void pci_outw(unsigned short val, unsigned int addr)
 406{
 407        volatile unsigned long  *rp;
 408        volatile unsigned short *sp;
 409
 410#ifdef DEBUGIO
 411        printk(KERN_DEBUG "pci_outw(val=%04x,addr=%x)\n", val, addr);
 412#endif
 413
 414        rp = (volatile unsigned long *) COMEM_BASE;
 415        sp = (volatile unsigned short *) COMEM_BASE;
 416        rp[LREG(COMEM_DAHBASE)] = COMEM_DA_IOWR | COMEM_DA_ADDR(addr);
 417        addr = (addr & ~0x3) + (~addr & 0x02);
 418        if (pci_byteswap)
 419                val = ((val & 0xff) << 8) | ((val >> 8) & 0xff);
 420        sp[WREG(COMEM_PCIBUS + COMEM_DA_OFFSET(addr))] = val;
 421}
 422
 423/*****************************************************************************/
 424
 425void pci_outl(unsigned int val, unsigned int addr)
 426{
 427        volatile unsigned long  *rp;
 428        volatile unsigned int   *lp;
 429
 430#ifdef DEBUGIO
 431        printk(KERN_DEBUG "pci_outl(val=%08x,addr=%x)\n", val, addr);
 432#endif
 433
 434        rp = (volatile unsigned long *) COMEM_BASE;
 435        lp = (volatile unsigned int *) COMEM_BASE;
 436        rp[LREG(COMEM_DAHBASE)] = COMEM_DA_IOWR | COMEM_DA_ADDR(addr);
 437
 438        if (pci_byteswap)
 439                val = (val << 24) | ((val & 0x0000ff00) << 8) |
 440                        ((val & 0x00ff0000) >> 8) | (val >> 24);
 441
 442        lp[LREG(COMEM_PCIBUS + COMEM_DA_OFFSET(addr))] = val;
 443}
 444
 445/*****************************************************************************/
 446
 447unsigned long   pci_blmask[] = {
 448        0x000000e0,
 449        0x000000d0,
 450        0x000000b0,
 451        0x00000070
 452};
 453
 454unsigned char pci_inb(unsigned int addr)
 455{
 456        volatile unsigned long  *rp;
 457        volatile unsigned char  *bp;
 458        unsigned long           r;
 459        unsigned char           val;
 460
 461#ifdef DEBUGIO
 462        printk(KERN_DEBUG "pci_inb(addr=%x)\n", addr);
 463#endif
 464
 465        rp = (volatile unsigned long *) COMEM_BASE;
 466        bp = (volatile unsigned char *) COMEM_BASE;
 467
 468        r = COMEM_DA_IORD | COMEM_DA_ADDR(addr) | pci_blmask[(addr & 0x3)];
 469        rp[LREG(COMEM_DAHBASE)] = r;
 470
 471        addr = (addr & ~0x3) + (~addr & 0x3);
 472        val = bp[(COMEM_PCIBUS + COMEM_DA_OFFSET(addr))];
 473        return(val);
 474}
 475
 476/*****************************************************************************/
 477
 478unsigned long   pci_bwmask[] = {
 479        0x000000c0,
 480        0x000000c0,
 481        0x00000030,
 482        0x00000030
 483};
 484
 485unsigned short pci_inw(unsigned int addr)
 486{
 487        volatile unsigned long  *rp;
 488        volatile unsigned short *sp;
 489        unsigned long           r;
 490        unsigned short          val;
 491
 492#ifdef DEBUGIO
 493        printk(KERN_DEBUG "pci_inw(addr=%x)", addr);
 494#endif
 495
 496        rp = (volatile unsigned long *) COMEM_BASE;
 497        r = COMEM_DA_IORD | COMEM_DA_ADDR(addr) | pci_bwmask[(addr & 0x3)];
 498        rp[LREG(COMEM_DAHBASE)] = r;
 499
 500        sp = (volatile unsigned short *) COMEM_BASE;
 501        addr = (addr & ~0x3) + (~addr & 0x02);
 502        val = sp[WREG(COMEM_PCIBUS + COMEM_DA_OFFSET(addr))];
 503        if (pci_byteswap)
 504                val = ((val & 0xff) << 8) | ((val >> 8) & 0xff);
 505#ifdef DEBUGIO
 506        printk(KERN_DEBUG "=%04x\n", val);
 507#endif
 508        return(val);
 509}
 510
 511/*****************************************************************************/
 512
 513unsigned int pci_inl(unsigned int addr)
 514{
 515        volatile unsigned long  *rp;
 516        volatile unsigned int   *lp;
 517        unsigned int            val;
 518
 519#ifdef DEBUGIO
 520        printk(KERN_DEBUG "pci_inl(addr=%x)", addr);
 521#endif
 522
 523        rp = (volatile unsigned long *) COMEM_BASE;
 524        lp = (volatile unsigned int *) COMEM_BASE;
 525        rp[LREG(COMEM_DAHBASE)] = COMEM_DA_IORD | COMEM_DA_ADDR(addr);
 526        val = lp[LREG(COMEM_PCIBUS + COMEM_DA_OFFSET(addr))];
 527
 528        if (pci_byteswap)
 529                val = (val << 24) | ((val & 0x0000ff00) << 8) |
 530                        ((val & 0x00ff0000) >> 8) | (val >> 24);
 531
 532#ifdef DEBUGIO
 533        printk(KERN_DEBUG "=%08x\n", val);
 534#endif
 535        return(val);
 536}
 537
 538/*****************************************************************************/
 539
 540void pci_outsb(void *addr, void *buf, int len)
 541{
 542        volatile unsigned long  *rp;
 543        volatile unsigned char  *bp;
 544        unsigned char           *dp = (unsigned char *) buf;
 545        unsigned int            a = (unsigned int) addr;
 546
 547#ifdef DEBUGIO
 548        printk(KERN_DEBUG "pci_outsb(addr=%x,buf=%x,len=%d)\n", (int)addr, (int)buf, len);
 549#endif
 550
 551        rp = (volatile unsigned long *) COMEM_BASE;
 552        rp[LREG(COMEM_DAHBASE)] = COMEM_DA_IOWR | COMEM_DA_ADDR(a);
 553
 554        a = (a & ~0x3) + (~a & 0x03);
 555        bp = (volatile unsigned char *)
 556                (COMEM_BASE + COMEM_PCIBUS + COMEM_DA_OFFSET(a));
 557
 558        while (len--)
 559                *bp = *dp++;
 560}
 561
 562/*****************************************************************************/
 563
 564void pci_outsw(void *addr, void *buf, int len)
 565{
 566        volatile unsigned long  *rp;
 567        volatile unsigned short *wp;
 568        unsigned short          w, *dp = (unsigned short *) buf;
 569        unsigned int            a = (unsigned int) addr;
 570
 571#ifdef DEBUGIO
 572        printk(KERN_DEBUG "pci_outsw(addr=%x,buf=%x,len=%d)\n", (int)addr, (int)buf, len);
 573#endif
 574
 575        rp = (volatile unsigned long *) COMEM_BASE;
 576        rp[LREG(COMEM_DAHBASE)] = COMEM_DA_IOWR | COMEM_DA_ADDR(a);
 577
 578        a = (a & ~0x3) + (~a & 0x2);
 579        wp = (volatile unsigned short *)
 580                (COMEM_BASE + COMEM_PCIBUS + COMEM_DA_OFFSET(a));
 581
 582        while (len--) {
 583                w = *dp++;
 584                if (pci_byteswap)
 585                        w = ((w & 0xff) << 8) | ((w >> 8) & 0xff);
 586                *wp = w;
 587        }
 588}
 589
 590/*****************************************************************************/
 591
 592void pci_outsl(void *addr, void *buf, int len)
 593{
 594        volatile unsigned long  *rp;
 595        volatile unsigned long  *lp;
 596        unsigned long           l, *dp = (unsigned long *) buf;
 597        unsigned int            a = (unsigned int) addr;
 598
 599#ifdef DEBUGIO
 600        printk(KERN_DEBUG "pci_outsl(addr=%x,buf=%x,len=%d)\n", (int)addr, (int)buf, len);
 601#endif
 602
 603        rp = (volatile unsigned long *) COMEM_BASE;
 604        rp[LREG(COMEM_DAHBASE)] = COMEM_DA_IOWR | COMEM_DA_ADDR(a);
 605
 606        lp = (volatile unsigned long *)
 607                (COMEM_BASE + COMEM_PCIBUS + COMEM_DA_OFFSET(a));
 608
 609        while (len--) {
 610                l = *dp++;
 611                if (pci_byteswap)
 612                        l = (l << 24) | ((l & 0x0000ff00) << 8) |
 613                                ((l & 0x00ff0000) >> 8) | (l >> 24);
 614                *lp = l;
 615        }
 616}
 617
 618/*****************************************************************************/
 619
 620void pci_insb(void *addr, void *buf, int len)
 621{
 622        volatile unsigned long  *rp;
 623        volatile unsigned char  *bp;
 624        unsigned char           *dp = (unsigned char *) buf;
 625        unsigned int            a = (unsigned int) addr;
 626
 627#ifdef DEBUGIO
 628        printk(KERN_DEBUG "pci_insb(addr=%x,buf=%x,len=%d)\n", (int)addr, (int)buf, len);
 629#endif
 630
 631        rp = (volatile unsigned long *) COMEM_BASE;
 632        rp[LREG(COMEM_DAHBASE)] = COMEM_DA_IORD | COMEM_DA_ADDR(a);
 633
 634        a = (a & ~0x3) + (~a & 0x03);
 635        bp = (volatile unsigned char *)
 636                (COMEM_BASE + COMEM_PCIBUS + COMEM_DA_OFFSET(a));
 637
 638        while (len--)
 639                *dp++ = *bp;
 640}
 641
 642/*****************************************************************************/
 643
 644void pci_insw(void *addr, void *buf, int len)
 645{
 646        volatile unsigned long  *rp;
 647        volatile unsigned short *wp;
 648        unsigned short          w, *dp = (unsigned short *) buf;
 649        unsigned int            a = (unsigned int) addr;
 650
 651#ifdef DEBUGIO
 652        printk(KERN_DEBUG "pci_insw(addr=%x,buf=%x,len=%d)\n", (int)addr, (int)buf, len);
 653#endif
 654
 655        rp = (volatile unsigned long *) COMEM_BASE;
 656        rp[LREG(COMEM_DAHBASE)] = COMEM_DA_IORD | COMEM_DA_ADDR(a);
 657
 658        a = (a & ~0x3) + (~a & 0x2);
 659        wp = (volatile unsigned short *)
 660                (COMEM_BASE + COMEM_PCIBUS + COMEM_DA_OFFSET(a));
 661
 662        while (len--) {
 663                w = *wp;
 664                if (pci_byteswap)
 665                        w = ((w & 0xff) << 8) | ((w >> 8) & 0xff);
 666                *dp++ = w;
 667        }
 668}
 669
 670/*****************************************************************************/
 671
 672void pci_insl(void *addr, void *buf, int len)
 673{
 674        volatile unsigned long  *rp;
 675        volatile unsigned long  *lp;
 676        unsigned long           l, *dp = (unsigned long *) buf;
 677        unsigned int            a = (unsigned int) addr;
 678
 679#ifdef DEBUGIO
 680        printk(KERN_DEBUG "pci_insl(addr=%x,buf=%x,len=%d)\n", (int)addr, (int)buf, len);
 681#endif
 682
 683        rp = (volatile unsigned long *) COMEM_BASE;
 684        rp[LREG(COMEM_DAHBASE)] = COMEM_DA_IORD | COMEM_DA_ADDR(a);
 685
 686        lp = (volatile unsigned long *)
 687                (COMEM_BASE + COMEM_PCIBUS + COMEM_DA_OFFSET(a));
 688
 689        while (len--) {
 690                l = *lp;
 691                if (pci_byteswap)
 692                        l = (l << 24) | ((l & 0x0000ff00) << 8) |
 693                                ((l & 0x00ff0000) >> 8) | (l >> 24);
 694                *dp++ = l;
 695        }
 696}
 697
 698/*****************************************************************************/
 699
 700struct pci_localirqlist {
 701        void            (*handler)(int, void *, struct pt_regs *);
 702        const char      *device;
 703        void            *dev_id;
 704};
 705
 706struct pci_localirqlist pci_irqlist[COMEM_MAXPCI];
 707
 708/*****************************************************************************/
 709
 710int pci_request_irq(unsigned int irq,
 711        void (*handler)(int, void *, struct pt_regs *),
 712        unsigned long flags, const char *device, void *dev_id)
 713{
 714        int     i;
 715
 716#ifdef DEBUGIO
 717        printk(KERN_DEBUG "pci_request_irq(irq=%d,handler=%x,flags=%x,device=%s,"
 718                "dev_id=%x)\n", irq, (int) handler, (int) flags, device,
 719                (int) dev_id);
 720#endif
 721
 722        /* Check if this interrupt handler is already lodged */
 723        for (i = 0; (i < COMEM_MAXPCI); i++) {
 724                if (pci_irqlist[i].handler == handler)
 725                        return(0);
 726        }
 727
 728        /* Find a free spot to put this handler */
 729        for (i = 0; (i < COMEM_MAXPCI); i++) {
 730                if (pci_irqlist[i].handler == 0) {
 731                        pci_irqlist[i].handler = handler;
 732                        pci_irqlist[i].device = device;
 733                        pci_irqlist[i].dev_id = dev_id;
 734                        return(0);
 735                }
 736        }
 737
 738        /* Couldn't fit?? */
 739        return(1);
 740}
 741
 742/*****************************************************************************/
 743
 744void pci_free_irq(unsigned int irq, void *dev_id)
 745{
 746        int     i;
 747
 748#ifdef DEBUGIO
 749        printk(KERN_DEBUG "pci_free_irq(irq=%d,dev_id=%x)\n", irq, (int) dev_id);
 750#endif
 751
 752        if (dev_id == (void *) NULL)
 753                return;
 754
 755        /* Check if this interrupt handler is lodged */
 756        for (i = 0; (i < COMEM_MAXPCI); i++) {
 757                if (pci_irqlist[i].dev_id == dev_id) {
 758                        pci_irqlist[i].handler = NULL;
 759                        pci_irqlist[i].device = NULL;
 760                        pci_irqlist[i].dev_id = NULL;
 761                        break;
 762                }
 763        }
 764}
 765
 766/*****************************************************************************/
 767
 768void pci_interrupt(int irq, void *id, struct pt_regs *fp)
 769{
 770        int     i;
 771
 772#ifdef DEBUGIO
 773        printk(KERN_DEBUG "pci_interrupt(irq=%d,id=%x,fp=%x)\n", irq, (int) id, (int) fp);
 774#endif
 775
 776        for (i = 0; (i < COMEM_MAXPCI); i++) {
 777                if (pci_irqlist[i].handler)
 778                        (*pci_irqlist[i].handler)(irq,pci_irqlist[i].dev_id,fp);
 779        }
 780}
 781
 782/*****************************************************************************/
 783
 784/*
 785 *      The shared memory region is broken up into contiguous 512 byte
 786 *      regions for easy allocation... This is not an optimal solution
 787 *      but it makes allocation and freeing regions really easy.
 788 */
 789
 790#define PCI_MEMSLOTSIZE         512
 791#define PCI_MEMSLOTS            (COMEM_SHMEMSIZE / PCI_MEMSLOTSIZE)
 792
 793char    pci_shmemmap[PCI_MEMSLOTS];
 794
 795
 796void *pci_bmalloc(int size)
 797{
 798        int     i, j, nrslots;
 799
 800#ifdef DEBUGIO
 801        printk(KERN_DEBUG "pci_bmalloc(size=%d)\n", size);
 802#endif
 803
 804        if (size <= 0)
 805                return((void *) NULL);
 806
 807        nrslots = (size - 1) / PCI_MEMSLOTSIZE;
 808
 809        for (i = 0; (i < (PCI_MEMSLOTS-nrslots)); i++) {
 810                if (pci_shmemmap[i] == 0) {
 811                        for (j = i+1; (j < (i+nrslots)); j++) {
 812                                if (pci_shmemmap[j])
 813                                        goto restart;
 814                        }
 815
 816                        for (j = i; (j <= i+nrslots); j++)
 817                                pci_shmemmap[j] = 1;
 818                        break;
 819                }
 820restart:
 821        }
 822
 823        return((void *) (COMEM_BASE + COMEM_SHMEM + (i * PCI_MEMSLOTSIZE)));
 824}
 825
 826/*****************************************************************************/
 827
 828void pci_bmfree(void *mp, int size)
 829{
 830        int     i, j, nrslots;
 831
 832#ifdef DEBUGIO
 833        printk(KERN_DEBUG "pci_bmfree(mp=%x,size=%d)\n", (int) mp, size);
 834#endif
 835
 836        nrslots = size / PCI_MEMSLOTSIZE;
 837        i = (((unsigned long) mp) - (COMEM_BASE + COMEM_SHMEM)) /
 838                PCI_MEMSLOTSIZE;
 839
 840        for (j = i; (j < (i+nrslots)); j++)
 841                pci_shmemmap[j] = 0;
 842}
 843
 844/*****************************************************************************/
 845
 846unsigned long pci_virt_to_bus(volatile void *address)
 847{
 848        unsigned long   l;
 849
 850#ifdef DEBUGIO
 851        printk(KERN_DEBUG "pci_virt_to_bus(address=%x)", (int) address);
 852#endif
 853
 854        l = ((unsigned long) address) - COMEM_BASE;
 855#ifdef DEBUGIO
 856        printk(KERN_DEBUG "=%x\n", (int) (l+pci_shmemaddr));
 857#endif
 858        return(l + pci_shmemaddr);
 859}
 860
 861/*****************************************************************************/
 862
 863void *pci_bus_to_virt(unsigned long address)
 864{
 865        unsigned long   l;
 866
 867#ifdef DEBUGIO
 868        printk(KERN_DEBUG "pci_bus_to_virt(address=%x)", (int) address);
 869#endif
 870
 871        l = address - pci_shmemaddr;
 872#ifdef DEBUGIO
 873        printk(KERN_DEBUG "=%x\n", (int) (address + COMEM_BASE));
 874#endif
 875        return((void *) (address + COMEM_BASE));
 876}
 877
 878/*****************************************************************************/
 879
 880void pci_bmcpyto(void *dst, void *src, int len)
 881{
 882        unsigned long   *dp, *sp, val;
 883        unsigned char   *dcp, *scp;
 884        int             i, j;
 885
 886#ifdef DEBUGIO
 887        printk(KERN_DEBUG "pci_bmcpyto(dst=%x,src=%x,len=%d)\n", (int)dst, (int)src, len);
 888#endif
 889
 890        dp = (unsigned long *) dst;
 891        sp = (unsigned long *) src;
 892        i = len >> 2;
 893
 894#if 0
 895        printk(KERN_INFO "DATA:");
 896        scp = (unsigned char *) sp;
 897        for (i = 0; (i < len); i++) {
 898                if ((i % 16) == 0) printk(KERN_INFO "\n%04x: ", i);
 899                printk(KERN_INFO "%02x ", *scp++);
 900        }
 901        printk(KERN_INFO "\n");
 902#endif
 903
 904        for (j = 0; (i >= 0); i--, j++) {
 905                val = *sp++;
 906                val = (val << 24) | ((val & 0x0000ff00) << 8) |
 907                        ((val & 0x00ff0000) >> 8) | (val >> 24);
 908                *dp++ = val;
 909        }
 910
 911        if (len & 0x3) {
 912                dcp = (unsigned char *) dp;
 913                scp = ((unsigned char *) sp) + 3;
 914                for (i = 0; (i < (len & 0x3)); i++)
 915                        *dcp++ = *scp--;
 916        }
 917}
 918
 919/*****************************************************************************/
 920
 921void pci_bmcpyfrom(void *dst, void *src, int len)
 922{
 923        unsigned long   *dp, *sp, val;
 924        unsigned char   *dcp, *scp;
 925        int             i;
 926
 927#ifdef DEBUGIO
 928        printk(KERN_DEBUG "pci_bmcpyfrom(dst=%x,src=%x,len=%d)\n",(int)dst,(int)src,len);
 929#endif
 930
 931        dp = (unsigned long *) dst;
 932        sp = (unsigned long *) src;
 933        i = len >> 2;
 934
 935        for (; (i >= 0); i--) {
 936                val = *sp++;
 937                val = (val << 24) | ((val & 0x0000ff00) << 8) |
 938                        ((val & 0x00ff0000) >> 8) | (val >> 24);
 939                *dp++ = val;
 940        }
 941
 942        if (len & 0x3) {
 943                dcp = ((unsigned char *) dp) + 3;
 944                scp = (unsigned char *) sp;
 945                for (i = 0; (i < (len & 0x3)); i++)
 946                        *dcp++ = *scp--;
 947        }
 948
 949#if 0
 950        printk(KERN_INFO "DATA:");
 951        dcp = (unsigned char *) dst;
 952        for (i = 0; (i < len); i++) {
 953                if ((i % 16) == 0) printk(KERN_INFO "\n%04x: ", i);
 954                printk(KERN_INFO "%02x ", *dcp++);
 955        }
 956        printk(KERN_INFO "\n");
 957#endif
 958}
 959
 960/*****************************************************************************/
 961
 962void *pci_alloc_consistent(struct pci_dev *dev, size_t size, dma_addr_t *dma_addr)
 963{
 964        void *mp;
 965        if ((mp = pci_bmalloc(size)) != NULL) {
 966                dma_addr = mp - (COMEM_BASE + COMEM_SHMEM);
 967                return(mp);
 968        }
 969        *dma_addr = (dma_addr_t) NULL;
 970        return(NULL);
 971}
 972
 973/*****************************************************************************/
 974
 975void pci_free_consistent(struct pci_dev *dev, size_t size, void *cpu_addr, dma_addr_t dma_addr)
 976{
 977        pci_bmfree(cpu_addr, size);
 978}
 979
 980/*****************************************************************************/
 981