patch-1.3.92 linux/include/asm-i386/floppy.h

Next file: linux/include/asm-sparc/floppy.h
Previous file: linux/include/asm-alpha/system.h
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v1.3.91/linux/include/asm-i386/floppy.h linux/include/asm-i386/floppy.h
@@ -10,24 +10,231 @@
 #ifndef __ASM_I386_FLOPPY_H
 #define __ASM_I386_FLOPPY_H
 
+
+#define SW fd_routine[use_virtual_dma&1]
+
+
 #define fd_inb(port)			inb_p(port)
 #define fd_outb(port,value)		outb_p(port,value)
 
-#define fd_enable_dma()         enable_dma(FLOPPY_DMA)
-#define fd_disable_dma()        disable_dma(FLOPPY_DMA)
-#define fd_request_dma()        request_dma(FLOPPY_DMA,"floppy")
-#define fd_free_dma()           free_dma(FLOPPY_DMA)
-#define fd_clear_dma_ff()       clear_dma_ff(FLOPPY_DMA)
-#define fd_set_dma_mode(mode)   set_dma_mode(FLOPPY_DMA,mode)
-#define fd_set_dma_addr(addr)   set_dma_addr(FLOPPY_DMA,addr)
-#define fd_set_dma_count(count) set_dma_count(FLOPPY_DMA,count)
+#define fd_enable_dma()         SW._enable_dma(FLOPPY_DMA)
+#define fd_disable_dma()        SW._disable_dma(FLOPPY_DMA)
+#define fd_request_dma()        SW._request_dma(FLOPPY_DMA,"floppy")
+#define fd_free_dma()           SW._free_dma(FLOPPY_DMA)
+#define fd_clear_dma_ff()       SW._clear_dma_ff(FLOPPY_DMA)
+#define fd_set_dma_mode(mode)   SW._set_dma_mode(FLOPPY_DMA,mode)
+#define fd_set_dma_addr(addr)   SW._set_dma_addr(FLOPPY_DMA,addr)
+#define fd_set_dma_count(count) SW._set_dma_count(FLOPPY_DMA,count)
 #define fd_enable_irq()         enable_irq(FLOPPY_IRQ)
 #define fd_disable_irq()        disable_irq(FLOPPY_IRQ)
 #define fd_cacheflush(addr,size) /* nothing */
