linux/drivers/parport/parport_pc.c

// SPDX-License-Identifier: GPL-2.0-only
/* Low-level parallel-port routines for 8255-based PC-style hardware.
 *
 * Authors: Phil Blundell <[email protected]>
 *          Tim Waugh <[email protected]>
 *	    Jose Renau <[email protected]>
 *          David Campbell
 *          Andrea Arcangeli
 *
 * based on work by Grant Guenther <[email protected]> and Phil Blundell.
 *
 * Cleaned up include files - Russell King <[email protected]>
 * DMA support - Bert De Jonghe <[email protected]>
 * Many ECP bugs fixed.  Fred Barnes & Jamie Lokier, 1999
 * More PCI support now conditional on CONFIG_PCI, 03/2001, Paul G.
 * Various hacks, Fred Barnes, 04/2001
 * Updated probing logic - Adam Belay <[email protected]>
 */

/* This driver should work with any hardware that is broadly compatible
 * with that in the IBM PC.  This applies to the majority of integrated
 * I/O chipsets that are commonly available.  The expected register
 * layout is:
 *
 *	base+0		data
 *	base+1		status
 *	base+2		control
 *
 * In addition, there are some optional registers:
 *
 *	base+3		EPP address
 *	base+4		EPP data
 *	base+0x400	ECP config A
 *	base+0x401	ECP config B
 *	base+0x402	ECP control
 *
 * All registers are 8 bits wide and read/write.  If your hardware differs
 * only in register addresses (eg because your registers are on 32-bit
 * word boundaries) then you can alter the constants in parport_pc.h to
 * accommodate this.
 *
 * Note that the ECP registers may not start at offset 0x400 for PCI cards,
 * but rather will start at port->base_hi.
 */

#include <linux/module.h>
#include <linux/init.h>
#include <linux/sched/signal.h>
#include <linux/delay.h>
#include <linux/errno.h>
#include <linux/interrupt.h>
#include <linux/ioport.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/dma-mapping.h>
#include <linux/pci.h>
#include <linux/pnp.h>
#include <linux/platform_device.h>
#include <linux/sysctl.h>
#include <linux/io.h>
#include <linux/uaccess.h>

#include <asm/dma.h>

#include <linux/parport.h>
#include <linux/parport_pc.h>
#include <linux/via.h>
#include <asm/parport.h>

#define PARPORT_PC_MAX_PORTS

#ifdef CONFIG_ISA_DMA_API
#define HAS_DMA
#endif

/* ECR modes */
#define ECR_SPP
#define ECR_PS2
#define ECR_PPF
#define ECR_ECP
#define ECR_EPP
#define ECR_VND
#define ECR_TST
#define ECR_CNF
#define ECR_MODE_MASK
#define ECR_WRITE(p, v)

#undef DEBUG

#define NR_SUPERIOS
static struct superio_struct {} superios[NR_SUPERIOS] =;

static int user_specified;
#if defined(CONFIG_PARPORT_PC_SUPERIO) || \
       (defined(CONFIG_PARPORT_1284) && defined(CONFIG_PARPORT_PC_FIFO))
static int verbose_probing;
#endif
static int pci_registered_parport;
static int pnp_registered_parport;

/* frob_control, but for ECR */
static void frob_econtrol(struct parport *pb, unsigned char m,
			   unsigned char v)
{}

static inline void frob_set_mode(struct parport *p, int mode)
{}

#ifdef CONFIG_PARPORT_PC_FIFO
/* Safely change the mode bits in the ECR
   Returns:
	    0    : Success
	   -EBUSY: Could not drain FIFO in some finite amount of time,
		   mode not changed!
 */
static int change_mode(struct parport *p, int m)
{}
#endif /* FIFO support */

/*
 * Clear TIMEOUT BIT in EPP MODE
 *
 * This is also used in SPP detection.
 */
static int clear_epp_timeout(struct parport *pb)
{}

/*
 * Access functions.
 *
 * Most of these aren't static because they may be used by the
 * parport_xxx_yyy macros.  extern __inline__ versions of several
 * of these are in parport_pc.h.
 */

static void parport_pc_init_state(struct pardevice *dev,
						struct parport_state *s)
{}

static void parport_pc_save_state(struct parport *p, struct parport_state *s)
{}

static void parport_pc_restore_state(struct parport *p,
						struct parport_state *s)
{}

#ifdef CONFIG_PARPORT_1284
static size_t parport_pc_epp_read_data(struct parport *port, void *buf,
				       size_t length, int flags)
{}

static size_t parport_pc_epp_write_data(struct parport *port, const void *buf,
					size_t length, int flags)
{}

static size_t parport_pc_epp_read_addr(struct parport *port, void *buf,
					size_t length, int flags)
{}

static size_t parport_pc_epp_write_addr(struct parport *port,
					 const void *buf, size_t length,
					 int flags)
{}

static size_t parport_pc_ecpepp_read_data(struct parport *port, void *buf,
					  size_t length, int flags)
{}

static size_t parport_pc_ecpepp_write_data(struct parport *port,
					   const void *buf, size_t length,
					   int flags)
{}

static size_t parport_pc_ecpepp_read_addr(struct parport *port, void *buf,
					  size_t length, int flags)
{}

static size_t parport_pc_ecpepp_write_addr(struct parport *port,
					    const void *buf, size_t length,
					    int flags)
{}
#endif /* IEEE 1284 support */

#ifdef CONFIG_PARPORT_PC_FIFO
static size_t parport_pc_fifo_write_block_pio(struct parport *port,
					       const void *buf, size_t length)
{}

#ifdef HAS_DMA
static size_t parport_pc_fifo_write_block_dma(struct parport *port,
					       const void *buf, size_t length)
{}
#endif

static inline size_t parport_pc_fifo_write_block(struct parport *port,
					       const void *buf, size_t length)
{}

/* Parallel Port FIFO mode (ECP chipsets) */
static size_t parport_pc_compat_write_block_pio(struct parport *port,
						 const void *buf, size_t length,
						 int flags)
{}

/* ECP */
#ifdef CONFIG_PARPORT_1284
static size_t parport_pc_ecp_write_block_pio(struct parport *port,
					      const void *buf, size_t length,
					      int flags)
{}
#endif /* IEEE 1284 support */
#endif /* Allowed to use FIFO/DMA */


/*
 *	******************************************
 *	INITIALISATION AND MODULE STUFF BELOW HERE
 *	******************************************
 */

/* GCC is not inlining extern inline function later overwritten to non-inline,
   so we use outlined_ variants here.  */
static const struct parport_operations parport_pc_ops =;

#ifdef CONFIG_PARPORT_PC_SUPERIO

static struct superio_struct *find_free_superio(void)
{}


/* Super-IO chipset detection, Winbond, SMSC */
static void show_parconfig_smsc37c669(int io, int key)
{}


static void show_parconfig_winbond(int io, int key)
{}

static void decode_winbond(int efer, int key, int devid, int devrev, int oldid)
{}

static void decode_smsc(int efer, int key, int devid, int devrev)
{}


static void winbond_check(int io, int key)
{}

static void winbond_check2(int io, int key)
{}

static void smsc_check(int io, int key)
{}


static void detect_and_report_winbond(void)
{}

static void detect_and_report_smsc(void)
{}

static void detect_and_report_it87(void)
{}
#endif /* CONFIG_PARPORT_PC_SUPERIO */

static struct superio_struct *find_superio(struct parport *p)
{}

static int get_superio_dma(struct parport *p)
{}

static int get_superio_irq(struct parport *p)
{}


/* --- Mode detection ------------------------------------- */

/*
 * Checks for port existence, all ports support SPP MODE
 * Returns:
 *         0           :  No parallel port at this address
 *  PARPORT_MODE_PCSPP :  SPP port detected
 *                        (if the user specified an ioport himself,
 *                         this shall always be the case!)
 *
 */
static int parport_SPP_supported(struct parport *pb)
{}

/* Check for ECR
 *
 * Old style XT ports alias io ports every 0x400, hence accessing ECR
 * on these cards actually accesses the CTR.
 *
 * Modern cards don't do this but reading from ECR will return 0xff
 * regardless of what is written here if the card does NOT support
 * ECP.
 *
 * We first check to see if ECR is the same as CTR.  If not, the low
 * two bits of ECR aren't writable, so we check by writing ECR and
 * reading it back to see if it's what we expect.
 */
static int parport_ECR_present(struct parport *pb)
{}

#ifdef CONFIG_PARPORT_1284
/* Detect PS/2 support.
 *
 * Bit 5 (0x20) sets the PS/2 data direction; setting this high
 * allows us to read data from the data lines.  In theory we would get back
 * 0xff but any peripheral attached to the port may drag some or all of the
 * lines down to zero.  So if we get back anything that isn't the contents
 * of the data register we deem PS/2 support to be present.
 *
 * Some SPP ports have "half PS/2" ability - you can't turn off the line
 * drivers, but an external peripheral with sufficiently beefy drivers of
 * its own can overpower them and assert its own levels onto the bus, from
 * where they can then be read back as normal.  Ports with this property
 * and the right type of device attached are likely to fail the SPP test,
 * (as they will appear to have stuck bits) and so the fact that they might
 * be misdetected here is rather academic.
 */

static int parport_PS2_supported(struct parport *pb)
{}

#ifdef CONFIG_PARPORT_PC_FIFO
static int parport_ECP_supported(struct parport *pb)
{}
#endif

#ifdef CONFIG_X86_32
static int intel_bug_present_check_epp(struct parport *pb)
{
	const struct parport_pc_private *priv = pb->private_data;
	int bug_present = 0;

	if (priv->ecr) {
		/* store value of ECR */
		unsigned char ecr = inb(ECONTROL(pb));
		unsigned char i;
		for (i = 0x00; i < 0x80; i += 0x20) {
			ECR_WRITE(pb, i);
			if (clear_epp_timeout(pb)) {
				/* Phony EPP in ECP. */
				bug_present = 1;
				break;
			}
		}
		/* return ECR into the inital state */
		ECR_WRITE(pb, ecr);
	}

	return bug_present;
}
static int intel_bug_present(struct parport *pb)
{
/* Check whether the device is legacy, not PCI or PCMCIA. Only legacy is known to be affected. */
	if (pb->dev != NULL) {
		return 0;
	}

	return intel_bug_present_check_epp(pb);
}
#else
static int intel_bug_present(struct parport *pb)
{}
#endif /* CONFIG_X86_32 */

static int parport_ECPPS2_supported(struct parport *pb)
{}

/* EPP mode detection  */

static int parport_EPP_supported(struct parport *pb)
{}

static int parport_ECPEPP_supported(struct parport *pb)
{}

#else /* No IEEE 1284 support */

/* Don't bother probing for modes we know we won't use. */
static int parport_PS2_supported(struct parport *pb) { return 0; }
#ifdef CONFIG_PARPORT_PC_FIFO
static int parport_ECP_supported(struct parport *pb)
{
	return 0;
}
#endif
static int parport_EPP_supported(struct parport *pb)
{
	return 0;
}

static int parport_ECPEPP_supported(struct parport *pb)
{
	return 0;
}

static int parport_ECPPS2_supported(struct parport *pb)
{
	return 0;
}

#endif /* No IEEE 1284 support */

/* --- IRQ detection -------------------------------------- */

/* Only if supports ECP mode */
static int programmable_irq_support(struct parport *pb)
{}

static int irq_probe_ECP(struct parport *pb)
{}

/*
 * This detection seems that only works in National Semiconductors
 * This doesn't work in SMC, LGS, and Winbond
 */
static int irq_probe_EPP(struct parport *pb)
{}

static int irq_probe_SPP(struct parport *pb)
{}

/* We will attempt to share interrupt requests since other devices
 * such as sound cards and network cards seem to like using the
 * printer IRQs.
 *
 * When ECP is available we can autoprobe for IRQs.
 * NOTE: If we can autoprobe it, we can register the IRQ.
 */
static int parport_irq_probe(struct parport *pb)
{}

/* --- DMA detection -------------------------------------- */

/* Only if chipset conforms to ECP ISA Interface Standard */
static int programmable_dma_support(struct parport *p)
{}

static int parport_dma_probe(struct parport *p)
{}

/* --- Initialisation code -------------------------------- */

static LIST_HEAD(ports_list);
static DEFINE_SPINLOCK(ports_lock);

static struct parport *__parport_pc_probe_port(unsigned long int base,
					       unsigned long int base_hi,
					       int irq, int dma,
					       struct device *dev,
					       int irqflags,
					       unsigned int mode_mask,
					       unsigned char ecr_writable)
{}

struct parport *parport_pc_probe_port(unsigned long int base,
				      unsigned long int base_hi,
				      int irq, int dma,
				      struct device *dev,
				      int irqflags)
{}
EXPORT_SYMBOL();

void parport_pc_unregister_port(struct parport *p)
{}
EXPORT_SYMBOL();

#ifdef CONFIG_PCI

/* ITE support maintained by Rich Liu <[email protected]> */
static int sio_ite_8872_probe(struct pci_dev *pdev, int autoirq, int autodma,
			      const struct parport_pc_via_data *via)
{}

/* VIA 8231 support by Pavel Fedin <[email protected]>
   based on VIA 686a support code by Jeff Garzik <[email protected]> */
static int parport_init_mode;

/* Data for two known VIA chips */
static struct parport_pc_via_data via_686a_data =;
static struct parport_pc_via_data via_8231_data =;

static int sio_via_probe(struct pci_dev *pdev, int autoirq, int autodma,
			 const struct parport_pc_via_data *via)
{}


enum parport_pc_sio_types {};

/* each element directly indexed from enum list, above */
static struct parport_pc_superio {} parport_pc_superio_info[] =;

enum parport_pc_pci_cards {};


/* each element directly indexed from enum list, above
 * (but offset by last_sio) */
static struct parport_pc_pci {} cards[] =;

static const struct pci_device_id parport_pc_pci_tbl[] =;
MODULE_DEVICE_TABLE(pci, parport_pc_pci_tbl);

struct pci_parport_data {};

static int parport_pc_pci_probe(struct pci_dev *dev,
					   const struct pci_device_id *id)
{}

static void parport_pc_pci_remove(struct pci_dev *dev)
{}

static struct pci_driver parport_pc_pci_driver =;

static int __init parport_pc_init_superio(int autoirq, int autodma)
{}
#else
static struct pci_driver parport_pc_pci_driver;
static int __init parport_pc_init_superio(int autoirq, int autodma)
{
	return 0;
}
#endif /* CONFIG_PCI */

#ifdef CONFIG_PNP

static const struct pnp_device_id parport_pc_pnp_tbl[] =;

MODULE_DEVICE_TABLE(pnp, parport_pc_pnp_tbl);

static int parport_pc_pnp_probe(struct pnp_dev *dev,
						const struct pnp_device_id *id)
{}

static void parport_pc_pnp_remove(struct pnp_dev *dev)
{}

/* we only need the pnp layer to activate the device, at least for now */
static struct pnp_driver parport_pc_pnp_driver =;

#else
static struct pnp_driver parport_pc_pnp_driver;
#endif /* CONFIG_PNP */

static int parport_pc_platform_probe(struct platform_device *pdev)
{}

static struct platform_driver parport_pc_platform_driver =;

/* This is called by parport_pc_find_nonpci_ports (in asm/parport.h) */
static int __attribute__((unused))
parport_pc_find_isa_ports(int autoirq, int autodma)
{}

/* This function is called by parport_pc_init if the user didn't
 * specify any ports to probe.  Its job is to find some ports.  Order
 * is important here -- we want ISA ports to be registered first,
 * followed by PCI cards (for least surprise), but before that we want
 * to do chipset-specific tests for some onboard ports that we know
 * about.
 *
 * autoirq is PARPORT_IRQ_NONE, PARPORT_IRQ_AUTO, or PARPORT_IRQ_PROBEONLY
 * autodma is PARPORT_DMA_NONE or PARPORT_DMA_AUTO
 */
static void __init parport_pc_find_ports(int autoirq, int autodma)
{}

/*
 *	Piles of crap below pretend to be a parser for module and kernel
 *	parameters.  Say "thank you" to whoever had come up with that
 *	syntax and keep in mind that code below is a cleaned up version.
 */

