summaryrefslogtreecommitdiff
path: root/sys/dev/pci/musyccvar.h
blob: 8325bedaa9558c9c2a6e8147e2bbef859aadd21f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
/*	$OpenBSD: musyccvar.h,v 1.8 2005/10/26 09:26:56 claudio Exp $ */

/*
 * Copyright (c) 2004,2005  Internet Business Solutions AG, Zurich, Switzerland
 * Written by: Claudio Jeker <jeker@accoom.net>
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */
#ifndef __MUSYCCVAR_H__
#define __MUSYCCVAR_H__

#include <sys/queue.h>

#define PPP_HEADER_LEN 4		/* should be globaly defined by sppp */

/* some defaults */
#define MUSYCC_NUMCHAN		32	/* 32 channels per group */
#define MUSYCC_NUMPORT		8	/* max 8 ports per controller */
#define MUSYCC_SREQNUM		16	/* pending SREQ */
#define MUSYCC_SREQMASK		(MUSYCC_SREQNUM - 1)
#define MUSYCC_SREQTIMEOUT	2

/* dma ring sizes */
#define MUSYCC_DMA_CNT		256
#define MUSYCC_DMA_MAPSIZE	(MUSYCC_DMA_CNT * sizeof(struct dma_desc))
#define MUSYCC_DMA_SIZE		32

struct musycc_softc;
struct ebus_softc;

/* DMA descriptor for data */
struct dma_desc {
	u_int32_t		 status;
	u_int32_t		 data;
	u_int32_t		 next;
	/* Software only */
	struct mbuf		*mbuf;
	struct dma_desc		*nextdesc;
	bus_dmamap_t		 map;
};

#define MUSYCC_INTLEN		512	/* 512 pending interrups is enough */
struct musycc_intdesc {
	u_int32_t		 md_intrq[MUSYCC_INTLEN];
};

struct musycc_dma_data {
	/*
	 * received dma ring. rx_prod points to the frist descriptors that
	 * is under musycc control (first empty).
	 */
	struct dma_desc		*rx_prod;
	int			 rx_cnt;

	struct dma_desc		*tx_pend;	/* finished pointer */
	struct dma_desc		*tx_cur;	/* current insertion pointer */
	int			 tx_cnt;	/* number of descriptors */
	int			 tx_use;	/* number of used descriptors */
	int			 tx_pkts;	/* number of packets in queue */
};

enum musycc_state {
	CHAN_FLOAT,	/* unconnected channel */
	CHAN_IDLE,
	CHAN_RUNNING,
	CHAN_FAULT,
	CHAN_TRANSIENT	/* dummy state to protect ongoing state changes */
};

enum musycc_event {
	EV_NULL,	/* null event, ignore */
	EV_ACTIVATE,	/* activate channel go to running state */
	EV_STOP,	/* stop dma engine */
	EV_IDLE,	/* free timeslots et al. and go to idle state */
	EV_WATCHDOG	/* watchdog event, stop dma engine */
};

/* group structure */
struct musycc_group {
	struct musycc_softc	*mg_hdlc;	/* main controller */
	struct musycc_grpdesc	*mg_group;	/* group descriptor */
	u_int8_t		 mg_gnum;	/* group number */
	u_int8_t		 mg_port;	/* port number */
	u_int8_t		 mg_loaded;	/* sreq(5) done? */
	u_int64_t		 mg_fifomask;	/* fifo allocation mask */

	struct channel_softc	*mg_channels[MUSYCC_NUMCHAN];
	struct musycc_dma_data	 mg_dma_d[MUSYCC_NUMCHAN];
	struct dma_desc		*mg_freelist;
	int			 mg_freecnt;

	struct {
		long			timeout;
		u_int32_t		sreq;
		enum musycc_event	event;
	}			 mg_sreq[MUSYCC_SREQNUM];
	int			 mg_sreqpend;
	int			 mg_sreqprod;

	struct dma_desc		*mg_dma_pool;
	bus_dma_tag_t		 mg_dmat;	/* bus dma tag */
	caddr_t			 mg_listkva;
	bus_dmamap_t		 mg_listmap;
	bus_dma_segment_t	 mg_listseg[1];
	int			 mg_listnseg;
	bus_dmamap_t		 mg_tx_sparemap;
	bus_dmamap_t		 mg_rx_sparemap;
};

