Threaded SCSI driver

Carsten Pluntke (su0289@sx2.hrz.uni-dortmund.de)
Wed, 15 Apr 1998 08:05:35 +0200 (MET DST)


Hello, I've written a device driver for my SCSI host adapter. I don't want
to bore you with details because it's just for Linux on Amiga, but I've
got a question which is more host independent.

The problem with the host adapter is that it's very similar to the Sparc
ESP (I can use the driver routines controlling that SCSI chip) and uses
the DMA transfer ability of that thing.

But the problem is that it writes the bytes transferred by 'DMA' not
direct and the location one wants to have them but in a dedicated memory
area of the host adapter, so one has to copy the data to/from the correct
location on one's own.

To make it more difficult it's the problem that you can read/write only
the bytes the SCSI chip transfers, if that limit is reached, the host
adapter causes the DMA interrupt and every read/write operation beyond
that limit is responded with a bus error.

At the moment I reduced the maximum transfer size and slopped the copying
into the interrupt routine, it works, but it makes things awfully slow.

I know, a better solution would be a kernel thread which is normally
dormant and will be woken up by an interrupt when data is about to
transfer and stopped by the second (the DMA) interrupt.

Anyone knows a clean solution for this kernel thread and
interrupt<-->thread communication? Are the macros/functions cli() and
sti() usable in general? (meaning m68k-Linux and ppc-Linux)

At the moment I've got something like that in mind:

void dma_kthread()
{
.
.
.

while(1)
{
something_putting_thread_to_sleep_to_wait_for_the_interrupt();
.
.
.

if(direction)
{
while(len)
{
cli();
*address++ = *port;
len--;
sti();
}
} else {
while(len)
{
cli();
*port = *address++;
len--;
sti();
}
}
}

Interrupt 'Ready_for_dma'
.
.
something_waking_up_the_kernel_thread();
.
.
.

Interrupt 'dma finished'
.
.
len = 0;
.
.

DMA transfer will be started with e.g. '256 Bytes to address 0x123456',
but after the 36th bytes there may be the 'dma finished' interrupt which
disallows any further transfer action.
I thought about 'brute force', meaning to set the len (bytes still to
transfer) simply to zero, breaking the while loops in the kernel thread
prematurely. So I needed something to frame the transfer operation to not
to have the IRQ happening at the wrong location.

OK... Anyone able to fill out the missing fields (e.g. the function names
which provide that what I've intended) or maybe having a better solution
for my problem?

Carsten

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu