From: Sudip Mukherjee <sudipm.mukherjee@gmail.com>
To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: linux-kernel@vger.kernel.org,
"Maciej W. Rozycki" <macro@orcam.me.uk>,
Sudip Mukherjee <sudipm.mukherjee@gmail.com>
Subject: [PATCH 3/7] parport_pc: Let chipset drivers mask ECR bits on writes
Date: Sun, 8 Jan 2023 21:56:52 +0000 [thread overview]
Message-ID: <20230108215656.6433-3-sudipm.mukherjee@gmail.com> (raw)
In-Reply-To: <20230108215656.6433-1-sudipm.mukherjee@gmail.com>
From: "Maciej W. Rozycki" <macro@orcam.me.uk>
Provide an `ecr_writable' parameter to `__parport_pc_probe_port' so that
callers can specify a mask of bits to modify on ECR writes.
To avoid the need for separate bit set and bit clear masks always set
bit 0 whenever a non-zero mask has been set, as all the currently known
cases where a mask is required, that is Oxford Semiconductor devices, do
require this bit to be set. If further cases are discovered where the
bit is required to be clear, we can update code accordingly, but chances
are very low as the bit is supposed to be read-only[1].
Skip ECR probing, which can be problematic as the Oxford Semiconductor
OX12PCI840 part has been reported to lock up on setting bit 2, whenever
a non-zero mask has been requested by a port subdriver, assuming that
the ECR must be there if the subdriver has requested a specific way to
access it.
References:
[1] "Extended Capabilities Port Protocol and ISA Interface Standard",
Microsoft Corporation, Revision: 1.14, July 14, 1993, Table 14
"Extended Control Register"
Signed-off-by: Maciej W. Rozycki <macro@orcam.me.uk>
Signed-off-by: Sudip Mukherjee <sudipm.mukherjee@gmail.com>
---
drivers/parport/parport_pc.c | 46 +++++++++++++++++++++++-------------
include/linux/parport_pc.h | 3 +++
2 files changed, 32 insertions(+), 17 deletions(-)
diff --git a/drivers/parport/parport_pc.c b/drivers/parport/parport_pc.c
index 9daaaaa305e6..ad49fd356c7b 100644
--- a/drivers/parport/parport_pc.c
+++ b/drivers/parport/parport_pc.c
@@ -106,15 +106,22 @@ static int pnp_registered_parport;
static void frob_econtrol(struct parport *pb, unsigned char m,
unsigned char v)
{
+ const struct parport_pc_private *priv = pb->physport->private_data;
+ unsigned char ecr_writable = priv->ecr_writable;
unsigned char ectr = 0;
+ unsigned char new;
if (m != 0xff)
ectr = inb(ECONTROL(pb));
- pr_debug("frob_econtrol(%02x,%02x): %02x -> %02x\n",
- m, v, ectr, (ectr & ~m) ^ v);
+ new = (ectr & ~m) ^ v;
+ if (ecr_writable)
+ /* All known users of the ECR mask require bit 0 to be set. */
+ new = (new & ecr_writable) | 1;
- outb((ectr & ~m) ^ v, ECONTROL(pb));
+ pr_debug("frob_econtrol(%02x,%02x): %02x -> %02x\n", m, v, ectr, new);
+
+ outb(new, ECONTROL(pb));
}
static inline void frob_set_mode(struct parport *p, int mode)
@@ -1479,21 +1486,24 @@ static int parport_ECR_present(struct parport *pb)
struct parport_pc_private *priv = pb->private_data;
unsigned char r = 0xc;
- outb(r, CONTROL(pb));
- if ((inb(ECONTROL(pb)) & 0x3) == (r & 0x3)) {
- outb(r ^ 0x2, CONTROL(pb)); /* Toggle bit 1 */
+ if (!priv->ecr_writable) {
+ outb(r, CONTROL(pb));
+ if ((inb(ECONTROL(pb)) & 0x3) == (r & 0x3)) {
+ outb(r ^ 0x2, CONTROL(pb)); /* Toggle bit 1 */
- r = inb(CONTROL(pb));
- if ((inb(ECONTROL(pb)) & 0x2) == (r & 0x2))
- goto no_reg; /* Sure that no ECR register exists */
- }
+ r = inb(CONTROL(pb));
+ if ((inb(ECONTROL(pb)) & 0x2) == (r & 0x2))
+ /* Sure that no ECR register exists */
+ goto no_reg;
+ }
- if ((inb(ECONTROL(pb)) & 0x3) != 0x1)
- goto no_reg;
+ if ((inb(ECONTROL(pb)) & 0x3) != 0x1)
+ goto no_reg;
- ECR_WRITE(pb, 0x34);
- if (inb(ECONTROL(pb)) != 0x35)
- goto no_reg;
+ ECR_WRITE(pb, 0x34);
+ if (inb(ECONTROL(pb)) != 0x35)
+ goto no_reg;
+ }
priv->ecr = 1;
outb(0xc, CONTROL(pb));
@@ -2005,7 +2015,8 @@ static struct parport *__parport_pc_probe_port(unsigned long int base,
int irq, int dma,
struct device *dev,
int irqflags,
- unsigned int mode_mask)
+ unsigned int mode_mask,
+ unsigned char ecr_writable)
{
struct parport_pc_private *priv;
struct parport_operations *ops;
@@ -2054,6 +2065,7 @@ static struct parport *__parport_pc_probe_port(unsigned long int base,
priv->ctr = 0xc;
priv->ctr_writable = ~0x10;
priv->ecr = 0;
+ priv->ecr_writable = ecr_writable;
priv->fifo_depth = 0;
priv->dma_buf = NULL;
priv->dma_handle = 0;
@@ -2256,7 +2268,7 @@ struct parport *parport_pc_probe_port(unsigned long int base,
int irqflags)
{
return __parport_pc_probe_port(base, base_hi, irq, dma,
- dev, irqflags, 0);
+ dev, irqflags, 0, 0);
}
EXPORT_SYMBOL(parport_pc_probe_port);
diff --git a/include/linux/parport_pc.h b/include/linux/parport_pc.h
index 3d6fc576d6a1..f1ec5c10c3b3 100644
--- a/include/linux/parport_pc.h
+++ b/include/linux/parport_pc.h
@@ -26,6 +26,9 @@ struct parport_pc_private {
/* Whether or not there's an ECR. */
int ecr;
+ /* Bitmask of writable ECR bits. */
+ unsigned char ecr_writable;
+
/* Number of PWords that FIFO will hold. */
int fifo_depth;
--
2.30.2
next prev parent reply other threads:[~2023-01-08 21:57 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-01-08 21:56 [PATCH 1/7] parport_pc: Remove stale `parport_pc_ecp_read_block_pio' reference Sudip Mukherjee
2023-01-08 21:56 ` [PATCH 2/7] parport_pc: Let chipset drivers mask unsupported modes Sudip Mukherjee
2023-01-08 21:56 ` Sudip Mukherjee [this message]
2023-01-08 21:56 ` [PATCH 4/7] parport_pc: Add a mode mask field for PCI devices Sudip Mukherjee
2023-01-08 21:56 ` [PATCH 5/7] parport_pc: Add an ECR " Sudip Mukherjee
2023-01-08 21:56 ` [PATCH 6/7] parport_pc: Set up mode and ECR masks for Oxford Semiconductor devices Sudip Mukherjee
2023-01-08 21:56 ` [PATCH 7/7] parport_pc: Limit the number of PCI BAR pairs to 2 Sudip Mukherjee
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20230108215656.6433-3-sudipm.mukherjee@gmail.com \
--to=sudipm.mukherjee@gmail.com \
--cc=gregkh@linuxfoundation.org \
--cc=linux-kernel@vger.kernel.org \
--cc=macro@orcam.me.uk \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®