lkml.org 
[lkml]   [1997]   [Jul]   [13]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
Date
From
SubjectPPA update
Hi,

I've played a bit with the PPA driver and found it doesn't work at all
with my ECP/EPP ports. I've found a couple of bugs then and re-wrote the
/proc interface (now 3x shorter).

Have a nice fortnight
--
Martin `MJ' Mares <mj@gts.cz> http://atrey.karlin.mff.cuni.cz/~mj/
Faculty of Math and Physics, Charles University, Prague, Czech Rep., Earth
"What color is a chameleon on a mirror?"


--- ./drivers/pnp/parport_init.c.mj Sun Jul 13 19:26:51 1997
+++ ./drivers/pnp/parport_init.c Sun Jul 13 19:47:52 1997
@@ -196,7 +196,7 @@
/*
* Clear TIMEOUT BIT in EPP MODE
*/
-static int epp_clear_timeout(struct parport *pb)
+int epp_clear_timeout(struct parport *pb)
{
int r;

@@ -810,6 +810,7 @@
EXPORT_SYMBOL(parport_unregister_device);
EXPORT_SYMBOL(parport_enumerate);
EXPORT_SYMBOL(parport_ieee1284_nibble_mode_ok);
+EXPORT_SYMBOL(epp_clear_timeout);

#ifdef CONFIG_PNP_PARPORT_AUTOPROBE
EXPORT_SYMBOL(parport_probe);
--- ./drivers/scsi/ppa.c.mj Sun Jul 13 18:56:12 1997
+++ ./drivers/scsi/ppa.c Sun Jul 13 21:17:00 1997
@@ -113,6 +113,14 @@
* Hmm... I think I know a way but it will send the driver into
* ALPHA state again.
* [Curtin-1-08-STABLE]
+ *
+ * More hacks by Martin Mares <mj@atrey.karlin.mff.cuni.cz>, 13-07-97
+ * - Allowed user override of protocol type in ppa_struct.
+ * - Correct programming of ECR register for ECP+EPP ports. Without this,
+ * PPA didn't work with most ECP+EPP ports not previously set to the
+ * EPP mode manually.
+ * - Using correct algorithm for resetting of the EPP timeout bit.
+ * - New /proc interface.
*/

#include <linux/config.h>
@@ -161,21 +169,31 @@
} ppa_struct;

static void ppa_interrupt(void *data);
-/* I know that this is a mess but it works!! */
-#define NO_HOSTS 4
+
+/*
+ * Table of known PPA hosts. Feel free to change PPA_AUTODETECT to specific
+ * protocol type if the auto-detection doesn't work for you.
+ */
+
+#define NO_HOSTS 4 /* Should be enough as we can't have more than 4 parports */
+
static ppa_struct ppa_hosts[NO_HOSTS] =
{
{0, 6, 1, CONFIG_SCSI_PPA_EPP_TIME, PPA_AUTODETECT, 0, -1, 0, DID_ERROR, 1, NULL, NULL,
- {0, 0, ppa_interrupt, NULL}, NULL},
+ {0, 0, ppa_interrupt, NULL}, NULL },
{0, 6, 1, CONFIG_SCSI_PPA_EPP_TIME, PPA_AUTODETECT, 0, -1, 0, DID_ERROR, 1, NULL, NULL,
- {0, 0, ppa_interrupt, NULL}, NULL},
+ {0, 0, ppa_interrupt, NULL}, NULL },
{0, 6, 1, CONFIG_SCSI_PPA_EPP_TIME, PPA_AUTODETECT, 0, -1, 0, DID_ERROR, 1, NULL, NULL,
- {0, 0, ppa_interrupt, NULL}, NULL},
+ {0, 0, ppa_interrupt, NULL}, NULL },
{0, 6, 1, CONFIG_SCSI_PPA_EPP_TIME, PPA_AUTODETECT, 0, -1, 0, DID_ERROR, 1, NULL, NULL,
- {0, 0, ppa_interrupt, NULL}, NULL}
+ {0, 0, ppa_interrupt, NULL}, NULL }
};

-/* This is a global option */
+/*
+ * Default timing parameters. If you can, use the /proc interface instead of
+ * chaning the global values here.
+ */
+
static int ppa_speed = -1; /* Set to >0 to act as a global value */
static int ppa_speed_fast = -1; /* ditto.. */
static int ppa_sg = SG_ALL; /* enable/disable scatter-gather. */
@@ -236,17 +254,19 @@

static int ppa_pb_claim(int host_no)
{
- if (parport_claim(ppa_hosts[host_no].dev)) {
- sleep_on(&ppa_hosts[host_no].ppa_wait_q);
- ppa_hosts[host_no].ppa_wait_q = NULL;
+ ppa_struct *h = &ppa_hosts[host_no];
+
+ if (parport_claim(h->dev)) {
+ sleep_on(&h->ppa_wait_q);
+ h->ppa_wait_q = NULL;

/* Check to see if we were aborted or reset */
- if (ppa_hosts[host_no].dev->port->cad !=
- ppa_hosts[host_no].dev) {
+ if (h->dev->port->cad != h->dev) {
printk("Abort detected on ppa%i\n", host_no);
return 1;
}
}
+
return 0;
}

@@ -473,6 +493,7 @@
ppa_hosts[host_no].timeout++;
printk("PPA: EPP timeout on port 0x%04x\n",
PPA_BASE(host_no));
+ epp_clear_timeout(ppa_hosts[host_no].dev->port);
ppa_fail(host_no, DID_BUS_BUSY);
return 0;
}
@@ -519,6 +540,7 @@
w_str(host_no, r & 0xfe);
ppa_hosts[host_no].timeout++;
printk("PPA: warning: EPP timeout\n");
+ epp_clear_timeout(ppa_hosts[host_no].dev->port);
ppa_fail(host_no, DID_BUS_BUSY);
return 0;
} else
@@ -1127,8 +1149,9 @@
struct Scsi_Host *hreg;
int rs;
int ports;
- int i, nhosts;
+ int i, nhosts, mode;
struct parport *pb = parport_enumerate();
+ ppa_struct *h;

printk("PPA driver version: %s\n", PPA_VERSION);
nhosts = 0;
@@ -1139,44 +1162,60 @@
/* We only understand PC-style ports */
if (modes & PARPORT_MODE_SPP) {

+ h = &ppa_hosts[i];
+
/* transfer global values here */
if (ppa_speed >= 0)
- ppa_hosts[i].speed = ppa_speed;
+ h->speed = ppa_speed;
if (ppa_speed_fast >= 0)
- ppa_hosts[i].speed_fast = ppa_speed_fast;
-
- ppa_hosts[i].dev = parport_register_device(pb, "ppa",
+ h->speed_fast = ppa_speed_fast;
+
+ h->dev = parport_register_device(pb, "ppa",
NULL, ppa_wakeup, NULL,
- PARPORT_DEV_TRAN, (void *) &ppa_hosts[i]);
-
+ PARPORT_DEV_TRAN, (void *) h);
+
/* Claim the bus so it remembers what we do to the
* control registers. [ CTR and ECP ]
*/
ppa_pb_claim(i);
w_ctr(i, 0x0c);

- ppa_hosts[i].mode = PPA_NIBBLE;
- if (modes & (PARPORT_MODE_EPP | PARPORT_MODE_ECPEPP)) {
- ppa_hosts[i].mode = PPA_EPP_32;
- printk("PPA: Parport [ EPP ]\n");
- } else if (modes & PARPORT_MODE_ECP) {
- w_ecr(i, 0x20);
- ppa_hosts[i].mode = PPA_PS2;
- printk("PPA: Parport [ ECP in PS2 submode ]\n");
- } else if (modes & PARPORT_MODE_PS2) {
- ppa_hosts[i].mode = PPA_PS2;
- printk("PPA: Parport [ PS2 ]\n");
+ if (!(mode = h->mode)) {
+ if (modes & (PARPORT_MODE_EPP | PARPORT_MODE_ECPEPP))
+ mode = PPA_EPP_32;
+ else if (modes & (PARPORT_MODE_ECP | PARPORT_MODE_PS2))
+ mode = PPA_PS2;
+ else
+ mode = PPA_NIBBLE;
}
+ printk("PPA: Parport [ %s ]\n", PPA_MODE_STRING[mode]);
+
+ /* In case we have an ECP port, switch it to the desired mode. */
+ if (modes & (PARPORT_MODE_ECP | PARPORT_MODE_ECPEPP)) {
+ w_ecr(i, 0x00); /* We must reset it to the standard mode first */
+ switch (mode) {
+ case PPA_PS2:
+ w_ecr(i, 0x20);
+ break;
+ case PPA_EPP_8:
+ case PPA_EPP_16:
+ case PPA_EPP_32:
+ w_ecr(i, 0x80);
+ break;
+ }
+ }
+
/* Done configuration */
+ h->mode = mode;
ppa_pb_release(i);

rs = ppa_init(i);
if (rs) {
- parport_unregister_device(ppa_hosts[i].dev);
+ parport_unregister_device(h->dev);
continue;
}
/* now the glue ... */
- switch (ppa_hosts[i].mode) {
+ switch (mode) {
case PPA_NIBBLE:
case PPA_PS2:
ports = 3;
@@ -1197,7 +1236,7 @@
hreg->n_io_port = ports;
hreg->dma_channel = -1;
hreg->unique_id = i;
- ppa_hosts[i].host = hreg->host_no;
+ h->host = hreg->host_no;
nhosts++;
}
}
@@ -1225,105 +1264,74 @@
return 0;
}

-static int ppa_proc_write(int hostno, char *buffer, int length)
+static int ppa_proc_write(ppa_struct *h, char *buffer, int length)
{
unsigned long x;
- const char *inv_num = "ppa /proc entry passed invalid number\n";
+ const char *inv_num = KERN_ERR "ppa: /proc entry passed an invalid number\n";

if ((length > 15) && (ppa_strncmp(buffer, "ppa_speed_fast=", 15) == 0)) {
x = simple_strtoul(buffer + 15, NULL, 0);
- if (x <= ppa_hosts[hostno].speed)
- ppa_hosts[hostno].speed_fast = x;
+ if (x <= h->speed)
+ h->speed_fast = x;
else
printk(inv_num);
return length;
}
if ((length > 10) && (ppa_strncmp(buffer, "ppa_speed=", 10) == 0)) {
x = simple_strtoul(buffer + 10, NULL, 0);
- if (x >= ppa_hosts[hostno].speed_fast)
- ppa_hosts[hostno].speed = x;
+ if (x >= h->speed_fast)
+ h->speed = x;
else
printk(inv_num);
return length;
}
if ((length > 10) && (ppa_strncmp(buffer, "epp_speed=", 10) == 0)) {
x = simple_strtoul(buffer + 10, NULL, 0);
- ppa_hosts[hostno].epp_speed = x;
+ h->epp_speed = x;
return length;
}
if ((length > 12) && (ppa_strncmp(buffer, "epp_timeout=", 12) == 0)) {
x = simple_strtoul(buffer + 12, NULL, 0);
- ppa_hosts[hostno].timeout = x;
+ h->timeout = x;
return length;
}
if ((length > 5) && (ppa_strncmp(buffer, "mode=", 5) == 0)) {
x = simple_strtoul(buffer + 5, NULL, 0);
- ppa_hosts[hostno].mode = x;
+ h->mode = x;
return length;
}
- printk("ppa /proc: invalid variable\n");
- return (-EINVAL);
+ printk(KERN_ERR "ppa: /proc: invalid variable\n");
+ return -EINVAL;
}

int ppa_proc_info(char *buffer, char **start, off_t offset,
int length, int hostno, int inout)
{
- int i;
- int size, len = 0;
- off_t begin = 0;
- off_t pos = 0;
+ int i, len;
+ char *p = buffer;
+ ppa_struct *h;

- for (i = 0; i < 4; i++)
+ for (i = 0; i < NO_HOSTS; i++)
if (ppa_hosts[i].host == hostno)
break;
+ if (i >= NO_HOSTS)
+ return -ENXIO;
+ h = &ppa_hosts[i];

if (inout)
- return ppa_proc_write(i, buffer, length);
-
- size = sprintf(buffer + len, "Version : %s\n", PPA_VERSION);
- len += size;
- pos = begin + len;
- size = sprintf(buffer + len, "Parport : %s\n",
- ppa_hosts[i].dev->port->name);
- len += size;
- pos = begin + len;
-
- size = sprintf(buffer + len, "Mode : %s\n",
- PPA_MODE_STRING[ppa_hosts[i].mode]);
- len += size;
- pos = begin + len;
-
- size = sprintf(buffer + len, "\nTiming Parameters\n");
- len += size;
- pos = begin + len;
-
- size = sprintf(buffer + len, "ppa_speed %i\n",
- ppa_hosts[i].speed);
- len += size;
- pos = begin + len;
-
- size = sprintf(buffer + len, "ppa_speed_fast %i\n",
- ppa_hosts[i].speed_fast);
- len += size;
- pos = begin + len;
+ return ppa_proc_write(h, buffer, length);

+ p += sprintf(p, "Version:\t%s\n", PPA_VERSION);
+ p += sprintf(p, "Parport:\t%s\n", h->dev->port->name);
+ p += sprintf(p, "Mode:\t%s\n", PPA_MODE_STRING[h->mode]);
+ p += sprintf(p, "ppa_speed:\t%i\n", h->speed);
+ p += sprintf(p, "ppa_speed_fast:\t%i\n", h->speed_fast);
if (IN_EPP_MODE(ppa_hosts[i].mode)) {
- size = sprintf(buffer + len, "epp_speed %i\n",
- ppa_hosts[i].epp_speed);
- len += size;
- pos = begin + len;
-
- size = sprintf(buffer + len, "\nInternal Counters\n");
- len += size;
- pos = begin + len;
-
- size = sprintf(buffer + len, "epp_timeout %i\n",
- ppa_hosts[i].timeout);
- len += size;
- pos = begin + len;
+ p += sprintf(p, "epp_speed:\t%i\n", h->epp_speed);
+ p += sprintf(p, "epp_timeout_count:\t%i\n", h->timeout);
}
- *start = buffer + (offset + begin);
- len -= (offset - begin);
+ *start = buffer + offset;
+ len = p - *start;
if (len > length)
len = length;
return len;
--- ./include/linux/parport.h.mj Sun Jul 13 19:27:04 1997
+++ ./include/linux/parport.h Sun Jul 13 20:14:25 1997
@@ -227,4 +227,6 @@
return inb(port->base+1);
}

+extern int epp_clear_timeout(struct parport *);
+
#endif /* _PARPORT_H_ */
\
 
 \ /
  Last update: 2005-03-22 13:39    [W:0.202 / U:0.908 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site