1 /* pro_2661ptr.c: serial port controller (used by ptr & ptr)
2
3 Copyright (c) 1997-2003, Tarik Isani (xhomer@isani.org)
4
5 This file is part of Xhomer.
6
7 Xhomer is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License version 2
9 as published by the Free Software Foundation.
10
11 Xhomer is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with Xhomer; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21
22 /* TBD:
23 -implement reading of line status
24 break
25 parity error
26 -update line parameters only if something changed
27 -overrun is not implemented. Is it needed for loopback?
28 -do global mask for odd byte writes
29 */
30
31 #ifdef PRO
32 #include "pdp11_defs.h"
33
34 /* XXX make generic */
35
36 LOCAL int pro_2661ptr_data;
37 LOCAL int pro_2661ptr_wdata;
38 LOCAL int pro_2661ptr_stat;
39 LOCAL int pro_2661ptr_mr1;
40 LOCAL int pro_2661ptr_mr2;
41 LOCAL int pro_2661ptr_cmd;
42
43 LOCAL int pro_2661ptr_mode_ptr; /* Indicates which mode register is to be accessed */
44
45 struct serctrl pro_2661ptr_ctrl; /* Stores line control parameters */
46
47
pro_2661ptr_ctrl_get()48 LOCAL void pro_2661ptr_ctrl_get ()
49 {
50 pro_ptr->ctrl_get(PRO_SER_PTR, &pro_2661ptr_ctrl);
51
52 pro_2661ptr_stat = (pro_2661ptr_stat & ~PRO_2661_DSR);
53
54 if (pro_2661ptr_ctrl.dsr == 1)
55 pro_2661ptr_stat |= PRO_2661_DSR;
56 }
57
58
pro_2661ptr_ctrl_put()59 LOCAL void pro_2661ptr_ctrl_put ()
60 {
61 pro_2661ptr_ctrl.cs = (pro_2661ptr_mr1 & PRO_2661_CL) >> 2;
62 pro_2661ptr_ctrl.stop = (pro_2661ptr_mr1 & PRO_2661_SBL) >> 6;
63 pro_2661ptr_ctrl.parity = (pro_2661ptr_mr1 & PRO_2661_PT) >> 5;
64 pro_2661ptr_ctrl.penable = (pro_2661ptr_mr1 & PRO_2661_PC) >> 4;
65 pro_2661ptr_ctrl.ibaud = pro_2661ptr_mr2 & PRO_2661_BAUD;
66 pro_2661ptr_ctrl.obaud = pro_2661ptr_mr2 & PRO_2661_BAUD;
67 pro_2661ptr_ctrl.dtr = (pro_2661ptr_cmd & PRO_2661_DTR) >> 1;
68 pro_2661ptr_ctrl.obrk = (pro_2661ptr_cmd & PRO_2661_FB) >> 3;
69
70 /* Hardwire rts */
71
72 pro_2661ptr_ctrl.rts = 1;
73
74 /* XXX Update serial line parameters only if they changed */
75
76 pro_ptr->ctrl_put(PRO_SER_PTR, &pro_2661ptr_ctrl);
77 }
78
79
80 /* Polling event queue scheduler */
81
pro_2661ptr_poll_sched()82 LOCAL void pro_2661ptr_poll_sched ()
83 {
84 pro_eq_sched(PRO_EVENT_PTR_POLL, PRO_EQ_PTR_POLL);
85 }
86
87
88 /* Polling event queue handler */
89
pro_2661ptr_poll_eq()90 void pro_2661ptr_poll_eq ()
91 {
92 int schar;
93
94 /* Only poll if receiver done is cleared, to avoid overrun */
95
96 /* Check if receiver is enabled */
97
98 if (((pro_2661ptr_cmd & PRO_2661_OM) == PRO_2661_NORMAL)
99 && ((pro_2661ptr_cmd & PRO_2661_RXEN) != 0)
100 && ((pro_2661ptr_stat & PRO_2661_RD) == 0))
101 {
102 schar = pro_ptr->get(PRO_SER_PTR);
103
104 if (schar != PRO_NOCHAR)
105 {
106 /* Copy received character to input buffer */
107
108 pro_2661ptr_data = schar;
109
110 /* Set receiver done bit */
111
112 pro_2661ptr_stat = pro_2661ptr_stat | PRO_2661_RD;
113
114 /* Set receiver interrupt event */
115
116 pro_int_set(PRO_INT_PTR_RCV);
117 }
118 }
119
120 /* Schedule next polling event */
121
122 pro_2661ptr_poll_sched();
123 }
124
125
126 /* Write data event handler */
127
pro_2661ptr_eq()128 void pro_2661ptr_eq ()
129 {
130 /* Queue another write data event if in NORMAL mode
131 and character send failed. Otherwise, complete write
132 data event */
133
134 if ((pro_2661ptr_cmd & PRO_2661_OM) == PRO_2661_NORMAL)
135 {
136 if (pro_ptr->put(PRO_SER_PTR, pro_2661ptr_wdata) == PRO_FAIL)
137 {
138 pro_eq_sched(PRO_EVENT_PTR, PRO_EQ_PTR_RETRY);
139 return;
140 }
141 }
142
143 /* Set transmitter ready bit */
144
145 pro_2661ptr_stat = pro_2661ptr_stat | PRO_2661_TR;
146
147 /* Set transmitter intterrupt */
148
149 pro_int_set(PRO_INT_PTR_XMIT);
150
151 /* Set receive int+rd if local loopback is enabled */
152
153 /* XXX is a delay between xmit and rcv interrupts needed? */
154
155 /* XXX does this cause an int+rd if RXEN is disabled? */
156
157 /* XXX various bits needed for loopback are not checked */
158
159 if ((pro_2661ptr_cmd & PRO_2661_OM) == PRO_2661_LOOPBACK)
160 {
161 /* Loop write data back */
162
163 pro_2661ptr_data = pro_2661ptr_wdata;
164
165 /* Set receiver done bit */
166
167 pro_2661ptr_stat = pro_2661ptr_stat | PRO_2661_RD;
168
169 /* Set receiver interrupt */
170
171 pro_int_set(PRO_INT_PTR_RCV);
172 }
173 }
174
175
176 /* 2661 serial controller registers */
177
pro_2661ptr_rd(int pa)178 int pro_2661ptr_rd (int pa)
179 {
180 int data;
181
182 switch (pa & 06)
183 {
184 case 00:
185 data = pro_2661ptr_data;
186
187 pro_2661ptr_stat = pro_2661ptr_stat & ~PRO_2661_RD; /* clear rec. done bit */
188
189 break;
190
191 case 02:
192 /* Get serial line status first */
193
194 pro_2661ptr_ctrl_get();
195 data = pro_2661ptr_stat;
196 break;
197
198 case 04:
199 if (pro_2661ptr_mode_ptr == 0)
200 {
201 data = pro_2661ptr_mr1;
202 pro_2661ptr_mode_ptr = 1;
203 }
204 else
205 {
206 data = pro_2661ptr_mr2;
207 pro_2661ptr_mode_ptr = 0;
208 }
209 break;
210
211 case 06:
212 data = pro_2661ptr_cmd;
213
214 if (pro_2661ptr_mode_ptr == 0)
215 pro_2661ptr_mode_ptr = 1;
216 else
217 pro_2661ptr_mode_ptr = 0;
218
219 break;
220
221 default:
222 data = 0;
223 break;
224 }
225
226 return data;
227 }
228
pro_2661ptr_wr(int data,int pa,int access)229 void pro_2661ptr_wr (int data, int pa, int access)
230 {
231 switch (pa & 06)
232 {
233 case 00:
234 if ((pro_2661ptr_cmd & PRO_2661_TXEN) != 0)
235 {
236 /* Store write data value for use in event handler */
237
238 WRITE_WB(pro_2661ptr_wdata, PRO_2661_DATA_W, access);
239
240 /* Clear transmitter ready bit */
241
242 pro_2661ptr_stat = pro_2661ptr_stat & ~PRO_2661_TR;
243
244 /* Queue write data event */
245
246 pro_eq_sched(PRO_EVENT_PTR, PRO_EQ_PTR);
247 }
248
249 break;
250
251 case 04:
252 if (pro_2661ptr_mode_ptr == 0)
253 {
254 WRITE_WB(pro_2661ptr_mr1, PRO_2661_MR1_W, access);
255 pro_2661ptr_mode_ptr = 1;
256 }
257 else
258 {
259 WRITE_WB(pro_2661ptr_mr2, PRO_2661_MR2_W, access);
260 pro_2661ptr_mode_ptr = 0;
261 }
262
263 /* Update line parameters */
264
265 pro_2661ptr_ctrl_put();
266 break;
267
268 case 06:
269 /* XXX Reset error unimplemented */
270
271 WRITE_WB(pro_2661ptr_cmd, PRO_2661_CMD_W, access);
272
273 /* Clear receiver done if receiver is disabled */
274
275 if ((pro_2661ptr_cmd & PRO_2661_RXEN) == 0)
276 pro_2661ptr_stat = pro_2661ptr_stat & ~PRO_2661_RD;
277
278 /* Clear transmitter ready if auto-echo or remote loopback modes */
279
280 if (((pro_2661ptr_cmd & PRO_2661_OM0) == 1)
281 || ((pro_2661ptr_cmd & PRO_2661_TXEN) == 0))
282 pro_2661ptr_stat = pro_2661ptr_stat & ~PRO_2661_TR;
283 else
284 pro_2661ptr_stat = pro_2661ptr_stat | PRO_2661_TR;
285
286 /* Update line parameters */
287
288 pro_2661ptr_ctrl_put();
289 break;
290
291 default:
292 break;
293 }
294 }
295
296
pro_2661ptr_reset()297 void pro_2661ptr_reset ()
298 {
299 pro_2661ptr_data = 0000;
300 pro_2661ptr_stat = 0100 | PRO_2661_TR; /* transmit ready, cleared for auto-echo or rem. loopback */
301 pro_2661ptr_mr1 = 0000;
302 pro_2661ptr_mr2 = 0000;
303 pro_2661ptr_cmd = 0000;
304
305 pro_2661ptr_mode_ptr = 0;
306
307 /* Initialize serial line parameters */
308
309 memset(&pro_2661ptr_ctrl, 0, sizeof(pro_2661ptr_ctrl));
310
311 /* Schedule 2661 polling event */
312
313 pro_2661ptr_poll_sched();
314 }
315
pro_2661ptr_open()316 void pro_2661ptr_open ()
317 {
318 /* Open serial port */
319
320 pro_ptr->reset(PRO_SER_PTR, pro_ptr_port);
321
322 /* Set and get serial line parameters */
323
324 pro_2661ptr_ctrl_put();
325 pro_2661ptr_ctrl_get();
326 }
327 #endif
328