static int __initdata io[PARPORT_PC_MAX_PORTS+1] =;
static int __initdata io_hi[PARPORT_PC_MAX_PORTS+1] =;
static int __initdata dmaval[PARPORT_PC_MAX_PORTS] =;
static int __initdata irqval[PARPORT_PC_MAX_PORTS] =;

static int __init parport_parse_param(const char *s, int *val,
				int automatic, int none, int nofifo)
{}

static int __init parport_parse_irq(const char *irqstr, int *val)
{}

static int __init parport_parse_dma(const char *dmastr, int *val)
{}

#ifdef CONFIG_PCI
static int __init parport_init_mode_setup(char *str)
{}
#endif

#ifdef MODULE
static char *irq[PARPORT_PC_MAX_PORTS];
static char *dma[PARPORT_PC_MAX_PORTS];

MODULE_PARM_DESC(io, "Base I/O address (SPP regs)");
module_param_hw_array(io, int, ioport, NULL, 0);
MODULE_PARM_DESC(io_hi, "Base I/O address (ECR)");
module_param_hw_array(io_hi, int, ioport, NULL, 0);
MODULE_PARM_DESC(irq, "IRQ line");
module_param_hw_array(irq, charp, irq, NULL, 0);
MODULE_PARM_DESC(dma, "DMA channel");
module_param_hw_array(dma, charp, dma, NULL, 0);
#if defined(CONFIG_PARPORT_PC_SUPERIO) || \
       (defined(CONFIG_PARPORT_1284) && defined(CONFIG_PARPORT_PC_FIFO))
MODULE_PARM_DESC(verbose_probing, "Log chit-chat during initialisation");
module_param(verbose_probing, int, 0644);
#endif
#ifdef CONFIG_PCI
static char *init_mode;
MODULE_PARM_DESC(init_mode,
	"Initialise mode for VIA VT8231 port (spp, ps2, epp, ecp or ecpepp)");
module_param(init_mode, charp, 0);
#endif

static int __init parse_parport_params(void)
{
	unsigned int i;
	int val;

#ifdef CONFIG_PCI
	if (init_mode)
		parport_init_mode_setup(init_mode);
#endif

	for (i = 0; i < PARPORT_PC_MAX_PORTS && io[i]; i++) {
		if (parport_parse_irq(irq[i], &val))
			return 1;
		irqval[i] = val;
		if (parport_parse_dma(dma[i], &val))
			return 1;
		dmaval[i] = val;
	}
	if (!io[0]) {
		/* The user can make us use any IRQs or DMAs we find. */
		if (irq[0] && !parport_parse_irq(irq[0], &val))
			switch (val) {
			case PARPORT_IRQ_NONE:
			case PARPORT_IRQ_AUTO:
				irqval[0] = val;
				break;
			default:
				pr_warn("parport_pc: irq specified without base address.  Use 'io=' to specify one\n");
			}

		if (dma[0] && !parport_parse_dma(dma[0], &val))
			switch (val) {
			case PARPORT_DMA_NONE:
			case PARPORT_DMA_AUTO:
				dmaval[0] = val;
				break;
			default:
				pr_warn("parport_pc: dma specified without base address.  Use 'io=' to specify one\n");
			}
	}
	return 0;
}

#else

static int parport_setup_ptr __initdata;

/*
 * Acceptable parameters:
 *
 * parport=0
 * parport=auto
 * parport=0xBASE[,IRQ[,DMA]]
 *
 * IRQ/DMA may be numeric or 'auto' or 'none'
 */
static int __init parport_setup(char *str)
{}

static int __init parse_parport_params(void)
{}

__setup();

/*
 * Acceptable parameters:
 *
 * parport_init_mode=[spp|ps2|epp|ecp|ecpepp]
 */
#ifdef CONFIG_PCI
__setup();
#endif
#endif

/* "Parser" ends here */

static int __init parport_pc_init(void)
{}

static void __exit parport_pc_exit(void)
{}

MODULE_AUTHOR();
MODULE_DESCRIPTION();
MODULE_LICENSE();
module_init()
module_exit()