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