1b2441318SGreg Kroah-Hartman /* SPDX-License-Identifier: GPL-2.0 */
21da177e4SLinus Torvalds #ifndef __LINUX_PARPORT_PC_H
31da177e4SLinus Torvalds #define __LINUX_PARPORT_PC_H
41da177e4SLinus Torvalds
51da177e4SLinus Torvalds #include <asm/io.h>
61da177e4SLinus Torvalds
71da177e4SLinus Torvalds /* --- register definitions ------------------------------- */
81da177e4SLinus Torvalds
91da177e4SLinus Torvalds #define ECONTROL(p) ((p)->base_hi + 0x2)
101da177e4SLinus Torvalds #define CONFIGB(p) ((p)->base_hi + 0x1)
111da177e4SLinus Torvalds #define CONFIGA(p) ((p)->base_hi + 0x0)
121da177e4SLinus Torvalds #define FIFO(p) ((p)->base_hi + 0x0)
131da177e4SLinus Torvalds #define EPPDATA(p) ((p)->base + 0x4)
141da177e4SLinus Torvalds #define EPPADDR(p) ((p)->base + 0x3)
151da177e4SLinus Torvalds #define CONTROL(p) ((p)->base + 0x2)
161da177e4SLinus Torvalds #define STATUS(p) ((p)->base + 0x1)
171da177e4SLinus Torvalds #define DATA(p) ((p)->base + 0x0)
181da177e4SLinus Torvalds
191da177e4SLinus Torvalds struct parport_pc_private {
201da177e4SLinus Torvalds /* Contents of CTR. */
211da177e4SLinus Torvalds unsigned char ctr;
221da177e4SLinus Torvalds
231da177e4SLinus Torvalds /* Bitmask of writable CTR bits. */
241da177e4SLinus Torvalds unsigned char ctr_writable;
251da177e4SLinus Torvalds
261da177e4SLinus Torvalds /* Whether or not there's an ECR. */
271da177e4SLinus Torvalds int ecr;
281da177e4SLinus Torvalds
29*6640727fSMaciej W. Rozycki /* Bitmask of writable ECR bits. */
30*6640727fSMaciej W. Rozycki unsigned char ecr_writable;
31*6640727fSMaciej W. Rozycki
321da177e4SLinus Torvalds /* Number of PWords that FIFO will hold. */
331da177e4SLinus Torvalds int fifo_depth;
341da177e4SLinus Torvalds
351da177e4SLinus Torvalds /* Number of bytes per portword. */
361da177e4SLinus Torvalds int pword;
371da177e4SLinus Torvalds
381da177e4SLinus Torvalds /* Not used yet. */
391da177e4SLinus Torvalds int readIntrThreshold;
401da177e4SLinus Torvalds int writeIntrThreshold;
411da177e4SLinus Torvalds
421da177e4SLinus Torvalds /* buffer suitable for DMA, if DMA enabled */
431da177e4SLinus Torvalds char *dma_buf;
441da177e4SLinus Torvalds dma_addr_t dma_handle;
451da177e4SLinus Torvalds struct list_head list;
461da177e4SLinus Torvalds struct parport *port;
471da177e4SLinus Torvalds };
481da177e4SLinus Torvalds
491da177e4SLinus Torvalds struct parport_pc_via_data
501da177e4SLinus Torvalds {
511da177e4SLinus Torvalds /* ISA PnP IRQ routing register 1 */
521da177e4SLinus Torvalds u8 via_pci_parport_irq_reg;
531da177e4SLinus Torvalds /* ISA PnP DMA request routing register */
541da177e4SLinus Torvalds u8 via_pci_parport_dma_reg;
551da177e4SLinus Torvalds /* Register and value to enable SuperIO configuration access */
561da177e4SLinus Torvalds u8 via_pci_superio_config_reg;
571da177e4SLinus Torvalds u8 via_pci_superio_config_data;
581da177e4SLinus Torvalds /* SuperIO function register number */
591da177e4SLinus Torvalds u8 viacfg_function;
601da177e4SLinus Torvalds /* parallel port control register number */
611da177e4SLinus Torvalds u8 viacfg_parport_control;
621da177e4SLinus Torvalds /* Parallel port base address register */
631da177e4SLinus Torvalds u8 viacfg_parport_base;
641da177e4SLinus Torvalds };
651da177e4SLinus Torvalds
parport_pc_write_data(struct parport * p,unsigned char d)661da177e4SLinus Torvalds static __inline__ void parport_pc_write_data(struct parport *p, unsigned char d)
671da177e4SLinus Torvalds {
681da177e4SLinus Torvalds #ifdef DEBUG_PARPORT
691da177e4SLinus Torvalds printk (KERN_DEBUG "parport_pc_write_data(%p,0x%02x)\n", p, d);
701da177e4SLinus Torvalds #endif
711da177e4SLinus Torvalds outb(d, DATA(p));
721da177e4SLinus Torvalds }
731da177e4SLinus Torvalds
parport_pc_read_data(struct parport * p)741da177e4SLinus Torvalds static __inline__ unsigned char parport_pc_read_data(struct parport *p)
751da177e4SLinus Torvalds {
761da177e4SLinus Torvalds unsigned char val = inb (DATA (p));
771da177e4SLinus Torvalds #ifdef DEBUG_PARPORT
781da177e4SLinus Torvalds printk (KERN_DEBUG "parport_pc_read_data(%p) = 0x%02x\n",
791da177e4SLinus Torvalds p, val);
801da177e4SLinus Torvalds #endif
811da177e4SLinus Torvalds return val;
821da177e4SLinus Torvalds }
831da177e4SLinus Torvalds
841da177e4SLinus Torvalds #ifdef DEBUG_PARPORT
dump_parport_state(char * str,struct parport * p)8581684ee6SAdrian Bunk static inline void dump_parport_state (char *str, struct parport *p)
861da177e4SLinus Torvalds {
871da177e4SLinus Torvalds /* here's hoping that reading these ports won't side-effect anything underneath */
881da177e4SLinus Torvalds unsigned char ecr = inb (ECONTROL (p));
891da177e4SLinus Torvalds unsigned char dcr = inb (CONTROL (p));
901da177e4SLinus Torvalds unsigned char dsr = inb (STATUS (p));
91110bee75SMarko Kohtala static const char *const ecr_modes[] = {"SPP", "PS2", "PPFIFO", "ECP", "xXx", "yYy", "TST", "CFG"};
9268799398SDave Jones const struct parport_pc_private *priv = p->physport->private_data;
931da177e4SLinus Torvalds int i;
941da177e4SLinus Torvalds
951da177e4SLinus Torvalds printk (KERN_DEBUG "*** parport state (%s): ecr=[%s", str, ecr_modes[(ecr & 0xe0) >> 5]);
961da177e4SLinus Torvalds if (ecr & 0x10) printk (",nErrIntrEn");
971da177e4SLinus Torvalds if (ecr & 0x08) printk (",dmaEn");
981da177e4SLinus Torvalds if (ecr & 0x04) printk (",serviceIntr");
991da177e4SLinus Torvalds if (ecr & 0x02) printk (",f_full");
1001da177e4SLinus Torvalds if (ecr & 0x01) printk (",f_empty");
1011da177e4SLinus Torvalds for (i=0; i<2; i++) {
1021da177e4SLinus Torvalds printk ("] dcr(%s)=[", i ? "soft" : "hard");
1031da177e4SLinus Torvalds dcr = i ? priv->ctr : inb (CONTROL (p));
1041da177e4SLinus Torvalds
1051da177e4SLinus Torvalds if (dcr & 0x20) {
1061da177e4SLinus Torvalds printk ("rev");
1071da177e4SLinus Torvalds } else {
1081da177e4SLinus Torvalds printk ("fwd");
1091da177e4SLinus Torvalds }
1101da177e4SLinus Torvalds if (dcr & 0x10) printk (",ackIntEn");
1111da177e4SLinus Torvalds if (!(dcr & 0x08)) printk (",N-SELECT-IN");
1121da177e4SLinus Torvalds if (dcr & 0x04) printk (",N-INIT");
1131da177e4SLinus Torvalds if (!(dcr & 0x02)) printk (",N-AUTOFD");
1141da177e4SLinus Torvalds if (!(dcr & 0x01)) printk (",N-STROBE");
1151da177e4SLinus Torvalds }
1161da177e4SLinus Torvalds printk ("] dsr=[");
1171da177e4SLinus Torvalds if (!(dsr & 0x80)) printk ("BUSY");
1181da177e4SLinus Torvalds if (dsr & 0x40) printk (",N-ACK");
1191da177e4SLinus Torvalds if (dsr & 0x20) printk (",PERROR");
1201da177e4SLinus Torvalds if (dsr & 0x10) printk (",SELECT");
1211da177e4SLinus Torvalds if (dsr & 0x08) printk (",N-FAULT");
1221da177e4SLinus Torvalds printk ("]\n");
1231da177e4SLinus Torvalds return;
1241da177e4SLinus Torvalds }
1251da177e4SLinus Torvalds #else /* !DEBUG_PARPORT */
1261da177e4SLinus Torvalds #define dump_parport_state(args...)
1271da177e4SLinus Torvalds #endif /* !DEBUG_PARPORT */
1281da177e4SLinus Torvalds
1291da177e4SLinus Torvalds /* __parport_pc_frob_control differs from parport_pc_frob_control in that
1301da177e4SLinus Torvalds * it doesn't do any extra masking. */
__parport_pc_frob_control(struct parport * p,unsigned char mask,unsigned char val)1311da177e4SLinus Torvalds static __inline__ unsigned char __parport_pc_frob_control (struct parport *p,
1321da177e4SLinus Torvalds unsigned char mask,
1331da177e4SLinus Torvalds unsigned char val)
1341da177e4SLinus Torvalds {
1351da177e4SLinus Torvalds struct parport_pc_private *priv = p->physport->private_data;
1361da177e4SLinus Torvalds unsigned char ctr = priv->ctr;
1371da177e4SLinus Torvalds #ifdef DEBUG_PARPORT
1381da177e4SLinus Torvalds printk (KERN_DEBUG
1391da177e4SLinus Torvalds "__parport_pc_frob_control(%02x,%02x): %02x -> %02x\n",
1401da177e4SLinus Torvalds mask, val, ctr, ((ctr & ~mask) ^ val) & priv->ctr_writable);
1411da177e4SLinus Torvalds #endif
1421da177e4SLinus Torvalds ctr = (ctr & ~mask) ^ val;
1431da177e4SLinus Torvalds ctr &= priv->ctr_writable; /* only write writable bits. */
1441da177e4SLinus Torvalds outb (ctr, CONTROL (p));
1451da177e4SLinus Torvalds priv->ctr = ctr; /* Update soft copy */
1461da177e4SLinus Torvalds return ctr;
1471da177e4SLinus Torvalds }
1481da177e4SLinus Torvalds
parport_pc_data_reverse(struct parport * p)1491da177e4SLinus Torvalds static __inline__ void parport_pc_data_reverse (struct parport *p)
1501da177e4SLinus Torvalds {
1511da177e4SLinus Torvalds __parport_pc_frob_control (p, 0x20, 0x20);
1521da177e4SLinus Torvalds }
1531da177e4SLinus Torvalds
parport_pc_data_forward(struct parport * p)1541da177e4SLinus Torvalds static __inline__ void parport_pc_data_forward (struct parport *p)
1551da177e4SLinus Torvalds {
1561da177e4SLinus Torvalds __parport_pc_frob_control (p, 0x20, 0x00);
1571da177e4SLinus Torvalds }
1581da177e4SLinus Torvalds
parport_pc_write_control(struct parport * p,unsigned char d)1591da177e4SLinus Torvalds static __inline__ void parport_pc_write_control (struct parport *p,
1601da177e4SLinus Torvalds unsigned char d)
1611da177e4SLinus Torvalds {
1621da177e4SLinus Torvalds const unsigned char wm = (PARPORT_CONTROL_STROBE |
1631da177e4SLinus Torvalds PARPORT_CONTROL_AUTOFD |
1641da177e4SLinus Torvalds PARPORT_CONTROL_INIT |
1651da177e4SLinus Torvalds PARPORT_CONTROL_SELECT);
1661da177e4SLinus Torvalds
1671da177e4SLinus Torvalds /* Take this out when drivers have adapted to newer interface. */
1681da177e4SLinus Torvalds if (d & 0x20) {
1691da177e4SLinus Torvalds printk (KERN_DEBUG "%s (%s): use data_reverse for this!\n",
1701da177e4SLinus Torvalds p->name, p->cad->name);
1711da177e4SLinus Torvalds parport_pc_data_reverse (p);
1721da177e4SLinus Torvalds }
1731da177e4SLinus Torvalds
1741da177e4SLinus Torvalds __parport_pc_frob_control (p, wm, d & wm);
1751da177e4SLinus Torvalds }
1761da177e4SLinus Torvalds
parport_pc_read_control(struct parport * p)1771da177e4SLinus Torvalds static __inline__ unsigned char parport_pc_read_control(struct parport *p)
1781da177e4SLinus Torvalds {
1791da177e4SLinus Torvalds const unsigned char rm = (PARPORT_CONTROL_STROBE |
1801da177e4SLinus Torvalds PARPORT_CONTROL_AUTOFD |
1811da177e4SLinus Torvalds PARPORT_CONTROL_INIT |
1821da177e4SLinus Torvalds PARPORT_CONTROL_SELECT);
1831da177e4SLinus Torvalds const struct parport_pc_private *priv = p->physport->private_data;
1841da177e4SLinus Torvalds return priv->ctr & rm; /* Use soft copy */
1851da177e4SLinus Torvalds }
1861da177e4SLinus Torvalds
parport_pc_frob_control(struct parport * p,unsigned char mask,unsigned char val)1871da177e4SLinus Torvalds static __inline__ unsigned char parport_pc_frob_control (struct parport *p,
1881da177e4SLinus Torvalds unsigned char mask,
1891da177e4SLinus Torvalds unsigned char val)
1901da177e4SLinus Torvalds {
1911da177e4SLinus Torvalds const unsigned char wm = (PARPORT_CONTROL_STROBE |
1921da177e4SLinus Torvalds PARPORT_CONTROL_AUTOFD |
1931da177e4SLinus Torvalds PARPORT_CONTROL_INIT |
1941da177e4SLinus Torvalds PARPORT_CONTROL_SELECT);
1951da177e4SLinus Torvalds
1961da177e4SLinus Torvalds /* Take this out when drivers have adapted to newer interface. */
1971da177e4SLinus Torvalds if (mask & 0x20) {
1981da177e4SLinus Torvalds printk (KERN_DEBUG "%s (%s): use data_%s for this!\n",
1991da177e4SLinus Torvalds p->name, p->cad->name,
2001da177e4SLinus Torvalds (val & 0x20) ? "reverse" : "forward");
2011da177e4SLinus Torvalds if (val & 0x20)
2021da177e4SLinus Torvalds parport_pc_data_reverse (p);
2031da177e4SLinus Torvalds else
2041da177e4SLinus Torvalds parport_pc_data_forward (p);
2051da177e4SLinus Torvalds }
2061da177e4SLinus Torvalds
2071da177e4SLinus Torvalds /* Restrict mask and val to control lines. */
2081da177e4SLinus Torvalds mask &= wm;
2091da177e4SLinus Torvalds val &= wm;
2101da177e4SLinus Torvalds
2111da177e4SLinus Torvalds return __parport_pc_frob_control (p, mask, val);
2121da177e4SLinus Torvalds }
2131da177e4SLinus Torvalds
parport_pc_read_status(struct parport * p)2141da177e4SLinus Torvalds static __inline__ unsigned char parport_pc_read_status(struct parport *p)
2151da177e4SLinus Torvalds {
2161da177e4SLinus Torvalds return inb(STATUS(p));
2171da177e4SLinus Torvalds }
2181da177e4SLinus Torvalds
2191da177e4SLinus Torvalds
parport_pc_disable_irq(struct parport * p)2201da177e4SLinus Torvalds static __inline__ void parport_pc_disable_irq(struct parport *p)
2211da177e4SLinus Torvalds {
2221da177e4SLinus Torvalds __parport_pc_frob_control (p, 0x10, 0x00);
2231da177e4SLinus Torvalds }
2241da177e4SLinus Torvalds
parport_pc_enable_irq(struct parport * p)2251da177e4SLinus Torvalds static __inline__ void parport_pc_enable_irq(struct parport *p)
2261da177e4SLinus Torvalds {
2271da177e4SLinus Torvalds __parport_pc_frob_control (p, 0x10, 0x10);
2281da177e4SLinus Torvalds }
2291da177e4SLinus Torvalds
2301da177e4SLinus Torvalds extern void parport_pc_release_resources(struct parport *p);
2311da177e4SLinus Torvalds
2321da177e4SLinus Torvalds extern int parport_pc_claim_resources(struct parport *p);
2331da177e4SLinus Torvalds
2341da177e4SLinus Torvalds /* PCMCIA code will want to get us to look at a port. Provide a mechanism. */
2351da177e4SLinus Torvalds extern struct parport *parport_pc_probe_port(unsigned long base,
2361da177e4SLinus Torvalds unsigned long base_hi,
2371da177e4SLinus Torvalds int irq, int dma,
23851dcdfecSAlan Cox struct device *dev,
23951dcdfecSAlan Cox int irqflags);
2401da177e4SLinus Torvalds extern void parport_pc_unregister_port(struct parport *p);
2411da177e4SLinus Torvalds
2421da177e4SLinus Torvalds #endif
243