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 )
*/
# 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 ) ;
}
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 ;
if ( count ) {
2005-04-17 02:20:36 +04:00
u16 * ps = ( u16 * ) src ;
u32 * pi ;
2005-09-01 02:01:33 +04:00
if ( ( ( u64 ) src ) & 0x2 ) {
2005-04-17 02:20:36 +04:00
u16 val = le16_to_cpup ( ps ) ;
outw ( val , addr ) ;
ps + + ;
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 = le32_to_cpup ( pi ) ;
pi + + ;
outw ( w > > 0 , addr ) ;
outw ( w > > 16 , addr ) ;
count - = 2 ;
}
ps = ( u16 * ) pi ;
2005-09-01 02:01:33 +04:00
if ( count ) {
2005-04-17 02:20:36 +04:00
u16 val = le16_to_cpup ( ps ) ;
outw ( val , addr ) ;
}
}
}
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 ;
if ( count ) {
if ( ( ( ( u64 ) src ) & 0x3 ) = = 0 ) {
2005-04-17 02:20:36 +04:00
u32 * p = ( u32 * ) src ;
2005-09-01 02:01:33 +04:00
while ( count - - ) {
2005-04-17 02:20:36 +04:00
u32 val = cpu_to_le32p ( p ) ;
outl ( val , addr ) ;
p + + ;
}
} else {
u8 * pb ;
u16 * ps = ( u16 * ) src ;
u32 l = 0 , l2 ;
u32 * pi ;
2005-09-01 02:01:33 +04:00
switch ( ( ( u64 ) src ) & 0x3 ) {
2005-04-17 02:20:36 +04:00
case 0x2 :
count - = 1 ;
l = cpu_to_le16p ( ps ) < < 16 ;
ps + + ;
pi = ( u32 * ) ps ;
2005-09-01 02:01:33 +04:00
while ( count - - ) {
2005-04-17 02:20:36 +04:00
l2 = cpu_to_le32p ( pi ) ;
pi + + ;
outl ( ( ( l > > 16 ) | ( l2 < < 16 ) ) , addr ) ;
l = l2 ;
}
ps = ( u16 * ) pi ;
l2 = cpu_to_le16p ( ps ) ;
outl ( ( ( l > > 16 ) | ( l2 < < 16 ) ) , addr ) ;
break ;
case 0x1 :
count - = 1 ;
pb = ( u8 * ) src ;
l = ( * pb + + < < 8 ) ;
ps = ( u16 * ) pb ;
l2 = cpu_to_le16p ( ps ) ;
ps + + ;
l | = ( l2 < < 16 ) ;
pi = ( u32 * ) ps ;
2005-09-01 02:01:33 +04:00
while ( count - - ) {
2005-04-17 02:20:36 +04:00
l2 = cpu_to_le32p ( pi ) ;
pi + + ;
outl ( ( ( l > > 8 ) | ( l2 < < 24 ) ) , addr ) ;
l = l2 ;
}
pb = ( u8 * ) pi ;
outl ( ( ( l > > 8 ) | ( * pb < < 24 ) ) , addr ) ;
break ;
case 0x3 :
count - = 1 ;
pb = ( u8 * ) src ;
l = ( * pb + + < < 24 ) ;
pi = ( u32 * ) pb ;
2005-09-01 02:01:33 +04:00
while ( count - - ) {
2005-04-17 02:20:36 +04:00
l2 = cpu_to_le32p ( pi ) ;
pi + + ;
outl ( ( ( l > > 24 ) | ( l2 < < 8 ) ) , addr ) ;
l = l2 ;
}
ps = ( u16 * ) pi ;
l2 = cpu_to_le16p ( ps ) ;
ps + + ;
pb = ( u8 * ) ps ;
l2 | = ( * pb < < 16 ) ;
outl ( ( ( l > > 24 ) | ( l2 < < 8 ) ) , addr ) ;
break ;
}
}
}
}
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 ) ;
}
}
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 ) ) ;
}
}
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 ;
}
}
}
}