1 /* SPDX-License-Identifier: GPL-2.0 */ 2 /* sun3xflop.h: Sun3/80 specific parts of the floppy driver. 3 * 4 * Derived partially from asm-sparc/floppy.h, which is: 5 * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) 6 * 7 * Sun3x version 2/4/2000 Sam Creasey (sammy@sammy.net) 8 */ 9 10 #ifndef __ASM_SUN3X_FLOPPY_H 11 #define __ASM_SUN3X_FLOPPY_H 12 13 #include <linux/pgtable.h> 14 #include <asm/page.h> 15 #include <asm/irq.h> 16 #include <asm/sun3x.h> 17 18 /* default interrupt vector */ 19 #define SUN3X_FDC_IRQ 0x40 20 21 /* some constants */ 22 #define FCR_TC 0x1 23 #define FCR_EJECT 0x2 24 #define FCR_MTRON 0x4 25 #define FCR_DSEL1 0x8 26 #define FCR_DSEL0 0x10 27 28 /* We don't need no stinkin' I/O port allocation crap. */ 29 #undef release_region 30 #undef request_region 31 #define release_region(X, Y) do { } while(0) 32 #define request_region(X, Y, Z) (1) 33 34 struct sun3xflop_private { 35 volatile unsigned char *status_r; 36 volatile unsigned char *data_r; 37 volatile unsigned char *fcr_r; 38 volatile unsigned char *fvr_r; 39 unsigned char fcr; 40 } sun3x_fdc; 41 42 /* Super paranoid... */ 43 #undef HAVE_DISABLE_HLT 44 45 /* Routines unique to each controller type on a Sun. */ 46 static unsigned char sun3x_82072_fd_inb(int port) 47 { 48 static int once = 0; 49 // udelay(5); 50 switch(port & 7) { 51 default: 52 pr_crit("floppy: Asked to read unknown port %d\n", port); 53 panic("floppy: Port bolixed."); 54 case 4: /* FD_STATUS */ 55 return (*sun3x_fdc.status_r) & ~STATUS_DMA; 56 case 5: /* FD_DATA */ 57 return (*sun3x_fdc.data_r); 58 case 7: /* FD_DIR */ 59 /* ugly hack, I can't find a way to actually detect the disk */ 60 if(!once) { 61 once = 1; 62 return 0x80; 63 } 64 return 0; 65 }; 66 panic("sun_82072_fd_inb: How did I get here?"); 67 } 68 69 static void sun3x_82072_fd_outb(unsigned char value, int port) 70 { 71 // udelay(5); 72 switch(port & 7) { 73 default: 74 pr_crit("floppy: Asked to write to unknown port %d\n", port); 75 panic("floppy: Port bolixed."); 76 case 2: /* FD_DOR */ 77 /* Oh geese, 82072 on the Sun has no DOR register, 78 * so we make do with taunting the FCR. 79 * 80 * ASSUMPTIONS: There will only ever be one floppy 81 * drive attached to a Sun controller 82 * and it will be at drive zero. 83 */ 84 85 { 86 unsigned char fcr = sun3x_fdc.fcr; 87 88 if(value & 0x10) { 89 fcr |= (FCR_DSEL0 | FCR_MTRON); 90 } else 91 fcr &= ~(FCR_DSEL0 | FCR_MTRON); 92 93 94 if(fcr != sun3x_fdc.fcr) { 95 *(sun3x_fdc.fcr_r) = fcr; 96 sun3x_fdc.fcr = fcr; 97 } 98 } 99 break; 100 case 5: /* FD_DATA */ 101 *(sun3x_fdc.data_r) = value; 102 break; 103 case 7: /* FD_DCR */ 104 *(sun3x_fdc.status_r) = value; 105 break; 106 case 4: /* FD_STATUS */ 107 *(sun3x_fdc.status_r) = value; 108 break; 109 } 110 return; 111 } 112 113 114 asmlinkage irqreturn_t sun3xflop_hardint(int irq, void *dev_id) 115 { 116 register unsigned char st; 117 118 #undef TRACE_FLPY_INT 119 #define NO_FLOPPY_ASSEMBLER 120 121 #ifdef TRACE_FLPY_INT 122 static int calls=0; 123 static int bytes=0; 124 static int dma_wait=0; 125 #endif 126 if(!doing_pdma) { 127 floppy_interrupt(irq, dev_id); 128 return IRQ_HANDLED; 129 } 130 131 // pr_info("doing pdma\n");// st %x\n", sun_fdc->status_82072); 132 133 #ifdef TRACE_FLPY_INT 134 if(!calls) 135 bytes = virtual_dma_count; 136 #endif 137 138 { 139 register int lcount; 140 register char *lptr; 141 142 for(lcount=virtual_dma_count, lptr=virtual_dma_addr; 143 lcount; lcount--, lptr++) { 144 /* st=fd_inb(virtual_dma_port+4) & 0x80 ; */ 145 st = *(sun3x_fdc.status_r); 146 /* if(st != 0xa0) */ 147 /* break; */ 148 149 if((st & 0x80) == 0) { 150 virtual_dma_count = lcount; 151 virtual_dma_addr = lptr; 152 return IRQ_HANDLED; 153 } 154 155 if((st & 0x20) == 0) 156 break; 157 158 if(virtual_dma_mode) 159 /* fd_outb(*lptr, virtual_dma_port+5); */ 160 *(sun3x_fdc.data_r) = *lptr; 161 else 162 /* *lptr = fd_inb(virtual_dma_port+5); */ 163 *lptr = *(sun3x_fdc.data_r); 164 } 165 166 virtual_dma_count = lcount; 167 virtual_dma_addr = lptr; 168 /* st = fd_inb(virtual_dma_port+4); */ 169 st = *(sun3x_fdc.status_r); 170 } 171 172 #ifdef TRACE_FLPY_INT 173 calls++; 174 #endif 175 // pr_info("st=%02x\n", st); 176 if(st == 0x20) 177 return IRQ_HANDLED; 178 if(!(st & 0x20)) { 179 virtual_dma_residue += virtual_dma_count; 180 virtual_dma_count=0; 181 doing_pdma = 0; 182 183 #ifdef TRACE_FLPY_INT 184 pr_info("count=%x, residue=%x calls=%d bytes=%x dma_wait=%d\n", 185 virtual_dma_count, virtual_dma_residue, calls, bytes, 186 dma_wait); 187 calls = 0; 188 dma_wait=0; 189 #endif 190 191 floppy_interrupt(irq, dev_id); 192 return IRQ_HANDLED; 193 } 194 195 196 #ifdef TRACE_FLPY_INT 197 if(!virtual_dma_count) 198 dma_wait++; 199 #endif 200 return IRQ_HANDLED; 201 } 202 203 static int sun3xflop_request_irq(void) 204 { 205 static int once = 0; 206 int error; 207 208 if(!once) { 209 once = 1; 210 error = request_irq(FLOPPY_IRQ, sun3xflop_hardint, 211 0, "floppy", NULL); 212 return ((error == 0) ? 0 : -1); 213 } else return 0; 214 } 215 216 static void __init floppy_set_flags(int *ints,int param, int param2); 217 218 static int sun3xflop_init(void) 219 { 220 if(FLOPPY_IRQ < 0x40) 221 FLOPPY_IRQ = SUN3X_FDC_IRQ; 222 223 sun3x_fdc.status_r = (volatile unsigned char *)SUN3X_FDC; 224 sun3x_fdc.data_r = (volatile unsigned char *)(SUN3X_FDC+1); 225 sun3x_fdc.fcr_r = (volatile unsigned char *)SUN3X_FDC_FCR; 226 sun3x_fdc.fvr_r = (volatile unsigned char *)SUN3X_FDC_FVR; 227 sun3x_fdc.fcr = 0; 228 229 /* Last minute sanity check... */ 230 if(*sun3x_fdc.status_r == 0xff) { 231 return -1; 232 } 233 234 *sun3x_fdc.fvr_r = FLOPPY_IRQ; 235 236 *sun3x_fdc.fcr_r = FCR_TC; 237 udelay(10); 238 *sun3x_fdc.fcr_r = 0; 239 240 /* Success... */ 241 floppy_set_flags(NULL, 1, FD_BROKEN_DCL); // I don't know how to detect this. 242 allowed_drive_mask = 0x01; 243 return (int) SUN3X_FDC; 244 } 245 246 /* I'm not precisely sure this eject routine works */ 247 static int sun3x_eject(void) 248 { 249 if(MACH_IS_SUN3X) { 250 251 sun3x_fdc.fcr |= (FCR_DSEL0 | FCR_EJECT); 252 *(sun3x_fdc.fcr_r) = sun3x_fdc.fcr; 253 udelay(10); 254 sun3x_fdc.fcr &= ~(FCR_DSEL0 | FCR_EJECT); 255 *(sun3x_fdc.fcr_r) = sun3x_fdc.fcr; 256 } 257 258 return 0; 259 } 260 261 #define fd_eject(drive) sun3x_eject() 262 263 #endif /* !(__ASM_SUN3X_FLOPPY_H) */ 264