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