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
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
|
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2005 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#ifndef _SYS_RMC_COMM_H
#define _SYS_RMC_COMM_H
#pragma ident "%Z%%M% %I% %E% SMI"
#ifdef __cplusplus
extern "C" {
#endif
/*
* Hardware: serial chip register numbers
*/
#define SIO_RXD 0 /* read */
#define SIO_TXD 0 /* write */
#define SIO_IER 1
#define SIO_EIR 2 /* read */
#define SIO_FCR 2 /* write */
#define SIO_LCR 3
#define SIO_BSR 3 /* wierd */
#define SIO_MCR 4
#define SIO_LSR 5
#define SIO_MSR 6
#define SIO_SCR 7
#define SIO_LBGDL 0 /* bank 1 */
#define SIO_LBGDH 1 /* bank 1 */
/*
* Hardware: serial chip register bits
*/
#define SIO_IER_RXHDL_IE 0x01
#define SIO_IER_STD 0x00
#define SIO_FCR_FIFO_EN 0x01
#define SIO_FCR_RXSR 0x02
#define SIO_FCR_TXSR 0x04
#define SIO_FCR_RXFTH0 0x40
#define SIO_FCR_STD (SIO_FCR_RXFTH0|SIO_FCR_FIFO_EN)
#define SIO_LCR_WLS0 0x01
#define SIO_LCR_WLS1 0x02
#define SIO_LCR_PEN 0x08
#define SIO_LCR_EPS 0x10
#define SIO_LCR_BKSE 0x80
#define SIO_LCR_8BIT (SIO_LCR_WLS0|SIO_LCR_WLS1)
#define SIO_LCR_STD (SIO_LCR_8BIT)
#define SIO_BSR_BANK0 (SIO_LCR_STD)
#define SIO_BSR_BANK1 (SIO_LCR_BKSE|SIO_LCR_STD)
#define SIO_MCR_ISEN 0x08
#define SIO_MCR_STD (SIO_MCR_ISEN)
/* Line Status Register */
#define SIO_LSR_RXDA 0x01 /* data ready */
#define SIO_LSR_OVRRUN 0x02 /* overrun error */
#define SIO_LSR_PARERR 0x04 /* parity error */
#define SIO_LSR_FRMERR 0x08 /* framing error */
#define SIO_LSR_BRKDET 0x10 /* a break has arrived */
#define SIO_LSR_XHRE 0x20 /* tx hold reg is now empty */
#define SIO_LSR_XSRE 0x40 /* tx shift reg is now empty */
#define SIO_LSR_RFBE 0x80 /* rx FIFO Buffer error */
/*
* Min/max/default baud rates, and a macro to convert from a baud
* rate to the number (divisor) to put in the baud rate registers
*/
#define SIO_BAUD_MIN 50
#define SIO_BAUD_MAX 115200
#define SIO_BAUD_DEFAULT 115200
#define SIO_BAUD_TO_DIVISOR(b) (115200 / (b))
#define SIO_BAUD_DIVISOR_MIN 1
#define SIO_BAUD_DIVISOR_MAX 64
/*
* serial rx buffer size: set to maximum message size + 'bits'
* (protocol overhead)
*/
#define SIO_MAX_RXBUF_SIZE (DP_MAX_MSGLEN + 128)
/*
* protocol status struct
*/
typedef struct rmc_comm_serdev_state {
ddi_acc_handle_t sio_handle;
uint8_t *sio_regs;
ddi_softintr_t softid;
cyclic_id_t cycid;
/*
* Hardware mutex (initialised using <hw_iblk>),
* used to prevent retriggering the softint while
* it's still fetching data out of the chip FIFO.
*/
kmutex_t hw_mutex[1];
ddi_iblock_cookie_t hw_iblk;
boolean_t hw_int_enabled;
/*
* Flag to indicate that we've incurred a hardware fault on
* accesses to the SIO; once this is set, we fake all further
* accesses in order not to provoke additional bus errors.
*/
boolean_t sio_fault;
/*
* serial device receive buffer
*/
char serdev_rx_buf[SIO_MAX_RXBUF_SIZE];
uint16_t serdev_rx_count;
} rmc_comm_serdev_state_t;
/*
* This driver's soft-state structure
*/
struct rmc_comm_state {
/*
* Configuration data, set during attach
*/
dev_info_t *dip;
major_t majornum;
int instance;
int n_registrations;
boolean_t is_attached;
/*
* Parameters derived from .conf properties
*/
int baud;
uint32_t debug;
int baud_divisor_factor;
/*
* serial device status...
*/
rmc_comm_serdev_state_t sd_state;
/*
* protocol status struct
*/
rmc_comm_dp_state_t dp_state;
/*
* driver interface status struct
*/
rmc_comm_drvintf_state_t drvi_state;
};
/*
* Time periods, in nanoseconds
*/
#define RMC_COMM_ONE_SEC 1000000000LL
/*
* debugging
*/
#define DSER 0x01 /* serial device */
#define DPRO 0x02 /* protocol */
#define DAPI 0x04 /* API */
#define DPKT 0x08 /* packet handling routine */
#define DGEN 0x10 /* generic */
#define DDSC 0x20 /* datascope */
#define DMEM 0x40 /* memory alloc/release */
#ifdef DEBUG
#define DPRINTF(rcs, d, ARGLIST) { if (rcs->debug & d) cmn_err ARGLIST; }
#define DATASCOPE(rcs, c, b, l) { int i, j; char s[80]; \
s[0] = (c); \
s[1] = '\0'; \
for (i = 1; i < (l)+1; i++) { \
j = strlen(s); \
(void) sprintf(s+j, "%02x ", \
(uchar_t)b[i-1]); \
if (i%24 == 0) { \
DPRINTF(rcs, DDSC, \
(CE_CONT, "%s\n", s)); \
s[0] = (c); \
s[1] = '\0'; \
} \
} \
if (i%24 != 0) \
DPRINTF(rcs, DDSC, \
(CE_CONT, "%s\n", s)); \
}
#else
#define DPRINTF(rcs, d, ARGLIST)
#define DATASCOPE(rcs, c, b, l)
#endif /* DEBUG */
/*
* function prototypes
*/
int rmc_comm_serdev_init(struct rmc_comm_state *, dev_info_t *);
void rmc_comm_serdev_fini(struct rmc_comm_state *, dev_info_t *);
void rmc_comm_serdev_receive(struct rmc_comm_state *);
void rmc_comm_serdev_send(struct rmc_comm_state *, char *, int);
void rmc_comm_serdev_drain(struct rmc_comm_state *);
struct rmc_comm_state *rmc_comm_getstate(dev_info_t *, int, const char *);
int rmc_comm_register(void);
void rmc_comm_unregister(void);
void rmc_comm_dp_init(struct rmc_comm_state *);
void rmc_comm_dp_fini(struct rmc_comm_state *);
void rmc_comm_dp_drecv(struct rmc_comm_state *, uint8_t *, int);
void rmc_comm_dp_mrecv(struct rmc_comm_state *, uint8_t *);
int rmc_comm_dp_msend(struct rmc_comm_state *, dp_message_t *);
void rmc_comm_bp_msend(struct rmc_comm_state *, bp_msg_t *);
void rmc_comm_bp_srecsend(struct rmc_comm_state *, char *, int);
int rmc_comm_dp_ctlsend(struct rmc_comm_state *, uint8_t);
void rmc_comm_dp_mcleanup(struct rmc_comm_state *);
int rmc_comm_drvintf_init(struct rmc_comm_state *);
void rmc_comm_drvintf_fini(struct rmc_comm_state *);
#ifdef __cplusplus
}
#endif
#endif /* _SYS_RMC_COMM_H */
|