[PARPORT] amiga-parport for 2.1.119


Joerg Dorchain (dorchain@wirbel.com)
Tue, 1 Sep 1998 01:19:15 +0200 (MET DST)


Hi,

this is the patch for amiga-parport for 2.1.119. As I received no mails
wether printing works or not with this driver, I ask you again to please
test the driver and report the results (regardless wehter good or bad,
I'd like to hear anything!)
Although I don't promised it doesn't blow up your PC, printer or mind
;-), I'm still as sane as before and the printer still prints. So chances
can't be that bad for your system.

Joerg

--- ./arch/m68k/config.in.orig Sun Aug 30 13:33:42 1998
+++ ./arch/m68k/config.in Mon Aug 31 14:39:23 1998
@@ -102,6 +102,15 @@
   fi
 fi
 bool '/proc/hardware support' CONFIG_PROC_HARDWARE
+
+if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+ tristate 'Parallel port support (disables old lp driver!)' CONFIG_PARPORT
+ if [ "$CONFIG_PARPORT" != "n" ]; then
+ if [ "$CONFIG_AMIGA" != "n" ]; then
+ dep_tristate ' Amiga builtin port' CONFIG_PARPORT_AMIGA $CONFIG_PARPORT
+ fi
+ fi
+fi
 endmenu
 
 source drivers/block/Config.in
@@ -257,9 +266,16 @@
   define_bool CONFIG_NVRAM y
 fi
 
-tristate 'Parallel printer support' CONFIG_M68K_PRINTER
-if [ "$CONFIG_ZORRO" = "y" ]; then
- dep_tristate 'Multiface Card III parallel support' CONFIG_MULTIFACE_III_LP $CONFIG_PRINTER
+if [ "$CONFIG_PARPORT" = "n" ]; then
+ tristate 'Parallel printer support' CONFIG_M68K_PRINTER
+ if [ "$CONFIG_ZORRO" = "y" ]; then
+ dep_tristate 'Multiface Card III parallel support' CONFIG_MULTIFACE_III_LP $CONFIG_PRINTER
+ fi
+else
+ dep_tristate 'Parallel printer support' CONFIG_PRINTER $CONFIG_PARPORT
+ if [ "$CONFIG_PRINTER" != "n" ]; then
+ bool ' Support IEEE1284 status readback' CONFIG_PRINTER_READBACK
+ fi
 fi
 if [ "$CONFIG_AMIGA" = "y" ]; then
   tristate 'Amiga mouse support' CONFIG_AMIGAMOUSE
--- ./drivers/char/lp.c.orig Sun Aug 30 13:33:56 1998
+++ ./drivers/char/lp.c Mon Aug 31 14:39:23 1998
@@ -94,7 +94,7 @@
 #include <linux/delay.h>
 
 #include <linux/parport.h>
-#undef LP_STATS
+#define LP_STATS
 #undef LP_NEED_CAREFUL
 #include <linux/lp.h>
 
@@ -126,7 +126,7 @@
 #define LP_READY(minor, status) ((status) & LP_PBUSY)
 #endif
 
-#undef LP_DEBUG
+#define LP_DEBUG
 #undef LP_READ_DEBUG
 
 /* --- parport support ----------------------------------------- */
@@ -211,7 +211,7 @@
 #endif
         /* must wait before taking strobe high, and after taking strobe
            low, according spec. Some printers need it, others don't. */
-#ifndef __sparc__
+#if !defined(__sparc__) && !defined(__mc68000__)
         while (wait != LP_WAIT(minor)) /* FIXME: should be a udelay() */
                 wait++;
 #else
@@ -219,7 +219,7 @@
 #endif
         /* control port takes strobe high */
         w_ctr(minor, LP_PSELECP | LP_PINITP | LP_PSTROBE);
-#ifndef __sparc__
+#if !defined(__sparc__) && !defined(__mc68000__)
         while (wait) /* FIXME: should be a udelay() */
                 wait--;
 #else
@@ -316,6 +316,7 @@
         unsigned long total_bytes_written = 0;
         unsigned long bytes_written;
         struct lp_struct *lp = &lp_table[minor];
+ unsigned long flags;
 
         if (minor >= LP_NO)
                 return -ENXIO;
