Moved source_fa into trunk
This commit is contained in:
107
FireBee/trunk/usb/store/asm-m68k/byteorder.h
Normal file
107
FireBee/trunk/usb/store/asm-m68k/byteorder.h
Normal file
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2007 Freescale Semiconductor, Inc.
|
||||
* TsiChung Liew (Tsi-Chung.Liew@freescale.com)
|
||||
*
|
||||
* See file CREDITS for list of people who contributed to this
|
||||
* project.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _M68K_BYTEORDER_H
|
||||
#define _M68K_BYTEORDER_H
|
||||
|
||||
#include "types.h"
|
||||
|
||||
#ifdef __GNUC__
|
||||
#define __sw16(x) \
|
||||
((__u16)( \
|
||||
(((__u16)(x) & (__u16)0x00ffU) << 8) | \
|
||||
(((__u16)(x) & (__u16)0xff00U) >> 8) ))
|
||||
#define __sw32(x) \
|
||||
((__u32)( \
|
||||
(((__u32)(x)) << 24) | \
|
||||
(((__u32)(x) & (__u32)0x0000ff00UL) << 8) | \
|
||||
(((__u32)(x) & (__u32)0x00ff0000UL) >> 8) | \
|
||||
(((__u32)(x)) >> 24) ))
|
||||
|
||||
extern __inline__ unsigned ld_le16(const volatile unsigned short *addr)
|
||||
{
|
||||
unsigned result = *addr;
|
||||
return __sw16(result);
|
||||
}
|
||||
|
||||
extern __inline__ void st_le16(volatile unsigned short *addr,
|
||||
const unsigned val)
|
||||
{
|
||||
*addr = __sw16(val);
|
||||
}
|
||||
|
||||
extern __inline__ unsigned ld_le32(const volatile unsigned *addr)
|
||||
{
|
||||
unsigned result = *addr;
|
||||
return __sw32(result);
|
||||
}
|
||||
|
||||
extern __inline__ void st_le32(volatile unsigned *addr, const unsigned val)
|
||||
{
|
||||
*addr = __sw32(val);
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* alas, egcs sounds like it has a bug in this code that doesn't use the
|
||||
inline asm correctly, and can cause file corruption. Until I hear that
|
||||
it's fixed, I can live without the extra speed. I hope. */
|
||||
#if !(__GNUC__ >= 2 && __GNUC_MINOR__ >= 90)
|
||||
#if 0
|
||||
# define __arch_swab16(x) ld_le16(&x)
|
||||
# define __arch_swab32(x) ld_le32(&x)
|
||||
#else
|
||||
static __inline__ __attribute__ ((const))
|
||||
__u16 ___arch__swab16(__u16 value)
|
||||
{
|
||||
return __sw16(value);
|
||||
}
|
||||
|
||||
static __inline__ __attribute__ ((const))
|
||||
__u32 ___arch__swab32(__u32 value)
|
||||
{
|
||||
return __sw32(value);
|
||||
}
|
||||
|
||||
#define __arch__swab32(x) ___arch__swab32(x)
|
||||
#define __arch__swab16(x) ___arch__swab16(x)
|
||||
#endif /* 0 */
|
||||
|
||||
#endif
|
||||
|
||||
/* The same, but returns converted value from the location pointer by addr. */
|
||||
#define __arch__swab16p(addr) ld_le16(addr)
|
||||
#define __arch__swab32p(addr) ld_le32(addr)
|
||||
|
||||
/* The same, but do the conversion in situ, ie. put the value back to addr. */
|
||||
#define __arch__swab16s(addr) st_le16(addr,*addr)
|
||||
#define __arch__swab32s(addr) st_le32(addr,*addr)
|
||||
#endif
|
||||
|
||||
#endif /* __GNUC__ */
|
||||
|
||||
#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
|
||||
#define __BYTEORDER_HAS_U64__
|
||||
#endif
|
||||
#include "byteorder/big_endian.h"
|
||||
|
||||
#endif /* _M68K_BYTEORDER_H */
|
||||
69
FireBee/trunk/usb/store/asm-m68k/byteorder/big_endian.h
Normal file
69
FireBee/trunk/usb/store/asm-m68k/byteorder/big_endian.h
Normal file
@@ -0,0 +1,69 @@
|
||||
#ifndef _LINUX_BYTEORDER_BIG_ENDIAN_H
|
||||
#define _LINUX_BYTEORDER_BIG_ENDIAN_H
|
||||
|
||||
#ifndef __BIG_ENDIAN
|
||||
#define __BIG_ENDIAN 4321
|
||||
#endif
|
||||
#ifndef __BIG_ENDIAN_BITFIELD
|
||||
#define __BIG_ENDIAN_BITFIELD
|
||||
#endif
|
||||
#define __BYTE_ORDER __BIG_ENDIAN
|
||||
|
||||
#include "swab.h"
|
||||
|
||||
#define __constant_htonl(x) ((__u32)(x))
|
||||
#define __constant_ntohl(x) ((__u32)(x))
|
||||
#define __constant_htons(x) ((__u16)(x))
|
||||
#define __constant_ntohs(x) ((__u16)(x))
|
||||
#define __constant_cpu_to_le64(x) ___swab64((x))
|
||||
#define __constant_le64_to_cpu(x) ___swab64((x))
|
||||
#define __constant_cpu_to_le32(x) ___swab32((x))
|
||||
#define __constant_le32_to_cpu(x) ___swab32((x))
|
||||
#define __constant_cpu_to_le16(x) ___swab16((x))
|
||||
#define __constant_le16_to_cpu(x) ___swab16((x))
|
||||
#define __constant_cpu_to_be64(x) ((__u64)(x))
|
||||
#define __constant_be64_to_cpu(x) ((__u64)(x))
|
||||
#define __constant_cpu_to_be32(x) ((__u32)(x))
|
||||
#define __constant_be32_to_cpu(x) ((__u32)(x))
|
||||
#define __constant_cpu_to_be16(x) ((__u16)(x))
|
||||
#define __constant_be16_to_cpu(x) ((__u16)(x))
|
||||
#define __cpu_to_le64(x) __swab64((x))
|
||||
#define __le64_to_cpu(x) __swab64((x))
|
||||
#define __cpu_to_le32(x) __swab32((x))
|
||||
#define __le32_to_cpu(x) __swab32((x))
|
||||
#define __cpu_to_le16(x) __swab16((x))
|
||||
#define __le16_to_cpu(x) __swab16((x))
|
||||
#define __cpu_to_be64(x) ((__u64)(x))
|
||||
#define __be64_to_cpu(x) ((__u64)(x))
|
||||
#define __cpu_to_be32(x) ((__u32)(x))
|
||||
#define __be32_to_cpu(x) ((__u32)(x))
|
||||
#define __cpu_to_be16(x) ((__u16)(x))
|
||||
#define __be16_to_cpu(x) ((__u16)(x))
|
||||
#define __cpu_to_le64p(x) __swab64p((x))
|
||||
#define __le64_to_cpup(x) __swab64p((x))
|
||||
#define __cpu_to_le32p(x) __swab32p((x))
|
||||
#define __le32_to_cpup(x) __swab32p((x))
|
||||
#define __cpu_to_le16p(x) __swab16p((x))
|
||||
#define __le16_to_cpup(x) __swab16p((x))
|
||||
#define __cpu_to_be64p(x) (*(__u64*)(x))
|
||||
#define __be64_to_cpup(x) (*(__u64*)(x))
|
||||
#define __cpu_to_be32p(x) (*(__u32*)(x))
|
||||
#define __be32_to_cpup(x) (*(__u32*)(x))
|
||||
#define __cpu_to_be16p(x) (*(__u16*)(x))
|
||||
#define __be16_to_cpup(x) (*(__u16*)(x))
|
||||
#define __cpu_to_le64s(x) __swab64s((x))
|
||||
#define __le64_to_cpus(x) __swab64s((x))
|
||||
#define __cpu_to_le32s(x) __swab32s((x))
|
||||
#define __le32_to_cpus(x) __swab32s((x))
|
||||
#define __cpu_to_le16s(x) __swab16s((x))
|
||||
#define __le16_to_cpus(x) __swab16s((x))
|
||||
#define __cpu_to_be64s(x) do {} while (0)
|
||||
#define __be64_to_cpus(x) do {} while (0)
|
||||
#define __cpu_to_be32s(x) do {} while (0)
|
||||
#define __be32_to_cpus(x) do {} while (0)
|
||||
#define __cpu_to_be16s(x) do {} while (0)
|
||||
#define __be16_to_cpus(x) do {} while (0)
|
||||
|
||||
#include "generic.h"
|
||||
|
||||
#endif /* _LINUX_BYTEORDER_BIG_ENDIAN_H */
|
||||
180
FireBee/trunk/usb/store/asm-m68k/byteorder/generic.h
Normal file
180
FireBee/trunk/usb/store/asm-m68k/byteorder/generic.h
Normal file
@@ -0,0 +1,180 @@
|
||||
#ifndef _LINUX_BYTEORDER_GENERIC_H
|
||||
#define _LINUX_BYTEORDER_GENERIC_H
|
||||
|
||||
/*
|
||||
* linux/byteorder_generic.h
|
||||
* Generic Byte-reordering support
|
||||
*
|
||||
* Francois-Rene Rideau <fare@tunes.org> 19970707
|
||||
* gathered all the good ideas from all asm-foo/byteorder.h into one file,
|
||||
* cleaned them up.
|
||||
* I hope it is compliant with non-GCC compilers.
|
||||
* I decided to put __BYTEORDER_HAS_U64__ in byteorder.h,
|
||||
* because I wasn't sure it would be ok to put it in types.h
|
||||
* Upgraded it to 2.1.43
|
||||
* Francois-Rene Rideau <fare@tunes.org> 19971012
|
||||
* Upgraded it to 2.1.57
|
||||
* to please Linus T., replaced huge #ifdef's between little/big endian
|
||||
* by nestedly #include'd files.
|
||||
* Francois-Rene Rideau <fare@tunes.org> 19971205
|
||||
* Made it to 2.1.71; now a facelift:
|
||||
* Put files under include/linux/byteorder/
|
||||
* Split swab from generic support.
|
||||
*
|
||||
* TODO:
|
||||
* = Regular kernel maintainers could also replace all these manual
|
||||
* byteswap macros that remain, disseminated among drivers,
|
||||
* after some grep or the sources...
|
||||
* = Linus might want to rename all these macros and files to fit his taste,
|
||||
* to fit his personal naming scheme.
|
||||
* = it seems that a few drivers would also appreciate
|
||||
* nybble swapping support...
|
||||
* = every architecture could add their byteswap macro in asm/byteorder.h
|
||||
* see how some architectures already do (i386, alpha, ppc, etc)
|
||||
* = cpu_to_beXX and beXX_to_cpu might some day need to be well
|
||||
* distinguished throughout the kernel. This is not the case currently,
|
||||
* since little endian, big endian, and pdp endian machines needn't it.
|
||||
* But this might be the case for, say, a port of Linux to 20/21 bit
|
||||
* architectures (and F21 Linux addict around?).
|
||||
*/
|
||||
|
||||
/*
|
||||
* The following macros are to be defined by <asm/byteorder.h>:
|
||||
*
|
||||
* Conversion of long and short int between network and host format
|
||||
* ntohl(__u32 x)
|
||||
* ntohs(__u16 x)
|
||||
* htonl(__u32 x)
|
||||
* htons(__u16 x)
|
||||
* It seems that some programs (which? where? or perhaps a standard? POSIX?)
|
||||
* might like the above to be functions, not macros (why?).
|
||||
* if that's true, then detect them, and take measures.
|
||||
* Anyway, the measure is: define only ___ntohl as a macro instead,
|
||||
* and in a separate file, have
|
||||
* unsigned long inline ntohl(x){return ___ntohl(x);}
|
||||
*
|
||||
* The same for constant arguments
|
||||
* __constant_ntohl(__u32 x)
|
||||
* __constant_ntohs(__u16 x)
|
||||
* __constant_htonl(__u32 x)
|
||||
* __constant_htons(__u16 x)
|
||||
*
|
||||
* Conversion of XX-bit integers (16- 32- or 64-)
|
||||
* between native CPU format and little/big endian format
|
||||
* 64-bit stuff only defined for proper architectures
|
||||
* cpu_to_[bl]eXX(__uXX x)
|
||||
* [bl]eXX_to_cpu(__uXX x)
|
||||
*
|
||||
* The same, but takes a pointer to the value to convert
|
||||
* cpu_to_[bl]eXXp(__uXX x)
|
||||
* [bl]eXX_to_cpup(__uXX x)
|
||||
*
|
||||
* The same, but change in situ
|
||||
* cpu_to_[bl]eXXs(__uXX x)
|
||||
* [bl]eXX_to_cpus(__uXX x)
|
||||
*
|
||||
* See asm-foo/byteorder.h for examples of how to provide
|
||||
* architecture-optimized versions
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
//#if defined(__KERNEL__)
|
||||
/*
|
||||
* inside the kernel, we can use nicknames;
|
||||
* outside of it, we must avoid POSIX namespace pollution...
|
||||
*/
|
||||
#define cpu_to_le64 __cpu_to_le64
|
||||
#define le64_to_cpu __le64_to_cpu
|
||||
#define cpu_to_le32 __cpu_to_le32
|
||||
#define le32_to_cpu __le32_to_cpu
|
||||
#define cpu_to_le16 __cpu_to_le16
|
||||
#define le16_to_cpu __le16_to_cpu
|
||||
#define cpu_to_be64 __cpu_to_be64
|
||||
#define be64_to_cpu __be64_to_cpu
|
||||
#define cpu_to_be32 __cpu_to_be32
|
||||
#define be32_to_cpu __be32_to_cpu
|
||||
#define cpu_to_be16 __cpu_to_be16
|
||||
#define be16_to_cpu __be16_to_cpu
|
||||
#define cpu_to_le64p __cpu_to_le64p
|
||||
#define le64_to_cpup __le64_to_cpup
|
||||
#define cpu_to_le32p __cpu_to_le32p
|
||||
#define le32_to_cpup __le32_to_cpup
|
||||
#define cpu_to_le16p __cpu_to_le16p
|
||||
#define le16_to_cpup __le16_to_cpup
|
||||
#define cpu_to_be64p __cpu_to_be64p
|
||||
#define be64_to_cpup __be64_to_cpup
|
||||
#define cpu_to_be32p __cpu_to_be32p
|
||||
#define be32_to_cpup __be32_to_cpup
|
||||
#define cpu_to_be16p __cpu_to_be16p
|
||||
#define be16_to_cpup __be16_to_cpup
|
||||
#define cpu_to_le64s __cpu_to_le64s
|
||||
#define le64_to_cpus __le64_to_cpus
|
||||
#define cpu_to_le32s __cpu_to_le32s
|
||||
#define le32_to_cpus __le32_to_cpus
|
||||
#define cpu_to_le16s __cpu_to_le16s
|
||||
#define le16_to_cpus __le16_to_cpus
|
||||
#define cpu_to_be64s __cpu_to_be64s
|
||||
#define be64_to_cpus __be64_to_cpus
|
||||
#define cpu_to_be32s __cpu_to_be32s
|
||||
#define be32_to_cpus __be32_to_cpus
|
||||
#define cpu_to_be16s __cpu_to_be16s
|
||||
#define be16_to_cpus __be16_to_cpus
|
||||
//#endif
|
||||
|
||||
|
||||
/*
|
||||
* Handle ntohl and suches. These have various compatibility
|
||||
* issues - like we want to give the prototype even though we
|
||||
* also have a macro for them in case some strange program
|
||||
* wants to take the address of the thing or something..
|
||||
*
|
||||
* Note that these used to return a "long" in libc5, even though
|
||||
* long is often 64-bit these days.. Thus the casts.
|
||||
*
|
||||
* They have to be macros in order to do the constant folding
|
||||
* correctly - if the argument passed into a inline function
|
||||
* it is no longer constant according to gcc..
|
||||
*/
|
||||
|
||||
#undef ntohl
|
||||
#undef ntohs
|
||||
#undef htonl
|
||||
#undef htons
|
||||
|
||||
/*
|
||||
* Do the prototypes. Somebody might want to take the
|
||||
* address or some such sick thing..
|
||||
*/
|
||||
#if defined(__KERNEL__) || (defined (__GLIBC__) && __GLIBC__ >= 2)
|
||||
extern __u32 ntohl(__u32);
|
||||
extern __u32 htonl(__u32);
|
||||
#else
|
||||
extern unsigned long int ntohl(unsigned long int);
|
||||
extern unsigned long int htonl(unsigned long int);
|
||||
#endif
|
||||
extern unsigned short int ntohs(unsigned short int);
|
||||
extern unsigned short int htons(unsigned short int);
|
||||
|
||||
|
||||
#if defined(__GNUC__) && (__GNUC__ >= 2)
|
||||
|
||||
#define ___htonl(x) __cpu_to_be32(x)
|
||||
#define ___htons(x) __cpu_to_be16(x)
|
||||
#define ___ntohl(x) __be32_to_cpu(x)
|
||||
#define ___ntohs(x) __be16_to_cpu(x)
|
||||
|
||||
#if defined(__KERNEL__) || (defined (__GLIBC__) && __GLIBC__ >= 2)
|
||||
#define htonl(x) ___htonl(x)
|
||||
#define ntohl(x) ___ntohl(x)
|
||||
#else
|
||||
#define htonl(x) ((unsigned long)___htonl(x))
|
||||
#define ntohl(x) ((unsigned long)___ntohl(x))
|
||||
#endif
|
||||
#define htons(x) ___htons(x)
|
||||
#define ntohs(x) ___ntohs(x)
|
||||
|
||||
#endif /* OPTIMIZE */
|
||||
|
||||
|
||||
#endif /* _LINUX_BYTEORDER_GENERIC_H */
|
||||
69
FireBee/trunk/usb/store/asm-m68k/byteorder/little_endian.h
Normal file
69
FireBee/trunk/usb/store/asm-m68k/byteorder/little_endian.h
Normal file
@@ -0,0 +1,69 @@
|
||||
#ifndef _LINUX_BYTEORDER_LITTLE_ENDIAN_H
|
||||
#define _LINUX_BYTEORDER_LITTLE_ENDIAN_H
|
||||
|
||||
#ifndef __LITTLE_ENDIAN
|
||||
#define __LITTLE_ENDIAN 1234
|
||||
#endif
|
||||
#ifndef __LITTLE_ENDIAN_BITFIELD
|
||||
#define __LITTLE_ENDIAN_BITFIELD
|
||||
#endif
|
||||
#define __BYTE_ORDER __LITTLE_ENDIAN
|
||||
|
||||
#include "swab.h"
|
||||
|
||||
#define __constant_htonl(x) ___constant_swab32((x))
|
||||
#define __constant_ntohl(x) ___constant_swab32((x))
|
||||
#define __constant_htons(x) ___constant_swab16((x))
|
||||
#define __constant_ntohs(x) ___constant_swab16((x))
|
||||
#define __constant_cpu_to_le64(x) ((__u64)(x))
|
||||
#define __constant_le64_to_cpu(x) ((__u64)(x))
|
||||
#define __constant_cpu_to_le32(x) ((__u32)(x))
|
||||
#define __constant_le32_to_cpu(x) ((__u32)(x))
|
||||
#define __constant_cpu_to_le16(x) ((__u16)(x))
|
||||
#define __constant_le16_to_cpu(x) ((__u16)(x))
|
||||
#define __constant_cpu_to_be64(x) ___constant_swab64((x))
|
||||
#define __constant_be64_to_cpu(x) ___constant_swab64((x))
|
||||
#define __constant_cpu_to_be32(x) ___constant_swab32((x))
|
||||
#define __constant_be32_to_cpu(x) ___constant_swab32((x))
|
||||
#define __constant_cpu_to_be16(x) ___constant_swab16((x))
|
||||
#define __constant_be16_to_cpu(x) ___constant_swab16((x))
|
||||
#define __cpu_to_le64(x) ((__u64)(x))
|
||||
#define __le64_to_cpu(x) ((__u64)(x))
|
||||
#define __cpu_to_le32(x) ((__u32)(x))
|
||||
#define __le32_to_cpu(x) ((__u32)(x))
|
||||
#define __cpu_to_le16(x) ((__u16)(x))
|
||||
#define __le16_to_cpu(x) ((__u16)(x))
|
||||
#define __cpu_to_be64(x) __swab64((x))
|
||||
#define __be64_to_cpu(x) __swab64((x))
|
||||
#define __cpu_to_be32(x) __swab32((x))
|
||||
#define __be32_to_cpu(x) __swab32((x))
|
||||
#define __cpu_to_be16(x) __swab16((x))
|
||||
#define __be16_to_cpu(x) __swab16((x))
|
||||
#define __cpu_to_le64p(x) (*(__u64*)(x))
|
||||
#define __le64_to_cpup(x) (*(__u64*)(x))
|
||||
#define __cpu_to_le32p(x) (*(__u32*)(x))
|
||||
#define __le32_to_cpup(x) (*(__u32*)(x))
|
||||
#define __cpu_to_le16p(x) (*(__u16*)(x))
|
||||
#define __le16_to_cpup(x) (*(__u16*)(x))
|
||||
#define __cpu_to_be64p(x) __swab64p((x))
|
||||
#define __be64_to_cpup(x) __swab64p((x))
|
||||
#define __cpu_to_be32p(x) __swab32p((x))
|
||||
#define __be32_to_cpup(x) __swab32p((x))
|
||||
#define __cpu_to_be16p(x) __swab16p((x))
|
||||
#define __be16_to_cpup(x) __swab16p((x))
|
||||
#define __cpu_to_le64s(x) do {} while (0)
|
||||
#define __le64_to_cpus(x) do {} while (0)
|
||||
#define __cpu_to_le32s(x) do {} while (0)
|
||||
#define __le32_to_cpus(x) do {} while (0)
|
||||
#define __cpu_to_le16s(x) do {} while (0)
|
||||
#define __le16_to_cpus(x) do {} while (0)
|
||||
#define __cpu_to_be64s(x) __swab64s((x))
|
||||
#define __be64_to_cpus(x) __swab64s((x))
|
||||
#define __cpu_to_be32s(x) __swab32s((x))
|
||||
#define __be32_to_cpus(x) __swab32s((x))
|
||||
#define __cpu_to_be16s(x) __swab16s((x))
|
||||
#define __be16_to_cpus(x) __swab16s((x))
|
||||
|
||||
#include "generic.h"
|
||||
|
||||
#endif /* _LINUX_BYTEORDER_LITTLE_ENDIAN_H */
|
||||
158
FireBee/trunk/usb/store/asm-m68k/byteorder/swab.h
Normal file
158
FireBee/trunk/usb/store/asm-m68k/byteorder/swab.h
Normal file
@@ -0,0 +1,158 @@
|
||||
#ifndef _LINUX_BYTEORDER_SWAB_H
|
||||
#define _LINUX_BYTEORDER_SWAB_H
|
||||
|
||||
/*
|
||||
* linux/byteorder/swab.h
|
||||
* Byte-swapping, independently from CPU endianness
|
||||
* swabXX[ps]?(foo)
|
||||
*
|
||||
* Francois-Rene Rideau <fare@tunes.org> 19971205
|
||||
* separated swab functions from cpu_to_XX,
|
||||
* to clean up support for bizarre-endian architectures.
|
||||
*
|
||||
* See asm-i386/byteorder.h and suches for examples of how to provide
|
||||
* architecture-dependent optimized versions
|
||||
*
|
||||
*/
|
||||
|
||||
/* casts are necessary for constants, because we never know how for sure
|
||||
* how U/UL/ULL map to __u16, __u32, __u64. At least not in a portable way.
|
||||
*/
|
||||
#define ___swab16(x) \
|
||||
((__u16)( \
|
||||
(((__u16)(x) & (__u16)0x00ffU) << 8) | \
|
||||
(((__u16)(x) & (__u16)0xff00U) >> 8) ))
|
||||
#define ___swab32(x) \
|
||||
((__u32)( \
|
||||
(((__u32)(x) & (__u32)0x000000ffUL) << 24) | \
|
||||
(((__u32)(x) & (__u32)0x0000ff00UL) << 8) | \
|
||||
(((__u32)(x) & (__u32)0x00ff0000UL) >> 8) | \
|
||||
(((__u32)(x) & (__u32)0xff000000UL) >> 24) ))
|
||||
#define ___swab64(x) \
|
||||
((__u64)( \
|
||||
(__u64)(((__u64)(x) & (__u64)0x00000000000000ffULL) << 56) | \
|
||||
(__u64)(((__u64)(x) & (__u64)0x000000000000ff00ULL) << 40) | \
|
||||
(__u64)(((__u64)(x) & (__u64)0x0000000000ff0000ULL) << 24) | \
|
||||
(__u64)(((__u64)(x) & (__u64)0x00000000ff000000ULL) << 8) | \
|
||||
(__u64)(((__u64)(x) & (__u64)0x000000ff00000000ULL) >> 8) | \
|
||||
(__u64)(((__u64)(x) & (__u64)0x0000ff0000000000ULL) >> 24) | \
|
||||
(__u64)(((__u64)(x) & (__u64)0x00ff000000000000ULL) >> 40) | \
|
||||
(__u64)(((__u64)(x) & (__u64)0xff00000000000000ULL) >> 56) ))
|
||||
|
||||
/*
|
||||
* provide defaults when no architecture-specific optimization is detected
|
||||
*/
|
||||
#ifndef __arch__swab16
|
||||
# define __arch__swab16(x) ___swab16(x)
|
||||
#endif
|
||||
#ifndef __arch__swab32
|
||||
# define __arch__swab32(x) ___swab32(x)
|
||||
#endif
|
||||
#ifndef __arch__swab64
|
||||
# define __arch__swab64(x) ___swab64(x)
|
||||
#endif
|
||||
|
||||
#ifndef __arch__swab16p
|
||||
# define __arch__swab16p(x) __swab16(*(x))
|
||||
#endif
|
||||
#ifndef __arch__swab32p
|
||||
# define __arch__swab32p(x) __swab32(*(x))
|
||||
#endif
|
||||
#ifndef __arch__swab64p
|
||||
# define __arch__swab64p(x) __swab64(*(x))
|
||||
#endif
|
||||
|
||||
#ifndef __arch__swab16s
|
||||
# define __arch__swab16s(x) do { *(x) = __swab16p((x)); } while (0)
|
||||
#endif
|
||||
#ifndef __arch__swab32s
|
||||
# define __arch__swab32s(x) do { *(x) = __swab32p((x)); } while (0)
|
||||
#endif
|
||||
#ifndef __arch__swab64s
|
||||
# define __arch__swab64s(x) do { *(x) = __swab64p((x)); } while (0)
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* Allow constant folding
|
||||
*/
|
||||
#if defined(__GNUC__) && (__GNUC__ >= 2) && defined(__OPTIMIZE__)
|
||||
# define __swab16(x) \
|
||||
(__builtin_constant_p((__u16)(x)) ? \
|
||||
___swab16((x)) : \
|
||||
__fswab16((x)))
|
||||
# define __swab32(x) \
|
||||
(__builtin_constant_p((__u32)(x)) ? \
|
||||
___swab32((x)) : \
|
||||
__fswab32((x)))
|
||||
# define __swab64(x) \
|
||||
(__builtin_constant_p((__u64)(x)) ? \
|
||||
___swab64((x)) : \
|
||||
__fswab64((x)))
|
||||
#else
|
||||
# define __swab16(x) __fswab16(x)
|
||||
# define __swab32(x) __fswab32(x)
|
||||
# define __swab64(x) __fswab64(x)
|
||||
#endif /* OPTIMIZE */
|
||||
|
||||
|
||||
static __inline__ __attribute__((const)) __u16 __fswab16(__u16 x)
|
||||
{
|
||||
return __arch__swab16(x);
|
||||
}
|
||||
static __inline__ __u16 __swab16p(__u16 *x)
|
||||
{
|
||||
return __arch__swab16p(x);
|
||||
}
|
||||
static __inline__ void __swab16s(__u16 *addr)
|
||||
{
|
||||
__arch__swab16s(addr);
|
||||
}
|
||||
|
||||
static __inline__ __attribute__((const)) __u32 __fswab32(__u32 x)
|
||||
{
|
||||
return __arch__swab32(x);
|
||||
}
|
||||
static __inline__ __u32 __swab32p(__u32 *x)
|
||||
{
|
||||
return __arch__swab32p(x);
|
||||
}
|
||||
static __inline__ void __swab32s(__u32 *addr)
|
||||
{
|
||||
__arch__swab32s(addr);
|
||||
}
|
||||
|
||||
#ifdef __BYTEORDER_HAS_U64__
|
||||
static __inline__ __attribute__((const)) __u64 __fswab64(__u64 x)
|
||||
{
|
||||
# ifdef __SWAB_64_THRU_32__
|
||||
__u32 h = x >> 32;
|
||||
__u32 l = x & ((1ULL<<32)-1);
|
||||
return (((__u64)__swab32(l)) << 32) | ((__u64)(__swab32(h)));
|
||||
# else
|
||||
return __arch__swab64(x);
|
||||
# endif
|
||||
}
|
||||
static __inline__ __u64 __swab64p(__u64 *x)
|
||||
{
|
||||
return __arch__swab64p(x);
|
||||
}
|
||||
static __inline__ void __swab64s(__u64 *addr)
|
||||
{
|
||||
__arch__swab64s(addr);
|
||||
}
|
||||
#endif /* __BYTEORDER_HAS_U64__ */
|
||||
|
||||
//#if defined(__KERNEL__)
|
||||
#define swab16 __swab16
|
||||
#define swab32 __swab32
|
||||
#define swab64 __swab64
|
||||
#define swab16p __swab16p
|
||||
#define swab32p __swab32p
|
||||
#define swab64p __swab64p
|
||||
#define swab16s __swab16s
|
||||
#define swab32s __swab32s
|
||||
#define swab64s __swab64s
|
||||
//#endif
|
||||
|
||||
#endif /* _LINUX_BYTEORDER_SWAB_H */
|
||||
263
FireBee/trunk/usb/store/asm-m68k/io.h
Normal file
263
FireBee/trunk/usb/store/asm-m68k/io.h
Normal file
@@ -0,0 +1,263 @@
|
||||
/*
|
||||
* IO header file
|
||||
*
|
||||
* Copyright (C) 2004-2007 Freescale Semiconductor, Inc.
|
||||
* TsiChung Liew (Tsi-Chung.Liew@freescale.com)
|
||||
*
|
||||
* See file CREDITS for list of people who contributed to this
|
||||
* project.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef __ASM_M68K_IO_H__
|
||||
#define __ASM_M68K_IO_H__
|
||||
|
||||
#include "byteorder.h"
|
||||
|
||||
#define __raw_readb(addr) (*(volatile u8 *)(addr))
|
||||
#define __raw_readw(addr) (*(volatile u16 *)(addr))
|
||||
#define __raw_readl(addr) (*(volatile u32 *)(addr))
|
||||
|
||||
#define __raw_writeb(b,addr) ((*(volatile u8 *) (addr)) = (b))
|
||||
#define __raw_writew(w,addr) ((*(volatile u16 *) (addr)) = (w))
|
||||
#define __raw_writel(l,addr) ((*(volatile u32 *) (addr)) = (l))
|
||||
|
||||
#define readb(addr) in_8((volatile u8 *)(addr))
|
||||
#define writeb(b,addr) out_8((volatile u8 *)(addr), (b))
|
||||
#if !defined(__BIG_ENDIAN)
|
||||
//#if defined(__BIG_ENDIAN)
|
||||
#define readw(addr) (*(volatile u16 *) (addr))
|
||||
#define readl(addr) (*(volatile u32 *) (addr))
|
||||
#define writew(b,addr) ((*(volatile u16 *) (addr)) = (b))
|
||||
#define writel(b,addr) ((*(volatile u32 *) (addr)) = (b))
|
||||
#else /* Galvez: in_le16() does the swap reading
|
||||
* twice from fifo (register), when reading
|
||||
* from fifo once the value is changed by the new one */
|
||||
#define readw(addr) ld_le16((volatile u16 *)(addr)) /* instead of in_le16((volatile u16 *)(addr))*/
|
||||
#define readl(addr) in_le32((volatile u32 *)(addr))
|
||||
#define writew(b,addr) out_le16((volatile u16 *)(addr),(b))
|
||||
#define writel(b,addr) out_le32((volatile u32 *)(addr),(b))
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The insw/outsw/insl/outsl macros don't do byte-swapping.
|
||||
* They are only used in practice for transferring buffers which
|
||||
* are arrays of bytes, and byte-swapping is not appropriate in
|
||||
* that case. - paulus
|
||||
*/
|
||||
#define insb(port, buf, ns) _insb((u8 *)((port)+_IO_BASE), (buf), (ns))
|
||||
#define outsb(port, buf, ns) _outsb((u8 *)((port)+_IO_BASE), (buf), (ns))
|
||||
#define insw(port, buf, ns) _insw_ns((u16 *)((port)+_IO_BASE), (buf), (ns))
|
||||
#define outsw(port, buf, ns) _outsw_ns((u16 *)((port)+_IO_BASE), (buf), (ns))
|
||||
#define insl(port, buf, nl) _insl_ns((u32 *)((port)+_IO_BASE), (buf), (nl))
|
||||
#define outsl(port, buf, nl) _outsl_ns((u32 *)((port)+_IO_BASE), (buf), (nl))
|
||||
|
||||
#define inb(port) in_8((u8 *)((port)+_IO_BASE))
|
||||
#define outb(val, port) out_8((u8 *)((port)+_IO_BASE), (val))
|
||||
#if !defined(__BIG_ENDIAN)
|
||||
//#if defined(__BIG_ENDIAN)
|
||||
#define inw(port) in_be16((u16 *)((port)+_IO_BASE))
|
||||
#define outw(val, port) out_be16((u16 *)((port)+_IO_BASE), (val))
|
||||
#define inl(port) in_be32((u32 *)((port)+_IO_BASE))
|
||||
#define outl(val, port) out_be32((u32 *)((port)+_IO_BASE), (val))
|
||||
#else
|
||||
#define inw(port) in_le16((u16 *)((port)+_IO_BASE))
|
||||
#define outw(val, port) out_le16((u16 *)((port)+_IO_BASE), (val))
|
||||
#define inl(port) in_le32((u32 *)((port)+_IO_BASE))
|
||||
#define outl(val, port) out_le32((u32 *)((port)+_IO_BASE), (val))
|
||||
#endif
|
||||
|
||||
extern inline void _insb(volatile u8 * port, void *buf, int ns)
|
||||
{
|
||||
u8 *data = (u8 *) buf;
|
||||
while (ns--)
|
||||
*data++ = *port;
|
||||
}
|
||||
|
||||
extern inline void _outsb(volatile u8 * port, const void *buf, int ns)
|
||||
{
|
||||
u8 *data = (u8 *) buf;
|
||||
while (ns--)
|
||||
*port = *data++;
|
||||
}
|
||||
|
||||
extern inline void _insw(volatile u16 * port, void *buf, int ns)
|
||||
{
|
||||
u16 *data = (u16 *) buf;
|
||||
while (ns--)
|
||||
*data++ = __sw16(*port);
|
||||
}
|
||||
|
||||
extern inline void _outsw(volatile u16 * port, const void *buf, int ns)
|
||||
{
|
||||
u16 *data = (u16 *) buf;
|
||||
while (ns--) {
|
||||
*port = __sw16(*data);
|
||||
data++;
|
||||
}
|
||||
}
|
||||
|
||||
extern inline void _insl(volatile u32 * port, void *buf, int nl)
|
||||
{
|
||||
u32 *data = (u32 *) buf;
|
||||
while (nl--)
|
||||
*data++ = __sw32(*port);
|
||||
}
|
||||
|
||||
extern inline void _outsl(volatile u32 * port, const void *buf, int nl)
|
||||
{
|
||||
u32 *data = (u32 *) buf;
|
||||
while (nl--) {
|
||||
*port = __sw32(*data);
|
||||
data++;
|
||||
}
|
||||
}
|
||||
|
||||
extern inline void _insw_ns(volatile u16 * port, void *buf, int ns)
|
||||
{
|
||||
u16 *data = (u16 *) buf;
|
||||
while (ns--)
|
||||
*data++ = *port;
|
||||
}
|
||||
|
||||
extern inline void _outsw_ns(volatile u16 * port, const void *buf, int ns)
|
||||
{
|
||||
u16 *data = (u16 *) buf;
|
||||
while (ns--) {
|
||||
*port = *data++;
|
||||
}
|
||||
}
|
||||
|
||||
extern inline void _insl_ns(volatile u32 * port, void *buf, int nl)
|
||||
{
|
||||
u32 *data = (u32 *) buf;
|
||||
while (nl--)
|
||||
*data++ = *port;
|
||||
}
|
||||
|
||||
extern inline void _outsl_ns(volatile u32 * port, const void *buf, int nl)
|
||||
{
|
||||
u32 *data = (u32 *) buf;
|
||||
while (nl--) {
|
||||
*port = *data;
|
||||
data++;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* The *_ns versions below don't do byte-swapping.
|
||||
* Neither do the standard versions now, these are just here
|
||||
* for older code.
|
||||
*/
|
||||
#define insw_ns(port, buf, ns) _insw_ns((u16 *)((port)+_IO_BASE), (buf), (ns))
|
||||
#define outsw_ns(port, buf, ns) _outsw_ns((u16 *)((port)+_IO_BASE), (buf), (ns))
|
||||
#define insl_ns(port, buf, nl) _insl_ns((u32 *)((port)+_IO_BASE), (buf), (nl))
|
||||
#define outsl_ns(port, buf, nl) _outsl_ns((u32 *)((port)+_IO_BASE), (buf), (nl))
|
||||
|
||||
#define IO_SPACE_LIMIT ~0
|
||||
|
||||
/*
|
||||
* 8, 16 and 32 bit, big and little endian I/O operations, with barrier.
|
||||
*/
|
||||
extern inline int in_8(volatile u8 * addr)
|
||||
{
|
||||
return (int)*addr;
|
||||
}
|
||||
|
||||
extern inline void out_8(volatile u8 * addr, int val)
|
||||
{
|
||||
*addr = (u8) val;
|
||||
}
|
||||
|
||||
extern inline int in_le16(volatile u16 * addr)
|
||||
{
|
||||
return __sw16(*addr);
|
||||
}
|
||||
|
||||
extern inline int in_be16(volatile u16 * addr)
|
||||
{
|
||||
return (*addr & 0xFFFF);
|
||||
}
|
||||
|
||||
extern inline void out_le16(volatile u16 * addr, int val)
|
||||
{
|
||||
*addr = __sw16(val);
|
||||
}
|
||||
|
||||
extern inline void out_be16(volatile u16 * addr, int val)
|
||||
{
|
||||
*addr = (u16) val;
|
||||
}
|
||||
|
||||
extern inline unsigned in_le32(volatile u32 * addr)
|
||||
{
|
||||
return __sw32(*addr);
|
||||
}
|
||||
|
||||
extern inline unsigned in_be32(volatile u32 * addr)
|
||||
{
|
||||
return (*addr);
|
||||
}
|
||||
|
||||
extern inline void out_le32(volatile unsigned *addr, int val)
|
||||
{
|
||||
*addr = __sw32(val);
|
||||
}
|
||||
|
||||
extern inline void out_be32(volatile unsigned *addr, int val)
|
||||
{
|
||||
*addr = val;
|
||||
}
|
||||
|
||||
static inline void sync(void)
|
||||
{
|
||||
/* This sync function is for PowerPC or other architecture instruction
|
||||
* ColdFire does not have this instruction. Dummy function, added for
|
||||
* compatibility (CFI driver)
|
||||
*/
|
||||
}
|
||||
|
||||
/*
|
||||
* Given a physical address and a length, return a virtual address
|
||||
* that can be used to access the memory range with the caching
|
||||
* properties specified by "flags".
|
||||
*/
|
||||
#define MAP_NOCACHE (0)
|
||||
#define MAP_WRCOMBINE (0)
|
||||
#define MAP_WRBACK (0)
|
||||
#define MAP_WRTHROUGH (0)
|
||||
|
||||
static inline void *map_physmem(phys_addr_t paddr, unsigned long len,
|
||||
unsigned long flags)
|
||||
{
|
||||
return (void *)paddr;
|
||||
}
|
||||
|
||||
/*
|
||||
* Take down a mapping set up by map_physmem().
|
||||
*/
|
||||
static inline void unmap_physmem(void *vaddr, unsigned long flags)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
static inline phys_addr_t virt_to_phys(void * vaddr)
|
||||
{
|
||||
return (phys_addr_t)(vaddr);
|
||||
}
|
||||
|
||||
#endif /* __ASM_M68K_IO_H__ */
|
||||
53
FireBee/trunk/usb/store/asm-m68k/types.h
Normal file
53
FireBee/trunk/usb/store/asm-m68k/types.h
Normal file
@@ -0,0 +1,53 @@
|
||||
#ifndef _M68K_TYPES_H
|
||||
#define _M68K_TYPES_H
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
typedef unsigned short umode_t;
|
||||
|
||||
typedef __signed__ char __s8;
|
||||
typedef unsigned char __u8;
|
||||
|
||||
typedef __signed__ short __s16;
|
||||
typedef unsigned short __u16;
|
||||
|
||||
typedef __signed__ int __s32;
|
||||
typedef unsigned int __u32;
|
||||
|
||||
#if defined(__GNUC__)
|
||||
__extension__ typedef __signed__ long long __s64;
|
||||
__extension__ typedef unsigned long long __u64;
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
__u32 u[4];
|
||||
} __attribute__((aligned(16))) vector128;
|
||||
|
||||
//#ifdef __KERNEL__
|
||||
/*
|
||||
* These aren't exported outside the kernel to avoid name space clashes
|
||||
*/
|
||||
typedef signed char s8;
|
||||
typedef unsigned char u8;
|
||||
|
||||
typedef signed short s16;
|
||||
typedef unsigned short u16;
|
||||
|
||||
typedef signed int s32;
|
||||
typedef unsigned int u32;
|
||||
|
||||
typedef signed long long s64;
|
||||
typedef unsigned long long u64;
|
||||
|
||||
#define BITS_PER_LONG 32
|
||||
|
||||
/* DMA addresses are 32-bits wide */
|
||||
typedef u32 dma_addr_t;
|
||||
|
||||
typedef unsigned long phys_addr_t;
|
||||
typedef unsigned long phys_size_t;
|
||||
|
||||
//#endif /* __KERNEL__ */
|
||||
#endif /* __ASSEMBLY__ */
|
||||
|
||||
#endif
|
||||
1378
FireBee/trunk/usb/store/bios.S
Normal file
1378
FireBee/trunk/usb/store/bios.S
Normal file
File diff suppressed because it is too large
Load Diff
731
FireBee/trunk/usb/store/cmd_usb.c
Normal file
731
FireBee/trunk/usb/store/cmd_usb.c
Normal file
@@ -0,0 +1,731 @@
|
||||
/*
|
||||
* Modified for Atari by David Gálvez 2010
|
||||
* Modified for Atari by Didier Mequignon 2009
|
||||
*
|
||||
* (C) Copyright 2001
|
||||
* Denis Peter, MPL AG Switzerland
|
||||
*
|
||||
* Most of this source has been derived from the Linux USB
|
||||
* project.
|
||||
*
|
||||
* See file CREDITS for list of people who contributed to this
|
||||
* project.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include "config.h"
|
||||
#include "asm-m68k/byteorder.h"
|
||||
#include "usb.h"
|
||||
|
||||
|
||||
//#undef RESET_START_STOP_CMDS
|
||||
//#define RESET_START_STOP_CMDS
|
||||
|
||||
#ifdef CONFIG_USB_STORAGE
|
||||
static int usb_stor_curr_dev = -1; /* current device */
|
||||
#endif
|
||||
|
||||
#ifdef PCI_XBIOS
|
||||
extern short pci_init(void);
|
||||
#endif
|
||||
|
||||
/* some display routines (info command) */
|
||||
char *usb_get_class_desc(unsigned char dclass)
|
||||
{
|
||||
switch (dclass) {
|
||||
case USB_CLASS_PER_INTERFACE:
|
||||
return "See Interface";
|
||||
case USB_CLASS_AUDIO:
|
||||
return "Audio";
|
||||
case USB_CLASS_COMM:
|
||||
return "Communication";
|
||||
case USB_CLASS_HID:
|
||||
return "Human Interface";
|
||||
case USB_CLASS_PRINTER:
|
||||
return "Printer";
|
||||
case USB_CLASS_MASS_STORAGE:
|
||||
return "Mass Storage";
|
||||
case USB_CLASS_HUB:
|
||||
return "Hub";
|
||||
case USB_CLASS_DATA:
|
||||
return "CDC Data";
|
||||
case USB_CLASS_VENDOR_SPEC:
|
||||
return "Vendor specific";
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
void usb_display_class_sub(unsigned char dclass, unsigned char subclass,
|
||||
unsigned char proto)
|
||||
{
|
||||
switch (dclass) {
|
||||
case USB_CLASS_PER_INTERFACE:
|
||||
printf("See Interface");
|
||||
break;
|
||||
case USB_CLASS_HID:
|
||||
printf("Human Interface, Subclass: ");
|
||||
switch (subclass) {
|
||||
case USB_SUB_HID_NONE:
|
||||
printf("None");
|
||||
break;
|
||||
case USB_SUB_HID_BOOT:
|
||||
printf("Boot ");
|
||||
switch (proto) {
|
||||
case USB_PROT_HID_NONE:
|
||||
printf("None");
|
||||
break;
|
||||
case USB_PROT_HID_KEYBOARD:
|
||||
printf("Keyboard");
|
||||
break;
|
||||
case USB_PROT_HID_MOUSE:
|
||||
printf("Mouse");
|
||||
break;
|
||||
default:
|
||||
printf("reserved");
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
printf("reserved");
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case USB_CLASS_MASS_STORAGE:
|
||||
printf("Mass Storage, ");
|
||||
switch (subclass) {
|
||||
case US_SC_RBC:
|
||||
printf("RBC ");
|
||||
break;
|
||||
case US_SC_8020:
|
||||
printf("SFF-8020i (ATAPI)");
|
||||
break;
|
||||
case US_SC_QIC:
|
||||
printf("QIC-157 (Tape)");
|
||||
break;
|
||||
case US_SC_UFI:
|
||||
printf("UFI");
|
||||
break;
|
||||
case US_SC_8070:
|
||||
printf("SFF-8070");
|
||||
break;
|
||||
case US_SC_SCSI:
|
||||
printf("Transp. SCSI");
|
||||
break;
|
||||
default:
|
||||
printf("reserved");
|
||||
break;
|
||||
}
|
||||
printf(", ");
|
||||
switch (proto) {
|
||||
case US_PR_CB:
|
||||
printf("Command/Bulk");
|
||||
break;
|
||||
case US_PR_CBI:
|
||||
printf("Command/Bulk/Int");
|
||||
break;
|
||||
case US_PR_BULK:
|
||||
printf("Bulk only");
|
||||
break;
|
||||
default:
|
||||
printf("reserved");
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
printf("%s", usb_get_class_desc(dclass));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void usb_display_string(struct usb_device *dev, int idx)
|
||||
{
|
||||
char buffer[256];
|
||||
if (idx != 0) {
|
||||
if (usb_string(dev, idx, &buffer[0], 256) > 0)
|
||||
printf("String: \"%s\"", buffer);
|
||||
}
|
||||
}
|
||||
|
||||
void usb_display_desc(struct usb_device *dev)
|
||||
{
|
||||
if (dev->descriptor.bDescriptorType == USB_DT_DEVICE) {
|
||||
printf("%d: %s, USB Revision %x.%x\n", dev->devnum,
|
||||
usb_get_class_desc(dev->config.if_desc[0].bInterfaceClass),
|
||||
(dev->descriptor.bcdUSB>>8) & 0xff,
|
||||
dev->descriptor.bcdUSB & 0xff);
|
||||
|
||||
if (strlen(dev->mf) || strlen(dev->prod) ||
|
||||
strlen(dev->serial))
|
||||
printf(" - %s %s %s\n", dev->mf, dev->prod,
|
||||
dev->serial);
|
||||
if (dev->descriptor.bDeviceClass) {
|
||||
printf(" - Class: ");
|
||||
usb_display_class_sub(dev->descriptor.bDeviceClass,
|
||||
dev->descriptor.bDeviceSubClass,
|
||||
dev->descriptor.bDeviceProtocol);
|
||||
printf("\n");
|
||||
} else {
|
||||
printf(" - Class: (from Interface) %s\n",
|
||||
usb_get_class_desc(
|
||||
dev->config.if_desc[0].bInterfaceClass));
|
||||
}
|
||||
printf(" - PacketSize: %d Configurations: %d\n",
|
||||
dev->descriptor.bMaxPacketSize0,
|
||||
dev->descriptor.bNumConfigurations);
|
||||
printf(" - Vendor: 0x%04x Product 0x%04x Version %d.%d\n",
|
||||
dev->descriptor.idVendor, dev->descriptor.idProduct,
|
||||
(dev->descriptor.bcdDevice>>8) & 0xff,
|
||||
dev->descriptor.bcdDevice & 0xff);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void usb_display_conf_desc(struct usb_config_descriptor *config,
|
||||
struct usb_device *dev)
|
||||
{
|
||||
printf(" Configuration: %d\n", config->bConfigurationValue);
|
||||
printf(" - Interfaces: %d %s%s%dmA\n", config->bNumInterfaces,
|
||||
(config->bmAttributes & 0x40) ? "Self Powered " : "Bus Powered ",
|
||||
(config->bmAttributes & 0x20) ? "Remote Wakeup " : "",
|
||||
config->MaxPower*2);
|
||||
if (config->iConfiguration) {
|
||||
printf(" - ");
|
||||
usb_display_string(dev, config->iConfiguration);
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
|
||||
void usb_display_if_desc(struct usb_interface_descriptor *ifdesc,
|
||||
struct usb_device *dev)
|
||||
{
|
||||
printf(" Interface: %d\n", ifdesc->bInterfaceNumber);
|
||||
printf(" - Alternate Setting %d, Endpoints: %d\n",
|
||||
ifdesc->bAlternateSetting, ifdesc->bNumEndpoints);
|
||||
printf(" - Class ");
|
||||
usb_display_class_sub(ifdesc->bInterfaceClass,
|
||||
ifdesc->bInterfaceSubClass, ifdesc->bInterfaceProtocol);
|
||||
printf("\n");
|
||||
if (ifdesc->iInterface) {
|
||||
printf(" - ");
|
||||
usb_display_string(dev, ifdesc->iInterface);
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
|
||||
void usb_display_ep_desc(struct usb_endpoint_descriptor *epdesc)
|
||||
{
|
||||
printf(" - Endpoint %d %s ", epdesc->bEndpointAddress & 0xf,
|
||||
(epdesc->bEndpointAddress & 0x80) ? "In" : "Out");
|
||||
switch ((epdesc->bmAttributes & 0x03)) {
|
||||
case 0:
|
||||
printf("Control");
|
||||
break;
|
||||
case 1:
|
||||
printf("Isochronous");
|
||||
break;
|
||||
case 2:
|
||||
printf("Bulk");
|
||||
break;
|
||||
case 3:
|
||||
printf("Interrupt");
|
||||
break;
|
||||
}
|
||||
printf(" MaxPacket %d", epdesc->wMaxPacketSize);
|
||||
if ((epdesc->bmAttributes & 0x03) == 0x3)
|
||||
printf(" Interval %dms", epdesc->bInterval);
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
/* main routine to diasplay the configs, interfaces and endpoints */
|
||||
void usb_display_config(struct usb_device *dev)
|
||||
{
|
||||
struct usb_config_descriptor *config;
|
||||
struct usb_interface_descriptor *ifdesc;
|
||||
struct usb_endpoint_descriptor *epdesc;
|
||||
int i, ii;
|
||||
|
||||
config = &dev->config;
|
||||
usb_display_conf_desc(config, dev);
|
||||
for (i = 0; i < config->no_of_if; i++) {
|
||||
ifdesc = &config->if_desc[i];
|
||||
usb_display_if_desc(ifdesc, dev);
|
||||
for (ii = 0; ii < ifdesc->no_of_ep; ii++) {
|
||||
epdesc = &ifdesc->ep_desc[ii];
|
||||
usb_display_ep_desc(epdesc);
|
||||
}
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
static inline char *portspeed(int speed)
|
||||
{
|
||||
if (speed == USB_SPEED_HIGH)
|
||||
return "480 Mb/s";
|
||||
else if (speed == USB_SPEED_LOW)
|
||||
return "1.5 Mb/s";
|
||||
else
|
||||
return "12 Mb/s";
|
||||
}
|
||||
|
||||
/* shows the device tree recursively */
|
||||
void usb_show_tree_graph(struct usb_device *dev, char *pre)
|
||||
{
|
||||
int i, idx;
|
||||
int has_child, last_child, port;
|
||||
|
||||
idx = strlen(pre);
|
||||
printf(" %s", pre);
|
||||
/* check if the device has connected children */
|
||||
has_child = 0;
|
||||
for (i = 0; i < dev->maxchild; i++) {
|
||||
if (dev->children[i] != NULL)
|
||||
has_child = 1;
|
||||
}
|
||||
/* check if we are the last one */
|
||||
last_child = 1;
|
||||
if (dev->parent != NULL) {
|
||||
for (i = 0; i < dev->parent->maxchild; i++) {
|
||||
/* search for children */
|
||||
if (dev->parent->children[i] == dev) {
|
||||
/* found our pointer, see if we have a
|
||||
* little sister
|
||||
*/
|
||||
port = i;
|
||||
while (i++ < dev->parent->maxchild) {
|
||||
if (dev->parent->children[i] != NULL) {
|
||||
/* found a sister */
|
||||
last_child = 0;
|
||||
break;
|
||||
} /* if */
|
||||
} /* while */
|
||||
} /* device found */
|
||||
} /* for all children of the parent */
|
||||
printf("\b+-");
|
||||
/* correct last child */
|
||||
if (last_child)
|
||||
pre[idx-1] = ' ';
|
||||
} /* if not root hub */
|
||||
else
|
||||
printf(" ");
|
||||
printf("%d ", dev->devnum);
|
||||
pre[idx++] = ' ';
|
||||
pre[idx++] = has_child ? '|' : ' ';
|
||||
pre[idx] = 0;
|
||||
printf(" %s (%s, %dmA)\n", usb_get_class_desc(
|
||||
dev->config.if_desc[0].bInterfaceClass),
|
||||
portspeed(dev->speed),
|
||||
dev->config.MaxPower * 2);
|
||||
if (strlen(dev->mf) || strlen(dev->prod) || strlen(dev->serial))
|
||||
printf(" %s %s %s %s\n", pre, dev->mf, dev->prod, dev->serial);
|
||||
printf(" %s\n", pre);
|
||||
if (dev->maxchild > 0) {
|
||||
for (i = 0; i < dev->maxchild; i++) {
|
||||
if (dev->children[i] != NULL) {
|
||||
usb_show_tree_graph(dev->children[i], pre);
|
||||
pre[idx] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* main routine for the tree command */
|
||||
void usb_show_tree(struct usb_device *dev)
|
||||
{
|
||||
char preamble[32];
|
||||
|
||||
memset(preamble, 0, 32);
|
||||
usb_show_tree_graph(dev, &preamble[0]);
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* usb boot command intepreter. Derived from diskboot
|
||||
*/
|
||||
#if 0
|
||||
#ifdef CONFIG_USB_STORAGE
|
||||
int do_usbboot(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
|
||||
{
|
||||
char *boot_device = NULL;
|
||||
char *ep;
|
||||
int dev, part = 1, rcode;
|
||||
ulong addr, cnt;
|
||||
disk_partition_t info;
|
||||
image_header_t *hdr;
|
||||
block_dev_desc_t *stor_dev;
|
||||
#if defined(CONFIG_FIT)
|
||||
const void *fit_hdr = NULL;
|
||||
#endif
|
||||
|
||||
switch (argc) {
|
||||
case 1:
|
||||
addr = CONFIG_SYS_LOAD_ADDR;
|
||||
boot_device = getenv("bootdevice");
|
||||
break;
|
||||
case 2:
|
||||
addr = strtoul(argv[1], NULL, 16);
|
||||
boot_device = getenv("bootdevice");
|
||||
break;
|
||||
case 3:
|
||||
addr = strtoul(argv[1], NULL, 16);
|
||||
boot_device = argv[2];
|
||||
break;
|
||||
default:
|
||||
// cmd_usage(cmdtp);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!boot_device) {
|
||||
puts("\n** No boot device **\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
dev = strtoul(boot_device, &ep, 16);
|
||||
stor_dev = usb_stor_get_dev(dev);
|
||||
if (stor_dev->type == DEV_TYPE_UNKNOWN) {
|
||||
printf("\n** Device %d not available\n", dev);
|
||||
return 1;
|
||||
}
|
||||
if (stor_dev->block_read == NULL) {
|
||||
printf("storage device not initialized. Use usb scan\n");
|
||||
return 1;
|
||||
}
|
||||
if (*ep) {
|
||||
if (*ep != ':') {
|
||||
puts("\n** Invalid boot device, use `dev[:part]' **\n");
|
||||
return 1;
|
||||
}
|
||||
part = strtoul(++ep, NULL, 16);
|
||||
}
|
||||
|
||||
if (get_partition_info(stor_dev, part, &info)) {
|
||||
/* try to boot raw .... */
|
||||
strncpy((char *)&info.type[0], BOOT_PART_TYPE,
|
||||
sizeof(BOOT_PART_TYPE));
|
||||
strncpy((char *)&info.name[0], "Raw", 4);
|
||||
info.start = 0;
|
||||
info.blksz = 0x200;
|
||||
info.size = 2880;
|
||||
printf("error reading partinfo...try to boot raw\n");
|
||||
}
|
||||
if ((strncmp((char *)info.type, BOOT_PART_TYPE,
|
||||
sizeof(info.type)) != 0) &&
|
||||
(strncmp((char *)info.type, BOOT_PART_COMP,
|
||||
sizeof(info.type)) != 0)) {
|
||||
printf("\n** Invalid partition type \"%.32s\""
|
||||
" (expect \"" BOOT_PART_TYPE "\")\n",
|
||||
info.type);
|
||||
return 1;
|
||||
}
|
||||
printf("\nLoading from USB device %d, partition %d: "
|
||||
"Name: %.32s Type: %.32s\n",
|
||||
dev, part, info.name, info.type);
|
||||
|
||||
debug("First Block: %ld, # of blocks: %ld, Block Size: %ld\n",
|
||||
info.start, info.size, info.blksz);
|
||||
|
||||
if (stor_dev->block_read(dev, info.start, 1, (ulong *)addr) != 1) {
|
||||
printf("** Read error on %d:%d\n", dev, part);
|
||||
return 1;
|
||||
}
|
||||
|
||||
switch (genimg_get_format((void *)addr)) {
|
||||
case IMAGE_FORMAT_LEGACY:
|
||||
// hdr = (image_header_t *)addr;
|
||||
|
||||
// if (!image_check_hcrc(hdr)) {
|
||||
// puts("\n** Bad Header Checksum **\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
// image_print_contents(hdr);
|
||||
|
||||
// cnt = image_get_image_size(hdr);
|
||||
break;
|
||||
#if defined(CONFIG_FIT)
|
||||
case IMAGE_FORMAT_FIT:
|
||||
fit_hdr = (const void *)addr;
|
||||
puts("Fit image detected...\n");
|
||||
|
||||
cnt = fit_get_size(fit_hdr);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
puts("** Unknown image type\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
cnt += info.blksz - 1;
|
||||
cnt /= info.blksz;
|
||||
cnt -= 1;
|
||||
|
||||
if (stor_dev->block_read(dev, info.start+1, cnt,
|
||||
(ulong *)(addr+info.blksz)) != cnt) {
|
||||
printf("\n** Read error on %d:%d\n", dev, part);
|
||||
return 1;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_FIT)
|
||||
/* This cannot be done earlier, we need complete FIT image in RAM
|
||||
* first
|
||||
*/
|
||||
if (genimg_get_format((void *)addr) == IMAGE_FORMAT_FIT) {
|
||||
if (!fit_check_format(fit_hdr)) {
|
||||
puts("** Bad FIT image format\n");
|
||||
return 1;
|
||||
}
|
||||
fit_print_contents(fit_hdr);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Loading ok, update default load address */
|
||||
load_addr = addr;
|
||||
|
||||
flush_cache(addr, (cnt+1)*info.blksz);
|
||||
|
||||
/* Check if we should attempt an auto-start */
|
||||
if (((ep = getenv("autostart")) != NULL) && (strcmp(ep, "yes") == 0)) {
|
||||
char *local_args[2];
|
||||
extern int do_bootm(cmd_tbl_t *, int, int, char *[]);
|
||||
local_args[0] = argv[0];
|
||||
local_args[1] = NULL;
|
||||
printf("Automatic boot of image at addr 0x%08lX ...\n", addr);
|
||||
rcode = do_bootm(cmdtp, 0, 1, local_args);
|
||||
return rcode;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
#endif /* CONFIG_USB_STORAGE */
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* usb command intepreter
|
||||
*/
|
||||
int do_usb(int argc, char **argv)
|
||||
{
|
||||
|
||||
int i;
|
||||
struct usb_device *dev = NULL;
|
||||
|
||||
#ifdef CONFIG_USB_STORAGE
|
||||
block_dev_desc_t *stor_dev;
|
||||
#endif
|
||||
extern char usb_started;
|
||||
|
||||
if ((strncmp(argv[1], "reset", 5) == 0) ||
|
||||
(strncmp(argv[1], "start", 5) == 0)) {
|
||||
usb_stop();
|
||||
printf("(Re)start USB...\n");
|
||||
#ifdef PCI_XBIOS
|
||||
i = pci_init();
|
||||
#else
|
||||
if (usb_init() >= 0)
|
||||
i = 1;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_USB_STORAGE
|
||||
/* try to recognize storage devices immediately */
|
||||
if (i == 1)
|
||||
usb_stor_curr_dev = usb_stor_scan( );
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
if (strncmp(argv[1], "stop", 4) == 0) {
|
||||
#ifdef CONFIG_USB_KEYBOARD
|
||||
if (argc == 2) {
|
||||
if (usb_kbd_deregister() != 0) {
|
||||
printf("USB not stopped: usbkbd still"
|
||||
" using USB\n");
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
/* forced stop, switch console in to serial */
|
||||
usb_kbd_deregister();
|
||||
}
|
||||
#endif
|
||||
printf("stopping USB..\n");
|
||||
usb_stop();
|
||||
return 0;
|
||||
}
|
||||
if (!usb_started) {
|
||||
printf("USB is stopped. Please issue 'usb start' first.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (strncmp(argv[1], "tree", 4) == 0) {
|
||||
printf("\nDevice Tree:\n");
|
||||
usb_show_tree(usb_get_dev_index(0));
|
||||
return 0;
|
||||
}
|
||||
if (strncmp(argv[1], "inf", 3) == 0)
|
||||
{
|
||||
int d1;
|
||||
if (argc == 2)
|
||||
{
|
||||
for (d1 = 0; d1 < USB_MAX_DEVICE; d1++) {
|
||||
dev = usb_get_dev_index(d1);
|
||||
if (dev == NULL)
|
||||
break;
|
||||
usb_display_desc(dev);
|
||||
usb_display_config(dev);
|
||||
}
|
||||
return 0;
|
||||
} else
|
||||
{
|
||||
int d2;
|
||||
|
||||
i = strtoul(argv[2], NULL, 16);
|
||||
printf("config for device %d\n", i);
|
||||
for (d2 = 0; d2 < USB_MAX_DEVICE; d2++) {
|
||||
dev = usb_get_dev_index(d2);
|
||||
if (dev == NULL)
|
||||
break;
|
||||
if (dev->devnum == i)
|
||||
break;
|
||||
}
|
||||
if (dev == NULL) {
|
||||
printf("*** NO Device avaiable ***\n");
|
||||
return 0;
|
||||
} else {
|
||||
usb_display_desc(dev);
|
||||
usb_display_config(dev);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#ifdef CONFIG_USB_STORAGE
|
||||
if (strncmp(argv[1], "stor", 4) == 0)
|
||||
return usb_stor_info();
|
||||
#if 0
|
||||
if (strncmp(argv[1], "part", 4) == 0) {
|
||||
int devno, ok = 0;
|
||||
if (argc == 2) {
|
||||
for (devno = 0; devno < USB_MAX_STOR_DEV; ++devno) {
|
||||
stor_dev = usb_stor_get_dev(devno);
|
||||
if (stor_dev->type != DEV_TYPE_UNKNOWN) {
|
||||
ok++;
|
||||
if (devno)
|
||||
printf("\n");
|
||||
printf("print_part of %x\n", devno);
|
||||
print_part(stor_dev);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
devno = strtoul(argv[2], NULL, 16);
|
||||
stor_dev = usb_stor_get_dev(devno);
|
||||
if (stor_dev->type != DEV_TYPE_UNKNOWN) {
|
||||
ok++;
|
||||
printf("print_part of %x\n", devno);
|
||||
print_part(stor_dev);
|
||||
}
|
||||
}
|
||||
if (!ok) {
|
||||
printf("\nno USB devices available\n");
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
if (strcmp(argv[1], "read") == 0) {
|
||||
if (usb_stor_curr_dev < 0) {
|
||||
printf("no current device selected\n");
|
||||
return 1;
|
||||
}
|
||||
if (argc == 5) {
|
||||
unsigned long addr = strtoul(argv[2], NULL, 16);
|
||||
unsigned long blk = strtoul(argv[3], NULL, 16);
|
||||
unsigned long cnt = strtoul(argv[4], NULL, 16);
|
||||
unsigned long n;
|
||||
printf("\nUSB read: device %d block # %ld, count %ld"
|
||||
" ... ", usb_stor_curr_dev, blk, cnt);
|
||||
stor_dev = usb_stor_get_dev(usb_stor_curr_dev);
|
||||
n = stor_dev->block_read(usb_stor_curr_dev, blk, cnt,
|
||||
(unsigned long *)addr);
|
||||
printf("%ld blocks read: %s\n", n,
|
||||
(n == cnt) ? "OK" : "ERROR");
|
||||
if (n == cnt)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
if (strncmp(argv[1], "dev", 3) == 0) {
|
||||
if (argc == 3) {
|
||||
int device = (int)strtoul(argv[2], NULL, 10);
|
||||
printf("\nUSB device %d: ", device);
|
||||
if (device >= USB_MAX_STOR_DEV) {
|
||||
printf("unknown device\n");
|
||||
return 1;
|
||||
}
|
||||
printf("\n Device %d: ", device);
|
||||
stor_dev = usb_stor_get_dev(device);
|
||||
dev_print(stor_dev);
|
||||
if (stor_dev->type == DEV_TYPE_UNKNOWN)
|
||||
return 1;
|
||||
usb_stor_curr_dev = device;
|
||||
printf("... is now current device\n");
|
||||
return 0;
|
||||
} else {
|
||||
printf("\nUSB device %d: ", usb_stor_curr_dev);
|
||||
stor_dev = usb_stor_get_dev(usb_stor_curr_dev);
|
||||
dev_print(stor_dev);
|
||||
if (stor_dev->type == DEV_TYPE_UNKNOWN)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_USB_STORAGE */
|
||||
// cmd_usage(cmdtp);
|
||||
return 1;
|
||||
}
|
||||
#if 0
|
||||
#ifdef CONFIG_USB_STORAGE
|
||||
U_BOOT_CMD(
|
||||
usb, 5, 1, do_usb,
|
||||
"USB sub-system",
|
||||
"reset - reset (rescan) USB controller\n"
|
||||
"usb stop [f] - stop USB [f]=force stop\n"
|
||||
"usb tree - show USB device tree\n"
|
||||
"usb info [dev] - show available USB devices\n"
|
||||
"usb storage - show details of USB storage devices\n"
|
||||
"usb dev [dev] - show or set current USB storage device\n"
|
||||
"usb part [dev] - print partition table of one or all USB storage"
|
||||
" devices\n"
|
||||
"usb read addr blk# cnt - read `cnt' blocks starting at block `blk#'\n"
|
||||
" to memory address `addr'"
|
||||
);
|
||||
|
||||
|
||||
U_BOOT_CMD(
|
||||
usbboot, 3, 1, do_usbboot,
|
||||
"boot from USB device",
|
||||
"loadAddr dev:part"
|
||||
);
|
||||
|
||||
#else
|
||||
U_BOOT_CMD(
|
||||
usb, 5, 1, do_usb,
|
||||
"USB sub-system",
|
||||
"reset - reset (rescan) USB controller\n"
|
||||
"usb tree - show USB device tree\n"
|
||||
"usb info [dev] - show available USB devices"
|
||||
);
|
||||
#endif
|
||||
#endif
|
||||
6
FireBee/trunk/usb/store/compile.txt
Normal file
6
FireBee/trunk/usb/store/compile.txt
Normal file
@@ -0,0 +1,6 @@
|
||||
I have used gcc 4.4.3 native version and gcc 4.4.3 cross-compiler version to
|
||||
compile these sources.
|
||||
There are 4 targets "make ethernat", "make netusbee", "make aranym", "make ohci-pci".
|
||||
If you use cross-compiler add "CROSS=yes" to the commands above.
|
||||
Before compiling "ohci-pci" target you must "make clean" if you have been compiling the other targets before.
|
||||
"make all" compiles the 4 targets.
|
||||
54
FireBee/trunk/usb/store/config.h
Normal file
54
FireBee/trunk/usb/store/config.h
Normal file
@@ -0,0 +1,54 @@
|
||||
#ifndef _CONFIG_H
|
||||
#define _CONFIG_H
|
||||
|
||||
//#define ARCH m68k
|
||||
//#define COLDFIRE /* Besides change one(first) .chip in detxbios.S 68060 or 5200 */
|
||||
//#define CONFIG_USB_ISP116X_HCD
|
||||
//#define SUPERVISOR
|
||||
/* Change .chip in detxbios.S 68060 or 5200 */
|
||||
|
||||
/*----- USB -----*/
|
||||
//#define CONFIG_LEGACY_USB_INIT_SEQ
|
||||
#define CONFIG_USB_STORAGE
|
||||
//#define CONFIG_USB_KEYBOARD
|
||||
//#define CONFIG_USB_MOUSE
|
||||
//#define CONFIG_USB_INTERRUPT_POLLING
|
||||
#define CONFIG_USB_ARANYM_HCD
|
||||
/*----- ISP116x-HCD ------*/
|
||||
#define ISP116X_HCD_USE_UDELAY
|
||||
#define ISP116X_HCD_USE_EXTRA_DELAY
|
||||
//#define ISP116X_HCD_SEL15kRES
|
||||
//#define ISP116X_HCD_OC_ENABLE
|
||||
//#define ISP116X_HCD_REMOTE_WAKEUP_ENABLE
|
||||
/*----- OHCI-HCI -----*/
|
||||
#define CONFIG_SYS_USB_OHCI_MAX_ROOT_PORTS 1
|
||||
#define CONFIG_USB_OHCI
|
||||
//#define PCI_XBIOS /* Defined in the makefile */
|
||||
|
||||
|
||||
/*----- DEBUG -----*/
|
||||
/* You should activate global debug,
|
||||
* #define DEBUG_GLOBAL 1 to turn on
|
||||
* #define DEBUG_GLOBAL 0 to turn off
|
||||
* After global debug is enable
|
||||
* you can activate the debug independently
|
||||
* in each layer where debug is possible
|
||||
*/
|
||||
|
||||
#define DEBUG_GLOBAL 1
|
||||
#if DEBUG_GLOBAL
|
||||
/* Define only one of the three debug posibilities below */
|
||||
#define DEBUG_TO_FILE 1
|
||||
#define DEBUG_TO_ARANYM 0 /* NOTE: No arguments are passed to the printf function */
|
||||
#define DEBUG_TO_CONSOLE 0
|
||||
|
||||
/* Define which local layer you want on */
|
||||
#define DEBUG_HOST_LAYER 0
|
||||
#define DEBUG_USB_LAYER 0
|
||||
#define DEBUG_HUB_LAYER 0
|
||||
#define DEBUG_STORAGE_LAYER 0
|
||||
#define DEBUG_XHDI_LAYER 0
|
||||
#define DEBUG_BIOS_LAYER 0 /* NOTE: Always to console */
|
||||
|
||||
#endif
|
||||
#endif /* _CONFIG_H */
|
||||
64
FireBee/trunk/usb/store/debug.c
Normal file
64
FireBee/trunk/usb/store/debug.c
Normal file
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* debug.c
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This file is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
#if DEBUG_TO_FILE
|
||||
static FILE *debug_handle = NULL;
|
||||
|
||||
|
||||
void
|
||||
debug_init(char *file)
|
||||
{
|
||||
char filename[20] = "";
|
||||
|
||||
strcpy(filename, file);
|
||||
|
||||
debug_handle = fopen(filename, "a");
|
||||
|
||||
if (debug_handle != NULL)
|
||||
setvbuf (debug_handle, NULL, _IONBF, 0);
|
||||
}
|
||||
|
||||
|
||||
void debug_exit(void)
|
||||
{
|
||||
if (debug_handle != NULL && debug_handle != stdout)
|
||||
fclose(debug_handle);
|
||||
debug_handle = NULL;
|
||||
}
|
||||
|
||||
|
||||
void debug(char *FormatString, ...)
|
||||
{
|
||||
va_list arg_ptr;
|
||||
|
||||
va_start(arg_ptr, FormatString);
|
||||
vfprintf(debug_handle, FormatString, arg_ptr);
|
||||
va_end(arg_ptr);
|
||||
fflush(debug_handle);
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
97
FireBee/trunk/usb/store/debug.h
Normal file
97
FireBee/trunk/usb/store/debug.h
Normal file
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
* debug.h
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This file is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _DEBUG_H
|
||||
#define _DEBUG_H
|
||||
|
||||
#include "config.h"
|
||||
#include "host/aranym/nf_ops.h"
|
||||
|
||||
void debug_init ( char *file);
|
||||
void debug_exit ( void );
|
||||
void debug (char *FormatString, ...);
|
||||
|
||||
/* You should activate global debug in config.h, uncommenting the #define DEBUG line */
|
||||
/* After global debug is enable you can activate them independly in each file */
|
||||
|
||||
|
||||
#if DEBUG_GLOBAL
|
||||
#if DEBUG_TO_FILE
|
||||
#define DEBUG(fmt, args...) debug_init("usb.log"); \
|
||||
debug( "%s: "fmt"\n\r" , __FUNCTION__, ##args); \
|
||||
debug_exit( )
|
||||
#endif /* DEBUG_TO_FILE */
|
||||
|
||||
#if DEBUG_TO_ARANYM
|
||||
#define DEBUG(fmt, args...) nf_debug(fmt )
|
||||
#endif /* DEBUG_TO_ARANYM */
|
||||
|
||||
#if DEBUG_TO_CONSOLE
|
||||
#define DEBUG(fmt, args...) printf("%s: "fmt"\n\r" , __FUNCTION__, ##args)
|
||||
#endif /* DEBUG_TO_CONSOLE */
|
||||
|
||||
/* This allows control debug messages independenly for different layers */
|
||||
#if DEBUG_HOST_LAYER
|
||||
#define DEBUG_HOST(fmt, args...) DEBUG(fmt, ##args)
|
||||
#else
|
||||
#define DEBUG_HOST(fmt, args...) {}
|
||||
#endif
|
||||
#if DEBUG_USB_LAYER
|
||||
#define DEBUG_USB(fmt, args...) DEBUG(fmt, ##args)
|
||||
#else
|
||||
#define DEBUG_USB(fmt, args...) {}
|
||||
#endif
|
||||
#if DEBUG_HUB_LAYER
|
||||
#define DEBUG_HUB(fmt, args...) DEBUG(fmt, ##args)
|
||||
#else
|
||||
#define DEBUG_HUB(fmt, args...) {}
|
||||
#endif
|
||||
#if DEBUG_STORAGE_LAYER
|
||||
#define DEBUG_STORAGE(fmt, args...) DEBUG(fmt, ##args)
|
||||
#else
|
||||
#define DEBUG_STORAGE(fmt, args...) {}
|
||||
#endif
|
||||
#if DEBUG_XHDI_LAYER
|
||||
#define DEBUG_XHDI(fmt, args...) DEBUG(fmt, ##args)
|
||||
#else
|
||||
#define DEBUG_XHDI(fmt, args...) {}
|
||||
#endif
|
||||
|
||||
#else
|
||||
#define DEBUG(fmt, args...) {}
|
||||
#if DEBUG_HOST_LAYER
|
||||
#define DEBUG_HOST(fmt, args...) DEBUG(fmt, ##args)
|
||||
#endif
|
||||
#define DEBUG(fmt, args...) {}
|
||||
#if DEBUG_USB_LAYER
|
||||
#define DEBUG_USB(fmt, args...) DEBUG(fmt, ##args)
|
||||
#endif
|
||||
#if DEBUG_HUB_LAYER
|
||||
#define DEBUG_HUB(fmt, args...) DEBUG(fmt, ##args)
|
||||
#endif
|
||||
#if DEBUG_STORAGE_LAYER
|
||||
#define DEBUG_STORAGE(fmt, args...) DEBUG(fmt, ##args)
|
||||
#endif
|
||||
#if DEBUG_XHDI_LAYER
|
||||
#define DEBUG_XHDI(fmt, args...) DEBUG(fmt, ##args)
|
||||
#endif
|
||||
|
||||
#endif /* DEBUG_GLOBAL */
|
||||
|
||||
|
||||
#endif /* _DEBUG_H */
|
||||
840
FireBee/trunk/usb/store/debug2.S
Normal file
840
FireBee/trunk/usb/store/debug2.S
Normal file
@@ -0,0 +1,840 @@
|
||||
/* Debug the CT60
|
||||
*
|
||||
* Didier Mequignon, 2003-2006, e-mail: aniplay@wanadoo.fr
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
.chip 68040
|
||||
.globl exception
|
||||
|
||||
#ifdef COLDFIRE
|
||||
.globl null
|
||||
|
||||
#include "fire.h"
|
||||
#endif
|
||||
|
||||
#include "vars.h"
|
||||
|
||||
#define DEBUG
|
||||
|
||||
#ifdef DEBUG
|
||||
.global display_string,hex_long,hex_word,hex_byte,display_char,wait_key,_debug
|
||||
#endif
|
||||
|
||||
.text
|
||||
|
||||
#ifdef COLDFIRE
|
||||
|
||||
null:
|
||||
clr.l 0x380 // not valid
|
||||
move.l SP,0x3C0
|
||||
move.l A6,0x3BC
|
||||
lea 0x384,A6
|
||||
movem.l D0-D7/A0-A5,(A6)
|
||||
clr.l 0x3C8 // USP
|
||||
moveq #-1,D1
|
||||
#endif
|
||||
|
||||
exception:
|
||||
|
||||
clr.l memvalid
|
||||
lea.l mess1(PC),A0
|
||||
bsr display_string
|
||||
#ifdef COLDFIRE
|
||||
ext.l D1
|
||||
addq.l #1,D1
|
||||
move.l D1,D7 // vector number
|
||||
#else
|
||||
addq.w #1,D1
|
||||
move.w D1,D7 // vector number
|
||||
#endif
|
||||
moveq #0,D0
|
||||
move.w D7,D0
|
||||
#ifdef COLDFIRE
|
||||
.chip 68060
|
||||
divu #10,D0
|
||||
.chip 5200
|
||||
move.l D0,D1
|
||||
and.l #7,D0
|
||||
beq.s .ex1
|
||||
or.l #0x30,D0
|
||||
bsr display_char
|
||||
.ex1:
|
||||
swap D1
|
||||
move.w D1,D0
|
||||
or.l #0x30,D0
|
||||
#else
|
||||
divu #10,D0
|
||||
and.w #7,D0
|
||||
beq.s .ex1
|
||||
or.w #0x30,D0
|
||||
bsr display_char
|
||||
.ex1:
|
||||
swap d0
|
||||
or.w #0x30,D0
|
||||
#endif
|
||||
bsr display_char
|
||||
moveq #0x3A,D0
|
||||
bsr display_char
|
||||
moveq #0x20,D0
|
||||
bsr display_char
|
||||
lea.l tab_mess_exc(PC),A0
|
||||
move.w D7,D0
|
||||
bsr display_tab
|
||||
moveq #13,D0
|
||||
bsr display_char
|
||||
moveq #10,D0
|
||||
bsr display_char
|
||||
#ifdef COLDFIRE
|
||||
tst.w D7
|
||||
beq .ex0
|
||||
#endif
|
||||
lea.l mess2(PC),A0 // SR
|
||||
bsr display_string
|
||||
#ifdef COLDFIRE
|
||||
move.w save_sr,D0 // SR
|
||||
#else
|
||||
move.l 0x3C0,A0 //SSP
|
||||
move.w (A0),D0
|
||||
#endif
|
||||
bsr hex_word // SR
|
||||
lea.l mess3(PC),A0
|
||||
bsr display_string
|
||||
#ifdef COLDFIRE
|
||||
move.w save_sr,D2 // SR
|
||||
and.l #0xB71F,D2
|
||||
#else
|
||||
move.l 0x3C0,A0 //SSP
|
||||
move.w (A0),D2 // SR
|
||||
and.w #0xB71F,D2
|
||||
#endif
|
||||
lea.l tab_status(PC),A1
|
||||
moveq #15,D1
|
||||
.ex5:
|
||||
btst.l D1,D2
|
||||
beq.s .ex6
|
||||
moveq #0,D0
|
||||
move.b (A1,D1),D0
|
||||
move.w D0,D3
|
||||
#ifdef COLDFIRE
|
||||
and.l #0xF8,D3
|
||||
cmp.l #0x30,D3
|
||||
#else
|
||||
and.w #0xF8,D3
|
||||
cmp.w #0x30,D3
|
||||
#endif
|
||||
bne.s .ex4
|
||||
move.w D0,-(SP)
|
||||
moveq #0x49,D0 // I
|
||||
bsr display_char
|
||||
move.w (SP)+,D0
|
||||
.ex4:
|
||||
bsr display_char
|
||||
moveq #0x20,D0
|
||||
bsr display_char
|
||||
.ex6:
|
||||
#ifdef COLDFIRE
|
||||
subq.l #1,D1
|
||||
bpl.s .ex5
|
||||
.ex0:
|
||||
#else
|
||||
dbf D1,.ex5
|
||||
#endif
|
||||
lea.l mess4(PC),A0 // PC
|
||||
bsr display_string
|
||||
#ifdef COLDFIRE
|
||||
move.l save_pc,D0 // PC
|
||||
#else
|
||||
move.l 0x3C0,A0 // SSP
|
||||
move.l 2(A0),D0 // PC
|
||||
#endif
|
||||
bsr hex_long
|
||||
lea.l mess10(PC),A0 // Basepage
|
||||
bsr display_string
|
||||
move.l 0x6EE4,D0
|
||||
bsr hex_long
|
||||
#ifdef COLDFIRE
|
||||
tst.w D7
|
||||
beq .ex2
|
||||
#endif
|
||||
lea.l mess5(PC),A0 // CACR
|
||||
bsr display_string
|
||||
#ifdef COLDFIRE
|
||||
.chip 68060
|
||||
movec.l CACR,D0 // from value stored in the CF68KLIB
|
||||
.chip 5200
|
||||
bsr hex_long
|
||||
cmp.l #2,D7
|
||||
bne.s .ex2
|
||||
lea.l mess6(PC),A0 // address fault
|
||||
bsr display_string
|
||||
move.l address_fault,D0 // from value stored in the CF68KLIB
|
||||
bsr hex_long
|
||||
#else /* ATARI - CT60 */
|
||||
movec.l CACR,D0
|
||||
bsr hex_long
|
||||
cmp.w #2,D7
|
||||
beq.s .ex3 // Acces Fault
|
||||
cmp.w #3,D7
|
||||
beq.s .ex3 // Adress Error
|
||||
cmp.w #5,D7
|
||||
beq.s .ex3 // Zero Divide
|
||||
cmp.w #9,D7
|
||||
bne .ex2 // <> Trace
|
||||
.ex3:
|
||||
lea.l mess6(PC),A0 // address fault
|
||||
bsr display_string
|
||||
move.l 0x3C0,A0 // SSP
|
||||
move.l 8(A0),D0 // address fault
|
||||
bsr hex_long
|
||||
cmp.w #2,D7
|
||||
bne .ex2 // <> Acces Fault
|
||||
lea.l mess7(PC),A0 // FSLW
|
||||
bsr display_string
|
||||
move.l 0x3C0,A0 // SSP
|
||||
move.l 12(A0),D0 // FSLW
|
||||
bsr hex_long
|
||||
lea.l mess3(PC),A0
|
||||
bsr display_string
|
||||
moveq #13,D0
|
||||
bsr display_char
|
||||
moveq #10,D0
|
||||
bsr display_char
|
||||
move.l 0x3C0,A0 // SSP
|
||||
move.l 12(A0),D2 // FSLW
|
||||
and.l #0x0BFFFFFD,D2
|
||||
lea.l tab_fslw1(PC),A1
|
||||
lea.l tab_fslw2(PC),A2
|
||||
lea.l tab_fslw3(PC),A3
|
||||
moveq #31,D1
|
||||
moveq #0,D3
|
||||
.ex13:
|
||||
btst.l D1,D2
|
||||
beq.s .ex14
|
||||
moveq #0,D0
|
||||
move.b (A1,D3),D0
|
||||
bsr display_char
|
||||
moveq #0,D0
|
||||
move.b (A2,D3),D0
|
||||
cmp.b #0x20,D0
|
||||
beq.s .ex12
|
||||
bsr display_char
|
||||
moveq #0,D0
|
||||
move.b (A3,D3),D0
|
||||
cmp.b #0x20,D0
|
||||
beq.s .ex12
|
||||
bsr display_char
|
||||
.ex12:
|
||||
moveq #0x20,D0
|
||||
bsr display_char
|
||||
.ex14:
|
||||
addq.w #1,D3
|
||||
dbf D1,.ex13
|
||||
#endif /* COLDFIRE */
|
||||
.ex2:
|
||||
lea.l mess8(PC),A0 // SSP
|
||||
bsr display_string
|
||||
move.l 0x3C0,D0 // SSP
|
||||
bsr hex_long
|
||||
lea.l mess9(PC),A0 // USP
|
||||
bsr display_string
|
||||
move.l 0x3C8,D0 // USP
|
||||
bsr hex_long
|
||||
lea.l 0x384,A1 // registers
|
||||
lea.l 32(A1),A2
|
||||
moveq #7,D1
|
||||
.ex8:
|
||||
moveq #13,D0
|
||||
bsr display_char
|
||||
moveq #10,D0
|
||||
bsr display_char
|
||||
moveq #0x44,D0
|
||||
bsr display_char
|
||||
moveq #7,D0
|
||||
#ifdef COLDFIRE
|
||||
sub.l D1,D0
|
||||
or.l #0x30,D0
|
||||
#else
|
||||
sub.w D1,D0
|
||||
or.w #0x30,D0
|
||||
#endif
|
||||
move.w D0,-(SP)
|
||||
bsr display_nb
|
||||
move.l (A1),D0
|
||||
bsr hex_long // data registers
|
||||
moveq #0x20,D0
|
||||
bsr display_char
|
||||
tst.w D1
|
||||
beq.s .ex9
|
||||
moveq #0x41,D0
|
||||
bsr display_char
|
||||
move.w (SP),D0
|
||||
bsr display_nb
|
||||
move.l (A2),D0
|
||||
bsr hex_long // address registers
|
||||
moveq #0x20,D0
|
||||
bsr display_char
|
||||
.ex9:
|
||||
addq.l #2,SP
|
||||
addq.l #4,A1
|
||||
addq.l #4,A2
|
||||
#ifdef COLDFIRE
|
||||
subq.l #1,D1
|
||||
bpl.s .ex8
|
||||
#else
|
||||
dbf D1,.ex8
|
||||
#endif
|
||||
moveq #13,D0
|
||||
bsr display_char
|
||||
.loop_wait_key:
|
||||
#ifdef COLDFIRE
|
||||
#ifdef DEBUG
|
||||
move.w #1,-(SP) // AUX
|
||||
#else
|
||||
move.w #2,-(SP) // CON
|
||||
#endif
|
||||
#else
|
||||
move.w #2,-(SP) // CON
|
||||
#endif
|
||||
move.w #2,-(SP) // Bconin
|
||||
trap #13
|
||||
addq.l #4,SP
|
||||
ext.l D0
|
||||
move.l D0,-(SP)
|
||||
move.l #0x5F504349,D0
|
||||
lea 0xED0000,A0 // 128 KB
|
||||
cmp.l (A0),D0 // _PCI
|
||||
beq.s .pci_drivers
|
||||
lea 0xEC0000,A0 // 192 KB
|
||||
cmp.l (A0),D0 // _PCI
|
||||
beq.s .pci_drivers
|
||||
lea 0xEB0000,A0 // 256 KB
|
||||
cmp.l (A0),D0 // _PCI
|
||||
beq.s .pci_drivers
|
||||
lea 0xEA0000,A0 // 320 KB
|
||||
cmp.l (A0),D0 // _PCI
|
||||
bne.s .no_pci_drivers
|
||||
.pci_drivers:
|
||||
jsr 40(A0) // drivers PCI in flash, add dbug (68k disassembler)
|
||||
move.l D0,(SP)
|
||||
bne .no_pci_drivers
|
||||
addq.l #4,SP
|
||||
bra.s .loop_wait_key
|
||||
.no_pci_drivers:
|
||||
move.l (SP)+,D0
|
||||
#ifdef COLDFIRE
|
||||
and.l #0xFF,D0
|
||||
cmp.l #0x6D,D0 // m
|
||||
#else
|
||||
cmp.b #0x6D,D0 // m
|
||||
#endif
|
||||
beq.s .memory_dump
|
||||
#ifdef COLDFIRE
|
||||
cmp.l #0x70,D0 // p
|
||||
#else
|
||||
cmp.b #0x70,D0 // p
|
||||
#endif
|
||||
beq.s .patch_memory
|
||||
#ifdef DEBUG
|
||||
#ifdef COLDFIRE
|
||||
cmp.l #0x20,D0
|
||||
#else
|
||||
cmp.b #0x20,D0
|
||||
#endif
|
||||
bne .loop_wait_key
|
||||
lea mess14(PC),A0
|
||||
bsr display_string
|
||||
#endif
|
||||
rts
|
||||
.memory_dump:
|
||||
lea mess11(PC),A0 // memory dump
|
||||
bsr display_string
|
||||
bsr get_hex_value
|
||||
move.l D0,A0
|
||||
bsr dump
|
||||
bra .loop_wait_key
|
||||
.patch_memory:
|
||||
lea mess12(PC),A0 // patch memory
|
||||
bsr display_string
|
||||
bsr get_hex_value
|
||||
move.l D0,A1
|
||||
lea mess13(PC),A0 // value
|
||||
bsr display_string
|
||||
bsr get_hex_value
|
||||
cmp.l #0x100,D0
|
||||
bcc.s .word_value
|
||||
move.b D0,(A1)
|
||||
lea crlf(PC),A0
|
||||
bsr display_string
|
||||
move.l A1,D0
|
||||
bsr hex_long
|
||||
moveq #0x20,D0
|
||||
bsr display_char
|
||||
move.b (A1),D0
|
||||
bsr hex_byte
|
||||
bra .loop_wait_key
|
||||
.word_value:
|
||||
cmp.l #0x10000,D0
|
||||
bcc.s .long_value
|
||||
move.w D0,(A1)
|
||||
lea crlf(PC),A0
|
||||
bsr display_string
|
||||
move.l A1,D0
|
||||
bsr hex_long
|
||||
moveq #0x20,D0
|
||||
bsr display_char
|
||||
move.w (A1),D0
|
||||
bsr hex_word
|
||||
bra .loop_wait_key
|
||||
.long_value:
|
||||
move.l D0,(A1)
|
||||
lea crlf(PC),A0
|
||||
bsr display_string
|
||||
move.l A1,D0
|
||||
bsr hex_long
|
||||
moveq #0x20,D0
|
||||
bsr display_char
|
||||
move.l (A1),D0
|
||||
bsr hex_long
|
||||
bra .loop_wait_key
|
||||
|
||||
display_nb:
|
||||
|
||||
bsr display_char
|
||||
moveq #0x3A,D0
|
||||
bsr display_char
|
||||
moveq #0x24,D0
|
||||
bsr display_char
|
||||
rts
|
||||
|
||||
display_tab:
|
||||
|
||||
#ifdef COLDFIRE
|
||||
move.l D1,-(SP)
|
||||
#endif
|
||||
move.w D0,-(SP)
|
||||
moveq #0,D0
|
||||
.dt1:
|
||||
#ifdef COLDFIRE
|
||||
move.b (A0),D1
|
||||
extb.l D1
|
||||
cmp.l #-1,D1
|
||||
beq.s .dt3
|
||||
moveq #0,D1
|
||||
move.w (SP),D1
|
||||
cmp.l D1,D0
|
||||
#else
|
||||
cmp.b #-1,(A0)
|
||||
beq.s .dt3
|
||||
cmp.w (SP),D0
|
||||
#endif
|
||||
beq.s .dt4
|
||||
.dt2:
|
||||
tst.b (A0)+
|
||||
bne.s .dt2
|
||||
#ifdef COLDFIRE
|
||||
addq.l #1,D0
|
||||
#else
|
||||
addq.w #1,D0
|
||||
#endif
|
||||
bra.s .dt1
|
||||
.dt4:
|
||||
bsr display_string
|
||||
.dt3:
|
||||
|
||||
addq.l #2,SP
|
||||
#ifdef COLDFIRE
|
||||
move.l (SP)+,D1
|
||||
#endif
|
||||
rts
|
||||
|
||||
hex_long:
|
||||
move.l D0,-(SP)
|
||||
swap D0
|
||||
bsr.s hex_word
|
||||
move.l (SP)+,D0
|
||||
hex_word:
|
||||
move.w D0,-(SP)
|
||||
#ifdef COLDFIRE
|
||||
lsr.l #8,D0
|
||||
bsr.s hex_byte
|
||||
move.w (SP)+,D0
|
||||
hex_byte:
|
||||
move.w D0,-(SP)
|
||||
lsr.l #4,D0
|
||||
bsr.s hex_char
|
||||
move.w (SP)+,D0
|
||||
hex_char:
|
||||
and.l #0xF,D0
|
||||
or.l #0x30,D0
|
||||
cmp.l #0x3A,D0
|
||||
bcs.s display_char
|
||||
addq.l #7,D0
|
||||
|
||||
display_char:
|
||||
and.l #0xFF,D0
|
||||
#ifdef DEBUG /* warning !!! If serial mouse */
|
||||
move.l D1,-(SP)
|
||||
.wait_uart:
|
||||
move.b MCF_UART_USR0,D1
|
||||
and.l #MCF_UART_USR_TXRDY,D1
|
||||
beq.s .wait_uart
|
||||
move.b D0,MCF_UART_UTB0 // send the character
|
||||
move.l (SP)+,D1
|
||||
#else
|
||||
lea -24(SP),SP
|
||||
movem.l D0-D2/A0-A2,(SP)
|
||||
move.w D0,-(sp)
|
||||
move.w #2,-(SP)
|
||||
move.w #3,-(SP) // Bconout
|
||||
trap #13
|
||||
addq.l #6,SP
|
||||
movem.l (SP),D0-D2/A0-A2
|
||||
lea 24(SP),SP
|
||||
#endif /* DEBUG */
|
||||
rts
|
||||
#else /* ATARI */
|
||||
lsr.w #8,D0
|
||||
bsr.s hex_byte
|
||||
move.w (SP)+,D0
|
||||
hex_byte:
|
||||
move.w D0,-(SP)
|
||||
lsr.b #4,D0
|
||||
bsr.s hex_char
|
||||
move.w (SP)+,D0
|
||||
hex_char:
|
||||
and.b #0xF,D0
|
||||
or.b #0x30,D0
|
||||
cmp.b #0x3A,D0
|
||||
bcs.s display_char
|
||||
addq.b #7,D0
|
||||
|
||||
display_char:
|
||||
and.w #0xFF,D0
|
||||
movem.l D0-D2/A0-A2,-(SP)
|
||||
move.w D0,-(sp)
|
||||
move.w #2,-(SP)
|
||||
move.w #3,-(SP) // Bconout
|
||||
trap #13
|
||||
addq.l #6,SP
|
||||
movem.l (SP)+,D0-D2/A0-A2
|
||||
rts
|
||||
#endif /* COLDFIRE */
|
||||
|
||||
display_string:
|
||||
|
||||
#ifdef COLDFIRE
|
||||
move.l D0,-(SP)
|
||||
move.l A0,-(SP)
|
||||
#else
|
||||
movem.l D0/A0,-(SP)
|
||||
#endif
|
||||
.os2:
|
||||
move.b (A0)+,D0
|
||||
beq.s .os1
|
||||
bsr display_char
|
||||
bra.s .os2
|
||||
.os1:
|
||||
#ifdef COLDFIRE
|
||||
move.l (SP)+,A0
|
||||
move.l (SP)+,D0
|
||||
#else
|
||||
movem.l (SP)+,D0/A0
|
||||
#endif
|
||||
rts
|
||||
|
||||
get_hex_value:
|
||||
|
||||
#ifdef COLDFIRE
|
||||
lea -56(SP),SP
|
||||
movem.l D1-A5,(SP)
|
||||
link A6,#-8
|
||||
moveq #0,D7
|
||||
.loop_get_value:
|
||||
#ifdef DEBUG
|
||||
move.w #1,-(SP) // AUX
|
||||
#else
|
||||
move.w #2,-(SP) // CON
|
||||
#endif
|
||||
move.w #2,-(SP) // Bconin
|
||||
trap #13
|
||||
addq.l #4,SP
|
||||
and.l #0xFF,D0
|
||||
cmp.l #13,D0
|
||||
beq.s .conv_get_value
|
||||
cmp.l #8,D0
|
||||
bne.s .not_backspace
|
||||
tst.w D7
|
||||
ble.s .loop_get_value
|
||||
bsr display_char
|
||||
subq.l #1,D7
|
||||
bra.s .loop_get_value
|
||||
.not_backspace:
|
||||
cmp.l #0x30,D0
|
||||
bcs.s .loop_get_value
|
||||
cmp.l #0x39,D0
|
||||
bls.s .number_value
|
||||
cmp.l #0x41,D0
|
||||
bcs.s .loop_get_value
|
||||
cmp.l #0x46,D0
|
||||
bls.s .letter_value
|
||||
cmp.l #0x61,D0
|
||||
bcs.s .loop_get_value
|
||||
cmp.l #0x66,D0
|
||||
bhi.s .loop_get_value
|
||||
.letter_value:
|
||||
bsr display_char
|
||||
and.l #0x0F,D0
|
||||
add.l #9,D0
|
||||
bra.s .store_value
|
||||
.number_value:
|
||||
bsr display_char
|
||||
and.l #0x0F,D0
|
||||
.store_value:
|
||||
move.b D0,-8(A6,D7)
|
||||
addq.l #1,D7
|
||||
cmp.l #8,D7
|
||||
bcs .loop_get_value
|
||||
.conv_get_value:
|
||||
moveq #0,D0
|
||||
subq.l #1,D7
|
||||
bmi.s .end_get_value
|
||||
moveq #0,D6
|
||||
.loop_value:
|
||||
asl.l #4,D0
|
||||
moveq #0,D1
|
||||
move.b -8(A6,D6),D1
|
||||
or.l D1,D0
|
||||
addq.l #1,D6
|
||||
subq.l #1,D7
|
||||
bpl.s .loop_value
|
||||
.end_get_value:
|
||||
tst.l D0
|
||||
unlk A6
|
||||
movem.l (SP),D1-A5
|
||||
lea 56(SP),SP
|
||||
#else /* ATARI */
|
||||
movem.l D1-A5,-(SP)
|
||||
link A6,#-8
|
||||
moveq #0,D7
|
||||
.loop_get_value:
|
||||
move.w #2,-(SP) // CON
|
||||
move.w #2,-(SP) // Bconin
|
||||
trap #13
|
||||
addq.l #4,SP
|
||||
cmp.b #13,D0
|
||||
beq.s .conv_get_value
|
||||
cmp.b #8,D0
|
||||
bne.s .not_backspace
|
||||
tst.w D7
|
||||
ble.s .loop_get_value
|
||||
bsr display_char
|
||||
subq.w #1,D7
|
||||
bra.s .loop_get_value
|
||||
.not_backspace:
|
||||
cmp.b #0x30,D0
|
||||
bcs.s .loop_get_value
|
||||
cmp.b #0x39,D0
|
||||
bls.s .number_value
|
||||
cmp.b #0x41,D0
|
||||
bcs.s .loop_get_value
|
||||
cmp.b #0x46,D0
|
||||
bls.s .letter_value
|
||||
cmp.b #0x61,D0
|
||||
bcs.s .loop_get_value
|
||||
cmp.b #0x66,D0
|
||||
bhi.s .loop_get_value
|
||||
.letter_value:
|
||||
bsr display_char
|
||||
and.b #0x0F,D0
|
||||
add.b #9,D0
|
||||
bra.s .store_value
|
||||
.number_value:
|
||||
bsr display_char
|
||||
and.b #0x0F,D0
|
||||
.store_value:
|
||||
move.b D0,-8(A6,D7)
|
||||
addq.w #1,D7
|
||||
cmp.w #8,D7
|
||||
bcs.s .loop_get_value
|
||||
.conv_get_value:
|
||||
moveq #0,D0
|
||||
subq.w #1,D7
|
||||
bmi.s .end_get_value
|
||||
moveq #0,D6
|
||||
.loop_value:
|
||||
asl.l #4,D0
|
||||
or.b -8(A6,D6),D0
|
||||
addq.w #1,D6
|
||||
dbf D7,.loop_value
|
||||
.end_get_value:
|
||||
tst.l D0
|
||||
unlk A6
|
||||
movem.l (SP)+,D1-A5
|
||||
#endif /* COLDFIRE */
|
||||
rts
|
||||
|
||||
dump:
|
||||
|
||||
#ifdef COLDFIRE
|
||||
lea -20(SP),SP
|
||||
movem.l D0-D2/A0-A1,(SP)
|
||||
#else
|
||||
movem.l D0-D2/A0-A1,-(SP)
|
||||
#endif
|
||||
move.l A0,A1
|
||||
moveq #3,D1
|
||||
.loop_dump1:
|
||||
lea crlf(PC),A0
|
||||
bsr display_string
|
||||
move.l A1,D0
|
||||
bsr hex_long
|
||||
moveq #0x20,D0
|
||||
bsr display_char
|
||||
moveq #15,D2
|
||||
.loop_dump2:
|
||||
move.b (A1)+,D0
|
||||
bsr hex_byte
|
||||
moveq #0x20,D0
|
||||
bsr display_char
|
||||
#ifdef COLDFIRE
|
||||
subq.l #1,D2
|
||||
bpl.s .loop_dump2
|
||||
#else
|
||||
dbf D2,.loop_dump2
|
||||
#endif
|
||||
lea -16(A1),A1
|
||||
moveq #15,D2
|
||||
.loop_dump3:
|
||||
move.b (A1)+,D0
|
||||
#ifdef COLDFIRE
|
||||
and.l #0xFF,D0
|
||||
cmp.l #0x20,D0
|
||||
bcs.s .dump_bad_char
|
||||
cmp.l #0x7F,D0
|
||||
#else
|
||||
cmp.b #0x20,D0
|
||||
bcs.s .dump_bad_char
|
||||
cmp.b #0x7F,D0
|
||||
#endif
|
||||
bcs.s .dump_ok
|
||||
.dump_bad_char:
|
||||
moveq #0x2E,D0
|
||||
.dump_ok:
|
||||
bsr display_char
|
||||
#ifdef COLDFIRE
|
||||
subq.l #1,D2
|
||||
bpl.s .loop_dump3
|
||||
subq.l #1,D1
|
||||
bpl.s .loop_dump1
|
||||
movem.l (SP),D0-D2/A0-A1
|
||||
lea 20(SP),SP
|
||||
#else
|
||||
dbf D2,.loop_dump3
|
||||
dbf D1,.loop_dump1
|
||||
movem.l (SP)+,D0-D2/A0-A1
|
||||
#endif
|
||||
rts
|
||||
|
||||
crlf: .byte 13,10,0
|
||||
mess1: .byte 13,10
|
||||
.asciz "EXCEPTION PROCESSING "
|
||||
mess2: .byte 13,10
|
||||
.asciz "Status Register (SR): $"
|
||||
mess3: .asciz ", bits to 1: "
|
||||
mess4: .byte 13,10
|
||||
.asciz "Program Counter (PC): $"
|
||||
mess5: .byte 13,10
|
||||
.asciz "Cache Register (CACR): $"
|
||||
mess6: .byte 13,10
|
||||
.asciz "Address Fault: $"
|
||||
mess7: .byte 13,10
|
||||
.asciz "Fault Status Word (FSLW): "
|
||||
mess8: .byte 13,10
|
||||
.asciz "Supervisor Stack (SSP): $"
|
||||
mess9: .byte 13,10
|
||||
.asciz "User Stack (USP): $"
|
||||
mess10: .byte 13,10
|
||||
.asciz "Basepage: $"
|
||||
mess11: .byte 13,10
|
||||
.asciz "Memory dump (hex) ? "
|
||||
mess12: .byte 13,10
|
||||
.asciz "Patch memory (hex) ? "
|
||||
mess13: .byte 13,10
|
||||
.asciz "Value (hex) ? "
|
||||
mess14: .byte 13,10
|
||||
.ascii "Pterm"
|
||||
.byte 13,10,0
|
||||
|
||||
tab_mess_exc:
|
||||
#ifdef COLDFIRE
|
||||
.asciz "Null (jump or call)"
|
||||
#else
|
||||
.byte 0
|
||||
#endif
|
||||
.byte 0
|
||||
.asciz "Access Fault"
|
||||
.asciz "Address Error"
|
||||
.asciz "Illegal Instruction"
|
||||
.asciz "Integer Zero Divide"
|
||||
.byte 0
|
||||
.byte 0
|
||||
.asciz "Privilege Violation"
|
||||
.asciz "Trace"
|
||||
.asciz "Line A"
|
||||
.asciz "Line F"
|
||||
.asciz "Emulator Interrupt"
|
||||
.byte 0
|
||||
.asciz "Format Error"
|
||||
.asciz "Uninitialised Interrupt"
|
||||
.byte 0
|
||||
.byte 0
|
||||
.byte 0
|
||||
.byte 0
|
||||
.byte 0
|
||||
.byte 0
|
||||
.byte 0
|
||||
.byte 0
|
||||
.asciz "Spurious Interrupt"
|
||||
.asciz "Interrupt level 1"
|
||||
.asciz "Interrupt level 2"
|
||||
.asciz "Interrupt level 3"
|
||||
.asciz "Interrupt level 4"
|
||||
.asciz "Interrupt level 5"
|
||||
.asciz "Interrupt level 6"
|
||||
.asciz "Interrupt level 7"
|
||||
.asciz "Trap #0"
|
||||
.asciz "Trap #1"
|
||||
.asciz "Trap #2"
|
||||
.asciz "Trap #3"
|
||||
.asciz "Trap #4"
|
||||
.asciz "Trap #5"
|
||||
.asciz "Trap #6"
|
||||
.asciz "Trap #7"
|
||||
.asciz "Trap #8"
|
||||
.asciz "Trap #9"
|
||||
.asciz "Trap #10"
|
||||
.asciz "Trap #11"
|
||||
.asciz "Trap #12"
|
||||
.asciz "Trap #13"
|
||||
.asciz "Trap #14"
|
||||
.asciz "Trap #15"
|
||||
.byte -1
|
||||
|
||||
tab_status: .ascii "CVZNX 012 MS T"
|
||||
|
||||
tab_fslw1: .ascii " M LRWSSTTTTTIPSPPIPSWTRWTB S"
|
||||
tab_fslw2: .ascii " A K ZZTTMMMOBBTTLFPPWEETP S"
|
||||
tab_fslw3: .ascii " 1010210 EEAB E RE E"
|
||||
150
FireBee/trunk/usb/store/host/aranym/aranym-hcd.c
Normal file
150
FireBee/trunk/usb/store/host/aranym/aranym-hcd.c
Normal file
@@ -0,0 +1,150 @@
|
||||
/*
|
||||
NatFeat USB host chip emulator
|
||||
|
||||
ARAnyM (C) 2010 David Gálvez
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/*--- Include ---*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <mint/cookie.h>
|
||||
#include <mint/osbind.h>
|
||||
|
||||
#include "nf_ops.h"
|
||||
#include "usbhost_nfapi.h"
|
||||
#include "../../config.h"
|
||||
#include "../../asm-m68k/io.h"
|
||||
#include "../../usb.h"
|
||||
#include "../../debug.h"
|
||||
|
||||
/*--- Defines ---*/
|
||||
|
||||
#ifndef EINVFN
|
||||
#define EINVFN -32
|
||||
#endif
|
||||
|
||||
#ifndef DEV_CONSOLE
|
||||
#define DEV_CONSOLE 2
|
||||
#endif
|
||||
|
||||
#define DRIVER_NAME "ARAnyM USB host chip emulator"
|
||||
#define VERSION "v0.1"
|
||||
|
||||
|
||||
/*--- Functions prototypes ---*/
|
||||
|
||||
static void press_any_key(void);
|
||||
|
||||
|
||||
/*--- Local variables ---*/
|
||||
|
||||
static struct nf_ops *nfOps;
|
||||
static unsigned long nfUsbHostId;
|
||||
|
||||
|
||||
/*--- Functions ---*/
|
||||
|
||||
|
||||
static void press_any_key(void)
|
||||
{
|
||||
|
||||
(void) Cconws("- Press any key to continue -\r\n");
|
||||
while (Bconstat(DEV_CONSOLE) == 0) { };
|
||||
}
|
||||
|
||||
|
||||
/* --- Transfer functions -------------------------------------------------- */
|
||||
|
||||
int submit_int_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
|
||||
int len, int interval)
|
||||
{
|
||||
int r;
|
||||
|
||||
r = nfOps->call(USBHOST(USBHOST_SUBMIT_INT_MSG), dev, pipe, buffer, len, interval);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int submit_control_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
|
||||
int len, struct devrequest *setup)
|
||||
{
|
||||
int r;
|
||||
|
||||
r = nfOps->call(USBHOST(USBHOST_SUBMIT_CONTROL_MSG), dev, pipe, buffer, len, setup);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int submit_bulk_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
|
||||
int len)
|
||||
{
|
||||
int r;
|
||||
|
||||
r = nfOps->call(USBHOST(USBHOST_SUBMIT_BULK_MSG), dev, pipe, buffer, len);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* --- Init functions ------------------------------------------------------ */
|
||||
|
||||
int usb_lowlevel_init(void)
|
||||
{
|
||||
int r;
|
||||
|
||||
(void) Cconws(
|
||||
"\033p " DRIVER_NAME " " VERSION " \033q\r\n"
|
||||
"Copyright (c) ARAnyM Development Team, " __DATE__ "\r\n"
|
||||
);
|
||||
|
||||
nfOps = nf_init();
|
||||
if (!nfOps) {
|
||||
(void) Cconws("__NF cookie not present on this system\r\n");
|
||||
press_any_key();
|
||||
return 0;
|
||||
}
|
||||
|
||||
nfUsbHostId=nfOps->get_id("USBHOST");
|
||||
if (nfUsbHostId == 0) {
|
||||
(void) Cconws("NF USBHOST functions not present on this system\r\n");
|
||||
press_any_key();
|
||||
}
|
||||
|
||||
/* List present devices */
|
||||
|
||||
r = nfOps->call(USBHOST(USBHOST_LOWLEVEL_INIT));
|
||||
|
||||
if (!r)
|
||||
(void) Cconws(" USB Init \r\n");
|
||||
else
|
||||
(void) Cconws(" Couldn't init aranym host chip emulator \r\n");
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
int usb_lowlevel_stop(void)
|
||||
{
|
||||
int r;
|
||||
|
||||
r = nfOps->call(USBHOST(USBHOST_LOWLEVEL_STOP));
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
118
FireBee/trunk/usb/store/host/aranym/natfeat.c
Normal file
118
FireBee/trunk/usb/store/host/aranym/natfeat.c
Normal file
@@ -0,0 +1,118 @@
|
||||
/*
|
||||
* ARAnyM native features interface.
|
||||
* (c) 2005-2008 ARAnyM development team
|
||||
*
|
||||
* In 2006 updated with FreeMiNT headers and code.
|
||||
* In 2008 converted from "__NF" cookie to direct usage of NF instructions
|
||||
*
|
||||
**/
|
||||
|
||||
/*
|
||||
* Copied from FreeMiNT source tree where Native Features were added recently
|
||||
*
|
||||
* Copyright 2003 Frank Naumann <fnaumann@freemint.de>
|
||||
* All rights reserved.
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This file is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
*
|
||||
* Author: Frank Naumann <fnaumann@freemint.de>
|
||||
* Started: 2003-12-13
|
||||
*
|
||||
*/
|
||||
|
||||
# include <compiler.h>
|
||||
# include <mint/osbind.h>
|
||||
# include "nf_ops.h"
|
||||
|
||||
|
||||
#define ARANYM 1
|
||||
# ifdef ARANYM
|
||||
|
||||
|
||||
static unsigned long nf_get_id_instr = 0x73004e75UL;
|
||||
static unsigned long nf_call_instr = 0x73014e75UL;
|
||||
|
||||
static struct nf_ops _nf_ops = { (void*)&nf_get_id_instr, (void*)&nf_call_instr };
|
||||
static struct nf_ops *nf_ops = 0UL;
|
||||
|
||||
extern int detect_native_features(void);
|
||||
|
||||
struct nf_ops *
|
||||
nf_init(void)
|
||||
{
|
||||
if (Supexec(detect_native_features))
|
||||
{
|
||||
nf_ops = &_nf_ops;
|
||||
return nf_ops;
|
||||
}
|
||||
|
||||
return 0UL;
|
||||
}
|
||||
|
||||
|
||||
const char *
|
||||
nf_name(void)
|
||||
{
|
||||
static char buf[64] = "Unknown emulator";
|
||||
|
||||
if (nf_ops)
|
||||
{
|
||||
static int done = 0;
|
||||
|
||||
if (!done)
|
||||
{
|
||||
long nfid_name = nf_ops->get_id("NF_NAME");
|
||||
|
||||
if (nfid_name)
|
||||
nf_ops->call(nfid_name, buf, sizeof(buf));
|
||||
|
||||
done = 1;
|
||||
}
|
||||
}
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
int
|
||||
nf_debug(const char *msg)
|
||||
{
|
||||
if (nf_ops)
|
||||
{
|
||||
long nfid_stderr = nf_ops->get_id("NF_STDERR");
|
||||
|
||||
if (nfid_stderr)
|
||||
{
|
||||
nf_ops->call(nfid_stderr, msg);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
nf_shutdown(void)
|
||||
{
|
||||
if (nf_ops)
|
||||
{
|
||||
long shutdown_id = nf_ops->get_id("NF_SHUTDOWN");
|
||||
|
||||
if (shutdown_id)
|
||||
nf_ops->call(shutdown_id);
|
||||
}
|
||||
}
|
||||
|
||||
# endif
|
||||
76
FireBee/trunk/usb/store/host/aranym/natfeat_asm.S
Normal file
76
FireBee/trunk/usb/store/host/aranym/natfeat_asm.S
Normal file
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* ARAnyM native features interface.
|
||||
* (c) 2005-2008 ARAnyM development team
|
||||
*
|
||||
* In 2006 updated with FreeMiNT headers and code.
|
||||
* In 2008 converted from "__NF" cookie to direct usage of NF instructions
|
||||
*
|
||||
**/
|
||||
|
||||
/*
|
||||
* Copied from FreeMiNT source tree where Native Features were added recently
|
||||
*
|
||||
* Copyright 2003 Frank Naumann <fnaumann@freemint.de>
|
||||
* All rights reserved.
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This file is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
*
|
||||
* Author: Frank Naumann <fnaumann@freemint.de>
|
||||
* Started: 2003-12-13
|
||||
*
|
||||
* please send suggestions, patches or bug reports to me or
|
||||
* the MiNT mailing list
|
||||
*
|
||||
*/
|
||||
|
||||
#define ARANYM 1
|
||||
# ifdef ARANYM
|
||||
|
||||
.text
|
||||
|
||||
.globl _detect_native_features
|
||||
|
||||
/*
|
||||
* NatFeats test (routine retuns TRUE/FALSE (1/0) in D0)
|
||||
*/
|
||||
_detect_native_features:
|
||||
|
||||
clr.l d0 // assume no NatFeats available
|
||||
move.l sp,a1 // save the ssp
|
||||
move.l (0x0010).w,a0 // illegal instruction vector
|
||||
move.l #fail_natfeat,(0x0010).w
|
||||
|
||||
nop // flush pipelines (for 68040+)
|
||||
|
||||
pea (nf_version_name).w(pc)
|
||||
subq.l #4,sp
|
||||
dc.w 0x7300 // Jump to NATFEAT_ID
|
||||
tst.l d0
|
||||
beq.s fail_natfeat
|
||||
moveq #1,d0 // NatFeats detected
|
||||
|
||||
fail_natfeat:
|
||||
move.l a1,sp
|
||||
move.l a0,(0x0010).w
|
||||
|
||||
nop // flush pipelines (for 68040+)
|
||||
|
||||
rts
|
||||
|
||||
nf_version_name:
|
||||
.ascii "NF_VERSION\0"
|
||||
|
||||
# endif
|
||||
63
FireBee/trunk/usb/store/host/aranym/nf_ops.h
Normal file
63
FireBee/trunk/usb/store/host/aranym/nf_ops.h
Normal file
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* $Id: nf_ops.h,v 1.2 2006-01-31 16:21:22 standa Exp $
|
||||
*
|
||||
* ARAnyM Native Features suite.
|
||||
*
|
||||
* This file was taken from FreeMiNT.
|
||||
*
|
||||
* Copyright 2003 Frank Naumann <fnaumann@freemint.de>
|
||||
* All rights reserved.
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This file is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
*
|
||||
* Author: Frank Naumann <fnaumann@freemint.de>
|
||||
* Started: 2003-12-14
|
||||
*
|
||||
* Please send suggestions, patches or bug reports to me or
|
||||
* the MiNT mailing list.
|
||||
*
|
||||
*/
|
||||
|
||||
# ifndef _m68k_nf_ops_h
|
||||
# define _m68k_nf_ops_h
|
||||
|
||||
#include <compiler.h> /* for __CDECL */
|
||||
|
||||
|
||||
struct nf_ops
|
||||
{
|
||||
long __CDECL (*get_id)(const char *);
|
||||
long __CDECL (*call)(long id, ...);
|
||||
long res[3];
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Use this function to intialize Native Features.
|
||||
*
|
||||
* @return the pointer to 'struct nf_ops' or NULL when
|
||||
* not available.
|
||||
**/
|
||||
struct nf_ops *nf_init(void);
|
||||
|
||||
|
||||
/* basic set native feature functions */
|
||||
const char *nf_name(void);
|
||||
int nf_debug(const char *msg);
|
||||
void nf_shutdown(void);
|
||||
|
||||
|
||||
# endif /* _m68k_nf_ops_h */
|
||||
40
FireBee/trunk/usb/store/host/aranym/usbhost_nfapi.h
Normal file
40
FireBee/trunk/usb/store/host/aranym/usbhost_nfapi.h
Normal file
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
NatFeat USB Host chip emulator
|
||||
|
||||
ARAnyM (C) 2010 David Gálvez
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _USBHOST_NFAPI_H
|
||||
#define _USBHOST_NFAPI_H
|
||||
|
||||
/* if you change anything in the enum {} below you have to increase
|
||||
this ARAUSBHOST_NFAPI_VERSION!
|
||||
*/
|
||||
#define ARAUSBHOST_NFAPI_VERSION 0x00000000
|
||||
|
||||
enum {
|
||||
GET_VERSION = 0, /* no parameters, return NFAPI_VERSION in d0 */
|
||||
USBHOST_LOWLEVEL_INIT,
|
||||
USBHOST_LOWLEVEL_STOP,
|
||||
USBHOST_SUBMIT_CONTROL_MSG,
|
||||
USBHOST_SUBMIT_INT_MSG,
|
||||
USBHOST_SUBMIT_BULK_MSG
|
||||
};
|
||||
|
||||
#define USBHOST(a) (nfUsbHostId + a)
|
||||
|
||||
#endif /* _USBHOST_NFAPI_H */
|
||||
1583
FireBee/trunk/usb/store/host/ethernat/isp116x-hcd.c
Normal file
1583
FireBee/trunk/usb/store/host/ethernat/isp116x-hcd.c
Normal file
File diff suppressed because it is too large
Load Diff
542
FireBee/trunk/usb/store/host/ethernat/isp116x.h
Normal file
542
FireBee/trunk/usb/store/host/ethernat/isp116x.h
Normal file
@@ -0,0 +1,542 @@
|
||||
/*
|
||||
* Modified for Atari-EtherNat by David Gálvez 2010
|
||||
*
|
||||
* ISP116x register declarations and HCD data structures
|
||||
*
|
||||
* Copyright (C) 2007 Rodolfo Giometti <giometti@linux.it>
|
||||
* Copyright (C) 2007 Eurotech S.p.A. <info@eurotech.it>
|
||||
* Copyright (C) 2005 Olav Kongas <ok@artecdesign.ee>
|
||||
* Portions:
|
||||
* Copyright (C) 2004 Lothar Wassmann
|
||||
* Copyright (C) 2004 Psion Teklogix
|
||||
* Copyright (C) 2004 David Brownell
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _ETHERNAT_ISP116X_H
|
||||
#define _ETHERNAT_ISP116X_H
|
||||
|
||||
|
||||
#define ERR(fmt, args...) printf("isp116x: %s: " fmt "\n\r" , __FUNCTION__ , ## args)
|
||||
#define WARN(fmt, args...) printf("isp116x: %s: " fmt "\n\r" , __FUNCTION__ , ## args)
|
||||
#define INFO(fmt, args...) printf("isp116x: " fmt "\n\r" , ## args)
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
/* us of 1ms frame */
|
||||
#define MAX_LOAD_LIMIT 850
|
||||
|
||||
/* Full speed: max # of bytes to transfer for a single urb
|
||||
at a time must be < 1024 && must be multiple of 64.
|
||||
832 allows transfering 4kiB within 5 frames. */
|
||||
#define MAX_TRANSFER_SIZE_FULLSPEED 832
|
||||
|
||||
/* Low speed: there is no reason to schedule in very big
|
||||
chunks; often the requested long transfers are for
|
||||
string descriptors containing short strings. */
|
||||
#define MAX_TRANSFER_SIZE_LOWSPEED 64
|
||||
|
||||
/* Bytetime (us), a rough indication of how much time it
|
||||
would take to transfer a byte of useful data over USB */
|
||||
#define BYTE_TIME_FULLSPEED 1
|
||||
#define BYTE_TIME_LOWSPEED 20
|
||||
|
||||
/* Buffer sizes */
|
||||
#define ISP116x_BUF_SIZE 4096
|
||||
#define ISP116x_ITL_BUFSIZE 0
|
||||
#define ISP116x_ATL_BUFSIZE ((ISP116x_BUF_SIZE) - 2*(ISP116x_ITL_BUFSIZE))
|
||||
|
||||
#define ISP116x_WRITE_OFFSET 0x80
|
||||
|
||||
/* --- ISP116x address registers in EtherNAT --------------------------------*/
|
||||
|
||||
#define ISP116X_HCD_ADDR 0x80000016
|
||||
#define ISP116X_HCD_DATA 0x80000012
|
||||
#define ETHERNAT_CPLD_CR 0x80000023 /* 0x80000023 - 1 */
|
||||
|
||||
/* --- ISP116x registers/bits ---------------------------------------------- */
|
||||
|
||||
#define HCREVISION 0x00
|
||||
#define HCCONTROL 0x01
|
||||
#define HCCONTROL_HCFS (3 << 6) /* host controller
|
||||
functional state */
|
||||
#define HCCONTROL_USB_RESET (0 << 6)
|
||||
#define HCCONTROL_USB_RESUME (1 << 6)
|
||||
#define HCCONTROL_USB_OPER (2 << 6)
|
||||
#define HCCONTROL_USB_SUSPEND (3 << 6)
|
||||
#define HCCONTROL_RWC (1 << 9) /* remote wakeup connected */
|
||||
#define HCCONTROL_RWE (1 << 10) /* remote wakeup enable */
|
||||
#define HCCMDSTAT 0x02
|
||||
#define HCCMDSTAT_HCR (1 << 0) /* host controller reset */
|
||||
#define HCCMDSTAT_SOC (3 << 16) /* scheduling overrun count */
|
||||
#define HCINTSTAT 0x03
|
||||
#define HCINT_SO (1 << 0) /* scheduling overrun */
|
||||
#define HCINT_WDH (1 << 1) /* writeback of done_head */
|
||||
#define HCINT_SF (1 << 2) /* start frame */
|
||||
#define HCINT_RD (1 << 3) /* resume detect */
|
||||
#define HCINT_UE (1 << 4) /* unrecoverable error */
|
||||
#define HCINT_FNO (1 << 5) /* frame number overflow */
|
||||
#define HCINT_RHSC (1 << 6) /* root hub status change */
|
||||
#define HCINT_OC (1 << 30) /* ownership change */
|
||||
#define HCINT_MIE (1 << 31) /* master interrupt enable */
|
||||
#define HCINTENB 0x04
|
||||
#define HCINTDIS 0x05
|
||||
#define HCFMINTVL 0x0d
|
||||
#define HCFMREM 0x0e
|
||||
#define HCFMNUM 0x0f
|
||||
#define HCLSTHRESH 0x11
|
||||
#define HCRHDESCA 0x12
|
||||
#define RH_A_NDP (0x3 << 0) /* # downstream ports */
|
||||
#define RH_A_PSM (1 << 8) /* power switching mode */
|
||||
#define RH_A_NPS (1 << 9) /* no power switching */
|
||||
#define RH_A_DT (1 << 10) /* device type (mbz) */
|
||||
#define RH_A_OCPM (1 << 11) /* overcurrent protection
|
||||
mode */
|
||||
#define RH_A_NOCP (1 << 12) /* no overcurrent protection */
|
||||
#define RH_A_POTPGT (0xff << 24) /* power on -> power good
|
||||
time */
|
||||
#define HCRHDESCB 0x13
|
||||
#define RH_B_DR (0xffff << 0) /* device removable flags */
|
||||
#define RH_B_PPCM (0xffff << 16) /* port power control mask */
|
||||
#define HCRHSTATUS 0x14
|
||||
#define RH_HS_LPS (1 << 0) /* local power status */
|
||||
#define RH_HS_OCI (1 << 1) /* over current indicator */
|
||||
#define RH_HS_DRWE (1 << 15) /* device remote wakeup
|
||||
enable */
|
||||
#define RH_HS_LPSC (1 << 16) /* local power status change */
|
||||
#define RH_HS_OCIC (1 << 17) /* over current indicator
|
||||
change */
|
||||
#define RH_HS_CRWE (1 << 31) /* clear remote wakeup
|
||||
enable */
|
||||
#define HCRHPORT1 0x15
|
||||
#define RH_PS_CCS (1 << 0) /* current connect status */
|
||||
#define RH_PS_PES (1 << 1) /* port enable status */
|
||||
#define RH_PS_PSS (1 << 2) /* port suspend status */
|
||||
#define RH_PS_POCI (1 << 3) /* port over current
|
||||
indicator */
|
||||
#define RH_PS_PRS (1 << 4) /* port reset status */
|
||||
#define RH_PS_PPS (1 << 8) /* port power status */
|
||||
#define RH_PS_LSDA (1 << 9) /* low speed device attached */
|
||||
#define RH_PS_CSC (1 << 16) /* connect status change */
|
||||
#define RH_PS_PESC (1 << 17) /* port enable status change */
|
||||
#define RH_PS_PSSC (1 << 18) /* port suspend status
|
||||
change */
|
||||
#define RH_PS_OCIC (1 << 19) /* over current indicator
|
||||
change */
|
||||
#define RH_PS_PRSC (1 << 20) /* port reset status change */
|
||||
#define HCRHPORT_CLRMASK (0x1f << 16)
|
||||
#define HCRHPORT2 0x16
|
||||
#define HCHWCFG 0x20
|
||||
#define HCHWCFG_15KRSEL (1 << 12)
|
||||
#define HCHWCFG_CLKNOTSTOP (1 << 11)
|
||||
#define HCHWCFG_ANALOG_OC (1 << 10)
|
||||
#define HCHWCFG_DACK_MODE (1 << 8)
|
||||
#define HCHWCFG_EOT_POL (1 << 7)
|
||||
#define HCHWCFG_DACK_POL (1 << 6)
|
||||
#define HCHWCFG_DREQ_POL (1 << 5)
|
||||
#define HCHWCFG_DBWIDTH_MASK (0x03 << 3)
|
||||
#define HCHWCFG_DBWIDTH(n) (((n) << 3) & HCHWCFG_DBWIDTH_MASK)
|
||||
#define HCHWCFG_INT_POL (1 << 2)
|
||||
#define HCHWCFG_INT_TRIGGER (1 << 1)
|
||||
#define HCHWCFG_INT_ENABLE (1 << 0)
|
||||
#define HCDMACFG 0x21
|
||||
#define HCDMACFG_BURST_LEN_MASK (0x03 << 5)
|
||||
#define HCDMACFG_BURST_LEN(n) (((n) << 5) & HCDMACFG_BURST_LEN_MASK)
|
||||
#define HCDMACFG_BURST_LEN_1 HCDMACFG_BURST_LEN(0)
|
||||
#define HCDMACFG_BURST_LEN_4 HCDMACFG_BURST_LEN(1)
|
||||
#define HCDMACFG_BURST_LEN_8 HCDMACFG_BURST_LEN(2)
|
||||
#define HCDMACFG_DMA_ENABLE (1 << 4)
|
||||
#define HCDMACFG_BUF_TYPE_MASK (0x07 << 1)
|
||||
#define HCDMACFG_CTR_SEL (1 << 2)
|
||||
#define HCDMACFG_ITLATL_SEL (1 << 1)
|
||||
#define HCDMACFG_DMA_RW_SELECT (1 << 0)
|
||||
#define HCXFERCTR 0x22
|
||||
#define HCuPINT 0x24
|
||||
#define HCuPINT_SOF (1 << 0)
|
||||
#define HCuPINT_ATL (1 << 1)
|
||||
#define HCuPINT_AIIEOT (1 << 2)
|
||||
#define HCuPINT_OPR (1 << 4)
|
||||
#define HCuPINT_SUSP (1 << 5)
|
||||
#define HCuPINT_CLKRDY (1 << 6)
|
||||
#define HCuPINTENB 0x25
|
||||
#define HCCHIPID 0x27
|
||||
#define HCCHIPID_MASK 0xff00
|
||||
#define HCCHIPID_MAGIC 0x6100
|
||||
#define HCSCRATCH 0x28
|
||||
#define HCSWRES 0x29
|
||||
#define HCSWRES_MAGIC 0x00f6
|
||||
#define HCITLBUFLEN 0x2a
|
||||
#define HCATLBUFLEN 0x2b
|
||||
#define HCBUFSTAT 0x2c
|
||||
#define HCBUFSTAT_ITL0_FULL (1 << 0)
|
||||
#define HCBUFSTAT_ITL1_FULL (1 << 1)
|
||||
#define HCBUFSTAT_ATL_FULL (1 << 2)
|
||||
#define HCBUFSTAT_ITL0_DONE (1 << 3)
|
||||
#define HCBUFSTAT_ITL1_DONE (1 << 4)
|
||||
#define HCBUFSTAT_ATL_DONE (1 << 5)
|
||||
#define HCRDITL0LEN 0x2d
|
||||
#define HCRDITL1LEN 0x2e
|
||||
#define HCITLPORT 0x40
|
||||
#define HCATLPORT 0x41
|
||||
|
||||
/* PTD accessor macros. */
|
||||
#define PTD_GET_COUNT(p) (((p)->count & PTD_COUNT_MSK) >> 0)
|
||||
#define PTD_COUNT(v) (((v) << 0) & PTD_COUNT_MSK)
|
||||
#define PTD_GET_TOGGLE(p) (((p)->count & PTD_TOGGLE_MSK) >> 10)
|
||||
#define PTD_TOGGLE(v) (((v) << 10) & PTD_TOGGLE_MSK)
|
||||
#define PTD_GET_ACTIVE(p) (((p)->count & PTD_ACTIVE_MSK) >> 11)
|
||||
#define PTD_ACTIVE(v) (((v) << 11) & PTD_ACTIVE_MSK)
|
||||
#define PTD_GET_CC(p) (((p)->count & PTD_CC_MSK) >> 12)
|
||||
#define PTD_CC(v) (((v) << 12) & PTD_CC_MSK)
|
||||
#define PTD_GET_MPS(p) (((p)->mps & PTD_MPS_MSK) >> 0)
|
||||
#define PTD_MPS(v) (((v) << 0) & PTD_MPS_MSK)
|
||||
#define PTD_GET_SPD(p) (((p)->mps & PTD_SPD_MSK) >> 10)
|
||||
#define PTD_SPD(v) (((v) << 10) & PTD_SPD_MSK)
|
||||
#define PTD_GET_LAST(p) (((p)->mps & PTD_LAST_MSK) >> 11)
|
||||
#define PTD_LAST(v) (((v) << 11) & PTD_LAST_MSK)
|
||||
#define PTD_GET_EP(p) (((p)->mps & PTD_EP_MSK) >> 12)
|
||||
#define PTD_EP(v) (((v) << 12) & PTD_EP_MSK)
|
||||
#define PTD_GET_LEN(p) (((p)->len & PTD_LEN_MSK) >> 0)
|
||||
#define PTD_LEN(v) (((v) << 0) & PTD_LEN_MSK)
|
||||
#define PTD_GET_DIR(p) (((p)->len & PTD_DIR_MSK) >> 10)
|
||||
#define PTD_DIR(v) (((v) << 10) & PTD_DIR_MSK)
|
||||
#define PTD_GET_B5_5(p) (((p)->len & PTD_B5_5_MSK) >> 13)
|
||||
#define PTD_B5_5(v) (((v) << 13) & PTD_B5_5_MSK)
|
||||
#define PTD_GET_FA(p) (((p)->faddr & PTD_FA_MSK) >> 0)
|
||||
#define PTD_FA(v) (((v) << 0) & PTD_FA_MSK)
|
||||
#define PTD_GET_FMT(p) (((p)->faddr & PTD_FMT_MSK) >> 7)
|
||||
#define PTD_FMT(v) (((v) << 7) & PTD_FMT_MSK)
|
||||
|
||||
/* Hardware transfer status codes -- CC from ptd->count */
|
||||
#define TD_CC_NOERROR 0x00
|
||||
#define TD_CC_CRC 0x01
|
||||
#define TD_CC_BITSTUFFING 0x02
|
||||
#define TD_CC_DATATOGGLEM 0x03
|
||||
#define TD_CC_STALL 0x04
|
||||
#define TD_DEVNOTRESP 0x05
|
||||
#define TD_PIDCHECKFAIL 0x06
|
||||
#define TD_UNEXPECTEDPID 0x07
|
||||
#define TD_DATAOVERRUN 0x08
|
||||
#define TD_DATAUNDERRUN 0x09
|
||||
/* 0x0A, 0x0B reserved for hardware */
|
||||
#define TD_BUFFEROVERRUN 0x0C
|
||||
#define TD_BUFFERUNDERRUN 0x0D
|
||||
/* 0x0E, 0x0F reserved for HCD */
|
||||
#define TD_NOTACCESSED 0x0F
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
#define LOG2_PERIODIC_SIZE 5 /* arbitrary; this matches OHCI */
|
||||
#define PERIODIC_SIZE (1 << LOG2_PERIODIC_SIZE)
|
||||
|
||||
/* Philips transfer descriptor */
|
||||
struct ptd {
|
||||
u16 count;
|
||||
#define PTD_COUNT_MSK (0x3ff << 0)
|
||||
#define PTD_TOGGLE_MSK (1 << 10)
|
||||
#define PTD_ACTIVE_MSK (1 << 11)
|
||||
#define PTD_CC_MSK (0xf << 12)
|
||||
u16 mps;
|
||||
#define PTD_MPS_MSK (0x3ff << 0)
|
||||
#define PTD_SPD_MSK (1 << 10)
|
||||
#define PTD_LAST_MSK (1 << 11)
|
||||
#define PTD_EP_MSK (0xf << 12)
|
||||
u16 len;
|
||||
#define PTD_LEN_MSK (0x3ff << 0)
|
||||
#define PTD_DIR_MSK (3 << 10)
|
||||
#define PTD_DIR_SETUP (0)
|
||||
#define PTD_DIR_OUT (1)
|
||||
#define PTD_DIR_IN (2)
|
||||
#define PTD_B5_5_MSK (1 << 13)
|
||||
u16 faddr;
|
||||
#define PTD_FA_MSK (0x7f << 0)
|
||||
#define PTD_FMT_MSK (1 << 7)
|
||||
} __attribute__ ((packed, aligned(2)));
|
||||
|
||||
struct isp116x_ep {
|
||||
struct usb_device *udev;
|
||||
struct ptd ptd;
|
||||
|
||||
u8 maxpacket;
|
||||
u8 epnum;
|
||||
u8 nextpid;
|
||||
|
||||
u16 length; /* of current packet */
|
||||
unsigned char *data; /* to databuf */
|
||||
|
||||
u16 error_count;
|
||||
};
|
||||
|
||||
/* URB struct */
|
||||
#define N_URB_TD 48
|
||||
#define URB_DEL 1
|
||||
typedef struct {
|
||||
struct isp116x_ep *ed;
|
||||
void *transfer_buffer; /* (in) associated data buffer */
|
||||
int actual_length; /* (return) actual transfer length */
|
||||
unsigned long pipe; /* (in) pipe information */
|
||||
#if 0
|
||||
int state;
|
||||
#endif
|
||||
} urb_priv_t;
|
||||
|
||||
struct isp116x_platform_data {
|
||||
/* Enable internal resistors on downstream ports */
|
||||
unsigned sel15Kres:1;
|
||||
/* On-chip overcurrent detection */
|
||||
unsigned oc_enable:1;
|
||||
/* Enable wakeup by devices on usb bus (e.g. wakeup
|
||||
by attachment/detachment or by device activity
|
||||
such as moving a mouse). When chosen, this option
|
||||
prevents stopping internal clock, increasing
|
||||
thereby power consumption in suspended state. */
|
||||
unsigned remote_wakeup_enable:1;
|
||||
};
|
||||
|
||||
struct isp116x {
|
||||
u16 *addr_reg;
|
||||
u16 *data_reg;
|
||||
|
||||
struct isp116x_platform_data *board;
|
||||
|
||||
struct dentry *dentry;
|
||||
unsigned long stat1, stat2, stat4, stat8, stat16;
|
||||
|
||||
/* Status flags */
|
||||
unsigned disabled:1;
|
||||
unsigned sleeping:1;
|
||||
|
||||
/* Root hub registers */
|
||||
u32 rhdesca;
|
||||
u32 rhdescb;
|
||||
u32 rhstatus;
|
||||
u32 rhport[2];
|
||||
|
||||
/* Schedule for the current frame */
|
||||
struct isp116x_ep *atl_active;
|
||||
int atl_buflen;
|
||||
int atl_bufshrt;
|
||||
int atl_last_dir;
|
||||
int atl_finishing;
|
||||
};
|
||||
|
||||
/* ------------------------------------------------- */
|
||||
|
||||
/* Inter-io delay (ns). The chip is picky about access timings; it
|
||||
* expects at least:
|
||||
* 150ns delay between consecutive accesses to DATA_REG,
|
||||
* 300ns delay between access to ADDR_REG and DATA_REG
|
||||
* OE, WE MUST NOT be changed during these intervals
|
||||
*/
|
||||
#if defined(UDELAY)
|
||||
#define isp116x_delay(h,d) udelay(d)
|
||||
#else
|
||||
#define isp116x_delay(h,d) do {} while (0)
|
||||
#endif
|
||||
|
||||
#include "../../super.h" /*
|
||||
* Functions to call supervisor mode
|
||||
* Super() in TOS is buggy
|
||||
*/
|
||||
|
||||
u32 p;
|
||||
|
||||
static inline void isp116x_write_addr(struct isp116x *isp116x, unsigned reg)
|
||||
{
|
||||
// p = SuperFromUser( );
|
||||
__raw_writew(reg & 0xff, isp116x->addr_reg );
|
||||
isp116x_delay(isp116x, UDELAY);
|
||||
// SuperToUser( p );
|
||||
}
|
||||
|
||||
static inline void isp116x_write_data16(struct isp116x *isp116x, u16 val)
|
||||
{
|
||||
// p = SuperFromUser( );
|
||||
writew(val, isp116x->data_reg);
|
||||
isp116x_delay(isp116x, UDELAY);
|
||||
// SuperToUser( p );
|
||||
}
|
||||
|
||||
static inline void isp116x_raw_write_data16(struct isp116x *isp116x, u16 val)
|
||||
{
|
||||
// p = SuperFromUser( );
|
||||
__raw_writew(val, isp116x->data_reg);
|
||||
isp116x_delay(isp116x, UDELAY);
|
||||
// SuperToUser( p );
|
||||
}
|
||||
|
||||
static inline u16 isp116x_read_data16(struct isp116x *isp116x)
|
||||
{
|
||||
u16 val;
|
||||
// p = SuperFromUser( );
|
||||
val = readw(isp116x->data_reg);
|
||||
isp116x_delay(isp116x, UDELAY);
|
||||
// SuperToUser( p );
|
||||
return val;
|
||||
}
|
||||
|
||||
static inline u16 isp116x_raw_read_data16(struct isp116x *isp116x)
|
||||
{
|
||||
u16 val;
|
||||
// p = SuperFromUser( );
|
||||
val = __raw_readw(isp116x->data_reg);
|
||||
isp116x_delay(isp116x, UDELAY);
|
||||
// SuperToUser( p );
|
||||
return val;
|
||||
}
|
||||
|
||||
|
||||
static inline void isp116x_write_data32(struct isp116x *isp116x, u32 val)
|
||||
{
|
||||
// p = SuperFromUser( );
|
||||
writew(val & 0xffff, isp116x->data_reg);
|
||||
isp116x_delay(isp116x, UDELAY);
|
||||
writew(val >> 16, isp116x->data_reg);
|
||||
isp116x_delay(isp116x, UDELAY);
|
||||
// SuperToUser( p );
|
||||
}
|
||||
|
||||
/*
|
||||
* Added for EtherNat, to write HC registers without swaping them
|
||||
* EtherNat already swap them by hardware (i suppose.....)
|
||||
*/
|
||||
static inline void isp116x_raw_write_data32(struct isp116x *isp116x, u32 val)
|
||||
{
|
||||
// p = SuperFromUser( );
|
||||
__raw_writew(val & 0xffff, isp116x->data_reg);
|
||||
isp116x_delay(isp116x, UDELAY);
|
||||
__raw_writew(val >> 16, isp116x->data_reg);
|
||||
isp116x_delay(isp116x, UDELAY);
|
||||
// SuperToUser( p );
|
||||
}
|
||||
/***********************************************/
|
||||
|
||||
static inline u32 isp116x_read_data32(struct isp116x *isp116x)
|
||||
{
|
||||
u32 val;
|
||||
// p = SuperFromUser( );
|
||||
val = (u32) readw(isp116x->data_reg);
|
||||
isp116x_delay(isp116x, UDELAY);
|
||||
val |= ((u32) readw(isp116x->data_reg)) << 16;
|
||||
isp116x_delay(isp116x, UDELAY);
|
||||
// SuperToUser( p );
|
||||
return val;
|
||||
}
|
||||
|
||||
/*
|
||||
* Added for EtherNat, to read HC registers without swaping them
|
||||
* EtherNat already swap them by hardware (i suppose.....)
|
||||
*/
|
||||
static inline u32 isp116x_raw_read_data32(struct isp116x *isp116x)
|
||||
{
|
||||
u32 val;
|
||||
// p = SuperFromUser( );
|
||||
val = (u32) __raw_readw(isp116x->data_reg);
|
||||
isp116x_delay(isp116x, UDELAY);
|
||||
val |= ((u32) __raw_readw(isp116x->data_reg)) << 16;
|
||||
isp116x_delay(isp116x, UDELAY);
|
||||
// SuperToUser( p );
|
||||
return val;
|
||||
}
|
||||
/*******************************************************************/
|
||||
|
||||
/* Let's keep register access functions out of line. Hint:
|
||||
we wait at least 150 ns at every access.
|
||||
*/
|
||||
|
||||
/* with EtherNat use raw_read to avoid swaping bytes*/
|
||||
|
||||
static u16 isp116x_read_reg16(struct isp116x *isp116x, unsigned reg)
|
||||
{
|
||||
isp116x_write_addr(isp116x, reg);
|
||||
return isp116x_raw_read_data16(isp116x);
|
||||
}
|
||||
|
||||
static u32 isp116x_read_reg32(struct isp116x *isp116x, unsigned reg)
|
||||
{
|
||||
isp116x_write_addr(isp116x, reg);
|
||||
return isp116x_raw_read_data32(isp116x);
|
||||
}
|
||||
|
||||
static void isp116x_write_reg16(struct isp116x *isp116x, unsigned reg,
|
||||
unsigned val)
|
||||
{
|
||||
isp116x_write_addr(isp116x, reg | ISP116x_WRITE_OFFSET);
|
||||
isp116x_raw_write_data16(isp116x, (u16) (val & 0xffff));
|
||||
}
|
||||
|
||||
/* with Etehrnat used raw_write to avoid swaping bytes by software */
|
||||
static void isp116x_write_reg32(struct isp116x *isp116x, unsigned reg,
|
||||
unsigned val)
|
||||
{
|
||||
isp116x_write_addr(isp116x, reg | ISP116x_WRITE_OFFSET);
|
||||
isp116x_raw_write_data32(isp116x, (u32) val);
|
||||
}
|
||||
|
||||
/* --- USB HUB constants (not OHCI-specific; see hub.h) -------------------- */
|
||||
|
||||
/* destination of request */
|
||||
#define RH_INTERFACE 0x01
|
||||
#define RH_ENDPOINT 0x02
|
||||
#define RH_OTHER 0x03
|
||||
|
||||
#define RH_CLASS 0x20
|
||||
#define RH_VENDOR 0x40
|
||||
|
||||
/* Requests: bRequest << 8 | bmRequestType */
|
||||
#define RH_GET_STATUS 0x0080
|
||||
#define RH_CLEAR_FEATURE 0x0100
|
||||
#define RH_SET_FEATURE 0x0300
|
||||
#define RH_SET_ADDRESS 0x0500
|
||||
#define RH_GET_DESCRIPTOR 0x0680
|
||||
#define RH_SET_DESCRIPTOR 0x0700
|
||||
#define RH_GET_CONFIGURATION 0x0880
|
||||
#define RH_SET_CONFIGURATION 0x0900
|
||||
#define RH_GET_STATE 0x0280
|
||||
#define RH_GET_INTERFACE 0x0A80
|
||||
#define RH_SET_INTERFACE 0x0B00
|
||||
#define RH_SYNC_FRAME 0x0C80
|
||||
/* Our Vendor Specific Request */
|
||||
#define RH_SET_EP 0x2000
|
||||
|
||||
/* Hub port features */
|
||||
#define RH_PORT_CONNECTION 0x00
|
||||
#define RH_PORT_ENABLE 0x01
|
||||
#define RH_PORT_SUSPEND 0x02
|
||||
#define RH_PORT_OVER_CURRENT 0x03
|
||||
#define RH_PORT_RESET 0x04
|
||||
#define RH_PORT_POWER 0x08
|
||||
#define RH_PORT_LOW_SPEED 0x09
|
||||
|
||||
#define RH_C_PORT_CONNECTION 0x10
|
||||
#define RH_C_PORT_ENABLE 0x11
|
||||
#define RH_C_PORT_SUSPEND 0x12
|
||||
#define RH_C_PORT_OVER_CURRENT 0x13
|
||||
#define RH_C_PORT_RESET 0x14
|
||||
|
||||
/* Hub features */
|
||||
#define RH_C_HUB_LOCAL_POWER 0x00
|
||||
#define RH_C_HUB_OVER_CURRENT 0x01
|
||||
|
||||
#define RH_DEVICE_REMOTE_WAKEUP 0x00
|
||||
#define RH_ENDPOINT_STALL 0x01
|
||||
|
||||
#define RH_ACK 0x01
|
||||
#define RH_REQ_ERR -1
|
||||
#define RH_NACK 0x00
|
||||
|
||||
#endif /* _ETHERNAT_ISP116X_H */
|
||||
1561
FireBee/trunk/usb/store/host/netusbee/isp116x-hcd.c
Normal file
1561
FireBee/trunk/usb/store/host/netusbee/isp116x-hcd.c
Normal file
File diff suppressed because it is too large
Load Diff
596
FireBee/trunk/usb/store/host/netusbee/isp116x.h
Normal file
596
FireBee/trunk/usb/store/host/netusbee/isp116x.h
Normal file
@@ -0,0 +1,596 @@
|
||||
/*
|
||||
* Modified for Atari-NetUSBee by David Gálvez 2010
|
||||
*
|
||||
* ISP116x register declarations and HCD data structures
|
||||
*
|
||||
* Copyright (C) 2007 Rodolfo Giometti <giometti@linux.it>
|
||||
* Copyright (C) 2007 Eurotech S.p.A. <info@eurotech.it>
|
||||
* Copyright (C) 2005 Olav Kongas <ok@artecdesign.ee>
|
||||
* Portions:
|
||||
* Copyright (C) 2004 Lothar Wassmann
|
||||
* Copyright (C) 2004 Psion Teklogix
|
||||
* Copyright (C) 2004 David Brownell
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
#ifndef _NETUSBEE_ISP116X_H
|
||||
#define _NETUSBEE_ISP116X_H
|
||||
|
||||
|
||||
#define ERR(fmt, args...) printf("isp116x: %s: " fmt "\n\r" , __FUNCTION__ , ## args)
|
||||
#define WARN(fmt, args...) printf("isp116x: %s: " fmt "\n\r" , __FUNCTION__ , ## args)
|
||||
#define INFO(fmt, args...) printf("isp116x: " fmt "\n\r" , ## args)
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
/* us of 1ms frame */
|
||||
#define MAX_LOAD_LIMIT 850
|
||||
|
||||
/* Full speed: max # of bytes to transfer for a single urb
|
||||
at a time must be < 1024 && must be multiple of 64.
|
||||
832 allows transfering 4kiB within 5 frames. */
|
||||
#define MAX_TRANSFER_SIZE_FULLSPEED 832
|
||||
|
||||
/* Low speed: there is no reason to schedule in very big
|
||||
chunks; often the requested long transfers are for
|
||||
string descriptors containing short strings. */
|
||||
#define MAX_TRANSFER_SIZE_LOWSPEED 64
|
||||
|
||||
/* Bytetime (us), a rough indication of how much time it
|
||||
would take to transfer a byte of useful data over USB */
|
||||
#define BYTE_TIME_FULLSPEED 1
|
||||
#define BYTE_TIME_LOWSPEED 20
|
||||
|
||||
/* Buffer sizes */
|
||||
#define ISP116x_BUF_SIZE 4096
|
||||
#define ISP116x_ITL_BUFSIZE 0
|
||||
#define ISP116x_ATL_BUFSIZE ((ISP116x_BUF_SIZE) - 2*(ISP116x_ITL_BUFSIZE))
|
||||
|
||||
#define ISP116x_WRITE_OFFSET 0x80
|
||||
|
||||
|
||||
/* --- ISP116x address registers in Netusbee --------------------------------*/
|
||||
|
||||
#define ISP116X_HCD_ADDR_BEE 0x00FBC000
|
||||
#define ISP116X_HCD_DATA_BEE 0x00FA0000
|
||||
|
||||
|
||||
/* --- ISP116x registers/bits ---------------------------------------------- */
|
||||
|
||||
#define HCREVISION 0x00
|
||||
#define HCCONTROL 0x01
|
||||
#define HCCONTROL_HCFS (3 << 6) /* host controller
|
||||
functional state */
|
||||
#define HCCONTROL_USB_RESET (0 << 6)
|
||||
#define HCCONTROL_USB_RESUME (1 << 6)
|
||||
#define HCCONTROL_USB_OPER (2 << 6)
|
||||
#define HCCONTROL_USB_SUSPEND (3 << 6)
|
||||
#define HCCONTROL_RWC (1 << 9) /* remote wakeup connected */
|
||||
#define HCCONTROL_RWE (1 << 10) /* remote wakeup enable */
|
||||
#define HCCMDSTAT 0x02
|
||||
#define HCCMDSTAT_HCR (1 << 0) /* host controller reset */
|
||||
#define HCCMDSTAT_SOC (3 << 16) /* scheduling overrun count */
|
||||
#define HCINTSTAT 0x03
|
||||
#define HCINT_SO (1 << 0) /* scheduling overrun */
|
||||
#define HCINT_WDH (1 << 1) /* writeback of done_head */
|
||||
#define HCINT_SF (1 << 2) /* start frame */
|
||||
#define HCINT_RD (1 << 3) /* resume detect */
|
||||
#define HCINT_UE (1 << 4) /* unrecoverable error */
|
||||
#define HCINT_FNO (1 << 5) /* frame number overflow */
|
||||
#define HCINT_RHSC (1 << 6) /* root hub status change */
|
||||
#define HCINT_OC (1 << 30) /* ownership change */
|
||||
#define HCINT_MIE (1 << 31) /* master interrupt enable */
|
||||
#define HCINTENB 0x04
|
||||
#define HCINTDIS 0x05
|
||||
#define HCFMINTVL 0x0d
|
||||
#define HCFMREM 0x0e
|
||||
#define HCFMNUM 0x0f
|
||||
#define HCLSTHRESH 0x11
|
||||
#define HCRHDESCA 0x12
|
||||
#define RH_A_NDP (0x3 << 0) /* # downstream ports */
|
||||
#define RH_A_PSM (1 << 8) /* power switching mode */
|
||||
#define RH_A_NPS (1 << 9) /* no power switching */
|
||||
#define RH_A_DT (1 << 10) /* device type (mbz) */
|
||||
#define RH_A_OCPM (1 << 11) /* overcurrent protection
|
||||
mode */
|
||||
#define RH_A_NOCP (1 << 12) /* no overcurrent protection */
|
||||
#define RH_A_POTPGT (0xff << 24) /* power on -> power good
|
||||
time */
|
||||
#define HCRHDESCB 0x13
|
||||
#define RH_B_DR (0xffff << 0) /* device removable flags */
|
||||
#define RH_B_PPCM (0xffff << 16) /* port power control mask */
|
||||
#define HCRHSTATUS 0x14
|
||||
#define RH_HS_LPS (1 << 0) /* local power status */
|
||||
#define RH_HS_OCI (1 << 1) /* over current indicator */
|
||||
#define RH_HS_DRWE (1 << 15) /* device remote wakeup
|
||||
enable */
|
||||
#define RH_HS_LPSC (1 << 16) /* local power status change */
|
||||
#define RH_HS_OCIC (1 << 17) /* over current indicator
|
||||
change */
|
||||
#define RH_HS_CRWE (1 << 31) /* clear remote wakeup
|
||||
enable */
|
||||
#define HCRHPORT1 0x15
|
||||
#define RH_PS_CCS (1 << 0) /* current connect status */
|
||||
#define RH_PS_PES (1 << 1) /* port enable status */
|
||||
#define RH_PS_PSS (1 << 2) /* port suspend status */
|
||||
#define RH_PS_POCI (1 << 3) /* port over current
|
||||
indicator */
|
||||
#define RH_PS_PRS (1 << 4) /* port reset status */
|
||||
#define RH_PS_PPS (1 << 8) /* port power status */
|
||||
#define RH_PS_LSDA (1 << 9) /* low speed device attached */
|
||||
#define RH_PS_CSC (1 << 16) /* connect status change */
|
||||
#define RH_PS_PESC (1 << 17) /* port enable status change */
|
||||
#define RH_PS_PSSC (1 << 18) /* port suspend status
|
||||
change */
|
||||
#define RH_PS_OCIC (1 << 19) /* over current indicator
|
||||
change */
|
||||
#define RH_PS_PRSC (1 << 20) /* port reset status change */
|
||||
#define HCRHPORT_CLRMASK (0x1f << 16)
|
||||
#define HCRHPORT2 0x16
|
||||
#define HCHWCFG 0x20
|
||||
#define HCHWCFG_15KRSEL (1 << 12)
|
||||
#define HCHWCFG_CLKNOTSTOP (1 << 11)
|
||||
#define HCHWCFG_ANALOG_OC (1 << 10)
|
||||
#define HCHWCFG_DACK_MODE (1 << 8)
|
||||
#define HCHWCFG_EOT_POL (1 << 7)
|
||||
#define HCHWCFG_DACK_POL (1 << 6)
|
||||
#define HCHWCFG_DREQ_POL (1 << 5)
|
||||
#define HCHWCFG_DBWIDTH_MASK (0x03 << 3)
|
||||
#define HCHWCFG_DBWIDTH(n) (((n) << 3) & HCHWCFG_DBWIDTH_MASK)
|
||||
#define HCHWCFG_INT_POL (1 << 2)
|
||||
#define HCHWCFG_INT_TRIGGER (1 << 1)
|
||||
#define HCHWCFG_INT_ENABLE (1 << 0)
|
||||
#define HCDMACFG 0x21
|
||||
#define HCDMACFG_BURST_LEN_MASK (0x03 << 5)
|
||||
#define HCDMACFG_BURST_LEN(n) (((n) << 5) & HCDMACFG_BURST_LEN_MASK)
|
||||
#define HCDMACFG_BURST_LEN_1 HCDMACFG_BURST_LEN(0)
|
||||
#define HCDMACFG_BURST_LEN_4 HCDMACFG_BURST_LEN(1)
|
||||
#define HCDMACFG_BURST_LEN_8 HCDMACFG_BURST_LEN(2)
|
||||
#define HCDMACFG_DMA_ENABLE (1 << 4)
|
||||
#define HCDMACFG_BUF_TYPE_MASK (0x07 << 1)
|
||||
#define HCDMACFG_CTR_SEL (1 << 2)
|
||||
#define HCDMACFG_ITLATL_SEL (1 << 1)
|
||||
#define HCDMACFG_DMA_RW_SELECT (1 << 0)
|
||||
#define HCXFERCTR 0x22
|
||||
#define HCuPINT 0x24
|
||||
#define HCuPINT_SOF (1 << 0)
|
||||
#define HCuPINT_ATL (1 << 1)
|
||||
#define HCuPINT_AIIEOT (1 << 2)
|
||||
#define HCuPINT_OPR (1 << 4)
|
||||
#define HCuPINT_SUSP (1 << 5)
|
||||
#define HCuPINT_CLKRDY (1 << 6)
|
||||
#define HCuPINTENB 0x25
|
||||
#define HCCHIPID 0x27
|
||||
#define HCCHIPID_MASK 0xff00
|
||||
#define HCCHIPID_MAGIC 0x6100
|
||||
#define HCSCRATCH 0x28
|
||||
#define HCSWRES 0x29
|
||||
#define HCSWRES_MAGIC 0x00f6
|
||||
#define HCITLBUFLEN 0x2a
|
||||
#define HCATLBUFLEN 0x2b
|
||||
#define HCBUFSTAT 0x2c
|
||||
#define HCBUFSTAT_ITL0_FULL (1 << 0)
|
||||
#define HCBUFSTAT_ITL1_FULL (1 << 1)
|
||||
#define HCBUFSTAT_ATL_FULL (1 << 2)
|
||||
#define HCBUFSTAT_ITL0_DONE (1 << 3)
|
||||
#define HCBUFSTAT_ITL1_DONE (1 << 4)
|
||||
#define HCBUFSTAT_ATL_DONE (1 << 5)
|
||||
#define HCRDITL0LEN 0x2d
|
||||
#define HCRDITL1LEN 0x2e
|
||||
#define HCITLPORT 0x40
|
||||
#define HCATLPORT 0x41
|
||||
|
||||
/* PTD accessor macros. */
|
||||
#define PTD_GET_COUNT(p) (((p)->count & PTD_COUNT_MSK) >> 0)
|
||||
#define PTD_COUNT(v) (((v) << 0) & PTD_COUNT_MSK)
|
||||
#define PTD_GET_TOGGLE(p) (((p)->count & PTD_TOGGLE_MSK) >> 10)
|
||||
#define PTD_TOGGLE(v) (((v) << 10) & PTD_TOGGLE_MSK)
|
||||
#define PTD_GET_ACTIVE(p) (((p)->count & PTD_ACTIVE_MSK) >> 11)
|
||||
#define PTD_ACTIVE(v) (((v) << 11) & PTD_ACTIVE_MSK)
|
||||
#define PTD_GET_CC(p) (((p)->count & PTD_CC_MSK) >> 12)
|
||||
#define PTD_CC(v) (((v) << 12) & PTD_CC_MSK)
|
||||
#define PTD_GET_MPS(p) (((p)->mps & PTD_MPS_MSK) >> 0)
|
||||
#define PTD_MPS(v) (((v) << 0) & PTD_MPS_MSK)
|
||||
#define PTD_GET_SPD(p) (((p)->mps & PTD_SPD_MSK) >> 10)
|
||||
#define PTD_SPD(v) (((v) << 10) & PTD_SPD_MSK)
|
||||
#define PTD_GET_LAST(p) (((p)->mps & PTD_LAST_MSK) >> 11)
|
||||
#define PTD_LAST(v) (((v) << 11) & PTD_LAST_MSK)
|
||||
#define PTD_GET_EP(p) (((p)->mps & PTD_EP_MSK) >> 12)
|
||||
#define PTD_EP(v) (((v) << 12) & PTD_EP_MSK)
|
||||
#define PTD_GET_LEN(p) (((p)->len & PTD_LEN_MSK) >> 0)
|
||||
#define PTD_LEN(v) (((v) << 0) & PTD_LEN_MSK)
|
||||
#define PTD_GET_DIR(p) (((p)->len & PTD_DIR_MSK) >> 10)
|
||||
#define PTD_DIR(v) (((v) << 10) & PTD_DIR_MSK)
|
||||
#define PTD_GET_B5_5(p) (((p)->len & PTD_B5_5_MSK) >> 13)
|
||||
#define PTD_B5_5(v) (((v) << 13) & PTD_B5_5_MSK)
|
||||
#define PTD_GET_FA(p) (((p)->faddr & PTD_FA_MSK) >> 0)
|
||||
#define PTD_FA(v) (((v) << 0) & PTD_FA_MSK)
|
||||
#define PTD_GET_FMT(p) (((p)->faddr & PTD_FMT_MSK) >> 7)
|
||||
#define PTD_FMT(v) (((v) << 7) & PTD_FMT_MSK)
|
||||
|
||||
/* Hardware transfer status codes -- CC from ptd->count */
|
||||
#define TD_CC_NOERROR 0x00
|
||||
#define TD_CC_CRC 0x01
|
||||
#define TD_CC_BITSTUFFING 0x02
|
||||
#define TD_CC_DATATOGGLEM 0x03
|
||||
#define TD_CC_STALL 0x04
|
||||
#define TD_DEVNOTRESP 0x05
|
||||
#define TD_PIDCHECKFAIL 0x06
|
||||
#define TD_UNEXPECTEDPID 0x07
|
||||
#define TD_DATAOVERRUN 0x08
|
||||
#define TD_DATAUNDERRUN 0x09
|
||||
/* 0x0A, 0x0B reserved for hardware */
|
||||
#define TD_BUFFEROVERRUN 0x0C
|
||||
#define TD_BUFFERUNDERRUN 0x0D
|
||||
/* 0x0E, 0x0F reserved for HCD */
|
||||
#define TD_NOTACCESSED 0x0F
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
#define LOG2_PERIODIC_SIZE 5 /* arbitrary; this matches OHCI */
|
||||
#define PERIODIC_SIZE (1 << LOG2_PERIODIC_SIZE)
|
||||
|
||||
/* Philips transfer descriptor */
|
||||
struct ptd {
|
||||
u16 count;
|
||||
#define PTD_COUNT_MSK (0x3ff << 0)
|
||||
#define PTD_TOGGLE_MSK (1 << 10)
|
||||
#define PTD_ACTIVE_MSK (1 << 11)
|
||||
#define PTD_CC_MSK (0xf << 12)
|
||||
u16 mps;
|
||||
#define PTD_MPS_MSK (0x3ff << 0)
|
||||
#define PTD_SPD_MSK (1 << 10)
|
||||
#define PTD_LAST_MSK (1 << 11)
|
||||
#define PTD_EP_MSK (0xf << 12)
|
||||
u16 len;
|
||||
#define PTD_LEN_MSK (0x3ff << 0)
|
||||
#define PTD_DIR_MSK (3 << 10)
|
||||
#define PTD_DIR_SETUP (0)
|
||||
#define PTD_DIR_OUT (1)
|
||||
#define PTD_DIR_IN (2)
|
||||
#define PTD_B5_5_MSK (1 << 13)
|
||||
u16 faddr;
|
||||
#define PTD_FA_MSK (0x7f << 0)
|
||||
#define PTD_FMT_MSK (1 << 7)
|
||||
} __attribute__ ((packed, aligned(2)));
|
||||
|
||||
struct isp116x_ep {
|
||||
struct usb_device *udev;
|
||||
struct ptd ptd;
|
||||
|
||||
u8 maxpacket;
|
||||
u8 epnum;
|
||||
u8 nextpid;
|
||||
|
||||
u16 length; /* of current packet */
|
||||
unsigned char *data; /* to databuf */
|
||||
|
||||
u16 error_count;
|
||||
};
|
||||
|
||||
/* URB struct */
|
||||
#define N_URB_TD 48
|
||||
#define URB_DEL 1
|
||||
typedef struct {
|
||||
struct isp116x_ep *ed;
|
||||
void *transfer_buffer; /* (in) associated data buffer */
|
||||
int actual_length; /* (return) actual transfer length */
|
||||
unsigned long pipe; /* (in) pipe information */
|
||||
#if 0
|
||||
int state;
|
||||
#endif
|
||||
} urb_priv_t;
|
||||
|
||||
struct isp116x_platform_data {
|
||||
/* Enable internal resistors on downstream ports */
|
||||
unsigned sel15Kres:1;
|
||||
/* On-chip overcurrent detection */
|
||||
unsigned oc_enable:1;
|
||||
/* Enable wakeup by devices on usb bus (e.g. wakeup
|
||||
by attachment/detachment or by device activity
|
||||
such as moving a mouse). When chosen, this option
|
||||
prevents stopping internal clock, increasing
|
||||
thereby power consumption in suspended state. */
|
||||
unsigned remote_wakeup_enable:1;
|
||||
};
|
||||
|
||||
struct isp116x {
|
||||
u16 *addr_reg;
|
||||
u16 *data_reg;
|
||||
|
||||
struct isp116x_platform_data *board;
|
||||
|
||||
struct dentry *dentry;
|
||||
unsigned long stat1, stat2, stat4, stat8, stat16;
|
||||
|
||||
/* Status flags */
|
||||
unsigned disabled:1;
|
||||
unsigned sleeping:1;
|
||||
|
||||
/* Root hub registers */
|
||||
u32 rhdesca;
|
||||
u32 rhdescb;
|
||||
u32 rhstatus;
|
||||
u32 rhport[2];
|
||||
|
||||
/* Schedule for the current frame */
|
||||
struct isp116x_ep *atl_active;
|
||||
int atl_buflen;
|
||||
int atl_bufshrt;
|
||||
int atl_last_dir;
|
||||
int atl_finishing;
|
||||
};
|
||||
|
||||
/* ------------------------------------------------- */
|
||||
|
||||
/* Inter-io delay (ns). The chip is picky about access timings; it
|
||||
* expects at least:
|
||||
* 150ns delay between consecutive accesses to DATA_REG,
|
||||
* 300ns delay between access to ADDR_REG and DATA_REG
|
||||
* OE, WE MUST NOT be changed during these intervals
|
||||
*/
|
||||
#if defined(UDELAY)
|
||||
#define isp116x_delay(h,d) udelay(d)
|
||||
#else
|
||||
#define isp116x_delay(h,d) do {} while (0)
|
||||
#endif
|
||||
|
||||
#include "../../super.h" /*
|
||||
* Functions to call supervisor mode
|
||||
* Super() in in TOS is buggy
|
||||
*/
|
||||
|
||||
|
||||
static inline void isp116x_write_addr(struct isp116x *isp116x, unsigned reg)
|
||||
{
|
||||
u16 dumm;
|
||||
u32 p = 0;
|
||||
if ( !(Super (SUP_INQUIRE)))
|
||||
p = SuperFromUser( );
|
||||
isp116x->data_reg = (u16*)(ISP116X_HCD_DATA_BEE + ((reg & 0x00ff)<<1));
|
||||
dumm = __raw_readw( isp116x->data_reg );
|
||||
isp116x->addr_reg = (u16*)ISP116X_HCD_ADDR_BEE;
|
||||
dumm = __raw_readw( isp116x->addr_reg );
|
||||
isp116x_delay(isp116x, UDELAY);
|
||||
if ((Super (SUP_INQUIRE)) && (p))
|
||||
SuperToUser( p );
|
||||
// ERR ( "data_reg: %x \n\r", isp116x->data_reg);
|
||||
// ERR ( "addr_reg: %x \n\r", isp116x->addr_reg);
|
||||
}
|
||||
|
||||
static inline void isp116x_write_data16(struct isp116x *isp116x, u16 val)
|
||||
{
|
||||
u16 dumm;
|
||||
u32 p = 0;
|
||||
if ( !(Super (SUP_INQUIRE)))
|
||||
p = SuperFromUser( );
|
||||
isp116x->data_reg = (u16*)(ISP116X_HCD_DATA_BEE + ((val & 0xff00)>>7) );
|
||||
dumm = __raw_readw(isp116x->data_reg);
|
||||
isp116x->addr_reg = (u16*)((ISP116X_HCD_ADDR_BEE - 0x4000) + ((val & 0x00ff)<<1));
|
||||
dumm = __raw_readw(isp116x->addr_reg);
|
||||
isp116x_delay(isp116x, UDELAY);
|
||||
if ((Super (SUP_INQUIRE)) && (p))
|
||||
SuperToUser( p );
|
||||
// ERR ( "data_reg: %x \n\r", isp116x->data_reg);
|
||||
// ERR ( "addr_reg: %x \n\r", isp116x->addr_reg);
|
||||
}
|
||||
|
||||
static inline void isp116x_raw_write_data16(struct isp116x *isp116x, u16 val)
|
||||
{
|
||||
u16 dumm;
|
||||
u32 p = 0;
|
||||
if ( !(Super (SUP_INQUIRE)))
|
||||
p = SuperFromUser( );
|
||||
isp116x->data_reg = (u16*)(ISP116X_HCD_DATA_BEE + ((val & 0x00ff)<<1));
|
||||
dumm = __raw_readw(isp116x->data_reg);
|
||||
isp116x->addr_reg = (u16*)((ISP116X_HCD_ADDR_BEE - 0x4000) + ((val & 0xff00)>>7));
|
||||
dumm = __raw_readw(isp116x->addr_reg);
|
||||
isp116x_delay(isp116x, UDELAY);
|
||||
if ((Super (SUP_INQUIRE)) && (p))
|
||||
SuperToUser( p );
|
||||
// ERR ( "data_reg: %x \n\r", isp116x->data_reg);
|
||||
// ERR ( "addr_reg: %x \n\r", isp116x->addr_reg);
|
||||
}
|
||||
|
||||
|
||||
static inline u16 isp116x_read_data16(struct isp116x *isp116x)
|
||||
{
|
||||
u16 val;
|
||||
u32 p = 0;
|
||||
if ( !(Super (SUP_INQUIRE)))
|
||||
p = SuperFromUser( );
|
||||
isp116x->data_reg = (u16*)(ISP116X_HCD_DATA_BEE + 0x8000);
|
||||
val = readw(isp116x->data_reg );
|
||||
isp116x_delay(isp116x, UDELAY);
|
||||
if ((Super (SUP_INQUIRE)) && (p))
|
||||
SuperToUser( p );
|
||||
return val;
|
||||
}
|
||||
|
||||
|
||||
static inline u16 isp116x_raw_read_data16(struct isp116x *isp116x)
|
||||
{
|
||||
u16 val;
|
||||
u32 p = 0;
|
||||
if ( !(Super (SUP_INQUIRE)))
|
||||
p = SuperFromUser( );
|
||||
isp116x->data_reg = (u16*)(ISP116X_HCD_DATA_BEE + 0x8000);
|
||||
val = __raw_readw(isp116x->data_reg );
|
||||
isp116x_delay(isp116x, UDELAY);
|
||||
if ((Super (SUP_INQUIRE)) && (p))
|
||||
SuperToUser( p );
|
||||
// ERR ( "data_reg: %x value: %x\n\r", isp116x->data_reg, val );
|
||||
return val;
|
||||
}
|
||||
|
||||
#if 0 /* We don't use it anymore */
|
||||
static inline void isp116x_write_data32(struct isp116x *isp116x, u32 val)
|
||||
{
|
||||
// p = SuperFromUser( );
|
||||
writew(val & 0xffff, isp116x->data_reg);
|
||||
isp116x_delay(isp116x, UDELAY);
|
||||
writew(val >> 16, isp116x->data_reg);
|
||||
isp116x_delay(isp116x, UDELAY);
|
||||
// SuperToUser( p );
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Added for NetUSBee, to write HC registers without swaping them
|
||||
* NetUSBee already swap them by hardware (i suppose.....)
|
||||
*/
|
||||
static inline void isp116x_raw_write_data32(struct isp116x *isp116x, u32 val)
|
||||
{
|
||||
u16 dumm;
|
||||
u32 p = 0;
|
||||
if ( !(Super (SUP_INQUIRE)))
|
||||
p = SuperFromUser( );
|
||||
isp116x->data_reg = (u16*)(ISP116X_HCD_DATA_BEE + ((val & 0x000000ff)<<1) );
|
||||
dumm = __raw_readw(isp116x->data_reg);
|
||||
isp116x->addr_reg = (u16*)((ISP116X_HCD_ADDR_BEE - 0x4000) + ((val & 0x0000ff00)>>7));
|
||||
dumm = __raw_readw(isp116x->addr_reg);
|
||||
isp116x_delay(isp116x, UDELAY);
|
||||
isp116x->data_reg = (u16*)(ISP116X_HCD_DATA_BEE + ((val & 0x00ff0000)>>15));
|
||||
dumm = __raw_readw(isp116x->data_reg);
|
||||
isp116x->addr_reg = (u16*)((ISP116X_HCD_ADDR_BEE - 0x4000) + ((val & 0xff000000)>>23) );
|
||||
dumm = __raw_readw(isp116x->addr_reg);
|
||||
isp116x_delay(isp116x, UDELAY);
|
||||
if ((Super (SUP_INQUIRE)) && (p))
|
||||
SuperToUser( p );
|
||||
}
|
||||
/***********************************************/
|
||||
|
||||
#if 0 /* We don't use it */
|
||||
static inline u32 isp116x_read_data32(struct isp116x *isp116x)
|
||||
{
|
||||
u32 val;
|
||||
p = SuperFromUser( );
|
||||
val = (u32) readw(isp116x->data_reg);
|
||||
isp116x_delay(isp116x, UDELAY);
|
||||
val |= ((u32) readw(isp116x->data_reg)) << 16;
|
||||
isp116x_delay(isp116x, UDELAY);
|
||||
SuperToUser( p );
|
||||
return val;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Added for NetUSBee, to read HC registers without swaping them
|
||||
* NetUSBee already swap them by hardware (i suppose.....)
|
||||
*/
|
||||
static inline u32 isp116x_raw_read_data32(struct isp116x *isp116x)
|
||||
{
|
||||
u32 val;
|
||||
u32 p = 0;
|
||||
if ( !(Super (SUP_INQUIRE)))
|
||||
p = SuperFromUser( );
|
||||
isp116x->data_reg = (u16*)(ISP116X_HCD_DATA_BEE + 0x8000);
|
||||
val = (u32) __raw_readw(isp116x->data_reg );
|
||||
isp116x_delay(isp116x, UDELAY);
|
||||
val |= ((u32) __raw_readw(isp116x->data_reg )) << 16;
|
||||
isp116x_delay(isp116x, UDELAY);
|
||||
if ((Super (SUP_INQUIRE)) && (p))
|
||||
SuperToUser( p );
|
||||
return val;
|
||||
}
|
||||
/*******************************************************************/
|
||||
|
||||
/* Let's keep register access functions out of line. Hint:
|
||||
we wait at least 150 ns at every access.
|
||||
*/
|
||||
|
||||
/* with NetUSBee use raw_read to avoid swaping bytes*/
|
||||
|
||||
static u16 isp116x_read_reg16(struct isp116x *isp116x, unsigned reg)
|
||||
{
|
||||
isp116x_write_addr(isp116x, reg);
|
||||
return isp116x_raw_read_data16(isp116x);
|
||||
}
|
||||
|
||||
static u32 isp116x_read_reg32(struct isp116x *isp116x, unsigned reg)
|
||||
{
|
||||
isp116x_write_addr(isp116x, reg);
|
||||
return isp116x_raw_read_data32(isp116x);
|
||||
}
|
||||
|
||||
static void isp116x_write_reg16(struct isp116x *isp116x, unsigned reg,
|
||||
unsigned val)
|
||||
{
|
||||
isp116x_write_addr(isp116x, reg | ISP116x_WRITE_OFFSET);
|
||||
isp116x_raw_write_data16(isp116x, (u16) (val & 0xffff));
|
||||
}
|
||||
|
||||
/* with NetUSBee used raw_write to avoid swaping bytes by software */
|
||||
static void isp116x_write_reg32(struct isp116x *isp116x, unsigned reg,
|
||||
unsigned val)
|
||||
{
|
||||
isp116x_write_addr(isp116x, reg | ISP116x_WRITE_OFFSET);
|
||||
isp116x_raw_write_data32(isp116x, (u32) val);
|
||||
}
|
||||
|
||||
/* --- USB HUB constants (not OHCI-specific; see hub.h) -------------------- */
|
||||
|
||||
/* destination of request */
|
||||
#define RH_INTERFACE 0x01
|
||||
#define RH_ENDPOINT 0x02
|
||||
#define RH_OTHER 0x03
|
||||
|
||||
#define RH_CLASS 0x20
|
||||
#define RH_VENDOR 0x40
|
||||
|
||||
/* Requests: bRequest << 8 | bmRequestType */
|
||||
#define RH_GET_STATUS 0x0080
|
||||
#define RH_CLEAR_FEATURE 0x0100
|
||||
#define RH_SET_FEATURE 0x0300
|
||||
#define RH_SET_ADDRESS 0x0500
|
||||
#define RH_GET_DESCRIPTOR 0x0680
|
||||
#define RH_SET_DESCRIPTOR 0x0700
|
||||
#define RH_GET_CONFIGURATION 0x0880
|
||||
#define RH_SET_CONFIGURATION 0x0900
|
||||
#define RH_GET_STATE 0x0280
|
||||
#define RH_GET_INTERFACE 0x0A80
|
||||
#define RH_SET_INTERFACE 0x0B00
|
||||
#define RH_SYNC_FRAME 0x0C80
|
||||
/* Our Vendor Specific Request */
|
||||
#define RH_SET_EP 0x2000
|
||||
|
||||
/* Hub port features */
|
||||
#define RH_PORT_CONNECTION 0x00
|
||||
#define RH_PORT_ENABLE 0x01
|
||||
#define RH_PORT_SUSPEND 0x02
|
||||
#define RH_PORT_OVER_CURRENT 0x03
|
||||
#define RH_PORT_RESET 0x04
|
||||
#define RH_PORT_POWER 0x08
|
||||
#define RH_PORT_LOW_SPEED 0x09
|
||||
|
||||
#define RH_C_PORT_CONNECTION 0x10
|
||||
#define RH_C_PORT_ENABLE 0x11
|
||||
#define RH_C_PORT_SUSPEND 0x12
|
||||
#define RH_C_PORT_OVER_CURRENT 0x13
|
||||
#define RH_C_PORT_RESET 0x14
|
||||
|
||||
/* Hub features */
|
||||
#define RH_C_HUB_LOCAL_POWER 0x00
|
||||
#define RH_C_HUB_OVER_CURRENT 0x01
|
||||
|
||||
#define RH_DEVICE_REMOTE_WAKEUP 0x00
|
||||
#define RH_ENDPOINT_STALL 0x01
|
||||
|
||||
#define RH_ACK 0x01
|
||||
#define RH_REQ_ERR -1
|
||||
#define RH_NACK 0x00
|
||||
|
||||
#endif /* _NETUSBEE_ISP116X_H */
|
||||
38
FireBee/trunk/usb/store/host/ohci-pci/ltoa.c
Normal file
38
FireBee/trunk/usb/store/host/ohci-pci/ltoa.c
Normal file
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* File: ltoa.c
|
||||
* Purpose: Function normally found in a standard C lib.
|
||||
*
|
||||
* Notes: This supports ASCII only!!!
|
||||
*/
|
||||
|
||||
void ltoa(char *buf, long n, unsigned long base)
|
||||
{
|
||||
unsigned long un;
|
||||
char *tmp, ch;
|
||||
un = n;
|
||||
if((base == 10) && (n < 0))
|
||||
{
|
||||
*buf++ = '-';
|
||||
un = -n;
|
||||
}
|
||||
tmp = buf;
|
||||
do
|
||||
{
|
||||
ch = un % base;
|
||||
un = un / base;
|
||||
if(ch <= 9)
|
||||
ch += '0';
|
||||
else
|
||||
ch += 'a' - 10;
|
||||
*tmp++ = ch;
|
||||
}
|
||||
while(un);
|
||||
*tmp = '\0';
|
||||
while(tmp > buf)
|
||||
{
|
||||
ch = *buf;
|
||||
*buf++ = *--tmp;
|
||||
*tmp = ch;
|
||||
}
|
||||
}
|
||||
|
||||
165
FireBee/trunk/usb/store/host/ohci-pci/mod_devicetable.h
Normal file
165
FireBee/trunk/usb/store/host/ohci-pci/mod_devicetable.h
Normal file
@@ -0,0 +1,165 @@
|
||||
#ifndef MOD_DEVICETABLE_H
|
||||
#define MOD_DEVICETABLE_H
|
||||
|
||||
#define PCI_ANY_ID (~0)
|
||||
|
||||
struct pci_device_id {
|
||||
unsigned long vendor, device; /* Vendor and device ID or PCI_ANY_ID*/
|
||||
unsigned long subvendor, subdevice; /* Subsystem ID's or PCI_ANY_ID */
|
||||
unsigned long class, class_mask; /* (class,subclass,prog-if) triplet */
|
||||
unsigned long driver_data; /* Data private to the driver */
|
||||
};
|
||||
|
||||
#define IEEE1394_MATCH_VENDOR_ID 0x0001
|
||||
#define IEEE1394_MATCH_MODEL_ID 0x0002
|
||||
#define IEEE1394_MATCH_SPECIFIER_ID 0x0004
|
||||
#define IEEE1394_MATCH_VERSION 0x0008
|
||||
|
||||
struct ieee1394_device_id {
|
||||
unsigned long match_flags;
|
||||
unsigned long vendor_id;
|
||||
unsigned long model_id;
|
||||
unsigned long specifier_id;
|
||||
unsigned long version;
|
||||
unsigned long driver_data;
|
||||
};
|
||||
|
||||
/*
|
||||
* Device table entry for "new style" table-driven USB drivers.
|
||||
* User mode code can read these tables to choose which modules to load.
|
||||
* Declare the table as a MODULE_DEVICE_TABLE.
|
||||
*
|
||||
* A probe() parameter will point to a matching entry from this table.
|
||||
* Use the driver_info field for each match to hold information tied
|
||||
* to that match: device quirks, etc.
|
||||
*
|
||||
* Terminate the driver's table with an all-zeroes entry.
|
||||
* Use the flag values to control which fields are compared.
|
||||
*/
|
||||
|
||||
/**
|
||||
* struct usb_device_id - identifies USB devices for probing and hotplugging
|
||||
* @match_flags: Bit mask controlling of the other fields are used to match
|
||||
* against new devices. Any field except for driver_info may be used,
|
||||
* although some only make sense in conjunction with other fields.
|
||||
* This is usually set by a USB_DEVICE_*() macro, which sets all
|
||||
* other fields in this structure except for driver_info.
|
||||
* @idVendor: USB vendor ID for a device; numbers are assigned
|
||||
* by the USB forum to its members.
|
||||
* @idProduct: Vendor-assigned product ID.
|
||||
* @bcdDevice_lo: Low end of range of vendor-assigned product version numbers.
|
||||
* This is also used to identify individual product versions, for
|
||||
* a range consisting of a single device.
|
||||
* @bcdDevice_hi: High end of version number range. The range of product
|
||||
* versions is inclusive.
|
||||
* @bDeviceClass: Class of device; numbers are assigned
|
||||
* by the USB forum. Products may choose to implement classes,
|
||||
* or be vendor-specific. Device classes specify behavior of all
|
||||
* the interfaces on a devices.
|
||||
* @bDeviceSubClass: Subclass of device; associated with bDeviceClass.
|
||||
* @bDeviceProtocol: Protocol of device; associated with bDeviceClass.
|
||||
* @bInterfaceClass: Class of interface; numbers are assigned
|
||||
* by the USB forum. Products may choose to implement classes,
|
||||
* or be vendor-specific. Interface classes specify behavior only
|
||||
* of a given interface; other interfaces may support other classes.
|
||||
* @bInterfaceSubClass: Subclass of interface; associated with bInterfaceClass.
|
||||
* @bInterfaceProtocol: Protocol of interface; associated with bInterfaceClass.
|
||||
* @driver_info: Holds information used by the driver. Usually it holds
|
||||
* a pointer to a descriptor understood by the driver, or perhaps
|
||||
* device flags.
|
||||
*
|
||||
* In most cases, drivers will create a table of device IDs by using
|
||||
* USB_DEVICE(), or similar macros designed for that purpose.
|
||||
* They will then export it to userspace using MODULE_DEVICE_TABLE(),
|
||||
* and provide it to the USB core through their usb_driver structure.
|
||||
*
|
||||
* See the usb_match_id() function for information about how matches are
|
||||
* performed. Briefly, you will normally use one of several macros to help
|
||||
* construct these entries. Each entry you provide will either identify
|
||||
* one or more specific products, or will identify a class of products
|
||||
* which have agreed to behave the same. You should put the more specific
|
||||
* matches towards the beginning of your table, so that driver_info can
|
||||
* record quirks of specific products.
|
||||
*/
|
||||
struct usb_device_id {
|
||||
/* which fields to match against? */
|
||||
unsigned short match_flags;
|
||||
|
||||
/* Used for product specific matches; range is inclusive */
|
||||
unsigned short idVendor;
|
||||
unsigned short idProduct;
|
||||
unsigned short bcdDevice_lo;
|
||||
unsigned short bcdDevice_hi;
|
||||
|
||||
/* Used for device class matches */
|
||||
unsigned char bDeviceClass;
|
||||
unsigned char bDeviceSubClass;
|
||||
unsigned char bDeviceProtocol;
|
||||
|
||||
/* Used for interface class matches */
|
||||
unsigned char bInterfaceClass;
|
||||
unsigned char bInterfaceSubClass;
|
||||
unsigned char bInterfaceProtocol;
|
||||
|
||||
/* not matched against */
|
||||
unsigned long driver_info;
|
||||
};
|
||||
|
||||
/* Some useful macros to use to create struct usb_device_id */
|
||||
#define USB_DEVICE_ID_MATCH_VENDOR 0x0001
|
||||
#define USB_DEVICE_ID_MATCH_PRODUCT 0x0002
|
||||
#define USB_DEVICE_ID_MATCH_DEV_LO 0x0004
|
||||
#define USB_DEVICE_ID_MATCH_DEV_HI 0x0008
|
||||
#define USB_DEVICE_ID_MATCH_DEV_CLASS 0x0010
|
||||
#define USB_DEVICE_ID_MATCH_DEV_SUBCLASS 0x0020
|
||||
#define USB_DEVICE_ID_MATCH_DEV_PROTOCOL 0x0040
|
||||
#define USB_DEVICE_ID_MATCH_INT_CLASS 0x0080
|
||||
#define USB_DEVICE_ID_MATCH_INT_SUBCLASS 0x0100
|
||||
#define USB_DEVICE_ID_MATCH_INT_PROTOCOL 0x0200
|
||||
|
||||
/* s390 CCW devices */
|
||||
struct ccw_device_id {
|
||||
unsigned short match_flags; /* which fields to match against */
|
||||
|
||||
unsigned short cu_type; /* control unit type */
|
||||
unsigned short dev_type; /* device type */
|
||||
unsigned char cu_model; /* control unit model */
|
||||
unsigned char dev_model; /* device model */
|
||||
|
||||
unsigned long driver_info;
|
||||
};
|
||||
|
||||
#define CCW_DEVICE_ID_MATCH_CU_TYPE 0x01
|
||||
#define CCW_DEVICE_ID_MATCH_CU_MODEL 0x02
|
||||
#define CCW_DEVICE_ID_MATCH_DEVICE_TYPE 0x04
|
||||
#define CCW_DEVICE_ID_MATCH_DEVICE_MODEL 0x08
|
||||
|
||||
|
||||
#define PNP_ID_LEN 8
|
||||
#define PNP_MAX_DEVICES 8
|
||||
|
||||
struct pnp_device_id {
|
||||
unsigned char id[PNP_ID_LEN];
|
||||
unsigned long driver_data;
|
||||
};
|
||||
|
||||
struct pnp_card_device_id {
|
||||
unsigned char id[PNP_ID_LEN];
|
||||
unsigned long driver_data;
|
||||
struct {
|
||||
unsigned char id[PNP_ID_LEN];
|
||||
} devs[PNP_MAX_DEVICES];
|
||||
};
|
||||
|
||||
|
||||
#define SERIO_ANY 0xff
|
||||
|
||||
struct serio_device_id {
|
||||
unsigned char type;
|
||||
unsigned char extra;
|
||||
unsigned char id;
|
||||
unsigned char proto;
|
||||
};
|
||||
|
||||
|
||||
#endif /* MOD_DEVICETABLE_H */
|
||||
1953
FireBee/trunk/usb/store/host/ohci-pci/ohci-hcd.c
Normal file
1953
FireBee/trunk/usb/store/host/ohci-pci/ohci-hcd.c
Normal file
File diff suppressed because it is too large
Load Diff
457
FireBee/trunk/usb/store/host/ohci-pci/ohci.h
Normal file
457
FireBee/trunk/usb/store/host/ohci-pci/ohci.h
Normal file
@@ -0,0 +1,457 @@
|
||||
/*
|
||||
* URB OHCI HCD (Host Controller Driver) for USB.
|
||||
*
|
||||
* (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at>
|
||||
* (C) Copyright 2000-2001 David Brownell <dbrownell@users.sourceforge.net>
|
||||
*
|
||||
* usb-ohci.h
|
||||
*/
|
||||
|
||||
static int cc_to_error[16] = {
|
||||
|
||||
/* mapping of the OHCI CC status to error codes */
|
||||
/* No Error */ 0,
|
||||
/* CRC Error */ USB_ST_CRC_ERR,
|
||||
/* Bit Stuff */ USB_ST_BIT_ERR,
|
||||
/* Data Togg */ USB_ST_CRC_ERR,
|
||||
/* Stall */ USB_ST_STALLED,
|
||||
/* DevNotResp */ -1,
|
||||
/* PIDCheck */ USB_ST_BIT_ERR,
|
||||
/* UnExpPID */ USB_ST_BIT_ERR,
|
||||
/* DataOver */ USB_ST_BUF_ERR,
|
||||
/* DataUnder */ USB_ST_BUF_ERR,
|
||||
/* reservd */ -1,
|
||||
/* reservd */ -1,
|
||||
/* BufferOver */ USB_ST_BUF_ERR,
|
||||
/* BuffUnder */ USB_ST_BUF_ERR,
|
||||
/* Not Access */ -1,
|
||||
/* Not Access */ -1
|
||||
};
|
||||
|
||||
static const char *cc_to_string[16] = {
|
||||
"No Error",
|
||||
"CRC: Last data packet from endpoint contained a CRC error.",
|
||||
"BITSTUFFING: Last data packet from endpoint contained a bit stuffing violation",
|
||||
"DATATOGGLEMISMATCH: Last packet from endpoint had data toggle PID that did not match the expected value.",
|
||||
"STALL: TD was moved to the Done Queue because the endpoint returned a STALL PID",
|
||||
"DEVICENOTRESPONDING: Device did not respond to token (IN) or did not provide a handshake (OUT)",
|
||||
"PIDCHECKFAILURE: Check bits on PID from endpoint failed on data PID (IN) or handshake (OUT)",
|
||||
"UNEXPECTEDPID: Receive PID was not valid when encountered or PID value is not defined.",
|
||||
"DATAOVERRUN: The amount of data returned by the endpoint exceeded either the size of the maximum data packet allowed from the endpoint (found in MaximumPacketSize field of ED) or the remaining buffer size.",
|
||||
"DATAUNDERRUN: The endpoint returned less than MaximumPacketSize and that amount was not sufficient to fill the specified buffer",
|
||||
"reserved1",
|
||||
"reserved2",
|
||||
"BUFFEROVERRUN: During an IN, HC received data from endpoint faster than it could be written to system memory",
|
||||
"BUFFERUNDERRUN: During an OUT, HC could not retrieve data from system memory fast enough to keep up with data USB data rate.",
|
||||
"NOT ACCESSED: This code is set by software before the TD is placed on a list to be processed by the HC.(1)",
|
||||
"NOT ACCESSED: This code is set by software before the TD is placed on a list to be processed by the HC.(2)",
|
||||
};
|
||||
|
||||
/* ED States */
|
||||
|
||||
#define ED_NEW 0x00
|
||||
#define ED_UNLINK 0x01
|
||||
#define ED_OPER 0x02
|
||||
#define ED_DEL 0x04
|
||||
#define ED_URB_DEL 0x08
|
||||
|
||||
/* usb_ohci_ed */
|
||||
struct ed {
|
||||
__u32 hwINFO;
|
||||
__u32 hwTailP;
|
||||
__u32 hwHeadP;
|
||||
__u32 hwNextED;
|
||||
|
||||
struct ed *ed_prev;
|
||||
__u8 int_period;
|
||||
__u8 int_branch;
|
||||
__u8 int_load;
|
||||
__u8 int_interval;
|
||||
__u8 state;
|
||||
__u8 type;
|
||||
__u16 last_iso;
|
||||
struct ed *ed_rm_list;
|
||||
|
||||
struct usb_device *usb_dev;
|
||||
void *purb;
|
||||
__u32 unused[2];
|
||||
} __attribute__((aligned(16)));
|
||||
typedef struct ed ed_t;
|
||||
|
||||
|
||||
/* TD info field */
|
||||
#define TD_CC 0xf0000000
|
||||
#define TD_CC_GET(td_p) ((td_p >>28) & 0x0f)
|
||||
#define TD_CC_SET(td_p, cc) (td_p) = ((td_p) & 0x0fffffff) | (((cc) & 0x0f) << 28)
|
||||
#define TD_EC 0x0C000000
|
||||
#define TD_T 0x03000000
|
||||
#define TD_T_DATA0 0x02000000
|
||||
#define TD_T_DATA1 0x03000000
|
||||
#define TD_T_TOGGLE 0x00000000
|
||||
#define TD_R 0x00040000
|
||||
#define TD_DI 0x00E00000
|
||||
#define TD_DI_SET(X) (((X) & 0x07)<< 21)
|
||||
#define TD_DP 0x00180000
|
||||
#define TD_DP_SETUP 0x00000000
|
||||
#define TD_DP_IN 0x00100000
|
||||
#define TD_DP_OUT 0x00080000
|
||||
|
||||
#define TD_ISO 0x00010000
|
||||
#define TD_DEL 0x00020000
|
||||
|
||||
/* CC Codes */
|
||||
#define TD_CC_NOERROR 0x00
|
||||
#define TD_CC_CRC 0x01
|
||||
#define TD_CC_BITSTUFFING 0x02
|
||||
#define TD_CC_DATATOGGLEM 0x03
|
||||
#define TD_CC_STALL 0x04
|
||||
#define TD_DEVNOTRESP 0x05
|
||||
#define TD_PIDCHECKFAIL 0x06
|
||||
#define TD_UNEXPECTEDPID 0x07
|
||||
#define TD_DATAOVERRUN 0x08
|
||||
#define TD_DATAUNDERRUN 0x09
|
||||
#define TD_BUFFEROVERRUN 0x0C
|
||||
#define TD_BUFFERUNDERRUN 0x0D
|
||||
#define TD_NOTACCESSED 0x0F
|
||||
|
||||
|
||||
#define MAXPSW 1
|
||||
|
||||
struct td {
|
||||
__u32 hwINFO;
|
||||
__u32 hwCBP; /* Current Buffer Pointer */
|
||||
__u32 hwNextTD; /* Next TD Pointer */
|
||||
__u32 hwBE; /* Memory Buffer End Pointer */
|
||||
|
||||
__u16 hwPSW[MAXPSW];
|
||||
__u8 unused;
|
||||
__u8 index;
|
||||
struct ed *ed;
|
||||
struct td *next_dl_td;
|
||||
struct usb_device *usb_dev;
|
||||
int transfer_len;
|
||||
__u32 data;
|
||||
|
||||
__u32 unused2[2];
|
||||
} __attribute__((aligned(32)));
|
||||
typedef struct td td_t;
|
||||
|
||||
#define OHCI_ED_SKIP (1 << 14)
|
||||
|
||||
/*
|
||||
* The HCCA (Host Controller Communications Area) is a 256 byte
|
||||
* structure defined in the OHCI spec. that the host controller is
|
||||
* told the base address of. It must be 256-byte aligned.
|
||||
*/
|
||||
|
||||
#define NUM_INTS 32 /* part of the OHCI standard */
|
||||
struct ohci_hcca {
|
||||
__u32 int_table[NUM_INTS]; /* Interrupt ED table */
|
||||
#if defined(CONFIG_MPC5200)
|
||||
__u16 pad1; /* set to 0 on each frame_no change */
|
||||
__u16 frame_no; /* current frame number */
|
||||
#else
|
||||
__u16 frame_no; /* current frame number */
|
||||
__u16 pad1; /* set to 0 on each frame_no change */
|
||||
#endif
|
||||
__u32 done_head; /* info returned for an interrupt */
|
||||
u8 reserved_for_hc[116];
|
||||
} __attribute__((aligned(256)));
|
||||
|
||||
|
||||
/*
|
||||
* Maximum number of root hub ports.
|
||||
*/
|
||||
#ifndef CONFIG_SYS_USB_OHCI_MAX_ROOT_PORTS
|
||||
# error "CONFIG_SYS_USB_OHCI_MAX_ROOT_PORTS undefined!"
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This is the structure of the OHCI controller's memory mapped I/O
|
||||
* region. This is Memory Mapped I/O. You must use the readl() and
|
||||
* writel() macros defined in asm/io.h to access these!!
|
||||
*/
|
||||
struct ohci_regs {
|
||||
/* control and status registers */
|
||||
__u32 revision;
|
||||
__u32 control;
|
||||
__u32 cmdstatus;
|
||||
__u32 intrstatus;
|
||||
__u32 intrenable;
|
||||
__u32 intrdisable;
|
||||
/* memory pointers */
|
||||
__u32 hcca;
|
||||
__u32 ed_periodcurrent;
|
||||
__u32 ed_controlhead;
|
||||
__u32 ed_controlcurrent;
|
||||
__u32 ed_bulkhead;
|
||||
__u32 ed_bulkcurrent;
|
||||
__u32 donehead;
|
||||
/* frame counters */
|
||||
__u32 fminterval;
|
||||
__u32 fmremaining;
|
||||
__u32 fmnumber;
|
||||
__u32 periodicstart;
|
||||
__u32 lsthresh;
|
||||
/* Root hub ports */
|
||||
struct ohci_roothub_regs {
|
||||
__u32 a;
|
||||
__u32 b;
|
||||
__u32 status;
|
||||
__u32 portstatus[CONFIG_SYS_USB_OHCI_MAX_ROOT_PORTS];
|
||||
} roothub;
|
||||
} __attribute__((aligned(32)));
|
||||
|
||||
/* Some EHCI controls */
|
||||
#define EHCI_USBCMD_OFF 0x20
|
||||
#define EHCI_USBCMD_HCRESET (1 << 1)
|
||||
|
||||
/* OHCI CONTROL AND STATUS REGISTER MASKS */
|
||||
|
||||
/*
|
||||
* HcControl (control) register masks
|
||||
*/
|
||||
#define OHCI_CTRL_CBSR (3 << 0) /* control/bulk service ratio */
|
||||
#define OHCI_CTRL_PLE (1 << 2) /* periodic list enable */
|
||||
#define OHCI_CTRL_IE (1 << 3) /* isochronous enable */
|
||||
#define OHCI_CTRL_CLE (1 << 4) /* control list enable */
|
||||
#define OHCI_CTRL_BLE (1 << 5) /* bulk list enable */
|
||||
#define OHCI_CTRL_HCFS (3 << 6) /* host controller functional state */
|
||||
#define OHCI_CTRL_IR (1 << 8) /* interrupt routing */
|
||||
#define OHCI_CTRL_RWC (1 << 9) /* remote wakeup connected */
|
||||
#define OHCI_CTRL_RWE (1 << 10) /* remote wakeup enable */
|
||||
|
||||
/* pre-shifted values for HCFS */
|
||||
# define OHCI_USB_RESET (0 << 6)
|
||||
# define OHCI_USB_RESUME (1 << 6)
|
||||
# define OHCI_USB_OPER (2 << 6)
|
||||
# define OHCI_USB_SUSPEND (3 << 6)
|
||||
|
||||
/*
|
||||
* HcCommandStatus (cmdstatus) register masks
|
||||
*/
|
||||
#define OHCI_HCR (1 << 0) /* host controller reset */
|
||||
#define OHCI_CLF (1 << 1) /* control list filled */
|
||||
#define OHCI_BLF (1 << 2) /* bulk list filled */
|
||||
#define OHCI_OCR (1 << 3) /* ownership change request */
|
||||
#define OHCI_SOC (3 << 16) /* scheduling overrun count */
|
||||
|
||||
/*
|
||||
* masks used with interrupt registers:
|
||||
* HcInterruptStatus (intrstatus)
|
||||
* HcInterruptEnable (intrenable)
|
||||
* HcInterruptDisable (intrdisable)
|
||||
*/
|
||||
#define OHCI_INTR_SO (1 << 0) /* scheduling overrun */
|
||||
#define OHCI_INTR_WDH (1 << 1) /* writeback of done_head */
|
||||
#define OHCI_INTR_SF (1 << 2) /* start frame */
|
||||
#define OHCI_INTR_RD (1 << 3) /* resume detect */
|
||||
#define OHCI_INTR_UE (1 << 4) /* unrecoverable error */
|
||||
#define OHCI_INTR_FNO (1 << 5) /* frame number overflow */
|
||||
#define OHCI_INTR_RHSC (1 << 6) /* root hub status change */
|
||||
#define OHCI_INTR_OC (1 << 30) /* ownership change */
|
||||
#define OHCI_INTR_MIE (1 << 31) /* master interrupt enable */
|
||||
|
||||
|
||||
/* Virtual Root HUB */
|
||||
struct virt_root_hub {
|
||||
int devnum; /* Address of Root Hub endpoint */
|
||||
void *dev; /* was urb */
|
||||
void *int_addr;
|
||||
int send;
|
||||
int interval;
|
||||
};
|
||||
|
||||
/* USB HUB CONSTANTS (not OHCI-specific; see hub.h) */
|
||||
|
||||
/* destination of request */
|
||||
#define RH_INTERFACE 0x01
|
||||
#define RH_ENDPOINT 0x02
|
||||
#define RH_OTHER 0x03
|
||||
|
||||
#define RH_CLASS 0x20
|
||||
#define RH_VENDOR 0x40
|
||||
|
||||
/* Requests: bRequest << 8 | bmRequestType */
|
||||
#define RH_GET_STATUS 0x0080
|
||||
#define RH_CLEAR_FEATURE 0x0100
|
||||
#define RH_SET_FEATURE 0x0300
|
||||
#define RH_SET_ADDRESS 0x0500
|
||||
#define RH_GET_DESCRIPTOR 0x0680
|
||||
#define RH_SET_DESCRIPTOR 0x0700
|
||||
#define RH_GET_CONFIGURATION 0x0880
|
||||
#define RH_SET_CONFIGURATION 0x0900
|
||||
#define RH_GET_STATE 0x0280
|
||||
#define RH_GET_INTERFACE 0x0A80
|
||||
#define RH_SET_INTERFACE 0x0B00
|
||||
#define RH_SYNC_FRAME 0x0C80
|
||||
/* Our Vendor Specific Request */
|
||||
#define RH_SET_EP 0x2000
|
||||
|
||||
|
||||
/* Hub port features */
|
||||
#define RH_PORT_CONNECTION 0x00
|
||||
#define RH_PORT_ENABLE 0x01
|
||||
#define RH_PORT_SUSPEND 0x02
|
||||
#define RH_PORT_OVER_CURRENT 0x03
|
||||
#define RH_PORT_RESET 0x04
|
||||
#define RH_PORT_POWER 0x08
|
||||
#define RH_PORT_LOW_SPEED 0x09
|
||||
|
||||
#define RH_C_PORT_CONNECTION 0x10
|
||||
#define RH_C_PORT_ENABLE 0x11
|
||||
#define RH_C_PORT_SUSPEND 0x12
|
||||
#define RH_C_PORT_OVER_CURRENT 0x13
|
||||
#define RH_C_PORT_RESET 0x14
|
||||
|
||||
/* Hub features */
|
||||
#define RH_C_HUB_LOCAL_POWER 0x00
|
||||
#define RH_C_HUB_OVER_CURRENT 0x01
|
||||
|
||||
#define RH_DEVICE_REMOTE_WAKEUP 0x00
|
||||
#define RH_ENDPOINT_STALL 0x01
|
||||
|
||||
#define RH_ACK 0x01
|
||||
#define RH_REQ_ERR -1
|
||||
#define RH_NACK 0x00
|
||||
|
||||
|
||||
/* OHCI ROOT HUB REGISTER MASKS */
|
||||
|
||||
/* roothub.portstatus [i] bits */
|
||||
#define RH_PS_CCS 0x00000001 /* current connect status */
|
||||
#define RH_PS_PES 0x00000002 /* port enable status*/
|
||||
#define RH_PS_PSS 0x00000004 /* port suspend status */
|
||||
#define RH_PS_POCI 0x00000008 /* port over current indicator */
|
||||
#define RH_PS_PRS 0x00000010 /* port reset status */
|
||||
#define RH_PS_PPS 0x00000100 /* port power status */
|
||||
#define RH_PS_LSDA 0x00000200 /* low speed device attached */
|
||||
#define RH_PS_CSC 0x00010000 /* connect status change */
|
||||
#define RH_PS_PESC 0x00020000 /* port enable status change */
|
||||
#define RH_PS_PSSC 0x00040000 /* port suspend status change */
|
||||
#define RH_PS_OCIC 0x00080000 /* over current indicator change */
|
||||
#define RH_PS_PRSC 0x00100000 /* port reset status change */
|
||||
|
||||
/* roothub.status bits */
|
||||
#define RH_HS_LPS 0x00000001 /* local power status */
|
||||
#define RH_HS_OCI 0x00000002 /* over current indicator */
|
||||
#define RH_HS_DRWE 0x00008000 /* device remote wakeup enable */
|
||||
#define RH_HS_LPSC 0x00010000 /* local power status change */
|
||||
#define RH_HS_OCIC 0x00020000 /* over current indicator change */
|
||||
#define RH_HS_CRWE 0x80000000 /* clear remote wakeup enable */
|
||||
|
||||
/* roothub.b masks */
|
||||
#define RH_B_DR 0x0000ffff /* device removable flags */
|
||||
#define RH_B_PPCM 0xffff0000 /* port power control mask */
|
||||
|
||||
/* roothub.a masks */
|
||||
#define RH_A_NDP (0xff << 0) /* number of downstream ports */
|
||||
#define RH_A_PSM (1 << 8) /* power switching mode */
|
||||
#define RH_A_NPS (1 << 9) /* no power switching */
|
||||
#define RH_A_DT (1 << 10) /* device type (mbz) */
|
||||
#define RH_A_OCPM (1 << 11) /* over current protection mode */
|
||||
#define RH_A_NOCP (1 << 12) /* no over current protection */
|
||||
#define RH_A_POTPGT (0xff << 24) /* power on to power good time */
|
||||
|
||||
/* urb */
|
||||
#define N_URB_TD 48
|
||||
typedef struct
|
||||
{
|
||||
ed_t *ed;
|
||||
__u16 length; /* number of tds associated with this request */
|
||||
__u16 td_cnt; /* number of tds already serviced */
|
||||
struct usb_device *dev;
|
||||
int state;
|
||||
unsigned long pipe;
|
||||
void *transfer_buffer;
|
||||
int transfer_buffer_length;
|
||||
int interval;
|
||||
int actual_length;
|
||||
int finished;
|
||||
td_t *td[N_URB_TD]; /* list pointer to all corresponding TDs associated with this request */
|
||||
} urb_priv_t;
|
||||
#define URB_DEL 1
|
||||
|
||||
#define NUM_EDS 8 /* num of preallocated endpoint descriptors */
|
||||
|
||||
struct ohci_device {
|
||||
ed_t ed[NUM_EDS];
|
||||
int ed_cnt;
|
||||
};
|
||||
|
||||
/*
|
||||
* This is the full ohci controller description
|
||||
*
|
||||
* Note how the "proper" USB information is just
|
||||
* a subset of what the full implementation needs. (Linus)
|
||||
*/
|
||||
|
||||
typedef struct ohci {
|
||||
long handle; /* PCI BIOS */
|
||||
int big_endian; /* PCI BIOS */
|
||||
struct ohci_hcca *hcca_unaligned;
|
||||
struct ohci_hcca *hcca; /* hcca */
|
||||
td_t *td_unaligned;
|
||||
struct ohci_device *ohci_dev_unaligned;
|
||||
/* this allocates EDs for all possible endpoints */
|
||||
struct ohci_device *ohci_dev;
|
||||
/*dma_addr_t hcca_dma;*/
|
||||
|
||||
int irq;
|
||||
int disabled; /* e.g. got a UE, we're hung */
|
||||
int sleeping;
|
||||
unsigned long flags; /* for HC bugs */
|
||||
|
||||
unsigned long dma_offset;
|
||||
struct ohci_regs *regs; /* OHCI controller's memory */
|
||||
|
||||
int ohci_int_load[32]; /* load of the 32 Interrupt Chains (for load balancing)*/
|
||||
ed_t *ed_rm_list[2]; /* lists of all endpoints to be removed */
|
||||
ed_t *ed_bulktail; /* last endpoint of bulk list */
|
||||
ed_t *ed_controltail; /* last endpoint of control list */
|
||||
int intrstatus;
|
||||
__u32 hc_control; /* copy of the hc control reg */
|
||||
struct usb_device *dev[32];
|
||||
struct virt_root_hub rh;
|
||||
|
||||
const char *slot_name;
|
||||
} ohci_t;
|
||||
|
||||
/* hcd */
|
||||
/* endpoint */
|
||||
static int ep_link(ohci_t * ohci, ed_t * ed);
|
||||
static int ep_unlink(ohci_t * ohci, ed_t * ed);
|
||||
static ed_t * ep_add_ed(struct usb_device * usb_dev, unsigned long pipe,
|
||||
int interval, int load);
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
/* we need more TDs than EDs */
|
||||
#define NUM_TD 64
|
||||
|
||||
/* pointers to aligned storage */
|
||||
td_t *ptd;
|
||||
|
||||
/* TDs ... */
|
||||
static inline struct td *td_alloc(struct usb_device *usb_dev)
|
||||
{
|
||||
int i;
|
||||
struct td *td;
|
||||
td = NULL;
|
||||
for(i = 0; i < NUM_TD; i++)
|
||||
{
|
||||
if(ptd[i].usb_dev == NULL)
|
||||
{
|
||||
td = &ptd[i];
|
||||
td->usb_dev = usb_dev;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return td;
|
||||
}
|
||||
|
||||
static inline void ed_free(struct ed *ed)
|
||||
{
|
||||
ed->usb_dev = NULL;
|
||||
}
|
||||
|
||||
2613
FireBee/trunk/usb/store/host/ohci-pci/pci_ids.h
Normal file
2613
FireBee/trunk/usb/store/host/ohci-pci/pci_ids.h
Normal file
File diff suppressed because it is too large
Load Diff
342
FireBee/trunk/usb/store/host/ohci-pci/pcixbios.h
Normal file
342
FireBee/trunk/usb/store/host/ohci-pci/pcixbios.h
Normal file
@@ -0,0 +1,342 @@
|
||||
/* TOS 4.04 Xbios PCI for the CT60 board
|
||||
* Didier Mequignon 2005, e-mail: aniplay@wanadoo.fr
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _OHCI_PCI_PCIXBIOS_H
|
||||
#define _OHCI_PCI_PCIXBIOS_H
|
||||
|
||||
#define PCIIDR 0x00 /* PCI Configuration ID Register */
|
||||
#define PCICSR 0x04 /* PCI Command/Status Register */
|
||||
#define PCICR 0x04 /* PCI Command Register */
|
||||
#define PCISR 0x06 /* PCI Status Register */
|
||||
#define PCIREV 0x08 /* PCI Revision ID Register */
|
||||
#define PCICCR 0x09 /* PCI Class Code Register */
|
||||
#define PCICLSR 0x0C /* PCI Cache Line Size Register */
|
||||
#define PCILTR 0x0D /* PCI Latency Timer Register */
|
||||
#define PCIHTR 0x0E /* PCI Header Type Register */
|
||||
#define PCIBISTR 0x0F /* PCI Build-In Self Test Register */
|
||||
#define PCIBAR0 0x10 /* PCI Base Address Register for Memory
|
||||
Accesses to Local, Runtime, and DMA */
|
||||
#define PCIBAR1 0x14 /* PCI Base Address Register for I/O
|
||||
Accesses to Local, Runtime, and DMA */
|
||||
#define PCIBAR2 0x18 /* PCI Base Address Register for Memory
|
||||
Accesses to Local Address Space 0 */
|
||||
#define PCIBAR3 0x1C /* PCI Base Address Register for Memory
|
||||
Accesses to Local Address Space 1 */
|
||||
#define PCIBAR4 0x20 /* PCI Base Address Register, reserved */
|
||||
#define PCIBAR5 0x24 /* PCI Base Address Register, reserved */
|
||||
#define PCICIS 0x28 /* PCI Cardbus CIS Pointer, not support*/
|
||||
#define PCISVID 0x2C /* PCI Subsystem Vendor ID */
|
||||
#define PCISID 0x2E /* PCI Subsystem ID */
|
||||
#define PCIERBAR 0x30 /* PCI Expansion ROM Base Register */
|
||||
#define CAP_PTR 0x34 /* New Capability Pointer */
|
||||
#define PCIILR 0x3C /* PCI Interrupt Line Register */
|
||||
#define PCIIPR 0x3D /* PCI Interrupt Pin Register */
|
||||
#define PCIMGR 0x3E /* PCI Min_Gnt Register */
|
||||
#define PCIMLR 0x3F /* PCI Max_Lat Register */
|
||||
#define PMCAPID 0x40 /* Power Management Capability ID */
|
||||
#define PMNEXT 0x41 /* Power Management Next Capability
|
||||
Pointer */
|
||||
#define PMC 0x42 /* Power Management Capabilities */
|
||||
#define PMCSR 0x44 /* Power Management Control/Status */
|
||||
#define PMCSR_BSE 0x46 /* PMCSR Bridge Support Extensions */
|
||||
#define PMDATA 0x47 /* Power Management Data */
|
||||
#define HS_CNTL 0x48 /* Hot Swap Control */
|
||||
#define HS_NEXT 0x49 /* Hot Swap Next Capability Pointer */
|
||||
#define HS_CSR 0x4A /* Hot Swap Control/Status */
|
||||
#define PVPDCNTL 0x4C /* PCI Vital Product Data Control */
|
||||
#define PVPD_NEXT 0x4D /* PCI Vital Product Data Next
|
||||
Capability Pointer */
|
||||
#define PVPDAD 0x4E /* PCI Vital Product Data Address */
|
||||
#define PVPDATA 0x50 /* PCI VPD Data */
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned long *subcookie;
|
||||
unsigned long version;
|
||||
long routine[45];
|
||||
} PCI_COOKIE;
|
||||
|
||||
typedef struct /* structure of resource descriptor */
|
||||
{
|
||||
unsigned short next; /* length of the following structure */
|
||||
unsigned short flags; /* type of resource and misc. flags */
|
||||
unsigned long start; /* start-address of resource */
|
||||
unsigned long length; /* length of resource */
|
||||
unsigned long offset; /* offset PCI to phys. CPU Address */
|
||||
unsigned long dmaoffset; /* offset for DMA-transfers */
|
||||
} PCI_RSC_DESC;
|
||||
|
||||
typedef struct /* structure of address conversion */
|
||||
{
|
||||
unsigned long adr; /* calculated address (CPU<->PCI) */
|
||||
unsigned long len; /* length of memory range */
|
||||
} PCI_CONV_ADR;
|
||||
|
||||
/******************************************************************************/
|
||||
/* PCI-BIOS Error Codes */
|
||||
/******************************************************************************/
|
||||
#define PCI_SUCCESSFUL 0 /* everything's fine */
|
||||
#define PCI_FUNC_NOT_SUPPORTED -2 /* function not supported */
|
||||
#define PCI_BAD_VENDOR_ID -3 /* wrong Vendor ID */
|
||||
#define PCI_DEVICE_NOT_FOUND -4 /* PCI-Device not found */
|
||||
#define PCI_BAD_REGISTER_NUMBER -5 /* wrong register number */
|
||||
#define PCI_SET_FAILED -6 /* reserved for later use */
|
||||
#define PCI_BUFFER_TOO_SMALL -7 /* reserved for later use */
|
||||
#define PCI_GENERAL_ERROR -8 /* general BIOS error code */
|
||||
#define PCI_BAD_HANDLE -9 /* wrong/unknown PCI-handle */
|
||||
|
||||
/******************************************************************************/
|
||||
/* Flags used in Resource-Descriptor */
|
||||
/******************************************************************************/
|
||||
#define FLG_IO 0x4000 /* Ressource in IO range */
|
||||
#define FLG_LAST 0x8000 /* last ressource */
|
||||
#define FLG_8BIT 0x0100 /* 8 bit accesses allowed */
|
||||
#define FLG_16BIT 0x0200 /* 16 bit accesses allowed */
|
||||
#define FLG_32BIT 0x0400 /* 32 bit accesses allowed */
|
||||
#define FLG_ENDMASK 0x000F /* mask for byte ordering */
|
||||
|
||||
/******************************************************************************/
|
||||
/* Values used in FLG_ENDMASK for Byte Ordering */
|
||||
/******************************************************************************/
|
||||
#define ORD_MOTOROLA 0 /* Motorola (big endian) */
|
||||
#define ORD_INTEL_AS 1 /* Intel (little endian), addr.swapped */
|
||||
#define ORD_INTEL_LS 2 /* Intel (little endian), lane swapped */
|
||||
#define ORD_UNKNOWN 15 /* unknown (BIOS-calls allowed only) */
|
||||
|
||||
/******************************************************************************/
|
||||
/* Status Info used in Device-Descriptor */
|
||||
/******************************************************************************/
|
||||
#define DEVICE_FREE 0 /* Device is not used */
|
||||
#define DEVICE_USED 1 /* Device is used by another driver */
|
||||
#define DEVICE_CALLBACK 2 /* used, but driver can be cancelled */
|
||||
#define DEVICE_AVAILABLE 3 /* used, not available */
|
||||
#define NO_DEVICE -1 /* no device detected */
|
||||
|
||||
/******************************************************************************/
|
||||
/* Callback-Routine */
|
||||
/******************************************************************************/
|
||||
#define GET_DRIVER_ID 0 /* CB-Routine 0: Get Driver ID */
|
||||
#define REMOVE_DRIVER 1 /* CB-Routine 1: Remove Driver */
|
||||
|
||||
/******************************************************************************/
|
||||
/* Functions */
|
||||
/******************************************************************************/
|
||||
//#ifndef OSBIND_CLOBBER_LIST
|
||||
//#define OSBIND_CLOBBER_LIST
|
||||
//#endif
|
||||
|
||||
#ifndef trap_14_wlw
|
||||
#define trap_14_wlw(n, a, b) \
|
||||
__extension__ \
|
||||
({ \
|
||||
register long retvalue __asm__("d0"); \
|
||||
long _a = (long) (a); \
|
||||
short _b = (short) (b); \
|
||||
\
|
||||
__asm__ volatile ( \
|
||||
"movw %3,sp@-\n\t" \
|
||||
"movl %2,sp@-\n\t" \
|
||||
"movw %1,sp@-\n\t" \
|
||||
"trap #14\n\t" \
|
||||
"lea sp@(8),sp" \
|
||||
: "=r"(retvalue) \
|
||||
: "g"(n), "r"(_a), "r"(_b) \
|
||||
); \
|
||||
retvalue; \
|
||||
})
|
||||
#endif
|
||||
#ifndef trap_14_wll
|
||||
#define trap_14_wll(n, a, b) \
|
||||
__extension__ \
|
||||
({ \
|
||||
register long retvalue __asm__("d0"); \
|
||||
long _a = (long) (a); \
|
||||
long _b = (long) (b); \
|
||||
\
|
||||
__asm__ volatile ( \
|
||||
"movl %3,sp@-\n\t" \
|
||||
"movl %2,sp@-\n\t" \
|
||||
"movw %1,sp@-\n\t" \
|
||||
"trap #14\n\t" \
|
||||
"lea sp@(10),sp" \
|
||||
: "=r"(retvalue) \
|
||||
: "g"(n), "r"(_a), "r"(_b) \
|
||||
); \
|
||||
retvalue; \
|
||||
})
|
||||
#endif
|
||||
#ifndef trap_14_wlww
|
||||
#define trap_14_wlww(n, a, b, c) \
|
||||
__extension__ \
|
||||
({ \
|
||||
register long retvalue __asm__("d0"); \
|
||||
long _a = (long) (a); \
|
||||
short _b = (short) (b); \
|
||||
short _c = (short) (c); \
|
||||
\
|
||||
__asm__ volatile ( \
|
||||
"movl %4,sp@-\n\t" \
|
||||
"movw %3,sp@-\n\t" \
|
||||
"movw %2,sp@-\n\t" \
|
||||
"movw %1,sp@-\n\t" \
|
||||
"trap #14\n\t" \
|
||||
"lea sp@(10),sp" \
|
||||
: "=r"(retvalue) \
|
||||
: "g"(n), "r"(_a), "r"(_b), "r"(_c) \
|
||||
); \
|
||||
retvalue; \
|
||||
})
|
||||
#endif
|
||||
#ifndef trap_14_wlwl
|
||||
#define trap_14_wlwl(n, a, b, c) \
|
||||
__extension__ \
|
||||
({ \
|
||||
register long retvalue __asm__("d0"); \
|
||||
long _a = (long) (a); \
|
||||
short _b = (short) (b); \
|
||||
long _c = (long) (c); \
|
||||
\
|
||||
__asm__ volatile ( \
|
||||
"movl %4,sp@-\n\t" \
|
||||
"movw %3,sp@-\n\t" \
|
||||
"movl %2,sp@-\n\t" \
|
||||
"movw %1,sp@-\n\t" \
|
||||
"trap #14\n\t" \
|
||||
"lea sp@(12),sp" \
|
||||
: "=r"(retvalue) \
|
||||
: "g"(n), "r"(_a), "r"(_b), "r"(_c) \
|
||||
); \
|
||||
retvalue; \
|
||||
})
|
||||
#endif
|
||||
#ifndef trap_14_wlll
|
||||
#define trap_14_wlll(n, a, b, c) \
|
||||
__extension__ \
|
||||
({ \
|
||||
register long retvalue __asm__("d0"); \
|
||||
long _a = (long) (a); \
|
||||
long _b = (long) (b); \
|
||||
long _c = (long) (c); \
|
||||
\
|
||||
__asm__ volatile ( \
|
||||
"movl %4,sp@-\n\t" \
|
||||
"movl %3,sp@-\n\t" \
|
||||
"movl %2,sp@-\n\t" \
|
||||
"movw %1,sp@-\n\t" \
|
||||
"trap #14\n\t" \
|
||||
"lea sp@(14),sp" \
|
||||
: "=r"(retvalue) \
|
||||
: "g"(n), "r"(_a), "r"(_b), "r"(_c) \
|
||||
); \
|
||||
retvalue; \
|
||||
})
|
||||
#endif
|
||||
|
||||
#define find_pci_device(id,index) (long)trap_14_wlw((short)(300),(unsigned long)(id),(unsigned short)(index))
|
||||
#define find_pci_classcode(classcode,index) (long)trap_14_wlw((short)(301),(unsigned long)(classcode),(unsigned short)(index))
|
||||
#define read_config_byte(handle,reg,address) (long)trap_14_wlwl((short)(302),(long)(handle),(unsigned short)(reg),(unsigned char *)(address))
|
||||
#define read_config_word(handle,reg,address) (long)trap_14_wlwl((short)(303),(long)(handle),(unsigned short)(reg),(unsigned short *)(address))
|
||||
#define read_config_longword(handle,reg,address) (long)trap_14_wlwl((short)(304),(long)(handle),(unsigned short)(reg),(unsigned long *)(address))
|
||||
#define fast_read_config_byte(handle,reg) (unsigned char)trap_14_wlw((short)(305),(long)(handle),(unsigned short)(reg))
|
||||
#define fast_read_config_word(handle,reg) (unsigned short)trap_14_wlw((short)(306),(long)(handle),(unsigned short)(reg))
|
||||
#define fast_read_config_longword(handle,reg) (unsigned long)trap_14_wlw((short)(307),(long)(handle),(unsigned short)(reg))
|
||||
#define write_config_byte(handle,reg,data) (long)trap_14_wlww((short)(308),(long)(handle),(unsigned short)(reg),(unsigned short)(data))
|
||||
#define write_config_word(handle,reg,data) (long)trap_14_wlww((short)(309),(long)(handle),(unsigned short)(reg),(unsigned short)(data))
|
||||
#define write_config_longword(handle,reg,data) (long)trap_14_wlwl((short)(310),(long)(handle),(unsigned short)(reg),(unsigned long)(data))
|
||||
#define hook_interrupt(handle,routine,parameter) (long)trap_14_wlll((short)(311),(long)(handle),(unsigned long *)(routine),(unsigned long *)(parameter))
|
||||
#define unhook_interrupt(handle) (long)trap_14_wl((short)(312),(long)(handle))
|
||||
#define special_cycle(bus_number,special_cycle) (long)trap_14_wwl((short)(313),(unsigned short)(bus_number),(unsigned long)(special_cycle))
|
||||
#define get_routing(handle) (long)trap_14_wl((short)(314),(long)(handle))
|
||||
#define set_interrupt(handle,mode) (long)trap_14_wlw((short)(315),(long)(handle),(short)(mode))
|
||||
#define get_resource(handle) (long)trap_14_wl((short)(316),(long)(handle))
|
||||
#define get_card_used(handle,callback) (long)trap_14_wll((short)(317),(long)(handle),(long *)(address))
|
||||
#define set_card_used(handle,callback) (long)trap_14_wll((short)(318),(long)(handle),(long *)(callback))
|
||||
#define read_mem_byte(handle,offset,address) (long)trap_14_wlll((short)(319),(long)(handle),(unsigned long)(offset),(unsigned char *)(address))
|
||||
#define read_mem_word(handle,offset,address) (long)trap_14_wlll((short)(320),(unsigned long)(offset),(unsigned short *)(address))
|
||||
#define read_mem_longword(handle,offset,address) (long)trap_14_wlll((short)(321),(unsigned long)(offset),(unsigned long *)(address))
|
||||
#define fast_read_mem_byte(handle,offset) (unsigned char)trap_14_wll((short)(322),(long)(handle),(unsigned long)(offset))
|
||||
#define fast_read_mem_word(handle,offset) (unsigned short)trap_14_wll((short)(323),(long)(handle),(unsigned long)(offset))
|
||||
#define fast_read_mem_longword(handle,offset) (unsigned long)trap_14_wll((short)(324),(long)(handle),(unsigned long)(offset))
|
||||
#define write_mem_byte(handle,offset,data) (long)trap_14_wllw((short)(325),(long)(handle),(unsigned long)(offset),(unsigned short)(data))
|
||||
#define write_mem_word(handle,offset,data) (long)trap_14_wllw((short)(326),(long)(handle),(unsigned long)(offset),(unsigned short)(data))
|
||||
#define write_mem_longword(handle,offset,data) (long)trap_14_wlll((short)(327),(long)(handle),(unsigned long)(offset),(unsigned long)(data))
|
||||
#define read_io_byte(handle,offset,address) (long)trap_14_wlll((short)(328),(long)(handle),(unsigned long)(offset),(unsigned char *)(address))
|
||||
#define read_io_word(handle,offset,address) (long)trap_14_wlll((short)(329),(long)(handle),(unsigned long)(offset),(unsigned short *)(address))
|
||||
#define read_io_longword(handle,offset,address) (long)trap_14_wlll((short)(330),(long)(handle),(unsigned long)(offset),(unsigned long *)(address))
|
||||
#define fast_read_io_byte(handle,offset) (unsigned char)trap_14_wll((short)(331),(long)(handle),(unsigned long)(offset))
|
||||
#define fast_read_io_word(handle,offset) (unsigned short)trap_14_wll((short)(332),(long)(handle),(unsigned long)(offset))
|
||||
#define fast_read_io_longword(handle,offset) (unsigned long)trap_14_wll((short)(333),(long)(handle),(unsigned long)(offset))
|
||||
#define write_io_byte(handle,offset,data) (long)trap_14_wllw((short)(334),(long)(handle),(unsigned long)(offset),(unsigned short)(data))
|
||||
#define write_io_word(handle,offset,data) (long)trap_14_wllw((short)(335),(long)(handle),(unsigned long)(offset),(unsigned short)(data))
|
||||
#define write_io_longword(handle,offset,data) (long)trap_14_wlll((short)(336),(long)(handle),(unsigned long)(offset),(unsigned long)(data))
|
||||
#define get_machine_id() (long)trap_14_w((short)(337))
|
||||
#define get_pagesize() (long)trap_14_w((short)(338))
|
||||
#define virt_to_bus(handle,address,pointer) (long)trap_14_wlll((short)(339),(long)(handle),(unsigned long)(address),(unsigned long *)(pointer))
|
||||
#define bus_to_virt(handle,address,pointer) (long)trap_14_wlll((short)(340),(long)(handle),(unsigned long)(address),(unsigned long *)(pointer))
|
||||
#define virt_to_phys(address,pointer) (long)trap_14_wll((short)(341),(unsigned long)(address),(unsigned long *)(pointer))
|
||||
#define phys_to_virt(address,pointer) (long)trap_14_wll((short)(342),(unsigned long)(address),(unsigned long *)(pointer))
|
||||
#define dma_setbuffer(pci_address,local_address,size) (long)trap_14_wlll((short)(350),(unsigned long)(pci_address),(unsigned long)(local_address),(unsigned long)(size))
|
||||
#define dma_buffoper(mode) (long)trap_14_ww((short)(351),(short)(mode))
|
||||
#define read_mailbox(mailbox,pointer) (long)trap_14_wwl((short)(352),(short)(mailbox),(unsigned long *)(pointer))
|
||||
#define write_mailbox(mailbox,data) (long)trap_14_wwl((short)(353),(short)(mailbox),(unsigned long)(data))
|
||||
|
||||
extern long Find_pci_device(unsigned long id, unsigned short index);
|
||||
extern long Find_pci_classcode(unsigned long class, unsigned short index);
|
||||
extern long Read_config_byte(long handle, unsigned short reg, unsigned char *address);
|
||||
extern long Read_config_word(long handle, unsigned short reg, unsigned short *address);
|
||||
extern long Read_config_longword(long handle, unsigned short reg, unsigned long *address);
|
||||
extern unsigned char Fast_read_config_byte(long handle, unsigned short reg);
|
||||
extern unsigned short Fast_read_config_word(long handle, unsigned short reg);
|
||||
extern unsigned long Fast_read_config_longword(long handle, unsigned short reg);
|
||||
extern long Write_config_byte(long handle, unsigned short reg, unsigned short val);
|
||||
extern long Write_config_word(long handle, unsigned short reg, unsigned short val);
|
||||
extern long Write_config_longword(long handle, unsigned short reg, unsigned long val);
|
||||
extern long Hook_interrupt(long handle, unsigned long *routine, unsigned long *parameter);
|
||||
extern long Unhook_interrupt(long handle);
|
||||
extern long Special_cycle(unsigned short bus, unsigned long data);
|
||||
extern long Get_routing(long handle);
|
||||
extern long Set_interrupt(long handle);
|
||||
extern long Get_resource(long handle);
|
||||
extern long Get_card_used(long handle, unsigned long *address);
|
||||
extern long Set_card_used(long handle, unsigned long *callback);
|
||||
extern long Read_mem_byte(long handle, unsigned long offset, unsigned char *address);
|
||||
extern long Read_mem_word(long handle, unsigned long offset, unsigned short *address);
|
||||
extern long Read_mem_longword(long handle, unsigned long offset, unsigned long *address);
|
||||
extern unsigned char Fast_read_mem_byte(long handle, unsigned long offset);
|
||||
extern unsigned short Fast_read_mem_word(long handle, unsigned long offset);
|
||||
extern unsigned long Fast_read_mem_longword(long handle, unsigned long offset);
|
||||
extern long Write_mem_byte(long handle, unsigned long offset, unsigned short val);
|
||||
extern long Write_mem_word(long handle, unsigned long offset, unsigned short val);
|
||||
extern long Write_mem_longword(long handle, unsigned long offset, unsigned long val);
|
||||
extern long Read_io_byte(long handle, unsigned long offset, unsigned char *address);
|
||||
extern long Read_io_word(long handle, unsigned long offset, unsigned short *address);
|
||||
extern long Read_io_longword(long handle, unsigned long offset, unsigned long *address);
|
||||
extern unsigned char Fast_read_io_byte(long handle, unsigned long offset);
|
||||
extern unsigned short Fast_read_io_word(long handle, unsigned long offset);
|
||||
extern unsigned long Fast_read_io_longword(long handle, unsigned long offset);
|
||||
extern long Write_io_byte(long handle, unsigned long offset, unsigned short val);
|
||||
extern long Write_io_word(long handle, unsigned long offset, unsigned short val);
|
||||
extern long Write_io_longword(long handle, unsigned long offset, unsigned long val);
|
||||
extern long Get_machine_id(void);
|
||||
extern long Get_pagesize(void);
|
||||
extern long Virt_to_bus(long handle, unsigned long address, PCI_CONV_ADR *pointer);
|
||||
extern long Bus_to_virt(long handle, unsigned long address, PCI_CONV_ADR *pointer);
|
||||
extern long Virt_to_phys(unsigned long address, PCI_CONV_ADR *pointer);
|
||||
extern long Phys_to_virt(unsigned long address, PCI_CONV_ADR *pointer);
|
||||
|
||||
#endif
|
||||
206
FireBee/trunk/usb/store/main.c
Normal file
206
FireBee/trunk/usb/store/main.c
Normal file
@@ -0,0 +1,206 @@
|
||||
/*
|
||||
* David Galvez. 2010, e-mail: dgalvez75@gmail.com
|
||||
* PCI code taken from FireTos by Didier Mequignon
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This file is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "usb.h"
|
||||
#include "super.h"
|
||||
#include "debug.h"
|
||||
#ifdef PCI_XBIOS
|
||||
#include "host/ohci-pci/pci_ids.h"
|
||||
#include "host/ohci-pci/pcixbios.h"
|
||||
#endif
|
||||
#include <mint/basepage.h>
|
||||
#include <mint/cookie.h>
|
||||
|
||||
extern long install_usb_stor(int dev_num, unsigned long part_type,
|
||||
unsigned long part_offset, unsigned long part_size,
|
||||
char *vendor, char *revision, char *product);
|
||||
extern int do_usb(int argc, char **argv);
|
||||
extern unsigned long _PgmSize;
|
||||
extern long __mint;
|
||||
#ifdef PCI_XBIOS
|
||||
extern struct pci_device_id usb_pci_table[]; /* ohci-hcd.c */
|
||||
#endif
|
||||
|
||||
int usb_stor_curr_dev;
|
||||
unsigned long usb_1st_disk_drive;
|
||||
short max_logical_drive;
|
||||
|
||||
#ifdef PCI_XBIOS
|
||||
short pci_init(void)
|
||||
{
|
||||
/* PCI devices detection */
|
||||
struct pci_device_id *board;
|
||||
long handle;
|
||||
short usb_found;
|
||||
|
||||
short idx;
|
||||
long err;
|
||||
unsigned long class;
|
||||
|
||||
usb_found = 0;
|
||||
idx = 0;
|
||||
do {
|
||||
handle = find_pci_device(0x0000FFFFL, idx++);
|
||||
printf("idx %d PCI handle: %lx\n", idx -1, handle); /* Galvez: Debug */
|
||||
if(handle >= 0) {
|
||||
unsigned long id = 0;
|
||||
err = read_config_longword(handle, PCIIDR, &id);
|
||||
|
||||
if((err >= 0) && !usb_found) {
|
||||
if(read_config_longword(handle, PCIREV, &class) >= 0
|
||||
&& ((class >> 16) == PCI_CLASS_SERIAL_USB)) {
|
||||
if((class >> 8) == PCI_CLASS_SERIAL_USB_UHCI)
|
||||
(void) Cconws("UHCI USB controller found\r\n");
|
||||
else if((class >> 8) == PCI_CLASS_SERIAL_USB_OHCI) {
|
||||
(void) Cconws("OHCI USB controller found\r\n");
|
||||
#ifdef CONFIG_USB_OHCI
|
||||
board = usb_pci_table; /* compare table */
|
||||
while(board->vendor) {
|
||||
if((board->vendor == (id & 0xFFFF))
|
||||
&& (board->device == (id >> 16))) {
|
||||
if(usb_init(handle, board) >= 0)
|
||||
usb_found = 1;
|
||||
break;
|
||||
}
|
||||
board++;
|
||||
}
|
||||
#endif /* CONFIG_USB_OHCI */
|
||||
}
|
||||
else if((class >> 8) == PCI_CLASS_SERIAL_USB_EHCI)
|
||||
(void) Cconws("EHCI USB controller found\r\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
while(handle >= 0);
|
||||
return usb_found;
|
||||
}
|
||||
#endif /* PCI_XBIOS */
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
#ifdef CONFIG_USB_STORAGE
|
||||
long p = 0;
|
||||
int r;
|
||||
|
||||
if (__mint)
|
||||
max_logical_drive = 24;
|
||||
else max_logical_drive = 16;
|
||||
|
||||
if (argc == 1) {
|
||||
short usb_found = 0;
|
||||
|
||||
usb_stor_curr_dev = -1;
|
||||
usb_1st_disk_drive = 0;
|
||||
|
||||
usb_stop();
|
||||
#ifdef PCI_XBIOS
|
||||
usb_found = pci_init();
|
||||
#else
|
||||
if (usb_init() >= 0)
|
||||
usb_found = 1;
|
||||
#endif /* PCI_XBIOS */
|
||||
if (usb_found) {
|
||||
/* Scan and get info from all the storage devices found */
|
||||
usb_stor_curr_dev = usb_stor_scan();
|
||||
/* it doesn't really return current device *
|
||||
* only 0 if it has found any store device *
|
||||
* -1 otherwise */
|
||||
if (usb_stor_curr_dev != -1) {
|
||||
int dev_num = usb_stor_curr_dev;
|
||||
block_dev_desc_t *stor_dev;
|
||||
|
||||
while ((stor_dev = usb_stor_get_dev(dev_num)) != NULL) {
|
||||
int part_num = 1;
|
||||
unsigned long part_type, part_offset, part_size;
|
||||
/* Now find partitions in this storage device */
|
||||
while (!fat_register_device(stor_dev, part_num, &part_type,
|
||||
&part_offset, &part_size)) {
|
||||
if (!(Super(SUP_INQUIRE))) {
|
||||
p = SuperFromUser ();
|
||||
}
|
||||
|
||||
/* install partition */
|
||||
r = install_usb_stor(dev_num, part_type, part_offset,
|
||||
part_size, stor_dev->vendor,
|
||||
stor_dev->revision, stor_dev->product);
|
||||
if (r == -1)
|
||||
printf("unable to install storage device\n");
|
||||
|
||||
if (p)
|
||||
SuperToUser(p);
|
||||
|
||||
part_num++;
|
||||
}
|
||||
dev_num++;
|
||||
}
|
||||
|
||||
}
|
||||
#if 0
|
||||
long *drvbits;
|
||||
long value;
|
||||
|
||||
p = SuperFromUser();
|
||||
|
||||
drvbits = 0x000004c2;
|
||||
|
||||
value = *drvbits;
|
||||
printf("\ndrvbits: %x \n", (unsigned)value);
|
||||
SuperToUser(p);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
if (!__mint) {
|
||||
printf(" Press any key");
|
||||
Bconin(DEV_CONSOLE);
|
||||
}
|
||||
Ptermres( _PgmSize, 0);
|
||||
}
|
||||
#endif /* CONFIG_USB_STORAGE */
|
||||
|
||||
if (strncmp(argv[1], "tree", 4) == 0) {
|
||||
argc = 2;
|
||||
argv[1] = "start";
|
||||
do_usb(argc, argv);
|
||||
|
||||
argv[1] = "inf";
|
||||
do_usb(argc, argv);
|
||||
|
||||
argv[1] = "tree";
|
||||
do_usb(argc, argv);
|
||||
|
||||
argv[1] = "storage";
|
||||
do_usb(argc, argv);
|
||||
|
||||
// argc = 3;
|
||||
// argv[1] = "dev";
|
||||
// argv[2] = "0";
|
||||
// do_usb(argc, argv);
|
||||
|
||||
// argc = 2;
|
||||
argv[1] = "stop";
|
||||
do_usb (argc, argv);
|
||||
|
||||
printf(" Press any key\r\n");
|
||||
Bconin(DEV_CONSOLE);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
85
FireBee/trunk/usb/store/makefile
Normal file
85
FireBee/trunk/usb/store/makefile
Normal file
@@ -0,0 +1,85 @@
|
||||
|
||||
ifeq ($(CROSS),yes)
|
||||
CC = m68k-atari-mint-gcc
|
||||
STRIP = m68k-atari-mint-strip
|
||||
STACK = m68k-atari-mint-stack
|
||||
INCLUDE_GEM_PATH = /usr/local/cross-mint/m68k-atari-mint/include
|
||||
LIB_GEM_PATH = /usr/local/cross-mint/m68k-atari-mint/lib
|
||||
else
|
||||
CC = gcc
|
||||
STRIP = /usr/bin/strip
|
||||
STACK = stack
|
||||
COMPRESS = upx
|
||||
INCLUDE_GEM_PATH = /usr/GEM/include
|
||||
LIB_GEM_PATH = /usr/GEM/lib
|
||||
endif
|
||||
|
||||
|
||||
ifeq ($(MAKECMDGOALS), aranym)
|
||||
HCD_S = ./host/aranym/natfeat_asm.S
|
||||
HCD_C = ./host/aranym/aranym-hcd.c ./host/aranym/natfeat.c
|
||||
HCD_H = ./host/aranym/nf_ops.h ./host/aranym/usbhost_nfapi.h
|
||||
PROGRAM = stor_ara.tos
|
||||
endif
|
||||
ifeq ($(MAKECMDGOALS), netusbee)
|
||||
HCD_C = ./host/netusbee/isp116x-hcd.c
|
||||
HCD_H = ./host/netusbee/isp116x.h
|
||||
PROGRAM = stor_ntu.tos
|
||||
endif
|
||||
ifeq ($(MAKECMDGOALS), ethernat)
|
||||
HCD_C = ./host/ethernat/isp116x-hcd.c
|
||||
HCD_H = ./host/ethernat/isp116x.h
|
||||
PROGRAM = stor_etn.tos
|
||||
endif
|
||||
ifeq ($(MAKECMDGOALS), ohci-pci)
|
||||
HCD_C = ./host/ohci-pci/ohci-hcd.c ./host/ohci-pci/ltoa.c
|
||||
HCD_H = ./host/ohci-pci/ohci.h ./host/ohci-pci/pcixbios.h
|
||||
DEFS = -DPCI_XBIOS
|
||||
PROGRAM = stor_pci.tos
|
||||
endif
|
||||
|
||||
STACKSIZE = 64k
|
||||
OPTIMISATION = -O -fomit-frame-pointer
|
||||
CPU = -m68020-60
|
||||
LIB =
|
||||
ASFLAGS = $(CPU)
|
||||
CFLAGS = $(CPU) $(OPTIMISATION) -Wall -Wshadow -I$(INCLUDE_GEM_PATH) $(DEFS) -g
|
||||
LFLAGS = -L$(LIB_GEM_PATH)
|
||||
COBJS = main.c udelay.c cmd_usb.c usb.c usb_mem.c usb_storage.c debug.c $(HCD_C)
|
||||
SOBJS = debug2.S bios.S $(HCD_S)
|
||||
HSRC = config.h debug.h part.h scsi.h super.h usb.h usb_defs.h vars.h $(HCD_H)
|
||||
COBJECTS = $(COBJS:.c=.o)
|
||||
SOBJECTS = $(SOBJS:.S=.o)
|
||||
|
||||
all:
|
||||
make ethernat
|
||||
make netusbee
|
||||
make aranym
|
||||
rm -f *.o
|
||||
make ohci-pci
|
||||
|
||||
ethernat: $(PROGRAM)
|
||||
|
||||
aranym: $(PROGRAM)
|
||||
|
||||
netusbee: $(PROGRAM)
|
||||
|
||||
ohci-pci: $(PROGRAM)
|
||||
|
||||
$(PROGRAM): $(COBJECTS) $(SOBJECTS) $(HSRC)
|
||||
$(CC) -o $@ $(COBJECTS) $(SOBJECTS)
|
||||
|
||||
strip:
|
||||
$(STRIP) $(PROGRAM)
|
||||
|
||||
stack:
|
||||
$(STACK) -S $(STACKSIZE) $(PROGRAM)
|
||||
|
||||
compress:
|
||||
$(COMPRESS) $(PROGRAM)
|
||||
|
||||
clean:
|
||||
rm -f *.tos *.log
|
||||
find ./ -type f -name "*.o" -exec rm -f {} \;
|
||||
|
||||
|
||||
88
FireBee/trunk/usb/store/part.h
Normal file
88
FireBee/trunk/usb/store/part.h
Normal file
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
* (C) Copyright 2000-2004
|
||||
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
|
||||
*
|
||||
* See file CREDITS for list of people who contributed to this
|
||||
* project.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
#ifndef _PART_H
|
||||
#define _PART_H
|
||||
|
||||
typedef unsigned long long uint64_t;
|
||||
typedef unsigned long lbaint_t;
|
||||
|
||||
typedef struct block_dev_desc {
|
||||
int if_type; /* type of the interface */
|
||||
int dev; /* device number */
|
||||
unsigned char part_type; /* partition type */
|
||||
unsigned char target; /* target SCSI ID */
|
||||
unsigned char lun; /* target LUN */
|
||||
unsigned char type; /* device type */
|
||||
unsigned char removable; /* removable device */
|
||||
#ifdef CONFIG_LBA48
|
||||
unsigned char lba48; /* device can use 48bit addr (ATA/ATAPI v7) */
|
||||
#endif
|
||||
lbaint_t lba; /* number of blocks */
|
||||
unsigned long blksz; /* block size */
|
||||
char vendor [40+1]; /* IDE model, SCSI Vendor */
|
||||
char product[20+1]; /* IDE Serial no, SCSI product */
|
||||
char revision[8+1]; /* firmware revision */
|
||||
unsigned long (*block_read)(int dev, unsigned long start, lbaint_t blkcnt, void *buffer);
|
||||
unsigned long (*block_write)(int dev, unsigned long start, lbaint_t blkcnt, const void *buffer);
|
||||
void *priv; /* driver private struct pointer */
|
||||
}block_dev_desc_t;
|
||||
|
||||
/* Interface types: */
|
||||
#define IF_TYPE_UNKNOWN 0
|
||||
#define IF_TYPE_IDE 1
|
||||
#define IF_TYPE_SCSI 2
|
||||
#define IF_TYPE_ATAPI 3
|
||||
#define IF_TYPE_USB 4
|
||||
#define IF_TYPE_DOC 5
|
||||
#define IF_TYPE_MMC 6
|
||||
#define IF_TYPE_SD 7
|
||||
#define IF_TYPE_SATA 8
|
||||
|
||||
/* Part types */
|
||||
#define PART_TYPE_UNKNOWN 0x00
|
||||
#define PART_TYPE_MAC 0x01
|
||||
#define PART_TYPE_DOS 0x02
|
||||
#define PART_TYPE_ISO 0x03
|
||||
#define PART_TYPE_AMIGA 0x04
|
||||
#define PART_TYPE_EFI 0x05
|
||||
|
||||
/*
|
||||
* Type string for U-Boot bootable partitions
|
||||
*/
|
||||
#define BOOT_PART_TYPE "U-Boot" /* primary boot partition type */
|
||||
#define BOOT_PART_COMP "PPCBoot" /* PPCBoot compatibility type */
|
||||
|
||||
/* device types */
|
||||
#define DEV_TYPE_UNKNOWN 0xff /* not connected */
|
||||
#define DEV_TYPE_HARDDISK 0x00 /* harddisk */
|
||||
#define DEV_TYPE_TAPE 0x01 /* Tape */
|
||||
#define DEV_TYPE_CDROM 0x05 /* CD-ROM */
|
||||
#define DEV_TYPE_OPDISK 0x07 /* optical disk */
|
||||
|
||||
void print_part(block_dev_desc_t *dev_desc);
|
||||
void init_part(block_dev_desc_t *dev_desc);
|
||||
void dev_print(block_dev_desc_t *dev_desc);
|
||||
|
||||
int fat_register_device(block_dev_desc_t *dev_desc, int part_no, unsigned long *part_type, unsigned long *part_offset, unsigned long *part_size);
|
||||
|
||||
#endif /* _PART_H */
|
||||
68
FireBee/trunk/usb/store/readme.txt
Normal file
68
FireBee/trunk/usb/store/readme.txt
Normal file
@@ -0,0 +1,68 @@
|
||||
This application allows you to mount an USB mass storage device though
|
||||
the Ethernat hardware or the Aranym USB Natfeat, read or copy files from/to this device.
|
||||
It's derived from the work done by Didier Mequignon for FireTOS.
|
||||
|
||||
This is still quite experimental so i am not responsable for any data loss
|
||||
or corruption, play with it at your own risk. Please backup your data ;-)
|
||||
|
||||
**** Binaries ****
|
||||
|
||||
stor_etn.tos ---> EtherNat
|
||||
stor_ara.tos ---> Aranym
|
||||
stor_ntu.tos ---> NetUSBee
|
||||
stor_pci.tos ---> PCI-OHCI
|
||||
|
||||
Note that NetUSBee and PCI-OHCI don't work yet
|
||||
|
||||
**** How it works *****
|
||||
|
||||
Depending on your hardware run stor_etn.tos or stor_ara.tos application from your desktop,
|
||||
if everything goes well you can use the "install partition" option in your desktop menu to
|
||||
access the new partitions.
|
||||
|
||||
It has been tested it under CT060 TOS and MiNT 1.16.3.
|
||||
Teted in Aranym with MiNT 1.17.0 beta and TOS 4.04.
|
||||
|
||||
**** Limits/Problems *****
|
||||
|
||||
- The supported partitions are the supported partitions by the OS.
|
||||
It has been tested with FAT16 in TOS4.04, with FAT16, FAT32 and ext2 with MiNT.
|
||||
|
||||
- There is still no handle for mounting/unmounting partitions. Neither detection for
|
||||
devices already plugged, so when you mount one device you can't unmount it.
|
||||
If you run the application several times with the same USB stick plugged, it
|
||||
will mount the device again as a new different logical partition.
|
||||
|
||||
- It's VERY VERY slow, for now the transfer rate it's quite ridiculous. I hope
|
||||
to solve this soon. Under Aranym it can be better.
|
||||
|
||||
- I don't think that it works together with umouse from Jan Thomas.
|
||||
|
||||
- This is only a start don't expect too much.
|
||||
|
||||
- Thing desktop crashes when inquiring to show info about the device.
|
||||
|
||||
For feedback, suggestions or tips mail me at dgalvez75@gmail.com
|
||||
|
||||
**** Histoy ****
|
||||
* 5/10/2010 (alfa 05)
|
||||
- XHDI working (assembler version).
|
||||
- Under MiNT FAT32 and ext2 partitions can be accesed.
|
||||
- Introduced NetUSBee sources (not working yet)
|
||||
- Introduced OHCI-PCI sources (to be tested)
|
||||
* 27/8/2010 (alfa 04)
|
||||
- Start XHDI translation to C.
|
||||
- Support for Aranym HCD.
|
||||
* 19/5/2010 (alfa 03)
|
||||
- Killed a bug that could produce some corruption in the pun_info struct.
|
||||
* 26/4/2010 (alfa 02)
|
||||
- Under MiNT if the number of partitions was greater than 16, the driver wasn't installed.
|
||||
- Wait for a key pess before retuning the desktop under TOS when driver is loaded.
|
||||
- Resolved big bug that produced that data written/read above the first 16 MB to be corrupted.
|
||||
* 1/3/2010 (alfa 01)
|
||||
- Initial release
|
||||
|
||||
David Galvez 05/10/2010
|
||||
Version: alfa 05
|
||||
|
||||
|
||||
209
FireBee/trunk/usb/store/scsi.h
Normal file
209
FireBee/trunk/usb/store/scsi.h
Normal file
@@ -0,0 +1,209 @@
|
||||
/*
|
||||
* (C) Copyright 2001
|
||||
* Denis Peter, MPL AG Switzerland
|
||||
*
|
||||
* See file CREDITS for list of people who contributed to this
|
||||
* project.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
#ifndef _SCSI_H
|
||||
#define _SCSI_H
|
||||
|
||||
typedef struct SCSI_cmd_block{
|
||||
unsigned char cmd[16]; /* command */
|
||||
unsigned char sense_buf[64]; /* for request sense */
|
||||
unsigned char status; /* SCSI Status */
|
||||
unsigned char target; /* Target ID */
|
||||
unsigned char lun; /* Target LUN */
|
||||
unsigned char cmdlen; /* command len */
|
||||
unsigned long datalen; /* Total data length */
|
||||
unsigned char * pdata; /* pointer to data */
|
||||
unsigned char msgout[12]; /* Messge out buffer (NOT USED) */
|
||||
unsigned char msgin[12]; /* Message in buffer */
|
||||
unsigned char sensecmdlen; /* Sense command len */
|
||||
unsigned long sensedatalen; /* Sense data len */
|
||||
unsigned char sensecmd[6]; /* Sense command */
|
||||
unsigned long contr_stat; /* Controller Status */
|
||||
unsigned long trans_bytes; /* tranfered bytes */
|
||||
|
||||
unsigned int priv;
|
||||
}ccb;
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
**
|
||||
** SCSI constants.
|
||||
**
|
||||
**-----------------------------------------------------------
|
||||
*/
|
||||
|
||||
/*
|
||||
** Messages
|
||||
*/
|
||||
|
||||
#define M_COMPLETE (0x00)
|
||||
#define M_EXTENDED (0x01)
|
||||
#define M_SAVE_DP (0x02)
|
||||
#define M_RESTORE_DP (0x03)
|
||||
#define M_DISCONNECT (0x04)
|
||||
#define M_ID_ERROR (0x05)
|
||||
#define M_ABORT (0x06)
|
||||
#define M_REJECT (0x07)
|
||||
#define M_NOOP (0x08)
|
||||
#define M_PARITY (0x09)
|
||||
#define M_LCOMPLETE (0x0a)
|
||||
#define M_FCOMPLETE (0x0b)
|
||||
#define M_RESET (0x0c)
|
||||
#define M_ABORT_TAG (0x0d)
|
||||
#define M_CLEAR_QUEUE (0x0e)
|
||||
#define M_INIT_REC (0x0f)
|
||||
#define M_REL_REC (0x10)
|
||||
#define M_TERMINATE (0x11)
|
||||
#define M_SIMPLE_TAG (0x20)
|
||||
#define M_HEAD_TAG (0x21)
|
||||
#define M_ORDERED_TAG (0x22)
|
||||
#define M_IGN_RESIDUE (0x23)
|
||||
#define M_IDENTIFY (0x80)
|
||||
|
||||
#define M_X_MODIFY_DP (0x00)
|
||||
#define M_X_SYNC_REQ (0x01)
|
||||
#define M_X_WIDE_REQ (0x03)
|
||||
#define M_X_PPR_REQ (0x04)
|
||||
|
||||
|
||||
/*
|
||||
** Status
|
||||
*/
|
||||
|
||||
#define S_GOOD (0x00)
|
||||
#define S_CHECK_COND (0x02)
|
||||
#define S_COND_MET (0x04)
|
||||
#define S_BUSY (0x08)
|
||||
#define S_INT (0x10)
|
||||
#define S_INT_COND_MET (0x14)
|
||||
#define S_CONFLICT (0x18)
|
||||
#define S_TERMINATED (0x20)
|
||||
#define S_QUEUE_FULL (0x28)
|
||||
#define S_ILLEGAL (0xff)
|
||||
#define S_SENSE (0x80)
|
||||
|
||||
/*
|
||||
* Sense_keys
|
||||
*/
|
||||
|
||||
#define SENSE_NO_SENSE 0x0
|
||||
#define SENSE_RECOVERED_ERROR 0x1
|
||||
#define SENSE_NOT_READY 0x2
|
||||
#define SENSE_MEDIUM_ERROR 0x3
|
||||
#define SENSE_HARDWARE_ERROR 0x4
|
||||
#define SENSE_ILLEGAL_REQUEST 0x5
|
||||
#define SENSE_UNIT_ATTENTION 0x6
|
||||
#define SENSE_DATA_PROTECT 0x7
|
||||
#define SENSE_BLANK_CHECK 0x8
|
||||
#define SENSE_VENDOR_SPECIFIC 0x9
|
||||
#define SENSE_COPY_ABORTED 0xA
|
||||
#define SENSE_ABORTED_COMMAND 0xB
|
||||
#define SENSE_VOLUME_OVERFLOW 0xD
|
||||
#define SENSE_MISCOMPARE 0xE
|
||||
|
||||
|
||||
#define SCSI_CHANGE_DEF 0x40 /* Change Definition (Optional) */
|
||||
#define SCSI_COMPARE 0x39 /* Compare (O) */
|
||||
#define SCSI_COPY 0x18 /* Copy (O) */
|
||||
#define SCSI_COP_VERIFY 0x3A /* Copy and Verify (O) */
|
||||
#define SCSI_INQUIRY 0x12 /* Inquiry (MANDATORY) */
|
||||
#define SCSI_LOG_SELECT 0x4C /* Log Select (O) */
|
||||
#define SCSI_LOG_SENSE 0x4D /* Log Sense (O) */
|
||||
#define SCSI_MODE_SEL6 0x15 /* Mode Select 6-byte (Device Specific) */
|
||||
#define SCSI_MODE_SEL10 0x55 /* Mode Select 10-byte (Device Specific) */
|
||||
#define SCSI_MODE_SEN6 0x1A /* Mode Sense 6-byte (Device Specific) */
|
||||
#define SCSI_MODE_SEN10 0x5A /* Mode Sense 10-byte (Device Specific) */
|
||||
#define SCSI_READ_BUFF 0x3C /* Read Buffer (O) */
|
||||
#define SCSI_REQ_SENSE 0x03 /* Request Sense (MANDATORY) */
|
||||
#define SCSI_SEND_DIAG 0x1D /* Send Diagnostic (O) */
|
||||
#define SCSI_TST_U_RDY 0x00 /* Test Unit Ready (MANDATORY) */
|
||||
#define SCSI_WRITE_BUFF 0x3B /* Write Buffer (O) */
|
||||
/***************************************************************************
|
||||
* %%% Commands Unique to Direct Access Devices %%%
|
||||
***************************************************************************/
|
||||
#define SCSI_COMPARE 0x39 /* Compare (O) */
|
||||
#define SCSI_FORMAT 0x04 /* Format Unit (MANDATORY) */
|
||||
#define SCSI_LCK_UN_CAC 0x36 /* Lock Unlock Cache (O) */
|
||||
#define SCSI_PREFETCH 0x34 /* Prefetch (O) */
|
||||
#define SCSI_MED_REMOVL 0x1E /* Prevent/Allow medium Removal (O) */
|
||||
#define SCSI_READ6 0x08 /* Read 6-byte (MANDATORY) */
|
||||
#define SCSI_READ10 0x28 /* Read 10-byte (MANDATORY) */
|
||||
#define SCSI_RD_CAPAC 0x25 /* Read Capacity (MANDATORY) */
|
||||
#define SCSI_RD_DEFECT 0x37 /* Read Defect Data (O) */
|
||||
#define SCSI_READ_LONG 0x3E /* Read Long (O) */
|
||||
#define SCSI_REASS_BLK 0x07 /* Reassign Blocks (O) */
|
||||
#define SCSI_RCV_DIAG 0x1C /* Receive Diagnostic Results (O) */
|
||||
#define SCSI_RELEASE 0x17 /* Release Unit (MANDATORY) */
|
||||
#define SCSI_REZERO 0x01 /* Rezero Unit (O) */
|
||||
#define SCSI_SRCH_DAT_E 0x31 /* Search Data Equal (O) */
|
||||
#define SCSI_SRCH_DAT_H 0x30 /* Search Data High (O) */
|
||||
#define SCSI_SRCH_DAT_L 0x32 /* Search Data Low (O) */
|
||||
#define SCSI_SEEK6 0x0B /* Seek 6-Byte (O) */
|
||||
#define SCSI_SEEK10 0x2B /* Seek 10-Byte (O) */
|
||||
#define SCSI_SEND_DIAG 0x1D /* Send Diagnostics (MANDATORY) */
|
||||
#define SCSI_SET_LIMIT 0x33 /* Set Limits (O) */
|
||||
#define SCSI_START_STP 0x1B /* Start/Stop Unit (O) */
|
||||
#define SCSI_SYNC_CACHE 0x35 /* Synchronize Cache (O) */
|
||||
#define SCSI_VERIFY 0x2F /* Verify (O) */
|
||||
#define SCSI_WRITE6 0x0A /* Write 6-Byte (MANDATORY) */
|
||||
#define SCSI_WRITE10 0x2A /* Write 10-Byte (MANDATORY) */
|
||||
#define SCSI_WRT_VERIFY 0x2E /* Write and Verify (O) */
|
||||
#define SCSI_WRITE_LONG 0x3F /* Write Long (O) */
|
||||
#define SCSI_WRITE_SAME 0x41 /* Write Same (O) */
|
||||
|
||||
#if 0
|
||||
/****************************************************************************
|
||||
* decleration of functions which have to reside in the LowLevel Part Driver
|
||||
*/
|
||||
|
||||
void scsi_print_error(ccb *pccb);
|
||||
int scsi_exec(ccb *pccb);
|
||||
void scsi_bus_reset(void);
|
||||
void scsi_low_level_init(int busdevfunc);
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
* functions residing inside cmd_scsi.c
|
||||
*/
|
||||
void scsi_init(void);
|
||||
|
||||
#endif
|
||||
|
||||
#define SCSI_IDENTIFY 0xC0 /* not used */
|
||||
|
||||
/* Hardware errors */
|
||||
#define SCSI_SEL_TIME_OUT 0x00000101 /* Selection time out */
|
||||
#define SCSI_HNS_TIME_OUT 0x00000102 /* Handshake */
|
||||
#define SCSI_MA_TIME_OUT 0x00000103 /* Phase error */
|
||||
#define SCSI_UNEXP_DIS 0x00000104 /* unexpected disconnect */
|
||||
|
||||
#define SCSI_INT_STATE 0x00010000 /* unknown Interrupt number is stored in 16 LSB */
|
||||
|
||||
|
||||
#ifndef TRUE
|
||||
#define TRUE 1
|
||||
#endif
|
||||
#ifndef FALSE
|
||||
#define FALSE 0
|
||||
#endif
|
||||
|
||||
#endif /* _SCSI_H */
|
||||
58
FireBee/trunk/usb/store/super.h
Normal file
58
FireBee/trunk/usb/store/super.h
Normal file
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* super.h
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This file is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _SUPER_H
|
||||
#define _SUPER_H
|
||||
|
||||
static inline
|
||||
long SuperFromUser()
|
||||
{
|
||||
register long retvalue __asm__("d0");
|
||||
|
||||
__asm__ volatile
|
||||
(
|
||||
"clr.l -(%%sp)\n\t"
|
||||
"move.w #0x20,-(%%sp)\n\t"
|
||||
"trap #1\n\t"
|
||||
"addq.l #6,%%sp"
|
||||
: "=r"(retvalue) /* outputs */
|
||||
: /* inputs */
|
||||
: "d1", "d2", "a0", "a1", "a2" /* clobbered regs */
|
||||
);
|
||||
|
||||
return retvalue;
|
||||
}
|
||||
|
||||
static inline
|
||||
void SuperToUser(long ssp)
|
||||
{
|
||||
register long spbackup;
|
||||
|
||||
__asm__ volatile
|
||||
(
|
||||
"move.l sp,%0\n\t"
|
||||
"move.l %1,-(%%sp)\n\t"
|
||||
"move.w #0x20,-(%%sp)\n\t"
|
||||
"trap #1\n\t"
|
||||
"move.l %0,sp"
|
||||
: "=&r"(spbackup) /* outputs */
|
||||
: "g"(ssp) /* inputs */
|
||||
: "d0", "d1", "d2", "a0", "a1", "a2" /* clobbered regs */
|
||||
);
|
||||
}
|
||||
#endif /* _SUPER_H */
|
||||
39
FireBee/trunk/usb/store/udelay.c
Normal file
39
FireBee/trunk/usb/store/udelay.c
Normal file
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* David Galvez. 2010, e-mail: dgalvez75@gmail.com
|
||||
* Modified from MiNTlib
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This file is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <time.h>
|
||||
#include <mint/mintbind.h>
|
||||
|
||||
#define USEC_PER_TICK (1000000L / ((unsigned long)CLOCKS_PER_SEC))
|
||||
#define USEC_TO_CLOCK_TICKS(us) ((us) / USEC_PER_TICK )
|
||||
|
||||
/*
|
||||
* Galvez: We should use usleep POSIX function in MiNTlib, but it gives problems related with
|
||||
* Fselect system call, until we trace where the problems come from we are using this function
|
||||
*/
|
||||
|
||||
void udelay(unsigned long usec)
|
||||
{
|
||||
long stop;
|
||||
|
||||
stop = _clock() + USEC_TO_CLOCK_TICKS(usec);
|
||||
while (_clock() < stop);
|
||||
}
|
||||
1422
FireBee/trunk/usb/store/usb.c
Normal file
1422
FireBee/trunk/usb/store/usb.c
Normal file
File diff suppressed because it is too large
Load Diff
470
FireBee/trunk/usb/store/usb.h
Normal file
470
FireBee/trunk/usb/store/usb.h
Normal file
@@ -0,0 +1,470 @@
|
||||
/*
|
||||
* Modified for Atari by David Gálvez 2010
|
||||
* Modified for Atari by Didier Mequignon 2009
|
||||
*
|
||||
* (C) Copyright 2001
|
||||
* Denis Peter, MPL AG Switzerland
|
||||
*
|
||||
* See file CREDITS for list of people who contributed to this
|
||||
* project.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Note: Part of this code has been derived from linux
|
||||
*
|
||||
*/
|
||||
#ifndef _USB_H_
|
||||
#define _USB_H_
|
||||
|
||||
#include <mint/osbind.h>
|
||||
#include <mint/sysvars.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "host/ohci-pci/mod_devicetable.h"
|
||||
#include "usb_defs.h"
|
||||
#include "asm-m68k/types.h"
|
||||
#include "asm-m68k/byteorder.h"
|
||||
#include "part.h"
|
||||
|
||||
#ifdef PCI_XBIOS
|
||||
|
||||
#define in8(addr) fast_read_mem_byte(usb_handle,addr)
|
||||
#define in16r(addr) fast_read_mem_word(usb_handle,addr)
|
||||
#define in32r(addr) fast_read_mem_longword(usb_handle,addr)
|
||||
#define out8(addr,val) write_mem_byte(usb_handle,addr,val)
|
||||
#define out16r(addr,val) write_mem_word(usb_handle,addr,val)
|
||||
#define out32r(addr,val) write_mem_longword(usb_handle,addr,val)
|
||||
|
||||
#else /* !PCI_XBIOS */
|
||||
|
||||
extern long *tab_funcs_pci;
|
||||
|
||||
#define in8(addr) Fast_read_mem_byte(usb_handle,addr)
|
||||
#define in16r(addr) Fast_read_mem_word(usb_handle,addr)
|
||||
#define in32r(addr) Fast_read_mem_longword(usb_handle,addr)
|
||||
#define out8(addr,val) Write_mem_byte(usb_handle,addr,val)
|
||||
#define out16r(addr,val) Write_mem_word(usb_handle,addr,val)
|
||||
#define out32r(addr,val) Write_mem_longword(usb_handle,addr,val)
|
||||
|
||||
#endif /* PCI_XBIOS */
|
||||
|
||||
|
||||
/* Everything is aribtrary */
|
||||
#define USB_ALTSETTINGALLOC 4
|
||||
#define USB_MAXALTSETTING 128 /* Hard limit */
|
||||
|
||||
#define USB_MAX_DEVICE 32
|
||||
#define USB_MAXCONFIG 8
|
||||
#define USB_MAXINTERFACES 8
|
||||
#define USB_MAXENDPOINTS 16
|
||||
#define USB_MAXCHILDREN 8 /* This is arbitrary */
|
||||
#define USB_MAX_HUB 16
|
||||
|
||||
#define USB_CNTL_TIMEOUT 100 /* 100ms timeout */
|
||||
|
||||
/* String descriptor */
|
||||
struct usb_string_descriptor {
|
||||
unsigned char bLength;
|
||||
unsigned char bDescriptorType;
|
||||
unsigned short wData[1];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/* device request (setup) */
|
||||
struct devrequest {
|
||||
unsigned char requesttype;
|
||||
unsigned char request;
|
||||
unsigned short value;
|
||||
unsigned short index;
|
||||
unsigned short length;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/* All standard descriptors have these 2 fields in common */
|
||||
struct usb_descriptor_header {
|
||||
unsigned char bLength;
|
||||
unsigned char bDescriptorType;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/* Device descriptor */
|
||||
struct usb_device_descriptor {
|
||||
unsigned char bLength;
|
||||
unsigned char bDescriptorType;
|
||||
unsigned short bcdUSB;
|
||||
unsigned char bDeviceClass;
|
||||
unsigned char bDeviceSubClass;
|
||||
unsigned char bDeviceProtocol;
|
||||
unsigned char bMaxPacketSize0;
|
||||
unsigned short idVendor;
|
||||
unsigned short idProduct;
|
||||
unsigned short bcdDevice;
|
||||
unsigned char iManufacturer;
|
||||
unsigned char iProduct;
|
||||
unsigned char iSerialNumber;
|
||||
unsigned char bNumConfigurations;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/* Endpoint descriptor */
|
||||
struct usb_endpoint_descriptor {
|
||||
unsigned char bLength;
|
||||
unsigned char bDescriptorType;
|
||||
unsigned char bEndpointAddress;
|
||||
unsigned char bmAttributes;
|
||||
unsigned short wMaxPacketSize;
|
||||
unsigned char bInterval;
|
||||
unsigned char bRefresh;
|
||||
unsigned char bSynchAddress;
|
||||
} __attribute__ ((packed)) __attribute__ ((aligned(2)));
|
||||
|
||||
/* Interface descriptor */
|
||||
struct usb_interface_descriptor {
|
||||
unsigned char bLength;
|
||||
unsigned char bDescriptorType;
|
||||
unsigned char bInterfaceNumber;
|
||||
unsigned char bAlternateSetting;
|
||||
unsigned char bNumEndpoints;
|
||||
unsigned char bInterfaceClass;
|
||||
unsigned char bInterfaceSubClass;
|
||||
unsigned char bInterfaceProtocol;
|
||||
unsigned char iInterface;
|
||||
|
||||
unsigned char no_of_ep;
|
||||
unsigned char num_altsetting;
|
||||
unsigned char act_altsetting;
|
||||
|
||||
struct usb_endpoint_descriptor ep_desc[USB_MAXENDPOINTS];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
|
||||
/* Configuration descriptor information.. */
|
||||
struct usb_config_descriptor {
|
||||
unsigned char bLength;
|
||||
unsigned char bDescriptorType;
|
||||
unsigned short wTotalLength;
|
||||
unsigned char bNumInterfaces;
|
||||
unsigned char bConfigurationValue;
|
||||
unsigned char iConfiguration;
|
||||
unsigned char bmAttributes;
|
||||
unsigned char MaxPower;
|
||||
|
||||
unsigned char no_of_if; /* number of interfaces */
|
||||
struct usb_interface_descriptor if_desc[USB_MAXINTERFACES];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
enum {
|
||||
/* Maximum packet size; encoded as 0,1,2,3 = 8,16,32,64 */
|
||||
PACKET_SIZE_8 = 0,
|
||||
PACKET_SIZE_16 = 1,
|
||||
PACKET_SIZE_32 = 2,
|
||||
PACKET_SIZE_64 = 3,
|
||||
};
|
||||
|
||||
struct usb_device {
|
||||
int devnum; /* Device number on USB bus */
|
||||
int speed; /* full/low/high */
|
||||
char mf[32]; /* manufacturer */
|
||||
char prod[32]; /* product */
|
||||
char serial[32]; /* serial number */
|
||||
|
||||
/* Maximum packet size; one of: PACKET_SIZE_* */
|
||||
int maxpacketsize;
|
||||
/* one bit for each endpoint ([0] = IN, [1] = OUT) */
|
||||
unsigned int toggle[2];
|
||||
/* endpoint halts; one bit per endpoint # & direction;
|
||||
* [0] = IN, [1] = OUT
|
||||
*/
|
||||
unsigned int halted[2];
|
||||
int epmaxpacketin[16]; /* INput endpoint specific maximums */
|
||||
int epmaxpacketout[16]; /* OUTput endpoint specific maximums */
|
||||
|
||||
int configno; /* selected config number */
|
||||
struct usb_device_descriptor descriptor; /* Device Descriptor */
|
||||
struct usb_config_descriptor config; /* config descriptor */
|
||||
|
||||
int have_langid; /* whether string_langid is valid yet */
|
||||
int string_langid; /* language ID for strings */
|
||||
int (*irq_handle)(struct usb_device *dev);
|
||||
unsigned long irq_status;
|
||||
int irq_act_len; /* transfered bytes */
|
||||
void *privptr;
|
||||
/*
|
||||
* Child devices - if this is a hub device
|
||||
* Each instance needs its own set of data structures.
|
||||
*/
|
||||
unsigned long status;
|
||||
int act_len; /* transfered bytes */
|
||||
int maxchild; /* Number of ports if hub */
|
||||
int portnr;
|
||||
struct usb_device *parent;
|
||||
struct usb_device *children[USB_MAXCHILDREN];
|
||||
};
|
||||
|
||||
/**********************************************************************
|
||||
* this is how the lowlevel part communicate with the outer world
|
||||
*/
|
||||
|
||||
#if defined(CONFIG_USB_UHCI) || defined(CONFIG_USB_OHCI) || \
|
||||
defined(CONFIG_USB_EHCI) || defined(CONFIG_USB_OHCI_NEW) || \
|
||||
defined(CONFIG_USB_SL811HS) || defined(CONFIG_USB_ISP116X_HCD) || \
|
||||
defined(CONFIG_USB_R8A66597_HCD) || defined(CONFIG_USB_DAVINCI) || \
|
||||
defined(CONFIG_USB_ARANYM_HCD)
|
||||
|
||||
#ifdef PCI_XBIOS
|
||||
int usb_lowlevel_init(long handle, const struct pci_device_id *ent);
|
||||
#else
|
||||
int usb_lowlevel_init(void);
|
||||
#endif
|
||||
|
||||
int usb_lowlevel_stop(void);
|
||||
int submit_bulk_msg(struct usb_device *dev, unsigned long pipe,
|
||||
void *buffer, int transfer_len);
|
||||
int submit_control_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
|
||||
int transfer_len, struct devrequest *setup);
|
||||
int submit_int_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
|
||||
int transfer_len, int interval);
|
||||
|
||||
#ifdef CONFIG_USB_INTERRUPT_POLLING
|
||||
void usb_event_poll(void);
|
||||
#else
|
||||
void usb_enable_interrupt(int enable);
|
||||
#endif
|
||||
|
||||
/* Defines */
|
||||
#define USB_UHCI_VEND_ID 0x8086
|
||||
#define USB_UHCI_DEV_ID 0x7112
|
||||
|
||||
#else
|
||||
#error USB Lowlevel not defined
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_USB_STORAGE
|
||||
|
||||
#define USB_MAX_STOR_DEV 2 /* GALVEZ: DEFAULT 5 */
|
||||
block_dev_desc_t *usb_stor_get_dev(int idx);
|
||||
int usb_stor_scan(void);
|
||||
int usb_stor_info(void);
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_USB_MOUSE
|
||||
int drv_usb_mouse_init(void);
|
||||
int usb_mouse_deregister(void);
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef CONFIG_USB_KEYBOARD
|
||||
int drv_usb_kbd_init(void);
|
||||
int usb_kbd_deregister(void);
|
||||
#endif
|
||||
|
||||
/* memory */
|
||||
void *usb_malloc(long amount);
|
||||
int usb_free(void *addr);
|
||||
int usb_mem_init(void);
|
||||
void usb_mem_stop(void);
|
||||
|
||||
|
||||
/* routines */
|
||||
#ifdef PCI_XBIOS
|
||||
int usb_init(long handle, const struct pci_device_id *ent); /* initialize the USB Controller */
|
||||
#else
|
||||
int usb_init(void); /* initialize the USB Controller */
|
||||
#endif
|
||||
int usb_stop(void); /* stop the USB Controller */
|
||||
|
||||
|
||||
int usb_set_protocol(struct usb_device *dev, int ifnum, int protocol);
|
||||
int usb_set_idle(struct usb_device *dev, int ifnum, int duration,
|
||||
int report_id);
|
||||
struct usb_device *usb_get_dev_index(int idx);
|
||||
int usb_control_msg(struct usb_device *dev, unsigned int pipe,
|
||||
unsigned char request, unsigned char requesttype,
|
||||
unsigned short value, unsigned short idx,
|
||||
void *data, unsigned short size, int timeout);
|
||||
int usb_bulk_msg(struct usb_device *dev, unsigned int pipe,
|
||||
void *data, int len, int *actual_length, int timeout);
|
||||
int usb_submit_int_msg(struct usb_device *dev, unsigned long pipe,
|
||||
void *buffer, int transfer_len, int interval);
|
||||
void usb_disable_asynch(int disable);
|
||||
int usb_maxpacket(struct usb_device *dev, unsigned long pipe);
|
||||
inline void wait_ms(unsigned long ms);
|
||||
int usb_get_configuration_no(struct usb_device *dev, unsigned char *buffer,
|
||||
int cfgno);
|
||||
int usb_get_report(struct usb_device *dev, int ifnum, unsigned char type,
|
||||
unsigned char id, void *buf, int size);
|
||||
int usb_get_class_descriptor(struct usb_device *dev, int ifnum,
|
||||
unsigned char type, unsigned char id, void *buf,
|
||||
int size);
|
||||
int usb_clear_halt(struct usb_device *dev, int pipe);
|
||||
int usb_string(struct usb_device *dev, int idx, char *buf, size_t size);
|
||||
int usb_set_interface(struct usb_device *dev, int interface, int alternate);
|
||||
|
||||
/* big endian -> little endian conversion */
|
||||
/* some CPUs are already little endian e.g. the ARM920T */
|
||||
#define __swap_16(x) \
|
||||
({ unsigned short x_ = (unsigned short)x; \
|
||||
(unsigned short)( \
|
||||
((x_ & 0x00FFU) << 8) | ((x_ & 0xFF00U) >> 8)); \
|
||||
})
|
||||
#define __swap_32(x) \
|
||||
({ unsigned long x_ = (unsigned long)x; \
|
||||
(unsigned long)( \
|
||||
((x_ & 0x000000FFUL) << 24) | \
|
||||
((x_ & 0x0000FF00UL) << 8) | \
|
||||
((x_ & 0x00FF0000UL) >> 8) | \
|
||||
((x_ & 0xFF000000UL) >> 24)); \
|
||||
})
|
||||
|
||||
#ifdef __LITTLE_ENDIAN
|
||||
# define swap_16(x) (x)
|
||||
# define swap_32(x) (x)
|
||||
#else
|
||||
# define swap_16(x) __swap_16(x)
|
||||
# define swap_32(x) __swap_32(x)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Calling this entity a "pipe" is glorifying it. A USB pipe
|
||||
* is something embarrassingly simple: it basically consists
|
||||
* of the following information:
|
||||
* - device number (7 bits)
|
||||
* - endpoint number (4 bits)
|
||||
* - current Data0/1 state (1 bit)
|
||||
* - direction (1 bit)
|
||||
* - speed (2 bits)
|
||||
* - max packet size (2 bits: 8, 16, 32 or 64)
|
||||
* - pipe type (2 bits: control, interrupt, bulk, isochronous)
|
||||
*
|
||||
* That's 18 bits. Really. Nothing more. And the USB people have
|
||||
* documented these eighteen bits as some kind of glorious
|
||||
* virtual data structure.
|
||||
*
|
||||
* Let's not fall in that trap. We'll just encode it as a simple
|
||||
* unsigned int. The encoding is:
|
||||
*
|
||||
* - max size: bits 0-1 (00 = 8, 01 = 16, 10 = 32, 11 = 64)
|
||||
* - direction: bit 7 (0 = Host-to-Device [Out],
|
||||
* (1 = Device-to-Host [In])
|
||||
* - device: bits 8-14
|
||||
* - endpoint: bits 15-18
|
||||
* - Data0/1: bit 19
|
||||
* - speed: bit 26 (0 = Full, 1 = Low Speed, 2 = High)
|
||||
* - pipe type: bits 30-31 (00 = isochronous, 01 = interrupt,
|
||||
* 10 = control, 11 = bulk)
|
||||
*
|
||||
* Why? Because it's arbitrary, and whatever encoding we select is really
|
||||
* up to us. This one happens to share a lot of bit positions with the UHCI
|
||||
* specification, so that much of the uhci driver can just mask the bits
|
||||
* appropriately.
|
||||
*/
|
||||
/* Create various pipes... */
|
||||
#define create_pipe(dev,endpoint) \
|
||||
(((dev)->devnum << 8) | (endpoint << 15) | \
|
||||
((dev)->speed << 26) | (dev)->maxpacketsize)
|
||||
#define default_pipe(dev) ((dev)->speed << 26)
|
||||
|
||||
#define usb_sndctrlpipe(dev, endpoint) ((PIPE_CONTROL << 30) | \
|
||||
create_pipe(dev, endpoint))
|
||||
#define usb_rcvctrlpipe(dev, endpoint) ((PIPE_CONTROL << 30) | \
|
||||
create_pipe(dev, endpoint) | \
|
||||
USB_DIR_IN)
|
||||
#define usb_sndisocpipe(dev, endpoint) ((PIPE_ISOCHRONOUS << 30) | \
|
||||
create_pipe(dev, endpoint))
|
||||
#define usb_rcvisocpipe(dev, endpoint) ((PIPE_ISOCHRONOUS << 30) | \
|
||||
create_pipe(dev, endpoint) | \
|
||||
USB_DIR_IN)
|
||||
#define usb_sndbulkpipe(dev, endpoint) ((PIPE_BULK << 30) | \
|
||||
create_pipe(dev, endpoint))
|
||||
#define usb_rcvbulkpipe(dev, endpoint) ((PIPE_BULK << 30) | \
|
||||
create_pipe(dev, endpoint) | \
|
||||
USB_DIR_IN)
|
||||
#define usb_sndintpipe(dev, endpoint) ((PIPE_INTERRUPT << 30) | \
|
||||
create_pipe(dev, endpoint))
|
||||
#define usb_rcvintpipe(dev, endpoint) ((PIPE_INTERRUPT << 30) | \
|
||||
create_pipe(dev, endpoint) | \
|
||||
USB_DIR_IN)
|
||||
#define usb_snddefctrl(dev) ((PIPE_CONTROL << 30) | \
|
||||
default_pipe(dev))
|
||||
#define usb_rcvdefctrl(dev) ((PIPE_CONTROL << 30) | \
|
||||
default_pipe(dev) | \
|
||||
USB_DIR_IN)
|
||||
|
||||
/* The D0/D1 toggle bits */
|
||||
#define usb_gettoggle(dev, ep, out) (((dev)->toggle[out] >> ep) & 1)
|
||||
#define usb_dotoggle(dev, ep, out) ((dev)->toggle[out] ^= (1 << ep))
|
||||
#define usb_settoggle(dev, ep, out, bit) ((dev)->toggle[out] = \
|
||||
((dev)->toggle[out] & \
|
||||
~(1 << ep)) | ((bit) << ep))
|
||||
|
||||
/* Endpoint halt control/status */
|
||||
#define usb_endpoint_out(ep_dir) (((ep_dir >> 7) & 1) ^ 1)
|
||||
#define usb_endpoint_halt(dev, ep, out) ((dev)->halted[out] |= (1 << (ep)))
|
||||
#define usb_endpoint_running(dev, ep, out) ((dev)->halted[out] &= ~(1 << (ep)))
|
||||
#define usb_endpoint_halted(dev, ep, out) ((dev)->halted[out] & (1 << (ep)))
|
||||
|
||||
#define usb_packetid(pipe) (((pipe) & USB_DIR_IN) ? USB_PID_IN : \
|
||||
USB_PID_OUT)
|
||||
|
||||
#define usb_pipeout(pipe) ((((pipe) >> 7) & 1) ^ 1)
|
||||
#define usb_pipein(pipe) (((pipe) >> 7) & 1)
|
||||
#define usb_pipedevice(pipe) (((pipe) >> 8) & 0x7f)
|
||||
#define usb_pipe_endpdev(pipe) (((pipe) >> 8) & 0x7ff)
|
||||
#define usb_pipeendpoint(pipe) (((pipe) >> 15) & 0xf)
|
||||
#define usb_pipedata(pipe) (((pipe) >> 19) & 1)
|
||||
#define usb_pipespeed(pipe) (((pipe) >> 26) & 3)
|
||||
#define usb_pipeslow(pipe) (usb_pipespeed(pipe) == USB_SPEED_LOW)
|
||||
#define usb_pipetype(pipe) (((pipe) >> 30) & 3)
|
||||
#define usb_pipeisoc(pipe) (usb_pipetype((pipe)) == PIPE_ISOCHRONOUS)
|
||||
#define usb_pipeint(pipe) (usb_pipetype((pipe)) == PIPE_INTERRUPT)
|
||||
#define usb_pipecontrol(pipe) (usb_pipetype((pipe)) == PIPE_CONTROL)
|
||||
#define usb_pipebulk(pipe) (usb_pipetype((pipe)) == PIPE_BULK)
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
* Hub Stuff
|
||||
*/
|
||||
struct usb_port_status {
|
||||
unsigned short wPortStatus;
|
||||
unsigned short wPortChange;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct usb_hub_status {
|
||||
unsigned short wHubStatus;
|
||||
unsigned short wHubChange;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
|
||||
/* Hub descriptor */
|
||||
struct usb_hub_descriptor {
|
||||
unsigned char bLength;
|
||||
unsigned char bDescriptorType;
|
||||
unsigned char bNbrPorts;
|
||||
unsigned short wHubCharacteristics;
|
||||
unsigned char bPwrOn2PwrGood;
|
||||
unsigned char bHubContrCurrent;
|
||||
unsigned char DeviceRemovable[(USB_MAXCHILDREN+1+7)/8];
|
||||
unsigned char PortPowerCtrlMask[(USB_MAXCHILDREN+1+7)/8];
|
||||
/* DeviceRemovable and PortPwrCtrlMask want to be variable-length
|
||||
bitmaps that hold max 255 entries. (bit0 is ignored) */
|
||||
} __attribute__ ((packed));
|
||||
|
||||
|
||||
struct usb_hub_device {
|
||||
struct usb_device *pusb_dev;
|
||||
struct usb_hub_descriptor desc;
|
||||
};
|
||||
|
||||
#endif /*_USB_H_ */
|
||||
251
FireBee/trunk/usb/store/usb_defs.h
Normal file
251
FireBee/trunk/usb/store/usb_defs.h
Normal file
@@ -0,0 +1,251 @@
|
||||
/*
|
||||
* (C) Copyright 2001
|
||||
* Denis Peter, MPL AG Switzerland
|
||||
*
|
||||
* See file CREDITS for list of people who contributed to this
|
||||
* project.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Note: Part of this code has been derived from linux
|
||||
*
|
||||
*/
|
||||
#ifndef _USB_DEFS_H_
|
||||
#define _USB_DEFS_H_
|
||||
|
||||
/* USB constants */
|
||||
|
||||
/* Device and/or Interface Class codes */
|
||||
#define USB_CLASS_PER_INTERFACE 0 /* for DeviceClass */
|
||||
#define USB_CLASS_AUDIO 1
|
||||
#define USB_CLASS_COMM 2
|
||||
#define USB_CLASS_HID 3
|
||||
#define USB_CLASS_PRINTER 7
|
||||
#define USB_CLASS_MASS_STORAGE 8
|
||||
#define USB_CLASS_HUB 9
|
||||
#define USB_CLASS_DATA 10
|
||||
#define USB_CLASS_VENDOR_SPEC 0xff
|
||||
|
||||
/* some HID sub classes */
|
||||
#define USB_SUB_HID_NONE 0
|
||||
#define USB_SUB_HID_BOOT 1
|
||||
|
||||
/* some UID Protocols */
|
||||
#define USB_PROT_HID_NONE 0
|
||||
#define USB_PROT_HID_KEYBOARD 1
|
||||
#define USB_PROT_HID_MOUSE 2
|
||||
|
||||
|
||||
/* Sub STORAGE Classes */
|
||||
#define US_SC_RBC 1 /* Typically, flash devices */
|
||||
#define US_SC_8020 2 /* CD-ROM */
|
||||
#define US_SC_QIC 3 /* QIC-157 Tapes */
|
||||
#define US_SC_UFI 4 /* Floppy */
|
||||
#define US_SC_8070 5 /* Removable media */
|
||||
#define US_SC_SCSI 6 /* Transparent */
|
||||
#define US_SC_MIN US_SC_RBC
|
||||
#define US_SC_MAX US_SC_SCSI
|
||||
|
||||
/* STORAGE Protocols */
|
||||
#define US_PR_CB 1 /* Control/Bulk w/o interrupt */
|
||||
#define US_PR_CBI 0 /* Control/Bulk/Interrupt */
|
||||
#define US_PR_BULK 0x50 /* bulk only */
|
||||
|
||||
/* USB types */
|
||||
#define USB_TYPE_STANDARD (0x00 << 5)
|
||||
#define USB_TYPE_CLASS (0x01 << 5)
|
||||
#define USB_TYPE_VENDOR (0x02 << 5)
|
||||
#define USB_TYPE_RESERVED (0x03 << 5)
|
||||
|
||||
/* USB recipients */
|
||||
#define USB_RECIP_DEVICE 0x00
|
||||
#define USB_RECIP_INTERFACE 0x01
|
||||
#define USB_RECIP_ENDPOINT 0x02
|
||||
#define USB_RECIP_OTHER 0x03
|
||||
|
||||
/* USB directions */
|
||||
#define USB_DIR_OUT 0
|
||||
#define USB_DIR_IN 0x80
|
||||
|
||||
/* USB device speeds */
|
||||
#define USB_SPEED_FULL 0x0 /* 12Mbps */
|
||||
#define USB_SPEED_LOW 0x1 /* 1.5Mbps */
|
||||
#define USB_SPEED_HIGH 0x2 /* 480Mbps */
|
||||
#define USB_SPEED_RESERVED 0x3
|
||||
|
||||
/* Descriptor types */
|
||||
#define USB_DT_DEVICE 0x01
|
||||
#define USB_DT_CONFIG 0x02
|
||||
#define USB_DT_STRING 0x03
|
||||
#define USB_DT_INTERFACE 0x04
|
||||
#define USB_DT_ENDPOINT 0x05
|
||||
|
||||
#define USB_DT_HID (USB_TYPE_CLASS | 0x01)
|
||||
#define USB_DT_REPORT (USB_TYPE_CLASS | 0x02)
|
||||
#define USB_DT_PHYSICAL (USB_TYPE_CLASS | 0x03)
|
||||
#define USB_DT_HUB (USB_TYPE_CLASS | 0x09)
|
||||
|
||||
/* Descriptor sizes per descriptor type */
|
||||
#define USB_DT_DEVICE_SIZE 18
|
||||
#define USB_DT_CONFIG_SIZE 9
|
||||
#define USB_DT_INTERFACE_SIZE 9
|
||||
#define USB_DT_ENDPOINT_SIZE 7
|
||||
#define USB_DT_ENDPOINT_AUDIO_SIZE 9 /* Audio extension */
|
||||
#define USB_DT_HUB_NONVAR_SIZE 7
|
||||
#define USB_DT_HID_SIZE 9
|
||||
|
||||
/* Endpoints */
|
||||
#define USB_ENDPOINT_NUMBER_MASK 0x0f /* in bEndpointAddress */
|
||||
#define USB_ENDPOINT_DIR_MASK 0x80
|
||||
|
||||
#define USB_ENDPOINT_XFERTYPE_MASK 0x03 /* in bmAttributes */
|
||||
#define USB_ENDPOINT_XFER_CONTROL 0
|
||||
#define USB_ENDPOINT_XFER_ISOC 1
|
||||
#define USB_ENDPOINT_XFER_BULK 2
|
||||
#define USB_ENDPOINT_XFER_INT 3
|
||||
|
||||
/* USB Packet IDs (PIDs) */
|
||||
#define USB_PID_UNDEF_0 0xf0
|
||||
#define USB_PID_OUT 0xe1
|
||||
#define USB_PID_ACK 0xd2
|
||||
#define USB_PID_DATA0 0xc3
|
||||
#define USB_PID_UNDEF_4 0xb4
|
||||
#define USB_PID_SOF 0xa5
|
||||
#define USB_PID_UNDEF_6 0x96
|
||||
#define USB_PID_UNDEF_7 0x87
|
||||
#define USB_PID_UNDEF_8 0x78
|
||||
#define USB_PID_IN 0x69
|
||||
#define USB_PID_NAK 0x5a
|
||||
#define USB_PID_DATA1 0x4b
|
||||
#define USB_PID_PREAMBLE 0x3c
|
||||
#define USB_PID_SETUP 0x2d
|
||||
#define USB_PID_STALL 0x1e
|
||||
#define USB_PID_UNDEF_F 0x0f
|
||||
|
||||
/* Standard requests */
|
||||
#define USB_REQ_GET_STATUS 0x00
|
||||
#define USB_REQ_CLEAR_FEATURE 0x01
|
||||
#define USB_REQ_SET_FEATURE 0x03
|
||||
#define USB_REQ_SET_ADDRESS 0x05
|
||||
#define USB_REQ_GET_DESCRIPTOR 0x06
|
||||
#define USB_REQ_SET_DESCRIPTOR 0x07
|
||||
#define USB_REQ_GET_CONFIGURATION 0x08
|
||||
#define USB_REQ_SET_CONFIGURATION 0x09
|
||||
#define USB_REQ_GET_INTERFACE 0x0A
|
||||
#define USB_REQ_SET_INTERFACE 0x0B
|
||||
#define USB_REQ_SYNCH_FRAME 0x0C
|
||||
|
||||
/* HID requests */
|
||||
#define USB_REQ_GET_REPORT 0x01
|
||||
#define USB_REQ_GET_IDLE 0x02
|
||||
#define USB_REQ_GET_PROTOCOL 0x03
|
||||
#define USB_REQ_SET_REPORT 0x09
|
||||
#define USB_REQ_SET_IDLE 0x0A
|
||||
#define USB_REQ_SET_PROTOCOL 0x0B
|
||||
|
||||
|
||||
/* "pipe" definitions */
|
||||
|
||||
#define PIPE_ISOCHRONOUS 0
|
||||
#define PIPE_INTERRUPT 1
|
||||
#define PIPE_CONTROL 2
|
||||
#define PIPE_BULK 3
|
||||
#define PIPE_DEVEP_MASK 0x0007ff00
|
||||
|
||||
#define USB_ISOCHRONOUS 0
|
||||
#define USB_INTERRUPT 1
|
||||
#define USB_CONTROL 2
|
||||
#define USB_BULK 3
|
||||
|
||||
/* USB-status codes: */
|
||||
#define USB_ST_ACTIVE 0x1 /* TD is active */
|
||||
#define USB_ST_STALLED 0x2 /* TD is stalled */
|
||||
#define USB_ST_BUF_ERR 0x4 /* buffer error */
|
||||
#define USB_ST_BABBLE_DET 0x8 /* Babble detected */
|
||||
#define USB_ST_NAK_REC 0x10 /* NAK Received*/
|
||||
#define USB_ST_CRC_ERR 0x20 /* CRC/timeout Error */
|
||||
#define USB_ST_BIT_ERR 0x40 /* Bitstuff error */
|
||||
#define USB_ST_NOT_PROC 0x80000000L /* Not yet processed */
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
* Hub defines
|
||||
*/
|
||||
|
||||
/*
|
||||
* Hub request types
|
||||
*/
|
||||
|
||||
#define USB_RT_HUB (USB_TYPE_CLASS | USB_RECIP_DEVICE)
|
||||
#define USB_RT_PORT (USB_TYPE_CLASS | USB_RECIP_OTHER)
|
||||
|
||||
/*
|
||||
* Hub Class feature numbers
|
||||
*/
|
||||
#define C_HUB_LOCAL_POWER 0
|
||||
#define C_HUB_OVER_CURRENT 1
|
||||
|
||||
/*
|
||||
* Port feature numbers
|
||||
*/
|
||||
#define USB_PORT_FEAT_CONNECTION 0
|
||||
#define USB_PORT_FEAT_ENABLE 1
|
||||
#define USB_PORT_FEAT_SUSPEND 2
|
||||
#define USB_PORT_FEAT_OVER_CURRENT 3
|
||||
#define USB_PORT_FEAT_RESET 4
|
||||
#define USB_PORT_FEAT_POWER 8
|
||||
#define USB_PORT_FEAT_LOWSPEED 9
|
||||
#define USB_PORT_FEAT_HIGHSPEED 10
|
||||
#define USB_PORT_FEAT_C_CONNECTION 16
|
||||
#define USB_PORT_FEAT_C_ENABLE 17
|
||||
#define USB_PORT_FEAT_C_SUSPEND 18
|
||||
#define USB_PORT_FEAT_C_OVER_CURRENT 19
|
||||
#define USB_PORT_FEAT_C_RESET 20
|
||||
|
||||
/* wPortStatus bits */
|
||||
#define USB_PORT_STAT_CONNECTION 0x0001
|
||||
#define USB_PORT_STAT_ENABLE 0x0002
|
||||
#define USB_PORT_STAT_SUSPEND 0x0004
|
||||
#define USB_PORT_STAT_OVERCURRENT 0x0008
|
||||
#define USB_PORT_STAT_RESET 0x0010
|
||||
#define USB_PORT_STAT_POWER 0x0100
|
||||
#define USB_PORT_STAT_LOW_SPEED 0x0200
|
||||
#define USB_PORT_STAT_HIGH_SPEED 0x0400 /* support for EHCI */
|
||||
#define USB_PORT_STAT_SPEED \
|
||||
(USB_PORT_STAT_LOW_SPEED | USB_PORT_STAT_HIGH_SPEED)
|
||||
|
||||
/* wPortChange bits */
|
||||
#define USB_PORT_STAT_C_CONNECTION 0x0001
|
||||
#define USB_PORT_STAT_C_ENABLE 0x0002
|
||||
#define USB_PORT_STAT_C_SUSPEND 0x0004
|
||||
#define USB_PORT_STAT_C_OVERCURRENT 0x0008
|
||||
#define USB_PORT_STAT_C_RESET 0x0010
|
||||
|
||||
/* wHubCharacteristics (masks) */
|
||||
#define HUB_CHAR_LPSM 0x0003
|
||||
#define HUB_CHAR_COMPOUND 0x0004
|
||||
#define HUB_CHAR_OCPM 0x0018
|
||||
|
||||
/*
|
||||
*Hub Status & Hub Change bit masks
|
||||
*/
|
||||
#define HUB_STATUS_LOCAL_POWER 0x0001
|
||||
#define HUB_STATUS_OVERCURRENT 0x0002
|
||||
|
||||
#define HUB_CHANGE_LOCAL_POWER 0x0001
|
||||
#define HUB_CHANGE_OVERCURRENT 0x0002
|
||||
|
||||
#endif /*_USB_DEFS_H_ */
|
||||
220
FireBee/trunk/usb/store/usb_mem.c
Normal file
220
FireBee/trunk/usb/store/usb_mem.c
Normal file
@@ -0,0 +1,220 @@
|
||||
/*
|
||||
* usb_mem.c
|
||||
*
|
||||
* based from Emutos / BDOS
|
||||
*
|
||||
* Copyright (c) 2001 Lineo, Inc.
|
||||
*
|
||||
* Authors: Karl T. Braun, Martin Doering, Laurent Vogel
|
||||
*
|
||||
* This file is distributed under the GPL, version 2 or at your
|
||||
* option any later version.
|
||||
*/
|
||||
|
||||
#include <mint/errno.h>
|
||||
#include <mint/osbind.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifndef FALSE
|
||||
#define FALSE 0
|
||||
#endif
|
||||
#ifndef TRUE
|
||||
#define TRUE 1
|
||||
#endif
|
||||
|
||||
#define USB_BUFFER_SIZE 0x10000
|
||||
|
||||
static void *usb_buffer;
|
||||
|
||||
/* MD - Memory Descriptor */
|
||||
|
||||
#define MD struct _md_
|
||||
|
||||
MD
|
||||
{
|
||||
MD *m_link;
|
||||
long m_start;
|
||||
long m_length;
|
||||
};
|
||||
|
||||
/* MPB - Memory Partition Block */
|
||||
|
||||
#define MPB struct _mpb
|
||||
|
||||
MPB
|
||||
{
|
||||
MD *mp_mfl;
|
||||
MD *mp_mal;
|
||||
MD *mp_rover;
|
||||
};
|
||||
|
||||
#define MAXMD 100
|
||||
|
||||
static int count_md;
|
||||
static MD tab_md[MAXMD];
|
||||
static MPB pmd;
|
||||
|
||||
static MD *ffit(long amount, MPB *mp)
|
||||
{
|
||||
MD *p,*q,*p1; /* free list is composed of MD's */
|
||||
int maxflg;
|
||||
long maxval;
|
||||
if(amount != -1)
|
||||
{
|
||||
amount += 15; /* 16 bytes alignment */
|
||||
amount &= 0xFFFFFFF0;
|
||||
}
|
||||
if((q = mp->mp_rover) == 0) /* get rotating pointer */
|
||||
return(0) ;
|
||||
maxval = 0;
|
||||
maxflg = (amount == -1 ? TRUE : FALSE) ;
|
||||
p = q->m_link; /* start with next MD */
|
||||
do /* search the list for an MD with enough space */
|
||||
{
|
||||
if(p == 0)
|
||||
{
|
||||
/* at end of list, wrap back to start */
|
||||
q = (MD *) &mp->mp_mfl; /* q => mfl field */
|
||||
p = q->m_link; /* p => 1st MD */
|
||||
}
|
||||
if((!maxflg) && (p->m_length >= amount))
|
||||
{
|
||||
/* big enough */
|
||||
if(p->m_length == amount)
|
||||
q->m_link = p->m_link; /* take the whole thing */
|
||||
else
|
||||
{
|
||||
/* break it up - 1st allocate a new
|
||||
MD to describe the remainder */
|
||||
if(count_md >= MAXMD)
|
||||
return(0);
|
||||
p1 = &tab_md[count_md++];
|
||||
/* init new MD */
|
||||
p1->m_length = p->m_length - amount;
|
||||
p1->m_start = p->m_start + amount;
|
||||
p1->m_link = p->m_link;
|
||||
p->m_length = amount; /* adjust allocated block */
|
||||
q->m_link = p1;
|
||||
}
|
||||
/* link allocate block into allocated list,
|
||||
mark owner of block, & adjust rover */
|
||||
p->m_link = mp->mp_mal;
|
||||
mp->mp_mal = p;
|
||||
mp->mp_rover = (q == (MD *) &mp->mp_mfl ? q->m_link : q);
|
||||
return(p); /* got some */
|
||||
}
|
||||
else if(p->m_length > maxval)
|
||||
maxval = p->m_length;
|
||||
p = ( q=p )->m_link;
|
||||
}
|
||||
while(q != mp->mp_rover);
|
||||
/* return either the max, or 0 (error) */
|
||||
if(maxflg)
|
||||
{
|
||||
maxval -= 15; /* 16 bytes alignment */
|
||||
if(maxval < 0)
|
||||
maxval = 0;
|
||||
else
|
||||
maxval &= 0xFFFFFFF0;
|
||||
}
|
||||
return(maxflg ? (MD *) maxval : 0);
|
||||
}
|
||||
|
||||
static void freeit(MD *m, MPB *mp)
|
||||
{
|
||||
MD *p, *q;
|
||||
q = 0;
|
||||
for(p = mp->mp_mfl; p ; p = (q=p) -> m_link)
|
||||
{
|
||||
if(m->m_start <= p->m_start)
|
||||
break;
|
||||
}
|
||||
m->m_link = p;
|
||||
if(q)
|
||||
q->m_link = m;
|
||||
else
|
||||
mp->mp_mfl = m;
|
||||
if(!mp->mp_rover)
|
||||
mp->mp_rover = m;
|
||||
if(p)
|
||||
{
|
||||
if(m->m_start + m->m_length == p->m_start)
|
||||
{ /* join to higher neighbor */
|
||||
m->m_length += p->m_length;
|
||||
m->m_link = p->m_link;
|
||||
if(p == mp->mp_rover)
|
||||
mp->mp_rover = m;
|
||||
if(count_md>=0)
|
||||
count_md--;
|
||||
}
|
||||
}
|
||||
if(q)
|
||||
{
|
||||
if(q->m_start + q->m_length == m->m_start)
|
||||
{ /* join to lower neighbor */
|
||||
q->m_length += m->m_length;
|
||||
q->m_link = m->m_link;
|
||||
if(m == mp->mp_rover)
|
||||
mp->mp_rover = q;
|
||||
if(count_md>=0)
|
||||
count_md--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int usb_free(void *addr)
|
||||
{
|
||||
MD *p,**q;
|
||||
MPB *mpb;
|
||||
mpb = &pmd;
|
||||
if(usb_buffer == NULL)
|
||||
return(EFAULT);
|
||||
for(p = *(q = &mpb->mp_mal); p; p = *(q = &p->m_link))
|
||||
{
|
||||
if((long)addr == p->m_start)
|
||||
break;
|
||||
}
|
||||
if(!p)
|
||||
return(EFAULT);
|
||||
*q = p->m_link;
|
||||
freeit(p,mpb);
|
||||
return(0);
|
||||
}
|
||||
|
||||
void *usb_malloc(long amount)
|
||||
{
|
||||
MD *m;
|
||||
if(usb_buffer == NULL)
|
||||
return(NULL);
|
||||
if(amount == -1L)
|
||||
return((void *)ffit(-1L,&pmd));
|
||||
if(amount <= 0 )
|
||||
return(0);
|
||||
if((amount & 1))
|
||||
amount++;
|
||||
m = ffit(amount,&pmd);
|
||||
if(m == NULL)
|
||||
return(NULL);
|
||||
return((void *)m->m_start);
|
||||
}
|
||||
|
||||
int usb_mem_init(void)
|
||||
{
|
||||
usb_buffer = (void *)Mxalloc(USB_BUFFER_SIZE + 16, 0); /* STRAM - cache in writethough */
|
||||
if(usb_buffer == NULL)
|
||||
return(-1);
|
||||
pmd.mp_mfl = pmd.mp_rover = &tab_md[0];
|
||||
tab_md[0].m_link = (MD *)NULL;
|
||||
tab_md[0].m_start = ((long)usb_buffer + 15) & ~15;
|
||||
tab_md[0].m_length = USB_BUFFER_SIZE;
|
||||
pmd.mp_mal = (MD *)NULL;
|
||||
count_md = 1;
|
||||
return(0);
|
||||
}
|
||||
|
||||
void usb_mem_stop(void)
|
||||
{
|
||||
if(usb_buffer != NULL)
|
||||
Mfree(usb_buffer);
|
||||
}
|
||||
|
||||
1632
FireBee/trunk/usb/store/usb_storage.c
Normal file
1632
FireBee/trunk/usb/store/usb_storage.c
Normal file
File diff suppressed because it is too large
Load Diff
83
FireBee/trunk/usb/store/vars.h
Normal file
83
FireBee/trunk/usb/store/vars.h
Normal file
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* Modified by David Gálvez 2010.
|
||||
*
|
||||
* TOS 4.04 Xbios vars for the CT60 board
|
||||
* Didier Mequignon 2002-2005, e-mail: aniplay@wanadoo.fr
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _VARS_H
|
||||
#define _VARS_H
|
||||
|
||||
|
||||
#define etv_timer 0x400
|
||||
#define etv_critic 0x404
|
||||
#define memvalid 0x420
|
||||
#define memctrl 0x424
|
||||
#define resvalid 0x426
|
||||
#define resvector 0x42A
|
||||
#define phystop 0x42E
|
||||
#define _memtop 0x436
|
||||
#define memval2 0x43A
|
||||
#define flock 0x43E
|
||||
#define _timer_ms 0x442
|
||||
#define _bootdev 0x446
|
||||
#define sshiftmd 0x44C
|
||||
#define _v_bas_ad 0x44E
|
||||
#define vblsem 0x452
|
||||
#define nvbls 0x454
|
||||
#define _vblqueue 0x456
|
||||
#define colorptr 0x45A
|
||||
#define _vbclock 0x462
|
||||
#define _frclock 0x466
|
||||
#define hdv_init 0x46A
|
||||
#define HDV_BPB 0x472
|
||||
#define hdv_bpb 0x472
|
||||
#define HDV_RW 0x476
|
||||
#define hdv_rw 0x476
|
||||
#define hdv_boot 0x47A
|
||||
#define HDV_MEDIACH 0x47E
|
||||
#define hdv_mediach 0x47E
|
||||
#define _cmdload 0x482
|
||||
#define conterm 0x484
|
||||
#define trp14ret 0x486
|
||||
#define __md 0x49E
|
||||
#define savptr 0x4A2
|
||||
#define _nflops 0x4A6
|
||||
#define con_state 0x4A8
|
||||
#define save_row 0x4AC
|
||||
#define _hz_200 0x4BA
|
||||
#define _DRVBITS 0x4C2
|
||||
#define _drvbits 0x4C2
|
||||
#define DSKBUFP 0x4C6
|
||||
#define _dskbufp 0x4C6
|
||||
#define _dumpflg 0x4EE
|
||||
#define _sysbase 0x4F2
|
||||
#define exec_os 0x4FE
|
||||
#define dump_vec 0x502
|
||||
#define ptr_stat 0x506
|
||||
#define ptr_vec 0x50A
|
||||
#define aux_sta 0x50E
|
||||
#define aux_vec 0x512
|
||||
#define PUN_PTR 0x516
|
||||
#define memval3 0x51A
|
||||
#define proc_type 0x59E
|
||||
#define COOKIE 0x5A0
|
||||
#define cookie 0x5A0
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
391
FireBee/trunk/usb/store/xhdi.c
Normal file
391
FireBee/trunk/usb/store/xhdi.c
Normal file
@@ -0,0 +1,391 @@
|
||||
/***************** NOT READY YET ***********************/
|
||||
/**************** ONLY EXPERIMENTAL ********************/
|
||||
|
||||
/* TOS 4.04 Xbios dispatcher for the CT60/CTPCI boards
|
||||
* and USB-disk / Ram-Disk utility
|
||||
* Didier Mequignon 2005-2009, e-mail: aniplay@wanadoo.fr
|
||||
*
|
||||
* Translation to C by David Galvez. 2010, e-mail: dgalvez75@gmail.com
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This file is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <mint/osbind.h>
|
||||
|
||||
#include "config.h"
|
||||
#include "vars.h"
|
||||
#include "xhdi.h"
|
||||
#include "debug.h"
|
||||
|
||||
long *drvbits = (long *)_DRVBITS;
|
||||
|
||||
struct pun_info *old_pun_ptr = (struct pun_info *)0x512;
|
||||
struct usb_pun_info pun_ptr_usb;
|
||||
|
||||
XBRA xbra_hdv_bpb;
|
||||
XBRA xbra_hdv_rw;
|
||||
XBRA xbra_hdv_mediach;
|
||||
|
||||
extern long usb_1st_disk_drive;
|
||||
extern short max_logical_drive;
|
||||
|
||||
extern unsigned long usb_stor_read(int device, unsigned long blknr, unsigned long blkcnt, void *buffer);
|
||||
|
||||
void drive_full_usb(void)
|
||||
{
|
||||
DEBUG_XHDI("\n");
|
||||
}
|
||||
|
||||
long __CDECL hdv_bpb_usb(void)
|
||||
{
|
||||
unsigned short dev;
|
||||
long r;
|
||||
|
||||
__asm__ volatile /* get arguments from the stack */
|
||||
(
|
||||
"move.w 12(%%sp),%0\n\t"
|
||||
|
||||
:/*outputs*/ "=m" (dev)
|
||||
:/*inputs*/
|
||||
);
|
||||
|
||||
__asm__ volatile /* call old vector */
|
||||
(
|
||||
"movem.l %%d2-%%d7/%%a2-%%a6,-(%%sp)\n\t" /* important to save register */
|
||||
"move.l %1,%%a0\n\t"
|
||||
"move.w #0,-(%%sp)\n\t"
|
||||
"move.w %2,-(%%sp)\n\t"
|
||||
"jsr (%%a0)\n\t"
|
||||
"addq.l #4,%%sp\n\t"
|
||||
"move.l %%d0,%0\n\t"
|
||||
"movem.l (%%sp)+,%%d2-%%d7/%%a2-%%a6\n\t"
|
||||
:/*outputs*/ "=r" (r)
|
||||
:/*inputs*/ "m" (xbra_hdv_bpb.xb_oldvec), "m" (dev)
|
||||
:"d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "a2", "a3", "a4", "a5" /*clobbered regs*/
|
||||
);
|
||||
return r;
|
||||
}
|
||||
|
||||
long __CDECL hdv_rw_usb(void)
|
||||
{
|
||||
void *buf;
|
||||
short count, recno, dev, mode;
|
||||
long lrecno;
|
||||
|
||||
long r = 0;
|
||||
|
||||
__asm__ volatile /* get arguments from the stack */
|
||||
(
|
||||
"move.l 18(%%sp),%0\n\t"
|
||||
"move.w 14(%%sp),%1\n\t"
|
||||
"move.w 12(%%sp),%2\n\t"
|
||||
"move.w 10(%%sp),%3\n\t"
|
||||
"move.l 8(%%sp),%4\n\t"
|
||||
"move.w 4(%%sp),%5\n\t"
|
||||
:/*outputs*/ "=r" (lrecno), "=r" (dev) ,"=r" (recno), "=r" (count), "=r" (buf), "=r" (mode)
|
||||
:/*inputs*/
|
||||
);
|
||||
|
||||
DEBUG_XHDI("lrecno %lx dev %d recno %x count %d mode %x\n",
|
||||
lrecno, dev, recno, count, mode);
|
||||
|
||||
DEBUG_XHDI("\n");
|
||||
DEBUG_XHDI("rw\n");
|
||||
|
||||
__asm__ volatile /* call old vector */
|
||||
(
|
||||
"movem.l %%d2-%%d7/%%a2-%%a6,-(%%sp)\n\t"
|
||||
"move.l %1,%%a0\n\t"
|
||||
"move.l (%%a0),%%d0\n\t"
|
||||
"move.w #0,-(%%sp)\n\t"
|
||||
"move.l %2,-(%%sp)\n\t"
|
||||
"move.w %3,-(%%sp)\n\t"
|
||||
"move.w %4,-(%%sp)\n\t"
|
||||
"move.w %5,-(%%sp)\n\t"
|
||||
"move.l %6,-(%%sp)\n\t"
|
||||
"move.w %7,-(%%sp)\n\t"
|
||||
"move.l %%d0,%%a0\n\t"
|
||||
"jsr (%%a0)\n\t"
|
||||
"addq.l #4,%%sp\n\t"
|
||||
"move.l %%d0,%0\n\t"
|
||||
"movem.l (%%sp)+,%%d2-%%d7/%%a2-%%a6\n\t"
|
||||
:/*outputs*/ "=r" (r)
|
||||
:/*inputs*/ "r" (xbra_hdv_rw.xb_oldvec), "r" (lrecno), "r" (dev) ,"r" (recno), "r" (count), "r" (buf), "r" (mode)
|
||||
:"d0"/*, "d1", "d2", "d3", "d4", "d5", "d6", "d7", "a2", "a3", "a4", "a5" clobbered regs*/
|
||||
);
|
||||
|
||||
// r = (*xbra_hdv_rw.xb_oldvec)(mode, buf, num, recno, dev, l);
|
||||
DEBUG_XHDI (" r %lx \n", r);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
long __CDECL hdv_mediach_usb(void)
|
||||
{
|
||||
DEBUG_XHDI("\n");
|
||||
DEBUG_XHDI("mediach\n");
|
||||
|
||||
short dev, dev1, dev2;
|
||||
long r;
|
||||
|
||||
__asm__ volatile /* get arguments from the stack */
|
||||
(
|
||||
"move.w 2(%%sp),%0\n\t"
|
||||
"move.w 4(%%sp),%1\n\t"
|
||||
"move.w 6(%%sp),%2\n\t"
|
||||
:/*outputs*/ "=r" (dev), "=r" (dev1), "=r" (dev2)
|
||||
:/*inputs*/
|
||||
);
|
||||
|
||||
DEBUG_XHDI (" dev(2) %x dev(4) %x dev(6) %x\n", dev, dev1, dev2);
|
||||
|
||||
__asm__ volatile /* call old vector */
|
||||
(
|
||||
"movem.l %%d2-%%d7/%%a2-%%a6,-(%%sp)\n\t"
|
||||
"move.l %1,%%a0\n\t"
|
||||
"move.l (%%a0),%%d0\n\t"
|
||||
"move.w #0,-(%%sp)\n\t"
|
||||
"move.w %2,-(%%sp)\n\t"
|
||||
"move.l %%d0,%%a0\n\t"
|
||||
"jsr (%%a0)\n\t"
|
||||
"addq.l #4,%%sp\n\t"
|
||||
"move.l %%d0,%0\n\t"
|
||||
"movem.l (%%sp)+,%%d2-%%d7/%%a2-%%a6\n\t"
|
||||
:/*outputs*/ "=r" (r)
|
||||
:/*inputs*/ "r" (xbra_hdv_mediach.xb_oldvec), "r" (dev)
|
||||
:"d0"/*, "d1", "d2", "d3", "d4", "d5", "d6", "d7", "a2", "a3", "a4", "a5" clobbered regs*/
|
||||
);
|
||||
// printf (" r %lx \n", r);
|
||||
// r = (*xbra_hdv_mediach.xb_oldvec)(d);
|
||||
// DEBUG_XHDI("Calling vector: %x\n", xbra_hdv_mediach.xb_oldvec);
|
||||
// r = (*xbra_hdv_mediach.xb_oldvec)(5);
|
||||
DEBUG_XHDI(" r %lx \n", r);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
void install_xbra(XBRA *xbra_hd, long id, long old_vec, long (*handle)())
|
||||
{
|
||||
DEBUG_XHDI("\n");
|
||||
#define XBRA_MAGIC 0x58425241L /* "XBRA" */
|
||||
#define JMP_OPCODE 0x4EF9
|
||||
|
||||
xbra_hd->xb_magic = XBRA_MAGIC;
|
||||
xbra_hd->xb_id = id;
|
||||
xbra_hd->xb_oldvec = *((Func *)old_vec);
|
||||
xbra_hd->jump = JMP_OPCODE;
|
||||
xbra_hd->handle = (Func) handle;
|
||||
|
||||
*((Func *)old_vec) = xbra_hd->handle;
|
||||
|
||||
DEBUG_XHDI("id: %x xbra_hd->xb_oldvec %x old_vec %x old_vec (*) %x old_vec (&) %x\n",
|
||||
xbra_hd->xb_id, xbra_hd->xb_oldvec, old_vec, *((Func *)old_vec), &old_vec);
|
||||
|
||||
__asm__ volatile /* clean cache ??? */
|
||||
(
|
||||
"cpusha BC\n\t"
|
||||
:/*outputs*/
|
||||
:/*inputs*/
|
||||
);
|
||||
}
|
||||
|
||||
void usb_drive_ok(void)
|
||||
{
|
||||
DEBUG_XHDI("\n");
|
||||
|
||||
}
|
||||
|
||||
|
||||
long install_usb_partition(unsigned char drive, int dev_num, unsigned long part_type,
|
||||
unsigned long part_offset, unsigned long part_size)
|
||||
{
|
||||
DEBUG_XHDI("\n");
|
||||
|
||||
int *dskbufp = (int *)DSKBUFP;
|
||||
unsigned short status_register;
|
||||
|
||||
long old_hdv_bpb;
|
||||
long old_hdv_rw;
|
||||
long old_hdv_mediach;
|
||||
|
||||
if (drive < 16) {
|
||||
(pun_ptr_usb.puns)++;
|
||||
pun_ptr_usb.pun[drive] = dev_num | PUN_USB;
|
||||
pun_ptr_usb.pstart[drive] = part_offset;
|
||||
pun_ptr_usb.ptype[drive] = part_type;
|
||||
pun_ptr_usb.psize[drive] = part_size;
|
||||
/* flags B15:swap, B7:change, B0:bootable */
|
||||
#define BOOTABLE 0x0001
|
||||
#define CHANGE 0x0080
|
||||
#define SWAP 0x8000
|
||||
pun_ptr_usb.flags[drive] = CHANGE;
|
||||
}
|
||||
|
||||
if (drive < 16) {
|
||||
old_pun_ptr->puns++;
|
||||
old_pun_ptr->pun[drive] = dev_num | PUN_USB;
|
||||
}
|
||||
|
||||
if (usb_stor_read (dev_num, part_offset, 1, (void *)(*dskbufp)) == 0)
|
||||
return -1;
|
||||
|
||||
if (usb_1st_disk_drive)
|
||||
usb_drive_ok();
|
||||
|
||||
usb_1st_disk_drive = drive;
|
||||
|
||||
long r;
|
||||
r = (long)Getbpb (2);
|
||||
DEBUG_XHDI("Before int. Getbpb return: %x \n", r);
|
||||
|
||||
|
||||
__asm__ volatile /* mask interrupts */
|
||||
(
|
||||
"move.w %%sr,%%d0\n\t"
|
||||
"move.w %%d0,%0\n\t"
|
||||
"or.l #0x700,%%d0\n\t"
|
||||
"move.w %%d0,%%sr\n\t"
|
||||
:/*outputs*/ "=r" (status_register)
|
||||
:/*inputs*/
|
||||
:"d0" /*clobbered regs*/
|
||||
);
|
||||
|
||||
#define _USB 0x5F555342 /* _USB */
|
||||
long id = _USB;
|
||||
old_hdv_bpb = (long)HDV_BPB;
|
||||
|
||||
DEBUG_XHDI("id: %x old_hdv_bpb %x old_hdv_bpb (*) %x hdv_bpb_usb %x\n",
|
||||
id, old_hdv_bpb, *((Func *)old_hdv_bpb), hdv_bpb_usb);
|
||||
install_xbra(&xbra_hdv_bpb, id, old_hdv_bpb, hdv_bpb_usb);
|
||||
DEBUG_XHDI("id: %x old_hdv_bpb %x old_hdv_bpb (*) %x hdv_bpb_usb %x\n",
|
||||
xbra_hdv_bpb.xb_id, xbra_hdv_bpb.xb_oldvec, *((Func *)xbra_hdv_bpb.xb_oldvec), xbra_hdv_bpb.handle);
|
||||
#if 0
|
||||
old_hdv_rw = (long)HDV_RW;
|
||||
DEBUG_XHDI("id: %x old_hdv_rw %x old_hdv_rw (*) %x hdv_rw_usb %x\n",
|
||||
id, old_hdv_rw, *((Func *)old_hdv_rw), hdv_rw_usb);
|
||||
install_xbra(&xbra_hdv_rw, id, old_hdv_rw, hdv_rw_usb);
|
||||
DEBUG_XHDI("id: %x old_hdv_rw %x old_hdv_rw (*) %x hdv_rw_usb %x\n",
|
||||
xbra_hdv_rw.xb_id, xbra_hdv_rw.xb_oldvec, *((Func *)xbra_hdv_rw.xb_oldvec), xbra_hdv_rw.handle);
|
||||
|
||||
old_hdv_mediach = (long)HDV_MEDIACH;
|
||||
DEBUG_XHDI("id: %x old_hdv_mediach %x old_hdv_mediach (*) %x hdv_mediach_usb %x\n",
|
||||
id, old_hdv_mediach, *((Func *)old_hdv_mediach), hdv_mediach_usb);
|
||||
install_xbra(&xbra_hdv_mediach, id, old_hdv_mediach, hdv_mediach_usb);
|
||||
DEBUG_XHDI("id: %x old_hdv_mediach %x old_hdv_mediach (*) %x hdv_mediach_usb %x\n",
|
||||
xbra_hdv_mediach.xb_id, xbra_hdv_mediach.xb_oldvec, *((Func *)xbra_hdv_mediach.xb_oldvec), xbra_hdv_mediach.handle);
|
||||
#endif
|
||||
|
||||
r = (long)Getbpb (4);
|
||||
|
||||
DEBUG_XHDI("Before int. Getbpb return: %x \n", r);
|
||||
|
||||
// Bconin(DEV_CONSOLE);
|
||||
__asm__ volatile /* restore interrupts */
|
||||
(
|
||||
"move.w %%sr,%%d0\n\t"
|
||||
"and.w %0,%%d0\n\t"
|
||||
"move.w %%d0,%%sr\n\t"
|
||||
:/*outputs*/
|
||||
:/*inputs*/ "r" (status_register)
|
||||
:"d0"
|
||||
);
|
||||
DEBUG_XHDI("after restore interrups\n");
|
||||
// Bconin(DEV_CONSOLE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned char search_empty_drive(int dev_num, unsigned long part_type,
|
||||
unsigned long part_offset, unsigned long part_size)
|
||||
{
|
||||
DEBUG_XHDI("\n");
|
||||
|
||||
unsigned char drive = 2;
|
||||
|
||||
DEBUG_XHDI("drvbits: %x\n", *drvbits);
|
||||
while (drive < MAX_LOGICAL_DRIVE) {
|
||||
if (!(*drvbits & (0x00000001 << drive))) {
|
||||
DEBUG_XHDI("drive: %d\n", drive);
|
||||
if (install_usb_partition(drive, dev_num, part_type, part_offset, part_size) == -1) {
|
||||
DEBUG_XHDI("Couldn't install USB partition\n");
|
||||
return -1;
|
||||
}
|
||||
else return drive;
|
||||
}
|
||||
drive++;
|
||||
}
|
||||
printf("all drives already used!\n\r");
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
unsigned char add_partition(int dev_num, unsigned long part_type,
|
||||
unsigned long part_offset, unsigned long part_size)
|
||||
{
|
||||
DEBUG_XHDI("\n");
|
||||
|
||||
unsigned char i;
|
||||
unsigned char drive;
|
||||
|
||||
pun_ptr_usb.puns = 0x0000;
|
||||
pun_ptr_usb.version_num = 0x0300;
|
||||
pun_ptr_usb.max_sect_siz = 0x4000;
|
||||
|
||||
for (i=0; i<16; i++)
|
||||
pun_ptr_usb.pun[i] = 0xff;
|
||||
|
||||
if ((drive = search_empty_drive(dev_num, part_type, part_offset, part_size)) == -1)
|
||||
return -1;
|
||||
return drive;
|
||||
}
|
||||
|
||||
int install_usb_stor(int dev_num, unsigned long part_type,
|
||||
unsigned long part_offset, unsigned long part_size,
|
||||
char *vendor, char *revision, char *product )
|
||||
{
|
||||
DEBUG_XHDI("\n");
|
||||
unsigned char part_num;
|
||||
|
||||
if (dev_num <= PUN_DEV) { /* Max. of 32 USB storage devices */
|
||||
switch (part_type) { /* Although real limit is 16 of pinfo struct */
|
||||
case GEM:
|
||||
break;
|
||||
case BGM:
|
||||
break;
|
||||
case RAW:
|
||||
break;
|
||||
case FAT16_32MB:
|
||||
break;
|
||||
case FAT16:
|
||||
break;
|
||||
case FAT16_WIN95:
|
||||
break;
|
||||
case FAT32:
|
||||
break;
|
||||
case FAT32_II:
|
||||
break;
|
||||
default:
|
||||
printf("Invalid partition type (0x%08lx)\r\n", part_type);
|
||||
return -1;
|
||||
}
|
||||
if ((part_num = add_partition(dev_num, part_type, part_offset, part_size)) == -1)
|
||||
return -1;
|
||||
else return 0;
|
||||
}
|
||||
printf("Maxim number(%d) of USB storage device reached \n\r", dev_num);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
101
FireBee/trunk/usb/store/xhdi.h
Normal file
101
FireBee/trunk/usb/store/xhdi.h
Normal file
@@ -0,0 +1,101 @@
|
||||
/*
|
||||
* David Galvez. 2010, e-mail: dgalvez75@gmail.com
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This file is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _XHDI_H
|
||||
#define _XHDI_H
|
||||
|
||||
typedef long __CDECL (*Func)();
|
||||
|
||||
//#define old_pun_ptr 0x516
|
||||
|
||||
#undef PUN_PTR
|
||||
//#define pun_ptr pun_ptr_usb
|
||||
|
||||
#define MAX_LOGICAL_DRIVE max_logical_drive
|
||||
|
||||
/* AHDI */
|
||||
|
||||
#define PUN_DEV 0x1F /* device number of HD */
|
||||
#define PUN_UNIT 0x07 /* Unit number */
|
||||
#define PUN_SCSI 0x08 /* 1=SCSI 0=ACSI */
|
||||
#define PUN_IDE 0x10 /* Falcon IDE */
|
||||
#define PUN_USB 0x20 /* USB */
|
||||
#define PUN_REMOVABLE 0x40 /* Removable media */
|
||||
#define PUN_VALID 0x80 /* zero if valid */
|
||||
|
||||
#define PINFO_PUNS 0 // 2 bytes
|
||||
#define PINFO_PUN 2 // 16 bytes
|
||||
#define PINFO_PSTART 18 // 16 x 4 bytes
|
||||
#define PINFO_COOKIE 82 // 4 bytes
|
||||
#define PINFO_COOKPTR 86 // 4 bytes
|
||||
#define PINFO_VERNUM 90 // 2 bytes
|
||||
#define PINFO_MAXSIZE 92 // 2 bytes
|
||||
#define PINFO_PTYPE 94 // 16 x 4 bytes
|
||||
#define PINFO_PSIZE 158 // 16 x 4 bytes
|
||||
#define PINFO_FLAGS 222 // 16 x 2 bytes, internal use: B15:swap, B7:change, B0:bootable
|
||||
#define PINFO_BPB 256 // 16 x 32 bytes
|
||||
#define PINFO_SIZE 768
|
||||
|
||||
struct pun_info
|
||||
{
|
||||
short puns; /* Number of HD's */
|
||||
char pun [16]; /* AND with masks below: */
|
||||
long pstart [16];
|
||||
long cookie; /* 'AHDI' if following valid */
|
||||
long *cook_ptr; /* Points to 'cookie' */
|
||||
unsigned short version_num; /* AHDI version */
|
||||
unsigned short max_sect_siz; /* Max logical sec size */
|
||||
long reserved[16]; /* Reserved */
|
||||
};
|
||||
|
||||
struct usb_pun_info
|
||||
{
|
||||
short puns; /* Number of HD's */
|
||||
char pun [16]; /* AND with masks below: */
|
||||
long pstart [16];
|
||||
long cookie; /* 'AHDI' if following valid */
|
||||
long *cook_ptr; /* Points to 'cookie' */
|
||||
unsigned short version_num; /* AHDI version */
|
||||
unsigned short max_sect_siz; /* Max logical sec size */
|
||||
long reserved[16]; /* Reserved */
|
||||
long ptype[16];
|
||||
long psize[16];
|
||||
unsigned short flags[16];
|
||||
};
|
||||
|
||||
/* PARTITIONS TYPES */
|
||||
#define GEM 0x47454D // GEM up to 16 MB
|
||||
#define BGM 0x42474D // BGM over 16 MB
|
||||
#define RAW 0x524157 // RAW
|
||||
#define FAT16_32MB 0x4 // DOS FAT16 up to 32 MB
|
||||
#define FAT16 0x6 // DOS FAT16 over 32 MB
|
||||
#define FAT16_WIN95 0xE // WIN95 FAT16
|
||||
#define FAT32 0xB // FAT32
|
||||
#define FAT32_II 0xC // FAT32
|
||||
|
||||
typedef struct xbra XBRA;
|
||||
struct xbra {
|
||||
long xb_magic; /* "XBRA" = 0x58425241 */
|
||||
long xb_id; /* ID of four ASCII characters */
|
||||
Func xb_oldvec; /* Old value of the vectors */
|
||||
short jump;
|
||||
Func handle;
|
||||
};
|
||||
|
||||
|
||||
#endif /* _XHDI_H */
|
||||
6
FireBee/trunk/vhdl/dsp56k/asm/asm.sh
Normal file
6
FireBee/trunk/vhdl/dsp56k/asm/asm.sh
Normal file
@@ -0,0 +1,6 @@
|
||||
#!/bin/bash
|
||||
export DSP_PATH=~/.wine/drive_c/Programme/Motorola/DSP56300/clas
|
||||
|
||||
wine $DSP_PATH/asm56300.exe -b -g -l $1.asm
|
||||
wine $DSP_PATH/dsplnk.exe $1.cln
|
||||
wine $DSP_PATH/cldlod.exe $1.cld > $1.lod
|
||||
13
FireBee/trunk/vhdl/dsp56k/asm/test_agu/test.asm
Normal file
13
FireBee/trunk/vhdl/dsp56k/asm/test_agu/test.asm
Normal file
@@ -0,0 +1,13 @@
|
||||
|
||||
move #1,n1
|
||||
move #10,r1
|
||||
nop
|
||||
move (r1)+n1
|
||||
move #15,m1
|
||||
rep #10
|
||||
move (r1)+n1
|
||||
move #10,n1
|
||||
rep #10
|
||||
move (r1)+n1
|
||||
|
||||
|
||||
12
FireBee/trunk/vhdl/dsp56k/asm/test_alu/test_abs.asm
Normal file
12
FireBee/trunk/vhdl/dsp56k/asm/test_alu/test_abs.asm
Normal file
@@ -0,0 +1,12 @@
|
||||
|
||||
; clear CCR
|
||||
andi #$00,CCR
|
||||
move #>0.25,a
|
||||
abs a
|
||||
move #>-0.25,a
|
||||
abs a
|
||||
move #>0,a
|
||||
abs a
|
||||
move #>$80,a2
|
||||
abs a
|
||||
|
||||
11
FireBee/trunk/vhdl/dsp56k/asm/test_alu/test_adc.asm
Normal file
11
FireBee/trunk/vhdl/dsp56k/asm/test_alu/test_adc.asm
Normal file
@@ -0,0 +1,11 @@
|
||||
move #>0,y0
|
||||
move #>1,y1
|
||||
clr b
|
||||
move #>1,b0
|
||||
; set only carry bit
|
||||
andi #$00,ccr
|
||||
ori #$01,ccr
|
||||
adc y,b
|
||||
move #>$800000,y1
|
||||
move #>$80,b2
|
||||
adc y,b
|
||||
11
FireBee/trunk/vhdl/dsp56k/asm/test_alu/test_add.asm
Normal file
11
FireBee/trunk/vhdl/dsp56k/asm/test_alu/test_add.asm
Normal file
@@ -0,0 +1,11 @@
|
||||
move #>0,y0
|
||||
move #>1,y1
|
||||
clr b
|
||||
move #>1,b0
|
||||
; set only carry bit
|
||||
andi #$00,ccr
|
||||
ori #$01,ccr
|
||||
add y,b
|
||||
move #>$800000,y1
|
||||
move #>$80,b2
|
||||
add y,b
|
||||
9
FireBee/trunk/vhdl/dsp56k/asm/test_alu/test_addl.asm
Normal file
9
FireBee/trunk/vhdl/dsp56k/asm/test_alu/test_addl.asm
Normal file
@@ -0,0 +1,9 @@
|
||||
move #>$55,a
|
||||
clr b
|
||||
move #>$55,b0
|
||||
andi #$00,ccr
|
||||
addl a,b
|
||||
move #>$AA,a
|
||||
addl a,b
|
||||
move #>$80,b2
|
||||
addl a,b
|
||||
9
FireBee/trunk/vhdl/dsp56k/asm/test_alu/test_addr.asm
Normal file
9
FireBee/trunk/vhdl/dsp56k/asm/test_alu/test_addr.asm
Normal file
@@ -0,0 +1,9 @@
|
||||
move #>$55,a
|
||||
clr b
|
||||
move #>$55,b0
|
||||
andi #$00,ccr
|
||||
addr a,b
|
||||
move #>$AA,a
|
||||
addr a,b
|
||||
move #>$80,b2
|
||||
addr a,b
|
||||
12
FireBee/trunk/vhdl/dsp56k/asm/test_alu/test_and.asm
Normal file
12
FireBee/trunk/vhdl/dsp56k/asm/test_alu/test_and.asm
Normal file
@@ -0,0 +1,12 @@
|
||||
move #>$000FFF,y0
|
||||
move #>$FFFFFF,b
|
||||
andi #$00,ccr
|
||||
and y0,b
|
||||
move #>$FFF000,y0
|
||||
move #>$FFFFFF,b
|
||||
andi #$00,ccr
|
||||
and y0,b
|
||||
move #>$000000,y0
|
||||
move #>$FFFFFF,b
|
||||
andi #$00,ccr
|
||||
and y0,b
|
||||
8
FireBee/trunk/vhdl/dsp56k/asm/test_alu/test_asl.asm
Normal file
8
FireBee/trunk/vhdl/dsp56k/asm/test_alu/test_asl.asm
Normal file
@@ -0,0 +1,8 @@
|
||||
; move #>0,y0
|
||||
; move #>1,y1
|
||||
clr b
|
||||
move #>$A5,b0
|
||||
move #>$A5,b1
|
||||
move #>$A5,b2
|
||||
andi #$00,ccr
|
||||
asl b
|
||||
8
FireBee/trunk/vhdl/dsp56k/asm/test_alu/test_asr.asm
Normal file
8
FireBee/trunk/vhdl/dsp56k/asm/test_alu/test_asr.asm
Normal file
@@ -0,0 +1,8 @@
|
||||
; move #>0,y0
|
||||
; move #>1,y1
|
||||
clr b
|
||||
move #>$A5,b0
|
||||
move #>$A5,b1
|
||||
move #>$A5,b2
|
||||
andi #$00,ccr
|
||||
asr b
|
||||
20
FireBee/trunk/vhdl/dsp56k/asm/test_alu/test_carry.asm
Normal file
20
FireBee/trunk/vhdl/dsp56k/asm/test_alu/test_carry.asm
Normal file
@@ -0,0 +1,20 @@
|
||||
clr a
|
||||
clr b
|
||||
andi #$00,ccr
|
||||
move #>$7F,a2
|
||||
move #>$7F,b2
|
||||
add a,b
|
||||
|
||||
clr a
|
||||
clr b
|
||||
andi #$00,ccr
|
||||
move #>$80,a2
|
||||
move #>$7F,b2
|
||||
add a,b
|
||||
|
||||
clr a
|
||||
clr b
|
||||
andi #$00,ccr
|
||||
move #>$80,a2
|
||||
move #>$80,b2
|
||||
add a,b
|
||||
9
FireBee/trunk/vhdl/dsp56k/asm/test_alu/test_clr.asm
Normal file
9
FireBee/trunk/vhdl/dsp56k/asm/test_alu/test_clr.asm
Normal file
@@ -0,0 +1,9 @@
|
||||
|
||||
; clear CCR
|
||||
andi #$00,CCR
|
||||
move #>0.25,a
|
||||
clr a
|
||||
move #>-0.25,a
|
||||
andi #$00,CCR
|
||||
ori #$01,CCR
|
||||
clr a
|
||||
20
FireBee/trunk/vhdl/dsp56k/asm/test_alu/test_cmp.asm
Normal file
20
FireBee/trunk/vhdl/dsp56k/asm/test_alu/test_cmp.asm
Normal file
@@ -0,0 +1,20 @@
|
||||
move #$20,b
|
||||
move #$24,y0
|
||||
andi #$00,ccr
|
||||
cmp y0,b
|
||||
move #$20,b
|
||||
move #$20,y0
|
||||
andi #$00,ccr
|
||||
cmp y0,b
|
||||
move #$24,b
|
||||
move #$20,y0
|
||||
andi #$00,ccr
|
||||
cmp y0,b
|
||||
move #$800AAA,b
|
||||
move #$20,y0
|
||||
andi #$00,ccr
|
||||
cmp y0,b
|
||||
move #$800AAA,y0
|
||||
move #$20,b
|
||||
andi #$00,ccr
|
||||
cmp y0,b
|
||||
20
FireBee/trunk/vhdl/dsp56k/asm/test_alu/test_cmpm.asm
Normal file
20
FireBee/trunk/vhdl/dsp56k/asm/test_alu/test_cmpm.asm
Normal file
@@ -0,0 +1,20 @@
|
||||
move #$20,b
|
||||
move #$24,y0
|
||||
andi #$00,ccr
|
||||
cmpm y0,b
|
||||
move #$20,b
|
||||
move #$20,y0
|
||||
andi #$00,ccr
|
||||
cmpm y0,b
|
||||
move #$24,b
|
||||
move #$20,y0
|
||||
andi #$00,ccr
|
||||
cmpm y0,b
|
||||
move #$800AAA,b
|
||||
move #$20,y0
|
||||
andi #$00,ccr
|
||||
cmpm y0,b
|
||||
move #$800AAA,y0
|
||||
move #$20,b
|
||||
andi #$00,ccr
|
||||
cmpm y0,b
|
||||
8
FireBee/trunk/vhdl/dsp56k/asm/test_alu/test_eor.asm
Normal file
8
FireBee/trunk/vhdl/dsp56k/asm/test_alu/test_eor.asm
Normal file
@@ -0,0 +1,8 @@
|
||||
move #>$000FFF,y0
|
||||
move #>$FF00FF,b
|
||||
andi #$00,ccr
|
||||
eor y0,b
|
||||
move #>$FFFFFF,y0
|
||||
move #>$FFFFFF,b
|
||||
andi #$00,ccr
|
||||
eor y0,b
|
||||
7
FireBee/trunk/vhdl/dsp56k/asm/test_alu/test_lsl.asm
Normal file
7
FireBee/trunk/vhdl/dsp56k/asm/test_alu/test_lsl.asm
Normal file
@@ -0,0 +1,7 @@
|
||||
|
||||
andi #$00,CCR
|
||||
move #>0.25,a
|
||||
move #>$AAAAAA,a
|
||||
move #>$BCDEFA,a0
|
||||
rep #24
|
||||
lsl a
|
||||
7
FireBee/trunk/vhdl/dsp56k/asm/test_alu/test_lsr.asm
Normal file
7
FireBee/trunk/vhdl/dsp56k/asm/test_alu/test_lsr.asm
Normal file
@@ -0,0 +1,7 @@
|
||||
|
||||
andi #$00,CCR
|
||||
move #>0.25,a
|
||||
move #>$AAAAAA,a
|
||||
move #>$BCDEFA,a0
|
||||
rep #24
|
||||
lsr a
|
||||
17
FireBee/trunk/vhdl/dsp56k/asm/test_alu/test_mac.asm
Normal file
17
FireBee/trunk/vhdl/dsp56k/asm/test_alu/test_mac.asm
Normal file
@@ -0,0 +1,17 @@
|
||||
|
||||
andi #$00,CCR
|
||||
clr a
|
||||
move #$80,a2
|
||||
move #>0.25,x0
|
||||
move #>0.50,y0
|
||||
mac -x0,y0,a
|
||||
move #>-0.25,x0
|
||||
move #>-0.55,y0
|
||||
mac x0,y0,a
|
||||
move #>-0.20,x0
|
||||
move #>+0.55,y0
|
||||
mac x0,y0,a
|
||||
move #>-0.20,x0
|
||||
move #>+0.55,y0
|
||||
mac -x0,y0,a
|
||||
|
||||
17
FireBee/trunk/vhdl/dsp56k/asm/test_alu/test_macr.asm
Normal file
17
FireBee/trunk/vhdl/dsp56k/asm/test_alu/test_macr.asm
Normal file
@@ -0,0 +1,17 @@
|
||||
|
||||
andi #$00,CCR
|
||||
clr a
|
||||
move #$100000,a
|
||||
move #>$123456,x0
|
||||
move #>$123456,y0
|
||||
macr x0,y0,a
|
||||
move #$100001,a
|
||||
move #>$123456,x0
|
||||
move #>$123456,y0
|
||||
macr x0,y0,a
|
||||
move #$100000,a
|
||||
move #$800000,a0
|
||||
move #>$123456,x0
|
||||
move #>$123456,y0
|
||||
macr x0,y0,a
|
||||
|
||||
15
FireBee/trunk/vhdl/dsp56k/asm/test_alu/test_mpy.asm
Normal file
15
FireBee/trunk/vhdl/dsp56k/asm/test_alu/test_mpy.asm
Normal file
@@ -0,0 +1,15 @@
|
||||
|
||||
andi #$00,CCR
|
||||
move #>0.25,x0
|
||||
move #>0.50,y0
|
||||
mpy x0,y0,a
|
||||
move #>-0.25,x0
|
||||
move #>-0.55,y0
|
||||
mpy x0,y0,a
|
||||
move #>-0.20,x0
|
||||
move #>+0.55,y0
|
||||
mpy x0,y0,a
|
||||
move #>-0.20,x0
|
||||
move #>+0.55,y0
|
||||
mpy -x0,y0,a
|
||||
|
||||
5
FireBee/trunk/vhdl/dsp56k/asm/test_alu/test_mpyr.asm
Normal file
5
FireBee/trunk/vhdl/dsp56k/asm/test_alu/test_mpyr.asm
Normal file
@@ -0,0 +1,5 @@
|
||||
|
||||
andi #$00,CCR
|
||||
move #>$654321,y0
|
||||
mpyr -y0,y0,a
|
||||
|
||||
10
FireBee/trunk/vhdl/dsp56k/asm/test_alu/test_neg.asm
Normal file
10
FireBee/trunk/vhdl/dsp56k/asm/test_alu/test_neg.asm
Normal file
@@ -0,0 +1,10 @@
|
||||
|
||||
andi #$00,CCR
|
||||
move #>$654321,a
|
||||
neg a
|
||||
clr a
|
||||
move #>$80,a2
|
||||
neg a
|
||||
move #>$800000,a
|
||||
neg a
|
||||
|
||||
14
FireBee/trunk/vhdl/dsp56k/asm/test_alu/test_norm.asm
Normal file
14
FireBee/trunk/vhdl/dsp56k/asm/test_alu/test_norm.asm
Normal file
@@ -0,0 +1,14 @@
|
||||
clr a
|
||||
move #$000001,a1
|
||||
tst a
|
||||
rep #$2F
|
||||
norm R3,a
|
||||
clr a
|
||||
move #$FF0000,a
|
||||
move #$84,a2
|
||||
tst a
|
||||
rep #$2F
|
||||
norm R1,a
|
||||
clr a
|
||||
rep #$2F
|
||||
norm R2,a
|
||||
8
FireBee/trunk/vhdl/dsp56k/asm/test_alu/test_not.asm
Normal file
8
FireBee/trunk/vhdl/dsp56k/asm/test_alu/test_not.asm
Normal file
@@ -0,0 +1,8 @@
|
||||
move #>$000FFF,y0
|
||||
move #>$7F00FF,b
|
||||
andi #$00,ccr
|
||||
not b
|
||||
move #>$000000,y0
|
||||
move #>$FFFFFF,b
|
||||
andi #$00,ccr
|
||||
not b
|
||||
8
FireBee/trunk/vhdl/dsp56k/asm/test_alu/test_or.asm
Normal file
8
FireBee/trunk/vhdl/dsp56k/asm/test_alu/test_or.asm
Normal file
@@ -0,0 +1,8 @@
|
||||
move #>$000FFF,y0
|
||||
move #>$FF00FF,b
|
||||
andi #$00,ccr
|
||||
or y0,b
|
||||
move #>$000000,y0
|
||||
move #>$000000,b
|
||||
andi #$00,ccr
|
||||
or y0,b
|
||||
11
FireBee/trunk/vhdl/dsp56k/asm/test_alu/test_rnd.asm
Normal file
11
FireBee/trunk/vhdl/dsp56k/asm/test_alu/test_rnd.asm
Normal file
@@ -0,0 +1,11 @@
|
||||
|
||||
andi #$00,CCR
|
||||
move #>$123456,a1
|
||||
move #>$789ABC,a0
|
||||
rnd a
|
||||
move #>$123456,a1
|
||||
move #>$800000,a0
|
||||
rnd a
|
||||
move #>$123455,a1
|
||||
move #>$800000,a0
|
||||
rnd a
|
||||
6
FireBee/trunk/vhdl/dsp56k/asm/test_alu/test_rol.asm
Normal file
6
FireBee/trunk/vhdl/dsp56k/asm/test_alu/test_rol.asm
Normal file
@@ -0,0 +1,6 @@
|
||||
|
||||
andi #$00,CCR
|
||||
move #>$AAAAAA,a
|
||||
move #>$BCDEFA,a0
|
||||
rep #24
|
||||
rol a
|
||||
6
FireBee/trunk/vhdl/dsp56k/asm/test_alu/test_ror.asm
Normal file
6
FireBee/trunk/vhdl/dsp56k/asm/test_alu/test_ror.asm
Normal file
@@ -0,0 +1,6 @@
|
||||
|
||||
andi #$00,CCR
|
||||
move #>$AAAAAA,a
|
||||
move #>$BCDEFA,a0
|
||||
rep #24
|
||||
ror a
|
||||
15
FireBee/trunk/vhdl/dsp56k/asm/test_alu/test_sbc.asm
Normal file
15
FireBee/trunk/vhdl/dsp56k/asm/test_alu/test_sbc.asm
Normal file
@@ -0,0 +1,15 @@
|
||||
move #>0,y0
|
||||
move #>1,y1
|
||||
clr b
|
||||
move #>1,b0
|
||||
; set only carry bit
|
||||
andi #$00,ccr
|
||||
ori #$01,ccr
|
||||
sbc y,b
|
||||
move #>$800000,y1
|
||||
move #>$80,b2
|
||||
sbc y,b
|
||||
clr b
|
||||
move #>$80,b2
|
||||
move #>$1,y1
|
||||
sbc y,b
|
||||
15
FireBee/trunk/vhdl/dsp56k/asm/test_alu/test_sub.asm
Normal file
15
FireBee/trunk/vhdl/dsp56k/asm/test_alu/test_sub.asm
Normal file
@@ -0,0 +1,15 @@
|
||||
move #>0,y0
|
||||
move #>1,y1
|
||||
clr b
|
||||
move #>1,b0
|
||||
; set only carry bit
|
||||
andi #$00,ccr
|
||||
ori #$01,ccr
|
||||
sub y,b
|
||||
move #>$800000,y1
|
||||
move #>$80,b2
|
||||
sub y,b
|
||||
clr b
|
||||
move #>$80,b2
|
||||
move #>$1,y1
|
||||
sub y1,b
|
||||
15
FireBee/trunk/vhdl/dsp56k/asm/test_alu/test_subl.asm
Normal file
15
FireBee/trunk/vhdl/dsp56k/asm/test_alu/test_subl.asm
Normal file
@@ -0,0 +1,15 @@
|
||||
move #>0,a0
|
||||
move #>1,a1
|
||||
clr b
|
||||
move #>1,b0
|
||||
; set only carry bit
|
||||
andi #$00,ccr
|
||||
ori #$01,ccr
|
||||
subl a,b
|
||||
move #>$800000,a1
|
||||
move #>$80,b2
|
||||
subl a,b
|
||||
clr b
|
||||
move #>$80,b2
|
||||
move #>$1,a1
|
||||
subl a,b
|
||||
15
FireBee/trunk/vhdl/dsp56k/asm/test_alu/test_subr.asm
Normal file
15
FireBee/trunk/vhdl/dsp56k/asm/test_alu/test_subr.asm
Normal file
@@ -0,0 +1,15 @@
|
||||
move #>0,a0
|
||||
move #>1,a1
|
||||
clr b
|
||||
move #>1,b0
|
||||
; set only carry bit
|
||||
andi #$00,ccr
|
||||
ori #$01,ccr
|
||||
subr a,b
|
||||
move #>$800000,a1
|
||||
move #>$80,b2
|
||||
subr a,b
|
||||
clr b
|
||||
move #>$80,b2
|
||||
move #>$1,a1
|
||||
subr a,b
|
||||
10
FireBee/trunk/vhdl/dsp56k/asm/test_alu/test_tcc.asm
Normal file
10
FireBee/trunk/vhdl/dsp56k/asm/test_alu/test_tcc.asm
Normal file
@@ -0,0 +1,10 @@
|
||||
move #20,r1
|
||||
move #$ABCDEF,x0
|
||||
move #$123456,b
|
||||
andi #$00,ccr
|
||||
tcs x0,a r1,r3
|
||||
tcc x0,b r1,r2
|
||||
; set Zero Flag
|
||||
ori #$04,ccr
|
||||
teq x0,a r1,r3
|
||||
tne x0,b r1,r2
|
||||
7
FireBee/trunk/vhdl/dsp56k/asm/test_alu/test_tfr.asm
Normal file
7
FireBee/trunk/vhdl/dsp56k/asm/test_alu/test_tfr.asm
Normal file
@@ -0,0 +1,7 @@
|
||||
move #$ABCDEF,a
|
||||
move #$123456,b
|
||||
tfr a,b b,a
|
||||
move #$555555,x0
|
||||
move #$AAAAAA,y1
|
||||
tfr x0,a a,x0
|
||||
tfr y1,b b,y0
|
||||
9
FireBee/trunk/vhdl/dsp56k/asm/test_alu/test_tst.asm
Normal file
9
FireBee/trunk/vhdl/dsp56k/asm/test_alu/test_tst.asm
Normal file
@@ -0,0 +1,9 @@
|
||||
clr b
|
||||
tst b
|
||||
; set only carry bit
|
||||
andi #$00,ccr
|
||||
ori #$01,ccr
|
||||
move #>$80,b2
|
||||
tst b
|
||||
move #>$7F,b2
|
||||
tst b
|
||||
8
FireBee/trunk/vhdl/dsp56k/asm/test_mem/test.asm
Normal file
8
FireBee/trunk/vhdl/dsp56k/asm/test_mem/test.asm
Normal file
@@ -0,0 +1,8 @@
|
||||
|
||||
move #4,r0
|
||||
move #20,r1
|
||||
move r1,x:(r0)
|
||||
move x:(r0),a
|
||||
move r1,y:(r0)
|
||||
move l:(r0)+,ab
|
||||
|
||||
21
FireBee/trunk/vhdl/dsp56k/asm/test_pm_l/test.asm
Normal file
21
FireBee/trunk/vhdl/dsp56k/asm/test_pm_l/test.asm
Normal file
@@ -0,0 +1,21 @@
|
||||
|
||||
move #>$10,x0
|
||||
move #>$11,x1
|
||||
move #11,a1
|
||||
move #-3,a2
|
||||
jclr #0,a,blubb
|
||||
bset #0,x:(r0)+
|
||||
move #>$26,y0
|
||||
move #>$27,y1
|
||||
move x,L:(r0)+
|
||||
move y,L:(r0)+
|
||||
move x,L:$0A
|
||||
move y,L:$1F
|
||||
move y,L:$00A0
|
||||
move x,L:$004F
|
||||
move L:-(r0),x
|
||||
move L:-(r0),y
|
||||
move L:$0A,x
|
||||
move L:$1F,y
|
||||
blubb
|
||||
|
||||
185
FireBee/trunk/vhdl/dsp56k/doc/Change.log
Normal file
185
FireBee/trunk/vhdl/dsp56k/doc/Change.log
Normal file
@@ -0,0 +1,185 @@
|
||||
Done:
|
||||
02.01.09
|
||||
- Started work on pipeline (FE, FE2, DC, AG, EX)
|
||||
- Program counter counts linearly
|
||||
- Initial program memory holds program data
|
||||
- Started work on instruction decoder
|
||||
03.01.09
|
||||
- Jump instructions work (with flushing of the pipeline)
|
||||
- First version of AGU implemented
|
||||
- Detection of double word instructions
|
||||
- Initial version of global register file
|
||||
04.01.09
|
||||
- Included hardware stack
|
||||
- Finished support for JSR and JSCC instructions
|
||||
- RTI/RTS work
|
||||
- ANDI/ORI work
|
||||
- Initial work on REP instruction
|
||||
10.01.09
|
||||
- Initial suppurt for X memory accesses. One stall cycle is introduced when
|
||||
accessing the X memory.
|
||||
- Finished implementation of REP instruction. Reading number of loops from
|
||||
registers is still missing.
|
||||
- Initial support for DO loops.
|
||||
- Preventing to write the R registers when stalling occurs or a jump is
|
||||
performed
|
||||
11.01.09
|
||||
- Finished implementation of DO loops (stop looping at the end)
|
||||
- Nested loops work
|
||||
- Single instruction loops work
|
||||
- ENDDO instruction implemented (very much the same as usual end of the loop)
|
||||
12.01.09
|
||||
- Included Y memory and its addressing modes for REP and DO instruction.
|
||||
- Setup of a sheet showing which types of which instructions have been
|
||||
implemented and how many clock cycles are needed.
|
||||
16.01.09
|
||||
- Integration of LUA instruction.
|
||||
24.01.09
|
||||
- Integrated different addressing schemes (immediate short, immediate long,
|
||||
absolute address)
|
||||
- Integration and test of MOVE(C) instruction. Some modes missing (writing to
|
||||
memory)
|
||||
- Testing of Y memory read accesses.
|
||||
26.01.09
|
||||
- Continued testing of different addressing modes.
|
||||
- Decoding for first parallel move operations.
|
||||
01.02.09
|
||||
- Moved memory components to an extra entity (memory_management)
|
||||
- Writing to internal X and Y memory supported. Problems are possible for
|
||||
reading the same address one instruction after writing at the same address!
|
||||
- Included ALU registers (x,y,a,b) into register file
|
||||
- Integration of x/y/l bus started
|
||||
03.02.09
|
||||
- Continued testing of parallel moves (there are quite a few cases!)
|
||||
07.02.09
|
||||
- Fixed REP instruction for instructions that are causing a stall due to
|
||||
a memory read
|
||||
- Fixed fetching from program data when stalling.
|
||||
- Fixed detection of double word instruction, when previous instruction
|
||||
used the AGU as well (forgot instruction word in sensitivity list).
|
||||
- Continued testing of parallel moves.
|
||||
- First synthesis run: Changed RAM description to map to BRAMs, removed
|
||||
latches, and many things are still missing, post-synthesis results:
|
||||
- Xilinx Spartan3A, Speed-Grade -4
|
||||
- 1488 FFs
|
||||
- 4657 4-Input LUTs
|
||||
- 3 BRAMs
|
||||
- 71.08 MHz
|
||||
08.02.09
|
||||
- Implemented second address generation unit in order to access X and Y
|
||||
memory at the same time
|
||||
- Implemented reverse carry addressing modes for FFT addressing
|
||||
- Started implementation of modulo addressing.
|
||||
- Set M0-M7 to -1 in reset.
|
||||
- Downloaded the assembler for DSP56300. I hope to use it in order to
|
||||
generate the content of the program memory automatically, which will
|
||||
boost the testing speed...
|
||||
- Encoding each instruction to test by hand just sucks. I think I will
|
||||
integrate some bootloader in order to use the LOD files from the
|
||||
assembler to initiate the RAMs.
|
||||
- Implementation of data shifter and limiter (when accessing a or b and
|
||||
giving the result to XDB or YDB). Needs testing.
|
||||
- Integration for L: addressing modes. Needs nesting.
|
||||
10.02.09
|
||||
- Fixed decoding of X: and Y: adressing mode (collided with L: adressing)
|
||||
- L: adressing modes are working
|
||||
14.02.09
|
||||
- Implemented BCHG,BCLR,BSET,BTST,JCLR,JSCLR,JSET,JSSET. A lot of testing
|
||||
is still needed. Peripheral register accesses are still missing.
|
||||
- Second synthesis run: Removed new latches again.
|
||||
, many things are still missing, post-synthesis results:
|
||||
- Xilinx Spartan3A, Speed-Grade -4
|
||||
- 1519 FFs
|
||||
- 6210 4-Input LUTs
|
||||
- 3 BRAMs
|
||||
- 51.68 MHz
|
||||
* Critical path for JSCLR/JSSET=> read limited a/b, go through bit modify
|
||||
unit, test whether condition met, push data to stack. Reading of
|
||||
limited A/B is probably a bug (DSP56001 UM says CCR is not changed,
|
||||
in DSP56300 simulator the flag is set when reading a/b!!).
|
||||
15.02.09
|
||||
- Started implementing the ALU.
|
||||
- ABS works.
|
||||
- MPY(R), MAC(R) implemented, rounding is missing.
|
||||
- Clock frequency dropped to 41 MHz, but the critical path is not caused by
|
||||
the MAC in the ALU! The multiplier is composed of four 18x18 multipliers
|
||||
and still seems to be very fast!
|
||||
16.02.09
|
||||
- Implemented decoding and controlling of ALU for
|
||||
ADC, ADD, ADDL, ADDR, AND, ASL, ASR, CLR, CMP, CMPM, EOR, NEG, NOT, OR
|
||||
Still missing ALU instructions:
|
||||
DIV, NORM, RND, ROL, ROR, SBC, SUB, SUBL, SUBR, Tcc, TFR, TST
|
||||
Except for DIV and NORM this will be straight forward.
|
||||
- Other things that need to be done :
|
||||
* Adress Generation Unit does not support modulo addressing.
|
||||
* MOVEP/MOVEM/STOP/WAIT/ILLEGAL/RESET/SWI
|
||||
* Interrupts
|
||||
* External memory accesses
|
||||
* Peripheral devices (SCI, SSI, Host port)
|
||||
17.02.09
|
||||
- Implemented decoding and controlling of ALU instructions for
|
||||
RND, ROL, ROR, SBC, SUB, SUBL, SUBR, TFR, TST
|
||||
Still missing ALU instructions:
|
||||
DIV, NORM, Tcc
|
||||
08.03.09
|
||||
- Forgot integration of LSR and LSL instructions. TBD.
|
||||
- Started integration of Condition flag generation in ALU.
|
||||
- New synthesis run with ALU, register balancing:
|
||||
- Xilinx Spartan3A, Speed-Grade -4
|
||||
- 3115 FFs
|
||||
- 7417 4-Input LUTs
|
||||
- 3 BRAMs
|
||||
- 39.47 MHz
|
||||
13.03.09
|
||||
- Integrated decoding of LSL/LSR instructions.
|
||||
- Integrated rotating function into ALU.
|
||||
- Included convergent rounding functionality into ALU.
|
||||
- Implemented Tcc instruction.
|
||||
- Implemented DIV instruction.
|
||||
15.03.09
|
||||
- Tested ABS,ADC,ADD,ADDL,ADDR,AND,ASL,ASR,CLR,CMP,CMPM,DIV,EOR,
|
||||
LSL,LSR,MPY,MPYR,MAC,MACR,NEG,NOT,OR
|
||||
- Bugs fixed:
|
||||
- Detection of overflow corrected when negating most negative
|
||||
value $80 000000 000000.
|
||||
- Decoding of ADC and TFR clarified.
|
||||
- Overflow flag generation when left shifting of 56 bit values.
|
||||
- For logical operations the flag generation relied on the adder
|
||||
output which was wrong. Now relies on the Logical unit output.
|
||||
- Decoding of CMPM clarified in order not to conflict with NOT.
|
||||
- Shifter was used for CMP(M) instructions, which is wrong.
|
||||
- Hopefully calculation of carry and overflow flag work correctly now...
|
||||
- MPY/MAC write result back.
|
||||
- Limit Flag is not cleared by the ALU anymore (has to be reset by the
|
||||
user!).
|
||||
16.03.09
|
||||
- Tested RND
|
||||
- Bugs fixed:
|
||||
- Simulator seems to misunderstand the X"1000000" where the first digit
|
||||
represents a single bit. Comparing against this value fixed! RND works.
|
||||
|
||||
17.03.09
|
||||
- Tested ROR,ROL,SBC,SUB,SUBL,SUBR,TCC,TFR,TST,NORM
|
||||
- Integrated logic for NORM instruction support.
|
||||
- ALU is complete now!
|
||||
- Bugs fixed:
|
||||
- Fixed setting of CCR for ROL/ROR
|
||||
- TCC didn't read register through ALU
|
||||
- Known bugs:
|
||||
- Carry calculation for SBC is still buggy
|
||||
- New synthesis run with ALU, register balancing:
|
||||
- Xilinx Spartan3A, Speed-Grade -4
|
||||
- 1801 FFs
|
||||
- 7407 4-Input LUTs
|
||||
- 3 BRAMs
|
||||
- 30.84 MHz
|
||||
Critical path is in the ALU (multiplication, adding, rounding, zero-flag
|
||||
calculation). I wonder why the values changed like that since the
|
||||
last synthesis run.
|
||||
26.03.09
|
||||
- Included support for modulo addressing in AGUs. This allows for the
|
||||
integration of ring buffers. Now 7900 LUTs.
|
||||
18.05.10
|
||||
- Commenting of code.
|
||||
- Added second memory port for p-mem (needed for movem-instruction)
|
||||
|
||||
291
FireBee/trunk/vhdl/dsp56k/src/adgen_stage.vhd
Normal file
291
FireBee/trunk/vhdl/dsp56k/src/adgen_stage.vhd
Normal file
@@ -0,0 +1,291 @@
|
||||
------------------------------------------------------------------------------
|
||||
--! @file
|
||||
--! @author Matthias Alles
|
||||
--! @date 01/2009
|
||||
--! @brief Address generation logic
|
||||
--!
|
||||
------------------------------------------------------------------------------
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.numeric_std.all;
|
||||
library work;
|
||||
use work.parameter_pkg.all;
|
||||
use work.types_pkg.all;
|
||||
use work.constants_pkg.all;
|
||||
|
||||
entity adgen_stage is port(
|
||||
activate_adgen : in std_logic;
|
||||
activate_x_mem : in std_logic;
|
||||
activate_y_mem : in std_logic;
|
||||
activate_l_mem : in std_logic;
|
||||
instr_word : in std_logic_vector(23 downto 0);
|
||||
instr_array : in instructions_type;
|
||||
optional_ea_word : in std_logic_vector(23 downto 0);
|
||||
register_file : in register_file_type;
|
||||
adgen_mode_a : in adgen_mode_type;
|
||||
adgen_mode_b : in adgen_mode_type;
|
||||
address_out_x : out unsigned(BW_ADDRESS-1 downto 0);
|
||||
address_out_y : out unsigned(BW_ADDRESS-1 downto 0);
|
||||
wr_R_port_A_valid : out std_logic;
|
||||
wr_R_port_A : out addr_wr_port_type;
|
||||
wr_R_port_B_valid : out std_logic;
|
||||
wr_R_port_B : out addr_wr_port_type
|
||||
);
|
||||
end entity;
|
||||
|
||||
|
||||
architecture rtl of adgen_stage is
|
||||
|
||||
signal address_out_x_int : unsigned(BW_ADDRESS-1 downto 0);
|
||||
|
||||
signal r_reg_local_x : unsigned(BW_ADDRESS-1 downto 0);
|
||||
signal n_reg_local_x : unsigned(BW_ADDRESS-1 downto 0);
|
||||
signal m_reg_local_x : unsigned(BW_ADDRESS-1 downto 0);
|
||||
|
||||
signal r_reg_local_y : unsigned(BW_ADDRESS-1 downto 0);
|
||||
signal n_reg_local_y : unsigned(BW_ADDRESS-1 downto 0);
|
||||
signal m_reg_local_y : unsigned(BW_ADDRESS-1 downto 0);
|
||||
|
||||
function calculate_modulo_bitmask(m_reg_local : in unsigned ) return std_logic_vector is
|
||||
variable modulo_bitmask_intern : std_logic_vector(BW_ADDRESS-1 downto 0);
|
||||
begin
|
||||
modulo_bitmask_intern(BW_ADDRESS-1) := m_reg_local(BW_ADDRESS-1);
|
||||
for i in BW_ADDRESS-2 downto 0 loop
|
||||
modulo_bitmask_intern(i) := modulo_bitmask_intern(i+1) or m_reg_local(i);
|
||||
end loop;
|
||||
|
||||
return modulo_bitmask_intern;
|
||||
end function calculate_modulo_bitmask;
|
||||
|
||||
function calculate_new_r_reg(new_r_reg_intermediate, r_reg_local, m_reg_local: in unsigned;
|
||||
modulo_bitmask: in std_logic_vector ) return unsigned is
|
||||
variable modulo_result : unsigned(BW_ADDRESS-1 downto 0);
|
||||
variable new_r_reg_intern : unsigned(BW_ADDRESS-1 downto 0);
|
||||
begin
|
||||
-- cut out the bits we are interested in
|
||||
-- for modulo addressing
|
||||
for i in 0 to BW_ADDRESS-1 loop
|
||||
if modulo_bitmask(i) = '1' then
|
||||
modulo_result(i) := new_r_reg_intermediate(i);
|
||||
else
|
||||
modulo_result(i) := '0';
|
||||
end if;
|
||||
end loop;
|
||||
-- compare whether an overflow occurred and we
|
||||
-- have to renormalize the result
|
||||
if modulo_result > m_reg_local then
|
||||
modulo_result := modulo_result - m_reg_local;
|
||||
end if;
|
||||
|
||||
-- linear addressing
|
||||
if m_reg_local = 2**BW_ADDRESS-1 then
|
||||
new_r_reg_intern := new_r_reg_intermediate;
|
||||
-- bit reverse operation
|
||||
elsif m_reg_local = 0 then
|
||||
for i in 0 to BW_ADDRESS-1 loop
|
||||
new_r_reg_intern(BW_ADDRESS - 1 - i) := new_r_reg_intermediate(i);
|
||||
end loop;
|
||||
-- modulo arithmetic / linear addressing
|
||||
else
|
||||
-- only update the bits that are part of the bitmask!
|
||||
for i in 0 to BW_ADDRESS-1 loop
|
||||
if modulo_bitmask(i) = '1' then
|
||||
new_r_reg_intern(i) := modulo_result(i);
|
||||
else
|
||||
new_r_reg_intern(i) := r_reg_local(i);
|
||||
end if;
|
||||
end loop;
|
||||
end if;
|
||||
return new_r_reg_intern;
|
||||
end function calculate_new_r_reg;
|
||||
|
||||
procedure set_operands(r_reg_local, m_reg_local, addr_mod : in unsigned; op1, op2 : out unsigned) is
|
||||
begin
|
||||
-- bit reverse operation
|
||||
if m_reg_local = 0 then
|
||||
-- reverse the input to the adder bit wise
|
||||
-- so we just need to use a single adder
|
||||
for i in 0 to BW_ADDRESS-1 loop
|
||||
op1(BW_ADDRESS - 1 - i) := r_reg_local(i);
|
||||
op2(BW_ADDRESS - 1 - i) := addr_mod(i);
|
||||
end loop;
|
||||
-- modulo arithmetic / linear addressing
|
||||
else
|
||||
op1 := r_reg_local;
|
||||
op2 := addr_mod;
|
||||
end if;
|
||||
end procedure set_operands;
|
||||
|
||||
begin
|
||||
|
||||
address_out_x <= address_out_x_int;
|
||||
|
||||
r_reg_local_x <= register_file.addr_r(to_integer(unsigned(instr_word(10 downto 8))));
|
||||
n_reg_local_x <= register_file.addr_n(to_integer(unsigned(instr_word(10 downto 8))));
|
||||
m_reg_local_x <= register_file.addr_m(to_integer(unsigned(instr_word(10 downto 8))));
|
||||
|
||||
r_reg_local_y <= register_file.addr_r(to_integer(unsigned((not instr_word(10)) & instr_word(14 downto 13))));
|
||||
n_reg_local_y <= register_file.addr_n(to_integer(unsigned((not instr_word(10)) & instr_word(14 downto 13))));
|
||||
m_reg_local_y <= register_file.addr_m(to_integer(unsigned((not instr_word(10)) & instr_word(14 downto 13))));
|
||||
|
||||
address_generator_X: process(activate_adgen, instr_word, adgen_mode_a, r_reg_local_x, n_reg_local_x, m_reg_local_x) is
|
||||
variable op1 : unsigned(BW_ADDRESS-1 downto 0);
|
||||
variable op2 : unsigned(BW_ADDRESS-1 downto 0);
|
||||
variable addr_mod : unsigned(BW_ADDRESS-1 downto 0);
|
||||
variable new_r_reg : unsigned(BW_ADDRESS-1 downto 0);
|
||||
variable new_r_reg_interm : unsigned(BW_ADDRESS-1 downto 0);
|
||||
variable modulo_bitmask : std_logic_vector(BW_ADDRESS-1 downto 0);
|
||||
variable modulo_result : unsigned(BW_ADDRESS-1 downto 0);
|
||||
begin
|
||||
|
||||
-- select the operands for the calculation
|
||||
case adgen_mode_a is
|
||||
-- (Rn) - Nn
|
||||
when POST_MIN_N => addr_mod := unsigned(- signed(n_reg_local_x));
|
||||
-- (Rn) + Nn
|
||||
when POST_PLUS_N => addr_mod := n_reg_local_x;
|
||||
-- (Rn)-
|
||||
when POST_MIN_1 => addr_mod := (others => '1'); -- -1
|
||||
-- (Rn)+
|
||||
when POST_PLUS_1 => addr_mod := to_unsigned(1, BW_ADDRESS);
|
||||
-- (Rn)
|
||||
when NOP => addr_mod := (others => '0');
|
||||
-- (Rn + Nn)
|
||||
when INDEXED_N => addr_mod := n_reg_local_x;
|
||||
-- -(Rn)
|
||||
when PRE_MIN_1 => addr_mod := (others => '1'); -- - 1
|
||||
-- absolute address (appended to instruction word)
|
||||
when ABSOLUTE => addr_mod := (others => '0');
|
||||
when IMMEDIATE => addr_mod := (others => '0');
|
||||
end case;
|
||||
|
||||
------------------------------------------------
|
||||
-- set op1 and op2 according to modulo register
|
||||
------------------------------------------------
|
||||
set_operands(r_reg_local_x, m_reg_local_x, addr_mod, op1, op2);
|
||||
|
||||
-------------------------
|
||||
-- Calculate new address
|
||||
-------------------------
|
||||
new_r_reg_interm := op1 + op2;
|
||||
|
||||
----------------------------------
|
||||
-- Calculate new register content
|
||||
-----------------------------------
|
||||
modulo_bitmask := calculate_modulo_bitmask(m_reg_local_x);
|
||||
new_r_reg := calculate_new_r_reg(new_r_reg_interm, r_reg_local_x, m_reg_local_x, modulo_bitmask);
|
||||
|
||||
-- store the updated register in the global register file
|
||||
-- do not store when we do nothing or there is nothing to update
|
||||
-- LUA instructions DO NOT UPDATE the source register!!
|
||||
if (adgen_mode_a = NOP or adgen_mode_a = ABSOLUTE or adgen_mode_a = IMMEDIATE or instr_array = INSTR_LUA) then
|
||||
wr_R_port_A_valid <= '0';
|
||||
else
|
||||
wr_R_port_A_valid <= '1';
|
||||
end if;
|
||||
wr_R_port_A.reg_number <= unsigned(instr_word(10 downto 8));
|
||||
wr_R_port_A.reg_value <= new_r_reg;
|
||||
|
||||
-- select the output of the AGU
|
||||
case adgen_mode_a is
|
||||
-- (Rn) - Nn
|
||||
when POST_MIN_N => address_out_x_int <= r_reg_local_x;
|
||||
-- (Rn) + Nn
|
||||
when POST_PLUS_N => address_out_x_int <= r_reg_local_x;
|
||||
-- (Rn)-
|
||||
when POST_MIN_1 => address_out_x_int <= r_reg_local_x;
|
||||
-- (Rn)+
|
||||
when POST_PLUS_1 => address_out_x_int <= r_reg_local_x;
|
||||
-- (Rn)
|
||||
when NOP => address_out_x_int <= r_reg_local_x;
|
||||
-- (Rn + Nn)
|
||||
when INDEXED_N => address_out_x_int <= new_r_reg;
|
||||
-- -(Rn)
|
||||
when PRE_MIN_1 => address_out_x_int <= new_r_reg;
|
||||
-- absolute address (appended to instruction word)
|
||||
when ABSOLUTE => address_out_x_int <= unsigned(optional_ea_word(BW_ADDRESS-1 downto 0));
|
||||
when IMMEDIATE => address_out_x_int <= r_reg_local_x; -- Done externally, value never used
|
||||
end case;
|
||||
-- LUA instructions only use the updated address!
|
||||
if instr_array = INSTR_LUA then
|
||||
address_out_x_int <= new_r_reg;
|
||||
end if;
|
||||
|
||||
end process address_generator_X;
|
||||
|
||||
|
||||
---------------------------------------------------------
|
||||
-- Second address generator
|
||||
-- Used when accessing X and Y memory at the same time
|
||||
---------------------------------------------------------
|
||||
address_generator_Y: process(activate_adgen, activate_x_mem, activate_y_mem, activate_l_mem, instr_word,
|
||||
register_file, adgen_mode_b, address_out_x_int, r_reg_local_y, n_reg_local_y, m_reg_local_y) is
|
||||
variable op1 : unsigned(BW_ADDRESS-1 downto 0);
|
||||
variable op2 : unsigned(BW_ADDRESS-1 downto 0);
|
||||
variable addr_mod : unsigned(BW_ADDRESS-1 downto 0);
|
||||
variable new_r_reg : unsigned(BW_ADDRESS-1 downto 0);
|
||||
variable new_r_reg_interm : unsigned(BW_ADDRESS-1 downto 0);
|
||||
variable modulo_bitmask : std_logic_vector(BW_ADDRESS-1 downto 0);
|
||||
variable modulo_result : unsigned(BW_ADDRESS-1 downto 0);
|
||||
begin
|
||||
|
||||
-- select the operands for the calculation
|
||||
case adgen_mode_b is
|
||||
-- (Rn) + Nn
|
||||
when POST_PLUS_N => addr_mod := n_reg_local_y;
|
||||
-- (Rn)-
|
||||
when POST_MIN_1 => addr_mod := (others => '1'); -- -1
|
||||
-- (Rn)+
|
||||
when POST_PLUS_1 => addr_mod := to_unsigned(1, BW_ADDRESS);
|
||||
-- (Rn)
|
||||
when others => addr_mod := (others => '0');
|
||||
end case;
|
||||
|
||||
------------------------------------------------
|
||||
-- set op1 and op2 according to modulo register
|
||||
------------------------------------------------
|
||||
set_operands(r_reg_local_y, m_reg_local_y, addr_mod, op1, op2);
|
||||
|
||||
-------------------------
|
||||
-- Calculate new address
|
||||
-------------------------
|
||||
new_r_reg_interm := op1 + op2;
|
||||
|
||||
----------------------------------
|
||||
-- Calculate new register content
|
||||
-----------------------------------
|
||||
modulo_bitmask := calculate_modulo_bitmask(m_reg_local_y);
|
||||
new_r_reg := calculate_new_r_reg(new_r_reg_interm, r_reg_local_y, m_reg_local_y, modulo_bitmask);
|
||||
|
||||
-- store the updated register in the global register file
|
||||
-- do not store when we do nothing or there is nothing to update
|
||||
if adgen_mode_b = NOP then
|
||||
wr_R_port_B_valid <= '0';
|
||||
else
|
||||
wr_R_port_B_valid <= '1';
|
||||
end if;
|
||||
wr_R_port_B.reg_number <= unsigned((not instr_word(10)) & instr_word(14 downto 13));
|
||||
wr_R_port_B.reg_value <= new_r_reg;
|
||||
|
||||
-- the address for the y memory is calculated in the first AGU if the x memory is not accessed!
|
||||
-- so use the other output as address output for the y memory!
|
||||
-- Furthermore, use the same address for L memory accesses (X and Y memory access the same address!)
|
||||
if (activate_y_mem = '1' and activate_x_mem = '0') or activate_l_mem = '1' then
|
||||
address_out_y <= address_out_x_int;
|
||||
-- in any other case use the locally computed value
|
||||
else
|
||||
-- select the output of the AGU
|
||||
case adgen_mode_b is
|
||||
-- (Rn) + Nn
|
||||
when POST_PLUS_N => address_out_y <= r_reg_local_y;
|
||||
-- (Rn)-
|
||||
when POST_MIN_1 => address_out_y <= r_reg_local_y;
|
||||
-- (Rn)+
|
||||
when POST_PLUS_1 => address_out_y <= r_reg_local_y;
|
||||
-- (Rn)
|
||||
when others => address_out_y <= r_reg_local_y;
|
||||
end case;
|
||||
end if;
|
||||
end process address_generator_Y;
|
||||
|
||||
end architecture;
|
||||
74
FireBee/trunk/vhdl/dsp56k/src/constants_pkg.vhd
Normal file
74
FireBee/trunk/vhdl/dsp56k/src/constants_pkg.vhd
Normal file
@@ -0,0 +1,74 @@
|
||||
------------------------------------------------------------------------------
|
||||
--! @file
|
||||
--! @author Matthias Alles
|
||||
--! @date 01/2009
|
||||
--! @brief General constants for decoding pipeline.
|
||||
--!
|
||||
------------------------------------------------------------------------------
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.numeric_std.all;
|
||||
library work;
|
||||
use work.parameter_pkg.all;
|
||||
use work.types_pkg.all;
|
||||
|
||||
|
||||
package constants_pkg is
|
||||
|
||||
|
||||
-------------------------
|
||||
-- Flags in CCR register
|
||||
-------------------------
|
||||
|
||||
constant C_FLAG : natural := 0;
|
||||
constant V_FLAG : natural := 1;
|
||||
constant Z_FLAG : natural := 2;
|
||||
constant N_FLAG : natural := 3;
|
||||
constant U_FLAG : natural := 4;
|
||||
constant E_FLAG : natural := 5;
|
||||
constant L_FLAG : natural := 6;
|
||||
constant S_FLAG : natural := 7;
|
||||
|
||||
|
||||
-------------------
|
||||
-- Pipeline stages
|
||||
-------------------
|
||||
|
||||
constant ST_FE_FE2 : natural := 0;
|
||||
constant ST_FE2_DEC : natural := 1;
|
||||
constant ST_DEC_ADG : natural := 2;
|
||||
constant ST_ADG_EX : natural := 3;
|
||||
|
||||
|
||||
----------------------
|
||||
-- Activation signals
|
||||
----------------------
|
||||
|
||||
constant ACT_ADGEN : natural := 0; -- Run the address generator
|
||||
constant ACT_ALU : natural := 1; -- Activation of ALU results in modification of the status register
|
||||
constant ACT_EXEC_BRA : natural := 2; -- Branch (in execute stage)
|
||||
constant ACT_EXEC_CR_MOD : natural := 3; -- Control Register Modification (in execute stage)
|
||||
constant ACT_EXEC_LOOP : natural := 4; -- Loop instruction (REP, DO)
|
||||
constant ACT_X_MEM_RD : natural := 5; -- Init read from X memory
|
||||
constant ACT_Y_MEM_RD : natural := 6; -- Init read from Y memory
|
||||
constant ACT_P_MEM_RD : natural := 7; -- Init read from P memory
|
||||
constant ACT_X_MEM_WR : natural := 8; -- Init write to X memory
|
||||
constant ACT_Y_MEM_WR : natural := 9; -- Init write to Y memory
|
||||
constant ACT_P_MEM_WR : natural := 10; -- Init write to P memory
|
||||
constant ACT_REG_RD : natural := 11; -- Read from register (6 bit addressing)
|
||||
constant ACT_REG_WR : natural := 12; -- Write to register (6 bit addressing)
|
||||
constant ACT_IMM_8BIT : natural := 13; -- 8 bit immediate operand (in instruction word)
|
||||
constant ACT_IMM_12BIT : natural := 14; -- 12 bit immediate operand (in instruction word)
|
||||
constant ACT_IMM_LONG : natural := 15; -- 24 bit immediate operant (in optional instruction word)
|
||||
constant ACT_X_BUS_RD : natural := 16; -- Read data via X-bus (from x0,x1,a,b)
|
||||
constant ACT_X_BUS_WR : natural := 17; -- Write data via X-bus (to x0,x1,a,b)
|
||||
constant ACT_Y_BUS_RD : natural := 18; -- Read data via Y-bus (from y0,y1,a,b)
|
||||
constant ACT_Y_BUS_WR : natural := 19; -- Write data via Y-bus (to y0,y1,a,b)
|
||||
constant ACT_L_BUS_RD : natural := 20; -- Read data via L-bus (from a10, b10,x,y,a,b,ab,ba)
|
||||
constant ACT_L_BUS_WR : natural := 21; -- Write data via L-bus (to a10, b10,x,y,a,b,ab,ba)
|
||||
constant ACT_BIT_MOD_WR : natural := 22; -- Bit modify write (to set for BSET, BCLR, BCHG)
|
||||
constant ACT_REG_WR_CC : natural := 23; -- Write to register file conditionally (Tcc)
|
||||
constant ACT_ALU_WR_CC : natural := 24; -- Write ALU result conditionally (Tcc)
|
||||
constant ACT_NORM : natural := 25; -- NORM instruction needs special handling
|
||||
|
||||
end package constants_pkg;
|
||||
1226
FireBee/trunk/vhdl/dsp56k/src/decode_stage.vhd
Normal file
1226
FireBee/trunk/vhdl/dsp56k/src/decode_stage.vhd
Normal file
File diff suppressed because it is too large
Load Diff
117
FireBee/trunk/vhdl/dsp56k/src/dsp56k.vhd
Normal file
117
FireBee/trunk/vhdl/dsp56k/src/dsp56k.vhd
Normal file
@@ -0,0 +1,117 @@
|
||||
------------------------------------------------------------------------------
|
||||
--! @file
|
||||
--! @author Matthias Alles
|
||||
--! @date 01/2009
|
||||
--! @brief Top entity of DSP
|
||||
--!
|
||||
------------------------------------------------------------------------------
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.numeric_std.all;
|
||||
library work;
|
||||
use work.parameter_pkg.all;
|
||||
use work.types_pkg.all;
|
||||
use work.constants_pkg.all;
|
||||
|
||||
entity dsp56k is port (
|
||||
clk, rst : in std_logic;
|
||||
-- put register file here for synthesis!
|
||||
register_file : out register_file_type
|
||||
-- port_a_in : in port_a_in_type;
|
||||
-- port_a_out : out port_a_out_type;
|
||||
-- port_b_in : in port_b_in_type;
|
||||
-- port_b_out : out port_b_out_type;
|
||||
-- port_c_in : in port_c_in_type;
|
||||
-- port_c_out : out port_c_out_type;
|
||||
|
||||
);
|
||||
end dsp56k;
|
||||
|
||||
|
||||
architecture rtl of dsp56k is
|
||||
|
||||
component pipeline is port (
|
||||
clk, rst : in std_logic;
|
||||
register_file_out : out register_file_type;
|
||||
stall_flags_out : out std_logic_vector(PIPELINE_DEPTH-1 downto 0);
|
||||
memory_stall : in std_logic;
|
||||
data_rom_enable: out std_logic;
|
||||
pmem_ctrl_in : out mem_ctrl_type_in;
|
||||
pmem_ctrl_out : in mem_ctrl_type_out;
|
||||
pmem2_ctrl_in : out mem_ctrl_type_in;
|
||||
pmem2_ctrl_out : in mem_ctrl_type_out;
|
||||
xmem_ctrl_in : out mem_ctrl_type_in;
|
||||
xmem_ctrl_out : in mem_ctrl_type_out;
|
||||
ymem_ctrl_in : out mem_ctrl_type_in;
|
||||
ymem_ctrl_out : in mem_ctrl_type_out
|
||||
|
||||
);
|
||||
end component pipeline;
|
||||
|
||||
component memory_management is port (
|
||||
clk, rst : in std_logic;
|
||||
stall_flags : in std_logic_vector(PIPELINE_DEPTH-1 downto 0);
|
||||
memory_stall : out std_logic;
|
||||
data_rom_enable: in std_logic;
|
||||
pmem_ctrl_in : in mem_ctrl_type_in;
|
||||
pmem_ctrl_out : out mem_ctrl_type_out;
|
||||
pmem2_ctrl_in : in mem_ctrl_type_in;
|
||||
pmem2_ctrl_out : out mem_ctrl_type_out;
|
||||
xmem_ctrl_in : in mem_ctrl_type_in;
|
||||
xmem_ctrl_out : out mem_ctrl_type_out;
|
||||
ymem_ctrl_in : in mem_ctrl_type_in;
|
||||
ymem_ctrl_out : out mem_ctrl_type_out
|
||||
);
|
||||
end component memory_management;
|
||||
|
||||
signal stall_flags : std_logic_vector(PIPELINE_DEPTH-1 downto 0);
|
||||
signal memory_stall : std_logic;
|
||||
signal data_rom_enable : std_logic;
|
||||
signal pmem_ctrl_in : mem_ctrl_type_in;
|
||||
signal pmem_ctrl_out : mem_ctrl_type_out;
|
||||
signal pmem2_ctrl_in : mem_ctrl_type_in;
|
||||
signal pmem2_ctrl_out : mem_ctrl_type_out;
|
||||
signal xmem_ctrl_in : mem_ctrl_type_in;
|
||||
signal xmem_ctrl_out : mem_ctrl_type_out;
|
||||
signal ymem_ctrl_in : mem_ctrl_type_in;
|
||||
signal ymem_ctrl_out : mem_ctrl_type_out;
|
||||
|
||||
begin
|
||||
|
||||
pipeline_inst : pipeline port map(
|
||||
clk => clk,
|
||||
rst => rst,
|
||||
register_file_out => register_file,
|
||||
stall_flags_out => stall_flags,
|
||||
memory_stall => memory_stall,
|
||||
data_rom_enable => data_rom_enable,
|
||||
pmem_ctrl_in => pmem_ctrl_in,
|
||||
pmem_ctrl_out => pmem_ctrl_out,
|
||||
pmem2_ctrl_in => pmem2_ctrl_in,
|
||||
pmem2_ctrl_out => pmem2_ctrl_out,
|
||||
xmem_ctrl_in => xmem_ctrl_in,
|
||||
xmem_ctrl_out => xmem_ctrl_out,
|
||||
ymem_ctrl_in => ymem_ctrl_in,
|
||||
ymem_ctrl_out => ymem_ctrl_out
|
||||
);
|
||||
|
||||
---------------------
|
||||
-- MEMORY MANAGEMENT
|
||||
---------------------
|
||||
MMU_inst: memory_management port map (
|
||||
clk => clk,
|
||||
rst => rst,
|
||||
stall_flags => stall_flags,
|
||||
memory_stall => memory_stall,
|
||||
data_rom_enable => data_rom_enable,
|
||||
pmem_ctrl_in => pmem_ctrl_in,
|
||||
pmem_ctrl_out => pmem_ctrl_out,
|
||||
pmem2_ctrl_in => pmem2_ctrl_in,
|
||||
pmem2_ctrl_out => pmem2_ctrl_out,
|
||||
xmem_ctrl_in => xmem_ctrl_in,
|
||||
xmem_ctrl_out => xmem_ctrl_out,
|
||||
ymem_ctrl_in => ymem_ctrl_in,
|
||||
ymem_ctrl_out => ymem_ctrl_out
|
||||
);
|
||||
|
||||
end architecture rtl;
|
||||
611
FireBee/trunk/vhdl/dsp56k/src/exec_stage_alu.vhd
Normal file
611
FireBee/trunk/vhdl/dsp56k/src/exec_stage_alu.vhd
Normal file
@@ -0,0 +1,611 @@
|
||||
------------------------------------------------------------------------------
|
||||
--! @file
|
||||
--! @author Matthias Alles
|
||||
--! @date 01/2009
|
||||
--! @brief ALU, including shifter, MAC unit, etc.
|
||||
--!
|
||||
------------------------------------------------------------------------------
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.numeric_std.all;
|
||||
library work;
|
||||
use work.parameter_pkg.all;
|
||||
use work.types_pkg.all;
|
||||
use work.constants_pkg.all;
|
||||
|
||||
entity exec_stage_alu is port(
|
||||
alu_activate : in std_logic;
|
||||
instr_word : in std_logic_vector(23 downto 0);
|
||||
alu_ctrl : in alu_ctrl_type;
|
||||
register_file : in register_file_type;
|
||||
addr_r_in : in unsigned(BW_ADDRESS-1 downto 0);
|
||||
addr_r_out : out unsigned(BW_ADDRESS-1 downto 0);
|
||||
modify_accu : out std_logic;
|
||||
dst_accu : out std_logic;
|
||||
modified_accu : out signed(55 downto 0);
|
||||
modify_sr : out std_logic;
|
||||
modified_sr : out std_logic_vector(15 downto 0)
|
||||
);
|
||||
end entity;
|
||||
|
||||
architecture rtl of exec_stage_alu is
|
||||
|
||||
signal alu_shifter_out : signed(55 downto 0);
|
||||
signal alu_shifter_carry_out : std_logic;
|
||||
signal alu_shifter_overflow_out : std_logic;
|
||||
|
||||
signal alu_logic_conj : signed(55 downto 0);
|
||||
signal alu_multiplier_out : signed(55 downto 0);
|
||||
signal alu_src_op : signed(55 downto 0);
|
||||
signal alu_add_result : signed(56 downto 0);
|
||||
signal alu_add_carry_out : std_logic;
|
||||
signal alu_post_adder_result : signed(56 downto 0);
|
||||
|
||||
signal scaling_mode : std_logic_vector(1 downto 0);
|
||||
|
||||
signal modified_accu_int : signed(55 downto 0);
|
||||
|
||||
signal norm_instr_asl : std_logic;
|
||||
signal norm_instr_asr : std_logic;
|
||||
signal norm_instr_nop : std_logic;
|
||||
signal norm_update_ccr : std_logic;
|
||||
|
||||
begin
|
||||
|
||||
|
||||
-- store calculated value?
|
||||
modify_accu <= alu_ctrl.store_result;
|
||||
modified_accu <= modified_accu_int;
|
||||
-- for the norm instruction we first need to determine whether we have to
|
||||
-- update the CCR register or not
|
||||
modify_sr <= alu_activate when alu_ctrl.norm_instr = '0' else
|
||||
norm_update_ccr;
|
||||
dst_accu <= alu_ctrl.dst_accu;
|
||||
|
||||
scaling_mode <= register_file.sr(11 downto 10);
|
||||
|
||||
|
||||
calcule_ccr_flags: process(register_file, alu_ctrl, alu_shifter_carry_out,
|
||||
alu_post_adder_result, modified_accu_int, alu_add_carry_out) is
|
||||
begin
|
||||
-- by default do not modify the flags in the status register
|
||||
modified_sr <= register_file.sr;
|
||||
|
||||
-- Carry flag generation
|
||||
-------------------------
|
||||
case alu_ctrl.ccr_flags_ctrl(C_FLAG) is
|
||||
when CLEAR => modified_sr(C_FLAG) <= '0';
|
||||
when SET => modified_sr(C_FLAG) <= '1';
|
||||
when MODIFY =>
|
||||
-- the carry flag can stem from the shifter or from the post adder
|
||||
-- in case we shift and add only a zero to the shift result (ASL, ASR, LSL, LSR, ROL, ROR)
|
||||
-- take the carry flag from the shifter, else from the post adder
|
||||
if (alu_ctrl.shift_mode = SHIFT_LEFT or alu_ctrl.shift_mode = SHIFT_RIGHT) and
|
||||
alu_ctrl.add_src_stage_2 = "00" then -- add zero after shifting?
|
||||
modified_sr(C_FLAG) <= alu_shifter_carry_out;
|
||||
elsif alu_ctrl.div_instr = '1' then
|
||||
modified_sr(C_FLAG) <= not std_logic(alu_post_adder_result(55));
|
||||
else
|
||||
-- modified_sr(C_FLAG) <= std_logic(alu_post_adder_result(57));
|
||||
modified_sr(C_FLAG) <= alu_add_carry_out;
|
||||
end if;
|
||||
when others => -- Don't touch
|
||||
end case;
|
||||
|
||||
-- Overflow flag generation
|
||||
----------------------------
|
||||
case alu_ctrl.ccr_flags_ctrl(V_FLAG) is
|
||||
when CLEAR => modified_sr(V_FLAG) <= '0';
|
||||
when SET => modified_sr(V_FLAG) <= '1';
|
||||
when MODIFY =>
|
||||
-- There are two sources for the overflow flag:
|
||||
-- 1)
|
||||
-- in case the result cannot be represented using 56 bits set
|
||||
-- the overflow flag. this is the case when the two MSBs of
|
||||
-- the 57 bit result are different
|
||||
-- 2)
|
||||
-- The shifter circuit performs a 56 bit left shift. In case the
|
||||
-- two MSBs of the operand are different set the overflow flag as well
|
||||
if (alu_ctrl.div_instr = '0' and alu_post_adder_result(56) /= alu_post_adder_result(55)) or
|
||||
(alu_ctrl.shift_mode = SHIFT_LEFT and alu_ctrl.word_24_update = '0' and
|
||||
alu_shifter_overflow_out = '1' ) then
|
||||
modified_sr(V_FLAG) <= '1';
|
||||
else
|
||||
modified_sr(V_FLAG) <= '0';
|
||||
end if;
|
||||
when others => -- Don't touch
|
||||
end case;
|
||||
|
||||
-- Zero flag generation
|
||||
----------------------------
|
||||
case alu_ctrl.ccr_flags_ctrl(Z_FLAG) is
|
||||
when CLEAR => modified_sr(Z_FLAG) <= '0';
|
||||
when SET => modified_sr(Z_FLAG) <= '1';
|
||||
when MODIFY =>
|
||||
-- in case the result is zero set this flag
|
||||
-- distinguish between 24 bit and 56 bit ALU operations
|
||||
-- 24 bit instructions are LSL, LSR, ROR, ROL, OR, EOR, NOT, AND
|
||||
if (alu_ctrl.word_24_update = '1' and modified_accu_int(47 downto 24) = 0) or
|
||||
(alu_ctrl.word_24_update = '0' and modified_accu_int(55 downto 0) = 0) then
|
||||
modified_sr(Z_FLAG) <= '1';
|
||||
else
|
||||
modified_sr(Z_FLAG) <= '0';
|
||||
end if;
|
||||
when others => -- Don't touch
|
||||
end case;
|
||||
|
||||
-- Negative flag generation
|
||||
----------------------------
|
||||
case alu_ctrl.ccr_flags_ctrl(N_FLAG) is
|
||||
when CLEAR => modified_sr(N_FLAG) <= '0';
|
||||
when SET => modified_sr(N_FLAG) <= '1';
|
||||
when MODIFY =>
|
||||
-- in case the result is negative set this flag
|
||||
-- distinguish between 24 bit and 56 bit ALU operations
|
||||
-- 24 bit instructions are LSL, LSR, ROR, ROL, OR, EOR, NOT, AND
|
||||
if alu_ctrl.word_24_update = '1' then
|
||||
modified_sr(N_FLAG) <= std_logic(modified_accu_int(47));
|
||||
else
|
||||
modified_sr(N_FLAG) <= std_logic(modified_accu_int(55));
|
||||
end if;
|
||||
when others => -- Don't touch
|
||||
end case;
|
||||
|
||||
-- Unnormalized flag generation
|
||||
----------------------------
|
||||
case alu_ctrl.ccr_flags_ctrl(U_FLAG) is
|
||||
when CLEAR => modified_sr(U_FLAG) <= '0';
|
||||
when SET => modified_sr(U_FLAG) <= '1';
|
||||
when MODIFY =>
|
||||
-- Set unnormalized bit according to the scaling mode
|
||||
if (scaling_mode = "00" and alu_post_adder_result(47) = alu_post_adder_result(46)) or
|
||||
(scaling_mode = "01" and alu_post_adder_result(48) = alu_post_adder_result(47)) or
|
||||
(scaling_mode = "10" and alu_post_adder_result(46) = alu_post_adder_result(45)) then
|
||||
modified_sr(U_FLAG) <= '1';
|
||||
else
|
||||
modified_sr(U_FLAG) <= '0';
|
||||
end if;
|
||||
when others => -- Don't touch
|
||||
end case;
|
||||
|
||||
-- Extension flag generation
|
||||
----------------------------
|
||||
case alu_ctrl.ccr_flags_ctrl(E_FLAG) is
|
||||
when CLEAR => modified_sr(E_FLAG) <= '0';
|
||||
when SET => modified_sr(E_FLAG) <= '1';
|
||||
when MODIFY =>
|
||||
-- Set extension flag by default
|
||||
modified_sr(E_FLAG) <= '1';
|
||||
-- Clear extension flag according to the scaling mode
|
||||
case scaling_mode is
|
||||
when "00" =>
|
||||
if alu_post_adder_result(55 downto 47) = "111111111" or alu_post_adder_result(55 downto 47) = "000000000" then
|
||||
modified_sr(E_FLAG) <= '0';
|
||||
end if;
|
||||
when "01" =>
|
||||
if alu_post_adder_result(55 downto 48) = "11111111" or alu_post_adder_result(55 downto 48) = "00000000" then
|
||||
modified_sr(E_FLAG) <= '0';
|
||||
end if;
|
||||
when "10" =>
|
||||
if alu_post_adder_result(55 downto 46) = "1111111111" or alu_post_adder_result(55 downto 46) = "0000000000" then
|
||||
modified_sr(E_FLAG) <= '0';
|
||||
end if;
|
||||
when others =>
|
||||
modified_sr(E_FLAG) <= '0';
|
||||
end case;
|
||||
when others => -- Don't touch
|
||||
end case;
|
||||
|
||||
-- Limit flag generation (equals overflow flag generaton!)
|
||||
-- Clearing of the Limit flag has to be done by the user!
|
||||
-----------------------------------------------------------
|
||||
case alu_ctrl.ccr_flags_ctrl(L_FLAG) is
|
||||
when CLEAR => modified_sr(L_FLAG) <= '0';
|
||||
when SET => modified_sr(L_FLAG) <= '1';
|
||||
when MODIFY =>
|
||||
-- There are two sources for the overflow flag:
|
||||
-- 1)
|
||||
-- in case the result cannot be represented using 56 bits set
|
||||
-- the overflow flag. this is the case when the two MSBs of
|
||||
-- the 57 bit result are different
|
||||
-- 2)
|
||||
-- The shifter circuit performs a 56 bit left shift. In case the
|
||||
-- two MSBs of the operand are different set the overflow flag as well
|
||||
if (alu_ctrl.div_instr = '0' and alu_post_adder_result(56) /= alu_post_adder_result(55)) or
|
||||
(alu_ctrl.shift_mode = SHIFT_LEFT and alu_ctrl.word_24_update = '0' and
|
||||
alu_shifter_overflow_out = '1' ) then
|
||||
modified_sr(L_FLAG) <= '1';
|
||||
end if;
|
||||
when others => -- Don't touch
|
||||
end case;
|
||||
|
||||
-- Scaling flag generation (DSP56002 and up)
|
||||
--------------------------------------------
|
||||
-- Scaling flag is not generated in the ALU, but when A or B are read to the XDB or YDB
|
||||
|
||||
end process;
|
||||
|
||||
|
||||
src_operand_select: process(register_file, alu_ctrl) is
|
||||
begin
|
||||
-- decoding according similar to JJJ representation
|
||||
case alu_ctrl.add_src_stage_1 is
|
||||
when "000" =>
|
||||
-- select depending on destination accu
|
||||
if alu_ctrl.dst_accu = '0' then
|
||||
alu_src_op <= register_file.a;
|
||||
else
|
||||
alu_src_op <= register_file.b;
|
||||
end if;
|
||||
when "001" => -- A,B or B,A
|
||||
-- select depending on destination accu
|
||||
if alu_ctrl.dst_accu = '0' then
|
||||
alu_src_op <= register_file.b;
|
||||
else
|
||||
alu_src_op <= register_file.a;
|
||||
end if;
|
||||
when "010" => -- X
|
||||
alu_src_op(55 downto 48) <= (others => register_file.x1(23));
|
||||
alu_src_op(47 downto 0) <= register_file.x1 & register_file.x0;
|
||||
when "011" => -- Y
|
||||
alu_src_op(55 downto 48) <= (others => register_file.y1(23));
|
||||
alu_src_op(47 downto 0) <= register_file.y1 & register_file.y0;
|
||||
when "100" => -- x0
|
||||
alu_src_op(55 downto 48) <= (others => register_file.x0(23));
|
||||
alu_src_op(47 downto 24) <= register_file.x0;
|
||||
alu_src_op(23 downto 0) <= (others => '0');
|
||||
when "101" => -- y0
|
||||
alu_src_op(55 downto 48) <= (others => register_file.y0(23));
|
||||
alu_src_op(47 downto 24) <= register_file.y0;
|
||||
alu_src_op(23 downto 0) <= (others => '0');
|
||||
when "110" => -- x1
|
||||
alu_src_op(55 downto 48) <= (others => register_file.x1(23));
|
||||
alu_src_op(47 downto 24) <= register_file.x1;
|
||||
alu_src_op(23 downto 0) <= (others => '0');
|
||||
when "111" => -- y1
|
||||
alu_src_op(55 downto 48) <= (others => register_file.y1(23));
|
||||
alu_src_op(47 downto 24) <= register_file.y1;
|
||||
alu_src_op(23 downto 0) <= (others => '0');
|
||||
when others =>
|
||||
end case;
|
||||
end process;
|
||||
|
||||
alu_logical_functions: process(alu_ctrl, alu_src_op, alu_shifter_out) is
|
||||
begin
|
||||
alu_logic_conj <= alu_shifter_out;
|
||||
case alu_ctrl.logic_function is
|
||||
when "110" =>
|
||||
alu_logic_conj(47 downto 24) <= alu_shifter_out(47 downto 24) and alu_src_op(47 downto 24);
|
||||
when "010" =>
|
||||
alu_logic_conj(47 downto 24) <= alu_shifter_out(47 downto 24) or alu_src_op(47 downto 24);
|
||||
when "011" =>
|
||||
alu_logic_conj(47 downto 24) <= alu_shifter_out(47 downto 24) xor alu_src_op(47 downto 24);
|
||||
when "111" =>
|
||||
alu_logic_conj(47 downto 24) <= not alu_shifter_out(47 downto 24);
|
||||
when others =>
|
||||
end case;
|
||||
end process;
|
||||
|
||||
alu_adder : process(alu_ctrl, alu_src_op, alu_multiplier_out, alu_shifter_out) is
|
||||
variable add_src_op_1 : signed(56 downto 0);
|
||||
variable add_src_op_2 : signed(56 downto 0);
|
||||
variable carry_const : signed(56 downto 0);
|
||||
variable alu_shifter_out_57 : signed(56 downto 0);
|
||||
variable alu_add_result_58 : signed(57 downto 0);
|
||||
variable alu_add_result_interm : signed(56 downto 0);
|
||||
variable invert_carry_flag : std_logic;
|
||||
begin
|
||||
|
||||
-- by default do not invert the carry
|
||||
invert_carry_flag := '0';
|
||||
|
||||
-- determine whether to use multiplier output, the operand defined above, or zeros!
|
||||
-- resizing is done here already. Like that we can see whether an overflow
|
||||
-- occurs due to negating the source operand
|
||||
case alu_ctrl.add_src_stage_2 is
|
||||
when "00" => add_src_op_1 := (others => '0');
|
||||
when "10" => add_src_op_1 := resize(alu_multiplier_out, 57);
|
||||
when others => add_src_op_1 := resize(alu_src_op, 57);
|
||||
end case;
|
||||
|
||||
-- determine the sign for the 1st operand!
|
||||
case alu_ctrl.add_src_sign is
|
||||
-- normal operation
|
||||
when "00" => add_src_op_1 := add_src_op_1;
|
||||
-- negative sign
|
||||
when "01" => add_src_op_1 := - add_src_op_1;
|
||||
invert_carry_flag := not invert_carry_flag;
|
||||
-- change according to sign
|
||||
-- performs - | accu | for the CMPM instruction
|
||||
when "10" =>
|
||||
-- we subtract in any case, so invert the carry!
|
||||
invert_carry_flag := not invert_carry_flag;
|
||||
if add_src_op_1(55) = '0' then
|
||||
add_src_op_1 := - add_src_op_1;
|
||||
else
|
||||
add_src_op_1 := add_src_op_1;
|
||||
end if;
|
||||
-- div instruction!
|
||||
-- sign dependant of D[55] XOR S[23], if 1 => positive , if 0 => negative
|
||||
-- add_src_op_1 holds S[23] (sign extension!)
|
||||
when others =>
|
||||
if (alu_ctrl.shift_src = '0' and add_src_op_1(55) /= register_file.a(55)) or
|
||||
(alu_ctrl.shift_src = '1' and add_src_op_1(55) /= register_file.b(55)) then
|
||||
add_src_op_1 := add_src_op_1;
|
||||
else
|
||||
add_src_op_1 := - add_src_op_1;
|
||||
-- invert_carry_flag := not invert_carry_flag;
|
||||
end if;
|
||||
end case;
|
||||
|
||||
alu_shifter_out_57 := resize(alu_shifter_out, 57);
|
||||
|
||||
-- determine the sign for the 2nd operand (coming from the shifter)!
|
||||
case alu_ctrl.shift_src_sign is
|
||||
-- negative sign
|
||||
when "01" =>
|
||||
add_src_op_2 := - alu_shifter_out_57;
|
||||
-- change according to sign
|
||||
-- this allows to build the magnitude (ABS, CMPM)
|
||||
when "10" =>
|
||||
if alu_shifter_out(55) = '1' then
|
||||
add_src_op_2 := - alu_shifter_out_57;
|
||||
else
|
||||
add_src_op_2 := alu_shifter_out_57;
|
||||
end if;
|
||||
when others =>
|
||||
add_src_op_2 := alu_shifter_out_57;
|
||||
end case;
|
||||
|
||||
-- determine whether carry flag has to be added or subtracted
|
||||
if alu_ctrl.rounding_used = "10" then
|
||||
carry_const := (others => '0');
|
||||
-- add carry flag
|
||||
carry_const(0) := register_file.sr(C_FLAG);
|
||||
elsif alu_ctrl.rounding_used = "11" then
|
||||
-- subtract carry flag
|
||||
carry_const := (others => register_file.sr(0)); -- carry flag
|
||||
else
|
||||
carry_const := (others => '0');
|
||||
end if;
|
||||
|
||||
-- add the values and calculate the carry bit
|
||||
alu_add_result_interm := ('0' & add_src_op_1(55 downto 0)) +
|
||||
('0' & add_src_op_2(55 downto 0)) +
|
||||
('0' & carry_const(55 downto 0));
|
||||
|
||||
-- here pops the new carry out of the adder
|
||||
if invert_carry_flag = '0' then
|
||||
alu_add_carry_out <= alu_add_result_interm(56);
|
||||
else
|
||||
alu_add_carry_out <= not alu_add_result_interm(56);
|
||||
end if;
|
||||
|
||||
-- calculate the last bit (56), in order to test for overflow later on
|
||||
alu_add_result(55 downto 0) <= alu_add_result_interm(55 downto 0);
|
||||
-- alu_add_result(56) <= add_src_op_1(56) xor add_src_op_2(56) xor alu_add_result_interm(56);
|
||||
alu_add_result(56) <= add_src_op_1(56) xor add_src_op_2(56)
|
||||
xor carry_const(56) xor alu_add_result_interm(56);
|
||||
|
||||
end process alu_adder;
|
||||
|
||||
|
||||
-- Adder after the normal arithmetic adder
|
||||
-- This adder is responsible for
|
||||
-- -- 1) carry addition
|
||||
-- -- 2) carry subtration
|
||||
-- 3) convergent rounding
|
||||
alu_post_adder: process(alu_add_result, scaling_mode, alu_ctrl) is
|
||||
variable post_adder_constant : signed(56 downto 0);
|
||||
variable testing_constant : signed(24 downto 0);
|
||||
begin
|
||||
-- by default add nothing
|
||||
post_adder_constant := (others => '0');
|
||||
|
||||
case alu_ctrl.rounding_used is
|
||||
-- rounding dependant on scaling bits
|
||||
when "01" =>
|
||||
case scaling_mode is
|
||||
-- no scaling
|
||||
when "00" => testing_constant := alu_add_result(23 downto 0) & '0';
|
||||
-- scale down
|
||||
when "01" => testing_constant := alu_add_result(24 downto 0);
|
||||
-- scale up
|
||||
when "10" => testing_constant := alu_add_result(22 downto 0) & "00";
|
||||
when others =>
|
||||
testing_constant := alu_add_result(23 downto 0) & '0';
|
||||
end case;
|
||||
|
||||
-- Special case!
|
||||
if testing_constant(24) = '1' and testing_constant(23 downto 0) = X"000000" then
|
||||
-- add depending on bit left to the rounding position
|
||||
case scaling_mode is
|
||||
-- no scaling
|
||||
when "00" => post_adder_constant(23) := alu_add_result(24);
|
||||
-- scale down
|
||||
when "01" => post_adder_constant(24) := alu_add_result(25);
|
||||
-- scale up
|
||||
when "10" => post_adder_constant(22) := alu_add_result(23);
|
||||
when others =>
|
||||
end case;
|
||||
else -- testing_constant /= X"1000000"
|
||||
-- add rounding constant depending on scaling mode
|
||||
-- results in round up if MSB of testing constant is set, else nothing happens
|
||||
case scaling_mode is
|
||||
-- no scaling
|
||||
when "00" => post_adder_constant(23) := '1';
|
||||
-- scale down
|
||||
when "01" => post_adder_constant(24) := '1';
|
||||
-- scale up
|
||||
when "10" => post_adder_constant(22) := '1';
|
||||
when others =>
|
||||
end case;
|
||||
end if;
|
||||
-- no rounding
|
||||
when others =>
|
||||
post_adder_constant := (others => '0');
|
||||
|
||||
end case;
|
||||
|
||||
-- Add the result of the first adder to the constant (e.g., carry flag)
|
||||
alu_post_adder_result <= alu_add_result + post_adder_constant;
|
||||
|
||||
-- When rounding is used set 24 LSBs to zero!
|
||||
if alu_ctrl.rounding_used = "01" then
|
||||
alu_post_adder_result(23 downto 0) <= (others => '0');
|
||||
end if;
|
||||
end process;
|
||||
|
||||
|
||||
|
||||
alu_select_new_accu: process(alu_post_adder_result, alu_logic_conj, alu_ctrl) is
|
||||
begin
|
||||
if alu_ctrl.logic_function /= "000" then
|
||||
modified_accu_int <= alu_logic_conj;
|
||||
else
|
||||
modified_accu_int <= alu_post_adder_result(55 downto 0);
|
||||
end if;
|
||||
end process;
|
||||
|
||||
|
||||
-- contains the 24*24 bit fractional multiplier
|
||||
alu_multiplier : process(register_file, alu_ctrl) is
|
||||
variable src_op1: signed(23 downto 0);
|
||||
variable src_op2: signed(23 downto 0);
|
||||
variable mul_result_interm : signed(47 downto 0);
|
||||
begin
|
||||
-- select source operands for multiplication
|
||||
case alu_ctrl.mul_op1 is
|
||||
when "00" => src_op1 := register_file.x0;
|
||||
when "01" => src_op1 := register_file.x1;
|
||||
when "10" => src_op1 := register_file.y0;
|
||||
when others => src_op1 := register_file.y1;
|
||||
end case;
|
||||
case alu_ctrl.mul_op2 is
|
||||
when "00" => src_op2 := register_file.x0;
|
||||
when "01" => src_op2 := register_file.x1;
|
||||
when "10" => src_op2 := register_file.y0;
|
||||
when others => src_op2 := register_file.y1;
|
||||
end case;
|
||||
|
||||
-- perform integer multiplication
|
||||
mul_result_interm := src_op1 * src_op2;
|
||||
|
||||
-- sign extension of result
|
||||
alu_multiplier_out(55 downto 48) <= (others => mul_result_interm(47));
|
||||
-- convert from two's complement representation to fractional format
|
||||
-- signed integer multiplication delivers twice the sign bit, but only one is needed for the
|
||||
-- fractional multiplication, so remove one and append a zero to the result
|
||||
alu_multiplier_out(47 downto 0) <= mul_result_interm(46 downto 0) & '0';
|
||||
|
||||
end process alu_multiplier;
|
||||
|
||||
|
||||
-- contains the data shifter
|
||||
alu_shifter: process(register_file, alu_ctrl, norm_instr_asl, norm_instr_asr) is
|
||||
variable src_accu : signed(55 downto 0);
|
||||
variable shift_to_perform : alu_shift_mode;
|
||||
begin
|
||||
-- read source accumulator
|
||||
if alu_ctrl.shift_src = '0' then
|
||||
src_accu := register_file.a;
|
||||
else
|
||||
src_accu := register_file.b;
|
||||
end if;
|
||||
|
||||
alu_shifter_carry_out <= '0';
|
||||
alu_shifter_overflow_out <= '0';
|
||||
|
||||
-- NORM instruction determines the shift value just
|
||||
-- in time, so overwrite the flag from the alu_ctrl
|
||||
-- for this instruction by the calculated value
|
||||
if alu_ctrl.norm_instr = '0' then
|
||||
shift_to_perform := alu_ctrl.shift_mode;
|
||||
else
|
||||
if norm_instr_asl = '1' then
|
||||
shift_to_perform := SHIFT_LEFT;
|
||||
elsif norm_instr_asr = '1' then
|
||||
shift_to_perform := SHIFT_RIGHT;
|
||||
else
|
||||
shift_to_perform := NO_SHIFT;
|
||||
end if;
|
||||
end if;
|
||||
|
||||
case shift_to_perform is
|
||||
when NO_SHIFT =>
|
||||
alu_shifter_out <= src_accu;
|
||||
when SHIFT_LEFT =>
|
||||
-- ASL, ADDL, DIV?
|
||||
if alu_ctrl.word_24_update = '0' then
|
||||
-- special handling for div instruction required
|
||||
if alu_ctrl.div_instr = '1' then
|
||||
alu_shifter_out <= src_accu(54 downto 0) & register_file.sr(C_FLAG);
|
||||
else
|
||||
alu_shifter_out <= src_accu(54 downto 0) & '0';
|
||||
end if;
|
||||
alu_shifter_carry_out <= src_accu(55);
|
||||
-- detect overflow that results from left shifting
|
||||
-- Needed for ASL, ADDL, DIV instructions
|
||||
if src_accu(55) /= src_accu(54) then
|
||||
alu_shifter_overflow_out <= '1';
|
||||
end if;
|
||||
-- LSL/ROL?
|
||||
elsif alu_ctrl.word_24_update = '1' then
|
||||
alu_shifter_out(55 downto 48) <= src_accu(55 downto 48);
|
||||
alu_shifter_out(23 downto 0) <= src_accu(23 downto 0);
|
||||
alu_shifter_carry_out <= src_accu(47);
|
||||
if alu_ctrl.rotate = '0' then -- LSL ?
|
||||
alu_shifter_out(47 downto 24) <= src_accu(46 downto 24) & '0';
|
||||
else -- ROL ?
|
||||
alu_shifter_out(47 downto 24) <= src_accu(46 downto 24) & register_file.sr(C_FLAG);
|
||||
end if;
|
||||
end if;
|
||||
when SHIFT_RIGHT =>
|
||||
-- ASR?
|
||||
if alu_ctrl.word_24_update = '0' then
|
||||
alu_shifter_out <= src_accu(55) & src_accu(55 downto 1);
|
||||
alu_shifter_carry_out <= src_accu(0);
|
||||
-- LSR/ROR?
|
||||
elsif alu_ctrl.word_24_update = '1' then
|
||||
alu_shifter_out(55 downto 48) <= src_accu(55 downto 48);
|
||||
alu_shifter_out(23 downto 0) <= src_accu(23 downto 0);
|
||||
alu_shifter_carry_out <= src_accu(24);
|
||||
if alu_ctrl.rotate = '0' then -- LSR
|
||||
alu_shifter_out(47 downto 24) <= '0' & src_accu(47 downto 25);
|
||||
else -- ROR
|
||||
alu_shifter_out(47 downto 24) <= register_file.sr(C_FLAG) & src_accu(47 downto 25);
|
||||
end if;
|
||||
end if;
|
||||
when ZEROS =>
|
||||
alu_shifter_out <= (others => '0');
|
||||
end case;
|
||||
end process alu_shifter;
|
||||
|
||||
|
||||
-- Special handling for NORM instruction
|
||||
-- Determine which case occurs (see User's Manual for more information)
|
||||
norm_instr_logic: process(register_file, addr_r_in) is
|
||||
begin
|
||||
norm_instr_asl <= '0';
|
||||
norm_instr_asr <= '0';
|
||||
|
||||
-- Either left shift
|
||||
if register_file.sr(E_FLAG) = '0' and
|
||||
register_file.sr(U_FLAG) = '1' and
|
||||
register_file.sr(Z_FLAG) = '0' then
|
||||
norm_instr_asl <= '1';
|
||||
norm_update_ccr <= '1';
|
||||
addr_r_out <= addr_r_in - 1;
|
||||
-- Or right shift
|
||||
elsif register_file.sr(E_FLAG) = '1' then
|
||||
norm_instr_asr <= '1';
|
||||
norm_update_ccr <= '1';
|
||||
addr_r_out <= addr_r_in + 1;
|
||||
-- Or do nothing!
|
||||
else
|
||||
norm_update_ccr <= '0';
|
||||
addr_r_out <= addr_r_in;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
end architecture;
|
||||
86
FireBee/trunk/vhdl/dsp56k/src/exec_stage_bit_modify.vhd
Normal file
86
FireBee/trunk/vhdl/dsp56k/src/exec_stage_bit_modify.vhd
Normal file
@@ -0,0 +1,86 @@
|
||||
-----------------------------------------------------------------------------
|
||||
--! @file
|
||||
--! @author Matthias Alles
|
||||
--! @date 01/2009
|
||||
--! @brief Bit modify (BCLR, BSET, J(S)CLR, J(S)SET)
|
||||
--!
|
||||
------------------------------------------------------------------------------
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.numeric_std.all;
|
||||
library work;
|
||||
use work.parameter_pkg.all;
|
||||
use work.types_pkg.all;
|
||||
use work.constants_pkg.all;
|
||||
|
||||
entity exec_stage_bit_modify is port(
|
||||
instr_word : in std_logic_vector(23 downto 0);
|
||||
instr_array : in instructions_type;
|
||||
src_operand : in std_logic_vector(23 downto 0);
|
||||
register_file : in register_file_type;
|
||||
dst_operand : out std_logic_vector(23 downto 0);
|
||||
bit_cond_met : out std_logic;
|
||||
modify_sr : out std_logic;
|
||||
modified_sr : out std_logic_vector(15 downto 0)
|
||||
);
|
||||
end entity;
|
||||
|
||||
|
||||
architecture rtl of exec_stage_bit_modify is
|
||||
|
||||
signal operand_bit : std_logic;
|
||||
signal src_operand_32 : std_logic_vector(31 downto 0);
|
||||
|
||||
begin
|
||||
|
||||
-- this is just a helper signal to prevent the simulator
|
||||
-- to stop when accessing a bit > 23.
|
||||
src_operand_32 <= "00000000" & src_operand;
|
||||
-- read the bit we want to test (and modify)
|
||||
operand_bit <= src_operand_32(to_integer(unsigned(instr_word(4 downto 0))));
|
||||
|
||||
-- modify the Carry flag only for the bit modify instructions!
|
||||
modify_sr <= '1' when instr_array = INSTR_BCLR or instr_array = INSTR_BSET or instr_array = INSTR_BCHG or instr_array = INSTR_BTST else '0';
|
||||
modified_sr <= register_file.sr(15 downto 1) & operand_bit;
|
||||
|
||||
bit_operation: process(instr_word, instr_array, src_operand, operand_bit) is
|
||||
variable new_bit : std_logic;
|
||||
begin
|
||||
-- do nothing by default!
|
||||
dst_operand <= src_operand;
|
||||
bit_cond_met <= '0';
|
||||
|
||||
-- determine which bit to write
|
||||
if instr_array = INSTR_BCLR then
|
||||
new_bit := '0';
|
||||
elsif instr_array = INSTR_BSET then
|
||||
new_bit := '1';
|
||||
else -- BCHG
|
||||
new_bit := not operand_bit;
|
||||
end if;
|
||||
|
||||
if instr_array = INSTR_BCLR or instr_array = INSTR_BSET or instr_array = INSTR_BCHG then
|
||||
dst_operand(to_integer(unsigned(instr_word(4 downto 0)))) <= new_bit;
|
||||
end if;
|
||||
|
||||
|
||||
-- check for the jump instructions whether condition is met or not!
|
||||
if instr_array = INSTR_JCLR or instr_array = INSTR_JSCLR then
|
||||
if operand_bit = '0' then
|
||||
bit_cond_met <= '1';
|
||||
else
|
||||
bit_cond_met <= '0';
|
||||
end if;
|
||||
end if;
|
||||
if instr_array = INSTR_JSET or instr_array = INSTR_JSSET then
|
||||
if operand_bit = '0' then
|
||||
bit_cond_met <= '0';
|
||||
else
|
||||
bit_cond_met <= '1';
|
||||
end if;
|
||||
end if;
|
||||
|
||||
end process;
|
||||
|
||||
|
||||
end architecture;
|
||||
124
FireBee/trunk/vhdl/dsp56k/src/exec_stage_branch.vhd
Normal file
124
FireBee/trunk/vhdl/dsp56k/src/exec_stage_branch.vhd
Normal file
@@ -0,0 +1,124 @@
|
||||
-----------------------------------------------------------------------------
|
||||
--! @file
|
||||
--! @author Matthias Alles
|
||||
--! @date 01/2009
|
||||
--! @brief Branch control
|
||||
--!
|
||||
------------------------------------------------------------------------------
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.numeric_std.all;
|
||||
library work;
|
||||
use work.parameter_pkg.all;
|
||||
use work.types_pkg.all;
|
||||
use work.constants_pkg.all;
|
||||
|
||||
entity exec_stage_branch is port(
|
||||
activate_exec_bra : in std_logic;
|
||||
instr_word : in std_logic_vector(23 downto 0);
|
||||
instr_array : in instructions_type;
|
||||
register_file : in register_file_type;
|
||||
jump_address : in unsigned(BW_ADDRESS-1 downto 0);
|
||||
bit_cond_met : in std_logic;
|
||||
cc_flag_set : in std_logic;
|
||||
push_stack : out push_stack_type;
|
||||
pop_stack : out pop_stack_type;
|
||||
modify_pc : out std_logic;
|
||||
modified_pc : out unsigned(BW_ADDRESS-1 downto 0);
|
||||
modify_sr : out std_logic;
|
||||
modified_sr : out std_logic_vector(15 downto 0)
|
||||
);
|
||||
end entity;
|
||||
|
||||
|
||||
architecture rtl of exec_stage_branch is
|
||||
|
||||
signal branch_condition_met : std_logic;
|
||||
signal modify_pc_int : std_logic;
|
||||
|
||||
begin
|
||||
|
||||
modify_pc_int <= '1' when activate_exec_bra = '1' and branch_condition_met = '1' else '0';
|
||||
modify_pc <= modify_pc_int;
|
||||
|
||||
calculate_branch_condition : process(instr_word, instr_array, register_file, bit_cond_met)
|
||||
begin
|
||||
branch_condition_met <= '0';
|
||||
|
||||
-- unconditional jumps
|
||||
if instr_array = INSTR_JMP or
|
||||
instr_array = INSTR_JSR or
|
||||
instr_array = INSTR_RTI or
|
||||
instr_array = INSTR_RTS then
|
||||
-- jump always
|
||||
branch_condition_met <= '1';
|
||||
end if;
|
||||
-- then see whether the branch condition is satisfied
|
||||
if instr_array = INSTR_JCC or instr_array = INSTR_JSCC then
|
||||
branch_condition_met <= cc_flag_set;
|
||||
end if;
|
||||
-- jmp that is executed according to a certain bit condition
|
||||
if instr_array = INSTR_JCLR or instr_array = INSTR_JSCLR or
|
||||
instr_array = INSTR_JSET or instr_array = INSTR_JSSET then
|
||||
branch_condition_met <= bit_cond_met;
|
||||
end if;
|
||||
end process calculate_branch_condition;
|
||||
|
||||
|
||||
calculate_branch_target : process(instr_array, instr_word, jump_address)
|
||||
begin
|
||||
modified_pc <= jump_address;
|
||||
|
||||
-- address calculation is the same for the following instructions
|
||||
if instr_array = INSTR_JMP or
|
||||
instr_array = INSTR_JCC or
|
||||
instr_array = INSTR_JSCC or
|
||||
instr_array = INSTR_JSR then
|
||||
if instr_word(18) = '1' then
|
||||
-- short jump address included in opcode (bits 11 downto 0)
|
||||
modified_pc(11 downto 0) <= unsigned(instr_word(11 downto 0));
|
||||
elsif instr_word(18) = '0' then
|
||||
-- effective address defined by opcode and coming from address generator unit
|
||||
modified_pc <= jump_address;
|
||||
end if;
|
||||
end if;
|
||||
|
||||
-- jump address contains the obligatory address of the second
|
||||
-- instruction word
|
||||
if instr_array = INSTR_JCLR or
|
||||
instr_array = INSTR_JSET or
|
||||
instr_array = INSTR_JSCLR or
|
||||
instr_array = INSTR_JSSET then
|
||||
modified_pc <= jump_address;
|
||||
end if;
|
||||
|
||||
-- target address is stored on the stack
|
||||
if instr_array = INSTR_RTS or
|
||||
instr_array = INSTR_RTI then
|
||||
modified_pc <= unsigned(register_file.current_ssh);
|
||||
end if;
|
||||
end process calculate_branch_target;
|
||||
|
||||
-- Subroutine functions need to store PC and SR on the stack
|
||||
push_stack.valid <= '1' when modify_pc_int = '1' and (instr_array = INSTR_JSCC or instr_array = INSTR_JSR or
|
||||
instr_array = INSTR_JSCLR or instr_array = INSTR_JSSET) else '0';
|
||||
push_stack.content <= PC_AND_SR;
|
||||
-- pc is set externally!
|
||||
push_stack.pc <= (others => '0');
|
||||
|
||||
-- RTI/RTS instructions need to read from the stack
|
||||
pop_stack.valid <= '1' when modify_pc_int = '1' and (instr_array = INSTR_RTI or instr_array = INSTR_RTS) else '0';
|
||||
|
||||
-- some instructions require to set the SR
|
||||
calculate_status_register : process(instr_array)
|
||||
begin
|
||||
modify_sr <= '0';
|
||||
modified_sr <= (others => '0');
|
||||
if instr_array = INSTR_RTI then
|
||||
modify_sr <= '1';
|
||||
modified_sr <= register_file.current_ssl;
|
||||
end if;
|
||||
end process calculate_status_register;
|
||||
|
||||
|
||||
end architecture rtl;
|
||||
82
FireBee/trunk/vhdl/dsp56k/src/exec_stage_cc_flag_calc.vhd
Normal file
82
FireBee/trunk/vhdl/dsp56k/src/exec_stage_cc_flag_calc.vhd
Normal file
@@ -0,0 +1,82 @@
|
||||
-----------------------------------------------------------------------------
|
||||
--! @file
|
||||
--! @author Matthias Alles
|
||||
--! @date 01/2009
|
||||
--! @brief Calculate whether cc flag condition is true
|
||||
--!
|
||||
------------------------------------------------------------------------------
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.numeric_std.all;
|
||||
library work;
|
||||
use work.parameter_pkg.all;
|
||||
use work.types_pkg.all;
|
||||
use work.constants_pkg.all;
|
||||
|
||||
entity exec_stage_cc_flag_calc is port(
|
||||
instr_word : in std_logic_vector(23 downto 0);
|
||||
instr_array : in instructions_type;
|
||||
register_file : in register_file_type;
|
||||
cc_flag_set : out std_logic
|
||||
);
|
||||
end entity;
|
||||
|
||||
|
||||
architecture rtl of exec_stage_cc_flag_calc is
|
||||
|
||||
|
||||
begin
|
||||
|
||||
calculate_cc_flag : process(instr_word, instr_array, register_file)
|
||||
|
||||
variable cc_select : std_logic_vector(3 downto 0);
|
||||
|
||||
procedure calculate_cc_flag(cc: std_logic_vector(3 downto 0)) is
|
||||
variable c_flag : std_logic := register_file.ccr(0);
|
||||
variable v_flag : std_logic := register_file.ccr(1);
|
||||
variable z_flag : std_logic := register_file.ccr(2);
|
||||
variable n_flag : std_logic := register_file.ccr(3);
|
||||
variable u_flag : std_logic := register_file.ccr(4);
|
||||
variable e_flag : std_logic := register_file.ccr(5);
|
||||
variable l_flag : std_logic := register_file.ccr(6);
|
||||
|
||||
begin
|
||||
if (cc = "0000" and c_flag = '0') or -- CC: carry clear
|
||||
(cc = "1000" and c_flag = '1') or -- CS: carry set
|
||||
(cc = "0101" and e_flag = '0') or -- EC: extension clear
|
||||
(cc = "1010" and z_flag = '1') or -- EQ: equal
|
||||
(cc = "1101" and e_flag = '1') or -- ES: extension set
|
||||
(cc = "0001" and (n_flag = v_flag)) or -- GE: greater than or equal
|
||||
(cc = "0001" and ((n_flag xor v_flag) or z_flag) = '0') or -- GT: greater than
|
||||
(cc = "0110" and l_flag = '0') or -- LC: limit clear
|
||||
(cc = "1111" and ((n_flag xor v_flag) or z_flag ) = '1') or -- LE: less or equal
|
||||
(cc = "1110" and l_flag = '1') or -- LS: limit set
|
||||
(cc = "1001" and (n_flag /= v_flag)) or -- LT: less than
|
||||
(cc = "1011" and n_flag = '1') or -- MI: minus
|
||||
(cc = "0010" and z_flag = '0') or -- NE: not equal
|
||||
(cc = "1100" and (( not u_flag and not e_flag) or z_flag) = '1') or -- NR: normalized
|
||||
(cc = "0011" and n_flag = '0') or -- PL: plus
|
||||
(cc = "0100" and (( not u_flag and not e_flag ) or z_flag) = '0') -- NN: not normalized
|
||||
then
|
||||
cc_flag_set <= '1';
|
||||
end if;
|
||||
end procedure;
|
||||
|
||||
begin
|
||||
|
||||
cc_flag_set <= '0';
|
||||
|
||||
-- Rip the flags we have to test for from the instruction word
|
||||
if (instr_array = INSTR_JCC and instr_word(18) = '0') or
|
||||
(instr_array = INSTR_JSCC) then
|
||||
cc_select := instr_word(3 downto 0);
|
||||
else
|
||||
cc_select := instr_word(15 downto 12);
|
||||
end if;
|
||||
|
||||
calculate_cc_flag(cc_select);
|
||||
|
||||
end process;
|
||||
|
||||
|
||||
end architecture;
|
||||
79
FireBee/trunk/vhdl/dsp56k/src/exec_stage_cr_mod.vhd
Normal file
79
FireBee/trunk/vhdl/dsp56k/src/exec_stage_cr_mod.vhd
Normal file
@@ -0,0 +1,79 @@
|
||||
-----------------------------------------------------------------------------
|
||||
--! @file
|
||||
--! @author Matthias Alles
|
||||
--! @date 01/2009
|
||||
--! @brief
|
||||
--!
|
||||
------------------------------------------------------------------------------
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.numeric_std.all;
|
||||
library work;
|
||||
use work.parameter_pkg.all;
|
||||
use work.types_pkg.all;
|
||||
use work.constants_pkg.all;
|
||||
|
||||
entity exec_stage_cr_mod is port (
|
||||
activate_exec_cr_mod : in std_logic;
|
||||
instr_word : in std_logic_vector(23 downto 0);
|
||||
instr_array : in instructions_type;
|
||||
register_file : in register_file_type;
|
||||
modify_sr : out std_logic;
|
||||
modified_sr : out std_logic_vector(15 downto 0);
|
||||
modify_omr : out std_logic;
|
||||
modified_omr : out std_logic_vector(7 downto 0)
|
||||
);
|
||||
end exec_stage_cr_mod;
|
||||
|
||||
|
||||
architecture rtl of exec_stage_cr_mod is
|
||||
|
||||
begin
|
||||
|
||||
process(activate_exec_cr_mod, instr_word, instr_array, register_file) is
|
||||
variable imm8 : std_logic_vector(7 downto 0);
|
||||
variable op8 : std_logic_vector(7 downto 0);
|
||||
variable res8 : std_logic_vector(7 downto 0);
|
||||
begin
|
||||
modify_sr <= '0';
|
||||
modify_omr <= '0';
|
||||
modified_sr <= (others => '0');
|
||||
modified_omr <= (others => '0');
|
||||
|
||||
imm8 := instr_word(15 downto 8);
|
||||
if instr_word(1 downto 0) = "00" then
|
||||
-- read MR
|
||||
op8 := register_file.mr;
|
||||
elsif instr_word(1 downto 0) = "01" then
|
||||
-- read CCR
|
||||
op8 := register_file.ccr;
|
||||
else -- instr_word(1 downto 0) = "10"
|
||||
-- read OMR
|
||||
op8 := register_file.omr;
|
||||
end if;
|
||||
|
||||
if instr_array = INSTR_ANDI then
|
||||
res8 := imm8 and op8;
|
||||
else -- instr_array = INSTR_ORI
|
||||
res8 := imm8 or op8;
|
||||
end if;
|
||||
|
||||
-- only write the result when activated
|
||||
if activate_exec_cr_mod = '1' then
|
||||
if instr_word(1 downto 0) = "00" then
|
||||
-- update MR
|
||||
modify_sr <= '1';
|
||||
modified_sr <= res8 & register_file.ccr;
|
||||
elsif instr_word(1 downto 0) = "01" then
|
||||
-- update CCR
|
||||
modify_sr <= '1';
|
||||
modified_sr <= register_file.mr & res8;
|
||||
elsif instr_word(1 downto 0) = "10" then
|
||||
-- update OMR
|
||||
modify_omr <= '1';
|
||||
modified_omr <= res8;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
end architecture;
|
||||
207
FireBee/trunk/vhdl/dsp56k/src/exec_stage_loops.vhd
Normal file
207
FireBee/trunk/vhdl/dsp56k/src/exec_stage_loops.vhd
Normal file
@@ -0,0 +1,207 @@
|
||||
------------------------------------------------------------------------------
|
||||
--! @file
|
||||
--! @author Matthias Alles
|
||||
--! @date 01/2009
|
||||
--! @brief Loop control (REP, DO, ENDDO)
|
||||
--!
|
||||
------------------------------------------------------------------------------
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.numeric_std.all;
|
||||
library work;
|
||||
use work.parameter_pkg.all;
|
||||
use work.types_pkg.all;
|
||||
use work.constants_pkg.all;
|
||||
|
||||
entity exec_stage_loop is port(
|
||||
clk, rst : in std_logic;
|
||||
activate_exec_loop : in std_logic;
|
||||
instr_word : in std_logic_vector(23 downto 0);
|
||||
instr_array : in instructions_type;
|
||||
loop_iterations : in unsigned(15 downto 0);
|
||||
loop_address : in unsigned(BW_ADDRESS-1 downto 0);
|
||||
loop_start_address: in unsigned(BW_ADDRESS-1 downto 0);
|
||||
register_file : in register_file_type;
|
||||
fetch_perform_enddo: in std_logic;
|
||||
memory_stall : in std_logic;
|
||||
push_stack : out push_stack_type;
|
||||
pop_stack : out pop_stack_type;
|
||||
stall_rep : out std_logic;
|
||||
stall_do : out std_logic;
|
||||
decrement_lc : out std_logic;
|
||||
modify_lc : out std_logic;
|
||||
modified_lc : out unsigned(15 downto 0);
|
||||
modify_la : out std_logic;
|
||||
modified_la : out unsigned(15 downto 0);
|
||||
modify_pc : out std_logic;
|
||||
modified_pc : out unsigned(BW_ADDRESS-1 downto 0);
|
||||
modify_sr : out std_logic;
|
||||
modified_sr : out std_logic_vector(15 downto 0)
|
||||
);
|
||||
end entity;
|
||||
|
||||
|
||||
architecture rtl of exec_stage_loop is
|
||||
|
||||
signal rep_loop_polling : std_logic;
|
||||
signal do_loop_polling : std_logic;
|
||||
signal enddo_polling : std_logic;
|
||||
signal lc_temp : unsigned(15 downto 0);
|
||||
signal rf_lc_eq_1 : std_logic;
|
||||
signal memory_stall_t : std_logic;
|
||||
|
||||
begin
|
||||
|
||||
modified_pc <= loop_start_address;
|
||||
|
||||
|
||||
-- loop counter in register file equal to 1?
|
||||
rf_lc_eq_1 <= '1' when register_file.lc = 1 else '0';
|
||||
|
||||
process(activate_exec_loop, instr_array, register_file, fetch_perform_enddo,
|
||||
rep_loop_polling, loop_iterations, rf_lc_eq_1, loop_start_address) is
|
||||
begin
|
||||
stall_rep <= '0';
|
||||
stall_do <= '0';
|
||||
|
||||
modify_la <= '0';
|
||||
modify_lc <= '0';
|
||||
modify_pc <= '0';
|
||||
modify_sr <= '0';
|
||||
modified_la <= loop_address;
|
||||
modified_lc <= loop_iterations; -- default
|
||||
-- set the loop flag LF (bit 15) of Status register
|
||||
modified_sr(15) <= '1';
|
||||
modified_sr(14 downto 0) <= register_file.sr(14 downto 0);
|
||||
|
||||
push_stack.valid <= '0'; -- push PC and SR on the stack
|
||||
push_stack.pc <= loop_start_address;
|
||||
push_stack.content <= LA_AND_LC;
|
||||
|
||||
pop_stack.valid <= '0';
|
||||
decrement_lc <= '0';
|
||||
------------------
|
||||
-- DO instruction
|
||||
------------------
|
||||
if activate_exec_loop = '1' and instr_array = INSTR_DO then
|
||||
-- first instruction of the do loop instruction?
|
||||
if do_loop_polling = '0' then
|
||||
stall_do <= '1';
|
||||
modify_lc <= '1'; -- store the new loop counter
|
||||
modify_la <= '1'; -- store the new loop address
|
||||
push_stack.valid <= '1'; -- push LA and LC on the stack
|
||||
push_stack.content <= LA_AND_LC;
|
||||
else -- second clock cycle of the do loop instruction ?
|
||||
push_stack.valid <= '1'; -- push PC and SR on the stack
|
||||
push_stack.pc <= loop_start_address;
|
||||
push_stack.content <= PC_AND_SR;
|
||||
-- set the PC to the first instruction of the loop
|
||||
-- the already fetched instruction are flushed from the pipeline
|
||||
-- this prevents problems, when the loop consists of only one or two instructions
|
||||
modify_pc <= '1';
|
||||
-- set the loop flag
|
||||
modify_sr <= '1';
|
||||
end if;
|
||||
end if;
|
||||
-----------------------------------------------
|
||||
-- ENDDO instruction / loop end in fetch stage
|
||||
-----------------------------------------------
|
||||
if (activate_exec_loop = '1' and instr_array = INSTR_ENDDO) or fetch_perform_enddo = '1' or enddo_polling = '1' then
|
||||
pop_stack.valid <= '1';
|
||||
if enddo_polling = '0' then
|
||||
-- only restore the LF from the stack
|
||||
modified_sr(15) <= register_file.current_ssl(15);
|
||||
modify_sr <= '1';
|
||||
stall_do <= '1'; -- stall one clock cycle
|
||||
else
|
||||
-- restore loop counter and loop address in second clock cycle
|
||||
modified_lc <= unsigned(register_file.current_ssl);
|
||||
modify_lc <= '1';
|
||||
modified_la <= unsigned(register_file.current_ssh);
|
||||
modify_la <= '1';
|
||||
end if;
|
||||
end if;
|
||||
-------------------
|
||||
-- REP instruction
|
||||
-------------------
|
||||
if activate_exec_loop = '1' and instr_array = INSTR_REP then
|
||||
-- only do something when there are more than 1 iterations
|
||||
-- the first execution is already on the way
|
||||
if loop_iterations /= 1 then
|
||||
stall_rep <= '1'; -- stall the fetch and decode stages
|
||||
modify_lc <= '1'; -- store the loop counter
|
||||
modified_lc <= loop_iterations - 1;
|
||||
end if;
|
||||
end if;
|
||||
|
||||
-- keep processing the single instruction
|
||||
if rep_loop_polling = '1' then
|
||||
stall_rep <= '1';
|
||||
-- if the REP instruction caused a stall do not modify the lc!
|
||||
if memory_stall_t = '0' then
|
||||
if rf_lc_eq_1 = '0' then
|
||||
decrement_lc <= '1';
|
||||
-- when the instruction to repeat caused a memory stall
|
||||
-- do not continue!
|
||||
else
|
||||
-- finish the REP instruction by restoring the LC
|
||||
stall_rep <= '0';
|
||||
modify_lc <= '1';
|
||||
modified_lc <= lc_temp;
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
|
||||
-- process that allows to remember that we are processing a REP/DO instruction
|
||||
-- even though the REP instruction is not available in the pipeline anymore
|
||||
-- also store the old loop counter
|
||||
process(clk) is
|
||||
begin
|
||||
if rising_edge(clk) then
|
||||
if rst = '1' then
|
||||
rep_loop_polling <= '0';
|
||||
do_loop_polling <= '0';
|
||||
enddo_polling <= '0';
|
||||
lc_temp <= (others => '0');
|
||||
memory_stall_t <= '0';
|
||||
else
|
||||
memory_stall_t <= memory_stall;
|
||||
|
||||
if activate_exec_loop = '1' and instr_array = INSTR_REP then
|
||||
-- only do something when there are more than 1 iterations
|
||||
-- the first execution is already on the way
|
||||
if loop_iterations /= 1 then
|
||||
rep_loop_polling <= '1';
|
||||
lc_temp <= register_file.lc;
|
||||
end if;
|
||||
end if;
|
||||
-- test whether the REP instruction has been executed
|
||||
if rep_loop_polling = '1' and rf_lc_eq_1 = '1' and memory_stall_t = '0' then
|
||||
rep_loop_polling <= '0';
|
||||
end if;
|
||||
|
||||
-- do loop execution takes two clock cycles
|
||||
-- in the first clock cycle we store loop address and loop counter on the stack
|
||||
-- in the second clock cycle we store programm counter and status register on the stack
|
||||
if activate_exec_loop = '1' and instr_array = INSTR_DO then
|
||||
do_loop_polling <= '1';
|
||||
end if;
|
||||
-- clear the flag immediately again (only two cycles execution time!)
|
||||
if do_loop_polling = '1' then
|
||||
do_loop_polling <= '0';
|
||||
end if;
|
||||
|
||||
-- ENDDO instructions take two clock cycles as well!
|
||||
if (activate_exec_loop = '1' and instr_array = INSTR_ENDDO) or fetch_perform_enddo = '1' then
|
||||
enddo_polling <= '1';
|
||||
end if;
|
||||
if enddo_polling = '1' then
|
||||
enddo_polling <= '0';
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
end architecture;
|
||||
67
FireBee/trunk/vhdl/dsp56k/src/fetch_stage.vhd
Normal file
67
FireBee/trunk/vhdl/dsp56k/src/fetch_stage.vhd
Normal file
@@ -0,0 +1,67 @@
|
||||
------------------------------------------------------------------------------
|
||||
--! @file
|
||||
--! @author Matthias Alles
|
||||
--! @date 01/2009
|
||||
--! @brief Fetching from program memory
|
||||
--!
|
||||
------------------------------------------------------------------------------
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.numeric_std.all;
|
||||
library work;
|
||||
use work.parameter_pkg.all;
|
||||
use work.types_pkg.all;
|
||||
|
||||
|
||||
entity fetch_stage is port(
|
||||
|
||||
pc_old : in unsigned(BW_ADDRESS-1 downto 0);
|
||||
pc_new : out unsigned(BW_ADDRESS-1 downto 0);
|
||||
modify_pc : in std_logic;
|
||||
modified_pc : in unsigned(BW_ADDRESS-1 downto 0);
|
||||
register_file : in register_file_type;
|
||||
decrement_lc : out std_logic;
|
||||
perform_enddo : out std_logic
|
||||
|
||||
);
|
||||
end fetch_stage;
|
||||
|
||||
|
||||
architecture rtl of fetch_stage is
|
||||
|
||||
|
||||
begin
|
||||
|
||||
pc_calculation: process(pc_old, modify_pc, modified_pc, register_file) is
|
||||
begin
|
||||
decrement_lc <= '0';
|
||||
perform_enddo <= '0';
|
||||
|
||||
-- by default increment pc by one
|
||||
pc_new <= pc_old + 1;
|
||||
if modify_pc = '1' then
|
||||
pc_new <= modified_pc;
|
||||
end if;
|
||||
-- Loop Flag set?
|
||||
if register_file.sr(15) = '1' then
|
||||
if register_file.la = pc_old then
|
||||
-- Loop not finished?
|
||||
-- => start from the beginning if necessary
|
||||
if register_file.lc /= 1 then
|
||||
-- if the last address was LA and the loop is not finished yet, we have to
|
||||
-- read now from the beginning of the loop again
|
||||
pc_new <= unsigned(register_file.current_ssh(BW_ADDRESS-1 downto 0));
|
||||
-- decrement loop counter
|
||||
decrement_lc <= '1';
|
||||
else
|
||||
-- loop done!
|
||||
-- => tell the loop controller in the exec stage to perform the enddo operation
|
||||
-- (without flushing of the pipeline!)
|
||||
perform_enddo <= '1';
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end process pc_calculation;
|
||||
|
||||
end architecture rtl;
|
||||
|
||||
1543
FireBee/trunk/vhdl/dsp56k/src/mem_control.vhd
Normal file
1543
FireBee/trunk/vhdl/dsp56k/src/mem_control.vhd
Normal file
File diff suppressed because it is too large
Load Diff
223
FireBee/trunk/vhdl/dsp56k/src/memory_management.vhd
Normal file
223
FireBee/trunk/vhdl/dsp56k/src/memory_management.vhd
Normal file
@@ -0,0 +1,223 @@
|
||||
------------------------------------------------------------------------------
|
||||
--! @file
|
||||
--! @author Matthias Alles
|
||||
--! @date 01/2009
|
||||
--! @brief Memory controller
|
||||
--!
|
||||
--! @details This entity contains the internal memories. These are:
|
||||
--! - pmem
|
||||
--! - xmem
|
||||
--! - ymem
|
||||
--! - ROM tables
|
||||
--! - Bootup code
|
||||
--! All memory requests are collected here. Only when they are all finished
|
||||
--! the memory_stall-flag is released. External memory accesses are given to
|
||||
--! the external interface.
|
||||
--!
|
||||
------------------------------------------------------------------------------
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.numeric_std.all;
|
||||
library work;
|
||||
use work.parameter_pkg.all;
|
||||
use work.types_pkg.all;
|
||||
use work.constants_pkg.all;
|
||||
|
||||
entity memory_management is port (
|
||||
clk, rst : in std_logic;
|
||||
stall_flags : in std_logic_vector(PIPELINE_DEPTH-1 downto 0);
|
||||
memory_stall : out std_logic;
|
||||
data_rom_enable: in std_logic;
|
||||
pmem_ctrl_in : in mem_ctrl_type_in;
|
||||
pmem_ctrl_out : out mem_ctrl_type_out;
|
||||
pmem2_ctrl_in : in mem_ctrl_type_in;
|
||||
pmem2_ctrl_out : out mem_ctrl_type_out;
|
||||
xmem_ctrl_in : in mem_ctrl_type_in;
|
||||
xmem_ctrl_out : out mem_ctrl_type_out;
|
||||
ymem_ctrl_in : in mem_ctrl_type_in;
|
||||
ymem_ctrl_out : out mem_ctrl_type_out
|
||||
);
|
||||
end memory_management;
|
||||
|
||||
|
||||
architecture rtl of memory_management is
|
||||
|
||||
component mem_control is
|
||||
generic(
|
||||
mem_type : memory_type
|
||||
);
|
||||
port(
|
||||
clk, rst : in std_logic;
|
||||
rd_addr : in unsigned(BW_ADDRESS-1 downto 0);
|
||||
rd_en : in std_logic;
|
||||
data_out : out std_logic_vector(23 downto 0);
|
||||
data_out_valid : out std_logic;
|
||||
wr_addr : in unsigned(BW_ADDRESS-1 downto 0);
|
||||
wr_en : in std_logic;
|
||||
wr_accomplished : out std_logic;
|
||||
data_in : in std_logic_vector(23 downto 0)
|
||||
);
|
||||
end component mem_control;
|
||||
|
||||
signal pmem_data_out : std_logic_vector(23 downto 0);
|
||||
signal pmem_data_out_valid : std_logic;
|
||||
|
||||
signal pmem_rd_addr : unsigned(BW_ADDRESS-1 downto 0);
|
||||
signal pmem_rd_en : std_logic;
|
||||
|
||||
signal xmem_rd_en : std_logic;
|
||||
signal xmem_data_out : std_logic_vector(23 downto 0);
|
||||
signal xmem_data_out_valid : std_logic;
|
||||
signal xmem_rd_polling : std_logic;
|
||||
|
||||
signal ymem_rd_en : std_logic;
|
||||
signal ymem_data_out : std_logic_vector(23 downto 0);
|
||||
signal ymem_data_out_valid : std_logic;
|
||||
signal ymem_rd_polling : std_logic;
|
||||
|
||||
signal pmem_stall_buffer : std_logic_vector(23 downto 0);
|
||||
signal pmem_stall_buffer_valid : std_logic;
|
||||
signal xmem_stall_buffer : std_logic_vector(23 downto 0);
|
||||
signal ymem_stall_buffer : std_logic_vector(23 downto 0);
|
||||
|
||||
signal stall_flags_d : std_logic_vector(PIPELINE_DEPTH-1 downto 0);
|
||||
|
||||
begin
|
||||
|
||||
-- here it is necessary to store the output of the pmem/xmem/ymem when the pipeline enters a stall
|
||||
-- when the pipeline wakes up, this temporal result is inserted into the pipeline
|
||||
stall_buffer: process(clk) is
|
||||
begin
|
||||
if rising_edge(clk) then
|
||||
if rst = '1' then
|
||||
pmem_stall_buffer <= (others => '0');
|
||||
pmem_stall_buffer_valid <= '0';
|
||||
xmem_stall_buffer <= (others => '0');
|
||||
ymem_stall_buffer <= (others => '0');
|
||||
stall_flags_d <= (others => '0');
|
||||
else
|
||||
stall_flags_d <= stall_flags;
|
||||
if stall_flags(ST_FE2_DEC) = '1' and stall_flags_d(ST_FE2_DEC) = '0' then
|
||||
if pmem_data_out_valid = '1' then
|
||||
pmem_stall_buffer <= pmem_data_out;
|
||||
pmem_stall_buffer_valid <= '1';
|
||||
end if;
|
||||
end if;
|
||||
if stall_flags(ST_FE2_DEC) = '0' and stall_flags_d(ST_FE2_DEC) = '1' then
|
||||
pmem_stall_buffer_valid <= '0';
|
||||
end if;
|
||||
|
||||
end if;
|
||||
end if;
|
||||
end process stall_buffer;
|
||||
|
||||
memory_stall <= '1' when ( xmem_rd_en = '1' or (xmem_rd_polling = '1' and xmem_data_out_valid = '0') ) or
|
||||
( ymem_rd_en = '1' or (ymem_rd_polling = '1' and ymem_data_out_valid = '0') ) else
|
||||
'0';
|
||||
|
||||
-------------------------------
|
||||
-- PMEM CONTROLLER
|
||||
-------------------------------
|
||||
inst_pmem_ctrl : mem_control
|
||||
generic map(
|
||||
mem_type => P_MEM
|
||||
)
|
||||
port map(
|
||||
clk => clk,
|
||||
rst => rst,
|
||||
rd_addr => pmem_ctrl_in.rd_addr,
|
||||
rd_en => pmem_ctrl_in.rd_en,
|
||||
data_out => pmem_data_out,
|
||||
data_out_valid => pmem_data_out_valid,
|
||||
wr_addr => pmem_ctrl_in.wr_addr,
|
||||
wr_en => pmem_ctrl_in.wr_en,
|
||||
data_in => pmem_ctrl_in.data_in
|
||||
);
|
||||
|
||||
-- In case we wake up from a stall use the buffered value
|
||||
pmem_ctrl_out.data_out <= pmem_stall_buffer when stall_flags(ST_FE2_DEC) = '0' and
|
||||
stall_flags_d(ST_FE2_DEC) = '1' and
|
||||
pmem_stall_buffer_valid = '1' else
|
||||
pmem_data_out;
|
||||
|
||||
pmem_ctrl_out.data_out_valid <= pmem_stall_buffer_valid when stall_flags(ST_FE2_DEC) = '0' and
|
||||
stall_flags_d(ST_FE2_DEC) = '1' else
|
||||
'0' when stall_flags(ST_FE2_DEC) = '1' else
|
||||
pmem_data_out_valid;
|
||||
|
||||
-------------------------------
|
||||
-- XMEM CONTROLLER
|
||||
-------------------------------
|
||||
inst_xmem_ctrl : mem_control
|
||||
generic map(
|
||||
mem_type => X_MEM
|
||||
)
|
||||
port map(
|
||||
clk => clk,
|
||||
rst => rst,
|
||||
rd_addr => xmem_ctrl_in.rd_addr,
|
||||
rd_en => xmem_rd_en,
|
||||
data_out => xmem_data_out,
|
||||
data_out_valid => xmem_data_out_valid,
|
||||
wr_addr => xmem_ctrl_in.wr_addr,
|
||||
wr_en => xmem_ctrl_in.wr_en,
|
||||
data_in => xmem_ctrl_in.data_in
|
||||
);
|
||||
|
||||
xmem_rd_en <= '1' when xmem_rd_polling = '0' and xmem_ctrl_in.rd_en = '1' else '0';
|
||||
|
||||
xmem_ctrl_out.data_out <= xmem_data_out;
|
||||
xmem_ctrl_out.data_out_valid <= xmem_data_out_valid;
|
||||
|
||||
-------------------------------
|
||||
-- YMEM CONTROLLER
|
||||
-------------------------------
|
||||
inst_ymem_ctrl : mem_control
|
||||
generic map(
|
||||
mem_type => Y_MEM
|
||||
)
|
||||
port map(
|
||||
clk => clk,
|
||||
rst => rst,
|
||||
rd_addr => ymem_ctrl_in.rd_addr,
|
||||
rd_en => ymem_rd_en,
|
||||
data_out => ymem_data_out,
|
||||
data_out_valid => ymem_data_out_valid,
|
||||
wr_addr => ymem_ctrl_in.wr_addr,
|
||||
wr_en => ymem_ctrl_in.wr_en,
|
||||
data_in => ymem_ctrl_in.data_in
|
||||
);
|
||||
|
||||
ymem_rd_en <= '1' when ymem_rd_polling = '0' and ymem_ctrl_in.rd_en = '1' else '0';
|
||||
|
||||
ymem_ctrl_out.data_out <= ymem_data_out;
|
||||
ymem_ctrl_out.data_out_valid <= ymem_data_out_valid;
|
||||
|
||||
mem_stall_control: process(clk) is
|
||||
begin
|
||||
if rising_edge(clk) then
|
||||
if rst = '1' then
|
||||
xmem_rd_polling <= '0';
|
||||
ymem_rd_polling <= '0';
|
||||
else
|
||||
if xmem_rd_en = '1' then
|
||||
xmem_rd_polling <= '1';
|
||||
end if;
|
||||
|
||||
if xmem_data_out_valid = '1' then
|
||||
xmem_rd_polling <= '0';
|
||||
end if;
|
||||
|
||||
if ymem_rd_en = '1' then
|
||||
ymem_rd_polling <= '1';
|
||||
end if;
|
||||
|
||||
if ymem_data_out_valid = '1' then
|
||||
ymem_rd_polling <= '0';
|
||||
end if;
|
||||
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
end architecture;
|
||||
|
||||
18
FireBee/trunk/vhdl/dsp56k/src/parameter_pkg.vhd
Normal file
18
FireBee/trunk/vhdl/dsp56k/src/parameter_pkg.vhd
Normal file
@@ -0,0 +1,18 @@
|
||||
------------------------------------------------------------------------------
|
||||
--! @file
|
||||
--! @author Matthias Alles
|
||||
--! @date 01/2009
|
||||
--! @brief Global parameters
|
||||
--!
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
package parameter_pkg is
|
||||
|
||||
constant BW_ADDRESS : natural := 16;
|
||||
|
||||
-- number of pipeline register stages
|
||||
constant PIPELINE_DEPTH : natural := 4;
|
||||
|
||||
constant NUM_ACT_SIGNALS : natural := 26;
|
||||
|
||||
end package;
|
||||
1007
FireBee/trunk/vhdl/dsp56k/src/pipeline.vhd
Normal file
1007
FireBee/trunk/vhdl/dsp56k/src/pipeline.vhd
Normal file
File diff suppressed because it is too large
Load Diff
686
FireBee/trunk/vhdl/dsp56k/src/reg_file.vhd
Normal file
686
FireBee/trunk/vhdl/dsp56k/src/reg_file.vhd
Normal file
@@ -0,0 +1,686 @@
|
||||
------------------------------------------------------------------------------
|
||||
--! @file
|
||||
--! @author Matthias Alles
|
||||
--! @date 01/2009
|
||||
--! @brief Global register file, including scaler and limiter
|
||||
--!
|
||||
------------------------------------------------------------------------------
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.numeric_std.all;
|
||||
library work;
|
||||
use work.parameter_pkg.all;
|
||||
use work.types_pkg.all;
|
||||
use work.constants_pkg.all;
|
||||
|
||||
entity reg_file is port(
|
||||
clk, rst : in std_logic;
|
||||
register_file : out register_file_type;
|
||||
wr_R_port_A_valid : in std_logic;
|
||||
wr_R_port_A : in addr_wr_port_type;
|
||||
wr_R_port_B_valid : in std_logic;
|
||||
wr_R_port_B : in addr_wr_port_type;
|
||||
alu_wr_valid : in std_logic;
|
||||
alu_wr_addr : in std_logic;
|
||||
alu_wr_data : in signed(55 downto 0);
|
||||
reg_wr_addr : in std_logic_vector(5 downto 0);
|
||||
reg_wr_addr_valid : in std_logic;
|
||||
reg_wr_data : in std_Logic_vector(23 downto 0);
|
||||
reg_rd_addr : in std_logic_vector(5 downto 0);
|
||||
reg_rd_data : out std_Logic_vector(23 downto 0);
|
||||
X_bus_rd_addr : in std_logic_vector(1 downto 0);
|
||||
X_bus_data_out : out std_logic_vector(23 downto 0);
|
||||
X_bus_wr_addr : in std_logic_vector(1 downto 0);
|
||||
X_bus_wr_valid : in std_logic;
|
||||
X_bus_data_in : in std_logic_vector(23 downto 0);
|
||||
Y_bus_rd_addr : in std_logic_vector(1 downto 0);
|
||||
Y_bus_data_out : out std_logic_vector(23 downto 0);
|
||||
Y_bus_wr_addr : in std_logic_vector(1 downto 0);
|
||||
Y_bus_wr_valid : in std_logic;
|
||||
Y_bus_data_in : in std_logic_vector(23 downto 0);
|
||||
L_bus_rd_addr : in std_logic_vector(2 downto 0);
|
||||
L_bus_rd_valid : in std_logic;
|
||||
L_bus_wr_addr : in std_logic_vector(2 downto 0);
|
||||
L_bus_wr_valid : in std_logic;
|
||||
push_stack : in push_stack_type;
|
||||
pop_stack : in pop_stack_type;
|
||||
set_sr : in std_logic;
|
||||
new_sr : in std_logic_vector(15 downto 0);
|
||||
set_omr : in std_logic;
|
||||
new_omr : in std_logic_vector(7 downto 0);
|
||||
dec_lc : in std_logic;
|
||||
set_lc : in std_logic;
|
||||
new_lc : in unsigned(15 downto 0);
|
||||
set_la : in std_logic;
|
||||
new_la : in unsigned(BW_ADDRESS-1 downto 0)
|
||||
);
|
||||
end entity;
|
||||
|
||||
|
||||
architecture rtl of reg_file is
|
||||
|
||||
signal addr_r : addr_array;
|
||||
signal addr_m : addr_array;
|
||||
signal addr_n : addr_array;
|
||||
|
||||
signal loop_address : unsigned(BW_ADDRESS-1 downto 0);
|
||||
signal loop_counter : unsigned(15 downto 0);
|
||||
|
||||
-- condition code register
|
||||
signal ccr : std_logic_vector(7 downto 0);
|
||||
-- mode register
|
||||
signal mr : std_logic_vector(7 downto 0);
|
||||
-- status register = mode register + condition code register
|
||||
signal sr : std_logic_vector(15 downto 0);
|
||||
-- operation mode register
|
||||
signal omr : std_logic_vector(7 downto 0);
|
||||
|
||||
signal stack_pointer : unsigned(5 downto 0);
|
||||
signal system_stack_ssh : stack_array_type;
|
||||
signal system_stack_ssl : stack_array_type;
|
||||
|
||||
signal x0 : signed(23 downto 0);
|
||||
signal x1 : signed(23 downto 0);
|
||||
signal y0 : signed(23 downto 0);
|
||||
signal y1 : signed(23 downto 0);
|
||||
|
||||
signal a0 : signed(23 downto 0);
|
||||
signal a1 : signed(23 downto 0);
|
||||
signal a2 : signed(7 downto 0);
|
||||
|
||||
signal b0 : signed(23 downto 0);
|
||||
signal b1 : signed(23 downto 0);
|
||||
signal b2 : signed(7 downto 0);
|
||||
|
||||
signal limited_a1 : signed(23 downto 0);
|
||||
signal limited_b1 : signed(23 downto 0);
|
||||
signal limited_a0 : signed(23 downto 0);
|
||||
signal limited_b0 : signed(23 downto 0);
|
||||
signal set_limiting_flag : std_logic;
|
||||
signal X_bus_rd_limited_a : std_logic;
|
||||
signal X_bus_rd_limited_b : std_logic;
|
||||
signal Y_bus_rd_limited_a : std_logic;
|
||||
signal Y_bus_rd_limited_b : std_logic;
|
||||
signal reg_rd_limited_a : std_logic;
|
||||
signal reg_rd_limited_b : std_logic;
|
||||
signal rd_limited_a : std_logic;
|
||||
signal rd_limited_b : std_logic;
|
||||
|
||||
begin
|
||||
|
||||
|
||||
|
||||
sr <= mr & ccr;
|
||||
|
||||
register_file.addr_r <= addr_r;
|
||||
register_file.addr_n <= addr_n;
|
||||
register_file.addr_m <= addr_m;
|
||||
register_file.lc <= loop_counter;
|
||||
register_file.la <= loop_address;
|
||||
register_file.ccr <= ccr;
|
||||
register_file.mr <= mr;
|
||||
register_file.sr <= sr;
|
||||
register_file.omr <= omr;
|
||||
register_file.stack_pointer <= stack_pointer;
|
||||
register_file.current_ssh <= system_stack_ssh(to_integer(stack_pointer(3 downto 0)));
|
||||
register_file.current_ssl <= system_stack_ssl(to_integer(stack_pointer(3 downto 0)));
|
||||
register_file.a <= a2 & a1 & a0;
|
||||
register_file.b <= b2 & b1 & b0;
|
||||
register_file.x0 <= x0;
|
||||
register_file.x1 <= x1;
|
||||
register_file.y0 <= y0;
|
||||
register_file.y1 <= y1;
|
||||
|
||||
|
||||
global_register_file: process(clk) is
|
||||
variable stack_pointer_plus_1 : unsigned(3 downto 0);
|
||||
variable reg_addr : integer range 0 to 7;
|
||||
begin
|
||||
if rising_edge(clk) then
|
||||
if rst = '1' then
|
||||
addr_r <= (others => (others => '0'));
|
||||
addr_n <= (others => (others => '0'));
|
||||
addr_m <= (others => (others => '1'));
|
||||
ccr <= (others => '0');
|
||||
mr <= (others => '0');
|
||||
omr <= (others => '0');
|
||||
system_stack_ssl <= (others => (others => '0'));
|
||||
system_stack_ssh <= (others => (others => '0'));
|
||||
stack_pointer <= (others => '0');
|
||||
loop_counter <= (others => '0');
|
||||
loop_address <= (others => '0');
|
||||
x0 <= (others => '0');
|
||||
x1 <= (others => '0');
|
||||
y0 <= (others => '0');
|
||||
y1 <= (others => '0');
|
||||
a0 <= (others => '0');
|
||||
a1 <= (others => '0');
|
||||
a2 <= (others => '0');
|
||||
b0 <= (others => '0');
|
||||
b1 <= (others => '0');
|
||||
b2 <= (others => '0');
|
||||
else
|
||||
reg_addr := to_integer(unsigned(reg_wr_addr(2 downto 0)));
|
||||
-----------------------------------------------------------------------
|
||||
-- General write port to register file using 6 bit addressing scheme
|
||||
-----------------------------------------------------------------------
|
||||
if reg_wr_addr_valid = '1' then
|
||||
case reg_wr_addr(5 downto 3) is
|
||||
-- X0, X1, Y0, Y1
|
||||
when "000" =>
|
||||
case reg_wr_addr(2 downto 0) is
|
||||
when "100" =>
|
||||
x0 <= signed(reg_wr_data);
|
||||
when "101" =>
|
||||
x1 <= signed(reg_wr_data);
|
||||
when "110" =>
|
||||
y0 <= signed(reg_wr_data);
|
||||
when "111" =>
|
||||
y1 <= signed(reg_wr_data);
|
||||
when others =>
|
||||
end case;
|
||||
|
||||
-- A0, B0, A2, B2, A1, B1, A, B
|
||||
when "001" =>
|
||||
case reg_wr_addr(2 downto 0) is
|
||||
when "000" =>
|
||||
a0 <= signed(reg_wr_data);
|
||||
when "001" =>
|
||||
b0 <= signed(reg_wr_data);
|
||||
when "010" =>
|
||||
a2 <= signed(reg_wr_data(7 downto 0));
|
||||
when "011" =>
|
||||
b2 <= signed(reg_wr_data(7 downto 0));
|
||||
when "100" =>
|
||||
a1 <= signed(reg_wr_data);
|
||||
when "101" =>
|
||||
b1 <= signed(reg_wr_data);
|
||||
when "110" =>
|
||||
a2 <= (others => reg_wr_data(23));
|
||||
a1 <= signed(reg_wr_data);
|
||||
a0 <= (others => '0');
|
||||
when "111" =>
|
||||
b2 <= (others => reg_wr_data(23));
|
||||
b1 <= signed(reg_wr_data);
|
||||
b0 <= (others => '0');
|
||||
when others =>
|
||||
end case;
|
||||
|
||||
-- R0-R7
|
||||
when "010" =>
|
||||
addr_r(reg_addr) <= unsigned(reg_wr_data(BW_ADDRESS-1 downto 0));
|
||||
|
||||
-- N0-N7
|
||||
when "011" =>
|
||||
addr_n(reg_addr) <= unsigned(reg_wr_data(BW_ADDRESS-1 downto 0));
|
||||
|
||||
-- M0-M7
|
||||
when "100" =>
|
||||
addr_m(reg_addr) <= unsigned(reg_wr_data(BW_ADDRESS-1 downto 0));
|
||||
|
||||
-- SR, OMR, SP, SSH, SSL, LA, LC
|
||||
when "111" =>
|
||||
case reg_wr_addr(2 downto 0) is
|
||||
-- SR
|
||||
when "001" =>
|
||||
mr <= reg_wr_data(15 downto 8);
|
||||
ccr <= reg_wr_data( 7 downto 0);
|
||||
|
||||
-- OMR
|
||||
when "010" =>
|
||||
omr <= reg_wr_data(7 downto 0);
|
||||
|
||||
-- SP
|
||||
when "011" =>
|
||||
stack_pointer <= unsigned(reg_wr_data(5 downto 0));
|
||||
|
||||
-- SSH
|
||||
when "100" =>
|
||||
system_stack_ssh(to_integer(stack_pointer_plus_1)) <= reg_wr_data(BW_ADDRESS-1 downto 0);
|
||||
-- increase stack after writing
|
||||
stack_pointer(3 downto 0) <= stack_pointer_plus_1;
|
||||
-- test whether stack is full, if so set the stack error flag (SE)
|
||||
if stack_pointer(3 downto 0) = "1111" then
|
||||
stack_pointer(4) <= '1';
|
||||
end if;
|
||||
|
||||
-- SSL
|
||||
when "101" =>
|
||||
system_stack_ssl(to_integer(stack_pointer)) <= reg_wr_data(BW_ADDRESS-1 downto 0);
|
||||
|
||||
-- LA
|
||||
when "110" =>
|
||||
loop_address <= unsigned(reg_wr_data(BW_ADDRESS-1 downto 0));
|
||||
|
||||
-- LC
|
||||
when "111" =>
|
||||
loop_counter <= unsigned(reg_wr_data(15 downto 0));
|
||||
|
||||
when others =>
|
||||
end case;
|
||||
when others =>
|
||||
end case;
|
||||
end if;
|
||||
|
||||
----------------
|
||||
-- X BUS Write
|
||||
----------------
|
||||
if X_bus_wr_valid = '1' then
|
||||
case X_bus_wr_addr is
|
||||
when "00" =>
|
||||
x0 <= signed(X_bus_data_in);
|
||||
when "01" =>
|
||||
x1 <= signed(X_bus_data_in);
|
||||
when "10" =>
|
||||
a2 <= (others => X_bus_data_in(23));
|
||||
a1 <= signed(X_bus_data_in);
|
||||
a0 <= (others => '0');
|
||||
when others =>
|
||||
b2 <= (others => X_bus_data_in(23));
|
||||
b1 <= signed(X_bus_data_in);
|
||||
b0 <= (others => '0');
|
||||
end case;
|
||||
end if;
|
||||
----------------
|
||||
-- Y BUS Write
|
||||
----------------
|
||||
if Y_bus_wr_valid = '1' then
|
||||
case Y_bus_wr_addr is
|
||||
when "00" =>
|
||||
y0 <= signed(Y_bus_data_in);
|
||||
when "01" =>
|
||||
y1 <= signed(Y_bus_data_in);
|
||||
when "10" =>
|
||||
a2 <= (others => Y_bus_data_in(23));
|
||||
a1 <= signed(Y_bus_data_in);
|
||||
a0 <= (others => '0');
|
||||
when others =>
|
||||
b2 <= (others => Y_bus_data_in(23));
|
||||
b1 <= signed(Y_bus_data_in);
|
||||
b0 <= (others => '0');
|
||||
end case;
|
||||
end if;
|
||||
------------------
|
||||
-- L BUS Write
|
||||
------------------
|
||||
if L_bus_wr_valid = '1' then
|
||||
case L_bus_wr_addr is
|
||||
-- A10
|
||||
when "000" =>
|
||||
a1 <= signed(X_bus_data_in);
|
||||
a0 <= signed(Y_bus_data_in);
|
||||
-- B10
|
||||
when "001" =>
|
||||
b1 <= signed(X_bus_data_in);
|
||||
b0 <= signed(Y_bus_data_in);
|
||||
-- X
|
||||
when "010" =>
|
||||
x1 <= signed(X_bus_data_in);
|
||||
x0 <= signed(Y_bus_data_in);
|
||||
-- Y
|
||||
when "011" =>
|
||||
y1 <= signed(X_bus_data_in);
|
||||
y0 <= signed(Y_bus_data_in);
|
||||
-- A
|
||||
when "100" =>
|
||||
a2 <= (others => X_bus_data_in(23));
|
||||
a1 <= signed(X_bus_data_in);
|
||||
a0 <= signed(Y_bus_data_in);
|
||||
-- B
|
||||
when "101" =>
|
||||
b2 <= (others => X_bus_data_in(23));
|
||||
b1 <= signed(X_bus_data_in);
|
||||
b0 <= signed(Y_bus_data_in);
|
||||
-- AB
|
||||
when "110" =>
|
||||
a2 <= (others => X_bus_data_in(23));
|
||||
a1 <= signed(X_bus_data_in);
|
||||
a0 <= (others => '0');
|
||||
b2 <= (others => Y_bus_data_in(23));
|
||||
b1 <= signed(Y_bus_data_in);
|
||||
b0 <= (others => '0');
|
||||
-- BA
|
||||
when others =>
|
||||
a2 <= (others => Y_bus_data_in(23));
|
||||
a1 <= signed(Y_bus_data_in);
|
||||
a0 <= (others => '0');
|
||||
b2 <= (others => X_bus_data_in(23));
|
||||
b1 <= signed(X_bus_data_in);
|
||||
b0 <= (others => '0');
|
||||
end case;
|
||||
end if;
|
||||
|
||||
---------------------
|
||||
-- STATUS REGISTERS
|
||||
---------------------
|
||||
if set_sr = '1' then
|
||||
ccr <= new_sr( 7 downto 0);
|
||||
mr <= new_sr(15 downto 8);
|
||||
end if;
|
||||
if set_omr = '1' then
|
||||
omr <= new_omr;
|
||||
end if;
|
||||
-- data limiter active?
|
||||
-- listing this statement after the set_sr test results
|
||||
-- in the correct behaviour for ALU operations with parallel move
|
||||
if set_limiting_flag = '1' then
|
||||
ccr(6) <= '1';
|
||||
end if;
|
||||
|
||||
--------------------
|
||||
-- LOOP REGISTERS
|
||||
--------------------
|
||||
if set_la = '1' then
|
||||
loop_address <= new_la;
|
||||
end if;
|
||||
if set_lc = '1' then
|
||||
loop_counter <= new_lc;
|
||||
end if;
|
||||
if dec_lc = '1' then
|
||||
loop_counter <= loop_counter - 1;
|
||||
end if;
|
||||
|
||||
---------------------
|
||||
-- ADDRESS REGISTER
|
||||
---------------------
|
||||
if wr_R_port_A_valid = '1' then
|
||||
addr_r(to_integer(wr_R_port_A.reg_number)) <= wr_R_port_A.reg_value;
|
||||
end if;
|
||||
if wr_R_port_B_valid = '1' then
|
||||
addr_r(to_integer(wr_R_port_B.reg_number)) <= wr_R_port_B.reg_value;
|
||||
end if;
|
||||
|
||||
-------------------------
|
||||
-- ALU ACCUMULATOR WRITE
|
||||
-------------------------
|
||||
if alu_wr_valid = '1' then
|
||||
if alu_wr_addr = '0' then
|
||||
a2 <= alu_wr_data(55 downto 48);
|
||||
a1 <= alu_wr_data(47 downto 24);
|
||||
a0 <= alu_wr_data(23 downto 0);
|
||||
else
|
||||
b2 <= alu_wr_data(55 downto 48);
|
||||
b1 <= alu_wr_data(47 downto 24);
|
||||
b0 <= alu_wr_data(23 downto 0);
|
||||
end if;
|
||||
end if;
|
||||
|
||||
---------------------
|
||||
-- STACK CONTROLLER
|
||||
---------------------
|
||||
stack_pointer_plus_1 := stack_pointer(3 downto 0) + 1;
|
||||
if push_stack.valid = '1' then
|
||||
-- increase stack after writing
|
||||
stack_pointer(3 downto 0) <= stack_pointer_plus_1;
|
||||
-- test whether stack is full, if so set the stack error flag (SE)
|
||||
if stack_pointer(3 downto 0) = "1111" then
|
||||
stack_pointer(4) <= '1';
|
||||
end if;
|
||||
case push_stack.content is
|
||||
when PC =>
|
||||
system_stack_ssh(to_integer(stack_pointer_plus_1)) <= std_logic_vector(push_stack.pc);
|
||||
|
||||
when PC_AND_SR =>
|
||||
system_stack_ssh(to_integer(stack_pointer_plus_1)) <= std_logic_vector(push_stack.pc);
|
||||
system_stack_ssl(to_integer(stack_pointer_plus_1)) <= SR;
|
||||
|
||||
when LA_AND_LC =>
|
||||
system_stack_ssh(to_integer(stack_pointer_plus_1)) <= std_logic_vector(loop_address);
|
||||
system_stack_ssl(to_integer(stack_pointer_plus_1)) <= std_logic_vector(loop_counter);
|
||||
|
||||
end case;
|
||||
end if;
|
||||
|
||||
-- decrease stack pointer
|
||||
if pop_stack.valid = '1' then
|
||||
stack_pointer(3 downto 0) <= stack_pointer(3 downto 0) - 1;
|
||||
-- if stack is empty set the underflow flag (bit 5, UF) and the stack error flag (bit 4, SE)
|
||||
if stack_pointer(3 downto 0) = "0000" then
|
||||
stack_pointer(5) <= '1';
|
||||
stack_pointer(4) <= '1';
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
|
||||
x_bus_rd_port: process(X_bus_rd_addr,x0,x1,a1,b1,limited_a1,limited_b1,
|
||||
L_bus_rd_addr,L_bus_rd_valid,y1) is
|
||||
begin
|
||||
X_bus_rd_limited_a <= '0';
|
||||
X_bus_rd_limited_b <= '0';
|
||||
case X_bus_rd_addr is
|
||||
when "00" => X_bus_data_out <= std_logic_vector(x0);
|
||||
when "01" => X_bus_data_out <= std_logic_vector(x1);
|
||||
when "10" => X_bus_data_out <= std_logic_vector(limited_a1); X_bus_rd_limited_a <= '1';
|
||||
when others => X_bus_data_out <= std_logic_vector(limited_b1); X_bus_rd_limited_b <= '1';
|
||||
end case;
|
||||
if L_bus_rd_valid = '1' then
|
||||
case L_bus_rd_addr is
|
||||
when "000" => X_bus_data_out <= std_logic_vector(a1);
|
||||
when "001" => X_bus_data_out <= std_logic_vector(b1);
|
||||
when "010" => X_bus_data_out <= std_logic_vector(x1);
|
||||
when "011" => X_bus_data_out <= std_logic_vector(y1);
|
||||
when "100" => X_bus_data_out <= std_logic_vector(limited_a1); X_bus_rd_limited_a <= '1';
|
||||
when "101" => X_bus_data_out <= std_logic_vector(limited_b1); X_bus_rd_limited_b <= '1';
|
||||
when "110" => X_bus_data_out <= std_logic_vector(limited_a1); X_bus_rd_limited_a <= '1';
|
||||
when others => X_bus_data_out <= std_logic_vector(limited_b1); X_bus_rd_limited_b <= '1';
|
||||
end case;
|
||||
end if;
|
||||
end process x_bus_rd_port;
|
||||
|
||||
y_bus_rd_port: process(Y_bus_rd_addr,y0,y1,a1,b1,limited_a1,limited_b1,
|
||||
L_bus_rd_addr,L_bus_rd_valid,a0,b0,x0,limited_a0,limited_b0) is
|
||||
begin
|
||||
Y_bus_rd_limited_a <= '0';
|
||||
Y_bus_rd_limited_b <= '0';
|
||||
case Y_bus_rd_addr is
|
||||
when "00" => Y_bus_data_out <= std_logic_vector(y0);
|
||||
when "01" => Y_bus_data_out <= std_logic_vector(y1);
|
||||
when "10" => Y_bus_data_out <= std_logic_vector(limited_a1); Y_bus_rd_limited_a <= '1';
|
||||
when others => Y_bus_data_out <= std_logic_vector(limited_b1); Y_bus_rd_limited_b <= '1';
|
||||
end case;
|
||||
if L_bus_rd_valid = '1' then
|
||||
case L_bus_rd_addr is
|
||||
when "000" => Y_bus_data_out <= std_logic_vector(a0);
|
||||
when "001" => Y_bus_data_out <= std_logic_vector(b0);
|
||||
when "010" => Y_bus_data_out <= std_logic_vector(x0);
|
||||
when "011" => Y_bus_data_out <= std_logic_vector(y0);
|
||||
when "100" => Y_bus_data_out <= std_logic_vector(limited_a0); Y_bus_rd_limited_a <= '1';
|
||||
when "101" => Y_bus_data_out <= std_logic_vector(limited_b0); Y_bus_rd_limited_b <= '1';
|
||||
when "110" => Y_bus_data_out <= std_logic_vector(limited_b1); Y_bus_rd_limited_b <= '1';
|
||||
when others => Y_bus_data_out <= std_logic_vector(limited_a1); Y_bus_rd_limited_a <= '1';
|
||||
end case;
|
||||
end if;
|
||||
end process y_bus_rd_port;
|
||||
|
||||
|
||||
reg_rd_port: process(reg_rd_addr, x0,x1,y0,y1,a0,a1,a2,b0,b1,b2,
|
||||
omr,ccr,mr,addr_r,addr_n,addr_m,stack_pointer,
|
||||
loop_address,loop_counter,system_stack_ssl,system_stack_ssh) is
|
||||
variable reg_addr : integer range 0 to 7;
|
||||
begin
|
||||
reg_addr := to_integer(unsigned(reg_rd_addr(2 downto 0)));
|
||||
reg_rd_data <= (others => '0');
|
||||
reg_rd_limited_a <= '0';
|
||||
reg_rd_limited_b <= '0';
|
||||
|
||||
case reg_rd_addr(5 downto 3) is
|
||||
-- X0, X1, Y0, Y1
|
||||
when "000" =>
|
||||
case reg_rd_addr(2 downto 0) is
|
||||
when "100" =>
|
||||
reg_rd_data <= std_logic_vector(x0);
|
||||
when "101" =>
|
||||
reg_rd_data <= std_logic_vector(x1);
|
||||
when "110" =>
|
||||
reg_rd_data <= std_logic_vector(y0);
|
||||
when "111" =>
|
||||
reg_rd_data <= std_logic_vector(y1);
|
||||
when others =>
|
||||
end case;
|
||||
|
||||
-- A0, B0, A2, B2, A1, B1, A, B
|
||||
when "001" =>
|
||||
case reg_rd_addr(2 downto 0) is
|
||||
when "000" =>
|
||||
reg_rd_data <= std_logic_vector(a0);
|
||||
when "001" =>
|
||||
reg_rd_data <= std_logic_vector(b0);
|
||||
when "010" =>
|
||||
-- MSBs are read as zero!
|
||||
reg_rd_data(23 downto 8) <= (others => '0');
|
||||
reg_rd_data(7 downto 0) <= std_logic_vector(a2);
|
||||
when "011" =>
|
||||
-- MSBs are read as zero!
|
||||
reg_rd_data(23 downto 8) <= (others => '0');
|
||||
reg_rd_data(7 downto 0) <= std_logic_vector(b2);
|
||||
when "100" =>
|
||||
reg_rd_data <= std_logic_vector(a1);
|
||||
when "101" =>
|
||||
reg_rd_data <= std_logic_vector(b1);
|
||||
when "110" =>
|
||||
reg_rd_data <= std_logic_vector(limited_a1);
|
||||
reg_rd_limited_a <= '1';
|
||||
when "111" =>
|
||||
reg_rd_data <= std_logic_vector(limited_b1);
|
||||
reg_rd_limited_b <= '1';
|
||||
when others =>
|
||||
end case;
|
||||
|
||||
-- R0-R7
|
||||
when "010" =>
|
||||
reg_rd_data <= std_logic_vector(resize(addr_r(reg_addr), 24));
|
||||
|
||||
-- N0-N7
|
||||
when "011" =>
|
||||
reg_rd_data <= std_logic_vector(resize(addr_n(reg_addr), 24));
|
||||
|
||||
-- M0-M7
|
||||
when "100" =>
|
||||
reg_rd_data <= std_logic_vector(resize(addr_m(reg_addr), 24));
|
||||
|
||||
-- SR, OMR, SP, SSH, SSL, LA, LC
|
||||
when "111" =>
|
||||
case reg_wr_addr(2 downto 0) is
|
||||
-- SR
|
||||
when "001" =>
|
||||
reg_rd_data(23 downto 16) <= (others => '0');
|
||||
reg_rd_data(15 downto 0) <= mr & ccr;
|
||||
|
||||
-- OMR
|
||||
when "010" =>
|
||||
reg_rd_data(23 downto 8) <= (others => '0');
|
||||
reg_rd_data( 7 downto 0) <= omr;
|
||||
|
||||
-- SP
|
||||
when "011" =>
|
||||
reg_rd_data(23 downto 6) <= (others => '0');
|
||||
reg_rd_data(5 downto 0) <= std_logic_vector(stack_pointer);
|
||||
|
||||
-- SSH
|
||||
when "100" =>
|
||||
-- TODO!
|
||||
-- system_stack_ssh(to_integer(stack_pointer_plus_1)) <= reg_wr_data(BW_ADDRESS-1 downto 0);
|
||||
-- -- increase stack after writing
|
||||
-- stack_pointer(3 downto 0) <= stack_pointer_plus_1;
|
||||
-- -- test whether stack is full, if so set the stack error flag (SE)
|
||||
-- if stack_pointer(3 downto 0) = "1111" then
|
||||
-- stack_pointer(4) <= '1';
|
||||
-- end if;
|
||||
|
||||
-- SSL
|
||||
when "101" =>
|
||||
reg_rd_data <= (others => '0');
|
||||
reg_rd_data(BW_ADDRESS-1 downto 0) <= std_logic_vector(system_stack_ssl(to_integer(stack_pointer)));
|
||||
|
||||
-- LA
|
||||
when "110" =>
|
||||
reg_rd_data <= (others => '0');
|
||||
reg_rd_data(BW_ADDRESS-1 downto 0) <= std_logic_vector(loop_address);
|
||||
|
||||
-- LC
|
||||
when "111" =>
|
||||
reg_rd_data <= (others => '0');
|
||||
reg_rd_data(15 downto 0) <= std_logic_vector(loop_counter);
|
||||
|
||||
when others =>
|
||||
end case;
|
||||
when others =>
|
||||
end case;
|
||||
end process;
|
||||
|
||||
rd_limited_a <= '1' when reg_rd_limited_a = '1' or X_bus_rd_limited_a = '1' or Y_bus_rd_limited_a = '1' else '0';
|
||||
rd_limited_b <= '1' when reg_rd_limited_b = '1' or X_bus_rd_limited_b = '1' or Y_bus_rd_limited_b = '1' else '0';
|
||||
|
||||
data_shifter_limiter: process(a2,a1,a0,b2,b1,b0,sr,rd_limited_a,rd_limited_b) is
|
||||
variable scaled_a : signed(55 downto 0);
|
||||
variable scaled_b : signed(55 downto 0);
|
||||
begin
|
||||
|
||||
set_limiting_flag <= '0';
|
||||
-----------------
|
||||
-- DATA SCALING
|
||||
-----------------
|
||||
-- test against scaling bits S1, S0
|
||||
case sr(11 downto 10) is
|
||||
-- scale down (right shift)
|
||||
when "01" =>
|
||||
scaled_a := a2(7) & a2 & a1 & a0(23 downto 1);
|
||||
scaled_b := b2(7) & b2 & b1 & b0(23 downto 1);
|
||||
-- scale up (arithmetic left shift)
|
||||
when "10" =>
|
||||
scaled_a := a2(6 downto 0) & a1 & a0 & '0';
|
||||
scaled_b := b2(6 downto 0) & b1 & b0 & '0';
|
||||
-- "00" do not scale!
|
||||
when others =>
|
||||
scaled_a := a2 & a1 & a0;
|
||||
scaled_b := b2 & b1 & b0;
|
||||
end case;
|
||||
|
||||
-- only sign extension stored in a2?
|
||||
-- Yes: No limiting needed!
|
||||
if scaled_a(55 downto 47) = "111111111" or scaled_a(55 downto 47) = "000000000" then
|
||||
limited_a1 <= scaled_a(47 downto 24);
|
||||
limited_a0 <= scaled_a(23 downto 0);
|
||||
else
|
||||
-- positive value in a?
|
||||
if scaled_a(55) = '0' then
|
||||
limited_a1 <= X"7FFFFF";
|
||||
limited_a0 <= X"FFFFFF";
|
||||
-- negative value in a?
|
||||
else
|
||||
limited_a1 <= X"800000";
|
||||
limited_a0 <= X"000000";
|
||||
end if;
|
||||
-- set the limit flag in the status register
|
||||
if rd_limited_a = '1' then
|
||||
set_limiting_flag <= '1';
|
||||
end if;
|
||||
end if;
|
||||
-- only sign extension stored in b2?
|
||||
-- Yes: No limiting needed!
|
||||
if scaled_b(55 downto 47) = "111111111" or scaled_b(55 downto 47) = "000000000" then
|
||||
limited_b1 <= scaled_b(47 downto 24);
|
||||
limited_b0 <= scaled_b(23 downto 0);
|
||||
else
|
||||
-- positive value in b?
|
||||
if scaled_b(55) = '0' then
|
||||
limited_b1 <= X"7FFFFF";
|
||||
limited_b0 <= X"FFFFFF";
|
||||
-- negative value in b?
|
||||
else
|
||||
limited_b1 <= X"800000";
|
||||
limited_b0 <= X"000000";
|
||||
end if;
|
||||
-- set the limit flag in the status register
|
||||
if rd_limited_b = '1' then
|
||||
set_limiting_flag <= '1';
|
||||
end if;
|
||||
end if;
|
||||
|
||||
end process;
|
||||
|
||||
|
||||
end architecture rtl;
|
||||
182
FireBee/trunk/vhdl/dsp56k/src/types_pkg.vhd
Normal file
182
FireBee/trunk/vhdl/dsp56k/src/types_pkg.vhd
Normal file
@@ -0,0 +1,182 @@
|
||||
------------------------------------------------------------------------------
|
||||
--! @file
|
||||
--! @author Matthias Alles
|
||||
--! @date 01/2009
|
||||
--! @brief Global types
|
||||
--!
|
||||
------------------------------------------------------------------------------
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.numeric_std.all;
|
||||
library work;
|
||||
use work.parameter_pkg.all;
|
||||
|
||||
|
||||
|
||||
package types_pkg is
|
||||
|
||||
-- the different addressing modes
|
||||
type ADGen_mode_type is (NOP,
|
||||
POST_MIN_N,
|
||||
POST_PLUS_N,
|
||||
POST_MIN_1,
|
||||
POST_PLUS_1,
|
||||
INDEXED_N,
|
||||
PRE_MIN_1,
|
||||
ABSOLUTE,
|
||||
IMMEDIATE);
|
||||
|
||||
------------------------
|
||||
-- Decoded instructions
|
||||
------------------------
|
||||
type instructions_type is (
|
||||
INSTR_NOP ,
|
||||
INSTR_RTI ,
|
||||
INSTR_ILLEGAL ,
|
||||
INSTR_SWI ,
|
||||
INSTR_RTS ,
|
||||
INSTR_RESET ,
|
||||
INSTR_WAIT ,
|
||||
INSTR_STOP ,
|
||||
INSTR_ENDDO ,
|
||||
INSTR_ANDI ,
|
||||
INSTR_ORI ,
|
||||
INSTR_DIV ,
|
||||
INSTR_NORM ,
|
||||
INSTR_LUA ,
|
||||
INSTR_MOVEC ,
|
||||
INSTR_REP ,
|
||||
INSTR_DO ,
|
||||
INSTR_MOVEM ,
|
||||
INSTR_MOVEP ,
|
||||
INSTR_PM_MOVEM,
|
||||
INSTR_BCLR ,
|
||||
INSTR_BSET ,
|
||||
INSTR_JCLR ,
|
||||
INSTR_JSET ,
|
||||
INSTR_JMP ,
|
||||
INSTR_JCC ,
|
||||
INSTR_BCHG ,
|
||||
INSTR_BTST ,
|
||||
INSTR_JSCLR ,
|
||||
INSTR_JSSET ,
|
||||
INSTR_JSR ,
|
||||
INSTR_JSCC );
|
||||
|
||||
type addr_array is array(0 to 7) of unsigned(BW_ADDRESS-1 downto 0);
|
||||
|
||||
type alu_shift_mode is (NO_SHIFT, SHIFT_LEFT, SHIFT_RIGHT, ZEROS);
|
||||
type alu_ccr_flag is (DONT_TOUCH, CLEAR, MODIFY, SET);
|
||||
type alu_ccr_flag_array is array(7 downto 0) of alu_ccr_flag;
|
||||
|
||||
type alu_ctrl_type is record
|
||||
mul_op1 : std_logic_vector(1 downto 0); -- x0,x1,y0,y1
|
||||
mul_op2 : std_logic_vector(1 downto 0); -- x0,x1,y0,y1
|
||||
shift_src : std_logic; -- a,b
|
||||
shift_src_sign : std_logic_vector(1 downto 0); -- 00: pos, 01: neg, 10: sign dependant, 11: reserved
|
||||
shift_mode : alu_shift_mode;
|
||||
rotate : std_logic; -- 0: logical shift, 1: rotate shift
|
||||
add_src_stage_1 : std_logic_vector(2 downto 0); -- x0,x1,y0,y1,x,y,a,b
|
||||
add_src_stage_2 : std_logic_vector(1 downto 0); -- 00: 0 , 01: add_src_1, 10: mul_result, 11: reserved
|
||||
add_src_sign : std_logic_vector(1 downto 0); -- 00: pos, 01: neg, 10: sign dependant, 11: reserved
|
||||
logic_function : std_logic_vector(2 downto 0); -- 000: none, 001: and, 010: or, 011: eor, 100: not
|
||||
word_24_update : std_logic; -- only accumulator bits 47 downto 24 affected?
|
||||
rounding_used : std_logic_vector(1 downto 0); -- 00: no rounding, 01: rounding, 10: add carry, 11: subtract carry
|
||||
store_result : std_logic; -- 0: do not update accumulator, 1: update accumulator
|
||||
dst_accu : std_logic; -- 0: a, 1: b
|
||||
div_instr : std_logic; -- DIV instruction? Special ALU operations needed!
|
||||
norm_instr : std_logic; -- NORM instruction? Special ALU operations needed!
|
||||
ccr_flags_ctrl : alu_ccr_flag_array;
|
||||
end record;
|
||||
|
||||
type pipeline_signals is record
|
||||
instr_word: std_logic_vector(23 downto 0);
|
||||
pc : unsigned(BW_ADDRESS-1 downto 0);
|
||||
dble_word_instr : std_logic;
|
||||
instr_array : instructions_type;
|
||||
act_array : std_logic_vector(NUM_ACT_SIGNALS-1 downto 0);
|
||||
dec_activate : std_logic;
|
||||
adgen_mode_a : adgen_mode_type;
|
||||
adgen_mode_b : adgen_mode_type;
|
||||
reg_wr_addr : std_logic_vector(5 downto 0);
|
||||
reg_rd_addr : std_logic_vector(5 downto 0);
|
||||
x_bus_rd_addr : std_logic_vector(1 downto 0);
|
||||
x_bus_wr_addr : std_logic_vector(1 downto 0);
|
||||
y_bus_rd_addr : std_logic_vector(1 downto 0);
|
||||
y_bus_wr_addr : std_logic_vector(1 downto 0);
|
||||
l_bus_addr : std_logic_vector(2 downto 0);
|
||||
adgen_address_x : unsigned(BW_ADDRESS-1 downto 0);
|
||||
adgen_address_y : unsigned(BW_ADDRESS-1 downto 0);
|
||||
RAM_out_x : std_logic_vector(23 downto 0);
|
||||
RAM_out_y : std_logic_vector(23 downto 0);
|
||||
alu_ctrl : alu_ctrl_type;
|
||||
end record;
|
||||
|
||||
type pipeline_type is array(0 to PIPELINE_DEPTH-1) of pipeline_signals;
|
||||
|
||||
|
||||
type register_file_type is record
|
||||
a : signed(55 downto 0);
|
||||
b : signed(55 downto 0);
|
||||
x0 : signed(23 downto 0);
|
||||
x1 : signed(23 downto 0);
|
||||
y0 : signed(23 downto 0);
|
||||
y1 : signed(23 downto 0);
|
||||
la : unsigned(BW_ADDRESS-1 downto 0);
|
||||
lc : unsigned(15 downto 0);
|
||||
addr_r : addr_array;
|
||||
addr_n : addr_array;
|
||||
addr_m : addr_array;
|
||||
ccr : std_logic_vector(7 downto 0);
|
||||
mr : std_logic_vector(7 downto 0);
|
||||
sr : std_logic_vector(15 downto 0);
|
||||
omr : std_logic_vector(7 downto 0);
|
||||
stack_pointer : unsigned(5 downto 0);
|
||||
-- system_stack_ssh : stack_array_type;
|
||||
-- system_stack_ssl : stack_array_type;
|
||||
current_ssh : std_logic_vector(BW_ADDRESS-1 downto 0);
|
||||
current_ssl : std_logic_vector(BW_ADDRESS-1 downto 0);
|
||||
|
||||
end record;
|
||||
|
||||
type addr_wr_port_type is record
|
||||
-- write_valid : std_logic;
|
||||
reg_number : unsigned(2 downto 0);
|
||||
reg_value : unsigned(15 downto 0);
|
||||
end record;
|
||||
|
||||
type mem_ctrl_type_in is record
|
||||
rd_addr : unsigned(BW_ADDRESS-1 downto 0);
|
||||
rd_en : std_logic;
|
||||
wr_addr : unsigned(BW_ADDRESS-1 downto 0);
|
||||
wr_en : std_logic;
|
||||
data_in : std_logic_vector(23 downto 0);
|
||||
end record;
|
||||
|
||||
type mem_ctrl_type_out is record
|
||||
data_out : std_logic_vector(23 downto 0);
|
||||
data_out_valid : std_logic;
|
||||
end record;
|
||||
|
||||
type memory_type is (X_MEM, Y_MEM, P_MEM);
|
||||
---------------
|
||||
-- STACK TYPES
|
||||
---------------
|
||||
type stack_array_type is array(0 to 15) of std_logic_vector(BW_ADDRESS-1 downto 0);
|
||||
|
||||
type push_stack_content_type is (PC, PC_AND_SR, LA_AND_LC);
|
||||
|
||||
type push_stack_type is record
|
||||
valid : std_logic;
|
||||
pc : unsigned(BW_ADDRESS-1 downto 0);
|
||||
content : push_stack_content_type;
|
||||
end record;
|
||||
|
||||
|
||||
-- type pop_stack_type is std_logic;
|
||||
type pop_stack_type is record
|
||||
valid : std_logic;
|
||||
-- content : pop_stack_content_type;
|
||||
end record;
|
||||
|
||||
end package types_pkg;
|
||||
49
FireBee/trunk/vhdl/dsp56k/testbench/tb_pipeline.vhd
Normal file
49
FireBee/trunk/vhdl/dsp56k/testbench/tb_pipeline.vhd
Normal file
@@ -0,0 +1,49 @@
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.numeric_std.all;
|
||||
library work;
|
||||
use work.parameter_pkg.all;
|
||||
use work.types_pkg.all;
|
||||
|
||||
entity tb_pipeline is generic (
|
||||
clk_period : time := 10 ns
|
||||
);
|
||||
|
||||
|
||||
end entity tb_pipeline;
|
||||
|
||||
|
||||
architecture uut of tb_pipeline is
|
||||
|
||||
signal clk : std_logic := '0';
|
||||
signal rst : std_logic;
|
||||
|
||||
component pipeline is port(
|
||||
clk, rst : std_logic
|
||||
);
|
||||
end component pipeline;
|
||||
|
||||
begin
|
||||
|
||||
|
||||
|
||||
uut: pipeline port map(
|
||||
clk => clk,
|
||||
rst => rst
|
||||
);
|
||||
|
||||
clk_gen: process
|
||||
begin
|
||||
wait for clk_period/2;
|
||||
clk <= not clk;
|
||||
end process clk_gen;
|
||||
|
||||
rst_gen : process
|
||||
begin
|
||||
rst <= '1';
|
||||
wait for 10 * clk_period;
|
||||
rst <= '0';
|
||||
wait;
|
||||
end process rst_gen;
|
||||
|
||||
end architecture uut;
|
||||
Reference in New Issue
Block a user