2005-04-17 02:20:36 +04:00
# ifndef MCA_DMA_H
# define MCA_DMA_H
# include <asm/io.h>
# include <linux/ioport.h>
/*
* Microchannel specific DMA stuff . DMA on an MCA machine is fairly similar to
* standard PC dma , but it certainly has its quirks . DMA register addresses
* are in a different place and there are some added functions . Most of this
* should be pretty obvious on inspection . Note that the user must divide
* count by 2 when using 16 - bit dma ; that is not handled by these functions .
*
* Ramen Noodles are yummy .
2008-03-23 11:02:41 +03:00
*
* 1998 Tymm Twillman < tymm @ computer . org >
2005-04-17 02:20:36 +04:00
*/
/*
2008-03-23 11:02:41 +03:00
* Registers that are used by the DMA controller ; FN is the function register
2005-04-17 02:20:36 +04:00
* ( tell the controller what to do ) and EXE is the execution register ( how
* to do it )
*/
# define MCA_DMA_REG_FN 0x18
2008-03-23 11:02:41 +03:00
# define MCA_DMA_REG_EXE 0x1A
2005-04-17 02:20:36 +04:00
/*
* Functions that the DMA controller can do
*/
# define MCA_DMA_FN_SET_IO 0x00
# define MCA_DMA_FN_SET_ADDR 0x20
# define MCA_DMA_FN_GET_ADDR 0x30
# define MCA_DMA_FN_SET_COUNT 0x40
# define MCA_DMA_FN_GET_COUNT 0x50
# define MCA_DMA_FN_GET_STATUS 0x60
# define MCA_DMA_FN_SET_MODE 0x70
# define MCA_DMA_FN_SET_ARBUS 0x80
# define MCA_DMA_FN_MASK 0x90
# define MCA_DMA_FN_RESET_MASK 0xA0
# define MCA_DMA_FN_MASTER_CLEAR 0xD0
/*
* Modes ( used by setting MCA_DMA_FN_MODE in the function register )
2008-03-23 11:02:41 +03:00
*
2005-04-17 02:20:36 +04:00
* Note that the MODE_READ is read from memory ( write to device ) , and
2008-03-23 11:02:41 +03:00
* MODE_WRITE is vice - versa .
2005-04-17 02:20:36 +04:00
*/
# define MCA_DMA_MODE_XFER 0x04 /* read by default */
# define MCA_DMA_MODE_READ 0x04 /* same as XFER */
# define MCA_DMA_MODE_WRITE 0x08 /* OR with MODE_XFER to use */
# define MCA_DMA_MODE_IO 0x01 /* DMA from IO register */
# define MCA_DMA_MODE_16 0x40 /* 16 bit xfers */
/**
* mca_enable_dma - channel to enable DMA on
* @ dmanr : DMA channel
*
* Enable the MCA bus DMA on a channel . This can be called from
* IRQ context .
*/
2008-03-23 11:02:41 +03:00
static inline void mca_enable_dma ( unsigned int dmanr )
2005-04-17 02:20:36 +04:00
{
outb ( MCA_DMA_FN_RESET_MASK | dmanr , MCA_DMA_REG_FN ) ;
}
/**
* mca_disble_dma - channel to disable DMA on
* @ dmanr : DMA channel
*
* Enable the MCA bus DMA on a channel . This can be called from
* IRQ context .
*/
2008-03-23 11:02:41 +03:00
static inline void mca_disable_dma ( unsigned int dmanr )
2005-04-17 02:20:36 +04:00
{
outb ( MCA_DMA_FN_MASK | dmanr , MCA_DMA_REG_FN ) ;
}
/**
* mca_set_dma_addr - load a 24 bit DMA address
* @ dmanr : DMA channel
* @ a : 24 bit bus address
*
* Load the address register in the DMA controller . This has a 24 bit
2008-03-23 11:02:41 +03:00
* limitation ( 16 Mb ) .
2005-04-17 02:20:36 +04:00
*/
2008-03-23 11:02:41 +03:00
static inline void mca_set_dma_addr ( unsigned int dmanr , unsigned int a )
2005-04-17 02:20:36 +04:00
{
outb ( MCA_DMA_FN_SET_ADDR | dmanr , MCA_DMA_REG_FN ) ;
outb ( a & 0xff , MCA_DMA_REG_EXE ) ;
outb ( ( a > > 8 ) & 0xff , MCA_DMA_REG_EXE ) ;
outb ( ( a > > 16 ) & 0xff , MCA_DMA_REG_EXE ) ;
}
/**
* mca_get_dma_addr - load a 24 bit DMA address
* @ dmanr : DMA channel
*
* Read the address register in the DMA controller . This has a 24 bit
* limitation ( 16 Mb ) . The return is a bus address .
*/
2008-03-23 11:02:41 +03:00
static inline unsigned int mca_get_dma_addr ( unsigned int dmanr )
2005-04-17 02:20:36 +04:00
{
unsigned int addr ;
outb ( MCA_DMA_FN_GET_ADDR | dmanr , MCA_DMA_REG_FN ) ;
addr = inb ( MCA_DMA_REG_EXE ) ;
addr | = inb ( MCA_DMA_REG_EXE ) < < 8 ;
2008-03-23 11:02:41 +03:00
addr | = inb ( MCA_DMA_REG_EXE ) < < 16 ;
2005-04-17 02:20:36 +04:00
return addr ;
}
/**
* mca_set_dma_count - load a 16 bit transfer count
* @ dmanr : DMA channel
* @ count : count
*
* Set the DMA count for this channel . This can be up to 64 Kbytes .
* Setting a count of zero will not do what you expect .
*/
2008-03-23 11:02:41 +03:00
static inline void mca_set_dma_count ( unsigned int dmanr , unsigned int count )
2005-04-17 02:20:36 +04:00
{
count - - ; /* transfers one more than count -- correct for this */
outb ( MCA_DMA_FN_SET_COUNT | dmanr , MCA_DMA_REG_FN ) ;
outb ( count & 0xff , MCA_DMA_REG_EXE ) ;
outb ( ( count > > 8 ) & 0xff , MCA_DMA_REG_EXE ) ;
}
/**
* mca_get_dma_residue - get the remaining bytes to transfer
* @ dmanr : DMA channel
*
* This function returns the number of bytes left to transfer
* on this DMA channel .
*/
2008-03-23 11:02:41 +03:00
static inline unsigned int mca_get_dma_residue ( unsigned int dmanr )
2005-04-17 02:20:36 +04:00
{
unsigned short count ;
outb ( MCA_DMA_FN_GET_COUNT | dmanr , MCA_DMA_REG_FN ) ;
count = 1 + inb ( MCA_DMA_REG_EXE ) ;
count + = inb ( MCA_DMA_REG_EXE ) < < 8 ;
return count ;
}
/**
* mca_set_dma_io - set the port for an I / O transfer
* @ dmanr : DMA channel
* @ io_addr : an I / O port number
*
* Unlike the ISA bus DMA controllers the DMA on MCA bus can transfer
* with an I / O port target .
*/
2008-03-23 11:02:41 +03:00
static inline void mca_set_dma_io ( unsigned int dmanr , unsigned int io_addr )
2005-04-17 02:20:36 +04:00
{
/*
* DMA from a port address - - set the io address
*/
2008-03-23 11:02:41 +03:00
2005-04-17 02:20:36 +04:00
outb ( MCA_DMA_FN_SET_IO | dmanr , MCA_DMA_REG_FN ) ;
outb ( io_addr & 0xff , MCA_DMA_REG_EXE ) ;
outb ( ( io_addr > > 8 ) & 0xff , MCA_DMA_REG_EXE ) ;
}
/**
* mca_set_dma_mode - set the DMA mode
* @ dmanr : DMA channel
* @ mode : mode to set
*
* The DMA controller supports several modes . The mode values you can
2006-10-03 12:13:50 +04:00
* set are -
2005-04-17 02:20:36 +04:00
*
* % MCA_DMA_MODE_READ when reading from the DMA device .
*
* % MCA_DMA_MODE_WRITE to writing to the DMA device .
*
* % MCA_DMA_MODE_IO to do DMA to or from an I / O port .
*
* % MCA_DMA_MODE_16 to do 16 bit transfers .
*/
2008-03-23 11:02:41 +03:00
static inline void mca_set_dma_mode ( unsigned int dmanr , unsigned int mode )
2005-04-17 02:20:36 +04:00
{
outb ( MCA_DMA_FN_SET_MODE | dmanr , MCA_DMA_REG_FN ) ;
outb ( mode , MCA_DMA_REG_EXE ) ;
}
# endif /* MCA_DMA_H */