/* attach arguments for framer devices */
struct musycc_attach_args {
	char				ma_product[64];
	bus_size_t			ma_base;
	bus_size_t			ma_size;
	u_int32_t			ma_type;
	u_int8_t			ma_gnum;
	u_int8_t			ma_port;
	u_int8_t			ma_flags;
	char				ma_slot;
};

/* generic ebus device handle */
struct ebus_dev {
	bus_size_t			base;
	bus_size_t			size;
	bus_space_tag_t			st;
	bus_space_handle_t		sh;
};

/* Softc for each HDLC channel config */
struct channel_softc {
	struct sppp		 cc_ppp;	/* sppp network attachement */
	struct ifnet		*cc_ifp;	/* pointer to the active ifp */
	struct musycc_group	*cc_group;
	struct device		*cc_parent;	/* parent framer */

	u_int32_t		 cc_tslots;	/* timeslot map */
	int			 cc_unit;
	enum musycc_state	 cc_state;	/* state machine info */
	u_int8_t		 cc_channel;	/* HDLC channel */
	u_int8_t		 cc_locked;
};

/* Softc for the HDLC Controller (function 0) */
struct musycc_softc {
	struct device		 mc_dev;	/* generic device structures */
	void			*mc_ih;		/* interrupt handler cookie */
	bus_space_tag_t		 mc_st;		/* bus space tag */
	bus_space_handle_t	 mc_sh;		/* bus space handle */
	bus_dma_tag_t		 mc_dmat;	/* bus dma tag */
	bus_size_t		 mc_iosize;	/* size of bus space */

	caddr_t			 mc_groupkva;	/* group configuration mem */
	bus_dmamap_t		 mc_cfgmap;
	bus_dma_segment_t	 mc_cfgseg[1];
	bus_dmamap_t		 mc_intrmap;
	bus_dma_segment_t	 mc_intrseg[1];
	int			 mc_cfgnseg;
	int			 mc_intrnseg;

	struct musycc_group	*mc_groups;	/* mc_ngroups groups */
	struct musycc_intdesc	*mc_intrd;
	u_int32_t		 mc_global_conf; /* global config descriptor */
	u_int32_t		 mc_intrqptr;	 /* interrupt queue pointer */
	int			 mc_ngroups;
	int			 mc_nports;

	struct musycc_softc	*mc_other;	/* the other EBUS/HDLC dev */
	bus_size_t		 mc_ledbase;
	u_int8_t		 mc_ledmask;
	u_int8_t		 mc_ledstate;	/* current state of the LEDs */
	int			 bus, device;	/* location of card */
	SLIST_ENTRY(musycc_softc) list;		/* list of all hdlc ctrls */
};

int	musycc_attach_common(struct musycc_softc *, u_int32_t, u_int32_t);
void	musycc_set_port(struct musycc_group *, int);
int	musycc_init_channel(struct channel_softc *, char);
void	musycc_stop_channel(struct channel_softc *);
void	musycc_free_channel(struct musycc_group *, int);
void	musycc_start(struct ifnet *);
void	musycc_watchdog(struct ifnet *);
void	musycc_tick(struct channel_softc *);

int	musycc_intr(void *);
int	ebus_intr(void *);

/* EBUS API */
int		ebus_attach_device(struct ebus_dev *, struct musycc_softc *,
		    bus_size_t, bus_size_t);
u_int8_t	ebus_read(struct ebus_dev *, bus_size_t);
void		ebus_write(struct ebus_dev *, bus_size_t, u_int8_t);
void		ebus_read_buf(struct ebus_dev *, bus_size_t, void *, size_t);
void		ebus_set_led(struct channel_softc *, int, u_int8_t);

#define MUSYCC_LED_GREEN	0x1
#define MUSYCC_LED_RED		0x2
#define MUSYCC_LED_MASK		0x3

/* channel API */
struct channel_softc	*musycc_channel_create(const char *, u_int8_t);
void		musycc_attach_sppp(struct channel_softc *,
		    int (*)(struct ifnet *, u_long, caddr_t));
int		musycc_channel_attach(struct musycc_softc *,
		    struct channel_softc *, struct device *, u_int8_t);
void		musycc_channel_detach(struct ifnet *);


#ifndef ACCOOM_DEBUG
#define ACCOOM_PRINTF(n, x)
#else
extern int accoom_debug;

#define ACCOOM_PRINTF(n, x)					\
	do {							\
		if (accoom_debug >= n)				\
			printf x;				\
	} while (0)
#endif

#endif