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