-#define fd_request_irq()        request_irq(FLOPPY_IRQ, floppy_interrupt, \
-					    SA_INTERRUPT|SA_SAMPLE_RANDOM, \
-				            "floppy", NULL)
-#define fd_free_irq()           free_irq(FLOPPY_IRQ, NULL);
+#define fd_request_irq()        SW._request_irq(FLOPPY_IRQ, floppy_interrupt, \
+					       SA_INTERRUPT|SA_SAMPLE_RANDOM, \
+					       "floppy", NULL)
+#define fd_free_irq()		free_irq(FLOPPY_IRQ, NULL)
+#define fd_get_dma_residue()    SW._get_dma_residue(FLOPPY_DMA)
+
+static int virtual_dma_count=0;
+static int virtual_dma_residue=0;
+static unsigned long virtual_dma_addr=0;
+static int virtual_dma_mode=0;
+static int doing_pdma=0;
+
+static void floppy_hardint(int irq, void *dev_id, struct pt_regs * regs)
+{
+	register unsigned char st;
+
+#undef TRACE_FLPY_INT
+#undef NO_FLOPPY_ASSEMBLER
+
+#ifdef TRACE_FLPY_INT
+	static int calls=0;
+	static int bytes=0;
+	static int dma_wait=0;
+#endif
+	if(!doing_pdma) {
+		floppy_interrupt(irq, dev_id, regs);
+		return;
+	}
+
+#ifdef TRACE_FLPY_INT
+	if(!calls)
+		bytes = virtual_dma_count;
+#endif
+
+#ifndef NO_FLOPPY_ASSEMBLER
+	__asm__ (
+       "testl %1,%1
+	je 3f
+1:	inb %w4,%b0
+	andb $160,%b0
+	cmpb $160,%b0
+	jne 2f
+	incw %w4
+	testl %3,%3
+	jne 4f
+	inb %w4,%b0
+	movb %0,(%2)
+	jmp 5f
+4:     	movb (%2),%0
+	outb %b0,%w4
+5:	decw %w4
+	outb %0,$0x80
+	decl %1
+	incl %2
+	testl %1,%1
+	jne 1b
+3:	inb %w4,%b0
+2:	"
+       : "=a" ((char) st), 
+       "=c" ((long) virtual_dma_count), 
+       "=S" ((long) virtual_dma_addr)
+       : "b" ((long) virtual_dma_mode),
+       "d" ((short) virtual_dma_port+4), 
+       "1" ((long) virtual_dma_count),
+       "2" ((long) virtual_dma_addr));
+#else	
+	{
+		register int lcount;
+		register char *lptr;
+
+		st = 1;
+		for(lcount=virtual_dma_count, lptr=(char *)virtual_dma_addr; 
+		    lcount; lcount--, lptr++) {
+			st=inb(virtual_dma_port+4) & 0xa0 ;
+			if(st != 0xa0) 
+				break;
+			if(virtual_dma_mode)
+				outb_p(*lptr, virtual_dma_port+5);
+			else
+				*lptr = inb_p(virtual_dma_port+5);
+			st = inb(virtual_dma_port+4);
+		}
+		virtual_dma_count = lcount;
+		virtual_dma_addr = (int) lptr;
+	}
+#endif
+
+#ifdef TRACE_FLPY_INT
+	calls++;
+#endif
+	if(st == 0x20)
+		return;
+	if(!(st & 0x20)) {
+		virtual_dma_residue += virtual_dma_count;
+		virtual_dma_count=0;
+#ifdef TRACE_FLPY_INT
+		printk("count=%x, residue=%x calls=%d bytes=%d dma_wait=%d\n", 
+		       virtual_dma_count, virtual_dma_residue, calls, bytes,
+		       dma_wait);
+		calls = 0;
+		dma_wait=0;
+#endif
+		doing_pdma = 0;
+		floppy_interrupt(irq, dev_id, regs);
+		return;
+	}
+#ifdef TRACE_FLPY_INT
+	if(!virtual_dma_count)
+		dma_wait++;
+#endif
+}
+
+static void vdma_enable_dma(unsigned int dummy)
+{
+	doing_pdma = 1;
+}
+
+static void vdma_disable_dma(unsigned int dummy)
+{
+	doing_pdma = 0;
+	virtual_dma_residue += virtual_dma_count;
+	virtual_dma_count=0;		
+}
+
+static int vdma_request_dma(unsigned int dmanr, const char * device_id)
+{
+	return 0;
+}
+
+static void vdma_nop(unsigned int dummy)
+{
+}
+
+static void vdma_set_dma_mode(unsigned int dummy,char mode)
+{
+	virtual_dma_mode = (mode  == DMA_MODE_WRITE);
+}
+
+static void vdma_set_dma_addr(unsigned int dummy,unsigned int addr)
+{
+	virtual_dma_addr = addr;
+}
+
+static void vdma_set_dma_count(unsigned int dummy,unsigned int count)
+{
+	virtual_dma_count = count;
+	virtual_dma_residue = 0;
+}
+
+static int vdma_get_dma_residue(unsigned int dummy)
+{
+	return virtual_dma_count + virtual_dma_residue;
+}
+
+
+static int vdma_request_irq(unsigned int irq,
+			    void (*handler)(int, void *, struct pt_regs *),
+			    unsigned long flags, 
+			    const char *device,
+			    void *dev_id)
+{
+	return request_irq(irq, floppy_hardint,SA_INTERRUPT,device, dev_id);
+
+}
+
+
+struct fd_routine_l {
+	void (*_enable_dma)(unsigned int dummy);
+	void (*_disable_dma)(unsigned int dummy);
+	int (*_request_dma)(unsigned int dmanr, const char * device_id);
+	void (*_free_dma)(unsigned int dmanr);
+	void (*_clear_dma_ff)(unsigned int dummy);
+	void (*_set_dma_mode)(unsigned int dummy, char mode);
+	void (*_set_dma_addr)(unsigned int dummy, unsigned int addr);
+	void (*_set_dma_count)(unsigned int dummy, unsigned int count);
+	int (*_get_dma_residue)(unsigned int dummy);
+	int (*_request_irq)(unsigned int irq,
+			   void (*handler)(int, void *, struct pt_regs *),
+			   unsigned long flags, 
+			   const char *device,
+			   void *dev_id);
+} fd_routine[] = {
+	{
+		enable_dma,
+		disable_dma,
+		request_dma,
+		free_dma,
+		clear_dma_ff,
+		set_dma_mode,
+		set_dma_addr,
+		set_dma_count,
+		get_dma_residue,
+		request_irq,
+	},
+	{
+		vdma_enable_dma,
+		vdma_disable_dma,
+		vdma_request_dma,
+		vdma_nop,
+		vdma_nop,
+		vdma_set_dma_mode,
+		vdma_set_dma_addr,
+		vdma_set_dma_count,
+		vdma_get_dma_residue,
+		vdma_request_irq
+	}
+};
 
 __inline__ void virtual_dma_init(void)
 {

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov with Sam's (original) version
of this