read from isa bus with inw() gives odd result

read from isa bus with inw() gives odd result

Post by Madeleine Thie » Sat, 26 Jan 2002 17:07:07



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:}

 
 
 

read from isa bus with inw() gives odd result

Post by wat.. » Fri, 01 Feb 2002 06:58:19


PCI bridge quirks?

The problem turned out to be that a default setting on the board
did not get set correctly. This value is normally set at power-on.
Something that apparantly works under NT but not under the current
linux (tested kernels 2.4.17 and 2.2.20). The ISA bus is a subsystem
of a pci slot (bridge).

The power-on cycle must be slightly different for linux. Any ideas?