1deae26bfSKyle McMartin /* Architecture specific parts of the Floppy driver 2deae26bfSKyle McMartin * 3deae26bfSKyle McMartin * Linux/PA-RISC Project (http://www.parisc-linux.org/) 4deae26bfSKyle McMartin * Copyright (C) 2000 Matthew Wilcox (willy a debian . org) 5deae26bfSKyle McMartin * Copyright (C) 2000 Dave Kennedy 6deae26bfSKyle McMartin * 7deae26bfSKyle McMartin * This program is free software; you can redistribute it and/or modify 8deae26bfSKyle McMartin * it under the terms of the GNU General Public License as published by 9deae26bfSKyle McMartin * the Free Software Foundation; either version 2 of the License, or 10deae26bfSKyle McMartin * (at your option) any later version. 11deae26bfSKyle McMartin * 12deae26bfSKyle McMartin * This program is distributed in the hope that it will be useful, 13deae26bfSKyle McMartin * but WITHOUT ANY WARRANTY; without even the implied warranty of 14deae26bfSKyle McMartin * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15deae26bfSKyle McMartin * GNU General Public License for more details. 16deae26bfSKyle McMartin * 17deae26bfSKyle McMartin * You should have received a copy of the GNU General Public License 18deae26bfSKyle McMartin * along with this program; if not, write to the Free Software 19deae26bfSKyle McMartin * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20deae26bfSKyle McMartin */ 21deae26bfSKyle McMartin #ifndef __ASM_PARISC_FLOPPY_H 22deae26bfSKyle McMartin #define __ASM_PARISC_FLOPPY_H 23deae26bfSKyle McMartin 24deae26bfSKyle McMartin #include <linux/vmalloc.h> 25deae26bfSKyle McMartin 26deae26bfSKyle McMartin 27deae26bfSKyle McMartin /* 28deae26bfSKyle McMartin * The DMA channel used by the floppy controller cannot access data at 29deae26bfSKyle McMartin * addresses >= 16MB 30deae26bfSKyle McMartin * 31deae26bfSKyle McMartin * Went back to the 1MB limit, as some people had problems with the floppy 32deae26bfSKyle McMartin * driver otherwise. It doesn't matter much for performance anyway, as most 33deae26bfSKyle McMartin * floppy accesses go through the track buffer. 34deae26bfSKyle McMartin */ 35deae26bfSKyle McMartin #define _CROSS_64KB(a,s,vdma) \ 36*9a334d39SHelge Deller (!(vdma) && ((unsigned long)(a)/K_64 != ((unsigned long)(a) + (s) - 1) / K_64)) 37deae26bfSKyle McMartin 38deae26bfSKyle McMartin #define CROSS_64KB(a,s) _CROSS_64KB(a,s,use_virtual_dma & 1) 39deae26bfSKyle McMartin 40deae26bfSKyle McMartin 41deae26bfSKyle McMartin #define SW fd_routine[use_virtual_dma&1] 42deae26bfSKyle McMartin #define CSW fd_routine[can_use_virtual_dma & 1] 43deae26bfSKyle McMartin 44deae26bfSKyle McMartin 45deae26bfSKyle McMartin #define fd_inb(port) readb(port) 46deae26bfSKyle McMartin #define fd_outb(value, port) writeb(value, port) 47deae26bfSKyle McMartin 48deae26bfSKyle McMartin #define fd_request_dma() CSW._request_dma(FLOPPY_DMA,"floppy") 49deae26bfSKyle McMartin #define fd_free_dma() CSW._free_dma(FLOPPY_DMA) 50deae26bfSKyle McMartin #define fd_enable_irq() enable_irq(FLOPPY_IRQ) 51deae26bfSKyle McMartin #define fd_disable_irq() disable_irq(FLOPPY_IRQ) 52deae26bfSKyle McMartin #define fd_free_irq() free_irq(FLOPPY_IRQ, NULL) 53deae26bfSKyle McMartin #define fd_get_dma_residue() SW._get_dma_residue(FLOPPY_DMA) 54deae26bfSKyle McMartin #define fd_dma_mem_alloc(size) SW._dma_mem_alloc(size) 55deae26bfSKyle McMartin #define fd_dma_setup(addr, size, mode, io) SW._dma_setup(addr, size, mode, io) 56deae26bfSKyle McMartin 57deae26bfSKyle McMartin #define FLOPPY_CAN_FALLBACK_ON_NODMA 58deae26bfSKyle McMartin 59deae26bfSKyle McMartin static int virtual_dma_count=0; 60deae26bfSKyle McMartin static int virtual_dma_residue=0; 61deae26bfSKyle McMartin static char *virtual_dma_addr=0; 62deae26bfSKyle McMartin static int virtual_dma_mode=0; 63deae26bfSKyle McMartin static int doing_pdma=0; 64deae26bfSKyle McMartin 65deae26bfSKyle McMartin static void floppy_hardint(int irq, void *dev_id, struct pt_regs * regs) 66deae26bfSKyle McMartin { 67deae26bfSKyle McMartin register unsigned char st; 68deae26bfSKyle McMartin 69deae26bfSKyle McMartin #undef TRACE_FLPY_INT 70deae26bfSKyle McMartin 71deae26bfSKyle McMartin #ifdef TRACE_FLPY_INT 72deae26bfSKyle McMartin static int calls=0; 73deae26bfSKyle McMartin static int bytes=0; 74deae26bfSKyle McMartin static int dma_wait=0; 75deae26bfSKyle McMartin #endif 76deae26bfSKyle McMartin if (!doing_pdma) { 77deae26bfSKyle McMartin floppy_interrupt(irq, dev_id, regs); 78deae26bfSKyle McMartin return; 79deae26bfSKyle McMartin } 80deae26bfSKyle McMartin 81deae26bfSKyle McMartin #ifdef TRACE_FLPY_INT 82deae26bfSKyle McMartin if(!calls) 83deae26bfSKyle McMartin bytes = virtual_dma_count; 84deae26bfSKyle McMartin #endif 85deae26bfSKyle McMartin 86deae26bfSKyle McMartin { 87deae26bfSKyle McMartin register int lcount; 88deae26bfSKyle McMartin register char *lptr = virtual_dma_addr; 89deae26bfSKyle McMartin 90deae26bfSKyle McMartin for (lcount = virtual_dma_count; lcount; lcount--) { 91deae26bfSKyle McMartin st = fd_inb(virtual_dma_port+4) & 0xa0 ; 92deae26bfSKyle McMartin if (st != 0xa0) 93deae26bfSKyle McMartin break; 94deae26bfSKyle McMartin if (virtual_dma_mode) { 95deae26bfSKyle McMartin fd_outb(*lptr, virtual_dma_port+5); 96deae26bfSKyle McMartin } else { 97deae26bfSKyle McMartin *lptr = fd_inb(virtual_dma_port+5); 98deae26bfSKyle McMartin } 99deae26bfSKyle McMartin lptr++; 100deae26bfSKyle McMartin } 101deae26bfSKyle McMartin virtual_dma_count = lcount; 102deae26bfSKyle McMartin virtual_dma_addr = lptr; 103deae26bfSKyle McMartin st = fd_inb(virtual_dma_port+4); 104deae26bfSKyle McMartin } 105deae26bfSKyle McMartin 106deae26bfSKyle McMartin #ifdef TRACE_FLPY_INT 107deae26bfSKyle McMartin calls++; 108deae26bfSKyle McMartin #endif 109deae26bfSKyle McMartin if (st == 0x20) 110deae26bfSKyle McMartin return; 111deae26bfSKyle McMartin if (!(st & 0x20)) { 112deae26bfSKyle McMartin virtual_dma_residue += virtual_dma_count; 113deae26bfSKyle McMartin virtual_dma_count = 0; 114deae26bfSKyle McMartin #ifdef TRACE_FLPY_INT 115deae26bfSKyle McMartin printk("count=%x, residue=%x calls=%d bytes=%d dma_wait=%d\n", 116deae26bfSKyle McMartin virtual_dma_count, virtual_dma_residue, calls, bytes, 117deae26bfSKyle McMartin dma_wait); 118deae26bfSKyle McMartin calls = 0; 119deae26bfSKyle McMartin dma_wait=0; 120deae26bfSKyle McMartin #endif 121deae26bfSKyle McMartin doing_pdma = 0; 122deae26bfSKyle McMartin floppy_interrupt(irq, dev_id, regs); 123deae26bfSKyle McMartin return; 124deae26bfSKyle McMartin } 125deae26bfSKyle McMartin #ifdef TRACE_FLPY_INT 126deae26bfSKyle McMartin if (!virtual_dma_count) 127deae26bfSKyle McMartin dma_wait++; 128deae26bfSKyle McMartin #endif 129deae26bfSKyle McMartin } 130deae26bfSKyle McMartin 131deae26bfSKyle McMartin static void fd_disable_dma(void) 132deae26bfSKyle McMartin { 133deae26bfSKyle McMartin if(! (can_use_virtual_dma & 1)) 134deae26bfSKyle McMartin disable_dma(FLOPPY_DMA); 135deae26bfSKyle McMartin doing_pdma = 0; 136deae26bfSKyle McMartin virtual_dma_residue += virtual_dma_count; 137deae26bfSKyle McMartin virtual_dma_count=0; 138deae26bfSKyle McMartin } 139deae26bfSKyle McMartin 140deae26bfSKyle McMartin static int vdma_request_dma(unsigned int dmanr, const char * device_id) 141deae26bfSKyle McMartin { 142deae26bfSKyle McMartin return 0; 143deae26bfSKyle McMartin } 144deae26bfSKyle McMartin 145deae26bfSKyle McMartin static void vdma_nop(unsigned int dummy) 146deae26bfSKyle McMartin { 147deae26bfSKyle McMartin } 148deae26bfSKyle McMartin 149deae26bfSKyle McMartin 150deae26bfSKyle McMartin static int vdma_get_dma_residue(unsigned int dummy) 151deae26bfSKyle McMartin { 152deae26bfSKyle McMartin return virtual_dma_count + virtual_dma_residue; 153deae26bfSKyle McMartin } 154deae26bfSKyle McMartin 155deae26bfSKyle McMartin 156deae26bfSKyle McMartin static int fd_request_irq(void) 157deae26bfSKyle McMartin { 158deae26bfSKyle McMartin if(can_use_virtual_dma) 159deae26bfSKyle McMartin return request_irq(FLOPPY_IRQ, floppy_hardint, 160b54cb233SPeter Zijlstra 0, "floppy", NULL); 161deae26bfSKyle McMartin else 162deae26bfSKyle McMartin return request_irq(FLOPPY_IRQ, floppy_interrupt, 163b54cb233SPeter Zijlstra 0, "floppy", NULL); 164deae26bfSKyle McMartin } 165deae26bfSKyle McMartin 166deae26bfSKyle McMartin static unsigned long dma_mem_alloc(unsigned long size) 167deae26bfSKyle McMartin { 168deae26bfSKyle McMartin return __get_dma_pages(GFP_KERNEL, get_order(size)); 169deae26bfSKyle McMartin } 170deae26bfSKyle McMartin 171deae26bfSKyle McMartin 172deae26bfSKyle McMartin static unsigned long vdma_mem_alloc(unsigned long size) 173deae26bfSKyle McMartin { 174deae26bfSKyle McMartin return (unsigned long) vmalloc(size); 175deae26bfSKyle McMartin 176deae26bfSKyle McMartin } 177deae26bfSKyle McMartin 178deae26bfSKyle McMartin #define nodma_mem_alloc(size) vdma_mem_alloc(size) 179deae26bfSKyle McMartin 180deae26bfSKyle McMartin static void _fd_dma_mem_free(unsigned long addr, unsigned long size) 181deae26bfSKyle McMartin { 182deae26bfSKyle McMartin if((unsigned int) addr >= (unsigned int) high_memory) 183deae26bfSKyle McMartin return vfree((void *)addr); 184deae26bfSKyle McMartin else 185deae26bfSKyle McMartin free_pages(addr, get_order(size)); 186deae26bfSKyle McMartin } 187deae26bfSKyle McMartin 188deae26bfSKyle McMartin #define fd_dma_mem_free(addr, size) _fd_dma_mem_free(addr, size) 189deae26bfSKyle McMartin 190deae26bfSKyle McMartin static void _fd_chose_dma_mode(char *addr, unsigned long size) 191deae26bfSKyle McMartin { 192deae26bfSKyle McMartin if(can_use_virtual_dma == 2) { 193deae26bfSKyle McMartin if((unsigned int) addr >= (unsigned int) high_memory || 194deae26bfSKyle McMartin virt_to_bus(addr) >= 0x1000000 || 195deae26bfSKyle McMartin _CROSS_64KB(addr, size, 0)) 196deae26bfSKyle McMartin use_virtual_dma = 1; 197deae26bfSKyle McMartin else 198deae26bfSKyle McMartin use_virtual_dma = 0; 199deae26bfSKyle McMartin } else { 200deae26bfSKyle McMartin use_virtual_dma = can_use_virtual_dma & 1; 201deae26bfSKyle McMartin } 202deae26bfSKyle McMartin } 203deae26bfSKyle McMartin 204deae26bfSKyle McMartin #define fd_chose_dma_mode(addr, size) _fd_chose_dma_mode(addr, size) 205deae26bfSKyle McMartin 206deae26bfSKyle McMartin 207deae26bfSKyle McMartin static int vdma_dma_setup(char *addr, unsigned long size, int mode, int io) 208deae26bfSKyle McMartin { 209deae26bfSKyle McMartin doing_pdma = 1; 210deae26bfSKyle McMartin virtual_dma_port = io; 211deae26bfSKyle McMartin virtual_dma_mode = (mode == DMA_MODE_WRITE); 212deae26bfSKyle McMartin virtual_dma_addr = addr; 213deae26bfSKyle McMartin virtual_dma_count = size; 214deae26bfSKyle McMartin virtual_dma_residue = 0; 215deae26bfSKyle McMartin return 0; 216deae26bfSKyle McMartin } 217deae26bfSKyle McMartin 218deae26bfSKyle McMartin static int hard_dma_setup(char *addr, unsigned long size, int mode, int io) 219deae26bfSKyle McMartin { 220deae26bfSKyle McMartin #ifdef FLOPPY_SANITY_CHECK 221deae26bfSKyle McMartin if (CROSS_64KB(addr, size)) { 222deae26bfSKyle McMartin printk("DMA crossing 64-K boundary %p-%p\n", addr, addr+size); 223deae26bfSKyle McMartin return -1; 224deae26bfSKyle McMartin } 225deae26bfSKyle McMartin #endif 226deae26bfSKyle McMartin /* actual, physical DMA */ 227deae26bfSKyle McMartin doing_pdma = 0; 228deae26bfSKyle McMartin clear_dma_ff(FLOPPY_DMA); 229deae26bfSKyle McMartin set_dma_mode(FLOPPY_DMA,mode); 230deae26bfSKyle McMartin set_dma_addr(FLOPPY_DMA,virt_to_bus(addr)); 231deae26bfSKyle McMartin set_dma_count(FLOPPY_DMA,size); 232deae26bfSKyle McMartin enable_dma(FLOPPY_DMA); 233deae26bfSKyle McMartin return 0; 234deae26bfSKyle McMartin } 235deae26bfSKyle McMartin 236deae26bfSKyle McMartin static struct fd_routine_l { 237deae26bfSKyle McMartin int (*_request_dma)(unsigned int dmanr, const char * device_id); 238deae26bfSKyle McMartin void (*_free_dma)(unsigned int dmanr); 239deae26bfSKyle McMartin int (*_get_dma_residue)(unsigned int dummy); 240deae26bfSKyle McMartin unsigned long (*_dma_mem_alloc) (unsigned long size); 241deae26bfSKyle McMartin int (*_dma_setup)(char *addr, unsigned long size, int mode, int io); 242deae26bfSKyle McMartin } fd_routine[] = { 243deae26bfSKyle McMartin { 244deae26bfSKyle McMartin request_dma, 245deae26bfSKyle McMartin free_dma, 246deae26bfSKyle McMartin get_dma_residue, 247deae26bfSKyle McMartin dma_mem_alloc, 248deae26bfSKyle McMartin hard_dma_setup 249deae26bfSKyle McMartin }, 250deae26bfSKyle McMartin { 251deae26bfSKyle McMartin vdma_request_dma, 252deae26bfSKyle McMartin vdma_nop, 253deae26bfSKyle McMartin vdma_get_dma_residue, 254deae26bfSKyle McMartin vdma_mem_alloc, 255deae26bfSKyle McMartin vdma_dma_setup 256deae26bfSKyle McMartin } 257deae26bfSKyle McMartin }; 258deae26bfSKyle McMartin 259deae26bfSKyle McMartin 260deae26bfSKyle McMartin static int FDC1 = 0x3f0; /* Lies. Floppy controller is memory mapped, not io mapped */ 261deae26bfSKyle McMartin static int FDC2 = -1; 262deae26bfSKyle McMartin 263deae26bfSKyle McMartin #define FLOPPY0_TYPE 0 264deae26bfSKyle McMartin #define FLOPPY1_TYPE 0 265deae26bfSKyle McMartin 266deae26bfSKyle McMartin #define N_FDC 1 267deae26bfSKyle McMartin #define N_DRIVE 8 268deae26bfSKyle McMartin 269deae26bfSKyle McMartin #define EXTRA_FLOPPY_PARAMS 270deae26bfSKyle McMartin 271deae26bfSKyle McMartin #endif /* __ASM_PARISC_FLOPPY_H */ 272