patch-2.4.23 linux-2.4.23/include/asm-ia64/sn/serialio.h

Next file: linux-2.4.23/include/asm-ia64/sn/sgi.h
Previous file: linux-2.4.23/include/asm-ia64/sn/pci/pic.h
Back to the patch index
Back to the overall index

diff -urN linux-2.4.22/include/asm-ia64/sn/serialio.h linux-2.4.23/include/asm-ia64/sn/serialio.h
@@ -0,0 +1,477 @@
+/*
+ * Copyright (c) 2003 Silicon Graphics, Inc.  All Rights Reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it 
+ * under the terms of version 2 of the GNU General Public License 
+ * as published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope that it would be useful, but 
+ * WITHOUT ANY WARRANTY; without even the implied warranty of 
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
+ * 
+ * Further, this software is distributed without any warranty that it is 
+ * free of the rightful claim of any third person regarding infringement 
+ * or the like.  Any license provided herein, whether implied or 
+ * otherwise, applies only to this software file.  Patent licenses, if 
+ * any, provided herein do not apply to combinations of this program with 
+ * other software, or any other product whatsoever.
+ * 
+ * You should have received a copy of the GNU General Public 
+ * License along with this program; if not, write the Free Software 
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ * 
+ * Contact information:  Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, 
+ * Mountain View, CA  94043, or:
+ * 
+ * http://www.sgi.com 
+ * 
+ */
+
+#ifndef _ASM_IA64_SN_SERIALIO_H
+#define _ASM_IA64_SN_SERIALIO_H
+
+/*
+ * Definitions for the modular serial i/o driver.
+ *
+ * The modular serial i/o driver is a driver which has the hardware
+ * dependent and hardware independent parts separated into separate
+ * modules. The upper half is responsible for all hardware independent
+ * operations, specifically the interface to the kernel. An upper half
+ * may implement a streams interface, character interface, or whatever
+ * interface it wishes to the kernel. The same upper half may access any
+ * physical hardware through a set of standardized entry points into the
+ * lower level, which deals directly with the hardware. Whereas a
+ * separate upper layer exists for each kernel interface type (streams,
+ * character, polling etc), a separate lower level exists for each
+ * hardware type supported. Any upper and lower layer pair may be
+ * connected to form a complete driver. This file defines the interface
+ * between the two
+ */
+
+/* Definitions needed per port by both layers. Each lower layer
+ * declares a set of per-port private data areas describing each
+ * physical port, and by definition the first member of that private
+ * data is the following structure. Thus a pointer to the lower
+ * layer's private data is interchangeable with a pointer to the
+ * common private data, and the upper layer does not allocate anything
+ * so it does need to know anything about the physical configuration
+ * of the machine. This structure may also contain any hardware
+ * independent info that must be persistent across device closes.
+ */
+typedef struct sioport {
+    /* calling vectors */
+    struct serial_calldown	*sio_calldown;
+    struct serial_callup	*sio_callup;
+
+    void	*sio_upper;	/* upper layer's private data area */
+
+    vertex_hdl_t sio_vhdl;	/* vertex handle of the hardware independent
+				 * portion of this port (e.g. tty/1 without
+				 * the d,m,f, etc)
+				 */
+    spinlock_t  sio_lock;
+} sioport_t;
+
+/* bits for sio_flags */
+#define SIO_HWGRAPH_INITED	0x1
+#define SIO_SPINLOCK_HELD	0x2
+#define SIO_MUTEX_HELD		0x4
+#define SIO_LOCKS_MASK (SIO_SPINLOCK_HELD | SIO_MUTEX_HELD)
+
+#if DEBUG
+/* bits for sio_lockcalls, one per downcall except du_write which is
+ * not called by an upper layer.
+ */
+#define L_OPEN		0x0001
+#define L_CONFIG	0x0002
+#define L_ENABLE_HFC	0x0004
+#define L_SET_EXTCLK	0x0008
+#define L_WRITE		0x0010
+#define L_BREAK		0x0020
+#define L_READ		0x0040
+#define L_NOTIFICATION	0x0080
+#define L_RX_TIMEOUT	0x0100
+#define L_SET_DTR	0x0200
+#define L_SET_RTS	0x0400
+#define L_QUERY_DCD	0x0800
+#define L_QUERY_CTS	0x1000
+#define L_SET_PROTOCOL	0x2000
+#define L_ENABLE_TX	0x4000
+
+#define L_LOCK_ALL	(~0)
+
+/* debug lock assertion: each lower layer entry point does an
+ * assertion with the following macro, passing in the port passed to
+ * the entry point and the bit corresponding to which entry point it
+ * is. If the upper layer has turned on the bit for that entry point,
+ * sio_port_islocked is called, thus an upper layer may specify that
+ * it is ok for a particular downcall to be made without the port lock
+ * held.
+ */
+#define L_LOCKED(port, flag) (((port)->sio_lockcalls & (flag)) == 0 || \
+			      sio_port_islocked(port))
+#endif
+
+/* flags for next_char_state */
+#define NCS_BREAK 1
+#define NCS_PARITY 2
+#define NCS_FRAMING 4
+#define NCS_OVERRUN 8
+
+/* protocol types for DOWN_SET_PROTOCOL */
+enum sio_proto {
+    PROTO_RS232,
+    PROTO_RS422
+};
+
+/* calldown vector. This is a set of entry points into a lower layer
+ * module, providing black-box access to the hardware by the upper
+ * layer
+ */
+struct serial_calldown {
+
+    /* hardware configuration */
+    int (*down_open)		(sioport_t *port);
+    int (*down_config)		(sioport_t *port, int baud, int byte_size,
+				 int stop_bits, int parenb, int parodd);
+    int (*down_enable_hfc)	(sioport_t *port, int enable);
+    int (*down_set_extclk)	(sioport_t *port, int clock_factor);
+
+    /* data transmission */
+    int (*down_write)		(sioport_t *port, char *buf, int len);
+    int (*down_du_write)	(sioport_t *port, char *buf, int len);
+    void (*down_du_flush)	(sioport_t *port);
+    int (*down_break)		(sioport_t *port, int brk);
+    int (*down_enable_tx)	(sioport_t *port, int enb);
+
+    /* data reception */
+    int (*down_read)		(sioport_t *port, char *buf, int len);
+    
+    /* event notification */
+    int (*down_notification)	(sioport_t *port, int mask, int on);
+    int (*down_rx_timeout)	(sioport_t *port, int timeout);
+
+    /* modem control */
+    int (*down_set_DTR)		(sioport_t *port, int dtr);
+    int (*down_set_RTS)		(sioport_t *port, int rts);
+    int (*down_query_DCD)	(sioport_t *port);
+    int (*down_query_CTS)	(sioport_t *port);
+
+    /* transmission protocol */
+    int (*down_set_protocol)	(sioport_t *port, enum sio_proto protocol);
+
+    /* memory mapped user driver support */
+    int (*down_mapid)		(sioport_t *port, void *arg);
+    int (*down_map)		(sioport_t *port, uint64_t *vt, off_t off);
+    void (*down_unmap)		(sioport_t *port);
+    int (*down_set_sscr)	(sioport_t *port, int arg, int flag);
+};
+
+/*
+ * Macros used by the upper layer to access the lower layer. Unless
+ * otherwise noted, all integer functions should return 0 on success
+ * or 1 if the hardware does not support the requested operation. In
+ * the case of non-support, the upper layer may work around the problem
+ * where appropriate or just notify the user.
+ * For hardware which supports detaching, these functions should
+ * return -1 if the hardware is no longer present.
+ */
+
+/* open a device. Do whatever initialization/resetting necessary */
+#define DOWN_OPEN(p) \
+    ((p)->sio_calldown->down_open(p))
+
+/* configure the hardware with the given baud rate, number of stop
+ * bits, byte size and parity
+ */
+#define DOWN_CONFIG(p, a, b, c, d, e) \
+    ((p)->sio_calldown->down_config(p, a, b, c, d, e))
+
+/* Enable hardware flow control. If the hardware does not support
+ * this, the upper layer will emulate HFC by manipulating RTS and CTS
+ */
+#define DOWN_ENABLE_HFC(p, enb) \
+    ((p)->sio_calldown->down_enable_hfc(p, enb))
+
+/* Set external clock to the given clock factor. If cf is zero,
+ * internal clock is used. If cf is non-zero external clock is used
+ * and the clock is cf times the baud.
+ */
+#define DOWN_SET_EXTCLK(p, cf) \
+    ((p)->sio_calldown->down_set_extclk(p, cf))
+
+/* Write bytes to the device. The number of bytes actually written is
+ * returned. The upper layer will continue to call this function until
+ * it has no more data to send or until 0 is returned, indicating that
+ * no more bytes may be sent until some have drained.
+ */
+#define DOWN_WRITE(p, buf, len) \
+    ((p)->sio_calldown->down_write(p, buf, len))
+
+/* Same as DOWN_WRITE, but called only from synchronous du output
+ * routines. Allows lower layer the option of implementing kernel
+ * printfs differently than ordinary console output.
+ */
+#define DOWN_DU_WRITE(p, buf, len) \
+    ((p)->sio_calldown->down_du_write(p, buf, len))
+
+/* Flushes previous down_du_write() calls.  Needed on serial controllers
+ * that can heavily buffer output like IOC3 for conbuf_flush().
+ */
+#define DOWN_DU_FLUSH(p) \
+     ((p)->sio_calldown->down_du_flush(p))
+
+/* Set the output break condition high or low */
+#define DOWN_BREAK(p, brk) \
+    ((p)->sio_calldown->down_break(p, brk))
+
+/* Enable/disable TX for soft flow control */
+#define DOWN_ENABLE_TX(p) \
+    ((p)->sio_calldown->down_enable_tx(p, 1))
+#define DOWN_DISABLE_TX(p) \
+    ((p)->sio_calldown->down_enable_tx(p, 0))
+
+/* Read bytes from the device. The number of bytes actually read is
+ * returned. All bytes returned by a single call have the same error
+ * status. Thus if the device has 10 bytes queued for input and byte 5
+ * has a parity error, the first call to DOWN_READ will return bytes 0-4
+ * only. A subsequent call to DOWN_READ will first cause a call to
+ * UP_PARITY_ERROR to notify the upper layer that the next byte has an
+ * error, and then the call to DOWN_READ returns byte 5 alone. A
+ * subsequent call to DOWN_READ returns bytes 6-9. The upper layer
+ * continues to call DOWN_READ until 0 is returned, or until it runs out
+ * of buffer space to receive the chars.
+ */
+#define DOWN_READ(p, buf, len) \
+    ((p)->sio_calldown->down_read(p, buf, len))
+
+/* Turn on/off event notification for the specified events. Notification
+ * status is unchanged for those events not specified.
+ */
+#define DOWN_NOTIFICATION(p, mask, on) \
+    ((p)->sio_calldown->down_notification(p, mask, on))
+
+/* Notification types. 1 per upcall. The upper layer can specify
+ * exactly which upcalls it wishes to receive. UP_DETACH is mandatory
+ * when applicable and cannot be enabled/disabled.
+ */
+#define N_DATA_READY	0x01
+#define N_OUTPUT_LOWAT	0x02
+#define N_BREAK		0x04
+#define N_PARITY_ERROR	0x08
+#define N_FRAMING_ERROR	0x10
+#define N_OVERRUN_ERROR	0x20
+#define N_DDCD		0x40
+#define N_DCTS		0x80
+
+#define N_ALL_INPUT	(N_DATA_READY | N_BREAK |			\
+			 N_PARITY_ERROR | N_FRAMING_ERROR |		\
+			 N_OVERRUN_ERROR | N_DDCD | N_DCTS)
+
+#define N_ALL_OUTPUT	N_OUTPUT_LOWAT
+
+#define N_ALL_ERRORS	(N_PARITY_ERROR | N_FRAMING_ERROR | N_OVERRUN_ERROR)
+
+#define N_ALL		(N_DATA_READY | N_OUTPUT_LOWAT | N_BREAK |	\
+			 N_PARITY_ERROR | N_FRAMING_ERROR |		\
+			 N_OVERRUN_ERROR | N_DDCD | N_DCTS)
+
+/* Instruct the lower layer that the upper layer would like to be
+ * notified every t ticks when data is being received. If data is
+ * streaming in, the lower layer should buffer enough data that
+ * notification is not required more often than requested, and set a
+ * timeout so that notification does not occur less often than
+ * requested. If the lower layer does not support such operations, it
+ * should return 1, indicating that the upper layer should emulate these
+ * functions in software.
+ */
+#define DOWN_RX_TIMEOUT(p, t) \
+    ((p)->sio_calldown->down_rx_timeout(p, t))
+
+/* Set the output value of DTR */
+#define DOWN_SET_DTR(p, dtr) \
+    ((p)->sio_calldown->down_set_DTR(p, dtr))
+
+/* Set the output value of RTS */
+#define DOWN_SET_RTS(p, rts) \
+    ((p)->sio_calldown->down_set_RTS(p, rts))
+
+/* Query current input value of DCD */
+#define DOWN_QUERY_DCD(p) \
+    ((p)->sio_calldown->down_query_DCD(p))
+
+/* Query current input value of CTS */
+#define DOWN_QUERY_CTS(p) \
+    ((p)->sio_calldown->down_query_CTS(p))
+
+/* Set transmission protocol */
+#define DOWN_SET_PROTOCOL(p, proto) \
+    ((p)->sio_calldown->down_set_protocol(p, proto))
+
+/* Query mapped interface type */
+#define DOWN_GET_MAPID(p, arg) \
+    ((p)->sio_calldown->down_mapid(p, arg))
+
+/* Perform mapping to user address space */
+#define DOWN_MAP(p, vt, off) \
+    ((p)->sio_calldown->down_map(p, vt, off))
+
+/* Cleanup after mapped port is closed */
+#define DOWN_UNMAP(p) \
+    ((p)->sio_calldown->down_unmap(p))
+
+/* Set/Reset ioc3 sscr register */
+#define DOWN_SET_SSCR(p, arg, flag) \
+    ((p)->sio_calldown->down_set_sscr(p, arg, flag))
+
+
+/* The callup struct. This is a set of entry points providing
+ * black-box access to the upper level kernel interface by the
+ * hardware handling code. These entry points are used for event
+ * notification 
+ */
+struct serial_callup {
+    void (*up_data_ready)	(sioport_t *port);
+    void (*up_output_lowat)	(sioport_t *port);
+    void (*up_ncs)		(sioport_t *port, int ncs);
+    void (*up_dDCD)		(sioport_t *port, int dcd);
+    void (*up_dCTS)		(sioport_t *port, int cts);
+    void (*up_detach)		(sioport_t *port);
+};
+
+/*
+ * Macros used by the lower layer to access the upper layer for event
+ * notificaiton. These functions are generally called in response to
+ * an interrupt. Since the port lock may be released across UP calls,
+ * we must check the callup vector each time. However since the port
+ * lock is held during DOWN calls (from which these UP calls are made)
+ * there is no danger of the sio_callup vector being cleared between
+ * where it is checked and where it is used in the macro
+ */
+
+/* Notify the upper layer that there are input bytes available and
+ * DOWN_READ may now be called
+ */
+#define UP_DATA_READY(p) \
+    ((p)->sio_callup ? (p)->sio_callup->up_data_ready(p):(void)0)
+
+/* Notify the upper layer that the lower layer has freed up some
+ * output buffer space and DOWN_WRITE may now be called
+ */
+#define UP_OUTPUT_LOWAT(p) \
+    ((p)->sio_callup ? (p)->sio_callup->up_output_lowat(p):(void)0)
+
+/* Notify the upper layer that the next char returned by DOWN_READ
+ * has the indicated special status. (see NCS_* above)
+ */
+#define UP_NCS(p, ncs) \
+    ((p)->sio_callup ? (p)->sio_callup->up_ncs(p, ncs):(void)0)
+
+/* Notify the upper layer of the new DCD input value */
+#define UP_DDCD(p, dcd) \
+    ((p)->sio_callup ? (p)->sio_callup->up_dDCD(p, dcd):(void)0)
+
+/* Notify the upper layer of the new CTS input value */
+#define UP_DCTS(p, cts) \
+    ((p)->sio_callup ? (p)->sio_callup->up_dCTS(p, cts):(void)0)
+
+/* notify the upper layer that the lower layer hardware has been detached 
+ * Since the port lock is NOT held when this macro is executed, we must
+ * guard against the sio_callup vector being cleared between when we check
+ * it and when we make the upcall, so we use a local copy.
+ */
+#define UP_DETACH(p) \
+{ \
+    struct serial_callup *up; \
+    if ((up = (p)->sio_callup)) \
+	up->up_detach(p); \
+}
+
+/* Port locking protocol:
+ * Any time a DOWN call is made into one of the lower layer entry points,
+ * the corresponding port is already locked and remains locked throughout
+ * that downcall. When a lower layer routine makes an UP call, the port
+ * is assumed to be locked on entry to the upper layer routine, but the
+ * upper layer routine may release and reacquire the lock if it wishes.
+ * Thus the lower layer routine should not rely on the port lock being
+ * held across upcalls. Further, since the port may be disconnected
+ * any time the port lock is not held, an UP call may cause subsequent
+ * UP calls to become noops since the upcall vector will be zeroed when
+ * the port is closed. Thus, any lower layer routine making UP calls must
+ * be prepared to deal with the possibility that any UP calls it makes
+ * are noops.
+ *
+ * The only time a lower layer routine should manipulate the port lock
+ * is the lower layer interrupt handler, which should acquire the lock
+ * during its critical execution.
+ * 
+ * Any function which assumes that the port is or isn't locked should
+ * use the function sio_port_islocked in an ASSERT statement to verify
+ * this assumption
+ */
+
+#if DEBUG
+extern int sio_port_islocked(sioport_t *);
+#endif
+
+#define SIO_LOCK_PORT(port, flags)	spin_lock_irqsave(&port->sio_lock, flags)
+#define SIO_UNLOCK_PORT(port, flags)	spin_unlock_irqrestore(&port->sio_lock, flags)
+
+/* kernel debugger support */
+#ifdef _LANGUAGE_C
+extern int console_is_tport;
+#define CNTRL_A		'\001'
+#if DEBUG
+#ifndef DEBUG_CHAR
+#define DEBUG_CHAR	CNTRL_A
+#endif
+#else
+#define DEBUG_CHAR	CNTRL_A
+#endif
+#endif
+
+
+extern void ioc4_serial_initport(sioport_t *, int);
+
+
+/* flags to notify sio_initport() which type of nodes are
+ * desired for a particular hardware type
+ */
+#define NODE_TYPE_D		0x01 /* standard plain streams interface */
+#define NODE_TYPE_MODEM		0x02 /* modem streams interface */
+#define NODE_TYPE_FLOW_MODEM	0x04 /* modem/flow control streams */
+#define NODE_TYPE_CHAR		0x08 /* character interface */
+#define NODE_TYPE_MIDI		0x10 /* midi interface */
+#define NODE_TYPE_D_RS422	0x20 /* RS422 without flow control */
+#define NODE_TYPE_FLOW_RS422	0x40 /* RS422 with flow control */
+
+#define NODE_TYPE_USER		0x80 /* user mapped interface */
+#define NODE_TYPE_TIMESTAMPED	0x100 /* user mapped interface */
+
+#define NODE_TYPE_ALL_RS232	(NODE_TYPE_D | NODE_TYPE_MODEM | \
+				 NODE_TYPE_FLOW_MODEM | NODE_TYPE_CHAR | \
+				 NODE_TYPE_MIDI | NODE_TYPE_TIMESTAMPED)
+#define NODE_TYPE_ALL_RS422	(NODE_TYPE_D_RS422 | NODE_TYPE_FLOW_RS422 | \
+				 NODE_TYPE_TIMESTAMPED)
+
+/* Flags for devflags field of miditype structure */
+#define MIDIDEV_EXTERNAL 0             /* lower half initializes devflags to this for an external device */
+#define MIDIDEV_INTERNAL 0x2
+
+#define MIDIDEV_UNREGISTERED -1    /* Initialization for portidx field of miditype structure */
+
+typedef struct miditype_s{
+  int devflags;                    /* DEV_EXTERNAL, DEV_INTERNAL */
+  int portidx;  
+  void *midi_upper;                      
+  sioport_t *port;
+} miditype_t;
+
+typedef struct tsiotype_s{
+  void *tsio_upper;                      
+  sioport_t *port;
+  int portidx;
+  int urbidx;
+} tsiotype_t;
+
+#endif /* _ASM_IA64_SN_SERIALIO_H */

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)