@@ -384,6 +385,11 @@
                                         current->timeout = jiffies + LP_TIME(minor);
                                         lp_schedule (minor);
                                 } else {
+ /* Replace cli()/sti() by
+ cli()/restore_flags.
+ It's a must for other architectures
+ and doesn't break i386 */
+ save_flags(flags);
                                         cli();
                                         if (LP_PREEMPTED(minor))
                                         {
@@ -394,7 +400,7 @@
                                                  * envinroment to avoid parport sharing
                                                  * starvation.
                                                  */
- sti();
+ restore_flags(flags);
                                                 goto lp_polling;
                                         }
                                         if (!lp_table[minor].irq_detected)
@@ -402,7 +408,7 @@
                                                 current->timeout = jiffies + LP_TIMEOUT_INTERRUPT;
                                                 interruptible_sleep_on(&lp->wait_q);
                                         }
- sti();
+ restore_flags(flags);
                                 }
                         }
                 }
--- ./drivers/misc/Makefile.orig Mon Feb 23 21:26:49 1998
+++ ./drivers/misc/Makefile Mon Aug 31 14:39:23 1998
@@ -37,6 +37,13 @@
       M_OBJS += parport_ax.o
     endif
   endif
+ ifeq ($(CONFIG_PARPORT_AMIGA),y)
+ LX_OBJS += parport_amiga.o
+ else
+ ifeq ($(CONFIG_PARPORT_AMIGA),m)
+ M_OBJS += parport_amiga.o
+ endif
+ endif
   LX_OBJS += parport_init.o
 else
   ifeq ($(CONFIG_PARPORT),m)
@@ -52,6 +59,9 @@
   endif
   ifeq ($(CONFIG_PARPORT_AX),m)
     M_OBJS += parport_ax.o
+ endif
+ ifeq ($(CONFIG_PARPORT_AMIGA),m)
+ M_OBJS += parport_amiga.o
   endif
 endif
 
