patch-2.2.18 linux/include/asm-m68k/m68kserial.h

Next file: linux/include/asm-m68k/mac_iop.h
Previous file: linux/include/asm-m68k/linux_logo.h
Back to the patch index
Back to the overall index

diff -u --new-file --recursive --exclude-from /usr/src/exclude v2.2.17/include/asm-m68k/m68kserial.h linux/include/asm-m68k/m68kserial.h
@@ -0,0 +1,454 @@
+/*
+ * include/linux/m68kserial.h
+ *
+ * Copyright (C) 1992 by Theodore Ts'o.
+ * 
+ * Redistribution of this file is permitted under the terms of the GNU 
+ * Public License (GPL)
+ *
+ * 2/28/99 RZ: renamed to allow coexistence with serial.c driver
+ */
+
+
+#ifndef _M68K_SERIAL_H
+#define _M68K_SERIAL_H
+
+
+/* m68k serial port types are numbered from 100 to avoid interference
+ * with the PC types (1..4)
+ */
+#define PORT_UNKNOWN	0
+#define PORT_8250	1
+#define PORT_16450	2
+#define PORT_16550	3
+#define PORT_16550A	4
+#define PORT_CIRRUS     5
+#define PORT_16650V2	7
+#define PORT_16750	8
+
+#define SER_SCC_NORM	100	/* standard SCC channel */
+#define	SER_SCC_DMA	101	/* SCC channel with DMA support */
+#define	SER_MFP_CTRL	102	/* standard MFP port with modem control signals */
+#define	SER_MFP_BARE	103	/* MFP port without modem controls */
+#define	SER_MIDI	104	/* Atari MIDI */
+#define	SER_AMIGA	105	/* Amiga built-in serial port */
+#define SER_IOEXT	106	/* Amiga GVP IO-Extender (16c552) */
+#define SER_MFC_III	107	/* Amiga BSC Multiface Card III (MC68681) */
+#define SER_WHIPPET	108	/* Amiga Hisoft Whippet PCMCIA (16c550B) */
+#define SER_SCC_MVME	109	/* MVME162/MVME172 ports */
+#define SER_SCC_MAC	110	/* Macintosh SCC channel */
+#define SER_HPDCA	111	/* HP DCA serial */
+#define SER_SCC_BVME	112	/* BVME6000 ports */
+
+struct serial_struct {
+	int	type;
+	int	line;
+	int	port;
+	int	irq;
+	int	flags;
+	int	xmit_fifo_size;
+	int	custom_divisor;
+	int	baud_base;
+	unsigned short	close_delay;
+	char	reserved_char[2];
+	int	hub6;
+	unsigned short	closing_wait; /* time to wait before closing */
+	unsigned short	closing_wait2; /* no longer used... */
+	int	reserved[4];
+};
+
+/*
+ * For the close wait times, 0 means wait forever for serial port to
+ * flush its output.  65535 means don't wait at all.
+ */
+#define ASYNC_CLOSING_WAIT_INF	0
+#define ASYNC_CLOSING_WAIT_NONE	65535
+
+/* This function tables does the abstraction from the underlying
+ * hardware:
+ *
+ *   init(): Initialize the port as necessary, set RTS and DTR and
+ *      enable interrupts. It does not need to set the speed and other
+ *      parameters, because change_speed() is called, too.
+ *   deinit(): Stop and shutdown the port (e.g. disable interrupts, ...)
+ *   enab_tx_int(): Enable or disable the Tx Buffer Empty interrupt
+ *      independently from other interrupt sources. If the int is
+ *      enabled, the transmitter should also be restarted, i.e. if there
+ *      are any chars to be sent, they should be put into the Tx
+ *      register. The real en/disabling of the interrupt may be a no-op
+ *      if there is no way to do this or it is too complex. This Tx ints
+ *      are just disabled to save some interrupts if the transmitter is
+ *      stopped anyway. But the restarting must be implemented!
+ *   check_custom_divisor(): Check the given custom divisor for legality
+ *      and return 0 if OK, non-zero otherwise.
+ *   change_speed(): Set port speed, character size, number of stop
+ *      bits and parity from the termios structure. If the user wants
+ *      to set the speed with a custom divisor, he is required to
+ *      check the baud_base first!
+ *   throttle(): Set or clear the RTS line according to 'status'.
+ *   set_break(): Set or clear the 'Send a Break' flag.
+ *   get_serial_info(): Fill in the baud_base and custom_divisor
+ *      fields of a serial_struct. It may also modify other fields, if
+ *      needed.
+ *   get_modem_info(): Return the status of RTS, DTR, DCD, RI, DSR and CTS.
+ *   set_modem_info(): Set the status of RTS and DTR according to
+ *      'new_dtr' and 'new_rts', resp. 0 = clear, 1 = set, -1 = don't change
+ *   ioctl(): Process any port-specific ioctl's. This pointer may be
+ *      NULL, if the port has no own ioctl's.
+ *   stop_receive(): Turn off the Rx part of the port, so no more characters
+ *      will be received. This is called before shutting the port down.
+ *   trans_empty(): Return !=0 if there are no more characters still to be
+ *      sent out (Tx buffer register and FIFOs empty)
+ *   check_open(): Is called before the port is opened. The driver can check
+ *      if that's ok and return an error code, or keep track of the opening
+ *      even before init() is called. Use deinit() for matching closing of the
+ *      port.
+ *
+ */
+
+struct m68k_async_struct;
+
+typedef struct {
+	void (*init)( struct m68k_async_struct *info );
+	void (*deinit)( struct m68k_async_struct *info, int leave_dtr );
+	void (*enab_tx_int)( struct m68k_async_struct *info, int enab_flag );
+	int  (*check_custom_divisor)( struct m68k_async_struct *info, int baud_base,
+				     int divisor );
+	void (*change_speed)( struct m68k_async_struct *info );
+	void (*throttle)( struct m68k_async_struct *info, int status );
+	void (*set_break)( struct m68k_async_struct *info, int break_flag );
+	void (*get_serial_info)( struct m68k_async_struct *info,
+				struct serial_struct *retinfo );
+	unsigned int (*get_modem_info)( struct m68k_async_struct *info );
+	int  (*set_modem_info)( struct m68k_async_struct *info, int new_dtr,
+			       int new_rts );
+	int  (*ioctl)( struct tty_struct *tty, struct file *file,
+		      struct m68k_async_struct *info, unsigned int cmd,
+		      unsigned long arg );
+	void (*stop_receive)( struct m68k_async_struct *info );
+	int  (*trans_empty)( struct m68k_async_struct *info );
+	int  (*check_open)( struct m68k_async_struct *info, struct tty_struct *tty,
+			   struct file *file );
+} SERIALSWITCH;
+
+/*
+ * Definitions for m68k_async_struct (and serial_struct) flags field
+ */
+#define ASYNC_HUP_NOTIFY 0x0001 /* Notify getty on hangups and closes 
+				   on the callout port */
+#define ASYNC_FOURPORT  0x0002	/* Set OU1, OUT2 per AST Fourport settings */
+#define ASYNC_SAK	0x0004	/* Secure Attention Key (Orange book) */
+#define ASYNC_SPLIT_TERMIOS 0x0008 /* Separate termios for dialin/callout */
+
+#define ASYNC_SPD_MASK	0x1030
+#define ASYNC_SPD_HI	0x0010	/* Use 56000 instead of 38400 bps */
+
+#define ASYNC_SPD_VHI	0x0020  /* Use 115200 instead of 38400 bps */
+#define ASYNC_SPD_CUST	0x0030  /* Use user-specified divisor */
+
+#define ASYNC_SKIP_TEST	0x0040 /* Skip UART test during autoconfiguration */
+#define ASYNC_AUTO_IRQ  0x0080 /* Do automatic IRQ during autoconfiguration */
+#define ASYNC_SESSION_LOCKOUT 0x0100 /* Lock out cua opens based on session */
+#define ASYNC_PGRP_LOCKOUT    0x0200 /* Lock out cua opens based on pgrp */
+#define ASYNC_CALLOUT_NOHUP   0x0400 /* Don't do hangups for cua device */
+
+#define ASYNC_HARDPPS_CD	0x0800	/* Call hardpps when CD goes high  */
+
+#define ASYNC_SPD_SHI	0x1000	/* Use 230400 instead of 38400 bps */
+#define ASYNC_SPD_WARP	0x1010	/* Use 460800 instead of 38400 bps */
+
+#define ASYNC_FLAGS	0x1FFF	/* Possible legal async flags */
+#define ASYNC_USR_MASK 0x1430	/* Legal flags that non-privileged
+				 * users can set or reset */
+
+/* Internal flags used only by drivers/char/m68kserial.c */
+#define ASYNC_INITIALIZED	0x80000000 /* Serial port was initialized */
+#define ASYNC_CALLOUT_ACTIVE	0x40000000 /* Call out device is active */
+#define ASYNC_NORMAL_ACTIVE	0x20000000 /* Normal device is active */
+#define ASYNC_BOOT_AUTOCONF	0x10000000 /* Autoconfigure port on bootup */
+#define ASYNC_CLOSING		0x08000000 /* Serial port is closing */
+#define ASYNC_CTS_FLOW		0x04000000 /* Do CTS flow control */
+#define ASYNC_CHECK_CD		0x02000000 /* i.e., CLOCAL */
+
+#define ASYNC_INTERNAL_FLAGS	0xFF000000 /* Internal flags */
+
+/*
+ * Serial input interrupt line counters -- external structure
+ * Four lines can interrupt: CTS, DSR, RI, DCD
+ */
+struct serial_icounter_struct {
+	int cts, dsr, rng, dcd;
+	int rx, tx;
+	int frame, overrun, parity, brk;
+	int buf_overrun;
+	int reserved[9];
+};
+
+
+#ifdef __KERNEL__
+/*
+ * This is our internal structure for each serial port's state.
+ * 
+ * Many fields are paralleled by the structure used by the serial_struct
+ * structure.
+ *
+ * For definitions of the flags field, see tty.h
+ */
+
+#include <linux/termios.h>
+#include <linux/tqueue.h>
+
+#include <linux/config.h>	/* for Mac SCC extensions */
+
+#ifdef CONFIG_MAC
+#define NUM_ZSREGS    16
+struct mac_zschannel {
+	volatile unsigned char *control;
+	volatile unsigned char *data;
+};
+struct m68k_async_private;
+#endif
+
+struct m68k_async_struct {
+	int			magic;
+	int			baud_base;
+	int			port;
+	int			irq;
+	int			flags; 		/* defined in tty.h */
+	int			hub6;		/* HUB6 plus one */
+	int			type;
+	struct tty_struct 	*tty;
+	int			read_status_mask;
+	int			ignore_status_mask;
+	int			timeout;
+	int			xmit_fifo_size;
+	int			custom_divisor;
+	int			x_char;	/* xon/xoff character */
+	int			close_delay;
+	unsigned short		closing_wait;
+	unsigned short		closing_wait2;
+	int			IER; 	/* Interrupt Enable Register */
+	int			MCR; 	/* Modem control register */
+	int			MCR_noint; /* MCR with interrupts off */
+	unsigned long		event;
+	unsigned long		last_active;
+	int			line;
+	int			count;	    /* # of fd on device */
+	int			blocked_open; /* # of blocked opens */
+	long			session; /* Session of opening process */
+	long			pgrp; /* pgrp of opening process */
+	unsigned char 		*xmit_buf;
+	int			xmit_head;
+	int			xmit_tail;
+	int			xmit_cnt;
+	struct tq_struct	tqueue;
+	struct termios		normal_termios;
+	struct termios		callout_termios;
+	struct wait_queue	*open_wait;
+	struct wait_queue	*close_wait;
+	struct wait_queue	*delta_msr_wait;
+	struct async_icount	icount;	/* kernel counters for the 4 input interrupts */
+	struct m68k_async_struct	*next_port; /* For the linked list */
+	struct m68k_async_struct	*prev_port;
+	void			*board_base; /* board-base address for use with
+						boards carrying several UART's,
+						like some Amiga boards. */
+	unsigned short		nr_uarts;    /* UART-counter, that indicates
+						how many UART's there are on
+						the board.  If the board has a
+						IRQ-register, this can be used
+						to check if any of the uarts,
+						on the board has requested an
+						interrupt, instead of checking
+						IRQ-registers on all UART's */
+	SERIALSWITCH		*sw;		/* functions to manage this port */
+#ifdef CONFIG_MAC
+	struct m68k_async_private	*private;
+#endif
+};
+
+#ifdef CONFIG_MAC
+struct m68k_async_private {
+	struct m68k_async_info	*zs_next;	/* For IRQ servicing chain */
+	struct mac_zschannel	*zs_channel;	/* Channel registers */
+	struct mac_zschannel	*zs_chan_a;	/* A side registers */
+	unsigned char		read_reg_zero;
+
+	char			soft_carrier;	/* Use soft carrier on this */
+	char			break_abort;	/* console, process brk/abrt */
+	char			kgdb_channel;	/* Kgdb running on this channel */
+	char			is_cons;	/* Is this our console. */
+	unsigned char		tx_active;	/* character being xmitted */
+	unsigned char		tx_stopped;	/* output is suspended */
+
+	/* We need to know the current clock divisor
+	 * to read the bps rate the chip has currently
+	 * loaded.
+	 */
+	unsigned char		clk_divisor;	/* May be 1, 16, 32, or 64 */
+	int			zs_baud;
+
+	/* Current write register values */
+	unsigned char		curregs[NUM_ZSREGS];
+
+	/* Values we need to set next opportunity */
+	unsigned char		pendregs[NUM_ZSREGS];
+
+	char			change_needed;
+};
+#endif
+#define SERIAL_MAGIC 0x5301
+
+/*
+ * The size of the serial xmit buffer is 1 page, or 4096 bytes
+ */
+#define SERIAL_XMIT_SIZE 4096
+
+/*
+ * Events are used to schedule things to happen at timer-interrupt
+ * time, instead of at rs interrupt time.
+ */
+#define RS_EVENT_WRITE_WAKEUP	0
+
+/* number of characters left in xmit buffer before we ask for more */
+#define WAKEUP_CHARS 256
+
+/* Export to allow PCMCIA to use this - Dave Hinds */
+extern int m68k_register_serial(struct serial_struct *req);
+extern void m68k_unregister_serial(int line);
+extern int register_serial(struct serial_struct *req);
+extern void unregister_serial(int line);
+extern struct m68k_async_struct rs_table[];
+extern task_queue tq_serial;
+
+
+/*
+ * This routine is used by the interrupt handler to schedule
+ * processing in the software interrupt portion of the driver.
+ */
+static __inline__ void rs_sched_event(struct m68k_async_struct *info, int event)
+{
+	info->event |= 1 << event;
+	queue_task(&info->tqueue, &tq_serial);
+	mark_bh(SERIAL_BH);
+}
+
+static __inline__ void rs_receive_char( struct m68k_async_struct *info,
+					    int ch, int err )
+{
+	struct tty_struct *tty = info->tty;
+	
+	if (tty->flip.count >= TTY_FLIPBUF_SIZE)
+		return;
+	tty->flip.count++;
+	switch(err) {
+	case TTY_BREAK:
+		info->icount.brk++;
+		if (info->flags & ASYNC_SAK)
+			do_SAK(tty);
+		break;
+	case TTY_PARITY:
+		info->icount.parity++;
+		break;
+	case TTY_OVERRUN:
+		info->icount.overrun++;
+		break;
+	case TTY_FRAME:
+		info->icount.frame++;
+		break;
+	}
+	*tty->flip.flag_buf_ptr++ = err;
+	*tty->flip.char_buf_ptr++ = ch;
+	info->icount.rx++;
+	tty_flip_buffer_push(tty);
+}
+
+static __inline__ int rs_get_tx_char( struct m68k_async_struct *info )
+{
+	unsigned char ch;
+	
+	if (info->x_char) {
+		ch = info->x_char;
+		info->icount.tx++;
+		info->x_char = 0;
+		return( ch );
+	}
+
+	if (info->xmit_cnt <= 0 || info->tty->stopped || info->tty->hw_stopped)
+		return( -1 );
+
+	ch = info->xmit_buf[info->xmit_tail++];
+	info->xmit_tail &= SERIAL_XMIT_SIZE - 1;
+	info->icount.tx++;
+	if (--info->xmit_cnt < WAKEUP_CHARS)
+		rs_sched_event(info, RS_EVENT_WRITE_WAKEUP);
+	return( ch );
+}
+
+static __inline__ int rs_no_more_tx( struct m68k_async_struct *info )
+{
+	return( info->xmit_cnt <= 0 ||
+			info->tty->stopped ||
+			info->tty->hw_stopped );
+}
+
+static __inline__ void rs_dcd_changed( struct m68k_async_struct *info, int dcd )
+
+{
+	/* update input line counter */
+	info->icount.dcd++;
+	wake_up_interruptible(&info->delta_msr_wait);
+
+	if (info->flags & ASYNC_CHECK_CD) {
+#if (defined(SERIAL_DEBUG_OPEN) || defined(SERIAL_DEBUG_INTR))
+		printk("ttyS%d CD now %s...", info->line,
+		       dcd ? "on" : "off");
+#endif		
+		if (dcd) {
+			wake_up_interruptible(&info->open_wait);
+		} else if (!((info->flags & ASYNC_CALLOUT_ACTIVE) &&
+			     (info->flags & ASYNC_CALLOUT_NOHUP))) {
+#ifdef SERIAL_DEBUG_OPEN
+			printk("scheduling hangup...");
+#endif
+			if (info->tty)
+				tty_hangup(info->tty);
+		}
+	}
+}
+
+
+void rs_stop( struct tty_struct *tty );
+void rs_start( struct tty_struct *tty );
+
+static __inline__ void rs_check_cts( struct m68k_async_struct *info, int cts )
+{
+	/* update input line counter */
+	info->icount.cts++;
+	wake_up_interruptible(&info->delta_msr_wait);
+	
+	if ((info->flags & ASYNC_CTS_FLOW) && info->tty) {
+		if (info->tty->hw_stopped) {
+			if (cts) {
+#if (defined(SERIAL_DEBUG_INTR) || defined(SERIAL_DEBUG_FLOW))
+				printk("CTS tx start...");
+#endif
+				info->tty->hw_stopped = 0;
+				rs_start( info->tty );
+				rs_sched_event(info, RS_EVENT_WRITE_WAKEUP);
+				return;
+			}
+		} else {
+			if (!cts) {
+				info->tty->hw_stopped = 1;
+				rs_stop( info->tty );
+			}
+		}
+	}
+}
+
+
+#endif /* __KERNEL__ */
+
+#endif /* _M68K_SERIAL_H */
+

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