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