xref: /openbmc/linux/arch/m68k/include/asm/sun3xflop.h (revision 77a42796786c2ea2d3a67262fb5f1f707c3e0594)
149148020SSam Ravnborg /* sun3xflop.h: Sun3/80 specific parts of the floppy driver.
249148020SSam Ravnborg  *
349148020SSam Ravnborg  * Derived partially from asm-sparc/floppy.h, which is:
449148020SSam Ravnborg  *     Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
549148020SSam Ravnborg  *
649148020SSam Ravnborg  * Sun3x version 2/4/2000 Sam Creasey (sammy@sammy.net)
749148020SSam Ravnborg  */
849148020SSam Ravnborg 
949148020SSam Ravnborg #ifndef __ASM_SUN3X_FLOPPY_H
1049148020SSam Ravnborg #define __ASM_SUN3X_FLOPPY_H
1149148020SSam Ravnborg 
1249148020SSam Ravnborg #include <asm/page.h>
1349148020SSam Ravnborg #include <asm/pgtable.h>
1449148020SSam Ravnborg #include <asm/irq.h>
1549148020SSam Ravnborg #include <asm/sun3x.h>
1649148020SSam Ravnborg 
1749148020SSam Ravnborg /* default interrupt vector */
1849148020SSam Ravnborg #define SUN3X_FDC_IRQ 0x40
1949148020SSam Ravnborg 
2049148020SSam Ravnborg /* some constants */
2149148020SSam Ravnborg #define FCR_TC 0x1
2249148020SSam Ravnborg #define FCR_EJECT 0x2
2349148020SSam Ravnborg #define FCR_MTRON 0x4
2449148020SSam Ravnborg #define FCR_DSEL1 0x8
2549148020SSam Ravnborg #define FCR_DSEL0 0x10
2649148020SSam Ravnborg 
2749148020SSam Ravnborg /* We don't need no stinkin' I/O port allocation crap. */
2849148020SSam Ravnborg #undef release_region
2949148020SSam Ravnborg #undef request_region
3049148020SSam Ravnborg #define release_region(X, Y)	do { } while(0)
3149148020SSam Ravnborg #define request_region(X, Y, Z)	(1)
3249148020SSam Ravnborg 
3349148020SSam Ravnborg struct sun3xflop_private {
3449148020SSam Ravnborg 	volatile unsigned char *status_r;
3549148020SSam Ravnborg 	volatile unsigned char *data_r;
3649148020SSam Ravnborg 	volatile unsigned char *fcr_r;
3749148020SSam Ravnborg 	volatile unsigned char *fvr_r;
3849148020SSam Ravnborg 	unsigned char fcr;
3949148020SSam Ravnborg } sun3x_fdc;
4049148020SSam Ravnborg 
4149148020SSam Ravnborg /* Super paranoid... */
4249148020SSam Ravnborg #undef HAVE_DISABLE_HLT
4349148020SSam Ravnborg 
4449148020SSam Ravnborg /* Routines unique to each controller type on a Sun. */
4549148020SSam Ravnborg static unsigned char sun3x_82072_fd_inb(int port)
4649148020SSam Ravnborg {
4749148020SSam Ravnborg 	static int once = 0;
4849148020SSam Ravnborg //	udelay(5);
4949148020SSam Ravnborg 	switch(port & 7) {
5049148020SSam Ravnborg 	default:
5149148020SSam Ravnborg 		printk("floppy: Asked to read unknown port %d\n", port);
5249148020SSam Ravnborg 		panic("floppy: Port bolixed.");
5349148020SSam Ravnborg 	case 4: /* FD_STATUS */
5449148020SSam Ravnborg 		return (*sun3x_fdc.status_r) & ~STATUS_DMA;
5549148020SSam Ravnborg 	case 5: /* FD_DATA */
5649148020SSam Ravnborg 		return (*sun3x_fdc.data_r);
5749148020SSam Ravnborg 	case 7: /* FD_DIR */
5849148020SSam Ravnborg 		/* ugly hack, I can't find a way to actually detect the disk */
5949148020SSam Ravnborg 		if(!once) {
6049148020SSam Ravnborg 			once = 1;
6149148020SSam Ravnborg 			return 0x80;
6249148020SSam Ravnborg 		}
6349148020SSam Ravnborg 		return 0;
6449148020SSam Ravnborg 	};
6549148020SSam Ravnborg 	panic("sun_82072_fd_inb: How did I get here?");
6649148020SSam Ravnborg }
6749148020SSam Ravnborg 
6849148020SSam Ravnborg static void sun3x_82072_fd_outb(unsigned char value, int port)
6949148020SSam Ravnborg {
7049148020SSam Ravnborg //	udelay(5);
7149148020SSam Ravnborg 	switch(port & 7) {
7249148020SSam Ravnborg 	default:
7349148020SSam Ravnborg 		printk("floppy: Asked to write to unknown port %d\n", port);
7449148020SSam Ravnborg 		panic("floppy: Port bolixed.");
7549148020SSam Ravnborg 	case 2: /* FD_DOR */
7649148020SSam Ravnborg 		/* Oh geese, 82072 on the Sun has no DOR register,
7749148020SSam Ravnborg 		 * so we make do with taunting the FCR.
7849148020SSam Ravnborg 		 *
7949148020SSam Ravnborg 		 * ASSUMPTIONS:  There will only ever be one floppy
8049148020SSam Ravnborg 		 *               drive attached to a Sun controller
8149148020SSam Ravnborg 		 *               and it will be at drive zero.
8249148020SSam Ravnborg 		 */
8349148020SSam Ravnborg 
8449148020SSam Ravnborg 	{
8549148020SSam Ravnborg 		unsigned char fcr = sun3x_fdc.fcr;
8649148020SSam Ravnborg 
8749148020SSam Ravnborg 		if(value & 0x10) {
8849148020SSam Ravnborg 			fcr |= (FCR_DSEL0 | FCR_MTRON);
8949148020SSam Ravnborg 		} else
9049148020SSam Ravnborg 			fcr &= ~(FCR_DSEL0 | FCR_MTRON);
9149148020SSam Ravnborg 
9249148020SSam Ravnborg 
9349148020SSam Ravnborg 		if(fcr != sun3x_fdc.fcr) {
9449148020SSam Ravnborg 			*(sun3x_fdc.fcr_r) = fcr;
9549148020SSam Ravnborg 			sun3x_fdc.fcr = fcr;
9649148020SSam Ravnborg 		}
9749148020SSam Ravnborg 	}
9849148020SSam Ravnborg 		break;
9949148020SSam Ravnborg 	case 5: /* FD_DATA */
10049148020SSam Ravnborg 		*(sun3x_fdc.data_r) = value;
10149148020SSam Ravnborg 		break;
10249148020SSam Ravnborg 	case 7: /* FD_DCR */
10349148020SSam Ravnborg 		*(sun3x_fdc.status_r) = value;
10449148020SSam Ravnborg 		break;
10549148020SSam Ravnborg 	case 4: /* FD_STATUS */
10649148020SSam Ravnborg 		*(sun3x_fdc.status_r) = value;
10749148020SSam Ravnborg 		break;
10849148020SSam Ravnborg 	};
10949148020SSam Ravnborg 	return;
11049148020SSam Ravnborg }
11149148020SSam Ravnborg 
11249148020SSam Ravnborg 
11349148020SSam Ravnborg asmlinkage irqreturn_t sun3xflop_hardint(int irq, void *dev_id)
11449148020SSam Ravnborg {
11549148020SSam Ravnborg 	register unsigned char st;
11649148020SSam Ravnborg 
11749148020SSam Ravnborg #undef TRACE_FLPY_INT
11849148020SSam Ravnborg #define NO_FLOPPY_ASSEMBLER
11949148020SSam Ravnborg 
12049148020SSam Ravnborg #ifdef TRACE_FLPY_INT
12149148020SSam Ravnborg 	static int calls=0;
12249148020SSam Ravnborg 	static int bytes=0;
12349148020SSam Ravnborg 	static int dma_wait=0;
12449148020SSam Ravnborg #endif
12549148020SSam Ravnborg 	if(!doing_pdma) {
12649148020SSam Ravnborg 		floppy_interrupt(irq, dev_id);
12749148020SSam Ravnborg 		return IRQ_HANDLED;
12849148020SSam Ravnborg 	}
12949148020SSam Ravnborg 
13049148020SSam Ravnborg //	printk("doing pdma\n");// st %x\n", sun_fdc->status_82072);
13149148020SSam Ravnborg 
13249148020SSam Ravnborg #ifdef TRACE_FLPY_INT
13349148020SSam Ravnborg 	if(!calls)
13449148020SSam Ravnborg 		bytes = virtual_dma_count;
13549148020SSam Ravnborg #endif
13649148020SSam Ravnborg 
13749148020SSam Ravnborg 	{
13849148020SSam Ravnborg 		register int lcount;
13949148020SSam Ravnborg 		register char *lptr;
14049148020SSam Ravnborg 
14149148020SSam Ravnborg 		for(lcount=virtual_dma_count, lptr=virtual_dma_addr;
14249148020SSam Ravnborg 		    lcount; lcount--, lptr++) {
14349148020SSam Ravnborg /*			st=fd_inb(virtual_dma_port+4) & 0x80 ;  */
14449148020SSam Ravnborg 			st = *(sun3x_fdc.status_r);
14549148020SSam Ravnborg /*			if(st != 0xa0)                  */
14649148020SSam Ravnborg /*				break;                  */
14749148020SSam Ravnborg 
14849148020SSam Ravnborg 			if((st & 0x80) == 0) {
14949148020SSam Ravnborg 				virtual_dma_count = lcount;
15049148020SSam Ravnborg 				virtual_dma_addr = lptr;
15149148020SSam Ravnborg 				return IRQ_HANDLED;
15249148020SSam Ravnborg 			}
15349148020SSam Ravnborg 
15449148020SSam Ravnborg 			if((st & 0x20) == 0)
15549148020SSam Ravnborg 				break;
15649148020SSam Ravnborg 
15749148020SSam Ravnborg 			if(virtual_dma_mode)
15849148020SSam Ravnborg /*				fd_outb(*lptr, virtual_dma_port+5); */
15949148020SSam Ravnborg 				*(sun3x_fdc.data_r) = *lptr;
16049148020SSam Ravnborg 			else
16149148020SSam Ravnborg /*				*lptr = fd_inb(virtual_dma_port+5); */
16249148020SSam Ravnborg 				*lptr = *(sun3x_fdc.data_r);
16349148020SSam Ravnborg 		}
16449148020SSam Ravnborg 
16549148020SSam Ravnborg 		virtual_dma_count = lcount;
16649148020SSam Ravnborg 		virtual_dma_addr = lptr;
16749148020SSam Ravnborg /*		st = fd_inb(virtual_dma_port+4);   */
16849148020SSam Ravnborg 		st = *(sun3x_fdc.status_r);
16949148020SSam Ravnborg 	}
17049148020SSam Ravnborg 
17149148020SSam Ravnborg #ifdef TRACE_FLPY_INT
17249148020SSam Ravnborg 	calls++;
17349148020SSam Ravnborg #endif
17449148020SSam Ravnborg //	printk("st=%02x\n", st);
17549148020SSam Ravnborg 	if(st == 0x20)
17649148020SSam Ravnborg 		return IRQ_HANDLED;
17749148020SSam Ravnborg 	if(!(st & 0x20)) {
17849148020SSam Ravnborg 		virtual_dma_residue += virtual_dma_count;
17949148020SSam Ravnborg 		virtual_dma_count=0;
18049148020SSam Ravnborg 		doing_pdma = 0;
18149148020SSam Ravnborg 
18249148020SSam Ravnborg #ifdef TRACE_FLPY_INT
18349148020SSam Ravnborg 		printk("count=%x, residue=%x calls=%d bytes=%x dma_wait=%d\n",
18449148020SSam Ravnborg 		       virtual_dma_count, virtual_dma_residue, calls, bytes,
18549148020SSam Ravnborg 		       dma_wait);
18649148020SSam Ravnborg 		calls = 0;
18749148020SSam Ravnborg 		dma_wait=0;
18849148020SSam Ravnborg #endif
18949148020SSam Ravnborg 
19049148020SSam Ravnborg 		floppy_interrupt(irq, dev_id);
19149148020SSam Ravnborg 		return IRQ_HANDLED;
19249148020SSam Ravnborg 	}
19349148020SSam Ravnborg 
19449148020SSam Ravnborg 
19549148020SSam Ravnborg #ifdef TRACE_FLPY_INT
19649148020SSam Ravnborg 	if(!virtual_dma_count)
19749148020SSam Ravnborg 		dma_wait++;
19849148020SSam Ravnborg #endif
19949148020SSam Ravnborg 	return IRQ_HANDLED;
20049148020SSam Ravnborg }
20149148020SSam Ravnborg 
20249148020SSam Ravnborg static int sun3xflop_request_irq(void)
20349148020SSam Ravnborg {
20449148020SSam Ravnborg 	static int once = 0;
20549148020SSam Ravnborg 	int error;
20649148020SSam Ravnborg 
20749148020SSam Ravnborg 	if(!once) {
20849148020SSam Ravnborg 		once = 1;
20949148020SSam Ravnborg 		error = request_irq(FLOPPY_IRQ, sun3xflop_hardint,
210*77a42796SMichael Opdenacker 				    0, "floppy", NULL);
21149148020SSam Ravnborg 		return ((error == 0) ? 0 : -1);
21249148020SSam Ravnborg 	} else return 0;
21349148020SSam Ravnborg }
21449148020SSam Ravnborg 
21549148020SSam Ravnborg static void __init floppy_set_flags(int *ints,int param, int param2);
21649148020SSam Ravnborg 
21749148020SSam Ravnborg static int sun3xflop_init(void)
21849148020SSam Ravnborg {
21949148020SSam Ravnborg 	if(FLOPPY_IRQ < 0x40)
22049148020SSam Ravnborg 		FLOPPY_IRQ = SUN3X_FDC_IRQ;
22149148020SSam Ravnborg 
22249148020SSam Ravnborg 	sun3x_fdc.status_r = (volatile unsigned char *)SUN3X_FDC;
22349148020SSam Ravnborg 	sun3x_fdc.data_r  = (volatile unsigned char *)(SUN3X_FDC+1);
22449148020SSam Ravnborg 	sun3x_fdc.fcr_r = (volatile unsigned char *)SUN3X_FDC_FCR;
22549148020SSam Ravnborg 	sun3x_fdc.fvr_r = (volatile unsigned char *)SUN3X_FDC_FVR;
22649148020SSam Ravnborg 	sun3x_fdc.fcr = 0;
22749148020SSam Ravnborg 
22849148020SSam Ravnborg 	/* Last minute sanity check... */
22949148020SSam Ravnborg 	if(*sun3x_fdc.status_r == 0xff) {
23049148020SSam Ravnborg 		return -1;
23149148020SSam Ravnborg 	}
23249148020SSam Ravnborg 
23349148020SSam Ravnborg 	*sun3x_fdc.fvr_r = FLOPPY_IRQ;
23449148020SSam Ravnborg 
23549148020SSam Ravnborg 	*sun3x_fdc.fcr_r = FCR_TC;
23649148020SSam Ravnborg 	udelay(10);
23749148020SSam Ravnborg 	*sun3x_fdc.fcr_r = 0;
23849148020SSam Ravnborg 
23949148020SSam Ravnborg 	/* Success... */
24049148020SSam Ravnborg 	floppy_set_flags(NULL, 1, FD_BROKEN_DCL); // I don't know how to detect this.
24149148020SSam Ravnborg 	allowed_drive_mask = 0x01;
24249148020SSam Ravnborg 	return (int) SUN3X_FDC;
24349148020SSam Ravnborg }
24449148020SSam Ravnborg 
24549148020SSam Ravnborg /* I'm not precisely sure this eject routine works */
24649148020SSam Ravnborg static int sun3x_eject(void)
24749148020SSam Ravnborg {
24849148020SSam Ravnborg 	if(MACH_IS_SUN3X) {
24949148020SSam Ravnborg 
25049148020SSam Ravnborg 		sun3x_fdc.fcr |= (FCR_DSEL0 | FCR_EJECT);
25149148020SSam Ravnborg 		*(sun3x_fdc.fcr_r) = sun3x_fdc.fcr;
25249148020SSam Ravnborg 		udelay(10);
25349148020SSam Ravnborg 		sun3x_fdc.fcr &= ~(FCR_DSEL0 | FCR_EJECT);
25449148020SSam Ravnborg 		*(sun3x_fdc.fcr_r) = sun3x_fdc.fcr;
25549148020SSam Ravnborg 	}
25649148020SSam Ravnborg 
25749148020SSam Ravnborg 	return 0;
25849148020SSam Ravnborg }
25949148020SSam Ravnborg 
26049148020SSam Ravnborg #define fd_eject(drive) sun3x_eject()
26149148020SSam Ravnborg 
26249148020SSam Ravnborg #endif /* !(__ASM_SUN3X_FLOPPY_H) */
263