Linux Audio

Check our new training course

Loading...
Note: File does not exist in v6.9.4.
  1#ifndef _FIREWIRE_FWSERIAL_H
  2#define _FIREWIRE_FWSERIAL_H
  3
  4#include <linux/kernel.h>
  5#include <linux/tty.h>
  6#include <linux/tty_driver.h>
  7#include <linux/tty_flip.h>
  8#include <linux/list.h>
  9#include <linux/firewire.h>
 10#include <linux/firewire-constants.h>
 11#include <linux/spinlock.h>
 12#include <linux/rcupdate.h>
 13#include <linux/mutex.h>
 14#include <linux/serial.h>
 15#include <linux/serial_reg.h>
 16#include <linux/module.h>
 17#include <linux/seq_file.h>
 18#include <linux/debugfs.h>
 19
 20#include "dma_fifo.h"
 21
 22#ifdef FWTTY_PROFILING
 23#define DISTRIBUTION_MAX_SIZE     8192
 24#define DISTRIBUTION_MAX_INDEX    (ilog2(DISTRIBUTION_MAX_SIZE) + 1)
 25static inline void fwtty_profile_data(unsigned stat[], unsigned val)
 26{
 27	int n = (val) ? min(ilog2(val) + 1, DISTRIBUTION_MAX_INDEX) : 0;
 28	++stat[n];
 29}
 30#else
 31#define DISTRIBUTION_MAX_INDEX    0
 32#define fwtty_profile_data(st, n)
 33#endif
 34
 35/* Parameters for both VIRT_CABLE_PLUG & VIRT_CABLE_PLUG_RSP mgmt codes */
 36struct virt_plug_params {
 37	__be32  status_hi;
 38	__be32  status_lo;
 39	__be32	fifo_hi;
 40	__be32	fifo_lo;
 41	__be32	fifo_len;
 42};
 43
 44struct peer_work_params {
 45	union {
 46		struct virt_plug_params plug_req;
 47	};
 48};
 49
 50/**
 51 * fwtty_peer: structure representing local & remote unit devices
 52 * @unit: unit child device of fw_device node
 53 * @serial: back pointer to associated fw_serial aggregate
 54 * @guid: unique 64-bit guid for this unit device
 55 * @generation: most recent bus generation
 56 * @node_id: most recent node_id
 57 * @speed: link speed of peer (0 = S100, 2 = S400, ... 5 = S3200)
 58 * @mgmt_addr: bus addr region to write mgmt packets to
 59 * @status_addr: bus addr register to write line status to
 60 * @fifo_addr: bus addr region to write serial output to
 61 * @fifo_len:  max length for single write to fifo_addr
 62 * @list: link for insertion into fw_serial's peer_list
 63 * @rcu: for deferring peer reclamation
 64 * @lock: spinlock to synchonize changes to state & port fields
 65 * @work: only one work item can be queued at any one time
 66 *        Note: pending work is canceled prior to removal, so this
 67 *        peer is valid for at least the lifetime of the work function
 68 * @work_params: parameter block for work functions
 69 * @timer: timer for resetting peer state if remote request times out
 70 * @state: current state
 71 * @connect: work item for auto-connecting
 72 * @connect_retries: # of connections already attempted
 73 * @port: associated tty_port (usable if state == FWSC_ATTACHED)
 74 */
 75struct fwtty_peer {
 76	struct fw_unit		*unit;
 77	struct fw_serial	*serial;
 78	u64			guid;
 79	int			generation;
 80	int			node_id;
 81	unsigned		speed;
 82	int			max_payload;
 83	u64			mgmt_addr;
 84
 85	/* these are usable only if state == FWSC_ATTACHED */
 86	u64			status_addr;
 87	u64			fifo_addr;
 88	int			fifo_len;
 89
 90	struct list_head	list;
 91	struct rcu_head		rcu;
 92
 93	spinlock_t		lock;
 94	work_func_t		workfn;
 95	struct work_struct	work;
 96	struct peer_work_params work_params;
 97	struct timer_list	timer;
 98	int			state;
 99	struct delayed_work	connect;
100	int			connect_retries;
101
102	struct fwtty_port	*port;
103};
104
105#define to_peer(ptr, field)	(container_of(ptr, struct fwtty_peer, field))
106
107/* state values for fwtty_peer.state field */
108enum fwtty_peer_state {
109	FWPS_GONE,
110	FWPS_NOT_ATTACHED,
111	FWPS_ATTACHED,
112	FWPS_PLUG_PENDING,
113	FWPS_PLUG_RESPONDING,
114	FWPS_UNPLUG_PENDING,
115	FWPS_UNPLUG_RESPONDING,
116
117	FWPS_NO_MGMT_ADDR = -1,
118};
119
120#define CONNECT_RETRY_DELAY	HZ
121#define MAX_CONNECT_RETRIES	10
122
123/* must be holding peer lock for these state funclets */
124static inline void peer_set_state(struct fwtty_peer *peer, int new)
125{
126	peer->state = new;
127}
128
129static inline struct fwtty_port *peer_revert_state(struct fwtty_peer *peer)
130{
131	struct fwtty_port *port = peer->port;
132
133	peer->port = NULL;
134	peer_set_state(peer, FWPS_NOT_ATTACHED);
135	return port;
136}
137
138struct fwserial_mgmt_pkt {
139	struct {
140		__be16		len;
141		__be16		code;
142	} hdr;
143	union {
144		struct virt_plug_params plug_req;
145		struct virt_plug_params plug_rsp;
146	};
147} __packed;
148
149/* fwserial_mgmt_packet codes */
150#define FWSC_RSP_OK			0x0000
151#define FWSC_RSP_NACK			0x8000
152#define FWSC_CODE_MASK			0x0fff
153
154#define FWSC_VIRT_CABLE_PLUG		1
155#define FWSC_VIRT_CABLE_UNPLUG		2
156#define FWSC_VIRT_CABLE_PLUG_RSP	3
157#define FWSC_VIRT_CABLE_UNPLUG_RSP	4
158
159/* 1 min. plug timeout -- suitable for userland authorization */
160#define VIRT_CABLE_PLUG_TIMEOUT		(60 * HZ)
161
162struct stats {
163	unsigned	xchars;
164	unsigned	dropped;
165	unsigned	tx_stall;
166	unsigned	fifo_errs;
167	unsigned	sent;
168	unsigned	lost;
169	unsigned	throttled;
170	unsigned	reads[DISTRIBUTION_MAX_INDEX + 1];
171	unsigned	writes[DISTRIBUTION_MAX_INDEX + 1];
172	unsigned	txns[DISTRIBUTION_MAX_INDEX + 1];
173	unsigned	unthrottle[DISTRIBUTION_MAX_INDEX + 1];
174};
175
176struct fwconsole_ops {
177	void (*notify)(int code, void *data);
178	void (*stats)(struct stats *stats, void *data);
179	void (*proc_show)(struct seq_file *m, void *data);
180};
181
182/* codes for console ops notify */
183#define FWCON_NOTIFY_ATTACH		1
184#define FWCON_NOTIFY_DETACH		2
185
186/**
187 * fwtty_port: structure used to track/represent underlying tty_port
188 * @port: underlying tty_port
189 * @device: tty device
190 * @index: index into port_table for this particular port
191 *    note: minor = index + minor_start assigned by tty_alloc_driver()
192 * @serial: back pointer to the containing fw_serial
193 * @rx_handler: bus address handler for unique addr region used by remotes
194 *              to communicate with this port. Every port uses
195 *		fwtty_port_handler() for per port transactions.
196 * @fwcon_ops: ops for attached fw_console (if any)
197 * @con_data: private data for fw_console
198 * @wait_tx: waitqueue for sleeping until writer/drain completes tx
199 * @emit_breaks: delayed work responsible for generating breaks when the
200 *               break line status is active
201 * @cps : characters per second computed from the termios settings
202 * @break_last: timestamp in jiffies from last emit_breaks
203 * @hangup: work responsible for HUPing when carrier is dropped/lost
204 * @mstatus: loose virtualization of LSR/MSR
205 *         bits 15..0  correspond to TIOCM_* bits
206 *         bits 19..16 reserved for mctrl
207 *         bit 20      OOB_TX_THROTTLE
208 *	   bits 23..21 reserved
209 *         bits 31..24 correspond to UART_LSR_* bits
210 * @lock: spinlock for protecting concurrent access to fields below it
211 * @mctrl: loose virtualization of MCR
212 *         bits 15..0  correspond to TIOCM_* bits
213 *         bit 16      OOB_RX_THROTTLE
214 *         bits 19..17 reserved
215 *	   bits 31..20 reserved for mstatus
216 * @drain: delayed work scheduled to ensure that writes are flushed.
217 *         The work can race with the writer but concurrent sending is
218 *         prevented with the IN_TX flag. Scheduled under lock to
219 *         limit scheduling when fifo has just been drained.
220 * @tx_fifo: fifo used to store & block-up writes for dma to remote
221 * @max_payload: max bytes transmissable per dma (based on peer's max_payload)
222 * @status_mask: UART_LSR_* bitmask significant to rx (based on termios)
223 * @ignore_mask: UART_LSR_* bitmask of states to ignore (also based on termios)
224 * @break_ctl: if set, port is 'sending break' to remote
225 * @write_only: self-explanatory
226 * @overrun: previous rx was lost (partially or completely)
227 * @loopback: if set, port is in loopback mode
228 * @flags: atomic bit flags
229 *         bit 0: IN_TX - gate to allow only one cpu to send from the dma fifo
230 *                        at a time.
231 *         bit 1: STOP_TX - force tx to exit while sending
232 * @peer: rcu-pointer to associated fwtty_peer (if attached)
233 *        NULL if no peer attached
234 * @icount: predefined statistics reported by the TIOCGICOUNT ioctl
235 * @stats: additional statistics reported in /proc/tty/driver/firewire_serial
236 */
237struct fwtty_port {
238	struct tty_port		   port;
239	struct device		   *device;
240	unsigned		   index;
241	struct fw_serial	   *serial;
242	struct fw_address_handler  rx_handler;
243
244	struct fwconsole_ops	   *fwcon_ops;
245	void			   *con_data;
246
247	wait_queue_head_t	   wait_tx;
248	struct delayed_work	   emit_breaks;
249	unsigned		   cps;
250	unsigned long		   break_last;
251
252	struct work_struct	   hangup;
253
254	unsigned		   mstatus;
255
256	spinlock_t		   lock;
257	unsigned		   mctrl;
258	struct delayed_work	   drain;
259	struct dma_fifo		   tx_fifo;
260	int			   max_payload;
261	unsigned		   status_mask;
262	unsigned		   ignore_mask;
263	unsigned		   break_ctl:1,
264				   write_only:1,
265				   overrun:1,
266				   loopback:1;
267	unsigned long		   flags;
268
269	struct fwtty_peer __rcu	   *peer;
270
271	struct async_icount	   icount;
272	struct stats		   stats;
273};
274
275#define to_port(ptr, field)	(container_of(ptr, struct fwtty_port, field))
276
277/* bit #s for flags field */
278#define IN_TX                      0
279#define STOP_TX                    1
280
281/* bitmasks for special mctrl/mstatus bits */
282#define OOB_RX_THROTTLE   0x00010000
283#define MCTRL_RSRVD       0x000e0000
284#define OOB_TX_THROTTLE   0x00100000
285#define MSTATUS_RSRVD     0x00e00000
286
287#define MCTRL_MASK        (TIOCM_DTR | TIOCM_RTS | TIOCM_OUT1 | TIOCM_OUT2 | \
288			   TIOCM_LOOP | OOB_RX_THROTTLE | MCTRL_RSRVD)
289
290/* XXX even every 1/50th secs. may be unnecessarily accurate */
291/* delay in jiffies between brk emits */
292#define FREQ_BREAKS        (HZ / 50)
293
294/* Ports are allocated in blocks of num_ports for each fw_card */
295#define MAX_CARD_PORTS           CONFIG_FWTTY_MAX_CARD_PORTS
296#define MAX_TOTAL_PORTS          CONFIG_FWTTY_MAX_TOTAL_PORTS
297
298/* tuning parameters */
299#define FWTTY_PORT_TXFIFO_LEN	4096
300#define FWTTY_PORT_MAX_PEND_DMA    8    /* costs a cache line per pend */
301#define DRAIN_THRESHOLD         1024
302#define MAX_ASYNC_PAYLOAD       4096    /* ohci-defined limit          */
303#define WRITER_MINIMUM           128
304/* TODO: how to set watermark to AR context size? see fwtty_rx() */
305#define HIGH_WATERMARK         32768	/* AR context is 32K	       */
306
307/*
308 * Size of bus addr region above 4GB used per port as the recv addr
309 * - must be at least as big as the MAX_ASYNC_PAYLOAD
310 */
311#define FWTTY_PORT_RXFIFO_LEN	MAX_ASYNC_PAYLOAD
312
313/**
314 * fw_serial: aggregate used to associate tty ports with specific fw_card
315 * @card: fw_card associated with this fw_serial device (1:1 association)
316 * @kref: reference-counted multi-port management allows delayed destroy
317 * @self: local unit device as 'peer'. Not valid until local unit device
318 *         is enumerated.
319 * @list: link for insertion into fwserial_list
320 * @peer_list: list of local & remote unit devices attached to this card
321 * @ports: fixed array of tty_ports provided by this serial device
322 */
323struct fw_serial {
324	struct fw_card	  *card;
325	struct kref	  kref;
326
327	struct dentry	  *debugfs;
328	struct fwtty_peer *self;
329
330	struct list_head  list;
331	struct list_head  peer_list;
332
333	struct fwtty_port *ports[MAX_CARD_PORTS];
334};
335
336#define to_serial(ptr, field)	(container_of(ptr, struct fw_serial, field))
337
338#define TTY_DEV_NAME		    "fwtty"	/* ttyFW was taken           */
339static const char tty_dev_name[] =  TTY_DEV_NAME;
340static const char loop_dev_name[] = "fwloop";
341
342extern struct tty_driver *fwtty_driver;
343
344struct fwtty_port *fwtty_port_get(unsigned index);
345void fwtty_port_put(struct fwtty_port *port);
346
347static inline void fwtty_bind_console(struct fwtty_port *port,
348				      struct fwconsole_ops *fwcon_ops,
349				      void *data)
350{
351	port->con_data = data;
352	port->fwcon_ops = fwcon_ops;
353}
354
355/*
356 * Returns the max send async payload size in bytes based on the unit device
357 * link speed. Self-limiting asynchronous bandwidth (via reducing the payload)
358 * is not necessary and does not work, because
359 *   1) asynchronous traffic will absorb all available bandwidth (less that
360 *	being used for isochronous traffic)
361 *   2) isochronous arbitration always wins.
362 */
363static inline int link_speed_to_max_payload(unsigned speed)
364{
365	/* Max async payload is 4096 - see IEEE 1394-2008 tables 6-4, 16-18 */
366	return min(512 << speed, 4096);
367}
368
369#endif /* _FIREWIRE_FWSERIAL_H */