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.9 2006/02/06 17:29:11 jmc 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 interrupts 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
|