18e75f744SArnaud Giersch /* Low-level parallel port routines for built-in port on SGI IP32 28e75f744SArnaud Giersch * 38e75f744SArnaud Giersch * Author: Arnaud Giersch <arnaud.giersch@free.fr> 48e75f744SArnaud Giersch * 58e75f744SArnaud Giersch * Based on parport_pc.c by 68e75f744SArnaud Giersch * Phil Blundell, Tim Waugh, Jose Renau, David Campbell, 78e75f744SArnaud Giersch * Andrea Arcangeli, et al. 88e75f744SArnaud Giersch * 98e75f744SArnaud Giersch * Thanks to Ilya A. Volynets-Evenbakh for his help. 108e75f744SArnaud Giersch * 118e75f744SArnaud Giersch * Copyright (C) 2005, 2006 Arnaud Giersch. 128e75f744SArnaud Giersch * 138e75f744SArnaud Giersch * This program is free software; you can redistribute it and/or modify it 148e75f744SArnaud Giersch * under the terms of the GNU General Public License as published by the Free 158e75f744SArnaud Giersch * Software Foundation; either version 2 of the License, or (at your option) 168e75f744SArnaud Giersch * any later version. 178e75f744SArnaud Giersch * 188e75f744SArnaud Giersch * This program is distributed in the hope that it will be useful, but WITHOUT 198e75f744SArnaud Giersch * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 208e75f744SArnaud Giersch * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 218e75f744SArnaud Giersch * more details. 228e75f744SArnaud Giersch * 238e75f744SArnaud Giersch * You should have received a copy of the GNU General Public License along 248e75f744SArnaud Giersch * with this program; if not, write to the Free Software Foundation, Inc., 59 258e75f744SArnaud Giersch * Temple Place - Suite 330, Boston, MA 02111-1307, USA. 268e75f744SArnaud Giersch */ 278e75f744SArnaud Giersch 288e75f744SArnaud Giersch /* Current status: 298e75f744SArnaud Giersch * 308e75f744SArnaud Giersch * Basic SPP and PS2 modes are supported. 318e75f744SArnaud Giersch * Support for parallel port IRQ is present. 328e75f744SArnaud Giersch * Hardware SPP (a.k.a. compatibility), EPP, and ECP modes are 338e75f744SArnaud Giersch * supported. 348e75f744SArnaud Giersch * SPP/ECP FIFO can be driven in PIO or DMA mode. PIO mode can work with 358e75f744SArnaud Giersch * or without interrupt support. 368e75f744SArnaud Giersch * 378e75f744SArnaud Giersch * Hardware ECP mode is not fully implemented (ecp_read_data and 388e75f744SArnaud Giersch * ecp_write_addr are actually missing). 398e75f744SArnaud Giersch * 408e75f744SArnaud Giersch * To do: 418e75f744SArnaud Giersch * 428e75f744SArnaud Giersch * Fully implement ECP mode. 438e75f744SArnaud Giersch * EPP and ECP mode need to be tested. I currently do not own any 448e75f744SArnaud Giersch * peripheral supporting these extended mode, and cannot test them. 458e75f744SArnaud Giersch * If DMA mode works well, decide if support for PIO FIFO modes should be 468e75f744SArnaud Giersch * dropped. 478e75f744SArnaud Giersch * Use the io{read,write} family functions when they become available in 488e75f744SArnaud Giersch * the linux-mips.org tree. Note: the MIPS specific functions readsb() 498e75f744SArnaud Giersch * and writesb() are to be translated by ioread8_rep() and iowrite8_rep() 508e75f744SArnaud Giersch * respectively. 518e75f744SArnaud Giersch */ 528e75f744SArnaud Giersch 538e75f744SArnaud Giersch /* The built-in parallel port on the SGI 02 workstation (a.k.a. IP32) is an 548e75f744SArnaud Giersch * IEEE 1284 parallel port driven by a Texas Instrument TL16PIR552PH chip[1]. 558e75f744SArnaud Giersch * This chip supports SPP, bidirectional, EPP and ECP modes. It has a 16 byte 568e75f744SArnaud Giersch * FIFO buffer and supports DMA transfers. 578e75f744SArnaud Giersch * 588e75f744SArnaud Giersch * [1] http://focus.ti.com/docs/prod/folders/print/tl16pir552.html 598e75f744SArnaud Giersch * 608e75f744SArnaud Giersch * Theoretically, we could simply use the parport_pc module. It is however 618e75f744SArnaud Giersch * not so simple. The parport_pc code assumes that the parallel port 628e75f744SArnaud Giersch * registers are port-mapped. On the O2, they are memory-mapped. 638e75f744SArnaud Giersch * Furthermore, each register is replicated on 256 consecutive addresses (as 648e75f744SArnaud Giersch * it is for the built-in serial ports on the same chip). 658e75f744SArnaud Giersch */ 668e75f744SArnaud Giersch 678e75f744SArnaud Giersch /*--- Some configuration defines ---------------------------------------*/ 688e75f744SArnaud Giersch 698e75f744SArnaud Giersch /* DEBUG_PARPORT_IP32 708e75f744SArnaud Giersch * 0 disable debug 718e75f744SArnaud Giersch * 1 standard level: pr_debug1 is enabled 728e75f744SArnaud Giersch * 2 parport_ip32_dump_state is enabled 738e75f744SArnaud Giersch * >=3 verbose level: pr_debug is enabled 748e75f744SArnaud Giersch */ 758e75f744SArnaud Giersch #if !defined(DEBUG_PARPORT_IP32) 768e75f744SArnaud Giersch # define DEBUG_PARPORT_IP32 0 /* 0 (disabled) for production */ 778e75f744SArnaud Giersch #endif 788e75f744SArnaud Giersch 798e75f744SArnaud Giersch /*----------------------------------------------------------------------*/ 808e75f744SArnaud Giersch 818e75f744SArnaud Giersch /* Setup DEBUG macros. This is done before any includes, just in case we 828e75f744SArnaud Giersch * activate pr_debug() with DEBUG_PARPORT_IP32 >= 3. 838e75f744SArnaud Giersch */ 848e75f744SArnaud Giersch #if DEBUG_PARPORT_IP32 == 1 858e75f744SArnaud Giersch # warning DEBUG_PARPORT_IP32 == 1 868e75f744SArnaud Giersch #elif DEBUG_PARPORT_IP32 == 2 878e75f744SArnaud Giersch # warning DEBUG_PARPORT_IP32 == 2 888e75f744SArnaud Giersch #elif DEBUG_PARPORT_IP32 >= 3 898e75f744SArnaud Giersch # warning DEBUG_PARPORT_IP32 >= 3 908e75f744SArnaud Giersch # if !defined(DEBUG) 918e75f744SArnaud Giersch # define DEBUG /* enable pr_debug() in kernel.h */ 928e75f744SArnaud Giersch # endif 938e75f744SArnaud Giersch #endif 948e75f744SArnaud Giersch 958e75f744SArnaud Giersch #include <linux/completion.h> 968e75f744SArnaud Giersch #include <linux/delay.h> 978e75f744SArnaud Giersch #include <linux/dma-mapping.h> 988e75f744SArnaud Giersch #include <linux/err.h> 998e75f744SArnaud Giersch #include <linux/init.h> 1008e75f744SArnaud Giersch #include <linux/interrupt.h> 1018e75f744SArnaud Giersch #include <linux/jiffies.h> 1028e75f744SArnaud Giersch #include <linux/kernel.h> 1038e75f744SArnaud Giersch #include <linux/module.h> 1048e75f744SArnaud Giersch #include <linux/parport.h> 1058e75f744SArnaud Giersch #include <linux/sched.h> 1068e75f744SArnaud Giersch #include <linux/spinlock.h> 1078e75f744SArnaud Giersch #include <linux/stddef.h> 1088e75f744SArnaud Giersch #include <linux/types.h> 1098e75f744SArnaud Giersch #include <asm/io.h> 1108e75f744SArnaud Giersch #include <asm/ip32/ip32_ints.h> 1118e75f744SArnaud Giersch #include <asm/ip32/mace.h> 1128e75f744SArnaud Giersch 1138e75f744SArnaud Giersch /*--- Global variables -------------------------------------------------*/ 1148e75f744SArnaud Giersch 1158e75f744SArnaud Giersch /* Verbose probing on by default for debugging. */ 1168e75f744SArnaud Giersch #if DEBUG_PARPORT_IP32 >= 1 1178e75f744SArnaud Giersch # define DEFAULT_VERBOSE_PROBING 1 1188e75f744SArnaud Giersch #else 1198e75f744SArnaud Giersch # define DEFAULT_VERBOSE_PROBING 0 1208e75f744SArnaud Giersch #endif 1218e75f744SArnaud Giersch 1228e75f744SArnaud Giersch /* Default prefix for printk */ 1238e75f744SArnaud Giersch #define PPIP32 "parport_ip32: " 1248e75f744SArnaud Giersch 1258e75f744SArnaud Giersch /* 1268e75f744SArnaud Giersch * These are the module parameters: 1278e75f744SArnaud Giersch * @features: bit mask of features to enable/disable 1288e75f744SArnaud Giersch * (all enabled by default) 1298e75f744SArnaud Giersch * @verbose_probing: log chit-chat during initialization 1308e75f744SArnaud Giersch */ 1318e75f744SArnaud Giersch #define PARPORT_IP32_ENABLE_IRQ (1U << 0) 1328e75f744SArnaud Giersch #define PARPORT_IP32_ENABLE_DMA (1U << 1) 1338e75f744SArnaud Giersch #define PARPORT_IP32_ENABLE_SPP (1U << 2) 1348e75f744SArnaud Giersch #define PARPORT_IP32_ENABLE_EPP (1U << 3) 1358e75f744SArnaud Giersch #define PARPORT_IP32_ENABLE_ECP (1U << 4) 1368e75f744SArnaud Giersch static unsigned int features = ~0U; 1378e75f744SArnaud Giersch static int verbose_probing = DEFAULT_VERBOSE_PROBING; 1388e75f744SArnaud Giersch 1398e75f744SArnaud Giersch /* We do not support more than one port. */ 1408e75f744SArnaud Giersch static struct parport *this_port = NULL; 1418e75f744SArnaud Giersch 1428e75f744SArnaud Giersch /* Timing constants for FIFO modes. */ 1438e75f744SArnaud Giersch #define FIFO_NFAULT_TIMEOUT 100 /* milliseconds */ 1448e75f744SArnaud Giersch #define FIFO_POLLING_INTERVAL 50 /* microseconds */ 1458e75f744SArnaud Giersch 1468e75f744SArnaud Giersch /*--- I/O register definitions -----------------------------------------*/ 1478e75f744SArnaud Giersch 1488e75f744SArnaud Giersch /** 1498e75f744SArnaud Giersch * struct parport_ip32_regs - virtual addresses of parallel port registers 1508e75f744SArnaud Giersch * @data: Data Register 1518e75f744SArnaud Giersch * @dsr: Device Status Register 1528e75f744SArnaud Giersch * @dcr: Device Control Register 1538e75f744SArnaud Giersch * @eppAddr: EPP Address Register 1548e75f744SArnaud Giersch * @eppData0: EPP Data Register 0 1558e75f744SArnaud Giersch * @eppData1: EPP Data Register 1 1568e75f744SArnaud Giersch * @eppData2: EPP Data Register 2 1578e75f744SArnaud Giersch * @eppData3: EPP Data Register 3 1588e75f744SArnaud Giersch * @ecpAFifo: ECP Address FIFO 1598e75f744SArnaud Giersch * @fifo: General FIFO register. The same address is used for: 1608e75f744SArnaud Giersch * - cFifo, the Parallel Port DATA FIFO 1618e75f744SArnaud Giersch * - ecpDFifo, the ECP Data FIFO 1628e75f744SArnaud Giersch * - tFifo, the ECP Test FIFO 1638e75f744SArnaud Giersch * @cnfgA: Configuration Register A 1648e75f744SArnaud Giersch * @cnfgB: Configuration Register B 1658e75f744SArnaud Giersch * @ecr: Extended Control Register 1668e75f744SArnaud Giersch */ 1678e75f744SArnaud Giersch struct parport_ip32_regs { 1688e75f744SArnaud Giersch void __iomem *data; 1698e75f744SArnaud Giersch void __iomem *dsr; 1708e75f744SArnaud Giersch void __iomem *dcr; 1718e75f744SArnaud Giersch void __iomem *eppAddr; 1728e75f744SArnaud Giersch void __iomem *eppData0; 1738e75f744SArnaud Giersch void __iomem *eppData1; 1748e75f744SArnaud Giersch void __iomem *eppData2; 1758e75f744SArnaud Giersch void __iomem *eppData3; 1768e75f744SArnaud Giersch void __iomem *ecpAFifo; 1778e75f744SArnaud Giersch void __iomem *fifo; 1788e75f744SArnaud Giersch void __iomem *cnfgA; 1798e75f744SArnaud Giersch void __iomem *cnfgB; 1808e75f744SArnaud Giersch void __iomem *ecr; 1818e75f744SArnaud Giersch }; 1828e75f744SArnaud Giersch 1838e75f744SArnaud Giersch /* Device Status Register */ 1848e75f744SArnaud Giersch #define DSR_nBUSY (1U << 7) /* PARPORT_STATUS_BUSY */ 1858e75f744SArnaud Giersch #define DSR_nACK (1U << 6) /* PARPORT_STATUS_ACK */ 1868e75f744SArnaud Giersch #define DSR_PERROR (1U << 5) /* PARPORT_STATUS_PAPEROUT */ 1878e75f744SArnaud Giersch #define DSR_SELECT (1U << 4) /* PARPORT_STATUS_SELECT */ 1888e75f744SArnaud Giersch #define DSR_nFAULT (1U << 3) /* PARPORT_STATUS_ERROR */ 1898e75f744SArnaud Giersch #define DSR_nPRINT (1U << 2) /* specific to TL16PIR552 */ 1908e75f744SArnaud Giersch /* #define DSR_reserved (1U << 1) */ 1918e75f744SArnaud Giersch #define DSR_TIMEOUT (1U << 0) /* EPP timeout */ 1928e75f744SArnaud Giersch 1938e75f744SArnaud Giersch /* Device Control Register */ 1948e75f744SArnaud Giersch /* #define DCR_reserved (1U << 7) | (1U << 6) */ 1958e75f744SArnaud Giersch #define DCR_DIR (1U << 5) /* direction */ 1968e75f744SArnaud Giersch #define DCR_IRQ (1U << 4) /* interrupt on nAck */ 1978e75f744SArnaud Giersch #define DCR_SELECT (1U << 3) /* PARPORT_CONTROL_SELECT */ 1988e75f744SArnaud Giersch #define DCR_nINIT (1U << 2) /* PARPORT_CONTROL_INIT */ 1998e75f744SArnaud Giersch #define DCR_AUTOFD (1U << 1) /* PARPORT_CONTROL_AUTOFD */ 2008e75f744SArnaud Giersch #define DCR_STROBE (1U << 0) /* PARPORT_CONTROL_STROBE */ 2018e75f744SArnaud Giersch 2028e75f744SArnaud Giersch /* ECP Configuration Register A */ 2038e75f744SArnaud Giersch #define CNFGA_IRQ (1U << 7) 2048e75f744SArnaud Giersch #define CNFGA_ID_MASK ((1U << 6) | (1U << 5) | (1U << 4)) 2058e75f744SArnaud Giersch #define CNFGA_ID_SHIFT 4 2068e75f744SArnaud Giersch #define CNFGA_ID_16 (00U << CNFGA_ID_SHIFT) 2078e75f744SArnaud Giersch #define CNFGA_ID_8 (01U << CNFGA_ID_SHIFT) 2088e75f744SArnaud Giersch #define CNFGA_ID_32 (02U << CNFGA_ID_SHIFT) 2098e75f744SArnaud Giersch /* #define CNFGA_reserved (1U << 3) */ 2108e75f744SArnaud Giersch #define CNFGA_nBYTEINTRANS (1U << 2) 2118e75f744SArnaud Giersch #define CNFGA_PWORDLEFT ((1U << 1) | (1U << 0)) 2128e75f744SArnaud Giersch 2138e75f744SArnaud Giersch /* ECP Configuration Register B */ 2148e75f744SArnaud Giersch #define CNFGB_COMPRESS (1U << 7) 2158e75f744SArnaud Giersch #define CNFGB_INTRVAL (1U << 6) 2168e75f744SArnaud Giersch #define CNFGB_IRQ_MASK ((1U << 5) | (1U << 4) | (1U << 3)) 2178e75f744SArnaud Giersch #define CNFGB_IRQ_SHIFT 3 2188e75f744SArnaud Giersch #define CNFGB_DMA_MASK ((1U << 2) | (1U << 1) | (1U << 0)) 2198e75f744SArnaud Giersch #define CNFGB_DMA_SHIFT 0 2208e75f744SArnaud Giersch 2218e75f744SArnaud Giersch /* Extended Control Register */ 2228e75f744SArnaud Giersch #define ECR_MODE_MASK ((1U << 7) | (1U << 6) | (1U << 5)) 2238e75f744SArnaud Giersch #define ECR_MODE_SHIFT 5 2248e75f744SArnaud Giersch #define ECR_MODE_SPP (00U << ECR_MODE_SHIFT) 2258e75f744SArnaud Giersch #define ECR_MODE_PS2 (01U << ECR_MODE_SHIFT) 2268e75f744SArnaud Giersch #define ECR_MODE_PPF (02U << ECR_MODE_SHIFT) 2278e75f744SArnaud Giersch #define ECR_MODE_ECP (03U << ECR_MODE_SHIFT) 2288e75f744SArnaud Giersch #define ECR_MODE_EPP (04U << ECR_MODE_SHIFT) 2298e75f744SArnaud Giersch /* #define ECR_MODE_reserved (05U << ECR_MODE_SHIFT) */ 2308e75f744SArnaud Giersch #define ECR_MODE_TST (06U << ECR_MODE_SHIFT) 2318e75f744SArnaud Giersch #define ECR_MODE_CFG (07U << ECR_MODE_SHIFT) 2328e75f744SArnaud Giersch #define ECR_nERRINTR (1U << 4) 2338e75f744SArnaud Giersch #define ECR_DMAEN (1U << 3) 2348e75f744SArnaud Giersch #define ECR_SERVINTR (1U << 2) 2358e75f744SArnaud Giersch #define ECR_F_FULL (1U << 1) 2368e75f744SArnaud Giersch #define ECR_F_EMPTY (1U << 0) 2378e75f744SArnaud Giersch 2388e75f744SArnaud Giersch /*--- Private data -----------------------------------------------------*/ 2398e75f744SArnaud Giersch 2408e75f744SArnaud Giersch /** 2418e75f744SArnaud Giersch * enum parport_ip32_irq_mode - operation mode of interrupt handler 2428e75f744SArnaud Giersch * @PARPORT_IP32_IRQ_FWD: forward interrupt to the upper parport layer 2438e75f744SArnaud Giersch * @PARPORT_IP32_IRQ_HERE: interrupt is handled locally 2448e75f744SArnaud Giersch */ 2458e75f744SArnaud Giersch enum parport_ip32_irq_mode { PARPORT_IP32_IRQ_FWD, PARPORT_IP32_IRQ_HERE }; 2468e75f744SArnaud Giersch 2478e75f744SArnaud Giersch /** 2488e75f744SArnaud Giersch * struct parport_ip32_private - private stuff for &struct parport 2498e75f744SArnaud Giersch * @regs: register addresses 2508e75f744SArnaud Giersch * @dcr_cache: cached contents of DCR 2518e75f744SArnaud Giersch * @dcr_writable: bit mask of writable DCR bits 2528e75f744SArnaud Giersch * @pword: number of bytes per PWord 2538e75f744SArnaud Giersch * @fifo_depth: number of PWords that FIFO will hold 2548e75f744SArnaud Giersch * @readIntrThreshold: minimum number of PWords we can read 2558e75f744SArnaud Giersch * if we get an interrupt 2568e75f744SArnaud Giersch * @writeIntrThreshold: minimum number of PWords we can write 2578e75f744SArnaud Giersch * if we get an interrupt 2588e75f744SArnaud Giersch * @irq_mode: operation mode of interrupt handler for this port 2598e75f744SArnaud Giersch * @irq_complete: mutex used to wait for an interrupt to occur 2608e75f744SArnaud Giersch */ 2618e75f744SArnaud Giersch struct parport_ip32_private { 2628e75f744SArnaud Giersch struct parport_ip32_regs regs; 2638e75f744SArnaud Giersch unsigned int dcr_cache; 2648e75f744SArnaud Giersch unsigned int dcr_writable; 2658e75f744SArnaud Giersch unsigned int pword; 2668e75f744SArnaud Giersch unsigned int fifo_depth; 2678e75f744SArnaud Giersch unsigned int readIntrThreshold; 2688e75f744SArnaud Giersch unsigned int writeIntrThreshold; 2698e75f744SArnaud Giersch enum parport_ip32_irq_mode irq_mode; 2708e75f744SArnaud Giersch struct completion irq_complete; 2718e75f744SArnaud Giersch }; 2728e75f744SArnaud Giersch 2738e75f744SArnaud Giersch /*--- Debug code -------------------------------------------------------*/ 2748e75f744SArnaud Giersch 2758e75f744SArnaud Giersch /* 2768e75f744SArnaud Giersch * pr_debug1 - print debug messages 2778e75f744SArnaud Giersch * 2788e75f744SArnaud Giersch * This is like pr_debug(), but is defined for %DEBUG_PARPORT_IP32 >= 1 2798e75f744SArnaud Giersch */ 2808e75f744SArnaud Giersch #if DEBUG_PARPORT_IP32 >= 1 2818e75f744SArnaud Giersch # define pr_debug1(...) printk(KERN_DEBUG __VA_ARGS__) 2828e75f744SArnaud Giersch #else /* DEBUG_PARPORT_IP32 < 1 */ 2838e75f744SArnaud Giersch # define pr_debug1(...) do { } while (0) 2848e75f744SArnaud Giersch #endif 2858e75f744SArnaud Giersch 2868e75f744SArnaud Giersch /* 2878e75f744SArnaud Giersch * pr_trace, pr_trace1 - trace function calls 2888e75f744SArnaud Giersch * @p: pointer to &struct parport 2898e75f744SArnaud Giersch * @fmt: printk format string 2908e75f744SArnaud Giersch * @...: parameters for format string 2918e75f744SArnaud Giersch * 2928e75f744SArnaud Giersch * Macros used to trace function calls. The given string is formatted after 2938e75f744SArnaud Giersch * function name. pr_trace() uses pr_debug(), and pr_trace1() uses 2948e75f744SArnaud Giersch * pr_debug1(). __pr_trace() is the low-level macro and is not to be used 2958e75f744SArnaud Giersch * directly. 2968e75f744SArnaud Giersch */ 2978e75f744SArnaud Giersch #define __pr_trace(pr, p, fmt, ...) \ 2988e75f744SArnaud Giersch pr("%s: %s" fmt "\n", \ 2998e75f744SArnaud Giersch ({ const struct parport *__p = (p); \ 3008e75f744SArnaud Giersch __p ? __p->name : "parport_ip32"; }), \ 3018e75f744SArnaud Giersch __func__ , ##__VA_ARGS__) 3028e75f744SArnaud Giersch #define pr_trace(p, fmt, ...) __pr_trace(pr_debug, p, fmt , ##__VA_ARGS__) 3038e75f744SArnaud Giersch #define pr_trace1(p, fmt, ...) __pr_trace(pr_debug1, p, fmt , ##__VA_ARGS__) 3048e75f744SArnaud Giersch 3058e75f744SArnaud Giersch /* 3068e75f744SArnaud Giersch * __pr_probe, pr_probe - print message if @verbose_probing is true 3078e75f744SArnaud Giersch * @p: pointer to &struct parport 3088e75f744SArnaud Giersch * @fmt: printk format string 3098e75f744SArnaud Giersch * @...: parameters for format string 3108e75f744SArnaud Giersch * 3118e75f744SArnaud Giersch * For new lines, use pr_probe(). Use __pr_probe() for continued lines. 3128e75f744SArnaud Giersch */ 3138e75f744SArnaud Giersch #define __pr_probe(...) \ 3148e75f744SArnaud Giersch do { if (verbose_probing) printk(__VA_ARGS__); } while (0) 3158e75f744SArnaud Giersch #define pr_probe(p, fmt, ...) \ 3168e75f744SArnaud Giersch __pr_probe(KERN_INFO PPIP32 "0x%lx: " fmt, (p)->base , ##__VA_ARGS__) 3178e75f744SArnaud Giersch 3188e75f744SArnaud Giersch /* 3198e75f744SArnaud Giersch * parport_ip32_dump_state - print register status of parport 3208e75f744SArnaud Giersch * @p: pointer to &struct parport 3218e75f744SArnaud Giersch * @str: string to add in message 3228e75f744SArnaud Giersch * @show_ecp_config: shall we dump ECP configuration registers too? 3238e75f744SArnaud Giersch * 3248e75f744SArnaud Giersch * This function is only here for debugging purpose, and should be used with 3258e75f744SArnaud Giersch * care. Reading the parallel port registers may have undesired side effects. 3268e75f744SArnaud Giersch * Especially if @show_ecp_config is true, the parallel port is resetted. 3278e75f744SArnaud Giersch * This function is only defined if %DEBUG_PARPORT_IP32 >= 2. 3288e75f744SArnaud Giersch */ 3298e75f744SArnaud Giersch #if DEBUG_PARPORT_IP32 >= 2 3308e75f744SArnaud Giersch static void parport_ip32_dump_state(struct parport *p, char *str, 3318e75f744SArnaud Giersch unsigned int show_ecp_config) 3328e75f744SArnaud Giersch { 3338e75f744SArnaud Giersch struct parport_ip32_private * const priv = p->physport->private_data; 3348e75f744SArnaud Giersch unsigned int i; 3358e75f744SArnaud Giersch 3368e75f744SArnaud Giersch printk(KERN_DEBUG PPIP32 "%s: state (%s):\n", p->name, str); 3378e75f744SArnaud Giersch { 3388e75f744SArnaud Giersch static const char ecr_modes[8][4] = {"SPP", "PS2", "PPF", 3398e75f744SArnaud Giersch "ECP", "EPP", "???", 3408e75f744SArnaud Giersch "TST", "CFG"}; 3418e75f744SArnaud Giersch unsigned int ecr = readb(priv->regs.ecr); 3428e75f744SArnaud Giersch printk(KERN_DEBUG PPIP32 " ecr=0x%02x", ecr); 3438e75f744SArnaud Giersch printk(" %s", 3448e75f744SArnaud Giersch ecr_modes[(ecr & ECR_MODE_MASK) >> ECR_MODE_SHIFT]); 3458e75f744SArnaud Giersch if (ecr & ECR_nERRINTR) 3468e75f744SArnaud Giersch printk(",nErrIntrEn"); 3478e75f744SArnaud Giersch if (ecr & ECR_DMAEN) 3488e75f744SArnaud Giersch printk(",dmaEn"); 3498e75f744SArnaud Giersch if (ecr & ECR_SERVINTR) 3508e75f744SArnaud Giersch printk(",serviceIntr"); 3518e75f744SArnaud Giersch if (ecr & ECR_F_FULL) 3528e75f744SArnaud Giersch printk(",f_full"); 3538e75f744SArnaud Giersch if (ecr & ECR_F_EMPTY) 3548e75f744SArnaud Giersch printk(",f_empty"); 3558e75f744SArnaud Giersch printk("\n"); 3568e75f744SArnaud Giersch } 3578e75f744SArnaud Giersch if (show_ecp_config) { 3588e75f744SArnaud Giersch unsigned int oecr, cnfgA, cnfgB; 3598e75f744SArnaud Giersch oecr = readb(priv->regs.ecr); 3608e75f744SArnaud Giersch writeb(ECR_MODE_PS2, priv->regs.ecr); 3618e75f744SArnaud Giersch writeb(ECR_MODE_CFG, priv->regs.ecr); 3628e75f744SArnaud Giersch cnfgA = readb(priv->regs.cnfgA); 3638e75f744SArnaud Giersch cnfgB = readb(priv->regs.cnfgB); 3648e75f744SArnaud Giersch writeb(ECR_MODE_PS2, priv->regs.ecr); 3658e75f744SArnaud Giersch writeb(oecr, priv->regs.ecr); 3668e75f744SArnaud Giersch printk(KERN_DEBUG PPIP32 " cnfgA=0x%02x", cnfgA); 3678e75f744SArnaud Giersch printk(" ISA-%s", (cnfgA & CNFGA_IRQ) ? "Level" : "Pulses"); 3688e75f744SArnaud Giersch switch (cnfgA & CNFGA_ID_MASK) { 3698e75f744SArnaud Giersch case CNFGA_ID_8: 3708e75f744SArnaud Giersch printk(",8 bits"); 3718e75f744SArnaud Giersch break; 3728e75f744SArnaud Giersch case CNFGA_ID_16: 3738e75f744SArnaud Giersch printk(",16 bits"); 3748e75f744SArnaud Giersch break; 3758e75f744SArnaud Giersch case CNFGA_ID_32: 3768e75f744SArnaud Giersch printk(",32 bits"); 3778e75f744SArnaud Giersch break; 3788e75f744SArnaud Giersch default: 3798e75f744SArnaud Giersch printk(",unknown ID"); 3808e75f744SArnaud Giersch break; 3818e75f744SArnaud Giersch } 3828e75f744SArnaud Giersch if (!(cnfgA & CNFGA_nBYTEINTRANS)) 3838e75f744SArnaud Giersch printk(",ByteInTrans"); 3848e75f744SArnaud Giersch if ((cnfgA & CNFGA_ID_MASK) != CNFGA_ID_8) 3858e75f744SArnaud Giersch printk(",%d byte%s left", cnfgA & CNFGA_PWORDLEFT, 3868e75f744SArnaud Giersch ((cnfgA & CNFGA_PWORDLEFT) > 1) ? "s" : ""); 3878e75f744SArnaud Giersch printk("\n"); 3888e75f744SArnaud Giersch printk(KERN_DEBUG PPIP32 " cnfgB=0x%02x", cnfgB); 3898e75f744SArnaud Giersch printk(" irq=%u,dma=%u", 3908e75f744SArnaud Giersch (cnfgB & CNFGB_IRQ_MASK) >> CNFGB_IRQ_SHIFT, 3918e75f744SArnaud Giersch (cnfgB & CNFGB_DMA_MASK) >> CNFGB_DMA_SHIFT); 3928e75f744SArnaud Giersch printk(",intrValue=%d", !!(cnfgB & CNFGB_INTRVAL)); 3938e75f744SArnaud Giersch if (cnfgB & CNFGB_COMPRESS) 3948e75f744SArnaud Giersch printk(",compress"); 3958e75f744SArnaud Giersch printk("\n"); 3968e75f744SArnaud Giersch } 3978e75f744SArnaud Giersch for (i = 0; i < 2; i++) { 3988e75f744SArnaud Giersch unsigned int dcr = i ? priv->dcr_cache : readb(priv->regs.dcr); 3998e75f744SArnaud Giersch printk(KERN_DEBUG PPIP32 " dcr(%s)=0x%02x", 4008e75f744SArnaud Giersch i ? "soft" : "hard", dcr); 4018e75f744SArnaud Giersch printk(" %s", (dcr & DCR_DIR) ? "rev" : "fwd"); 4028e75f744SArnaud Giersch if (dcr & DCR_IRQ) 4038e75f744SArnaud Giersch printk(",ackIntEn"); 4048e75f744SArnaud Giersch if (!(dcr & DCR_SELECT)) 4058e75f744SArnaud Giersch printk(",nSelectIn"); 4068e75f744SArnaud Giersch if (dcr & DCR_nINIT) 4078e75f744SArnaud Giersch printk(",nInit"); 4088e75f744SArnaud Giersch if (!(dcr & DCR_AUTOFD)) 4098e75f744SArnaud Giersch printk(",nAutoFD"); 4108e75f744SArnaud Giersch if (!(dcr & DCR_STROBE)) 4118e75f744SArnaud Giersch printk(",nStrobe"); 4128e75f744SArnaud Giersch printk("\n"); 4138e75f744SArnaud Giersch } 4148e75f744SArnaud Giersch #define sep (f++ ? ',' : ' ') 4158e75f744SArnaud Giersch { 4168e75f744SArnaud Giersch unsigned int f = 0; 4178e75f744SArnaud Giersch unsigned int dsr = readb(priv->regs.dsr); 4188e75f744SArnaud Giersch printk(KERN_DEBUG PPIP32 " dsr=0x%02x", dsr); 4198e75f744SArnaud Giersch if (!(dsr & DSR_nBUSY)) 4208e75f744SArnaud Giersch printk("%cBusy", sep); 4218e75f744SArnaud Giersch if (dsr & DSR_nACK) 4228e75f744SArnaud Giersch printk("%cnAck", sep); 4238e75f744SArnaud Giersch if (dsr & DSR_PERROR) 4248e75f744SArnaud Giersch printk("%cPError", sep); 4258e75f744SArnaud Giersch if (dsr & DSR_SELECT) 4268e75f744SArnaud Giersch printk("%cSelect", sep); 4278e75f744SArnaud Giersch if (dsr & DSR_nFAULT) 4288e75f744SArnaud Giersch printk("%cnFault", sep); 4298e75f744SArnaud Giersch if (!(dsr & DSR_nPRINT)) 4308e75f744SArnaud Giersch printk("%c(Print)", sep); 4318e75f744SArnaud Giersch if (dsr & DSR_TIMEOUT) 4328e75f744SArnaud Giersch printk("%cTimeout", sep); 4338e75f744SArnaud Giersch printk("\n"); 4348e75f744SArnaud Giersch } 4358e75f744SArnaud Giersch #undef sep 4368e75f744SArnaud Giersch } 4378e75f744SArnaud Giersch #else /* DEBUG_PARPORT_IP32 < 2 */ 4388e75f744SArnaud Giersch #define parport_ip32_dump_state(...) do { } while (0) 4398e75f744SArnaud Giersch #endif 4408e75f744SArnaud Giersch 4418e75f744SArnaud Giersch /* 4428e75f744SArnaud Giersch * CHECK_EXTRA_BITS - track and log extra bits 4438e75f744SArnaud Giersch * @p: pointer to &struct parport 4448e75f744SArnaud Giersch * @b: byte to inspect 4458e75f744SArnaud Giersch * @m: bit mask of authorized bits 4468e75f744SArnaud Giersch * 4478e75f744SArnaud Giersch * This is used to track and log extra bits that should not be there in 4488e75f744SArnaud Giersch * parport_ip32_write_control() and parport_ip32_frob_control(). It is only 4498e75f744SArnaud Giersch * defined if %DEBUG_PARPORT_IP32 >= 1. 4508e75f744SArnaud Giersch */ 4518e75f744SArnaud Giersch #if DEBUG_PARPORT_IP32 >= 1 4528e75f744SArnaud Giersch #define CHECK_EXTRA_BITS(p, b, m) \ 4538e75f744SArnaud Giersch do { \ 4548e75f744SArnaud Giersch unsigned int __b = (b), __m = (m); \ 4558e75f744SArnaud Giersch if (__b & ~__m) \ 4568e75f744SArnaud Giersch pr_debug1(PPIP32 "%s: extra bits in %s(%s): " \ 4578e75f744SArnaud Giersch "0x%02x/0x%02x\n", \ 4588e75f744SArnaud Giersch (p)->name, __func__, #b, __b, __m); \ 4598e75f744SArnaud Giersch } while (0) 4608e75f744SArnaud Giersch #else /* DEBUG_PARPORT_IP32 < 1 */ 4618e75f744SArnaud Giersch #define CHECK_EXTRA_BITS(...) do { } while (0) 4628e75f744SArnaud Giersch #endif 4638e75f744SArnaud Giersch 4648e75f744SArnaud Giersch /*--- IP32 parallel port DMA operations --------------------------------*/ 4658e75f744SArnaud Giersch 4668e75f744SArnaud Giersch /** 4678e75f744SArnaud Giersch * struct parport_ip32_dma_data - private data needed for DMA operation 4688e75f744SArnaud Giersch * @dir: DMA direction (from or to device) 4698e75f744SArnaud Giersch * @buf: buffer physical address 4708e75f744SArnaud Giersch * @len: buffer length 4718e75f744SArnaud Giersch * @next: address of next bytes to DMA transfer 4728e75f744SArnaud Giersch * @left: number of bytes remaining 4738e75f744SArnaud Giersch * @ctx: next context to write (0: context_a; 1: context_b) 4748e75f744SArnaud Giersch * @irq_on: are the DMA IRQs currently enabled? 4758e75f744SArnaud Giersch * @lock: spinlock to protect access to the structure 4768e75f744SArnaud Giersch */ 4778e75f744SArnaud Giersch struct parport_ip32_dma_data { 4788e75f744SArnaud Giersch enum dma_data_direction dir; 4798e75f744SArnaud Giersch dma_addr_t buf; 4808e75f744SArnaud Giersch dma_addr_t next; 4818e75f744SArnaud Giersch size_t len; 4828e75f744SArnaud Giersch size_t left; 4838e75f744SArnaud Giersch unsigned int ctx; 4848e75f744SArnaud Giersch unsigned int irq_on; 4858e75f744SArnaud Giersch spinlock_t lock; 4868e75f744SArnaud Giersch }; 4878e75f744SArnaud Giersch static struct parport_ip32_dma_data parport_ip32_dma; 4888e75f744SArnaud Giersch 4898e75f744SArnaud Giersch /** 4908e75f744SArnaud Giersch * parport_ip32_dma_setup_context - setup next DMA context 4918e75f744SArnaud Giersch * @limit: maximum data size for the context 4928e75f744SArnaud Giersch * 4938e75f744SArnaud Giersch * The alignment constraints must be verified in caller function, and the 4948e75f744SArnaud Giersch * parameter @limit must be set accordingly. 4958e75f744SArnaud Giersch */ 4968e75f744SArnaud Giersch static void parport_ip32_dma_setup_context(unsigned int limit) 4978e75f744SArnaud Giersch { 4988e75f744SArnaud Giersch unsigned long flags; 4998e75f744SArnaud Giersch 5008e75f744SArnaud Giersch spin_lock_irqsave(&parport_ip32_dma.lock, flags); 5018e75f744SArnaud Giersch if (parport_ip32_dma.left > 0) { 5028e75f744SArnaud Giersch /* Note: ctxreg is "volatile" here only because 5038e75f744SArnaud Giersch * mace->perif.ctrl.parport.context_a and context_b are 5048e75f744SArnaud Giersch * "volatile". */ 5058e75f744SArnaud Giersch volatile u64 __iomem *ctxreg = (parport_ip32_dma.ctx == 0) ? 5068e75f744SArnaud Giersch &mace->perif.ctrl.parport.context_a : 5078e75f744SArnaud Giersch &mace->perif.ctrl.parport.context_b; 5088e75f744SArnaud Giersch u64 count; 5098e75f744SArnaud Giersch u64 ctxval; 5108e75f744SArnaud Giersch if (parport_ip32_dma.left <= limit) { 5118e75f744SArnaud Giersch count = parport_ip32_dma.left; 5128e75f744SArnaud Giersch ctxval = MACEPAR_CONTEXT_LASTFLAG; 5138e75f744SArnaud Giersch } else { 5148e75f744SArnaud Giersch count = limit; 5158e75f744SArnaud Giersch ctxval = 0; 5168e75f744SArnaud Giersch } 5178e75f744SArnaud Giersch 5188e75f744SArnaud Giersch pr_trace(NULL, 5198e75f744SArnaud Giersch "(%u): 0x%04x:0x%04x, %u -> %u%s", 5208e75f744SArnaud Giersch limit, 5218e75f744SArnaud Giersch (unsigned int)parport_ip32_dma.buf, 5228e75f744SArnaud Giersch (unsigned int)parport_ip32_dma.next, 5238e75f744SArnaud Giersch (unsigned int)count, 5248e75f744SArnaud Giersch parport_ip32_dma.ctx, ctxval ? "*" : ""); 5258e75f744SArnaud Giersch 5268e75f744SArnaud Giersch ctxval |= parport_ip32_dma.next & 5278e75f744SArnaud Giersch MACEPAR_CONTEXT_BASEADDR_MASK; 5288e75f744SArnaud Giersch ctxval |= ((count - 1) << MACEPAR_CONTEXT_DATALEN_SHIFT) & 5298e75f744SArnaud Giersch MACEPAR_CONTEXT_DATALEN_MASK; 5308e75f744SArnaud Giersch writeq(ctxval, ctxreg); 5318e75f744SArnaud Giersch parport_ip32_dma.next += count; 5328e75f744SArnaud Giersch parport_ip32_dma.left -= count; 5338e75f744SArnaud Giersch parport_ip32_dma.ctx ^= 1U; 5348e75f744SArnaud Giersch } 5358e75f744SArnaud Giersch /* If there is nothing more to send, disable IRQs to avoid to 5368e75f744SArnaud Giersch * face an IRQ storm which can lock the machine. Disable them 5378e75f744SArnaud Giersch * only once. */ 5388e75f744SArnaud Giersch if (parport_ip32_dma.left == 0 && parport_ip32_dma.irq_on) { 5398e75f744SArnaud Giersch pr_debug(PPIP32 "IRQ off (ctx)\n"); 5408e75f744SArnaud Giersch disable_irq_nosync(MACEISA_PAR_CTXA_IRQ); 5418e75f744SArnaud Giersch disable_irq_nosync(MACEISA_PAR_CTXB_IRQ); 5428e75f744SArnaud Giersch parport_ip32_dma.irq_on = 0; 5438e75f744SArnaud Giersch } 5448e75f744SArnaud Giersch spin_unlock_irqrestore(&parport_ip32_dma.lock, flags); 5458e75f744SArnaud Giersch } 5468e75f744SArnaud Giersch 5478e75f744SArnaud Giersch /** 5488e75f744SArnaud Giersch * parport_ip32_dma_interrupt - DMA interrupt handler 5498e75f744SArnaud Giersch * @irq: interrupt number 5508e75f744SArnaud Giersch * @dev_id: unused 5518e75f744SArnaud Giersch */ 5527d12e780SDavid Howells static irqreturn_t parport_ip32_dma_interrupt(int irq, void *dev_id) 5538e75f744SArnaud Giersch { 5548e75f744SArnaud Giersch if (parport_ip32_dma.left) 5558e75f744SArnaud Giersch pr_trace(NULL, "(%d): ctx=%d", irq, parport_ip32_dma.ctx); 5568e75f744SArnaud Giersch parport_ip32_dma_setup_context(MACEPAR_CONTEXT_DATA_BOUND); 5578e75f744SArnaud Giersch return IRQ_HANDLED; 5588e75f744SArnaud Giersch } 5598e75f744SArnaud Giersch 5608e75f744SArnaud Giersch #if DEBUG_PARPORT_IP32 5617d12e780SDavid Howells static irqreturn_t parport_ip32_merr_interrupt(int irq, void *dev_id) 5628e75f744SArnaud Giersch { 5638e75f744SArnaud Giersch pr_trace1(NULL, "(%d)", irq); 5648e75f744SArnaud Giersch return IRQ_HANDLED; 5658e75f744SArnaud Giersch } 5668e75f744SArnaud Giersch #endif 5678e75f744SArnaud Giersch 5688e75f744SArnaud Giersch /** 5698e75f744SArnaud Giersch * parport_ip32_dma_start - begins a DMA transfer 5708e75f744SArnaud Giersch * @dir: DMA direction: DMA_TO_DEVICE or DMA_FROM_DEVICE 5718e75f744SArnaud Giersch * @addr: pointer to data buffer 5728e75f744SArnaud Giersch * @count: buffer size 5738e75f744SArnaud Giersch * 5748e75f744SArnaud Giersch * Calls to parport_ip32_dma_start() and parport_ip32_dma_stop() must be 5758e75f744SArnaud Giersch * correctly balanced. 5768e75f744SArnaud Giersch */ 5778e75f744SArnaud Giersch static int parport_ip32_dma_start(enum dma_data_direction dir, 5788e75f744SArnaud Giersch void *addr, size_t count) 5798e75f744SArnaud Giersch { 5808e75f744SArnaud Giersch unsigned int limit; 5818e75f744SArnaud Giersch u64 ctrl; 5828e75f744SArnaud Giersch 5838e75f744SArnaud Giersch pr_trace(NULL, "(%d, %lu)", dir, (unsigned long)count); 5848e75f744SArnaud Giersch 5858e75f744SArnaud Giersch /* FIXME - add support for DMA_FROM_DEVICE. In this case, buffer must 5868e75f744SArnaud Giersch * be 64 bytes aligned. */ 5878e75f744SArnaud Giersch BUG_ON(dir != DMA_TO_DEVICE); 5888e75f744SArnaud Giersch 5898e75f744SArnaud Giersch /* Reset DMA controller */ 5908e75f744SArnaud Giersch ctrl = MACEPAR_CTLSTAT_RESET; 5918e75f744SArnaud Giersch writeq(ctrl, &mace->perif.ctrl.parport.cntlstat); 5928e75f744SArnaud Giersch 5938e75f744SArnaud Giersch /* DMA IRQs should normally be enabled */ 5948e75f744SArnaud Giersch if (!parport_ip32_dma.irq_on) { 5958e75f744SArnaud Giersch WARN_ON(1); 5968e75f744SArnaud Giersch enable_irq(MACEISA_PAR_CTXA_IRQ); 5978e75f744SArnaud Giersch enable_irq(MACEISA_PAR_CTXB_IRQ); 5988e75f744SArnaud Giersch parport_ip32_dma.irq_on = 1; 5998e75f744SArnaud Giersch } 6008e75f744SArnaud Giersch 6018e75f744SArnaud Giersch /* Prepare DMA pointers */ 6028e75f744SArnaud Giersch parport_ip32_dma.dir = dir; 6038e75f744SArnaud Giersch parport_ip32_dma.buf = dma_map_single(NULL, addr, count, dir); 6048e75f744SArnaud Giersch parport_ip32_dma.len = count; 6058e75f744SArnaud Giersch parport_ip32_dma.next = parport_ip32_dma.buf; 6068e75f744SArnaud Giersch parport_ip32_dma.left = parport_ip32_dma.len; 6078e75f744SArnaud Giersch parport_ip32_dma.ctx = 0; 6088e75f744SArnaud Giersch 6098e75f744SArnaud Giersch /* Setup DMA direction and first two contexts */ 6108e75f744SArnaud Giersch ctrl = (dir == DMA_TO_DEVICE) ? 0 : MACEPAR_CTLSTAT_DIRECTION; 6118e75f744SArnaud Giersch writeq(ctrl, &mace->perif.ctrl.parport.cntlstat); 6128e75f744SArnaud Giersch /* Single transfer should not cross a 4K page boundary */ 6138e75f744SArnaud Giersch limit = MACEPAR_CONTEXT_DATA_BOUND - 6148e75f744SArnaud Giersch (parport_ip32_dma.next & (MACEPAR_CONTEXT_DATA_BOUND - 1)); 6158e75f744SArnaud Giersch parport_ip32_dma_setup_context(limit); 6168e75f744SArnaud Giersch parport_ip32_dma_setup_context(MACEPAR_CONTEXT_DATA_BOUND); 6178e75f744SArnaud Giersch 6188e75f744SArnaud Giersch /* Real start of DMA transfer */ 6198e75f744SArnaud Giersch ctrl |= MACEPAR_CTLSTAT_ENABLE; 6208e75f744SArnaud Giersch writeq(ctrl, &mace->perif.ctrl.parport.cntlstat); 6218e75f744SArnaud Giersch 6228e75f744SArnaud Giersch return 0; 6238e75f744SArnaud Giersch } 6248e75f744SArnaud Giersch 6258e75f744SArnaud Giersch /** 6268e75f744SArnaud Giersch * parport_ip32_dma_stop - ends a running DMA transfer 6278e75f744SArnaud Giersch * 6288e75f744SArnaud Giersch * Calls to parport_ip32_dma_start() and parport_ip32_dma_stop() must be 6298e75f744SArnaud Giersch * correctly balanced. 6308e75f744SArnaud Giersch */ 6318e75f744SArnaud Giersch static void parport_ip32_dma_stop(void) 6328e75f744SArnaud Giersch { 6338e75f744SArnaud Giersch u64 ctx_a; 6348e75f744SArnaud Giersch u64 ctx_b; 6358e75f744SArnaud Giersch u64 ctrl; 6368e75f744SArnaud Giersch u64 diag; 6378e75f744SArnaud Giersch size_t res[2]; /* {[0] = res_a, [1] = res_b} */ 6388e75f744SArnaud Giersch 6398e75f744SArnaud Giersch pr_trace(NULL, "()"); 6408e75f744SArnaud Giersch 6418e75f744SArnaud Giersch /* Disable IRQs */ 6428e75f744SArnaud Giersch spin_lock_irq(&parport_ip32_dma.lock); 6438e75f744SArnaud Giersch if (parport_ip32_dma.irq_on) { 6448e75f744SArnaud Giersch pr_debug(PPIP32 "IRQ off (stop)\n"); 6458e75f744SArnaud Giersch disable_irq_nosync(MACEISA_PAR_CTXA_IRQ); 6468e75f744SArnaud Giersch disable_irq_nosync(MACEISA_PAR_CTXB_IRQ); 6478e75f744SArnaud Giersch parport_ip32_dma.irq_on = 0; 6488e75f744SArnaud Giersch } 6498e75f744SArnaud Giersch spin_unlock_irq(&parport_ip32_dma.lock); 6508e75f744SArnaud Giersch /* Force IRQ synchronization, even if the IRQs were disabled 6518e75f744SArnaud Giersch * elsewhere. */ 6528e75f744SArnaud Giersch synchronize_irq(MACEISA_PAR_CTXA_IRQ); 6538e75f744SArnaud Giersch synchronize_irq(MACEISA_PAR_CTXB_IRQ); 6548e75f744SArnaud Giersch 6558e75f744SArnaud Giersch /* Stop DMA transfer */ 6568e75f744SArnaud Giersch ctrl = readq(&mace->perif.ctrl.parport.cntlstat); 6578e75f744SArnaud Giersch ctrl &= ~MACEPAR_CTLSTAT_ENABLE; 6588e75f744SArnaud Giersch writeq(ctrl, &mace->perif.ctrl.parport.cntlstat); 6598e75f744SArnaud Giersch 6608e75f744SArnaud Giersch /* Adjust residue (parport_ip32_dma.left) */ 6618e75f744SArnaud Giersch ctx_a = readq(&mace->perif.ctrl.parport.context_a); 6628e75f744SArnaud Giersch ctx_b = readq(&mace->perif.ctrl.parport.context_b); 6638e75f744SArnaud Giersch ctrl = readq(&mace->perif.ctrl.parport.cntlstat); 6648e75f744SArnaud Giersch diag = readq(&mace->perif.ctrl.parport.diagnostic); 6658e75f744SArnaud Giersch res[0] = (ctrl & MACEPAR_CTLSTAT_CTXA_VALID) ? 6668e75f744SArnaud Giersch 1 + ((ctx_a & MACEPAR_CONTEXT_DATALEN_MASK) >> 6678e75f744SArnaud Giersch MACEPAR_CONTEXT_DATALEN_SHIFT) : 6688e75f744SArnaud Giersch 0; 6698e75f744SArnaud Giersch res[1] = (ctrl & MACEPAR_CTLSTAT_CTXB_VALID) ? 6708e75f744SArnaud Giersch 1 + ((ctx_b & MACEPAR_CONTEXT_DATALEN_MASK) >> 6718e75f744SArnaud Giersch MACEPAR_CONTEXT_DATALEN_SHIFT) : 6728e75f744SArnaud Giersch 0; 6738e75f744SArnaud Giersch if (diag & MACEPAR_DIAG_DMACTIVE) 6748e75f744SArnaud Giersch res[(diag & MACEPAR_DIAG_CTXINUSE) != 0] = 6758e75f744SArnaud Giersch 1 + ((diag & MACEPAR_DIAG_CTRMASK) >> 6768e75f744SArnaud Giersch MACEPAR_DIAG_CTRSHIFT); 6778e75f744SArnaud Giersch parport_ip32_dma.left += res[0] + res[1]; 6788e75f744SArnaud Giersch 6798e75f744SArnaud Giersch /* Reset DMA controller, and re-enable IRQs */ 6808e75f744SArnaud Giersch ctrl = MACEPAR_CTLSTAT_RESET; 6818e75f744SArnaud Giersch writeq(ctrl, &mace->perif.ctrl.parport.cntlstat); 6828e75f744SArnaud Giersch pr_debug(PPIP32 "IRQ on (stop)\n"); 6838e75f744SArnaud Giersch enable_irq(MACEISA_PAR_CTXA_IRQ); 6848e75f744SArnaud Giersch enable_irq(MACEISA_PAR_CTXB_IRQ); 6858e75f744SArnaud Giersch parport_ip32_dma.irq_on = 1; 6868e75f744SArnaud Giersch 6878e75f744SArnaud Giersch dma_unmap_single(NULL, parport_ip32_dma.buf, parport_ip32_dma.len, 6888e75f744SArnaud Giersch parport_ip32_dma.dir); 6898e75f744SArnaud Giersch } 6908e75f744SArnaud Giersch 6918e75f744SArnaud Giersch /** 6928e75f744SArnaud Giersch * parport_ip32_dma_get_residue - get residue from last DMA transfer 6938e75f744SArnaud Giersch * 6948e75f744SArnaud Giersch * Returns the number of bytes remaining from last DMA transfer. 6958e75f744SArnaud Giersch */ 6968e75f744SArnaud Giersch static inline size_t parport_ip32_dma_get_residue(void) 6978e75f744SArnaud Giersch { 6988e75f744SArnaud Giersch return parport_ip32_dma.left; 6998e75f744SArnaud Giersch } 7008e75f744SArnaud Giersch 7018e75f744SArnaud Giersch /** 7028e75f744SArnaud Giersch * parport_ip32_dma_register - initialize DMA engine 7038e75f744SArnaud Giersch * 7048e75f744SArnaud Giersch * Returns zero for success. 7058e75f744SArnaud Giersch */ 7068e75f744SArnaud Giersch static int parport_ip32_dma_register(void) 7078e75f744SArnaud Giersch { 7088e75f744SArnaud Giersch int err; 7098e75f744SArnaud Giersch 7108e75f744SArnaud Giersch spin_lock_init(&parport_ip32_dma.lock); 7118e75f744SArnaud Giersch parport_ip32_dma.irq_on = 1; 7128e75f744SArnaud Giersch 7138e75f744SArnaud Giersch /* Reset DMA controller */ 7148e75f744SArnaud Giersch writeq(MACEPAR_CTLSTAT_RESET, &mace->perif.ctrl.parport.cntlstat); 7158e75f744SArnaud Giersch 7168e75f744SArnaud Giersch /* Request IRQs */ 7178e75f744SArnaud Giersch err = request_irq(MACEISA_PAR_CTXA_IRQ, parport_ip32_dma_interrupt, 7188e75f744SArnaud Giersch 0, "parport_ip32", NULL); 7198e75f744SArnaud Giersch if (err) 7208e75f744SArnaud Giersch goto fail_a; 7218e75f744SArnaud Giersch err = request_irq(MACEISA_PAR_CTXB_IRQ, parport_ip32_dma_interrupt, 7228e75f744SArnaud Giersch 0, "parport_ip32", NULL); 7238e75f744SArnaud Giersch if (err) 7248e75f744SArnaud Giersch goto fail_b; 7258e75f744SArnaud Giersch #if DEBUG_PARPORT_IP32 7268e75f744SArnaud Giersch /* FIXME - what is this IRQ for? */ 7278e75f744SArnaud Giersch err = request_irq(MACEISA_PAR_MERR_IRQ, parport_ip32_merr_interrupt, 7288e75f744SArnaud Giersch 0, "parport_ip32", NULL); 7298e75f744SArnaud Giersch if (err) 7308e75f744SArnaud Giersch goto fail_merr; 7318e75f744SArnaud Giersch #endif 7328e75f744SArnaud Giersch return 0; 7338e75f744SArnaud Giersch 7348e75f744SArnaud Giersch #if DEBUG_PARPORT_IP32 7358e75f744SArnaud Giersch fail_merr: 7368e75f744SArnaud Giersch free_irq(MACEISA_PAR_CTXB_IRQ, NULL); 7378e75f744SArnaud Giersch #endif 7388e75f744SArnaud Giersch fail_b: 7398e75f744SArnaud Giersch free_irq(MACEISA_PAR_CTXA_IRQ, NULL); 7408e75f744SArnaud Giersch fail_a: 7418e75f744SArnaud Giersch return err; 7428e75f744SArnaud Giersch } 7438e75f744SArnaud Giersch 7448e75f744SArnaud Giersch /** 7458e75f744SArnaud Giersch * parport_ip32_dma_unregister - release and free resources for DMA engine 7468e75f744SArnaud Giersch */ 7478e75f744SArnaud Giersch static void parport_ip32_dma_unregister(void) 7488e75f744SArnaud Giersch { 7498e75f744SArnaud Giersch #if DEBUG_PARPORT_IP32 7508e75f744SArnaud Giersch free_irq(MACEISA_PAR_MERR_IRQ, NULL); 7518e75f744SArnaud Giersch #endif 7528e75f744SArnaud Giersch free_irq(MACEISA_PAR_CTXB_IRQ, NULL); 7538e75f744SArnaud Giersch free_irq(MACEISA_PAR_CTXA_IRQ, NULL); 7548e75f744SArnaud Giersch } 7558e75f744SArnaud Giersch 7568e75f744SArnaud Giersch /*--- Interrupt handlers and associates --------------------------------*/ 7578e75f744SArnaud Giersch 7588e75f744SArnaud Giersch /** 7598e75f744SArnaud Giersch * parport_ip32_wakeup - wakes up code waiting for an interrupt 7608e75f744SArnaud Giersch * @p: pointer to &struct parport 7618e75f744SArnaud Giersch */ 7628e75f744SArnaud Giersch static inline void parport_ip32_wakeup(struct parport *p) 7638e75f744SArnaud Giersch { 7648e75f744SArnaud Giersch struct parport_ip32_private * const priv = p->physport->private_data; 7658e75f744SArnaud Giersch complete(&priv->irq_complete); 7668e75f744SArnaud Giersch } 7678e75f744SArnaud Giersch 7688e75f744SArnaud Giersch /** 7698e75f744SArnaud Giersch * parport_ip32_interrupt - interrupt handler 7708e75f744SArnaud Giersch * @irq: interrupt number 7718e75f744SArnaud Giersch * @dev_id: pointer to &struct parport 7728e75f744SArnaud Giersch * 7738e75f744SArnaud Giersch * Caught interrupts are forwarded to the upper parport layer if IRQ_mode is 7748e75f744SArnaud Giersch * %PARPORT_IP32_IRQ_FWD. 7758e75f744SArnaud Giersch */ 7767d12e780SDavid Howells static irqreturn_t parport_ip32_interrupt(int irq, void *dev_id) 7778e75f744SArnaud Giersch { 7788e75f744SArnaud Giersch struct parport * const p = dev_id; 7798e75f744SArnaud Giersch struct parport_ip32_private * const priv = p->physport->private_data; 7808e75f744SArnaud Giersch enum parport_ip32_irq_mode irq_mode = priv->irq_mode; 781*3f2e40dfSJeff Garzik 7828e75f744SArnaud Giersch switch (irq_mode) { 7838e75f744SArnaud Giersch case PARPORT_IP32_IRQ_FWD: 784*3f2e40dfSJeff Garzik return parport_irq_handler(irq, dev_id); 785*3f2e40dfSJeff Garzik 7868e75f744SArnaud Giersch case PARPORT_IP32_IRQ_HERE: 7878e75f744SArnaud Giersch parport_ip32_wakeup(p); 7888e75f744SArnaud Giersch break; 7898e75f744SArnaud Giersch } 790*3f2e40dfSJeff Garzik 7918e75f744SArnaud Giersch return IRQ_HANDLED; 7928e75f744SArnaud Giersch } 7938e75f744SArnaud Giersch 7948e75f744SArnaud Giersch /*--- Some utility function to manipulate ECR register -----------------*/ 7958e75f744SArnaud Giersch 7968e75f744SArnaud Giersch /** 7978e75f744SArnaud Giersch * parport_ip32_read_econtrol - read contents of the ECR register 7988e75f744SArnaud Giersch * @p: pointer to &struct parport 7998e75f744SArnaud Giersch */ 8008e75f744SArnaud Giersch static inline unsigned int parport_ip32_read_econtrol(struct parport *p) 8018e75f744SArnaud Giersch { 8028e75f744SArnaud Giersch struct parport_ip32_private * const priv = p->physport->private_data; 8038e75f744SArnaud Giersch return readb(priv->regs.ecr); 8048e75f744SArnaud Giersch } 8058e75f744SArnaud Giersch 8068e75f744SArnaud Giersch /** 8078e75f744SArnaud Giersch * parport_ip32_write_econtrol - write new contents to the ECR register 8088e75f744SArnaud Giersch * @p: pointer to &struct parport 8098e75f744SArnaud Giersch * @c: new value to write 8108e75f744SArnaud Giersch */ 8118e75f744SArnaud Giersch static inline void parport_ip32_write_econtrol(struct parport *p, 8128e75f744SArnaud Giersch unsigned int c) 8138e75f744SArnaud Giersch { 8148e75f744SArnaud Giersch struct parport_ip32_private * const priv = p->physport->private_data; 8158e75f744SArnaud Giersch writeb(c, priv->regs.ecr); 8168e75f744SArnaud Giersch } 8178e75f744SArnaud Giersch 8188e75f744SArnaud Giersch /** 8198e75f744SArnaud Giersch * parport_ip32_frob_econtrol - change bits from the ECR register 8208e75f744SArnaud Giersch * @p: pointer to &struct parport 8218e75f744SArnaud Giersch * @mask: bit mask of bits to change 8228e75f744SArnaud Giersch * @val: new value for changed bits 8238e75f744SArnaud Giersch * 8248e75f744SArnaud Giersch * Read from the ECR, mask out the bits in @mask, exclusive-or with the bits 8258e75f744SArnaud Giersch * in @val, and write the result to the ECR. 8268e75f744SArnaud Giersch */ 8278e75f744SArnaud Giersch static inline void parport_ip32_frob_econtrol(struct parport *p, 8288e75f744SArnaud Giersch unsigned int mask, 8298e75f744SArnaud Giersch unsigned int val) 8308e75f744SArnaud Giersch { 8318e75f744SArnaud Giersch unsigned int c; 8328e75f744SArnaud Giersch c = (parport_ip32_read_econtrol(p) & ~mask) ^ val; 8338e75f744SArnaud Giersch parport_ip32_write_econtrol(p, c); 8348e75f744SArnaud Giersch } 8358e75f744SArnaud Giersch 8368e75f744SArnaud Giersch /** 8378e75f744SArnaud Giersch * parport_ip32_set_mode - change mode of ECP port 8388e75f744SArnaud Giersch * @p: pointer to &struct parport 8398e75f744SArnaud Giersch * @mode: new mode to write in ECR 8408e75f744SArnaud Giersch * 8418e75f744SArnaud Giersch * ECR is reset in a sane state (interrupts and DMA disabled), and placed in 8428e75f744SArnaud Giersch * mode @mode. Go through PS2 mode if needed. 8438e75f744SArnaud Giersch */ 8448e75f744SArnaud Giersch static void parport_ip32_set_mode(struct parport *p, unsigned int mode) 8458e75f744SArnaud Giersch { 8468e75f744SArnaud Giersch unsigned int omode; 8478e75f744SArnaud Giersch 8488e75f744SArnaud Giersch mode &= ECR_MODE_MASK; 8498e75f744SArnaud Giersch omode = parport_ip32_read_econtrol(p) & ECR_MODE_MASK; 8508e75f744SArnaud Giersch 8518e75f744SArnaud Giersch if (!(mode == ECR_MODE_SPP || mode == ECR_MODE_PS2 8528e75f744SArnaud Giersch || omode == ECR_MODE_SPP || omode == ECR_MODE_PS2)) { 8538e75f744SArnaud Giersch /* We have to go through PS2 mode */ 8548e75f744SArnaud Giersch unsigned int ecr = ECR_MODE_PS2 | ECR_nERRINTR | ECR_SERVINTR; 8558e75f744SArnaud Giersch parport_ip32_write_econtrol(p, ecr); 8568e75f744SArnaud Giersch } 8578e75f744SArnaud Giersch parport_ip32_write_econtrol(p, mode | ECR_nERRINTR | ECR_SERVINTR); 8588e75f744SArnaud Giersch } 8598e75f744SArnaud Giersch 8608e75f744SArnaud Giersch /*--- Basic functions needed for parport -------------------------------*/ 8618e75f744SArnaud Giersch 8628e75f744SArnaud Giersch /** 8638e75f744SArnaud Giersch * parport_ip32_read_data - return current contents of the DATA register 8648e75f744SArnaud Giersch * @p: pointer to &struct parport 8658e75f744SArnaud Giersch */ 8668e75f744SArnaud Giersch static inline unsigned char parport_ip32_read_data(struct parport *p) 8678e75f744SArnaud Giersch { 8688e75f744SArnaud Giersch struct parport_ip32_private * const priv = p->physport->private_data; 8698e75f744SArnaud Giersch return readb(priv->regs.data); 8708e75f744SArnaud Giersch } 8718e75f744SArnaud Giersch 8728e75f744SArnaud Giersch /** 8738e75f744SArnaud Giersch * parport_ip32_write_data - set new contents for the DATA register 8748e75f744SArnaud Giersch * @p: pointer to &struct parport 8758e75f744SArnaud Giersch * @d: new value to write 8768e75f744SArnaud Giersch */ 8778e75f744SArnaud Giersch static inline void parport_ip32_write_data(struct parport *p, unsigned char d) 8788e75f744SArnaud Giersch { 8798e75f744SArnaud Giersch struct parport_ip32_private * const priv = p->physport->private_data; 8808e75f744SArnaud Giersch writeb(d, priv->regs.data); 8818e75f744SArnaud Giersch } 8828e75f744SArnaud Giersch 8838e75f744SArnaud Giersch /** 8848e75f744SArnaud Giersch * parport_ip32_read_status - return current contents of the DSR register 8858e75f744SArnaud Giersch * @p: pointer to &struct parport 8868e75f744SArnaud Giersch */ 8878e75f744SArnaud Giersch static inline unsigned char parport_ip32_read_status(struct parport *p) 8888e75f744SArnaud Giersch { 8898e75f744SArnaud Giersch struct parport_ip32_private * const priv = p->physport->private_data; 8908e75f744SArnaud Giersch return readb(priv->regs.dsr); 8918e75f744SArnaud Giersch } 8928e75f744SArnaud Giersch 8938e75f744SArnaud Giersch /** 8948e75f744SArnaud Giersch * __parport_ip32_read_control - return cached contents of the DCR register 8958e75f744SArnaud Giersch * @p: pointer to &struct parport 8968e75f744SArnaud Giersch */ 8978e75f744SArnaud Giersch static inline unsigned int __parport_ip32_read_control(struct parport *p) 8988e75f744SArnaud Giersch { 8998e75f744SArnaud Giersch struct parport_ip32_private * const priv = p->physport->private_data; 9008e75f744SArnaud Giersch return priv->dcr_cache; /* use soft copy */ 9018e75f744SArnaud Giersch } 9028e75f744SArnaud Giersch 9038e75f744SArnaud Giersch /** 9048e75f744SArnaud Giersch * __parport_ip32_write_control - set new contents for the DCR register 9058e75f744SArnaud Giersch * @p: pointer to &struct parport 9068e75f744SArnaud Giersch * @c: new value to write 9078e75f744SArnaud Giersch */ 9088e75f744SArnaud Giersch static inline void __parport_ip32_write_control(struct parport *p, 9098e75f744SArnaud Giersch unsigned int c) 9108e75f744SArnaud Giersch { 9118e75f744SArnaud Giersch struct parport_ip32_private * const priv = p->physport->private_data; 9128e75f744SArnaud Giersch CHECK_EXTRA_BITS(p, c, priv->dcr_writable); 9138e75f744SArnaud Giersch c &= priv->dcr_writable; /* only writable bits */ 9148e75f744SArnaud Giersch writeb(c, priv->regs.dcr); 9158e75f744SArnaud Giersch priv->dcr_cache = c; /* update soft copy */ 9168e75f744SArnaud Giersch } 9178e75f744SArnaud Giersch 9188e75f744SArnaud Giersch /** 9198e75f744SArnaud Giersch * __parport_ip32_frob_control - change bits from the DCR register 9208e75f744SArnaud Giersch * @p: pointer to &struct parport 9218e75f744SArnaud Giersch * @mask: bit mask of bits to change 9228e75f744SArnaud Giersch * @val: new value for changed bits 9238e75f744SArnaud Giersch * 9248e75f744SArnaud Giersch * This is equivalent to read from the DCR, mask out the bits in @mask, 9258e75f744SArnaud Giersch * exclusive-or with the bits in @val, and write the result to the DCR. 9268e75f744SArnaud Giersch * Actually, the cached contents of the DCR is used. 9278e75f744SArnaud Giersch */ 9288e75f744SArnaud Giersch static inline void __parport_ip32_frob_control(struct parport *p, 9298e75f744SArnaud Giersch unsigned int mask, 9308e75f744SArnaud Giersch unsigned int val) 9318e75f744SArnaud Giersch { 9328e75f744SArnaud Giersch unsigned int c; 9338e75f744SArnaud Giersch c = (__parport_ip32_read_control(p) & ~mask) ^ val; 9348e75f744SArnaud Giersch __parport_ip32_write_control(p, c); 9358e75f744SArnaud Giersch } 9368e75f744SArnaud Giersch 9378e75f744SArnaud Giersch /** 9388e75f744SArnaud Giersch * parport_ip32_read_control - return cached contents of the DCR register 9398e75f744SArnaud Giersch * @p: pointer to &struct parport 9408e75f744SArnaud Giersch * 9418e75f744SArnaud Giersch * The return value is masked so as to only return the value of %DCR_STROBE, 9428e75f744SArnaud Giersch * %DCR_AUTOFD, %DCR_nINIT, and %DCR_SELECT. 9438e75f744SArnaud Giersch */ 9448e75f744SArnaud Giersch static inline unsigned char parport_ip32_read_control(struct parport *p) 9458e75f744SArnaud Giersch { 9468e75f744SArnaud Giersch const unsigned int rm = 9478e75f744SArnaud Giersch DCR_STROBE | DCR_AUTOFD | DCR_nINIT | DCR_SELECT; 9488e75f744SArnaud Giersch return __parport_ip32_read_control(p) & rm; 9498e75f744SArnaud Giersch } 9508e75f744SArnaud Giersch 9518e75f744SArnaud Giersch /** 9528e75f744SArnaud Giersch * parport_ip32_write_control - set new contents for the DCR register 9538e75f744SArnaud Giersch * @p: pointer to &struct parport 9548e75f744SArnaud Giersch * @c: new value to write 9558e75f744SArnaud Giersch * 9568e75f744SArnaud Giersch * The value is masked so as to only change the value of %DCR_STROBE, 9578e75f744SArnaud Giersch * %DCR_AUTOFD, %DCR_nINIT, and %DCR_SELECT. 9588e75f744SArnaud Giersch */ 9598e75f744SArnaud Giersch static inline void parport_ip32_write_control(struct parport *p, 9608e75f744SArnaud Giersch unsigned char c) 9618e75f744SArnaud Giersch { 9628e75f744SArnaud Giersch const unsigned int wm = 9638e75f744SArnaud Giersch DCR_STROBE | DCR_AUTOFD | DCR_nINIT | DCR_SELECT; 9648e75f744SArnaud Giersch CHECK_EXTRA_BITS(p, c, wm); 9658e75f744SArnaud Giersch __parport_ip32_frob_control(p, wm, c & wm); 9668e75f744SArnaud Giersch } 9678e75f744SArnaud Giersch 9688e75f744SArnaud Giersch /** 9698e75f744SArnaud Giersch * parport_ip32_frob_control - change bits from the DCR register 9708e75f744SArnaud Giersch * @p: pointer to &struct parport 9718e75f744SArnaud Giersch * @mask: bit mask of bits to change 9728e75f744SArnaud Giersch * @val: new value for changed bits 9738e75f744SArnaud Giersch * 9748e75f744SArnaud Giersch * This differs from __parport_ip32_frob_control() in that it only allows to 9758e75f744SArnaud Giersch * change the value of %DCR_STROBE, %DCR_AUTOFD, %DCR_nINIT, and %DCR_SELECT. 9768e75f744SArnaud Giersch */ 9778e75f744SArnaud Giersch static inline unsigned char parport_ip32_frob_control(struct parport *p, 9788e75f744SArnaud Giersch unsigned char mask, 9798e75f744SArnaud Giersch unsigned char val) 9808e75f744SArnaud Giersch { 9818e75f744SArnaud Giersch const unsigned int wm = 9828e75f744SArnaud Giersch DCR_STROBE | DCR_AUTOFD | DCR_nINIT | DCR_SELECT; 9838e75f744SArnaud Giersch CHECK_EXTRA_BITS(p, mask, wm); 9848e75f744SArnaud Giersch CHECK_EXTRA_BITS(p, val, wm); 9858e75f744SArnaud Giersch __parport_ip32_frob_control(p, mask & wm, val & wm); 9868e75f744SArnaud Giersch return parport_ip32_read_control(p); 9878e75f744SArnaud Giersch } 9888e75f744SArnaud Giersch 9898e75f744SArnaud Giersch /** 9908e75f744SArnaud Giersch * parport_ip32_disable_irq - disable interrupts on the rising edge of nACK 9918e75f744SArnaud Giersch * @p: pointer to &struct parport 9928e75f744SArnaud Giersch */ 9938e75f744SArnaud Giersch static inline void parport_ip32_disable_irq(struct parport *p) 9948e75f744SArnaud Giersch { 9958e75f744SArnaud Giersch __parport_ip32_frob_control(p, DCR_IRQ, 0); 9968e75f744SArnaud Giersch } 9978e75f744SArnaud Giersch 9988e75f744SArnaud Giersch /** 9998e75f744SArnaud Giersch * parport_ip32_enable_irq - enable interrupts on the rising edge of nACK 10008e75f744SArnaud Giersch * @p: pointer to &struct parport 10018e75f744SArnaud Giersch */ 10028e75f744SArnaud Giersch static inline void parport_ip32_enable_irq(struct parport *p) 10038e75f744SArnaud Giersch { 10048e75f744SArnaud Giersch __parport_ip32_frob_control(p, DCR_IRQ, DCR_IRQ); 10058e75f744SArnaud Giersch } 10068e75f744SArnaud Giersch 10078e75f744SArnaud Giersch /** 10088e75f744SArnaud Giersch * parport_ip32_data_forward - enable host-to-peripheral communications 10098e75f744SArnaud Giersch * @p: pointer to &struct parport 10108e75f744SArnaud Giersch * 10118e75f744SArnaud Giersch * Enable the data line drivers, for 8-bit host-to-peripheral communications. 10128e75f744SArnaud Giersch */ 10138e75f744SArnaud Giersch static inline void parport_ip32_data_forward(struct parport *p) 10148e75f744SArnaud Giersch { 10158e75f744SArnaud Giersch __parport_ip32_frob_control(p, DCR_DIR, 0); 10168e75f744SArnaud Giersch } 10178e75f744SArnaud Giersch 10188e75f744SArnaud Giersch /** 10198e75f744SArnaud Giersch * parport_ip32_data_reverse - enable peripheral-to-host communications 10208e75f744SArnaud Giersch * @p: pointer to &struct parport 10218e75f744SArnaud Giersch * 10228e75f744SArnaud Giersch * Place the data bus in a high impedance state, if @p->modes has the 10238e75f744SArnaud Giersch * PARPORT_MODE_TRISTATE bit set. 10248e75f744SArnaud Giersch */ 10258e75f744SArnaud Giersch static inline void parport_ip32_data_reverse(struct parport *p) 10268e75f744SArnaud Giersch { 10278e75f744SArnaud Giersch __parport_ip32_frob_control(p, DCR_DIR, DCR_DIR); 10288e75f744SArnaud Giersch } 10298e75f744SArnaud Giersch 10308e75f744SArnaud Giersch /** 10318e75f744SArnaud Giersch * parport_ip32_init_state - for core parport code 10328e75f744SArnaud Giersch * @dev: pointer to &struct pardevice 10338e75f744SArnaud Giersch * @s: pointer to &struct parport_state to initialize 10348e75f744SArnaud Giersch */ 10358e75f744SArnaud Giersch static void parport_ip32_init_state(struct pardevice *dev, 10368e75f744SArnaud Giersch struct parport_state *s) 10378e75f744SArnaud Giersch { 10388e75f744SArnaud Giersch s->u.ip32.dcr = DCR_SELECT | DCR_nINIT; 10398e75f744SArnaud Giersch s->u.ip32.ecr = ECR_MODE_PS2 | ECR_nERRINTR | ECR_SERVINTR; 10408e75f744SArnaud Giersch } 10418e75f744SArnaud Giersch 10428e75f744SArnaud Giersch /** 10438e75f744SArnaud Giersch * parport_ip32_save_state - for core parport code 10448e75f744SArnaud Giersch * @p: pointer to &struct parport 10458e75f744SArnaud Giersch * @s: pointer to &struct parport_state to save state to 10468e75f744SArnaud Giersch */ 10478e75f744SArnaud Giersch static void parport_ip32_save_state(struct parport *p, 10488e75f744SArnaud Giersch struct parport_state *s) 10498e75f744SArnaud Giersch { 10508e75f744SArnaud Giersch s->u.ip32.dcr = __parport_ip32_read_control(p); 10518e75f744SArnaud Giersch s->u.ip32.ecr = parport_ip32_read_econtrol(p); 10528e75f744SArnaud Giersch } 10538e75f744SArnaud Giersch 10548e75f744SArnaud Giersch /** 10558e75f744SArnaud Giersch * parport_ip32_restore_state - for core parport code 10568e75f744SArnaud Giersch * @p: pointer to &struct parport 10578e75f744SArnaud Giersch * @s: pointer to &struct parport_state to restore state from 10588e75f744SArnaud Giersch */ 10598e75f744SArnaud Giersch static void parport_ip32_restore_state(struct parport *p, 10608e75f744SArnaud Giersch struct parport_state *s) 10618e75f744SArnaud Giersch { 10628e75f744SArnaud Giersch parport_ip32_set_mode(p, s->u.ip32.ecr & ECR_MODE_MASK); 10638e75f744SArnaud Giersch parport_ip32_write_econtrol(p, s->u.ip32.ecr); 10648e75f744SArnaud Giersch __parport_ip32_write_control(p, s->u.ip32.dcr); 10658e75f744SArnaud Giersch } 10668e75f744SArnaud Giersch 10678e75f744SArnaud Giersch /*--- EPP mode functions -----------------------------------------------*/ 10688e75f744SArnaud Giersch 10698e75f744SArnaud Giersch /** 10708e75f744SArnaud Giersch * parport_ip32_clear_epp_timeout - clear Timeout bit in EPP mode 10718e75f744SArnaud Giersch * @p: pointer to &struct parport 10728e75f744SArnaud Giersch * 10738e75f744SArnaud Giersch * Returns 1 if the Timeout bit is clear, and 0 otherwise. 10748e75f744SArnaud Giersch */ 10758e75f744SArnaud Giersch static unsigned int parport_ip32_clear_epp_timeout(struct parport *p) 10768e75f744SArnaud Giersch { 10778e75f744SArnaud Giersch struct parport_ip32_private * const priv = p->physport->private_data; 10788e75f744SArnaud Giersch unsigned int cleared; 10798e75f744SArnaud Giersch 10808e75f744SArnaud Giersch if (!(parport_ip32_read_status(p) & DSR_TIMEOUT)) 10818e75f744SArnaud Giersch cleared = 1; 10828e75f744SArnaud Giersch else { 10838e75f744SArnaud Giersch unsigned int r; 10848e75f744SArnaud Giersch /* To clear timeout some chips require double read */ 10858e75f744SArnaud Giersch parport_ip32_read_status(p); 10868e75f744SArnaud Giersch r = parport_ip32_read_status(p); 10878e75f744SArnaud Giersch /* Some reset by writing 1 */ 10888e75f744SArnaud Giersch writeb(r | DSR_TIMEOUT, priv->regs.dsr); 10898e75f744SArnaud Giersch /* Others by writing 0 */ 10908e75f744SArnaud Giersch writeb(r & ~DSR_TIMEOUT, priv->regs.dsr); 10918e75f744SArnaud Giersch 10928e75f744SArnaud Giersch r = parport_ip32_read_status(p); 10938e75f744SArnaud Giersch cleared = !(r & DSR_TIMEOUT); 10948e75f744SArnaud Giersch } 10958e75f744SArnaud Giersch 10968e75f744SArnaud Giersch pr_trace(p, "(): %s", cleared ? "cleared" : "failed"); 10978e75f744SArnaud Giersch return cleared; 10988e75f744SArnaud Giersch } 10998e75f744SArnaud Giersch 11008e75f744SArnaud Giersch /** 11018e75f744SArnaud Giersch * parport_ip32_epp_read - generic EPP read function 11028e75f744SArnaud Giersch * @eppreg: I/O register to read from 11038e75f744SArnaud Giersch * @p: pointer to &struct parport 11048e75f744SArnaud Giersch * @buf: buffer to store read data 11058e75f744SArnaud Giersch * @len: length of buffer @buf 11068e75f744SArnaud Giersch * @flags: may be PARPORT_EPP_FAST 11078e75f744SArnaud Giersch */ 11088e75f744SArnaud Giersch static size_t parport_ip32_epp_read(void __iomem *eppreg, 11098e75f744SArnaud Giersch struct parport *p, void *buf, 11108e75f744SArnaud Giersch size_t len, int flags) 11118e75f744SArnaud Giersch { 11128e75f744SArnaud Giersch struct parport_ip32_private * const priv = p->physport->private_data; 11138e75f744SArnaud Giersch size_t got; 11148e75f744SArnaud Giersch parport_ip32_set_mode(p, ECR_MODE_EPP); 11158e75f744SArnaud Giersch parport_ip32_data_reverse(p); 11168e75f744SArnaud Giersch parport_ip32_write_control(p, DCR_nINIT); 11178e75f744SArnaud Giersch if ((flags & PARPORT_EPP_FAST) && (len > 1)) { 11188e75f744SArnaud Giersch readsb(eppreg, buf, len); 11198e75f744SArnaud Giersch if (readb(priv->regs.dsr) & DSR_TIMEOUT) { 11208e75f744SArnaud Giersch parport_ip32_clear_epp_timeout(p); 11218e75f744SArnaud Giersch return -EIO; 11228e75f744SArnaud Giersch } 11238e75f744SArnaud Giersch got = len; 11248e75f744SArnaud Giersch } else { 11258e75f744SArnaud Giersch u8 *bufp = buf; 11268e75f744SArnaud Giersch for (got = 0; got < len; got++) { 11278e75f744SArnaud Giersch *bufp++ = readb(eppreg); 11288e75f744SArnaud Giersch if (readb(priv->regs.dsr) & DSR_TIMEOUT) { 11298e75f744SArnaud Giersch parport_ip32_clear_epp_timeout(p); 11308e75f744SArnaud Giersch break; 11318e75f744SArnaud Giersch } 11328e75f744SArnaud Giersch } 11338e75f744SArnaud Giersch } 11348e75f744SArnaud Giersch parport_ip32_data_forward(p); 11358e75f744SArnaud Giersch parport_ip32_set_mode(p, ECR_MODE_PS2); 11368e75f744SArnaud Giersch return got; 11378e75f744SArnaud Giersch } 11388e75f744SArnaud Giersch 11398e75f744SArnaud Giersch /** 11408e75f744SArnaud Giersch * parport_ip32_epp_write - generic EPP write function 11418e75f744SArnaud Giersch * @eppreg: I/O register to write to 11428e75f744SArnaud Giersch * @p: pointer to &struct parport 11438e75f744SArnaud Giersch * @buf: buffer of data to write 11448e75f744SArnaud Giersch * @len: length of buffer @buf 11458e75f744SArnaud Giersch * @flags: may be PARPORT_EPP_FAST 11468e75f744SArnaud Giersch */ 11478e75f744SArnaud Giersch static size_t parport_ip32_epp_write(void __iomem *eppreg, 11488e75f744SArnaud Giersch struct parport *p, const void *buf, 11498e75f744SArnaud Giersch size_t len, int flags) 11508e75f744SArnaud Giersch { 11518e75f744SArnaud Giersch struct parport_ip32_private * const priv = p->physport->private_data; 11528e75f744SArnaud Giersch size_t written; 11538e75f744SArnaud Giersch parport_ip32_set_mode(p, ECR_MODE_EPP); 11548e75f744SArnaud Giersch parport_ip32_data_forward(p); 11558e75f744SArnaud Giersch parport_ip32_write_control(p, DCR_nINIT); 11568e75f744SArnaud Giersch if ((flags & PARPORT_EPP_FAST) && (len > 1)) { 11578e75f744SArnaud Giersch writesb(eppreg, buf, len); 11588e75f744SArnaud Giersch if (readb(priv->regs.dsr) & DSR_TIMEOUT) { 11598e75f744SArnaud Giersch parport_ip32_clear_epp_timeout(p); 11608e75f744SArnaud Giersch return -EIO; 11618e75f744SArnaud Giersch } 11628e75f744SArnaud Giersch written = len; 11638e75f744SArnaud Giersch } else { 11648e75f744SArnaud Giersch const u8 *bufp = buf; 11658e75f744SArnaud Giersch for (written = 0; written < len; written++) { 11668e75f744SArnaud Giersch writeb(*bufp++, eppreg); 11678e75f744SArnaud Giersch if (readb(priv->regs.dsr) & DSR_TIMEOUT) { 11688e75f744SArnaud Giersch parport_ip32_clear_epp_timeout(p); 11698e75f744SArnaud Giersch break; 11708e75f744SArnaud Giersch } 11718e75f744SArnaud Giersch } 11728e75f744SArnaud Giersch } 11738e75f744SArnaud Giersch parport_ip32_set_mode(p, ECR_MODE_PS2); 11748e75f744SArnaud Giersch return written; 11758e75f744SArnaud Giersch } 11768e75f744SArnaud Giersch 11778e75f744SArnaud Giersch /** 11788e75f744SArnaud Giersch * parport_ip32_epp_read_data - read a block of data in EPP mode 11798e75f744SArnaud Giersch * @p: pointer to &struct parport 11808e75f744SArnaud Giersch * @buf: buffer to store read data 11818e75f744SArnaud Giersch * @len: length of buffer @buf 11828e75f744SArnaud Giersch * @flags: may be PARPORT_EPP_FAST 11838e75f744SArnaud Giersch */ 11848e75f744SArnaud Giersch static size_t parport_ip32_epp_read_data(struct parport *p, void *buf, 11858e75f744SArnaud Giersch size_t len, int flags) 11868e75f744SArnaud Giersch { 11878e75f744SArnaud Giersch struct parport_ip32_private * const priv = p->physport->private_data; 11888e75f744SArnaud Giersch return parport_ip32_epp_read(priv->regs.eppData0, p, buf, len, flags); 11898e75f744SArnaud Giersch } 11908e75f744SArnaud Giersch 11918e75f744SArnaud Giersch /** 11928e75f744SArnaud Giersch * parport_ip32_epp_write_data - write a block of data in EPP mode 11938e75f744SArnaud Giersch * @p: pointer to &struct parport 11948e75f744SArnaud Giersch * @buf: buffer of data to write 11958e75f744SArnaud Giersch * @len: length of buffer @buf 11968e75f744SArnaud Giersch * @flags: may be PARPORT_EPP_FAST 11978e75f744SArnaud Giersch */ 11988e75f744SArnaud Giersch static size_t parport_ip32_epp_write_data(struct parport *p, const void *buf, 11998e75f744SArnaud Giersch size_t len, int flags) 12008e75f744SArnaud Giersch { 12018e75f744SArnaud Giersch struct parport_ip32_private * const priv = p->physport->private_data; 12028e75f744SArnaud Giersch return parport_ip32_epp_write(priv->regs.eppData0, p, buf, len, flags); 12038e75f744SArnaud Giersch } 12048e75f744SArnaud Giersch 12058e75f744SArnaud Giersch /** 12068e75f744SArnaud Giersch * parport_ip32_epp_read_addr - read a block of addresses in EPP mode 12078e75f744SArnaud Giersch * @p: pointer to &struct parport 12088e75f744SArnaud Giersch * @buf: buffer to store read data 12098e75f744SArnaud Giersch * @len: length of buffer @buf 12108e75f744SArnaud Giersch * @flags: may be PARPORT_EPP_FAST 12118e75f744SArnaud Giersch */ 12128e75f744SArnaud Giersch static size_t parport_ip32_epp_read_addr(struct parport *p, void *buf, 12138e75f744SArnaud Giersch size_t len, int flags) 12148e75f744SArnaud Giersch { 12158e75f744SArnaud Giersch struct parport_ip32_private * const priv = p->physport->private_data; 12168e75f744SArnaud Giersch return parport_ip32_epp_read(priv->regs.eppAddr, p, buf, len, flags); 12178e75f744SArnaud Giersch } 12188e75f744SArnaud Giersch 12198e75f744SArnaud Giersch /** 12208e75f744SArnaud Giersch * parport_ip32_epp_write_addr - write a block of addresses in EPP mode 12218e75f744SArnaud Giersch * @p: pointer to &struct parport 12228e75f744SArnaud Giersch * @buf: buffer of data to write 12238e75f744SArnaud Giersch * @len: length of buffer @buf 12248e75f744SArnaud Giersch * @flags: may be PARPORT_EPP_FAST 12258e75f744SArnaud Giersch */ 12268e75f744SArnaud Giersch static size_t parport_ip32_epp_write_addr(struct parport *p, const void *buf, 12278e75f744SArnaud Giersch size_t len, int flags) 12288e75f744SArnaud Giersch { 12298e75f744SArnaud Giersch struct parport_ip32_private * const priv = p->physport->private_data; 12308e75f744SArnaud Giersch return parport_ip32_epp_write(priv->regs.eppAddr, p, buf, len, flags); 12318e75f744SArnaud Giersch } 12328e75f744SArnaud Giersch 12338e75f744SArnaud Giersch /*--- ECP mode functions (FIFO) ----------------------------------------*/ 12348e75f744SArnaud Giersch 12358e75f744SArnaud Giersch /** 12368e75f744SArnaud Giersch * parport_ip32_fifo_wait_break - check if the waiting function should return 12378e75f744SArnaud Giersch * @p: pointer to &struct parport 12388e75f744SArnaud Giersch * @expire: timeout expiring date, in jiffies 12398e75f744SArnaud Giersch * 12408e75f744SArnaud Giersch * parport_ip32_fifo_wait_break() checks if the waiting function should return 12418e75f744SArnaud Giersch * immediately or not. The break conditions are: 12428e75f744SArnaud Giersch * - expired timeout; 12438e75f744SArnaud Giersch * - a pending signal; 12448e75f744SArnaud Giersch * - nFault asserted low. 12458e75f744SArnaud Giersch * This function also calls cond_resched(). 12468e75f744SArnaud Giersch */ 12478e75f744SArnaud Giersch static unsigned int parport_ip32_fifo_wait_break(struct parport *p, 12488e75f744SArnaud Giersch unsigned long expire) 12498e75f744SArnaud Giersch { 12508e75f744SArnaud Giersch cond_resched(); 12518e75f744SArnaud Giersch if (time_after(jiffies, expire)) { 12528e75f744SArnaud Giersch pr_debug1(PPIP32 "%s: FIFO write timed out\n", p->name); 12538e75f744SArnaud Giersch return 1; 12548e75f744SArnaud Giersch } 12558e75f744SArnaud Giersch if (signal_pending(current)) { 12568e75f744SArnaud Giersch pr_debug1(PPIP32 "%s: Signal pending\n", p->name); 12578e75f744SArnaud Giersch return 1; 12588e75f744SArnaud Giersch } 12598e75f744SArnaud Giersch if (!(parport_ip32_read_status(p) & DSR_nFAULT)) { 12608e75f744SArnaud Giersch pr_debug1(PPIP32 "%s: nFault asserted low\n", p->name); 12618e75f744SArnaud Giersch return 1; 12628e75f744SArnaud Giersch } 12638e75f744SArnaud Giersch return 0; 12648e75f744SArnaud Giersch } 12658e75f744SArnaud Giersch 12668e75f744SArnaud Giersch /** 12678e75f744SArnaud Giersch * parport_ip32_fwp_wait_polling - wait for FIFO to empty (polling) 12688e75f744SArnaud Giersch * @p: pointer to &struct parport 12698e75f744SArnaud Giersch * 12708e75f744SArnaud Giersch * Returns the number of bytes that can safely be written in the FIFO. A 12718e75f744SArnaud Giersch * return value of zero means that the calling function should terminate as 12728e75f744SArnaud Giersch * fast as possible. 12738e75f744SArnaud Giersch */ 12748e75f744SArnaud Giersch static unsigned int parport_ip32_fwp_wait_polling(struct parport *p) 12758e75f744SArnaud Giersch { 12768e75f744SArnaud Giersch struct parport_ip32_private * const priv = p->physport->private_data; 12778e75f744SArnaud Giersch struct parport * const physport = p->physport; 12788e75f744SArnaud Giersch unsigned long expire; 12798e75f744SArnaud Giersch unsigned int count; 12808e75f744SArnaud Giersch unsigned int ecr; 12818e75f744SArnaud Giersch 12828e75f744SArnaud Giersch expire = jiffies + physport->cad->timeout; 12838e75f744SArnaud Giersch count = 0; 12848e75f744SArnaud Giersch while (1) { 12858e75f744SArnaud Giersch if (parport_ip32_fifo_wait_break(p, expire)) 12868e75f744SArnaud Giersch break; 12878e75f744SArnaud Giersch 12888e75f744SArnaud Giersch /* Check FIFO state. We do nothing when the FIFO is nor full, 12898e75f744SArnaud Giersch * nor empty. It appears that the FIFO full bit is not always 12908e75f744SArnaud Giersch * reliable, the FIFO state is sometimes wrongly reported, and 12918e75f744SArnaud Giersch * the chip gets confused if we give it another byte. */ 12928e75f744SArnaud Giersch ecr = parport_ip32_read_econtrol(p); 12938e75f744SArnaud Giersch if (ecr & ECR_F_EMPTY) { 12948e75f744SArnaud Giersch /* FIFO is empty, fill it up */ 12958e75f744SArnaud Giersch count = priv->fifo_depth; 12968e75f744SArnaud Giersch break; 12978e75f744SArnaud Giersch } 12988e75f744SArnaud Giersch 12998e75f744SArnaud Giersch /* Wait a moment... */ 13008e75f744SArnaud Giersch udelay(FIFO_POLLING_INTERVAL); 13018e75f744SArnaud Giersch } /* while (1) */ 13028e75f744SArnaud Giersch 13038e75f744SArnaud Giersch return count; 13048e75f744SArnaud Giersch } 13058e75f744SArnaud Giersch 13068e75f744SArnaud Giersch /** 13078e75f744SArnaud Giersch * parport_ip32_fwp_wait_interrupt - wait for FIFO to empty (interrupt-driven) 13088e75f744SArnaud Giersch * @p: pointer to &struct parport 13098e75f744SArnaud Giersch * 13108e75f744SArnaud Giersch * Returns the number of bytes that can safely be written in the FIFO. A 13118e75f744SArnaud Giersch * return value of zero means that the calling function should terminate as 13128e75f744SArnaud Giersch * fast as possible. 13138e75f744SArnaud Giersch */ 13148e75f744SArnaud Giersch static unsigned int parport_ip32_fwp_wait_interrupt(struct parport *p) 13158e75f744SArnaud Giersch { 13168e75f744SArnaud Giersch static unsigned int lost_interrupt = 0; 13178e75f744SArnaud Giersch struct parport_ip32_private * const priv = p->physport->private_data; 13188e75f744SArnaud Giersch struct parport * const physport = p->physport; 13198e75f744SArnaud Giersch unsigned long nfault_timeout; 13208e75f744SArnaud Giersch unsigned long expire; 13218e75f744SArnaud Giersch unsigned int count; 13228e75f744SArnaud Giersch unsigned int ecr; 13238e75f744SArnaud Giersch 13248e75f744SArnaud Giersch nfault_timeout = min((unsigned long)physport->cad->timeout, 13258e75f744SArnaud Giersch msecs_to_jiffies(FIFO_NFAULT_TIMEOUT)); 13268e75f744SArnaud Giersch expire = jiffies + physport->cad->timeout; 13278e75f744SArnaud Giersch count = 0; 13288e75f744SArnaud Giersch while (1) { 13298e75f744SArnaud Giersch if (parport_ip32_fifo_wait_break(p, expire)) 13308e75f744SArnaud Giersch break; 13318e75f744SArnaud Giersch 13328e75f744SArnaud Giersch /* Initialize mutex used to take interrupts into account */ 13338e75f744SArnaud Giersch INIT_COMPLETION(priv->irq_complete); 13348e75f744SArnaud Giersch 13358e75f744SArnaud Giersch /* Enable serviceIntr */ 13368e75f744SArnaud Giersch parport_ip32_frob_econtrol(p, ECR_SERVINTR, 0); 13378e75f744SArnaud Giersch 13388e75f744SArnaud Giersch /* Enabling serviceIntr while the FIFO is empty does not 13398e75f744SArnaud Giersch * always generate an interrupt, so check for emptiness 13408e75f744SArnaud Giersch * now. */ 13418e75f744SArnaud Giersch ecr = parport_ip32_read_econtrol(p); 13428e75f744SArnaud Giersch if (!(ecr & ECR_F_EMPTY)) { 13438e75f744SArnaud Giersch /* FIFO is not empty: wait for an interrupt or a 13448e75f744SArnaud Giersch * timeout to occur */ 13458e75f744SArnaud Giersch wait_for_completion_interruptible_timeout( 13468e75f744SArnaud Giersch &priv->irq_complete, nfault_timeout); 13478e75f744SArnaud Giersch ecr = parport_ip32_read_econtrol(p); 13488e75f744SArnaud Giersch if ((ecr & ECR_F_EMPTY) && !(ecr & ECR_SERVINTR) 13498e75f744SArnaud Giersch && !lost_interrupt) { 13508e75f744SArnaud Giersch printk(KERN_WARNING PPIP32 13518e75f744SArnaud Giersch "%s: lost interrupt in %s\n", 13528e75f744SArnaud Giersch p->name, __func__); 13538e75f744SArnaud Giersch lost_interrupt = 1; 13548e75f744SArnaud Giersch } 13558e75f744SArnaud Giersch } 13568e75f744SArnaud Giersch 13578e75f744SArnaud Giersch /* Disable serviceIntr */ 13588e75f744SArnaud Giersch parport_ip32_frob_econtrol(p, ECR_SERVINTR, ECR_SERVINTR); 13598e75f744SArnaud Giersch 13608e75f744SArnaud Giersch /* Check FIFO state */ 13618e75f744SArnaud Giersch if (ecr & ECR_F_EMPTY) { 13628e75f744SArnaud Giersch /* FIFO is empty, fill it up */ 13638e75f744SArnaud Giersch count = priv->fifo_depth; 13648e75f744SArnaud Giersch break; 13658e75f744SArnaud Giersch } else if (ecr & ECR_SERVINTR) { 13668e75f744SArnaud Giersch /* FIFO is not empty, but we know that can safely push 13678e75f744SArnaud Giersch * writeIntrThreshold bytes into it */ 13688e75f744SArnaud Giersch count = priv->writeIntrThreshold; 13698e75f744SArnaud Giersch break; 13708e75f744SArnaud Giersch } 13718e75f744SArnaud Giersch /* FIFO is not empty, and we did not get any interrupt. 13728e75f744SArnaud Giersch * Either it's time to check for nFault, or a signal is 13738e75f744SArnaud Giersch * pending. This is verified in 13748e75f744SArnaud Giersch * parport_ip32_fifo_wait_break(), so we continue the loop. */ 13758e75f744SArnaud Giersch } /* while (1) */ 13768e75f744SArnaud Giersch 13778e75f744SArnaud Giersch return count; 13788e75f744SArnaud Giersch } 13798e75f744SArnaud Giersch 13808e75f744SArnaud Giersch /** 13818e75f744SArnaud Giersch * parport_ip32_fifo_write_block_pio - write a block of data (PIO mode) 13828e75f744SArnaud Giersch * @p: pointer to &struct parport 13838e75f744SArnaud Giersch * @buf: buffer of data to write 13848e75f744SArnaud Giersch * @len: length of buffer @buf 13858e75f744SArnaud Giersch * 13868e75f744SArnaud Giersch * Uses PIO to write the contents of the buffer @buf into the parallel port 13878e75f744SArnaud Giersch * FIFO. Returns the number of bytes that were actually written. It can work 13888e75f744SArnaud Giersch * with or without the help of interrupts. The parallel port must be 13898e75f744SArnaud Giersch * correctly initialized before calling parport_ip32_fifo_write_block_pio(). 13908e75f744SArnaud Giersch */ 13918e75f744SArnaud Giersch static size_t parport_ip32_fifo_write_block_pio(struct parport *p, 13928e75f744SArnaud Giersch const void *buf, size_t len) 13938e75f744SArnaud Giersch { 13948e75f744SArnaud Giersch struct parport_ip32_private * const priv = p->physport->private_data; 13958e75f744SArnaud Giersch const u8 *bufp = buf; 13968e75f744SArnaud Giersch size_t left = len; 13978e75f744SArnaud Giersch 13988e75f744SArnaud Giersch priv->irq_mode = PARPORT_IP32_IRQ_HERE; 13998e75f744SArnaud Giersch 14008e75f744SArnaud Giersch while (left > 0) { 14018e75f744SArnaud Giersch unsigned int count; 14028e75f744SArnaud Giersch 14038e75f744SArnaud Giersch count = (p->irq == PARPORT_IRQ_NONE) ? 14048e75f744SArnaud Giersch parport_ip32_fwp_wait_polling(p) : 14058e75f744SArnaud Giersch parport_ip32_fwp_wait_interrupt(p); 14068e75f744SArnaud Giersch if (count == 0) 14078e75f744SArnaud Giersch break; /* Transmission should be stopped */ 14088e75f744SArnaud Giersch if (count > left) 14098e75f744SArnaud Giersch count = left; 14108e75f744SArnaud Giersch if (count == 1) { 14118e75f744SArnaud Giersch writeb(*bufp, priv->regs.fifo); 14128e75f744SArnaud Giersch bufp++, left--; 14138e75f744SArnaud Giersch } else { 14148e75f744SArnaud Giersch writesb(priv->regs.fifo, bufp, count); 14158e75f744SArnaud Giersch bufp += count, left -= count; 14168e75f744SArnaud Giersch } 14178e75f744SArnaud Giersch } 14188e75f744SArnaud Giersch 14198e75f744SArnaud Giersch priv->irq_mode = PARPORT_IP32_IRQ_FWD; 14208e75f744SArnaud Giersch 14218e75f744SArnaud Giersch return len - left; 14228e75f744SArnaud Giersch } 14238e75f744SArnaud Giersch 14248e75f744SArnaud Giersch /** 14258e75f744SArnaud Giersch * parport_ip32_fifo_write_block_dma - write a block of data (DMA mode) 14268e75f744SArnaud Giersch * @p: pointer to &struct parport 14278e75f744SArnaud Giersch * @buf: buffer of data to write 14288e75f744SArnaud Giersch * @len: length of buffer @buf 14298e75f744SArnaud Giersch * 14308e75f744SArnaud Giersch * Uses DMA to write the contents of the buffer @buf into the parallel port 14318e75f744SArnaud Giersch * FIFO. Returns the number of bytes that were actually written. The 14328e75f744SArnaud Giersch * parallel port must be correctly initialized before calling 14338e75f744SArnaud Giersch * parport_ip32_fifo_write_block_dma(). 14348e75f744SArnaud Giersch */ 14358e75f744SArnaud Giersch static size_t parport_ip32_fifo_write_block_dma(struct parport *p, 14368e75f744SArnaud Giersch const void *buf, size_t len) 14378e75f744SArnaud Giersch { 14388e75f744SArnaud Giersch struct parport_ip32_private * const priv = p->physport->private_data; 14398e75f744SArnaud Giersch struct parport * const physport = p->physport; 14408e75f744SArnaud Giersch unsigned long nfault_timeout; 14418e75f744SArnaud Giersch unsigned long expire; 14428e75f744SArnaud Giersch size_t written; 14438e75f744SArnaud Giersch unsigned int ecr; 14448e75f744SArnaud Giersch 14458e75f744SArnaud Giersch priv->irq_mode = PARPORT_IP32_IRQ_HERE; 14468e75f744SArnaud Giersch 14478e75f744SArnaud Giersch parport_ip32_dma_start(DMA_TO_DEVICE, (void *)buf, len); 14488e75f744SArnaud Giersch INIT_COMPLETION(priv->irq_complete); 14498e75f744SArnaud Giersch parport_ip32_frob_econtrol(p, ECR_DMAEN | ECR_SERVINTR, ECR_DMAEN); 14508e75f744SArnaud Giersch 14518e75f744SArnaud Giersch nfault_timeout = min((unsigned long)physport->cad->timeout, 14528e75f744SArnaud Giersch msecs_to_jiffies(FIFO_NFAULT_TIMEOUT)); 14538e75f744SArnaud Giersch expire = jiffies + physport->cad->timeout; 14548e75f744SArnaud Giersch while (1) { 14558e75f744SArnaud Giersch if (parport_ip32_fifo_wait_break(p, expire)) 14568e75f744SArnaud Giersch break; 14578e75f744SArnaud Giersch wait_for_completion_interruptible_timeout(&priv->irq_complete, 14588e75f744SArnaud Giersch nfault_timeout); 14598e75f744SArnaud Giersch ecr = parport_ip32_read_econtrol(p); 14608e75f744SArnaud Giersch if (ecr & ECR_SERVINTR) 14618e75f744SArnaud Giersch break; /* DMA transfer just finished */ 14628e75f744SArnaud Giersch } 14638e75f744SArnaud Giersch parport_ip32_dma_stop(); 14648e75f744SArnaud Giersch written = len - parport_ip32_dma_get_residue(); 14658e75f744SArnaud Giersch 14668e75f744SArnaud Giersch priv->irq_mode = PARPORT_IP32_IRQ_FWD; 14678e75f744SArnaud Giersch 14688e75f744SArnaud Giersch return written; 14698e75f744SArnaud Giersch } 14708e75f744SArnaud Giersch 14718e75f744SArnaud Giersch /** 14728e75f744SArnaud Giersch * parport_ip32_fifo_write_block - write a block of data 14738e75f744SArnaud Giersch * @p: pointer to &struct parport 14748e75f744SArnaud Giersch * @buf: buffer of data to write 14758e75f744SArnaud Giersch * @len: length of buffer @buf 14768e75f744SArnaud Giersch * 14778e75f744SArnaud Giersch * Uses PIO or DMA to write the contents of the buffer @buf into the parallel 14788e75f744SArnaud Giersch * p FIFO. Returns the number of bytes that were actually written. 14798e75f744SArnaud Giersch */ 14808e75f744SArnaud Giersch static size_t parport_ip32_fifo_write_block(struct parport *p, 14818e75f744SArnaud Giersch const void *buf, size_t len) 14828e75f744SArnaud Giersch { 14838e75f744SArnaud Giersch size_t written = 0; 14848e75f744SArnaud Giersch if (len) 14858e75f744SArnaud Giersch /* FIXME - Maybe some threshold value should be set for @len 14868e75f744SArnaud Giersch * under which we revert to PIO mode? */ 14878e75f744SArnaud Giersch written = (p->modes & PARPORT_MODE_DMA) ? 14888e75f744SArnaud Giersch parport_ip32_fifo_write_block_dma(p, buf, len) : 14898e75f744SArnaud Giersch parport_ip32_fifo_write_block_pio(p, buf, len); 14908e75f744SArnaud Giersch return written; 14918e75f744SArnaud Giersch } 14928e75f744SArnaud Giersch 14938e75f744SArnaud Giersch /** 14948e75f744SArnaud Giersch * parport_ip32_drain_fifo - wait for FIFO to empty 14958e75f744SArnaud Giersch * @p: pointer to &struct parport 14968e75f744SArnaud Giersch * @timeout: timeout, in jiffies 14978e75f744SArnaud Giersch * 14988e75f744SArnaud Giersch * This function waits for FIFO to empty. It returns 1 when FIFO is empty, or 14998e75f744SArnaud Giersch * 0 if the timeout @timeout is reached before, or if a signal is pending. 15008e75f744SArnaud Giersch */ 15018e75f744SArnaud Giersch static unsigned int parport_ip32_drain_fifo(struct parport *p, 15028e75f744SArnaud Giersch unsigned long timeout) 15038e75f744SArnaud Giersch { 15048e75f744SArnaud Giersch unsigned long expire = jiffies + timeout; 15058e75f744SArnaud Giersch unsigned int polling_interval; 15068e75f744SArnaud Giersch unsigned int counter; 15078e75f744SArnaud Giersch 15088e75f744SArnaud Giersch /* Busy wait for approx. 200us */ 15098e75f744SArnaud Giersch for (counter = 0; counter < 40; counter++) { 15108e75f744SArnaud Giersch if (parport_ip32_read_econtrol(p) & ECR_F_EMPTY) 15118e75f744SArnaud Giersch break; 15128e75f744SArnaud Giersch if (time_after(jiffies, expire)) 15138e75f744SArnaud Giersch break; 15148e75f744SArnaud Giersch if (signal_pending(current)) 15158e75f744SArnaud Giersch break; 15168e75f744SArnaud Giersch udelay(5); 15178e75f744SArnaud Giersch } 15188e75f744SArnaud Giersch /* Poll slowly. Polling interval starts with 1 millisecond, and is 15198e75f744SArnaud Giersch * increased exponentially until 128. */ 15208e75f744SArnaud Giersch polling_interval = 1; /* msecs */ 15218e75f744SArnaud Giersch while (!(parport_ip32_read_econtrol(p) & ECR_F_EMPTY)) { 15228e75f744SArnaud Giersch if (time_after_eq(jiffies, expire)) 15238e75f744SArnaud Giersch break; 15248e75f744SArnaud Giersch msleep_interruptible(polling_interval); 15258e75f744SArnaud Giersch if (signal_pending(current)) 15268e75f744SArnaud Giersch break; 15278e75f744SArnaud Giersch if (polling_interval < 128) 15288e75f744SArnaud Giersch polling_interval *= 2; 15298e75f744SArnaud Giersch } 15308e75f744SArnaud Giersch 15318e75f744SArnaud Giersch return !!(parport_ip32_read_econtrol(p) & ECR_F_EMPTY); 15328e75f744SArnaud Giersch } 15338e75f744SArnaud Giersch 15348e75f744SArnaud Giersch /** 15358e75f744SArnaud Giersch * parport_ip32_get_fifo_residue - reset FIFO 15368e75f744SArnaud Giersch * @p: pointer to &struct parport 15378e75f744SArnaud Giersch * @mode: current operation mode (ECR_MODE_PPF or ECR_MODE_ECP) 15388e75f744SArnaud Giersch * 15398e75f744SArnaud Giersch * This function resets FIFO, and returns the number of bytes remaining in it. 15408e75f744SArnaud Giersch */ 15418e75f744SArnaud Giersch static unsigned int parport_ip32_get_fifo_residue(struct parport *p, 15428e75f744SArnaud Giersch unsigned int mode) 15438e75f744SArnaud Giersch { 15448e75f744SArnaud Giersch struct parport_ip32_private * const priv = p->physport->private_data; 15458e75f744SArnaud Giersch unsigned int residue; 15468e75f744SArnaud Giersch unsigned int cnfga; 15478e75f744SArnaud Giersch 15488e75f744SArnaud Giersch /* FIXME - We are missing one byte if the printer is off-line. I 15498e75f744SArnaud Giersch * don't know how to detect this. It looks that the full bit is not 15508e75f744SArnaud Giersch * always reliable. For the moment, the problem is avoided in most 15518e75f744SArnaud Giersch * cases by testing for BUSY in parport_ip32_compat_write_data(). 15528e75f744SArnaud Giersch */ 15538e75f744SArnaud Giersch if (parport_ip32_read_econtrol(p) & ECR_F_EMPTY) 15548e75f744SArnaud Giersch residue = 0; 15558e75f744SArnaud Giersch else { 15568e75f744SArnaud Giersch pr_debug1(PPIP32 "%s: FIFO is stuck\n", p->name); 15578e75f744SArnaud Giersch 15588e75f744SArnaud Giersch /* Stop all transfers. 15598e75f744SArnaud Giersch * 15608e75f744SArnaud Giersch * Microsoft's document instructs to drive DCR_STROBE to 0, 15618e75f744SArnaud Giersch * but it doesn't work (at least in Compatibility mode, not 15628e75f744SArnaud Giersch * tested in ECP mode). Switching directly to Test mode (as 15638e75f744SArnaud Giersch * in parport_pc) is not an option: it does confuse the port, 15648e75f744SArnaud Giersch * ECP service interrupts are no more working after that. A 15658e75f744SArnaud Giersch * hard reset is then needed to revert to a sane state. 15668e75f744SArnaud Giersch * 15678e75f744SArnaud Giersch * Let's hope that the FIFO is really stuck and that the 15688e75f744SArnaud Giersch * peripheral doesn't wake up now. 15698e75f744SArnaud Giersch */ 15708e75f744SArnaud Giersch parport_ip32_frob_control(p, DCR_STROBE, 0); 15718e75f744SArnaud Giersch 15728e75f744SArnaud Giersch /* Fill up FIFO */ 15738e75f744SArnaud Giersch for (residue = priv->fifo_depth; residue > 0; residue--) { 15748e75f744SArnaud Giersch if (parport_ip32_read_econtrol(p) & ECR_F_FULL) 15758e75f744SArnaud Giersch break; 15768e75f744SArnaud Giersch writeb(0x00, priv->regs.fifo); 15778e75f744SArnaud Giersch } 15788e75f744SArnaud Giersch } 15798e75f744SArnaud Giersch if (residue) 15808e75f744SArnaud Giersch pr_debug1(PPIP32 "%s: %d PWord%s left in FIFO\n", 15818e75f744SArnaud Giersch p->name, residue, 15828e75f744SArnaud Giersch (residue == 1) ? " was" : "s were"); 15838e75f744SArnaud Giersch 15848e75f744SArnaud Giersch /* Now reset the FIFO */ 15858e75f744SArnaud Giersch parport_ip32_set_mode(p, ECR_MODE_PS2); 15868e75f744SArnaud Giersch 15878e75f744SArnaud Giersch /* Host recovery for ECP mode */ 15888e75f744SArnaud Giersch if (mode == ECR_MODE_ECP) { 15898e75f744SArnaud Giersch parport_ip32_data_reverse(p); 15908e75f744SArnaud Giersch parport_ip32_frob_control(p, DCR_nINIT, 0); 15918e75f744SArnaud Giersch if (parport_wait_peripheral(p, DSR_PERROR, 0)) 15928e75f744SArnaud Giersch pr_debug1(PPIP32 "%s: PEerror timeout 1 in %s\n", 15938e75f744SArnaud Giersch p->name, __func__); 15948e75f744SArnaud Giersch parport_ip32_frob_control(p, DCR_STROBE, DCR_STROBE); 15958e75f744SArnaud Giersch parport_ip32_frob_control(p, DCR_nINIT, DCR_nINIT); 15968e75f744SArnaud Giersch if (parport_wait_peripheral(p, DSR_PERROR, DSR_PERROR)) 15978e75f744SArnaud Giersch pr_debug1(PPIP32 "%s: PEerror timeout 2 in %s\n", 15988e75f744SArnaud Giersch p->name, __func__); 15998e75f744SArnaud Giersch } 16008e75f744SArnaud Giersch 16018e75f744SArnaud Giersch /* Adjust residue if needed */ 16028e75f744SArnaud Giersch parport_ip32_set_mode(p, ECR_MODE_CFG); 16038e75f744SArnaud Giersch cnfga = readb(priv->regs.cnfgA); 16048e75f744SArnaud Giersch if (!(cnfga & CNFGA_nBYTEINTRANS)) { 16058e75f744SArnaud Giersch pr_debug1(PPIP32 "%s: cnfgA contains 0x%02x\n", 16068e75f744SArnaud Giersch p->name, cnfga); 16078e75f744SArnaud Giersch pr_debug1(PPIP32 "%s: Accounting for extra byte\n", 16088e75f744SArnaud Giersch p->name); 16098e75f744SArnaud Giersch residue++; 16108e75f744SArnaud Giersch } 16118e75f744SArnaud Giersch 16128e75f744SArnaud Giersch /* Don't care about partial PWords since we do not support 16138e75f744SArnaud Giersch * PWord != 1 byte. */ 16148e75f744SArnaud Giersch 16158e75f744SArnaud Giersch /* Back to forward PS2 mode. */ 16168e75f744SArnaud Giersch parport_ip32_set_mode(p, ECR_MODE_PS2); 16178e75f744SArnaud Giersch parport_ip32_data_forward(p); 16188e75f744SArnaud Giersch 16198e75f744SArnaud Giersch return residue; 16208e75f744SArnaud Giersch } 16218e75f744SArnaud Giersch 16228e75f744SArnaud Giersch /** 16238e75f744SArnaud Giersch * parport_ip32_compat_write_data - write a block of data in SPP mode 16248e75f744SArnaud Giersch * @p: pointer to &struct parport 16258e75f744SArnaud Giersch * @buf: buffer of data to write 16268e75f744SArnaud Giersch * @len: length of buffer @buf 16278e75f744SArnaud Giersch * @flags: ignored 16288e75f744SArnaud Giersch */ 16298e75f744SArnaud Giersch static size_t parport_ip32_compat_write_data(struct parport *p, 16308e75f744SArnaud Giersch const void *buf, size_t len, 16318e75f744SArnaud Giersch int flags) 16328e75f744SArnaud Giersch { 16338e75f744SArnaud Giersch static unsigned int ready_before = 1; 16348e75f744SArnaud Giersch struct parport_ip32_private * const priv = p->physport->private_data; 16358e75f744SArnaud Giersch struct parport * const physport = p->physport; 16368e75f744SArnaud Giersch size_t written = 0; 16378e75f744SArnaud Giersch 16388e75f744SArnaud Giersch /* Special case: a timeout of zero means we cannot call schedule(). 16398e75f744SArnaud Giersch * Also if O_NONBLOCK is set then use the default implementation. */ 16408e75f744SArnaud Giersch if (physport->cad->timeout <= PARPORT_INACTIVITY_O_NONBLOCK) 16418e75f744SArnaud Giersch return parport_ieee1284_write_compat(p, buf, len, flags); 16428e75f744SArnaud Giersch 16438e75f744SArnaud Giersch /* Reset FIFO, go in forward mode, and disable ackIntEn */ 16448e75f744SArnaud Giersch parport_ip32_set_mode(p, ECR_MODE_PS2); 16458e75f744SArnaud Giersch parport_ip32_write_control(p, DCR_SELECT | DCR_nINIT); 16468e75f744SArnaud Giersch parport_ip32_data_forward(p); 16478e75f744SArnaud Giersch parport_ip32_disable_irq(p); 16488e75f744SArnaud Giersch parport_ip32_set_mode(p, ECR_MODE_PPF); 16498e75f744SArnaud Giersch physport->ieee1284.phase = IEEE1284_PH_FWD_DATA; 16508e75f744SArnaud Giersch 16518e75f744SArnaud Giersch /* Wait for peripheral to become ready */ 16528e75f744SArnaud Giersch if (parport_wait_peripheral(p, DSR_nBUSY | DSR_nFAULT, 16538e75f744SArnaud Giersch DSR_nBUSY | DSR_nFAULT)) { 16548e75f744SArnaud Giersch /* Avoid to flood the logs */ 16558e75f744SArnaud Giersch if (ready_before) 16568e75f744SArnaud Giersch printk(KERN_INFO PPIP32 "%s: not ready in %s\n", 16578e75f744SArnaud Giersch p->name, __func__); 16588e75f744SArnaud Giersch ready_before = 0; 16598e75f744SArnaud Giersch goto stop; 16608e75f744SArnaud Giersch } 16618e75f744SArnaud Giersch ready_before = 1; 16628e75f744SArnaud Giersch 16638e75f744SArnaud Giersch written = parport_ip32_fifo_write_block(p, buf, len); 16648e75f744SArnaud Giersch 16658e75f744SArnaud Giersch /* Wait FIFO to empty. Timeout is proportional to FIFO_depth. */ 16668e75f744SArnaud Giersch parport_ip32_drain_fifo(p, physport->cad->timeout * priv->fifo_depth); 16678e75f744SArnaud Giersch 16688e75f744SArnaud Giersch /* Check for a potential residue */ 16698e75f744SArnaud Giersch written -= parport_ip32_get_fifo_residue(p, ECR_MODE_PPF); 16708e75f744SArnaud Giersch 16718e75f744SArnaud Giersch /* Then, wait for BUSY to get low. */ 16728e75f744SArnaud Giersch if (parport_wait_peripheral(p, DSR_nBUSY, DSR_nBUSY)) 16738e75f744SArnaud Giersch printk(KERN_DEBUG PPIP32 "%s: BUSY timeout in %s\n", 16748e75f744SArnaud Giersch p->name, __func__); 16758e75f744SArnaud Giersch 16768e75f744SArnaud Giersch stop: 16778e75f744SArnaud Giersch /* Reset FIFO */ 16788e75f744SArnaud Giersch parport_ip32_set_mode(p, ECR_MODE_PS2); 16798e75f744SArnaud Giersch physport->ieee1284.phase = IEEE1284_PH_FWD_IDLE; 16808e75f744SArnaud Giersch 16818e75f744SArnaud Giersch return written; 16828e75f744SArnaud Giersch } 16838e75f744SArnaud Giersch 16848e75f744SArnaud Giersch /* 16858e75f744SArnaud Giersch * FIXME - Insert here parport_ip32_ecp_read_data(). 16868e75f744SArnaud Giersch */ 16878e75f744SArnaud Giersch 16888e75f744SArnaud Giersch /** 16898e75f744SArnaud Giersch * parport_ip32_ecp_write_data - write a block of data in ECP mode 16908e75f744SArnaud Giersch * @p: pointer to &struct parport 16918e75f744SArnaud Giersch * @buf: buffer of data to write 16928e75f744SArnaud Giersch * @len: length of buffer @buf 16938e75f744SArnaud Giersch * @flags: ignored 16948e75f744SArnaud Giersch */ 16958e75f744SArnaud Giersch static size_t parport_ip32_ecp_write_data(struct parport *p, 16968e75f744SArnaud Giersch const void *buf, size_t len, 16978e75f744SArnaud Giersch int flags) 16988e75f744SArnaud Giersch { 16998e75f744SArnaud Giersch static unsigned int ready_before = 1; 17008e75f744SArnaud Giersch struct parport_ip32_private * const priv = p->physport->private_data; 17018e75f744SArnaud Giersch struct parport * const physport = p->physport; 17028e75f744SArnaud Giersch size_t written = 0; 17038e75f744SArnaud Giersch 17048e75f744SArnaud Giersch /* Special case: a timeout of zero means we cannot call schedule(). 17058e75f744SArnaud Giersch * Also if O_NONBLOCK is set then use the default implementation. */ 17068e75f744SArnaud Giersch if (physport->cad->timeout <= PARPORT_INACTIVITY_O_NONBLOCK) 17078e75f744SArnaud Giersch return parport_ieee1284_ecp_write_data(p, buf, len, flags); 17088e75f744SArnaud Giersch 17098e75f744SArnaud Giersch /* Negotiate to forward mode if necessary. */ 17108e75f744SArnaud Giersch if (physport->ieee1284.phase != IEEE1284_PH_FWD_IDLE) { 17118e75f744SArnaud Giersch /* Event 47: Set nInit high. */ 17128e75f744SArnaud Giersch parport_ip32_frob_control(p, DCR_nINIT | DCR_AUTOFD, 17138e75f744SArnaud Giersch DCR_nINIT | DCR_AUTOFD); 17148e75f744SArnaud Giersch 17158e75f744SArnaud Giersch /* Event 49: PError goes high. */ 17168e75f744SArnaud Giersch if (parport_wait_peripheral(p, DSR_PERROR, DSR_PERROR)) { 17178e75f744SArnaud Giersch printk(KERN_DEBUG PPIP32 "%s: PError timeout in %s", 17188e75f744SArnaud Giersch p->name, __func__); 17198e75f744SArnaud Giersch physport->ieee1284.phase = IEEE1284_PH_ECP_DIR_UNKNOWN; 17208e75f744SArnaud Giersch return 0; 17218e75f744SArnaud Giersch } 17228e75f744SArnaud Giersch } 17238e75f744SArnaud Giersch 17248e75f744SArnaud Giersch /* Reset FIFO, go in forward mode, and disable ackIntEn */ 17258e75f744SArnaud Giersch parport_ip32_set_mode(p, ECR_MODE_PS2); 17268e75f744SArnaud Giersch parport_ip32_write_control(p, DCR_SELECT | DCR_nINIT); 17278e75f744SArnaud Giersch parport_ip32_data_forward(p); 17288e75f744SArnaud Giersch parport_ip32_disable_irq(p); 17298e75f744SArnaud Giersch parport_ip32_set_mode(p, ECR_MODE_ECP); 17308e75f744SArnaud Giersch physport->ieee1284.phase = IEEE1284_PH_FWD_DATA; 17318e75f744SArnaud Giersch 17328e75f744SArnaud Giersch /* Wait for peripheral to become ready */ 17338e75f744SArnaud Giersch if (parport_wait_peripheral(p, DSR_nBUSY | DSR_nFAULT, 17348e75f744SArnaud Giersch DSR_nBUSY | DSR_nFAULT)) { 17358e75f744SArnaud Giersch /* Avoid to flood the logs */ 17368e75f744SArnaud Giersch if (ready_before) 17378e75f744SArnaud Giersch printk(KERN_INFO PPIP32 "%s: not ready in %s\n", 17388e75f744SArnaud Giersch p->name, __func__); 17398e75f744SArnaud Giersch ready_before = 0; 17408e75f744SArnaud Giersch goto stop; 17418e75f744SArnaud Giersch } 17428e75f744SArnaud Giersch ready_before = 1; 17438e75f744SArnaud Giersch 17448e75f744SArnaud Giersch written = parport_ip32_fifo_write_block(p, buf, len); 17458e75f744SArnaud Giersch 17468e75f744SArnaud Giersch /* Wait FIFO to empty. Timeout is proportional to FIFO_depth. */ 17478e75f744SArnaud Giersch parport_ip32_drain_fifo(p, physport->cad->timeout * priv->fifo_depth); 17488e75f744SArnaud Giersch 17498e75f744SArnaud Giersch /* Check for a potential residue */ 17508e75f744SArnaud Giersch written -= parport_ip32_get_fifo_residue(p, ECR_MODE_ECP); 17518e75f744SArnaud Giersch 17528e75f744SArnaud Giersch /* Then, wait for BUSY to get low. */ 17538e75f744SArnaud Giersch if (parport_wait_peripheral(p, DSR_nBUSY, DSR_nBUSY)) 17548e75f744SArnaud Giersch printk(KERN_DEBUG PPIP32 "%s: BUSY timeout in %s\n", 17558e75f744SArnaud Giersch p->name, __func__); 17568e75f744SArnaud Giersch 17578e75f744SArnaud Giersch stop: 17588e75f744SArnaud Giersch /* Reset FIFO */ 17598e75f744SArnaud Giersch parport_ip32_set_mode(p, ECR_MODE_PS2); 17608e75f744SArnaud Giersch physport->ieee1284.phase = IEEE1284_PH_FWD_IDLE; 17618e75f744SArnaud Giersch 17628e75f744SArnaud Giersch return written; 17638e75f744SArnaud Giersch } 17648e75f744SArnaud Giersch 17658e75f744SArnaud Giersch /* 17668e75f744SArnaud Giersch * FIXME - Insert here parport_ip32_ecp_write_addr(). 17678e75f744SArnaud Giersch */ 17688e75f744SArnaud Giersch 17698e75f744SArnaud Giersch /*--- Default parport operations ---------------------------------------*/ 17708e75f744SArnaud Giersch 17718e75f744SArnaud Giersch static __initdata struct parport_operations parport_ip32_ops = { 17728e75f744SArnaud Giersch .write_data = parport_ip32_write_data, 17738e75f744SArnaud Giersch .read_data = parport_ip32_read_data, 17748e75f744SArnaud Giersch 17758e75f744SArnaud Giersch .write_control = parport_ip32_write_control, 17768e75f744SArnaud Giersch .read_control = parport_ip32_read_control, 17778e75f744SArnaud Giersch .frob_control = parport_ip32_frob_control, 17788e75f744SArnaud Giersch 17798e75f744SArnaud Giersch .read_status = parport_ip32_read_status, 17808e75f744SArnaud Giersch 17818e75f744SArnaud Giersch .enable_irq = parport_ip32_enable_irq, 17828e75f744SArnaud Giersch .disable_irq = parport_ip32_disable_irq, 17838e75f744SArnaud Giersch 17848e75f744SArnaud Giersch .data_forward = parport_ip32_data_forward, 17858e75f744SArnaud Giersch .data_reverse = parport_ip32_data_reverse, 17868e75f744SArnaud Giersch 17878e75f744SArnaud Giersch .init_state = parport_ip32_init_state, 17888e75f744SArnaud Giersch .save_state = parport_ip32_save_state, 17898e75f744SArnaud Giersch .restore_state = parport_ip32_restore_state, 17908e75f744SArnaud Giersch 17918e75f744SArnaud Giersch .epp_write_data = parport_ieee1284_epp_write_data, 17928e75f744SArnaud Giersch .epp_read_data = parport_ieee1284_epp_read_data, 17938e75f744SArnaud Giersch .epp_write_addr = parport_ieee1284_epp_write_addr, 17948e75f744SArnaud Giersch .epp_read_addr = parport_ieee1284_epp_read_addr, 17958e75f744SArnaud Giersch 17968e75f744SArnaud Giersch .ecp_write_data = parport_ieee1284_ecp_write_data, 17978e75f744SArnaud Giersch .ecp_read_data = parport_ieee1284_ecp_read_data, 17988e75f744SArnaud Giersch .ecp_write_addr = parport_ieee1284_ecp_write_addr, 17998e75f744SArnaud Giersch 18008e75f744SArnaud Giersch .compat_write_data = parport_ieee1284_write_compat, 18018e75f744SArnaud Giersch .nibble_read_data = parport_ieee1284_read_nibble, 18028e75f744SArnaud Giersch .byte_read_data = parport_ieee1284_read_byte, 18038e75f744SArnaud Giersch 18048e75f744SArnaud Giersch .owner = THIS_MODULE, 18058e75f744SArnaud Giersch }; 18068e75f744SArnaud Giersch 18078e75f744SArnaud Giersch /*--- Device detection -------------------------------------------------*/ 18088e75f744SArnaud Giersch 18098e75f744SArnaud Giersch /** 18108e75f744SArnaud Giersch * parport_ip32_ecp_supported - check for an ECP port 18118e75f744SArnaud Giersch * @p: pointer to the &parport structure 18128e75f744SArnaud Giersch * 18138e75f744SArnaud Giersch * Returns 1 if an ECP port is found, and 0 otherwise. This function actually 18148e75f744SArnaud Giersch * checks if an Extended Control Register seems to be present. On successful 18158e75f744SArnaud Giersch * return, the port is placed in SPP mode. 18168e75f744SArnaud Giersch */ 18178e75f744SArnaud Giersch static __init unsigned int parport_ip32_ecp_supported(struct parport *p) 18188e75f744SArnaud Giersch { 18198e75f744SArnaud Giersch struct parport_ip32_private * const priv = p->physport->private_data; 18208e75f744SArnaud Giersch unsigned int ecr; 18218e75f744SArnaud Giersch 18228e75f744SArnaud Giersch ecr = ECR_MODE_PS2 | ECR_nERRINTR | ECR_SERVINTR; 18238e75f744SArnaud Giersch writeb(ecr, priv->regs.ecr); 18248e75f744SArnaud Giersch if (readb(priv->regs.ecr) != (ecr | ECR_F_EMPTY)) 18258e75f744SArnaud Giersch goto fail; 18268e75f744SArnaud Giersch 18278e75f744SArnaud Giersch pr_probe(p, "Found working ECR register\n"); 18288e75f744SArnaud Giersch parport_ip32_set_mode(p, ECR_MODE_SPP); 18298e75f744SArnaud Giersch parport_ip32_write_control(p, DCR_SELECT | DCR_nINIT); 18308e75f744SArnaud Giersch return 1; 18318e75f744SArnaud Giersch 18328e75f744SArnaud Giersch fail: 18338e75f744SArnaud Giersch pr_probe(p, "ECR register not found\n"); 18348e75f744SArnaud Giersch return 0; 18358e75f744SArnaud Giersch } 18368e75f744SArnaud Giersch 18378e75f744SArnaud Giersch /** 18388e75f744SArnaud Giersch * parport_ip32_fifo_supported - check for FIFO parameters 18398e75f744SArnaud Giersch * @p: pointer to the &parport structure 18408e75f744SArnaud Giersch * 18418e75f744SArnaud Giersch * Check for FIFO parameters of an Extended Capabilities Port. Returns 1 on 18428e75f744SArnaud Giersch * success, and 0 otherwise. Adjust FIFO parameters in the parport structure. 18438e75f744SArnaud Giersch * On return, the port is placed in SPP mode. 18448e75f744SArnaud Giersch */ 18458e75f744SArnaud Giersch static __init unsigned int parport_ip32_fifo_supported(struct parport *p) 18468e75f744SArnaud Giersch { 18478e75f744SArnaud Giersch struct parport_ip32_private * const priv = p->physport->private_data; 18488e75f744SArnaud Giersch unsigned int configa, configb; 18498e75f744SArnaud Giersch unsigned int pword; 18508e75f744SArnaud Giersch unsigned int i; 18518e75f744SArnaud Giersch 18528e75f744SArnaud Giersch /* Configuration mode */ 18538e75f744SArnaud Giersch parport_ip32_set_mode(p, ECR_MODE_CFG); 18548e75f744SArnaud Giersch configa = readb(priv->regs.cnfgA); 18558e75f744SArnaud Giersch configb = readb(priv->regs.cnfgB); 18568e75f744SArnaud Giersch 18578e75f744SArnaud Giersch /* Find out PWord size */ 18588e75f744SArnaud Giersch switch (configa & CNFGA_ID_MASK) { 18598e75f744SArnaud Giersch case CNFGA_ID_8: 18608e75f744SArnaud Giersch pword = 1; 18618e75f744SArnaud Giersch break; 18628e75f744SArnaud Giersch case CNFGA_ID_16: 18638e75f744SArnaud Giersch pword = 2; 18648e75f744SArnaud Giersch break; 18658e75f744SArnaud Giersch case CNFGA_ID_32: 18668e75f744SArnaud Giersch pword = 4; 18678e75f744SArnaud Giersch break; 18688e75f744SArnaud Giersch default: 18698e75f744SArnaud Giersch pr_probe(p, "Unknown implementation ID: 0x%0x\n", 18708e75f744SArnaud Giersch (configa & CNFGA_ID_MASK) >> CNFGA_ID_SHIFT); 18718e75f744SArnaud Giersch goto fail; 18728e75f744SArnaud Giersch break; 18738e75f744SArnaud Giersch } 18748e75f744SArnaud Giersch if (pword != 1) { 18758e75f744SArnaud Giersch pr_probe(p, "Unsupported PWord size: %u\n", pword); 18768e75f744SArnaud Giersch goto fail; 18778e75f744SArnaud Giersch } 18788e75f744SArnaud Giersch priv->pword = pword; 18798e75f744SArnaud Giersch pr_probe(p, "PWord is %u bits\n", 8 * priv->pword); 18808e75f744SArnaud Giersch 18818e75f744SArnaud Giersch /* Check for compression support */ 18828e75f744SArnaud Giersch writeb(configb | CNFGB_COMPRESS, priv->regs.cnfgB); 18838e75f744SArnaud Giersch if (readb(priv->regs.cnfgB) & CNFGB_COMPRESS) 18848e75f744SArnaud Giersch pr_probe(p, "Hardware compression detected (unsupported)\n"); 18858e75f744SArnaud Giersch writeb(configb & ~CNFGB_COMPRESS, priv->regs.cnfgB); 18868e75f744SArnaud Giersch 18878e75f744SArnaud Giersch /* Reset FIFO and go in test mode (no interrupt, no DMA) */ 18888e75f744SArnaud Giersch parport_ip32_set_mode(p, ECR_MODE_TST); 18898e75f744SArnaud Giersch 18908e75f744SArnaud Giersch /* FIFO must be empty now */ 18918e75f744SArnaud Giersch if (!(readb(priv->regs.ecr) & ECR_F_EMPTY)) { 18928e75f744SArnaud Giersch pr_probe(p, "FIFO not reset\n"); 18938e75f744SArnaud Giersch goto fail; 18948e75f744SArnaud Giersch } 18958e75f744SArnaud Giersch 18968e75f744SArnaud Giersch /* Find out FIFO depth. */ 18978e75f744SArnaud Giersch priv->fifo_depth = 0; 18988e75f744SArnaud Giersch for (i = 0; i < 1024; i++) { 18998e75f744SArnaud Giersch if (readb(priv->regs.ecr) & ECR_F_FULL) { 19008e75f744SArnaud Giersch /* FIFO full */ 19018e75f744SArnaud Giersch priv->fifo_depth = i; 19028e75f744SArnaud Giersch break; 19038e75f744SArnaud Giersch } 19048e75f744SArnaud Giersch writeb((u8)i, priv->regs.fifo); 19058e75f744SArnaud Giersch } 19068e75f744SArnaud Giersch if (i >= 1024) { 19078e75f744SArnaud Giersch pr_probe(p, "Can't fill FIFO\n"); 19088e75f744SArnaud Giersch goto fail; 19098e75f744SArnaud Giersch } 19108e75f744SArnaud Giersch if (!priv->fifo_depth) { 19118e75f744SArnaud Giersch pr_probe(p, "Can't get FIFO depth\n"); 19128e75f744SArnaud Giersch goto fail; 19138e75f744SArnaud Giersch } 19148e75f744SArnaud Giersch pr_probe(p, "FIFO is %u PWords deep\n", priv->fifo_depth); 19158e75f744SArnaud Giersch 19168e75f744SArnaud Giersch /* Enable interrupts */ 19178e75f744SArnaud Giersch parport_ip32_frob_econtrol(p, ECR_SERVINTR, 0); 19188e75f744SArnaud Giersch 19198e75f744SArnaud Giersch /* Find out writeIntrThreshold: number of PWords we know we can write 19208e75f744SArnaud Giersch * if we get an interrupt. */ 19218e75f744SArnaud Giersch priv->writeIntrThreshold = 0; 19228e75f744SArnaud Giersch for (i = 0; i < priv->fifo_depth; i++) { 19238e75f744SArnaud Giersch if (readb(priv->regs.fifo) != (u8)i) { 19248e75f744SArnaud Giersch pr_probe(p, "Invalid data in FIFO\n"); 19258e75f744SArnaud Giersch goto fail; 19268e75f744SArnaud Giersch } 19278e75f744SArnaud Giersch if (!priv->writeIntrThreshold 19288e75f744SArnaud Giersch && readb(priv->regs.ecr) & ECR_SERVINTR) 19298e75f744SArnaud Giersch /* writeIntrThreshold reached */ 19308e75f744SArnaud Giersch priv->writeIntrThreshold = i + 1; 19318e75f744SArnaud Giersch if (i + 1 < priv->fifo_depth 19328e75f744SArnaud Giersch && readb(priv->regs.ecr) & ECR_F_EMPTY) { 19338e75f744SArnaud Giersch /* FIFO empty before the last byte? */ 19348e75f744SArnaud Giersch pr_probe(p, "Data lost in FIFO\n"); 19358e75f744SArnaud Giersch goto fail; 19368e75f744SArnaud Giersch } 19378e75f744SArnaud Giersch } 19388e75f744SArnaud Giersch if (!priv->writeIntrThreshold) { 19398e75f744SArnaud Giersch pr_probe(p, "Can't get writeIntrThreshold\n"); 19408e75f744SArnaud Giersch goto fail; 19418e75f744SArnaud Giersch } 19428e75f744SArnaud Giersch pr_probe(p, "writeIntrThreshold is %u\n", priv->writeIntrThreshold); 19438e75f744SArnaud Giersch 19448e75f744SArnaud Giersch /* FIFO must be empty now */ 19458e75f744SArnaud Giersch if (!(readb(priv->regs.ecr) & ECR_F_EMPTY)) { 19468e75f744SArnaud Giersch pr_probe(p, "Can't empty FIFO\n"); 19478e75f744SArnaud Giersch goto fail; 19488e75f744SArnaud Giersch } 19498e75f744SArnaud Giersch 19508e75f744SArnaud Giersch /* Reset FIFO */ 19518e75f744SArnaud Giersch parport_ip32_set_mode(p, ECR_MODE_PS2); 19528e75f744SArnaud Giersch /* Set reverse direction (must be in PS2 mode) */ 19538e75f744SArnaud Giersch parport_ip32_data_reverse(p); 19548e75f744SArnaud Giersch /* Test FIFO, no interrupt, no DMA */ 19558e75f744SArnaud Giersch parport_ip32_set_mode(p, ECR_MODE_TST); 19568e75f744SArnaud Giersch /* Enable interrupts */ 19578e75f744SArnaud Giersch parport_ip32_frob_econtrol(p, ECR_SERVINTR, 0); 19588e75f744SArnaud Giersch 19598e75f744SArnaud Giersch /* Find out readIntrThreshold: number of PWords we can read if we get 19608e75f744SArnaud Giersch * an interrupt. */ 19618e75f744SArnaud Giersch priv->readIntrThreshold = 0; 19628e75f744SArnaud Giersch for (i = 0; i < priv->fifo_depth; i++) { 19638e75f744SArnaud Giersch writeb(0xaa, priv->regs.fifo); 19648e75f744SArnaud Giersch if (readb(priv->regs.ecr) & ECR_SERVINTR) { 19658e75f744SArnaud Giersch /* readIntrThreshold reached */ 19668e75f744SArnaud Giersch priv->readIntrThreshold = i + 1; 19678e75f744SArnaud Giersch break; 19688e75f744SArnaud Giersch } 19698e75f744SArnaud Giersch } 19708e75f744SArnaud Giersch if (!priv->readIntrThreshold) { 19718e75f744SArnaud Giersch pr_probe(p, "Can't get readIntrThreshold\n"); 19728e75f744SArnaud Giersch goto fail; 19738e75f744SArnaud Giersch } 19748e75f744SArnaud Giersch pr_probe(p, "readIntrThreshold is %u\n", priv->readIntrThreshold); 19758e75f744SArnaud Giersch 19768e75f744SArnaud Giersch /* Reset ECR */ 19778e75f744SArnaud Giersch parport_ip32_set_mode(p, ECR_MODE_PS2); 19788e75f744SArnaud Giersch parport_ip32_data_forward(p); 19798e75f744SArnaud Giersch parport_ip32_set_mode(p, ECR_MODE_SPP); 19808e75f744SArnaud Giersch return 1; 19818e75f744SArnaud Giersch 19828e75f744SArnaud Giersch fail: 19838e75f744SArnaud Giersch priv->fifo_depth = 0; 19848e75f744SArnaud Giersch parport_ip32_set_mode(p, ECR_MODE_SPP); 19858e75f744SArnaud Giersch return 0; 19868e75f744SArnaud Giersch } 19878e75f744SArnaud Giersch 19888e75f744SArnaud Giersch /*--- Initialization code ----------------------------------------------*/ 19898e75f744SArnaud Giersch 19908e75f744SArnaud Giersch /** 19918e75f744SArnaud Giersch * parport_ip32_make_isa_registers - compute (ISA) register addresses 19928e75f744SArnaud Giersch * @regs: pointer to &struct parport_ip32_regs to fill 19938e75f744SArnaud Giersch * @base: base address of standard and EPP registers 19948e75f744SArnaud Giersch * @base_hi: base address of ECP registers 19958e75f744SArnaud Giersch * @regshift: how much to shift register offset by 19968e75f744SArnaud Giersch * 19978e75f744SArnaud Giersch * Compute register addresses, according to the ISA standard. The addresses 19988e75f744SArnaud Giersch * of the standard and EPP registers are computed from address @base. The 19998e75f744SArnaud Giersch * addresses of the ECP registers are computed from address @base_hi. 20008e75f744SArnaud Giersch */ 20018e75f744SArnaud Giersch static void __init 20028e75f744SArnaud Giersch parport_ip32_make_isa_registers(struct parport_ip32_regs *regs, 20038e75f744SArnaud Giersch void __iomem *base, void __iomem *base_hi, 20048e75f744SArnaud Giersch unsigned int regshift) 20058e75f744SArnaud Giersch { 20068e75f744SArnaud Giersch #define r_base(offset) ((u8 __iomem *)base + ((offset) << regshift)) 20078e75f744SArnaud Giersch #define r_base_hi(offset) ((u8 __iomem *)base_hi + ((offset) << regshift)) 20088e75f744SArnaud Giersch *regs = (struct parport_ip32_regs){ 20098e75f744SArnaud Giersch .data = r_base(0), 20108e75f744SArnaud Giersch .dsr = r_base(1), 20118e75f744SArnaud Giersch .dcr = r_base(2), 20128e75f744SArnaud Giersch .eppAddr = r_base(3), 20138e75f744SArnaud Giersch .eppData0 = r_base(4), 20148e75f744SArnaud Giersch .eppData1 = r_base(5), 20158e75f744SArnaud Giersch .eppData2 = r_base(6), 20168e75f744SArnaud Giersch .eppData3 = r_base(7), 20178e75f744SArnaud Giersch .ecpAFifo = r_base(0), 20188e75f744SArnaud Giersch .fifo = r_base_hi(0), 20198e75f744SArnaud Giersch .cnfgA = r_base_hi(0), 20208e75f744SArnaud Giersch .cnfgB = r_base_hi(1), 20218e75f744SArnaud Giersch .ecr = r_base_hi(2) 20228e75f744SArnaud Giersch }; 20238e75f744SArnaud Giersch #undef r_base_hi 20248e75f744SArnaud Giersch #undef r_base 20258e75f744SArnaud Giersch } 20268e75f744SArnaud Giersch 20278e75f744SArnaud Giersch /** 20288e75f744SArnaud Giersch * parport_ip32_probe_port - probe and register IP32 built-in parallel port 20298e75f744SArnaud Giersch * 20308e75f744SArnaud Giersch * Returns the new allocated &parport structure. On error, an error code is 20318e75f744SArnaud Giersch * encoded in return value with the ERR_PTR function. 20328e75f744SArnaud Giersch */ 20338e75f744SArnaud Giersch static __init struct parport *parport_ip32_probe_port(void) 20348e75f744SArnaud Giersch { 20358e75f744SArnaud Giersch struct parport_ip32_regs regs; 20368e75f744SArnaud Giersch struct parport_ip32_private *priv = NULL; 20378e75f744SArnaud Giersch struct parport_operations *ops = NULL; 20388e75f744SArnaud Giersch struct parport *p = NULL; 20398e75f744SArnaud Giersch int err; 20408e75f744SArnaud Giersch 20418e75f744SArnaud Giersch parport_ip32_make_isa_registers(®s, &mace->isa.parallel, 20428e75f744SArnaud Giersch &mace->isa.ecp1284, 8 /* regshift */); 20438e75f744SArnaud Giersch 20448e75f744SArnaud Giersch ops = kmalloc(sizeof(struct parport_operations), GFP_KERNEL); 20458e75f744SArnaud Giersch priv = kmalloc(sizeof(struct parport_ip32_private), GFP_KERNEL); 20468e75f744SArnaud Giersch p = parport_register_port(0, PARPORT_IRQ_NONE, PARPORT_DMA_NONE, ops); 20478e75f744SArnaud Giersch if (ops == NULL || priv == NULL || p == NULL) { 20488e75f744SArnaud Giersch err = -ENOMEM; 20498e75f744SArnaud Giersch goto fail; 20508e75f744SArnaud Giersch } 20518e75f744SArnaud Giersch p->base = MACE_BASE + offsetof(struct sgi_mace, isa.parallel); 20528e75f744SArnaud Giersch p->base_hi = MACE_BASE + offsetof(struct sgi_mace, isa.ecp1284); 20538e75f744SArnaud Giersch p->private_data = priv; 20548e75f744SArnaud Giersch 20558e75f744SArnaud Giersch *ops = parport_ip32_ops; 20568e75f744SArnaud Giersch *priv = (struct parport_ip32_private){ 20578e75f744SArnaud Giersch .regs = regs, 20588e75f744SArnaud Giersch .dcr_writable = DCR_DIR | DCR_SELECT | DCR_nINIT | 20598e75f744SArnaud Giersch DCR_AUTOFD | DCR_STROBE, 20608e75f744SArnaud Giersch .irq_mode = PARPORT_IP32_IRQ_FWD, 20618e75f744SArnaud Giersch }; 20628e75f744SArnaud Giersch init_completion(&priv->irq_complete); 20638e75f744SArnaud Giersch 20648e75f744SArnaud Giersch /* Probe port. */ 20658e75f744SArnaud Giersch if (!parport_ip32_ecp_supported(p)) { 20668e75f744SArnaud Giersch err = -ENODEV; 20678e75f744SArnaud Giersch goto fail; 20688e75f744SArnaud Giersch } 20698e75f744SArnaud Giersch parport_ip32_dump_state(p, "begin init", 0); 20708e75f744SArnaud Giersch 20718e75f744SArnaud Giersch /* We found what looks like a working ECR register. Simply assume 20728e75f744SArnaud Giersch * that all modes are correctly supported. Enable basic modes. */ 20738e75f744SArnaud Giersch p->modes = PARPORT_MODE_PCSPP | PARPORT_MODE_SAFEININT; 20748e75f744SArnaud Giersch p->modes |= PARPORT_MODE_TRISTATE; 20758e75f744SArnaud Giersch 20768e75f744SArnaud Giersch if (!parport_ip32_fifo_supported(p)) { 20778e75f744SArnaud Giersch printk(KERN_WARNING PPIP32 20788e75f744SArnaud Giersch "%s: error: FIFO disabled\n", p->name); 20798e75f744SArnaud Giersch /* Disable hardware modes depending on a working FIFO. */ 20808e75f744SArnaud Giersch features &= ~PARPORT_IP32_ENABLE_SPP; 20818e75f744SArnaud Giersch features &= ~PARPORT_IP32_ENABLE_ECP; 20828e75f744SArnaud Giersch /* DMA is not needed if FIFO is not supported. */ 20838e75f744SArnaud Giersch features &= ~PARPORT_IP32_ENABLE_DMA; 20848e75f744SArnaud Giersch } 20858e75f744SArnaud Giersch 20868e75f744SArnaud Giersch /* Request IRQ */ 20878e75f744SArnaud Giersch if (features & PARPORT_IP32_ENABLE_IRQ) { 20888e75f744SArnaud Giersch int irq = MACEISA_PARALLEL_IRQ; 20898e75f744SArnaud Giersch if (request_irq(irq, parport_ip32_interrupt, 0, p->name, p)) { 20908e75f744SArnaud Giersch printk(KERN_WARNING PPIP32 20918e75f744SArnaud Giersch "%s: error: IRQ disabled\n", p->name); 20928e75f744SArnaud Giersch /* DMA cannot work without interrupts. */ 20938e75f744SArnaud Giersch features &= ~PARPORT_IP32_ENABLE_DMA; 20948e75f744SArnaud Giersch } else { 20958e75f744SArnaud Giersch pr_probe(p, "Interrupt support enabled\n"); 20968e75f744SArnaud Giersch p->irq = irq; 20978e75f744SArnaud Giersch priv->dcr_writable |= DCR_IRQ; 20988e75f744SArnaud Giersch } 20998e75f744SArnaud Giersch } 21008e75f744SArnaud Giersch 21018e75f744SArnaud Giersch /* Allocate DMA resources */ 21028e75f744SArnaud Giersch if (features & PARPORT_IP32_ENABLE_DMA) { 21038e75f744SArnaud Giersch if (parport_ip32_dma_register()) 21048e75f744SArnaud Giersch printk(KERN_WARNING PPIP32 21058e75f744SArnaud Giersch "%s: error: DMA disabled\n", p->name); 21068e75f744SArnaud Giersch else { 21078e75f744SArnaud Giersch pr_probe(p, "DMA support enabled\n"); 21088e75f744SArnaud Giersch p->dma = 0; /* arbitrary value != PARPORT_DMA_NONE */ 21098e75f744SArnaud Giersch p->modes |= PARPORT_MODE_DMA; 21108e75f744SArnaud Giersch } 21118e75f744SArnaud Giersch } 21128e75f744SArnaud Giersch 21138e75f744SArnaud Giersch if (features & PARPORT_IP32_ENABLE_SPP) { 21148e75f744SArnaud Giersch /* Enable compatibility FIFO mode */ 21158e75f744SArnaud Giersch p->ops->compat_write_data = parport_ip32_compat_write_data; 21168e75f744SArnaud Giersch p->modes |= PARPORT_MODE_COMPAT; 21178e75f744SArnaud Giersch pr_probe(p, "Hardware support for SPP mode enabled\n"); 21188e75f744SArnaud Giersch } 21198e75f744SArnaud Giersch if (features & PARPORT_IP32_ENABLE_EPP) { 21208e75f744SArnaud Giersch /* Set up access functions to use EPP hardware. */ 21218e75f744SArnaud Giersch p->ops->epp_read_data = parport_ip32_epp_read_data; 21228e75f744SArnaud Giersch p->ops->epp_write_data = parport_ip32_epp_write_data; 21238e75f744SArnaud Giersch p->ops->epp_read_addr = parport_ip32_epp_read_addr; 21248e75f744SArnaud Giersch p->ops->epp_write_addr = parport_ip32_epp_write_addr; 21258e75f744SArnaud Giersch p->modes |= PARPORT_MODE_EPP; 21268e75f744SArnaud Giersch pr_probe(p, "Hardware support for EPP mode enabled\n"); 21278e75f744SArnaud Giersch } 21288e75f744SArnaud Giersch if (features & PARPORT_IP32_ENABLE_ECP) { 21298e75f744SArnaud Giersch /* Enable ECP FIFO mode */ 21308e75f744SArnaud Giersch p->ops->ecp_write_data = parport_ip32_ecp_write_data; 21318e75f744SArnaud Giersch /* FIXME - not implemented */ 21328e75f744SArnaud Giersch /* p->ops->ecp_read_data = parport_ip32_ecp_read_data; */ 21338e75f744SArnaud Giersch /* p->ops->ecp_write_addr = parport_ip32_ecp_write_addr; */ 21348e75f744SArnaud Giersch p->modes |= PARPORT_MODE_ECP; 21358e75f744SArnaud Giersch pr_probe(p, "Hardware support for ECP mode enabled\n"); 21368e75f744SArnaud Giersch } 21378e75f744SArnaud Giersch 21388e75f744SArnaud Giersch /* Initialize the port with sensible values */ 21398e75f744SArnaud Giersch parport_ip32_set_mode(p, ECR_MODE_PS2); 21408e75f744SArnaud Giersch parport_ip32_write_control(p, DCR_SELECT | DCR_nINIT); 21418e75f744SArnaud Giersch parport_ip32_data_forward(p); 21428e75f744SArnaud Giersch parport_ip32_disable_irq(p); 21438e75f744SArnaud Giersch parport_ip32_write_data(p, 0x00); 21448e75f744SArnaud Giersch parport_ip32_dump_state(p, "end init", 0); 21458e75f744SArnaud Giersch 21468e75f744SArnaud Giersch /* Print out what we found */ 21478e75f744SArnaud Giersch printk(KERN_INFO "%s: SGI IP32 at 0x%lx (0x%lx)", 21488e75f744SArnaud Giersch p->name, p->base, p->base_hi); 21498e75f744SArnaud Giersch if (p->irq != PARPORT_IRQ_NONE) 21508e75f744SArnaud Giersch printk(", irq %d", p->irq); 21518e75f744SArnaud Giersch printk(" ["); 21528e75f744SArnaud Giersch #define printmode(x) if (p->modes & PARPORT_MODE_##x) \ 21538e75f744SArnaud Giersch printk("%s%s", f++ ? "," : "", #x) 21548e75f744SArnaud Giersch { 21558e75f744SArnaud Giersch unsigned int f = 0; 21568e75f744SArnaud Giersch printmode(PCSPP); 21578e75f744SArnaud Giersch printmode(TRISTATE); 21588e75f744SArnaud Giersch printmode(COMPAT); 21598e75f744SArnaud Giersch printmode(EPP); 21608e75f744SArnaud Giersch printmode(ECP); 21618e75f744SArnaud Giersch printmode(DMA); 21628e75f744SArnaud Giersch } 21638e75f744SArnaud Giersch #undef printmode 21648e75f744SArnaud Giersch printk("]\n"); 21658e75f744SArnaud Giersch 21668e75f744SArnaud Giersch parport_announce_port(p); 21678e75f744SArnaud Giersch return p; 21688e75f744SArnaud Giersch 21698e75f744SArnaud Giersch fail: 21708e75f744SArnaud Giersch if (p) 21718e75f744SArnaud Giersch parport_put_port(p); 21728e75f744SArnaud Giersch kfree(priv); 21738e75f744SArnaud Giersch kfree(ops); 21748e75f744SArnaud Giersch return ERR_PTR(err); 21758e75f744SArnaud Giersch } 21768e75f744SArnaud Giersch 21778e75f744SArnaud Giersch /** 21788e75f744SArnaud Giersch * parport_ip32_unregister_port - unregister a parallel port 21798e75f744SArnaud Giersch * @p: pointer to the &struct parport 21808e75f744SArnaud Giersch * 21818e75f744SArnaud Giersch * Unregisters a parallel port and free previously allocated resources 21828e75f744SArnaud Giersch * (memory, IRQ, ...). 21838e75f744SArnaud Giersch */ 21848e75f744SArnaud Giersch static __exit void parport_ip32_unregister_port(struct parport *p) 21858e75f744SArnaud Giersch { 21868e75f744SArnaud Giersch struct parport_ip32_private * const priv = p->physport->private_data; 21878e75f744SArnaud Giersch struct parport_operations *ops = p->ops; 21888e75f744SArnaud Giersch 21898e75f744SArnaud Giersch parport_remove_port(p); 21908e75f744SArnaud Giersch if (p->modes & PARPORT_MODE_DMA) 21918e75f744SArnaud Giersch parport_ip32_dma_unregister(); 21928e75f744SArnaud Giersch if (p->irq != PARPORT_IRQ_NONE) 21938e75f744SArnaud Giersch free_irq(p->irq, p); 21948e75f744SArnaud Giersch parport_put_port(p); 21958e75f744SArnaud Giersch kfree(priv); 21968e75f744SArnaud Giersch kfree(ops); 21978e75f744SArnaud Giersch } 21988e75f744SArnaud Giersch 21998e75f744SArnaud Giersch /** 22008e75f744SArnaud Giersch * parport_ip32_init - module initialization function 22018e75f744SArnaud Giersch */ 22028e75f744SArnaud Giersch static int __init parport_ip32_init(void) 22038e75f744SArnaud Giersch { 22048e75f744SArnaud Giersch pr_info(PPIP32 "SGI IP32 built-in parallel port driver v0.6\n"); 22058e75f744SArnaud Giersch pr_debug1(PPIP32 "Compiled on %s, %s\n", __DATE__, __TIME__); 22068e75f744SArnaud Giersch this_port = parport_ip32_probe_port(); 22078e75f744SArnaud Giersch return IS_ERR(this_port) ? PTR_ERR(this_port) : 0; 22088e75f744SArnaud Giersch } 22098e75f744SArnaud Giersch 22108e75f744SArnaud Giersch /** 22118e75f744SArnaud Giersch * parport_ip32_exit - module termination function 22128e75f744SArnaud Giersch */ 22138e75f744SArnaud Giersch static void __exit parport_ip32_exit(void) 22148e75f744SArnaud Giersch { 22158e75f744SArnaud Giersch parport_ip32_unregister_port(this_port); 22168e75f744SArnaud Giersch } 22178e75f744SArnaud Giersch 22188e75f744SArnaud Giersch /*--- Module stuff -----------------------------------------------------*/ 22198e75f744SArnaud Giersch 22208e75f744SArnaud Giersch MODULE_AUTHOR("Arnaud Giersch <arnaud.giersch@free.fr>"); 22218e75f744SArnaud Giersch MODULE_DESCRIPTION("SGI IP32 built-in parallel port driver"); 22228e75f744SArnaud Giersch MODULE_LICENSE("GPL"); 22238e75f744SArnaud Giersch MODULE_VERSION("0.6"); /* update in parport_ip32_init() too */ 22248e75f744SArnaud Giersch 22258e75f744SArnaud Giersch module_init(parport_ip32_init); 22268e75f744SArnaud Giersch module_exit(parport_ip32_exit); 22278e75f744SArnaud Giersch 22288e75f744SArnaud Giersch module_param(verbose_probing, bool, S_IRUGO); 22298e75f744SArnaud Giersch MODULE_PARM_DESC(verbose_probing, "Log chit-chat during initialization"); 22308e75f744SArnaud Giersch 22318e75f744SArnaud Giersch module_param(features, uint, S_IRUGO); 22328e75f744SArnaud Giersch MODULE_PARM_DESC(features, 22338e75f744SArnaud Giersch "Bit mask of features to enable" 22348e75f744SArnaud Giersch ", bit 0: IRQ support" 22358e75f744SArnaud Giersch ", bit 1: DMA support" 22368e75f744SArnaud Giersch ", bit 2: hardware SPP mode" 22378e75f744SArnaud Giersch ", bit 3: hardware EPP mode" 22388e75f744SArnaud Giersch ", bit 4: hardware ECP mode"); 22398e75f744SArnaud Giersch 22408e75f744SArnaud Giersch /*--- Inform (X)Emacs about preferred coding style ---------------------*/ 22418e75f744SArnaud Giersch /* 22428e75f744SArnaud Giersch * Local Variables: 22438e75f744SArnaud Giersch * mode: c 22448e75f744SArnaud Giersch * c-file-style: "linux" 22458e75f744SArnaud Giersch * indent-tabs-mode: t 22468e75f744SArnaud Giersch * tab-width: 8 22478e75f744SArnaud Giersch * fill-column: 78 22488e75f744SArnaud Giersch * ispell-local-dictionary: "american" 22498e75f744SArnaud Giersch * End: 22508e75f744SArnaud Giersch */ 2251