1139749Simp/*-
2119815Smarcel * Copyright (c) 2003 Marcel Moolenaar
3119815Smarcel * All rights reserved.
4119815Smarcel *
5119815Smarcel * Redistribution and use in source and binary forms, with or without
6119815Smarcel * modification, are permitted provided that the following conditions
7119815Smarcel * are met:
8119815Smarcel *
9119815Smarcel * 1. Redistributions of source code must retain the above copyright
10119815Smarcel *    notice, this list of conditions and the following disclaimer.
11119815Smarcel * 2. Redistributions in binary form must reproduce the above copyright
12119815Smarcel *    notice, this list of conditions and the following disclaimer in the
13119815Smarcel *    documentation and/or other materials provided with the distribution.
14119815Smarcel *
15119815Smarcel * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16119815Smarcel * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17119815Smarcel * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18119815Smarcel * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19119815Smarcel * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20119815Smarcel * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21119815Smarcel * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22119815Smarcel * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23119815Smarcel * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24119815Smarcel * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25119815Smarcel *
26119815Smarcel * $FreeBSD$
27119815Smarcel */
28119815Smarcel
29119815Smarcel#ifndef _DEV_UART_BUS_H_
30119815Smarcel#define _DEV_UART_BUS_H_
31119815Smarcel
32119996Smarcel#ifndef KLD_MODULE
33119996Smarcel#include "opt_uart.h"
34119996Smarcel#endif
35119996Smarcel
36131043Sphk#include <sys/serial.h>
37119996Smarcel#include <sys/timepps.h>
38119996Smarcel
39119815Smarcel/* Drain and flush targets. */
40119815Smarcel#define	UART_DRAIN_RECEIVER	0x0001
41119815Smarcel#define	UART_DRAIN_TRANSMITTER	0x0002
42119815Smarcel#define	UART_FLUSH_RECEIVER	UART_DRAIN_RECEIVER
43119815Smarcel#define	UART_FLUSH_TRANSMITTER	UART_DRAIN_TRANSMITTER
44119815Smarcel
45119815Smarcel/* Received character status bits. */
46119815Smarcel#define	UART_STAT_BREAK		0x0100
47119815Smarcel#define	UART_STAT_FRAMERR	0x0200
48119815Smarcel#define	UART_STAT_OVERRUN	0x0400
49119815Smarcel#define	UART_STAT_PARERR	0x0800
50119815Smarcel
51119815Smarcel/* UART_IOCTL() requests */
52119815Smarcel#define	UART_IOCTL_BREAK	1
53119815Smarcel#define	UART_IOCTL_IFLOW	2
54119815Smarcel#define	UART_IOCTL_OFLOW	3
55137706Smarcel#define	UART_IOCTL_BAUD		4
56119815Smarcel
57119815Smarcel/*
58119815Smarcel * UART class & instance (=softc)
59119815Smarcel */
60119815Smarcelstruct uart_class {
61119815Smarcel	KOBJ_CLASS_FIELDS;
62168281Smarcel	struct uart_ops *uc_ops;	/* Low-level console operations. */
63119815Smarcel	u_int	uc_range;		/* Bus space address range. */
64119815Smarcel	u_int	uc_rclk;		/* Default rclk for this device. */
65119815Smarcel};
66119815Smarcel
67119815Smarcelstruct uart_softc {
68119815Smarcel	KOBJ_FIELDS;
69119815Smarcel	struct uart_class *sc_class;
70119815Smarcel	struct uart_bas	sc_bas;
71119815Smarcel	device_t	sc_dev;
72119815Smarcel
73157300Smarcel	struct mtx	sc_hwmtx_s;	/* Spinlock protecting hardware. */
74157300Smarcel	struct mtx	*sc_hwmtx;
75120143Smarcel
76119815Smarcel	struct resource	*sc_rres;	/* Register resource. */
77119815Smarcel	int		sc_rrid;
78119815Smarcel	int		sc_rtype;	/* SYS_RES_{IOPORT|MEMORY}. */
79119815Smarcel	struct resource *sc_ires;	/* Interrupt resource. */
80119815Smarcel	void		*sc_icookie;
81119815Smarcel	int		sc_irid;
82234194Sgrehan	struct callout	sc_timer;
83119815Smarcel
84119815Smarcel	int		sc_callout:1;	/* This UART is opened for callout. */
85119815Smarcel	int		sc_fastintr:1;	/* This UART uses fast interrupts. */
86119815Smarcel	int		sc_hwiflow:1;	/* This UART has HW input flow ctl. */
87119815Smarcel	int		sc_hwoflow:1;	/* This UART has HW output flow ctl. */
88119815Smarcel	int		sc_leaving:1;	/* This UART is going away. */
89119815Smarcel	int		sc_opened:1;	/* This UART is open for business. */
90119815Smarcel	int		sc_polled:1;	/* This UART has no interrupts. */
91119815Smarcel	int		sc_txbusy:1;	/* This UART is transmitting. */
92197721Smarcel	int		sc_isquelch:1;	/* This UART has input squelched. */
93286059Smarius	int		sc_testintr:1;	/* This UART is under int. testing. */
94119815Smarcel
95119815Smarcel	struct uart_devinfo *sc_sysdev;	/* System device (or NULL). */
96119815Smarcel
97119815Smarcel	int		sc_altbrk;	/* State for alt break sequence. */
98119815Smarcel	uint32_t	sc_hwsig;	/* Signal state. Used by HW driver. */
99119815Smarcel
100119815Smarcel	/* Receiver data. */
101119815Smarcel	uint16_t	*sc_rxbuf;
102119815Smarcel	int		sc_rxbufsz;
103119815Smarcel	int		sc_rxput;
104119815Smarcel	int		sc_rxget;
105119815Smarcel	int		sc_rxfifosz;	/* Size of RX FIFO. */
106119815Smarcel
107119815Smarcel	/* Transmitter data. */
108119815Smarcel	uint8_t		*sc_txbuf;
109119815Smarcel	int		sc_txdatasz;
110119815Smarcel	int		sc_txfifosz;	/* Size of TX FIFO and buffer. */
111119815Smarcel
112119996Smarcel	/* Pulse capturing support (PPS). */
113119996Smarcel	struct pps_state sc_pps;
114287037Sian	int		 sc_pps_mode;
115294229Sian	sbintime_t	 sc_pps_captime;
116119996Smarcel
117119815Smarcel	/* Upper layer data. */
118119815Smarcel	void		*sc_softih;
119119815Smarcel	uint32_t	sc_ttypend;
120119815Smarcel	union {
121119815Smarcel		/* TTY specific data. */
122119815Smarcel		struct {
123119815Smarcel			struct tty *tp;
124119815Smarcel		} u_tty;
125119815Smarcel		/* Keyboard specific data. */
126119815Smarcel		struct {
127119815Smarcel		} u_kbd;
128119815Smarcel	} sc_u;
129119815Smarcel};
130119815Smarcel
131119815Smarcelextern devclass_t uart_devclass;
132286059Smariusextern const char uart_driver_name[];
133119815Smarcel
134119815Smarcelint uart_bus_attach(device_t dev);
135119815Smarcelint uart_bus_detach(device_t dev);
136246243Savgint uart_bus_resume(device_t dev);
137157300Smarcelserdev_intr_t *uart_bus_ihand(device_t dev, int ipend);
138158119Smarcelint uart_bus_ipend(device_t dev);
139120452Smarcelint uart_bus_probe(device_t dev, int regshft, int rclk, int rid, int chan);
140157300Smarcelint uart_bus_sysdev(device_t dev);
141119815Smarcel
142197721Smarcelvoid uart_sched_softih(struct uart_softc *, uint32_t);
143197721Smarcel
144119815Smarcelint uart_tty_attach(struct uart_softc *);
145119815Smarcelint uart_tty_detach(struct uart_softc *);
146287037Sianstruct mtx *uart_tty_getlock(struct uart_softc *);
147119815Smarcelvoid uart_tty_intr(void *arg);
148119815Smarcel
149119815Smarcel/*
150119815Smarcel * Receive buffer operations.
151119815Smarcel */
152119815Smarcelstatic __inline int
153119815Smarceluart_rx_empty(struct uart_softc *sc)
154119815Smarcel{
155286059Smarius
156119815Smarcel	return ((sc->sc_rxget == sc->sc_rxput) ? 1 : 0);
157119815Smarcel}
158119815Smarcel
159119815Smarcelstatic __inline int
160119815Smarceluart_rx_full(struct uart_softc *sc)
161119815Smarcel{
162286059Smarius
163286059Smarius	return ((sc->sc_rxput + 1 < sc->sc_rxbufsz) ?
164286059Smarius	    (sc->sc_rxput + 1 == sc->sc_rxget) : (sc->sc_rxget == 0));
165119815Smarcel}
166119815Smarcel
167119815Smarcelstatic __inline int
168119815Smarceluart_rx_get(struct uart_softc *sc)
169119815Smarcel{
170119815Smarcel	int ptr, xc;
171119815Smarcel
172119815Smarcel	ptr = sc->sc_rxget;
173119815Smarcel	if (ptr == sc->sc_rxput)
174119815Smarcel		return (-1);
175119815Smarcel	xc = sc->sc_rxbuf[ptr++];
176119815Smarcel	sc->sc_rxget = (ptr < sc->sc_rxbufsz) ? ptr : 0;
177119815Smarcel	return (xc);
178119815Smarcel}
179119815Smarcel
180119815Smarcelstatic __inline int
181197721Smarceluart_rx_next(struct uart_softc *sc)
182197721Smarcel{
183197721Smarcel	int ptr;
184197721Smarcel
185197721Smarcel	ptr = sc->sc_rxget;
186197721Smarcel	if (ptr == sc->sc_rxput)
187197721Smarcel		return (-1);
188197721Smarcel	ptr += 1;
189197721Smarcel	sc->sc_rxget = (ptr < sc->sc_rxbufsz) ? ptr : 0;
190197721Smarcel	return (0);
191197721Smarcel}
192197721Smarcel
193197721Smarcelstatic __inline int
194197721Smarceluart_rx_peek(struct uart_softc *sc)
195197721Smarcel{
196197721Smarcel	int ptr;
197197721Smarcel
198197721Smarcel	ptr = sc->sc_rxget;
199197721Smarcel	return ((ptr == sc->sc_rxput) ? -1 : sc->sc_rxbuf[ptr]);
200197721Smarcel}
201197721Smarcel
202197721Smarcelstatic __inline int
203119815Smarceluart_rx_put(struct uart_softc *sc, int xc)
204119815Smarcel{
205119815Smarcel	int ptr;
206119815Smarcel
207119815Smarcel	ptr = (sc->sc_rxput + 1 < sc->sc_rxbufsz) ? sc->sc_rxput + 1 : 0;
208119815Smarcel	if (ptr == sc->sc_rxget)
209119815Smarcel		return (ENOSPC);
210119815Smarcel	sc->sc_rxbuf[sc->sc_rxput] = xc;
211119815Smarcel	sc->sc_rxput = ptr;
212119815Smarcel	return (0);
213119815Smarcel}
214119815Smarcel
215119815Smarcel#endif /* _DEV_UART_BUS_H_ */
216