/****************************************************************************/ /* * linux/include/asm-m68knommu/ide.h * * Copyright (C) 1994-1996 Linus Torvalds & authors * Copyright (C) 2001 Lineo Inc., davidm@uclinux.org */ /****************************************************************************/ #ifndef _M68KNOMMU_IDE_H #define _M68KNOMMU_IDE_H #ifdef __KERNEL__ /****************************************************************************/ #include <linux/config.h> #include <linux/interrupt.h> #include <asm/setup.h> #include <asm/io.h> #include <asm/irq.h> /****************************************************************************/ /* * some coldfire specifics */ #ifdef CONFIG_COLDFIRE #include <asm/coldfire.h> #include <asm/mcfsim.h> /* * Save some space, only have 1 interface */ #define MAX_HWIFS 1 /* we only have one interface for now */ #ifdef CONFIG_SECUREEDGEMP3 #define MCFSIM_LOCALCS MCFSIM_CSCR4 #else #define MCFSIM_LOCALCS MCFSIM_CSCR6 #endif #endif /* CONFIG_COLDFIRE */ /****************************************************************************/ /* * Fix up things that may not have been provided */ #ifndef MAX_HWIFS #define MAX_HWIFS 4 /* same as the other archs */ #endif #undef SUPPORT_SLOW_DATA_PORTS #define SUPPORT_SLOW_DATA_PORTS 0 #undef SUPPORT_VLB_SYNC #define SUPPORT_VLB_SYNC 0 /* this definition is used only on startup .. */ #undef HD_DATA #define HD_DATA NULL #define DBGIDE(fmt,a...) // #define DBGIDE(fmt,a...) printk(fmt, ##a) #define IDE_INLINE __inline__ // #define IDE_INLINE /****************************************************************************/ typedef union { unsigned all : 8; /* all of the bits together */ struct { unsigned bit7 : 1; /* always 1 */ unsigned lba : 1; /* using LBA instead of CHS */ unsigned bit5 : 1; /* always 1 */ unsigned unit : 1; /* drive select number, 0 or 1 */ unsigned head : 4; /* always zeros here */ } b; } select_t; /* * our list of ports/irq's for different boards */ static struct m68k_ide_defaults { ide_ioreg_t base; int irq; } m68k_ide_defaults[MAX_HWIFS] = { #if defined(CONFIG_SECUREEDGEMP3) { ((ide_ioreg_t)0x30800000), 29 }, #elif defined(CONFIG_eLIA) { ((ide_ioreg_t)0x30c00000), 29 }, #else { ((ide_ioreg_t)0x0), 0 } #endif }; /****************************************************************************/ static IDE_INLINE int ide_default_irq(ide_ioreg_t base) { int i; for (i = 0; i < MAX_HWIFS; i++) if (m68k_ide_defaults[i].base == base) return(m68k_ide_defaults[i].irq); return 0; } static IDE_INLINE ide_ioreg_t ide_default_io_base(int index) { if (index >= 0 && index < MAX_HWIFS) return(m68k_ide_defaults[index].base); return 0; } /* * Set up a hw structure for a specified data port, control port and IRQ. * This should follow whatever the default interface uses. */ static IDE_INLINE void ide_init_hwif_ports( hw_regs_t *hw, ide_ioreg_t data_port, ide_ioreg_t ctrl_port, int *irq) { ide_ioreg_t reg = data_port; int i; for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) { hw->io_ports[i] = reg; reg += 1; } if (ctrl_port) { hw->io_ports[IDE_CONTROL_OFFSET] = ctrl_port; } else { hw->io_ports[IDE_CONTROL_OFFSET] = data_port + 0xe; } } #define ide_init_default_irq(base) ide_default_irq(base) static IDE_INLINE int ide_request_irq( unsigned int irq, void (*handler)(int, void *, struct pt_regs *), unsigned long flags, const char *device, void *dev_id) { #ifdef CONFIG_COLDFIRE mcf_autovector(irq); #endif return(request_irq(irq, handler, flags, device, dev_id)); } static IDE_INLINE void ide_free_irq(unsigned int irq, void *dev_id) { free_irq(irq, dev_id); } static IDE_INLINE int ide_check_region(ide_ioreg_t from, unsigned int extent) { return 0; } static IDE_INLINE void ide_request_region(ide_ioreg_t from, unsigned int extent, const char *name) { } static IDE_INLINE void ide_release_region(ide_ioreg_t from, unsigned int extent) { } static IDE_INLINE void ide_fix_driveid(struct hd_driveid *id) { #ifdef CONFIG_COLDFIRE int i, n; unsigned short *wp = (unsigned short *) id; int avoid[] = {49, 51, 52, 59, -1 }; /* do not swap these words */ /* Need to byte swap shorts, but not char fields */ for (i = n = 0; i < sizeof(*id) / sizeof(*wp); i++, wp++) { if (avoid[n] == i) { n++; continue; } *wp = ((*wp & 0xff) << 8) | ((*wp >> 8) & 0xff); } /* have to word swap the one 32 bit field */ id->lba_capacity = ((id->lba_capacity & 0xffff) << 16) | ((id->lba_capacity >> 16) & 0xffff); #endif } static IDE_INLINE void ide_release_lock (int *ide_lock) { } static IDE_INLINE void ide_get_lock( int *ide_lock, void (*handler)(int, void *, struct pt_regs *), void *data) { } #define ide_ack_intr(hwif) \ ((hwif)->hw.ack_intr ? (hwif)->hw.ack_intr(hwif) : 1) #define ide__sti() __sti() /****************************************************************************/ /* * System specific IO requirements */ #ifdef CONFIG_COLDFIRE #ifdef CONFIG_SECUREEDGEMP3 /* Replace standard IO functions for funky mapping of MP3 board */ #undef outb #undef outb_p #undef inb #undef inb_p #define outb(v, a) ide_outb(v, (unsigned long) (a)) #define outb_p(v, a) ide_outb(v, (unsigned long) (a)) #define inb(a) ide_inb((unsigned long) (a)) #define inb_p(a) ide_inb((unsigned long) (a)) #define ADDR8_PTR(addr) (((addr) & 0x1) ? (0x8000 + (addr) - 1) : (addr)) #define ADDR16_PTR(addr) (addr) #define ADDR32_PTR(addr) (addr) #define SWAP8(w) ((((w) & 0xffff) << 8) | (((w) & 0xffff) >> 8)) #define SWAP16(w) (w) #define SWAP32(w) (w) static IDE_INLINE void ide_outb(unsigned int val, unsigned int addr) { volatile unsigned short *rp; DBGIDE("%s(val=%x,addr=%x)\n", __FUNCTION__, val, addr); rp = (volatile unsigned short *) ADDR8_PTR(addr); *rp = SWAP8(val); } static IDE_INLINE int ide_inb(unsigned int addr) { volatile unsigned short *rp, val; DBGIDE("%s(addr=%x)\n", __FUNCTION__, addr); rp = (volatile unsigned short *) ADDR8_PTR(addr); val = *rp; return(SWAP8(val)); } static IDE_INLINE void ide_outw(unsigned int val, unsigned int addr) { volatile unsigned short *rp; DBGIDE("%s(val=%x,addr=%x)\n", __FUNCTION__, val, addr); rp = (volatile unsigned short *) ADDR16_PTR(addr); *rp = SWAP16(val); } static IDE_INLINE void ide_outsw(unsigned int addr, const void *vbuf, unsigned long len) { volatile unsigned short *rp, val; unsigned short *buf; DBGIDE("%s(addr=%x,vbuf=%p,len=%x)\n", __FUNCTION__, addr, vbuf, len); buf = (unsigned short *) vbuf; rp = (volatile unsigned short *) ADDR16_PTR(addr); for (; (len > 0); len--) { val = *buf++; *rp = SWAP16(val); } } static IDE_INLINE int ide_inw(unsigned int addr) { volatile unsigned short *rp, val; DBGIDE("%s(addr=%x)\n", __FUNCTION__, addr); rp = (volatile unsigned short *) ADDR16_PTR(addr); val = *rp; return(SWAP16(val)); } static IDE_INLINE void ide_insw(unsigned int addr, void *vbuf, unsigned long len) { volatile unsigned short *rp; unsigned short w, *buf; DBGIDE("%s(addr=%x,vbuf=%p,len=%x)\n", __FUNCTION__, addr, vbuf, len); buf = (unsigned short *) vbuf; rp = (volatile unsigned short *) ADDR16_PTR(addr); for (; (len > 0); len--) { w = *rp; *buf++ = SWAP16(w); } } static IDE_INLINE void ide_insl(unsigned int addr, void *vbuf, unsigned long len) { volatile unsigned long *rp; unsigned long w, *buf; DBGIDE("%s(addr=%x,vbuf=%p,len=%x)\n", __FUNCTION__, addr, vbuf, len); buf = (unsigned long *) vbuf; rp = (volatile unsigned long *) ADDR32_PTR(addr); for (; (len > 0); len--) { w = *rp; *buf++ = SWAP32(w); } } static IDE_INLINE void ide_outsl(unsigned int addr, const void *vbuf, unsigned long len) { volatile unsigned long *rp, val; unsigned long *buf; DBGIDE("%s(addr=%x,vbuf=%p,len=%x)\n", __FUNCTION__, addr, vbuf, len); buf = (unsigned long *) vbuf; rp = (volatile unsigned long *) ADDR32_PTR(addr); for (; (len > 0); len--) { val = *buf++; *rp = SWAP32(val); } } #elif CONFIG_eLIA /* 8/16 bit acesses are controlled by flicking bits in the CS register */ #define ACCESS_MODE_16BIT() \ *((volatile unsigned short *) (MCF_MBAR + MCFSIM_LOCALCS)) = 0x0080 #define ACCESS_MODE_8BIT() \ *((volatile unsigned short *) (MCF_MBAR + MCFSIM_LOCALCS)) = 0x0040 static IDE_INLINE void ide_outw(unsigned int val, unsigned int addr) { ACCESS_MODE_16BIT(); outw(val, addr); ACCESS_MODE_8BIT(); } static IDE_INLINE void ide_outsw(unsigned int addr, const void *vbuf, unsigned long len) { ACCESS_MODE_16BIT(); outsw(addr, vbuf, len); ACCESS_MODE_8BIT(); } static IDE_INLINE int ide_inw(unsigned int addr) { int ret; ACCESS_MODE_16BIT(); ret = inw(addr); ACCESS_MODE_8BIT(); return(ret); } static IDE_INLINE void ide_insw(unsigned int addr, void *vbuf, unsigned long len) { ACCESS_MODE_16BIT(); insw(addr, vbuf, len); ACCESS_MODE_8BIT(); } static IDE_INLINE void ide_insl(unsigned int addr, void *vbuf, unsigned long len) { ACCESS_MODE_16BIT(); insl(addr, vbuf, len); ACCESS_MODE_8BIT(); } static IDE_INLINE void ide_outsl(unsigned int addr, const void *vbuf, unsigned long len) { ACCESS_MODE_16BIT(); outsl(addr, vbuf, len); ACCESS_MODE_8BIT(); } #endif /* CONFIG_SECUREEDGEMP3 */ #undef outw #undef outw_p #undef outsw #undef inw #undef inw_p #undef insw #undef insl #undef outsl #define outw(v, a) ide_outw(v, (unsigned long) (a)) #define outw_p(v, a) ide_outw(v, (unsigned long) (a)) #define outsw(a, b, n) ide_outsw((unsigned long) (a), b, n) #define inw(a) ide_inw((unsigned long) (a)) #define inw_p(a) ide_inw((unsigned long) (a)) #define insw(a, b, n) ide_insw((unsigned long) (a), b, n) #define insl(a, b, n) ide_insl((unsigned long) (a), b, n) #define outsl(a, b, n) ide_outsl((unsigned long) (a), b, n) #endif CONFIG_COLDFIRE /****************************************************************************/ #endif /* __KERNEL__ */ #endif /* _M68KNOMMU_IDE_H */ /****************************************************************************/