2008-05-20 03:52:27 +04:00
/*
2005-04-17 02:20:36 +04:00
* PeeCeeI . c : The emerging standard . . .
*
* Copyright ( C ) 1997 David S . Miller ( davem @ caip . rutgers . edu )
*/
2009-01-09 03:58:20 +03:00
# include <linux/module.h>
2005-04-17 02:20:36 +04:00
# include <asm/io.h>
# include <asm/byteorder.h>
2005-09-01 02:01:33 +04:00
void outsb ( unsigned long __addr , const void * src , unsigned long count )
2005-04-17 02:20:36 +04:00
{
2005-09-01 02:01:33 +04:00
void __iomem * addr = ( void __iomem * ) __addr ;
2005-04-17 02:20:36 +04:00
const u8 * p = src ;
2005-09-01 02:01:33 +04:00
while ( count - - )
2005-04-17 02:20:36 +04:00
outb ( * p + + , addr ) ;
}
2009-01-09 03:58:20 +03:00
EXPORT_SYMBOL ( outsb ) ;
2005-04-17 02:20:36 +04:00
2005-09-01 02:01:33 +04:00
void outsw ( unsigned long __addr , const void * src , unsigned long count )
2005-04-17 02:20:36 +04:00
{
2005-09-01 02:01:33 +04:00
void __iomem * addr = ( void __iomem * ) __addr ;
2008-10-30 01:33:28 +03:00
while ( count - - ) {
__raw_writew ( * ( u16 * ) src , addr ) ;
src + = sizeof ( u16 ) ;
2005-04-17 02:20:36 +04:00
}
}
2009-01-09 03:58:20 +03:00
EXPORT_SYMBOL ( outsw ) ;
2005-04-17 02:20:36 +04:00
2005-09-01 02:01:33 +04:00
void outsl ( unsigned long __addr , const void * src , unsigned long count )
2005-04-17 02:20:36 +04:00
{
2005-09-01 02:01:33 +04:00
void __iomem * addr = ( void __iomem * ) __addr ;
2008-10-30 01:33:28 +03:00
u32 l , l2 ;
2005-09-01 02:01:33 +04:00
2008-10-30 01:33:28 +03:00
if ( ! count )
return ;
2005-04-17 02:20:36 +04:00
2008-10-30 01:33:28 +03:00
switch ( ( ( unsigned long ) src ) & 0x3 ) {
case 0x0 :
/* src is naturally aligned */
while ( count - - ) {
__raw_writel ( * ( u32 * ) src , addr ) ;
src + = sizeof ( u32 ) ;
}
break ;
case 0x2 :
/* 2-byte alignment */
while ( count - - ) {
l = ( * ( u16 * ) src ) < < 16 ;
l | = * ( u16 * ) ( src + sizeof ( u16 ) ) ;
__raw_writel ( l , addr ) ;
src + = sizeof ( u32 ) ;
}
break ;
case 0x1 :
/* Hold three bytes in l each time, grab a byte from l2 */
l = ( * ( u8 * ) src ) < < 24 ;
l | = ( * ( u16 * ) ( src + sizeof ( u8 ) ) ) < < 8 ;
src + = sizeof ( u8 ) + sizeof ( u16 ) ;
while ( count - - ) {
l2 = * ( u32 * ) src ;
l | = ( l2 > > 24 ) ;
__raw_writel ( l , addr ) ;
l = l2 < < 8 ;
src + = sizeof ( u32 ) ;
}
break ;
case 0x3 :
/* Hold a byte in l each time, grab 3 bytes from l2 */
l = ( * ( u8 * ) src ) < < 24 ;
src + = sizeof ( u8 ) ;
while ( count - - ) {
l2 = * ( u32 * ) src ;
l | = ( l2 > > 8 ) ;
__raw_writel ( l , addr ) ;
l = l2 < < 24 ;
src + = sizeof ( u32 ) ;
2005-04-17 02:20:36 +04:00
}
2008-10-30 01:33:28 +03:00
break ;
2005-04-17 02:20:36 +04:00
}
}
2009-01-09 03:58:20 +03:00
EXPORT_SYMBOL ( outsl ) ;
2005-04-17 02:20:36 +04:00
2005-09-01 02:01:33 +04:00
void insb ( unsigned long __addr , void * dst , unsigned long count )
2005-04-17 02:20:36 +04:00
{
2005-09-01 02:01:33 +04:00
void __iomem * addr = ( void __iomem * ) __addr ;
if ( count ) {
2005-04-17 02:20:36 +04:00
u32 * pi ;
u8 * pb = dst ;
2005-09-01 02:01:33 +04:00
while ( ( ( ( unsigned long ) pb ) & 0x3 ) & & count - - )
2005-04-17 02:20:36 +04:00
* pb + + = inb ( addr ) ;
pi = ( u32 * ) pb ;
2005-09-01 02:01:33 +04:00
while ( count > = 4 ) {
2005-04-17 02:20:36 +04:00
u32 w ;
w = ( inb ( addr ) < < 24 ) ;
w | = ( inb ( addr ) < < 16 ) ;
w | = ( inb ( addr ) < < 8 ) ;
w | = ( inb ( addr ) < < 0 ) ;
* pi + + = w ;
count - = 4 ;
}
pb = ( u8 * ) pi ;
2005-09-01 02:01:33 +04:00
while ( count - - )
2005-04-17 02:20:36 +04:00
* pb + + = inb ( addr ) ;
}
}
2009-01-09 03:58:20 +03:00
EXPORT_SYMBOL ( insb ) ;
2005-04-17 02:20:36 +04:00
2005-09-01 02:01:33 +04:00
void insw ( unsigned long __addr , void * dst , unsigned long count )
2005-04-17 02:20:36 +04:00
{
2005-09-01 02:01:33 +04:00
void __iomem * addr = ( void __iomem * ) __addr ;
if ( count ) {
2005-04-17 02:20:36 +04:00
u16 * ps = dst ;
u32 * pi ;
2005-09-01 02:01:33 +04:00
if ( ( ( unsigned long ) ps ) & 0x2 ) {
2005-04-17 02:20:36 +04:00
* ps + + = le16_to_cpu ( inw ( addr ) ) ;
count - - ;
}
pi = ( u32 * ) ps ;
2005-09-01 02:01:33 +04:00
while ( count > = 2 ) {
2005-04-17 02:20:36 +04:00
u32 w ;
w = ( le16_to_cpu ( inw ( addr ) ) < < 16 ) ;
w | = ( le16_to_cpu ( inw ( addr ) ) < < 0 ) ;
* pi + + = w ;
count - = 2 ;
}
ps = ( u16 * ) pi ;
2005-09-01 02:01:33 +04:00
if ( count )
2005-04-17 02:20:36 +04:00
* ps = le16_to_cpu ( inw ( addr ) ) ;
}
}
2009-01-09 03:58:20 +03:00
EXPORT_SYMBOL ( insw ) ;
2005-04-17 02:20:36 +04:00
2005-09-01 02:01:33 +04:00
void insl ( unsigned long __addr , void * dst , unsigned long count )
2005-04-17 02:20:36 +04:00
{
2005-09-01 02:01:33 +04:00
void __iomem * addr = ( void __iomem * ) __addr ;
if ( count ) {
if ( ( ( ( unsigned long ) dst ) & 0x3 ) = = 0 ) {
2005-04-17 02:20:36 +04:00
u32 * pi = dst ;
2005-09-01 02:01:33 +04:00
while ( count - - )
2005-04-17 02:20:36 +04:00
* pi + + = le32_to_cpu ( inl ( addr ) ) ;
} else {
u32 l = 0 , l2 , * pi ;
u16 * ps ;
u8 * pb ;
2005-09-01 02:01:33 +04:00
switch ( ( ( unsigned long ) dst ) & 3 ) {
2005-04-17 02:20:36 +04:00
case 0x2 :
ps = dst ;
count - = 1 ;
l = le32_to_cpu ( inl ( addr ) ) ;
* ps + + = l ;
pi = ( u32 * ) ps ;
2005-09-01 02:01:33 +04:00
while ( count - - ) {
2005-04-17 02:20:36 +04:00
l2 = le32_to_cpu ( inl ( addr ) ) ;
* pi + + = ( l < < 16 ) | ( l2 > > 16 ) ;
l = l2 ;
}
ps = ( u16 * ) pi ;
* ps = l ;
break ;
case 0x1 :
pb = dst ;
count - = 1 ;
l = le32_to_cpu ( inl ( addr ) ) ;
* pb + + = l > > 24 ;
ps = ( u16 * ) pb ;
* ps + + = ( ( l > > 8 ) & 0xffff ) ;
pi = ( u32 * ) ps ;
2005-09-01 02:01:33 +04:00
while ( count - - ) {
2005-04-17 02:20:36 +04:00
l2 = le32_to_cpu ( inl ( addr ) ) ;
* pi + + = ( l < < 24 ) | ( l2 > > 8 ) ;
l = l2 ;
}
pb = ( u8 * ) pi ;
* pb = l ;
break ;
case 0x3 :
pb = ( u8 * ) dst ;
count - = 1 ;
l = le32_to_cpu ( inl ( addr ) ) ;
* pb + + = l > > 24 ;
pi = ( u32 * ) pb ;
2005-09-01 02:01:33 +04:00
while ( count - - ) {
2005-04-17 02:20:36 +04:00
l2 = le32_to_cpu ( inl ( addr ) ) ;
* pi + + = ( l < < 8 ) | ( l2 > > 24 ) ;
l = l2 ;
}
ps = ( u16 * ) pi ;
* ps + + = ( ( l > > 8 ) & 0xffff ) ;
pb = ( u8 * ) ps ;
* pb = l ;
break ;
}
}
}
}
2009-01-09 03:58:20 +03:00
EXPORT_SYMBOL ( insl ) ;
2005-04-17 02:20:36 +04:00