tpqic02.c

Dirk Weigenand (weigo@fred.rz.uni-leipzig.de)
Tue, 1 Oct 1996 17:45:36 +0100 (MET)


Hi,

since 2.1.0 the tape driver for Wangtek streamers doesn't work
anymore. Due to the changes regarding the memory mapping from
physical to virtual pages the address for its DMA buffer is
above 16M. I've come up with a patch that althouh it works
for me looks suspicious to me. Can someone more knowledgable
than me please have a lookt at it and be so kind to shed some
light on what and why my assumptions have been wrong.

regards,
Dirk

--- linux/drivers/char/tpqic02.c.old Tue Oct 1 16:54:50 1996
+++ linux/drivers/char/tpqic02.c Tue Oct 1 17:40:09 1996
@@ -211,6 +211,7 @@
#include <linux/delay.h>
#include <linux/tpqic02.h>
#include <linux/config.h>
+#include <linux/malloc.h>
#include <linux/mm.h>

#include <asm/dma.h>
@@ -333,7 +334,8 @@
* at 512 bytes, to prevent problems with 64k boundaries.
*/

-static volatile char qic02_tape_buf[TPQBUF_SIZE+TAPE_BLKSIZE];
+/* static volatile char qic02_tape_buf[TPQBUF_SIZE+TAPE_BLKSIZE]; */
+static char *qic02_tape_buf = NULL;
/* A really good compiler would be able to align this at 512 bytes... :-( */

static unsigned long buffaddr; /* aligned physical address of buffer */
@@ -1538,7 +1540,7 @@

clear_dma_ff(QIC02_TAPE_DMA);
set_dma_mode(QIC02_TAPE_DMA, dma_mode);
- set_dma_addr(QIC02_TAPE_DMA, buffaddr+dma_bytes_done); /* full address */
+ set_dma_addr(QIC02_TAPE_DMA, (unsigned int)__va(buffaddr+dma_bytes_done)); /* full address */
set_dma_count(QIC02_TAPE_DMA, TAPE_BLKSIZE);

/* start tape DMA controller */
@@ -2039,7 +2041,7 @@
}
/* copy buffer to user-space in one go */
if (bytes_done>0)
- memcpy_tofs( (void *) buf, (void *) buffaddr, bytes_done);
+ memcpy_tofs( (void *) buf, (void *) __va(buffaddr), bytes_done);
#if 1
/* Checks Ton's patch below */
if ((return_read_eof == NO) && (status_eof_detected == YES)) {
@@ -2167,7 +2169,7 @@

/* copy from user to DMA buffer and initiate transfer. */
if (bytes_todo>0) {
- memcpy_fromfs( (void *) buffaddr, (const void *) buf, bytes_todo);
+ memcpy_fromfs( (void *) __va(buffaddr), (const void *) buf, bytes_todo);

/****************** similar problem with read() at FM could happen here at EOT.
******************/
@@ -2920,8 +2922,9 @@
* This assumes a one-to-one identity mapping between
* kernel addresses and physical memory.
*/
- buffaddr = align_buffer((unsigned long) &qic02_tape_buf, TAPE_BLKSIZE);
- printk(", at address 0x%lx (0x%lx)\n", buffaddr, (unsigned long) &qic02_tape_buf);
+ qic02_tape_buf = (char *)__pa(kmalloc(TPQBUF_SIZE+TAPE_BLKSIZE, GFP_DMA));
+ buffaddr = align_buffer((unsigned long) qic02_tape_buf, TAPE_BLKSIZE);
+ printk(", at address 0x%lx (0x%lx)\n", buffaddr, (unsigned long) qic02_tape_buf);

#ifndef CONFIG_MAX_16M
if (buffaddr+TPQBUF_SIZE>=0x1000000) {
@@ -2937,6 +2940,7 @@
free_irq(QIC02_TAPE_IRQ, NULL);
free_dma(QIC02_TAPE_DMA);
#endif
+ kfree(qic02_tape_buf);
return -ENODEV;
}

-- 
E-mail: weigo@wilma.rz.uni-leipzig.de
Phone : 0341/2614768