--- ./drivers/misc/parport_amiga.c.orig Mon Aug 31 14:39:23 1998
+++ ./drivers/misc/parport_amiga.c Mon Aug 31 14:39:23 1998
@@ -0,0 +1,311 @@
+/* Low-level parallel port routines for the Amiga buildin port
+ *
+ * Author: Joerg Dorchain <dorchain@wirbel.com>
+ *
+ * This is a complete rewrite of the code, but based heaviy upon the old
+ * lp_intern. code.
+ *
+ * The built-in Amiga parallel port provides one port at a fixed address
+ * with 8 bisdirecttional data lines (D0 - D7) and 3 bidirectional status
+ * lines (BUSY, POUT, SEL), 1 output control line /STROBE (raised automatically in
+ * hardware when the data register is accessed), and 1 input control line
+ * /ACK, able to cause an interrupt, but both not directly settable by
+ * software.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/parport.h>
+#include <asm/setup.h>
+#include <asm/amigahw.h>
+#include <asm/irq.h>
+#include <asm/amigaints.h>
+
+#undef DEBUG
+#ifdef DEBUG
+#define DPRINTK printk
+#else
+static inline int DPRINTK() {return 0;}
+#endif
+
+static void amiga_write_data(struct parport *p, unsigned char data)
+{
+DPRINTK("write_data %c\n",data);
+ /* Triggers also /STROBE. This behavior cannot be changed */
+ ciaa.prb = data;
+}
+
+static unsigned char amiga_read_data(struct parport *p)
+{
+ /* Triggers also /STROBE. This behavior cannot be changed */
+ return ciaa.prb;
+}
+
+#if 0
+static unsigned char control_pc_to_amiga(unsigned char control)
+{
+ unsigned char ret = 0;
+
+ if (control & 0x10) /* XXX: What is INTEN? */
+ ;
+ if (control & 0x08) /* XXX: What is SELECP? */
+ ;
+ if (control & 0x04) /* INITP */
+ /* reset connected to cpu reset pin */;
+ if (control & 0x02) /* AUTOLF */
+ /* Not connected */;
+ if (control & 0x01) /* Strobe */
+ /* Handled only directly by hardware */;
+ return ret;
+}
+#endif
+
+static unsigned char control_amiga_to_pc(unsigned char control)
+{
+ return 0x1b;
+ /* fake value: interrupt enable, select in, no reset,
+ no autolf, no strobe - seems to be closest the wiring diagram */
+}
+
+static void amiga_write_control(struct parport *p, unsigned char control)
+{
+DPRINTK("write_control %02x\n",control);
+ /* No implementation possible */
+}
+
+static unsigned char amiga_read_control( struct parport *p)
+{
+DPRINTK("read_control \n");
+ return control_amiga_to_pc(0);
+}
+
+static unsigned char amiga_frob_control( struct parport *p, unsigned char mask, unsigned char val)
+{
+ unsigned char old;
+
+DPRINTK("frob_control mask %02x, value %02x\n",mask,val);
+ old = amiga_read_control(p);
+ amiga_write_control(p, (old & ~mask) ^ val);
+ return old;
+}
+
+
+static unsigned char status_pc_to_amiga(unsigned char status)
+{
+ unsigned char ret = 1;
+
+ if (status & 0x80) /* Busy */
+ ret &= ~1;
+ if (status & 0x40) /* Ack */
+ /* handled in hardware */;
+ if (status & 0x20) /* PaperOut */
+ ret |= 2;
+ if (status & 0x10) /* select */
+ ret |= 4;
+ if (status & 0x08) /* error */
+ /* not connected */;
+ return ret;
+}
+
+static unsigned char status_amiga_to_pc(unsigned char status)
+{
+ unsigned char ret = 0x80 + 0x40 + 0x08;
+
+ if (status & 1) /* Busy */
+ ret &= ~0x80;
+ if (status & 2) /* PaperOut */
+ ret |= 0x20;
+ if (status & 4) /* Selected */
+ ret |= 0x10;
+ /* the rest is not connected or handled autonomously in hardware */
+
+ return ret;
+}
+
+static void amiga_write_status( struct parport *p, unsigned char status)
+{
+DPRINTK("write_status %02x\n",status);
+ ciab.pra |= (ciab.pra & 0xf8) | status_pc_to_amiga(status);
+}
+
+static unsigned char amiga_read_status(struct parport *p)
+{
+ unsigned char status;
+
+ status = status_amiga_to_pc(ciab.pra & 7);
+DPRINTK("read_status %02x\n", status);
+ return status;
+}
+
+static void amiga_change_mode( struct parport *p, int m)
+{
+ /* XXX: This port only has one mode, and I am
+ not sure about the corresponding PC-style mode*/
+}
+
+static void amiga_intr_func(int irq, void *dev_id, struct pt_regs *regs)
+{
+ /* nothing to do */
+}
+
+static void amiga_release_resources(struct parport *p)
+{
+DPRINTK("realease_resources\n");
+ if (p->irq != PARPORT_IRQ_NONE)
+ free_irq(IRQ_AMIGA_CIAA_FLG, &ciaa.prb);
+}
+
+static int amiga_claim_resources(struct parport *p)
+{
+DPRINTK("claim_resources\n");
+ return request_irq(IRQ_AMIGA_CIAA_FLG, amiga_intr_func, 0, p->name, &ciaa.prb);
+}
+
+static void amiga_init_state(struct parport_state *s)
+{
+ s->u.amiga.data = 0;
+ s->u.amiga.datadir = 255;
+ s->u.amiga.status = 0;
+ s->u.amiga.statusdir = 0;
+}
+
+static void amiga_save_state(struct parport *p, struct parport_state *s)
+{
+ s->u.amiga.data = ciaa.prb;
+ s->u.amiga.datadir = ciaa.ddrb;
+ s->u.amiga.status = ciab.pra & 7;
+ s->u.amiga.statusdir = ciab.ddra & 7;
+}
+
+static void amiga_restore_state(struct parport *p, struct parport_state *s)
+{
+ ciaa.prb = s->u.amiga.data;
+ ciaa.ddrb = s->u.amiga.datadir;
+ ciab.pra |= (ciab.pra & 0xf8) | s->u.amiga.status;
+ ciab.ddra |= (ciab.ddra & 0xf8) | s->u.amiga.statusdir;
+}
+
+static void amiga_enable_irq(struct parport *p)
+{
+ enable_irq(IRQ_AMIGA_CIAA_FLG);
+}
+
+static void amiga_disable_irq(struct parport *p)
+{
+ disable_irq(IRQ_AMIGA_CIAA_FLG);
+}
+
+static int amiga_examine_irq(struct parport *p)
+{
+ return 1; /* if an interrupt happened, we know it is ours */
+}
+
+static void amiga_inc_use_count(void)
+{
+ MOD_INC_USE_COUNT;
+}
+
+static void amiga_dec_use_count(void)
+{
+ MOD_DEC_USE_COUNT;
+}
+
+static struct parport_operations pp_amiga_ops = {
+ amiga_write_data,
+ amiga_read_data,
+
+ amiga_write_control,
+ amiga_read_control,
+ amiga_frob_control,
+
+ NULL, /* write_econtrol */
+ NULL, /* read_econtrol */
+ NULL, /* frob_econtrol */
+
+ amiga_write_status,
+ amiga_read_status,
+
+ NULL, /* write fifo */
+ NULL, /* read fifo */
+
+ amiga_change_mode,
+
+
+ amiga_release_resources,
+ amiga_claim_resources,
+
+
+ NULL, /* epp_write_data */
+ NULL, /* epp_read_data */
+ NULL, /* epp_write_addr */
+ NULL, /* epp_read_addr */
+ NULL, /* epp_check_timeout */
+
+ NULL, /* epp_write_block */
+ NULL, /* epp_read_block */
+
+ NULL, /* ecp_write_block */
+ NULL, /* ecp_read_block */
+
+ amiga_init_state,
+ amiga_save_state,
+ amiga_restore_state,
+
+ amiga_enable_irq,
+ amiga_disable_irq,
+ amiga_examine_irq,
+
+ amiga_inc_use_count,
+ amiga_dec_use_count
+};
+
+/* ----------- Initialisation code --------------------------------- */
+
+__initfunc(int parport_amiga_init(void))
+{
+ struct parport *p;
+
+ if (MACH_IS_AMIGA && AMIGAHW_PRESENT(AMI_PARALLEL)) {
+ ciaa.ddrb = 0xff;
+ ciab.ddra &= 0xf8;
+ if (!(p = parport_register_port((unsigned long)&ciaa.prb,
+ IRQ_AMIGA_CIAA_FLG, PARPORT_DMA_NONE,
+ &pp_amiga_ops)))
+ return 0;
+ printk(KERN_INFO "%s: Amiga built-in port using irq\n", p->name);
+ /* XXX: set operating mode */
+ parport_proc_register(p);
+ p->flags |= PARPORT_FLAG_COMA;
+
+ if (parport_probe_hook)
+ (*parport_probe_hook)(p);
+ return 1;
+
+ }
+ return 0;
+}
+
+#ifdef MODULE
+int init_module(void)
+{
+ return ! parport_amiga_init();
+}
+
+void cleanup_module(void)
+{
+ struct parport *p = parport_enumerate(), *next;
+
+ while (p) {
+ next = p->next;
+ if (p->ops == &pp_amiga_ops) {
+ if (!(p->flags & PARPORT_FLAG_COMA))
+ parport_quiesce(p);
+ parport_proc_unregister(p);
+ parport_unregister_port(p);
+ }
+ p = next;
+ }
+}
+#endif
+
+
--- ./drivers/misc/parport_init.c.orig Thu Dec 11 06:23:33 1902
+++ ./drivers/misc/parport_init.c Mon Aug 31 14:39:23 1998
@@ -122,6 +122,9 @@
 #ifdef CONFIG_PARPORT_AX
         parport_ax_init();
 #endif
+#ifdef CONFIG_PARPORT_AMIGA
+ parport_amiga_init();
+#endif
         return 0;
 }
 #endif
--- ./include/linux/parport.h.orig Mon Aug 10 17:38:36 1998
+++ ./include/linux/parport.h Mon Aug 31 14:47:23 1998
@@ -78,11 +78,19 @@
         unsigned int ecr;
 };
 
+struct amiga_parport_state {
+ unsigned char data; /* ciaa.prb */
+ unsigned char datadir; /* ciaa.ddrb */
+ unsigned char status; /* ciab.pra & 7 */
+ unsigned char statusdir;/* ciab.ddrb & 7 */
+};
+
 struct parport_state {
         union {
                 struct pc_parport_state pc;
                 /* ARC has no state. */
                 /* AX uses same state information as PC */
+ struct amiga_parport_state amiga;
                 void *misc;
         } u;
 };

-- 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:12 EST