Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
at v2.6.25-rc2 278 lines 6.6 kB view raw
1/* 2 * Architecture specific parts of the Floppy driver 3 * 4 * This file is subject to the terms and conditions of the GNU General Public 5 * License. See the file "COPYING" in the main directory of this archive 6 * for more details. 7 * 8 * Copyright (C) 1995 9 */ 10#ifndef _ASM_X86_FLOPPY_H 11#define _ASM_X86_FLOPPY_H 12 13#include <linux/vmalloc.h> 14 15/* 16 * The DMA channel used by the floppy controller cannot access data at 17 * addresses >= 16MB 18 * 19 * Went back to the 1MB limit, as some people had problems with the floppy 20 * driver otherwise. It doesn't matter much for performance anyway, as most 21 * floppy accesses go through the track buffer. 22 */ 23#define _CROSS_64KB(a,s,vdma) \ 24(!(vdma) && ((unsigned long)(a)/K_64 != ((unsigned long)(a) + (s) - 1) / K_64)) 25 26#define CROSS_64KB(a,s) _CROSS_64KB(a,s,use_virtual_dma & 1) 27 28 29#define SW fd_routine[use_virtual_dma&1] 30#define CSW fd_routine[can_use_virtual_dma & 1] 31 32 33#define fd_inb(port) inb_p(port) 34#define fd_outb(value,port) outb_p(value,port) 35 36#define fd_request_dma() CSW._request_dma(FLOPPY_DMA,"floppy") 37#define fd_free_dma() CSW._free_dma(FLOPPY_DMA) 38#define fd_enable_irq() enable_irq(FLOPPY_IRQ) 39#define fd_disable_irq() disable_irq(FLOPPY_IRQ) 40#define fd_free_irq() free_irq(FLOPPY_IRQ, NULL) 41#define fd_get_dma_residue() SW._get_dma_residue(FLOPPY_DMA) 42#define fd_dma_mem_alloc(size) SW._dma_mem_alloc(size) 43#define fd_dma_setup(addr, size, mode, io) SW._dma_setup(addr, size, mode, io) 44 45#define FLOPPY_CAN_FALLBACK_ON_NODMA 46 47static int virtual_dma_count; 48static int virtual_dma_residue; 49static char *virtual_dma_addr; 50static int virtual_dma_mode; 51static int doing_pdma; 52 53static irqreturn_t floppy_hardint(int irq, void *dev_id) 54{ 55 register unsigned char st; 56 57#undef TRACE_FLPY_INT 58 59#ifdef TRACE_FLPY_INT 60 static int calls=0; 61 static int bytes=0; 62 static int dma_wait=0; 63#endif 64 if (!doing_pdma) 65 return floppy_interrupt(irq, dev_id); 66 67#ifdef TRACE_FLPY_INT 68 if(!calls) 69 bytes = virtual_dma_count; 70#endif 71 72 { 73 register int lcount; 74 register char *lptr; 75 76 st = 1; 77 for(lcount=virtual_dma_count, lptr=virtual_dma_addr; 78 lcount; lcount--, lptr++) { 79 st=inb(virtual_dma_port+4) & 0xa0 ; 80 if(st != 0xa0) 81 break; 82 if(virtual_dma_mode) 83 outb_p(*lptr, virtual_dma_port+5); 84 else 85 *lptr = inb_p(virtual_dma_port+5); 86 } 87 virtual_dma_count = lcount; 88 virtual_dma_addr = lptr; 89 st = inb(virtual_dma_port+4); 90 } 91 92#ifdef TRACE_FLPY_INT 93 calls++; 94#endif 95 if(st == 0x20) 96 return IRQ_HANDLED; 97 if(!(st & 0x20)) { 98 virtual_dma_residue += virtual_dma_count; 99 virtual_dma_count=0; 100#ifdef TRACE_FLPY_INT 101 printk("count=%x, residue=%x calls=%d bytes=%d dma_wait=%d\n", 102 virtual_dma_count, virtual_dma_residue, calls, bytes, 103 dma_wait); 104 calls = 0; 105 dma_wait=0; 106#endif 107 doing_pdma = 0; 108 floppy_interrupt(irq, dev_id); 109 return IRQ_HANDLED; 110 } 111#ifdef TRACE_FLPY_INT 112 if(!virtual_dma_count) 113 dma_wait++; 114#endif 115 return IRQ_HANDLED; 116} 117 118static void fd_disable_dma(void) 119{ 120 if(! (can_use_virtual_dma & 1)) 121 disable_dma(FLOPPY_DMA); 122 doing_pdma = 0; 123 virtual_dma_residue += virtual_dma_count; 124 virtual_dma_count=0; 125} 126 127static int vdma_request_dma(unsigned int dmanr, const char * device_id) 128{ 129 return 0; 130} 131 132static void vdma_nop(unsigned int dummy) 133{ 134} 135 136 137static int vdma_get_dma_residue(unsigned int dummy) 138{ 139 return virtual_dma_count + virtual_dma_residue; 140} 141 142 143static int fd_request_irq(void) 144{ 145 if(can_use_virtual_dma) 146 return request_irq(FLOPPY_IRQ, floppy_hardint, 147 IRQF_DISABLED, "floppy", NULL); 148 else 149 return request_irq(FLOPPY_IRQ, floppy_interrupt, 150 IRQF_DISABLED, "floppy", NULL); 151} 152 153static unsigned long dma_mem_alloc(unsigned long size) 154{ 155 return __get_dma_pages(GFP_KERNEL|__GFP_NORETRY,get_order(size)); 156} 157 158 159static unsigned long vdma_mem_alloc(unsigned long size) 160{ 161 return (unsigned long) vmalloc(size); 162 163} 164 165#define nodma_mem_alloc(size) vdma_mem_alloc(size) 166 167static void _fd_dma_mem_free(unsigned long addr, unsigned long size) 168{ 169 if((unsigned long) addr >= (unsigned long) high_memory) 170 vfree((void *)addr); 171 else 172 free_pages(addr, get_order(size)); 173} 174 175#define fd_dma_mem_free(addr, size) _fd_dma_mem_free(addr, size) 176 177static void _fd_chose_dma_mode(char *addr, unsigned long size) 178{ 179 if(can_use_virtual_dma == 2) { 180 if((unsigned long) addr >= (unsigned long) high_memory || 181 isa_virt_to_bus(addr) >= 0x1000000 || 182 _CROSS_64KB(addr, size, 0)) 183 use_virtual_dma = 1; 184 else 185 use_virtual_dma = 0; 186 } else { 187 use_virtual_dma = can_use_virtual_dma & 1; 188 } 189} 190 191#define fd_chose_dma_mode(addr, size) _fd_chose_dma_mode(addr, size) 192 193 194static int vdma_dma_setup(char *addr, unsigned long size, int mode, int io) 195{ 196 doing_pdma = 1; 197 virtual_dma_port = io; 198 virtual_dma_mode = (mode == DMA_MODE_WRITE); 199 virtual_dma_addr = addr; 200 virtual_dma_count = size; 201 virtual_dma_residue = 0; 202 return 0; 203} 204 205static int hard_dma_setup(char *addr, unsigned long size, int mode, int io) 206{ 207#ifdef FLOPPY_SANITY_CHECK 208 if (CROSS_64KB(addr, size)) { 209 printk("DMA crossing 64-K boundary %p-%p\n", addr, addr+size); 210 return -1; 211 } 212#endif 213 /* actual, physical DMA */ 214 doing_pdma = 0; 215 clear_dma_ff(FLOPPY_DMA); 216 set_dma_mode(FLOPPY_DMA,mode); 217 set_dma_addr(FLOPPY_DMA,isa_virt_to_bus(addr)); 218 set_dma_count(FLOPPY_DMA,size); 219 enable_dma(FLOPPY_DMA); 220 return 0; 221} 222 223static struct fd_routine_l { 224 int (*_request_dma)(unsigned int dmanr, const char * device_id); 225 void (*_free_dma)(unsigned int dmanr); 226 int (*_get_dma_residue)(unsigned int dummy); 227 unsigned long (*_dma_mem_alloc) (unsigned long size); 228 int (*_dma_setup)(char *addr, unsigned long size, int mode, int io); 229} fd_routine[] = { 230 { 231 request_dma, 232 free_dma, 233 get_dma_residue, 234 dma_mem_alloc, 235 hard_dma_setup 236 }, 237 { 238 vdma_request_dma, 239 vdma_nop, 240 vdma_get_dma_residue, 241 vdma_mem_alloc, 242 vdma_dma_setup 243 } 244}; 245 246 247static int FDC1 = 0x3f0; 248static int FDC2 = -1; 249 250/* 251 * Floppy types are stored in the rtc's CMOS RAM and so rtc_lock 252 * is needed to prevent corrupted CMOS RAM in case "insmod floppy" 253 * coincides with another rtc CMOS user. Paul G. 254 */ 255#define FLOPPY0_TYPE ({ \ 256 unsigned long flags; \ 257 unsigned char val; \ 258 spin_lock_irqsave(&rtc_lock, flags); \ 259 val = (CMOS_READ(0x10) >> 4) & 15; \ 260 spin_unlock_irqrestore(&rtc_lock, flags); \ 261 val; \ 262}) 263 264#define FLOPPY1_TYPE ({ \ 265 unsigned long flags; \ 266 unsigned char val; \ 267 spin_lock_irqsave(&rtc_lock, flags); \ 268 val = CMOS_READ(0x10) & 15; \ 269 spin_unlock_irqrestore(&rtc_lock, flags); \ 270 val; \ 271}) 272 273#define N_FDC 2 274#define N_DRIVE 8 275 276#define EXTRA_FLOPPY_PARAMS 277 278#endif /* _ASM_X86_FLOPPY_H */