patch-2.4.25 linux-2.4.25/drivers/parport/parport_ip22.c
Next file: linux-2.4.25/drivers/pci/pci.ids
Previous file: linux-2.4.25/drivers/parport/Makefile
Back to the patch index
Back to the overall index
- Lines: 314
- Date:
2004-02-18 05:36:31.000000000 -0800
- Orig file:
linux-2.4.24/drivers/parport/parport_ip22.c
- Orig date:
1969-12-31 16:00:00.000000000 -0800
diff -urN linux-2.4.24/drivers/parport/parport_ip22.c linux-2.4.25/drivers/parport/parport_ip22.c
@@ -0,0 +1,313 @@
+/*
+ * Low-level parallel port routines for the SGI Indy/Indigo2 builtin port
+ *
+ * Copyright (c) 2002 Vincent Stehlé <vincent.stehle@free.fr>
+ * (shamelessly based on other parport_xxx.c)
+ * See the "COPYING" license file at the top-level.
+ *
+ * PI1 registers have the same bits as the PC parallel port registers, but
+ * all PI1 bits are "direct"; i.e. no invertion: A 1 is TTL "high" (5 V),
+ * a 0 is TTL "low" (0 V). There are also some bits on the PI1, which have
+ * no equivalents on the PC. They are for non-SPP modes.
+ *
+ * Here follows a little summary of the signals and their meanings:
+ *
+ * A "/" in front of a signal means that the _bit_ is inverted: i.e. a "1"
+ * bit value means a TTL "low" (0 V) signal.
+ *
+ * A "-" in front of a signal means that it is low active: i.e. a TTL "low"
+ * (0 V) value means that the signal is active.
+ *
+ * Internal only signals are between ()'s.
+ *
+ * Control
+ * -------
+ * PC SGI
+ *
+ * 7 6 5 4 3 2 1 0
+ * \ \ \ \ \ \ \ `- /-STROBE -STROBE
+ * \ \ \ \ \ \ `-- /-AUTO FEED -AFD
+ * \ \ \ \ \ `--- -INIT -INIT
+ * \ \ \ \ `---- /-SELECT -SLIN
+ * \ \ \ `----- (IRQ 1=enabled)
+ * \ \ `------ (DIRECTION 0=forward)
+ * \ `------- (SEL ?)
+ * `--------
+ *
+ * Status
+ * ------
+ * PC SGI
+ *
+ * 7 6 5 4 3 2 1 0
+ * \ \ \ \ \ \ \ `- DEVID
+ * \ \ \ \ \ \ `-- " "
+ * \ \ \ \ \ `--- NOINK
+ * \ \ \ \ `---- -ERROR -ERROR
+ * \ \ \ `----- SELECT IN ONLINE
+ * \ \ `------ PAPER END PE
+ * \ `------- -ACK -ACK
+ * `-------- / BUSY BUSY
+ *
+ * Note that some of those information have been "guessed" with a multimeter
+ * and some spare nights :)
+ *
+ * Reminder: all functions await PC-style values, i.e. one should convert
+ * status and control.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/parport.h>
+#include <asm/sgi/ioc.h>
+#include <asm/sgi/pi1.h>
+
+#undef DEBUG
+
+#ifdef DEBUG
+#define DPRINTK printk
+#else
+#define DPRINTK(x...) do { } while (0)
+#endif
+
+const unsigned char control_invert = PARPORT_CONTROL_STROBE
+ | PARPORT_CONTROL_AUTOFD | PARPORT_CONTROL_SELECT;
+const unsigned char status_invert = PARPORT_STATUS_BUSY;
+
+static struct parport *this_port = NULL;
+
+static inline void debug_dump_registers(void)
+{
+#ifdef DEBUG
+ printk(KERN_DEBUG
+ "PI1 registers:\n"
+ " data= %02x\n"
+ " control= %02x\n"
+ " status= %02x\n"
+ " dma control= %02x\n"
+ " interrupt status= %02x\n"
+ " interrupt mask= %02x\n"
+ " timer 1= %02x\n"
+ " timer 2= %02x\n"
+ " timer 3= %02x\n"
+ " timer 4= %02x\n"
+ ,
+ sgioc->pport.data,
+ sgioc->pport.ctrl,
+ sgioc->pport.status,
+ sgioc->pport.dmactrl,
+ sgioc->pport.intstat,
+ sgioc->pport.intmask,
+ sgioc->pport.timer1,
+ sgioc->pport.timer2,
+ sgioc->pport.timer3,
+ sgioc->pport.timer4
+ );
+#endif
+}
+
+static unsigned char pi1_read_data(struct parport *p)
+{
+ unsigned char data = sgioc->pport.data;
+ DPRINTK("pi1_read_data: %#x\n", data);
+ return data;
+}
+
+static void pi1_write_data(struct parport *p, unsigned char data)
+{
+ DPRINTK("pi1_write_data: %#x\n", data);
+ sgioc->pport.data = data;
+}
+
+static unsigned char pi1_read_control(struct parport *p)
+{
+ const unsigned char mask = PARPORT_CONTROL_STROBE
+ | PARPORT_CONTROL_AUTOFD | PARPORT_CONTROL_INIT
+ | PARPORT_CONTROL_SELECT;
+ unsigned char pctrl = sgioc->pport.ctrl,
+ control = ((pctrl & mask) ^ control_invert);
+ DPRINTK("pi1_read_control: %#x, %#x\n", pctrl, control);
+ return control;
+}
+
+static void pi1_write_control(struct parport *p, unsigned char control)
+{
+ const unsigned char mask = PARPORT_CONTROL_STROBE
+ | PARPORT_CONTROL_AUTOFD | PARPORT_CONTROL_INIT
+ | PARPORT_CONTROL_SELECT,
+ /* we enforce some necessary bits */
+ force = 0x30;
+ unsigned char pctrl = ((control & mask) ^ control_invert) | force;
+ DPRINTK("pi1_write_control: %#x, %#x\n", control, pctrl);
+ sgioc->pport.ctrl = pctrl;
+}
+
+static unsigned char pi1_frob_control(struct parport *p,
+ unsigned char mask, unsigned char val)
+{
+ unsigned char old;
+ DPRINTK(KERN_DEBUG "pi1_frob_control mask %02x, value %02x\n",mask,val);
+ old = pi1_read_control(p);
+ pi1_write_control(p, (old & ~mask) ^ val);
+ return old;
+}
+
+static unsigned char pi1_read_status(struct parport *p)
+{
+ const unsigned mask = PARPORT_STATUS_ERROR | PARPORT_STATUS_SELECT
+ | PARPORT_STATUS_PAPEROUT | PARPORT_STATUS_ACK
+ | PARPORT_STATUS_BUSY;
+ unsigned char pstat = sgioc->pport.status,
+ status = ((pstat & mask) ^ status_invert);
+ DPRINTK("pi1_read_status: %#x, %#x\n", pstat, status);
+ return status;
+}
+
+static void pi1_init_state(struct pardevice *d, struct parport_state *s)
+{
+ DPRINTK("pi1_init_state\n");
+}
+
+static void pi1_save_state(struct parport *p, struct parport_state *s)
+{
+ DPRINTK("pi1_save_state\n");
+}
+
+static void pi1_restore_state(struct parport *p, struct parport_state *s)
+{
+ DPRINTK("pi1_restore_state\n");
+}
+
+static void pi1_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+ DPRINTK("pi1_interrupt\n");
+ parport_generic_irq(irq, (struct parport *) dev_id, regs);
+}
+
+static void pi1_enable_irq(struct parport *p)
+{
+ DPRINTK("pi1_enable_irq\n");
+}
+
+static void pi1_disable_irq(struct parport *p)
+{
+ DPRINTK("pi1_disable_irq\n");
+}
+
+static void pi1_data_forward(struct parport *p)
+{
+ DPRINTK("pi1_data_forward\n");
+ sgioc->pport.ctrl &= ~PI1_CTRL_DIR;
+}
+
+static void pi1_data_reverse(struct parport *p)
+{
+ DPRINTK("pi1_data_reverse\n");
+ sgioc->pport.ctrl |= PI1_CTRL_DIR;
+}
+
+static void pi1_inc_use_count(void)
+{
+ DPRINTK("pi1_inc_use_count\n");
+ MOD_INC_USE_COUNT;
+}
+
+static void pi1_dec_use_count(void)
+{
+ DPRINTK("pi1_dec_use_count\n");
+ MOD_DEC_USE_COUNT;
+}
+
+static struct parport_operations pi1_ops = {
+ pi1_write_data,
+ pi1_read_data,
+ pi1_write_control,
+ pi1_read_control,
+ pi1_frob_control,
+ pi1_read_status,
+ pi1_enable_irq,
+ pi1_disable_irq,
+ pi1_data_forward,
+ pi1_data_reverse,
+ pi1_init_state,
+ pi1_save_state,
+ pi1_restore_state,
+ pi1_inc_use_count,
+ pi1_dec_use_count,
+ parport_ieee1284_epp_write_data,
+ parport_ieee1284_epp_read_data,
+ parport_ieee1284_epp_write_addr,
+ parport_ieee1284_epp_read_addr,
+ parport_ieee1284_ecp_write_data,
+ parport_ieee1284_ecp_read_data,
+ parport_ieee1284_ecp_write_addr,
+ parport_ieee1284_write_compat,
+ parport_ieee1284_read_nibble,
+ parport_ieee1284_read_byte
+};
+
+static void init_hardware(void)
+{
+ sgioc->pport.intmask = 0xfc;
+ sgioc->pport.dmactrl = 1;
+ sgioc->pport.ctrl = 0x3f;
+ sgioc->pport.timer1 = 0;
+ sgioc->pport.timer2 = 0;
+ sgioc->pport.timer3 = 0;
+ sgioc->pport.timer4 = 0;
+ sgioc->pport.data = 0;
+}
+
+static int __init pi1_init(void)
+{
+ struct parport *p;
+
+ DPRINTK("pi1_init\n");
+ p = parport_register_port((unsigned long) &sgioc->pport.data,
+ PARPORT_IRQ_NONE, PARPORT_DMA_NONE,
+ &pi1_ops);
+ if (!p)
+ return -EBUSY;
+
+/* TODO
+ err = request_irq(IRQ_AMIGA_CIAA_FLG, amiga_interrupt, 0, p->name, p);
+ if (err)
+ goto out_irq;
+*/
+
+ /* tell what we are capable of */
+ p->modes = PARPORT_MODE_PCSPP;
+
+/* TODO
+ | PARPORT_MODE_TRISTATE;*/
+
+ /* remember for exit */
+ this_port = p;
+
+ /* put hardware into known initial state */
+ init_hardware();
+
+ printk(KERN_INFO "%s: SGI PI1\n", p->name);
+ parport_proc_register(p);
+ parport_announce_port(p);
+
+ return 0;
+}
+
+static void __exit pi1_exit(void)
+{
+ DPRINTK("pi1_exit\n");
+ if (this_port->irq != PARPORT_IRQ_NONE)
+ free_irq(this_port->irq, this_port);
+
+ parport_proc_unregister(this_port);
+ parport_unregister_port(this_port);
+}
+
+MODULE_AUTHOR("Vincent Stehle <vincent.stehle@free.fr>");
+MODULE_DESCRIPTION("Driver for SGI Indy/Indigo2 parallel port");
+MODULE_SUPPORTED_DEVICE("SGI PI1 parallel port");
+MODULE_LICENSE("GPL");
+
+module_init(pi1_init);
+module_exit(pi1_exit);
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)