From: <pal...@us...> - 2005-01-16 23:27:53
|
Update of /cvsroot/gc-linux/linux/drivers/block In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv24723/drivers/block Modified Files: gcn-aram.c Log Message: Fixed buffer invalidation on interrupt reception. Index: gcn-aram.c =================================================================== RCS file: /cvsroot/gc-linux/linux/drivers/block/gcn-aram.c,v retrieving revision 1.3 retrieving revision 1.4 diff -u -d -r1.3 -r1.4 --- gcn-aram.c 13 Jan 2005 01:55:31 -0000 1.3 +++ gcn-aram.c 16 Jan 2005 23:27:42 -0000 1.4 @@ -34,18 +34,20 @@ #include <linux/hdreg.h> /* HDIO_GETGEO */ #include <asm/io.h> +#include <asm/scatterlist.h> #define ARAM_MAJOR Z2RAM_MAJOR #define HARD_SECTOR_SIZE 512 +//#define ARAM_DEBUG //#define ARAM_DBG printk #define ARAM_DBG(format, arg...); { } #define ARAM_SOUNDMEMORYOFFSET 0 #define ARAM_BUFFERSIZE (16*1024*1024 - ARAM_SOUNDMEMORYOFFSET) -#define AI_DSP_CSR (void* __iomem)0xCC00500A +#define AI_DSP_CSR (void __iomem *)0xCC00500A #define AI_CSR_RES (1<<0) #define AI_CSR_PIINT (1<<1) #define AI_CSR_HALT (1<<2) @@ -58,9 +60,17 @@ #define AI_CSR_DSPDMA (1<<9) #define AI_CSR_RESETXXX (1<<11) -#define AR_DMA_MMADDR (void* __iomem)0xCC005020 -#define AR_DMA_ARADDR (void* __iomem)0xCC005024 -#define AR_DMA_CNT (void* __iomem)0xCC005028 +#define AR_SIZE (void __iomem*)0xCC005012 +#define AR_MODE (void __iomem*)0xCC005016 +#define AR_MODE_ACCELERATOR (1 << 0) + +#define AR_REFRESH (void __iomem*)0xCC00501A + +#define AR_DMA_MMADDR (void __iomem*)0xCC005020 +#define AR_DMA_ARADDR (void __iomem*)0xCC005024 +#define AR_DMA_CNT_H (void __iomem*)0xCC005028 +#define AR_DMA_CNT_L (void __iomem*)0xCC00502A +#define AR_DMA_CNT AR_DMA_CNT_H #define ARAM_READ (1 << 31) #define ARAM_WRITE 0 @@ -80,36 +90,51 @@ static inline void ARAM_StartDMA(void *mmAddr, unsigned long arAddr, unsigned long length, unsigned long type) { +#ifdef ARAM_DEBUG + if ((readw(AI_DSP_CSR) & AI_CSR_DSPDMA) || + (readl(AR_DMA_CNT) & 0x7FFFFFFF)) { + printk("StartDMA called, but there is already an outstanding DMA request!\n"); + } + else if (((u32)mmAddr & 0x1F) || (length & 0x1F)) { + printk("StartDMA called on unaligned data\n"); + } +#endif + /* process */ writel(virt_to_phys(mmAddr),AR_DMA_MMADDR); writel(arAddr,AR_DMA_ARADDR); + /* writing the low-word kicks off the DMA */ writel(type | length,AR_DMA_CNT); } static irqreturn_t aram_irq(int irq,void *dev_id,struct pt_regs *regs) { unsigned long flags; - unsigned long len; u16 tmp; struct request *req; if (readw(AI_DSP_CSR) & AI_CSR_ARINT) { +#ifdef ARAM_DEBUG + if (readw(AI_DSP_CSR) & AI_CSR_DSPDMA) { + flags = readl(AR_DMA_CNT); + do { + cpu_relax(); + } while(readw(AI_DSP_CSR) & AI_CSR_DSPDMA); + printk("Received interrupt before completion, number of bytes remaining was %lu\n",flags); + } + else if ((flags = (readl(AR_DMA_CNT) & 0x7FFFFFFF))) { + printk("Received interrupt before completion, number of bytes remaining was %lu\n",flags); + } +#endif /* ack the int, but only ours */ local_irq_save(flags); tmp = readw(AI_DSP_CSR); - tmp &= ~(AI_CSR_PIINT | AI_CSR_AIDINT | AI_CSR_DSPINT); + tmp &= ~(AI_CSR_AIDINT | AI_CSR_DSPINT); writew(tmp,AI_DSP_CSR); local_irq_restore(flags); /* now process */ - spin_lock_irqsave(&aram_lock,flags); + spin_lock(&aram_lock); if ((req = irq_request)) { - len = req->current_nr_sectors << 9; - /* invalidate cache on read */ - if (rq_data_dir(req) == READ) { - invalidate_dcache_range( - (unsigned long)req->buffer, - (unsigned long)req->buffer + len); - } /* complete request */ if (!end_that_request_first(req,1, req->current_nr_sectors)) { @@ -126,7 +151,7 @@ else { printk(KERN_ERR DEVICE_NAME " received an interrupt but no irq_request set\n"); } - spin_unlock_irqrestore(&aram_lock,flags); + spin_unlock(&aram_lock); /* return handled */ return IRQ_HANDLED; } @@ -140,7 +165,7 @@ unsigned long start; unsigned long len; unsigned long flags; - /*unsigned long flags; */ + spin_lock_irqsave(&aram_lock,flags); while ((req = elv_next_request(q))) { @@ -165,6 +190,9 @@ irq_request = req; /* schedule DMA */ if (rq_data_dir(req) == READ) { + invalidate_dcache_range((unsigned long)req->buffer, + (unsigned long)req->buffer + + len); ARAM_StartDMA(req->buffer, start + ARAM_SOUNDMEMORYOFFSET, len, ARAM_READ); @@ -228,7 +256,7 @@ return ioctl_by_bdev(inode->i_bdev,cmd,arg); case HDIO_GETGEO: /* fake the entries */ - geo.heads = 32; + geo.heads = 16; geo.sectors = 32; geo.start = 0; geo.cylinders = ARAM_BUFFERSIZE / (geo.heads * geo.sectors); @@ -301,11 +329,14 @@ /* lock this since audio driver might be using it */ local_irq_save(flags); - writew(readw(AI_DSP_CSR) | AI_CSR_ARINTMASK,AI_DSP_CSR); + writew(readw(AI_DSP_CSR) | AI_CSR_ARINTMASK | AI_CSR_PIINT,AI_DSP_CSR); local_irq_restore(flags); refCount = 0; + printk("ARAM info: Size = %u,Mode = 0x%x,Refresh = %u\n", + readw(AR_SIZE),readw(AR_MODE),readl(AR_REFRESH)); + return 0; out_queue: |