schreite@helena.physik.uni-stuttgart.de
Wed, 30 Sep 98 14:24:18 +0100
Kernel 2.1.123:
diff -u6:
--- parport.h.orig Wed Sep 30 08:51:34 1998
+++ parport.h Wed Sep 30 09:09:25 1998
@@ -56,12 +56,35 @@
#define PARPORT_MODE_PCEPP 0x0004
#define PARPORT_MODE_PCECP 0x0008
#define PARPORT_MODE_PCECPEPP 0x0010
#define PARPORT_MODE_PCECR 0x0020 /* ECR Register Exists */
#define PARPORT_MODE_PCECPPS2 0x0040
+#define PARPORT_FORWARD 1
+#define PARPORT_REVERSE 2
+#define IEEE1284_REVERSE_DATA_AVAILABLE 1
+
+/* IEEE1284_modes */
+#define IEEE1284_NIBBLE_MODE 0
+#define IEEE1284_NONE 0
+#define IEEE1284_BYTE_MODE 1
+#define IEEE1284_REQUEST_ID 4
+#define IEEE1284_NIBBLE_MODE_BIT IEEE1284_REQUEST_ID /* this can't confuse */
+#define IEEE1284_ECP 0x10
+#define IEEE1284_ECPRLE_BIT 0x20
+#define IEEE1284_ECPRLE (IEEE1284_ECP|IEEE1284_ECPRLE_BIT)
+#define IEEE1284_EPP 0x40
+
+/* well known command sets: */
+#define PARPORT_PJL 1
+#define PARPORT_PCL 2
+#define PARPORT_PS 4
+#define PARPORT_SCL 8
+#define PARPORT_MLC 16
+#define PARPORT_PML 32
+
/* The rest is for the kernel only */
#ifdef __KERNEL__
#include <asm/system.h>
#include <asm/ptrace.h>
#include <asm/spinlock.h>
@@ -133,15 +156,33 @@
struct parport_device_info {
parport_device_class class;
const char *class_name;
const char *mfr;
const char *model;
const char *cmdset;
+ int well_known_cmdsets;
const char *description;
+ unsigned char ieee1284_modes; /* nibble mode: IEEE1284_NIBBLE_MODE_BIT
+ */
};
+
+/* data for IEEE128 I/O:
+ * flags: PARPORT_FORWARD (1) - idle mode
+ * PARPORT_REVERSE (2) - idle mode */
+#define PARPORT_IEEE1284_ERROR 4
+struct ieee1284_data {
+ unsigned char current_mode; /* IEEE1284_NIBBLE_MODE_BIT for
+ nibble mode */
+ unsigned char idle_mode;
+ unsigned char highest_forward_mode;
+ unsigned char highest_reverse_mode;
+ int flags;
+};
+
+
/* Each device can have two callback functions:
* 1) a preemption function, called by the resource manager to request
* that the driver relinquish control of the port. The driver should
* return zero if it agrees to release the port, and nonzero if it
* refuses. Do not call parport_release() - the kernel will do this
* implicitly.
@@ -164,12 +205,13 @@
struct pardevice *prev;
struct parport_state *state; /* saved status over preemption */
struct wait_queue *wait_q;
unsigned long int time;
unsigned long int timeslice;
unsigned int waiting;
+ struct ieee1284_data ieee1284;
struct pardevice *waitprev;
struct pardevice *waitnext;
};
/* Directory information for the /proc interface */
struct parport_dir {
@@ -297,17 +339,77 @@
/* Flags used to identify what a device does. */
#define PARPORT_DEV_TRAN 0x0000 /* We're transient. */
#define PARPORT_DEV_LURK 0x0001 /* We lurk. */
#define PARPORT_FLAG_COMA 1
+/* parport_argument_packet *****************/
+#define PARPORT_ABORT 2
+#define PARPORT_ATOMIC 1
+#define PARPORT_MAY_SLEEP 0
+#define PARPORT_TRYING_AGAIN -99
+#define PARPORT_ARGUMENT_PACKET_MAXDEPTH 4
+#include <linux/tqueue.h>
+
+struct parport_argument_packet {
+ struct parport *port;
+ char *buffer;
+ long bufferlen;
+ unsigned char data;
+ void (*call_back)(void*);
+ void *driver_data;
+ int mode;
+ /* the members above won't be changed by the IEEE1284 functions ... */
+ long result;
+ long save_result;
+ char *res_txt;
+ long sum_delay;
+ unsigned char status;
+ unsigned char lastcontrol;
+ int depth;
+ int pc[PARPORT_ARGUMENT_PACKET_MAXDEPTH];
+ void (*in_function[PARPORT_ARGUMENT_PACKET_MAXDEPTH])(struct
parport_argument_packet*);
+ int wait_short;
+ long timeout_absolute;
+ struct tq_struct tq;
+};
+#define EMPTY_PARPORT_ARGUMENT_PACKET (struct parport_argument_packet){ \
+ NULL, NULL, 0, 0, parport_nop, NULL, PARPORT_MAY_SLEEP, \
+ 0, 0, NULL, 0, 0, 0, -1, { -1, -1, -1, -1 }, \
+ { NULL, NULL, NULL, NULL }, 0, 0, \
+ { NULL, 0, NULL, NULL } };
+
+/*********************************************/
+
extern void parport_parse_irqs(int, const char *[], int irqval[]);
extern int parport_ieee1284_nibble_mode_ok(struct parport *, unsigned char);
extern int parport_wait_peripheral(struct parport *, unsigned char, unsigned
char);
+extern void parport_nop(void*);
+extern int parport_ieee1284_negotiate(struct parport*, int, struct
parport_argument_packet*);
+extern void parport_ieee1284_negotiate_p(struct parport_argument_packet*);
+extern void parport_quit_ieee1284_modes(struct parport*, struct
parport_argument_packet*);
+extern void parport_quit_ieee1284_modes_p(struct parport_argument_packet*);
+extern int parport_ieee1284_write_block(struct parport*, char*, long,
struct parport_argument_packet*);
+extern void parport_ieee1284_write_block_p(struct parport_argument_packet*);
+extern long parport_ieee1284_read_block(struct parport*, char *, long,
struct parport_argument_packet*);
+extern void parport_ieee1284_read_block_p(struct parport_argument_packet*);
+extern int parport_ieee1284_change_channel(struct parport*, char *,
struct parport_argument_packet*);
+extern void parport_ieee1284_change_channel_p(struct parport_argument_packet*);
+extern int parport_ieee1284_query_state(struct parport *);
+/* flags: PARPORT_FORWARD (1) */
+/* PARPORT_REVERSE (2) */
+#define PARPORT_IEEE1284_PREFER_ECP 4
+#define PARPORT_IGNORE_PROBE_INFO 8
+#define PARPORT_IGNORE_PORT_INFO 0x10
+extern unsigned int parport_ieee1284_set_modemask(struct parport *,
+ unsigned int, int);
+extern int parport_ieee1284_set_mode(struct parport*, unsigned char,
struct parport_argument_packet*);
+extern void parport_ieee1284_set_mode_p(struct parport_argument_packet*);
+
/* Prototypes from parport_procfs */
extern int parport_proc_init(void);
extern void parport_proc_cleanup(void);
extern int parport_proc_register(struct parport *pp);
extern int parport_proc_unregister(struct parport *pp);
diff -u6:
--- parport_init.c.orig Wed Sep 30 09:44:52 1998
+++ parport_init.c Wed Sep 30 09:44:55 1998
@@ -136,12 +136,27 @@
EXPORT_SYMBOL(parport_quiesce);
EXPORT_SYMBOL(parport_register_device);
EXPORT_SYMBOL(parport_unregister_device);
EXPORT_SYMBOL(parport_enumerate);
EXPORT_SYMBOL(parport_ieee1284_nibble_mode_ok);
EXPORT_SYMBOL(parport_wait_peripheral);
+EXPORT_SYMBOL(parport_nop);
+EXPORT_SYMBOL(parport_ieee1284_negotiate);
+EXPORT_SYMBOL(parport_ieee1284_negotiate_p);
+EXPORT_SYMBOL(parport_quit_ieee1284_modes);
+EXPORT_SYMBOL(parport_quit_ieee1284_modes_p);
+EXPORT_SYMBOL(parport_ieee1284_write_block);
+EXPORT_SYMBOL(parport_ieee1284_write_block_p);
+EXPORT_SYMBOL(parport_ieee1284_read_block);
+EXPORT_SYMBOL(parport_ieee1284_read_block_p);
+EXPORT_SYMBOL(parport_ieee1284_change_channel);
+EXPORT_SYMBOL(parport_ieee1284_change_channel_p);
+EXPORT_SYMBOL(parport_ieee1284_query_state);
+EXPORT_SYMBOL(parport_ieee1284_set_modemask);
+EXPORT_SYMBOL(parport_ieee1284_set_mode);
+EXPORT_SYMBOL(parport_ieee1284_set_mode_p);
EXPORT_SYMBOL(parport_proc_register);
EXPORT_SYMBOL(parport_proc_unregister);
EXPORT_SYMBOL(parport_probe_hook);
EXPORT_SYMBOL(parport_parse_irqs);
void inc_parport_count(void)
diff -u6:
--- parport_probe.c.orig Wed Sep 30 09:10:39 1998
+++ parport_probe.c Wed Sep 30 09:59:21 1998
@@ -1,11 +1,14 @@
/* $Id: parport_probe.c,v 1.3 1997/10/19 18:18:46 phil Exp $
* Parallel port device probing code
*
* Authors: Carsten Gross, carsten@sol.wohnheim.uni-ulm.de
* Philip Blundell <Philip.Blundell@pobox.com>
+ * some minor things ("well known command sets", probe for
+ * IEEE1284-modes) added by:
+ * Roger Schreiter <Roger.Schreiter@t-online.de>
*/
#include <linux/tasks.h>
#include <linux/parport.h>
#include <linux/delay.h>
#include <linux/errno.h>
@@ -20,23 +23,26 @@
#include <asm/io.h>
#include <asm/dma.h>
#include <asm/uaccess.h>
#undef DEBUG_PROBE
+/* uncomment the following line to test the new generic IEEE1284 code */
+/* #define PROBE_FOR_IEEE1284_MODES */
static inline int read_nibble(struct parport *port)
{
unsigned char i;
i = parport_read_status(port)>>3;
i &= ~8;
if ((i & 0x10) == 0) i |= 8;
return (i & 0x0f);
}
static void read_terminate(struct parport *port) {
+ if (port->cad) port->cad->ieee1284.current_mode=IEEE1284_NONE;
parport_write_control(port, (parport_read_control(port) & ~2) | 8);
/* SelectIN high, AutoFeed low */
if (parport_wait_peripheral(port, 0x80, 0))
/* timeout, SelectIN high, Autofeed low */
return;
parport_write_control(port, parport_read_control(port) | 2);
@@ -91,28 +97,41 @@
int parport_probe(struct parport *port, char *buffer, int len)
{
struct pardevice *dev = parport_register_device(port, "IEEE
1284 probe", NULL, NULL, NULL, PARPORT_DEV_TRAN, &dev);
int result = 0;
+#ifdef PROBE_FOR_IEEE1284_MODES
+ struct parport_argument_packet data=EMPTY_PARPORT_ARGUMENT_PACKET;
+#endif
if (!dev) {
printk("%s: unable to register for probe.\n", port->name);
return -EINVAL;
}
parport_claim_or_block(dev);
+#ifdef PROBE_FOR_IEEE1284_MODES
+ switch (parport_ieee1284_negotiate(port, 4, &data)) {
+ case 2:
+#else
switch (parport_ieee1284_nibble_mode_ok(port, 4)) {
case 1:
+#endif
current->state=TASK_INTERRUPTIBLE;
current->timeout=jiffies+1;
schedule(); /* HACK: wait 10ms because printer seems to
* ack wrong */
result = read_polled(port, buffer, len);
break;
+#ifdef PROBE_FOR_IEEE1284_MODES
+ case 1:
+ result = 0;
+ break;
+#endif
case 0:
result = -EIO;
break;
}
parport_release(dev);
@@ -193,18 +212,26 @@
goto rock_on;
}
}
printk(KERN_WARNING "%s probe: warning,
class '%s' not understood.\n", port->name, sep);
port->probe_info.class = PARPORT_CLASS_OTHER;
} else if (!strcmp(p, "CMD") || !strcmp(p, "COMMAND SET")) {
+ if (strstr(sep, "PJL"))
port->probe_info.well_known_cmdsets|=PARPORT_PJL;
+ if (strstr(sep, "PCL"))
port->probe_info.well_known_cmdsets|=PARPORT_PCL;
+ if (strstr(sep, "PS"))
port->probe_info.well_known_cmdsets|=PARPORT_PS;
+ if (strstr(sep, "POSTSCRIPT"))
port->probe_info.well_known_cmdsets|=PARPORT_PS;
+ if (strstr(sep, "SCL"))
port->probe_info.well_known_cmdsets|=PARPORT_SCL;
+ if (strstr(sep, "MLC"))
port->probe_info.well_known_cmdsets|=PARPORT_MLC;
+ if (strstr(sep, "PML"))
port->probe_info.well_known_cmdsets|=PARPORT_PML;
if (port->probe_info.cmdset)
kfree (port->probe_info.cmdset);
port->probe_info.cmdset = strdup(sep);
/* if it speaks printer language, it's
probably a printer */
- if (strstr(sep, "PJL") || strstr(sep, "PCL"))
+ if ( port->probe_info.well_known_cmdsets &
+ (PARPORT_PJL|PARPORT_PCL|PARPORT_PS) )
guessed_class = PARPORT_CLASS_PRINTER;
} else if (!strcmp(p, "DES") || !strcmp(p, "DESCRIPTION")) {
if (port->probe_info.description)
kfree (port->probe_info.description);
port->probe_info.description = strdup(sep);
}
@@ -233,42 +260,87 @@
}
void parport_probe_one(struct parport *port)
{
char *buffer = kmalloc(2048, GFP_KERNEL);
int r;
+#ifdef PROBE_FOR_IEEE1284_MODES
+ struct parport_argument_packet data=EMPTY_PARPORT_ARGUMENT_PACKET;
+#endif
MOD_INC_USE_COUNT;
port->probe_info.model = strdup ("Unknown device");
port->probe_info.mfr = strdup ("Unknown vendor");
port->probe_info.description = port->probe_info.cmdset = NULL;
port->probe_info.class = PARPORT_CLASS_UNSPEC;
port->probe_info.class_name = NULL;
+ port->probe_info.well_known_cmdsets=0;
+ port->probe_info.ieee1284_modes=0;
if (!buffer) {
printk(KERN_ERR "%s probe: Memory squeeze.\n", port->name);
return;
}
+#ifdef PROBE_FOR_IEEE1284_MODES
+ if (parport_ieee1284_negotiate(port, IEEE1284_BYTE_MODE|
+ IEEE1284_REQUEST_ID, &data)==2)
+ port->probe_info.ieee1284_modes|=IEEE1284_BYTE_MODE;
+ parport_quit_ieee1284_modes(port, &data);
+ /* We do this here, because byte mode is not available, if
+ there are no data, on most devices. */
+#endif
+
r = parport_probe(port, buffer, 2047);
if (r < 0) {
printk(KERN_INFO "%s: no IEEE-1284 device present.\n",
port->name);
port->probe_info.class = PARPORT_CLASS_LEGACY;
} else if (r == 0) {
printk(KERN_INFO "%s: no ID data returned by device.\n",
port->name);
} else {
+ port->probe_info.ieee1284_modes|=IEEE1284_NIBBLE_MODE_BIT;
buffer[r] = 0;
#ifdef DEBUG_PROBE
printk("%s id: %s\n", port->name, buffer+2);
#endif
parse_data(port, buffer+2);
pretty_print(port);
}
+
+#ifdef PROBE_FOR_IEEE1284_MODES
+ if (r>=0) { /* probe for ieee1284 modes */
+ if (parport_ieee1284_negotiate(port, IEEE1284_EPP, &data)==2)
+ port->probe_info.ieee1284_modes|=IEEE1284_EPP;
+ parport_quit_ieee1284_modes(port, &data);
+
+ if (parport_ieee1284_negotiate(port, IEEE1284_ECPRLE, &data)==2)
+ port->probe_info.ieee1284_modes|=IEEE1284_ECPRLE_BIT;
+ parport_quit_ieee1284_modes(port, &data);
+
+ if (parport_ieee1284_negotiate(port, IEEE1284_ECP, &data)==2)
+ port->probe_info.ieee1284_modes|=IEEE1284_ECP;
+ parport_quit_ieee1284_modes(port, &data);
+
+ if (parport_ieee1284_negotiate(port, IEEE1284_BYTE_MODE, &data)==2)
+ port->probe_info.ieee1284_modes|=IEEE1284_BYTE_MODE;
+ parport_quit_ieee1284_modes(port, &data);
+
+ if (parport_ieee1284_negotiate(port,
IEEE1284_NIBBLE_MODE, &data)==2)
+ port->probe_info.ieee1284_modes|=IEEE1284_NIBBLE_MODE_BIT;
+ parport_quit_ieee1284_modes(port, &data);
+ }
+/* if we didn't get byte and nibble mode, it doesn't mean, that
+ * these modes don't exist on the device. Perhaps it is, because
+ * the device doesn't report an ID, and nibble or byte mode
+ * are only available, when there are reverse data available.
+ * Sorry, the device driver has to manage this problem. */
+#endif
+
kfree(buffer);
MOD_DEC_USE_COUNT;
}
#if MODULE
int init_module(void)
diff -u6:
--- parport_share.c.orig Wed Sep 30 09:47:11 1998
+++ parport_share.c Wed Sep 30 09:49:54 1998
@@ -129,12 +129,14 @@
portlist_tail = tmp;
if (!portlist)
portlist = tmp;
spin_unlock_irqrestore (&parportlist_lock, flags);
tmp->probe_info.class = PARPORT_CLASS_LEGACY; /* assume the worst */
+ tmp->probe_info.well_known_cmdsets=0;
+ tmp->probe_info.ieee1284_modes=0;
tmp->waithead = tmp->waittail = NULL;
return tmp;
}
void parport_unregister_port(struct parport *port)
@@ -236,12 +238,17 @@
tmp->wakeup = kf;
tmp->private = handle;
tmp->flags = flags;
tmp->irq_func = irq_func;
port->ops->init_state(tmp->state);
tmp->waiting = 0;
+ tmp->ieee1284.current_mode=
+ tmp->ieee1284.highest_forward_mode=
+ tmp->ieee1284.highest_reverse_mode=
+ tmp->ieee1284.idle_mode=IEEE1284_NONE;
+ tmp->ieee1284.flags=0;
/* Chain this onto the list */
tmp->prev = NULL;
spin_lock_irqsave (&port->lock, flgs);
tmp->next = port->devices;
if (port->devices)
-- To unsubscribe, send mail to: linux-parport-request@torque.net --
-- with the single word "unsubscribe" in the body of the message. --
This archive was generated by hypermail 2.0b3 on Wed 30 Dec 1998 - 10:18:27 EST