Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.17 263 lines 5.8 kB view raw
1/* sun3xflop.h: Sun3/80 specific parts of the floppy driver. 2 * 3 * Derived partially from asm-sparc/floppy.h, which is: 4 * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) 5 * 6 * Sun3x version 2/4/2000 Sam Creasey (sammy@sammy.net) 7 */ 8 9#ifndef __ASM_SUN3X_FLOPPY_H 10#define __ASM_SUN3X_FLOPPY_H 11 12#include <asm/page.h> 13#include <asm/pgtable.h> 14#include <asm/system.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 34struct 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. */ 46static unsigned char sun3x_82072_fd_inb(int port) 47{ 48 static int once = 0; 49// udelay(5); 50 switch(port & 7) { 51 default: 52 printk("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 69static void sun3x_82072_fd_outb(unsigned char value, int port) 70{ 71// udelay(5); 72 switch(port & 7) { 73 default: 74 printk("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 114asmlinkage irqreturn_t sun3xflop_hardint(int irq, void *dev_id, 115 struct pt_regs * regs) 116{ 117 register unsigned char st; 118 119#undef TRACE_FLPY_INT 120#define NO_FLOPPY_ASSEMBLER 121 122#ifdef TRACE_FLPY_INT 123 static int calls=0; 124 static int bytes=0; 125 static int dma_wait=0; 126#endif 127 if(!doing_pdma) { 128 floppy_interrupt(irq, dev_id, regs); 129 return IRQ_HANDLED; 130 } 131 132// printk("doing pdma\n");// st %x\n", sun_fdc->status_82072); 133 134#ifdef TRACE_FLPY_INT 135 if(!calls) 136 bytes = virtual_dma_count; 137#endif 138 139 { 140 register int lcount; 141 register char *lptr; 142 143 for(lcount=virtual_dma_count, lptr=virtual_dma_addr; 144 lcount; lcount--, lptr++) { 145/* st=fd_inb(virtual_dma_port+4) & 0x80 ; */ 146 st = *(sun3x_fdc.status_r); 147/* if(st != 0xa0) */ 148/* break; */ 149 150 if((st & 0x80) == 0) { 151 virtual_dma_count = lcount; 152 virtual_dma_addr = lptr; 153 return IRQ_HANDLED; 154 } 155 156 if((st & 0x20) == 0) 157 break; 158 159 if(virtual_dma_mode) 160/* fd_outb(*lptr, virtual_dma_port+5); */ 161 *(sun3x_fdc.data_r) = *lptr; 162 else 163/* *lptr = fd_inb(virtual_dma_port+5); */ 164 *lptr = *(sun3x_fdc.data_r); 165 } 166 167 virtual_dma_count = lcount; 168 virtual_dma_addr = lptr; 169/* st = fd_inb(virtual_dma_port+4); */ 170 st = *(sun3x_fdc.status_r); 171 } 172 173#ifdef TRACE_FLPY_INT 174 calls++; 175#endif 176// printk("st=%02x\n", st); 177 if(st == 0x20) 178 return IRQ_HANDLED; 179 if(!(st & 0x20)) { 180 virtual_dma_residue += virtual_dma_count; 181 virtual_dma_count=0; 182 doing_pdma = 0; 183 184#ifdef TRACE_FLPY_INT 185 printk("count=%x, residue=%x calls=%d bytes=%x dma_wait=%d\n", 186 virtual_dma_count, virtual_dma_residue, calls, bytes, 187 dma_wait); 188 calls = 0; 189 dma_wait=0; 190#endif 191 192 floppy_interrupt(irq, dev_id, regs); 193 return IRQ_HANDLED; 194 } 195 196 197#ifdef TRACE_FLPY_INT 198 if(!virtual_dma_count) 199 dma_wait++; 200#endif 201 return IRQ_HANDLED; 202} 203 204static int sun3xflop_request_irq(void) 205{ 206 static int once = 0; 207 int error; 208 209 if(!once) { 210 once = 1; 211 error = request_irq(FLOPPY_IRQ, sun3xflop_hardint, SA_INTERRUPT, "floppy", NULL); 212 return ((error == 0) ? 0 : -1); 213 } else return 0; 214} 215 216static void __init floppy_set_flags(int *ints,int param, int param2); 217 218static 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 */ 247static 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) */