/* * $Id: io_hd64465.c,v 1.7 2001/05/09 07:39:36 gniibe Exp $ * by Greg Banks * (c) 2000 PocketPenguins Inc * * Derived from io_hd64461.c, which bore the message: * Copyright (C) 2000 YAEGASHI Takeshi * * Typical I/O routines for HD64465 system. */ #include #include #include #include #include #define HD64465_DEBUG 0 #if HD64465_DEBUG #define DPRINTK(args...) printk(args) #define DIPRINTK(n, args...) if (hd64465_io_debug>(n)) printk(args) #else #define DPRINTK(args...) #define DIPRINTK(n, args...) #endif /* This is a hack suitable only for debugging IO port problems */ int hd64465_io_debug; EXPORT_SYMBOL(hd64465_io_debug); /* Low iomap maps port 0-1K to addresses in 8byte chunks */ #define HD64465_IOMAP_LO_THRESH 0x400 #define HD64465_IOMAP_LO_SHIFT 3 #define HD64465_IOMAP_LO_MASK ((1<>HD64465_IOMAP_LO_SHIFT) static unsigned long hd64465_iomap_lo[HD64465_IOMAP_LO_NMAP]; static unsigned char hd64465_iomap_lo_shift[HD64465_IOMAP_LO_NMAP]; /* High iomap maps port 1K-64K to addresses in 1K chunks */ #define HD64465_IOMAP_HI_THRESH 0x10000 #define HD64465_IOMAP_HI_SHIFT 10 #define HD64465_IOMAP_HI_MASK ((1<>HD64465_IOMAP_HI_SHIFT) static unsigned long hd64465_iomap_hi[HD64465_IOMAP_HI_NMAP]; static unsigned char hd64465_iomap_hi_shift[HD64465_IOMAP_HI_NMAP]; #ifndef MAX #define MAX(a,b) ((a)>(b)?(a):(b)) #endif #define PORT2ADDR(x) (sh_mv.mv_isa_port2addr(x)) void hd64465_port_map(unsigned short baseport, unsigned int nports, unsigned long addr, unsigned char shift) { unsigned int port, endport = baseport + nports; DPRINTK("hd64465_port_map(base=0x%04hx, n=0x%04hx, addr=0x%08lx,endport=0x%04x)\n", baseport, nports, addr,endport); for (port = baseport ; port < endport && port < HD64465_IOMAP_LO_THRESH ; port += (1<>HD64465_IOMAP_LO_SHIFT] = addr; hd64465_iomap_lo_shift[port>>HD64465_IOMAP_LO_SHIFT] = shift; addr += (1<<(HD64465_IOMAP_LO_SHIFT)); } for (port = MAX(baseport, HD64465_IOMAP_LO_THRESH) ; port < endport && port < HD64465_IOMAP_HI_THRESH ; port += (1<>HD64465_IOMAP_HI_SHIFT] = addr; hd64465_iomap_hi_shift[port>>HD64465_IOMAP_HI_SHIFT] = shift; addr += (1<<(HD64465_IOMAP_HI_SHIFT)); } } EXPORT_SYMBOL(hd64465_port_map); void hd64465_port_unmap(unsigned short baseport, unsigned int nports) { unsigned int port, endport = baseport + nports; DPRINTK("hd64465_port_unmap(base=0x%04hx, n=0x%04hx)\n", baseport, nports); for (port = baseport ; port < endport && port < HD64465_IOMAP_LO_THRESH ; port += (1<>HD64465_IOMAP_LO_SHIFT] = 0; } for (port = MAX(baseport, HD64465_IOMAP_LO_THRESH) ; port < endport && port < HD64465_IOMAP_HI_THRESH ; port += (1<>HD64465_IOMAP_HI_SHIFT] = 0; } } EXPORT_SYMBOL(hd64465_port_unmap); unsigned long hd64465_isa_port2addr(unsigned long port) { unsigned long addr = 0; unsigned char shift; /* handle remapping of low IO ports */ if (port < HD64465_IOMAP_LO_THRESH) { addr = hd64465_iomap_lo[port >> HD64465_IOMAP_LO_SHIFT]; shift = hd64465_iomap_lo_shift[port >> HD64465_IOMAP_LO_SHIFT]; if (addr != 0) addr += (port & HD64465_IOMAP_LO_MASK) << shift; else printk(KERN_NOTICE "io_hd64465: access to un-mapped port %lx\n", port); } else if (port < HD64465_IOMAP_HI_THRESH) { addr = hd64465_iomap_hi[port >> HD64465_IOMAP_HI_SHIFT]; shift = hd64465_iomap_hi_shift[port >> HD64465_IOMAP_HI_SHIFT]; if (addr != 0) addr += (port & HD64465_IOMAP_HI_MASK) << shift; else printk(KERN_NOTICE "io_hd64465: access to un-mapped port %lx\n", port); } /* HD64465 internal devices (0xb0000000) */ else if (port < 0x20000) addr = CONFIG_HD64465_IOBASE + port - 0x10000; /* Whole physical address space (0xa0000000) */ else addr = P2SEGADDR(port); DIPRINTK(2, "PORT2ADDR(0x%08lx) = 0x%08lx\n", port, addr); return addr; } static inline void delay(void) { ctrl_inw(0xa0000000); } unsigned char hd64465_inb(unsigned long port) { unsigned long addr = PORT2ADDR(port); unsigned long b = (addr == 0 ? 0 : *(volatile unsigned char*)addr); DIPRINTK(0, "inb(%08lx) = %02x\n", addr, (unsigned)b); return b; } unsigned char hd64465_inb_p(unsigned long port) { unsigned long v; unsigned long addr = PORT2ADDR(port); v = (addr == 0 ? 0 : *(volatile unsigned char*)addr); delay(); DIPRINTK(0, "inb_p(%08lx) = %02x\n", addr, (unsigned)v); return v; } unsigned short hd64465_inw(unsigned long port) { unsigned long addr = PORT2ADDR(port); unsigned long b = (addr == 0 ? 0 : *(volatile unsigned short*)addr); DIPRINTK(0, "inw(%08lx) = %04lx\n", addr, b); return b; } unsigned int hd64465_inl(unsigned long port) { unsigned long addr = PORT2ADDR(port); unsigned int b = (addr == 0 ? 0 : *(volatile unsigned long*)addr); DIPRINTK(0, "inl(%08lx) = %08x\n", addr, b); return b; } void hd64465_insb(unsigned long port, void *buffer, unsigned long count) { unsigned char *buf=buffer; while(count--) *buf++=inb(port); } void hd64465_insw(unsigned long port, void *buffer, unsigned long count) { unsigned short *buf=buffer; while(count--) *buf++=inw(port); } void hd64465_insl(unsigned long port, void *buffer, unsigned long count) { unsigned long *buf=buffer; while(count--) *buf++=inl(port); } void hd64465_outb(unsigned char b, unsigned long port) { unsigned long addr = PORT2ADDR(port); DIPRINTK(0, "outb(%02x, %08lx)\n", (unsigned)b, addr); if (addr != 0) *(volatile unsigned char*)addr = b; } void hd64465_outb_p(unsigned char b, unsigned long port) { unsigned long addr = PORT2ADDR(port); DIPRINTK(0, "outb_p(%02x, %08lx)\n", (unsigned)b, addr); if (addr != 0) *(volatile unsigned char*)addr = b; delay(); } void hd64465_outw(unsigned short b, unsigned long port) { unsigned long addr = PORT2ADDR(port); DIPRINTK(0, "outw(%04x, %08lx)\n", (unsigned)b, addr); if (addr != 0) *(volatile unsigned short*)addr = b; } void hd64465_outl(unsigned int b, unsigned long port) { unsigned long addr = PORT2ADDR(port); DIPRINTK(0, "outl(%08x, %08lx)\n", b, addr); if (addr != 0) *(volatile unsigned long*)addr = b; } void hd64465_outsb(unsigned long port, const void *buffer, unsigned long count) { const unsigned char *buf=buffer; while(count--) outb(*buf++, port); } void hd64465_outsw(unsigned long port, const void *buffer, unsigned long count) { const unsigned short *buf=buffer; while(count--) outw(*buf++, port); } void hd64465_outsl(unsigned long port, const void *buffer, unsigned long count) { const unsigned long *buf=buffer; while(count--) outl(*buf++, port); }