I am writing a driver for a custom isa card, which involves reading data
from the isa bus in response to interrupts. All works well with the
driver except for the inw() instruction, which returns zero. I wrote a
windows nt version of the driver that operates without a problem on the
same hardware. The ISR reads data from the io port with inw() and places
it in a circular buffer that is accessed by read().
From all I can tell the problem must be with the inw() command somehow.
However, the nt version works fine on the same hardware.
I would greatly appreciate any useful hints!
Here is the interrupt service routine I use:
//
// Define access macros for registers. Each macro takes
// a pointer to a device struct with the base pointer as an argument.
//
#define ATIFT_WriteAddress( pDev, wData ) \
(outw( wData, pDev->base_address + ATIFT_ADDRESS ))
#define ATIFT_ReadData( pDev ) \
(inw( pDev->base_address + ATIFT_DATA ))
#define ATIFT_WriteData( pDev, wData ) \
(outw( wData, pDev->base_address + ATIFT_DATA ))
#define ATIFT_ReadStatus( pDev ) \
(inw( pDev->base_address + ATIFT_STATUS ))
#define ATIFT_WriteStatus( pDev, wData ) \
(outw( wData, pDev->base_address + ATIFT_STATUS )
void atift_isr(int irq, void *dev_id, struct pt_regs *r)
{
pATIFT_Device pDev = (pATIFT_Device) dev_id ;
unsigned int i;
u16 dword, *dptr ;
/* check status register to see if card caused the interrupt */
dword = ATIFT_ReadStatus( pDev ) ; /* read status register */
if( (dword&ATIFT_STS_INTERRUPT)!=0 )
{
ATIFT_WriteAddress( pDev, 0x0100 ) ; /* location of data counter */
dword = ATIFT_ReadData( pDev ); /* get card "semaphore" number */
/* This value is actually a sample counter!
* This is not documented, so may change in the future!
*/
pDev->board_overrun = dword-1 ; /* signal board overrun */
ATIFT_ReadData( pDev ) ; /* skip the monitoring conditions */
dptr = (u16*) (pDev->fifo.pData + pDev->fifo.head) ;
/* read the data */
for(i=0;i<6;i++)
// dptr[i] = inw( pDev->base_address+4 ) ; /* this is what the next
line does */
/* this next line is buggy:
*(dptr++) = ATIFT_ReadData( pDev ) ;
/* this is a test, works well - no problems with buffering: */
// *(dptr++) = (i<<8) | (pDev->interrupt_count & 0x0FF) ;
pDev->fifo.count ++ ;
pDev->fifo.head ++ ; /* point to the next empty spot */
if (pDev->fifo.head==pDev->fifo.size)
pDev->fifo.head = 0 ; /* point to next */
printk(
KERN_INFO "atift|isr: head: %d, tail: %d, count: %d.\n",
pDev->fifo.head,
pDev->fifo.tail,
pDev->fifo.count ) ;
ATIFT_WriteStatus( pDev, 1 ) ; /* clear status register */
ATIFT_WriteAddress( pDev, 0x0100 ) ; /* location of data counter */
ATIFT_WriteData( pDev, 0 ) ; /* reset data flag */
#ifdef ATIFT_DEBUG
pDev->interrupt_count ++ ;
#endif
/* wake up reading processes */
wake_up_interruptible( &pDev->in_queue ) ;
}
Quote:}