BPicture: Fix archive constructor.
[haiku.git] / src / add-ons / kernel / debugger / laplinkll / laplinkll.cpp
blob3905b1d122dcc91e3e9c9a865a5cd51672818cba
1 /*
2 * Copyright 2008, Haiku, Inc. All Rights Reserved.
3 * Distributed under the terms of the MIT License.
5 * Authors:
6 * François Revol, revol@free.fr
7 *
8 * Copyright 2005, François Revol.
9 */
12 Description: Implements a tty on top of the parallel port,
13 using PLIP-like byte-by-byte protocol.
14 Low level stuff.
18 #include <Drivers.h>
19 //#include <parallel_driver.h>
20 #include <KernelExport.h>
21 #include <driver_settings.h>
22 #include <OS.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <sys/stat.h>
26 #include <sys/types.h>
27 #include <unistd.h>
28 #include <ISA.h>
30 //XXX: move to Jamfile when adding driver
31 #define _BUILDING_kernel 1
33 #if _BUILDING_kernel
34 #include <debug.h>
35 #endif
37 #include "laplinkll.h"
39 enum {
40 st_sync = 0, // syncing...
41 st_lsb,
42 st_msb,
43 st_error
46 static isa_module_info *sISAModule;
48 #pragma mark // raw access
50 static inline uint8 read_status(uint32 port)
52 uint8 val;
53 val = sISAModule->read_io_8(port+1);
54 return val;
57 static inline void write_control(uint32 port, uint8 val)
59 sISAModule->write_io_8(port+2, val);
62 static inline void write_data(uint32 port, uint8 val)
64 sISAModule->write_io_8(port, val);
67 #pragma mark // framing
69 status_t ll_send_sof(laplink_state *st)
71 uint8 v;
72 int tries = LPTSOFTRIES;
73 if (st->rstate != st_sync || st->wstate != st_sync)
74 return B_TIMED_OUT;
75 // check for idle bus
76 if ((read_status(st->port) & 0xf8) != 0x80)
77 return B_TIMED_OUT;
78 // raise ACK
79 write_data(st->port, 0x08);
80 do {
81 spin(LPTSPIN);
82 v = read_status(st->port);
83 if (st->rstate != st_sync)
84 return B_TIMED_OUT;
85 if (tries-- == 0)
86 return B_TIMED_OUT;
87 } while (!(v & 0x08));
88 st->wstate = st_lsb;
89 return B_OK;
92 status_t ll_check_sof(laplink_state *st)
94 uint8 v;
95 if (st->rstate != st_sync || st->wstate != st_sync)
96 return EINTR;
97 v = read_status(st->port);
98 if ((v & 0xf8) != 0xc0)
99 return EINTR;
100 return B_OK;
103 status_t ll_ack_sof(laplink_state *st)
105 write_data(st->port, 0x01); // ack the sof
106 st->rstate = st_lsb;
107 return B_OK;
110 status_t ll_send_eof(laplink_state *st)
113 if (st->rstate != st_sync || st->wstate != st_sync)
114 return B_TIMED_OUT;
116 st->rstate = st_sync;
117 st->wstate = st_sync;
118 write_data(st->port, 0x00);
119 return B_OK;
122 #pragma mark // nibbles
124 status_t ll_send_lnibble(laplink_state *st, uint8 v)
126 int tries = LPTNIBTRIES;
127 uint8 s;
128 if (st->rstate != st_sync)
129 goto err;
130 if (st->wstate != st_lsb)
131 goto err;
132 write_data(st->port, v & 0x0f);
133 spin(10);
134 write_data(st->port, (v & 0x0f) | 0x10);
135 // wait for ack
136 do {
137 s = read_status(st->port);
138 if (tries-- == 0)
139 goto err;
140 spin(LPTSPIN);
141 } while (s & 0x80);
142 st->wstate = st_msb;
143 return B_OK;
144 err:
145 st->wstate = st_sync;
146 return B_TIMED_OUT;
149 status_t ll_send_mnibble(laplink_state *st, uint8 v)
151 int tries = LPTNIBTRIES;
152 uint8 s;
153 if (st->rstate != st_sync)
154 goto err;
155 if (st->wstate != st_msb)
156 goto err;
157 write_data(st->port, (v >> 4) | 0x10);
158 spin(10);
159 write_data(st->port, (v >> 4));
160 // wait for ack
161 do {
162 s = read_status(st->port);
163 if (tries-- == 0)
164 goto err;
165 spin(LPTSPIN);
166 } while (!(s & 0x80));
167 st->wstate = st_lsb;//st_sync;
168 return B_OK;
169 err:
170 st->wstate = st_sync;
171 return B_TIMED_OUT;
174 status_t ll_wait_lnibble(laplink_state *st, uint8 *v)
176 int tries = LPTNIBTRIES;
177 uint8 s;
178 // wait for data
179 do {
180 s = read_status(st->port);
181 if (tries-- == 0)
182 goto err;
183 spin(LPTSPIN);
184 } while ((s & 0x80) || (s != read_status(st->port)));
185 // get the nibble
186 *v = (s >> 3) & 0x0f;
187 st->rstate = st_msb;
188 // tell we got that one
189 write_data(st->port, 0x10);
190 return B_OK;
191 err:
192 st->rstate = st_sync;
193 return B_TIMED_OUT;
196 status_t ll_wait_mnibble(laplink_state *st, uint8 *v)
198 int tries = LPTNIBTRIES;
199 uint8 s;
200 // wait for data
201 do {
202 s = read_status(st->port);
203 if (tries-- == 0)
204 goto err;
205 spin(LPTSPIN);
206 } while (!(s & 0x80) || (s != read_status(st->port)));
207 // get the nibble
208 *v |= (s << (4-3)) & 0xf0;
209 st->rstate = st_sync;
210 // tell we got that one
211 write_data(st->port, 0x00);
212 return B_OK;
213 err:
214 st->rstate = st_sync;
215 return B_TIMED_OUT;
218 #pragma mark // byte mode
220 status_t ll_send_byte(laplink_state *st, uint8 v)
222 status_t err;
223 err = ll_send_sof(st);
224 if (!err)
225 err = ll_send_lnibble(st, v);
226 if (!err)
227 err = ll_send_mnibble(st, v);
228 if (!err)
229 err = ll_send_eof(st);
230 return err;
233 status_t ll_check_byte(laplink_state *st, uint8 *v)
235 status_t err;
236 *v = 0;
237 err = ll_check_sof(st);
238 if (err)
239 return err;
240 err = ll_ack_sof(st);
241 if (!err)
242 err = ll_wait_lnibble(st, v);
243 if (!err)
244 err = ll_wait_mnibble(st, v);
245 if (!err)
246 err = ll_send_eof(st);
247 return err;
250 status_t ll_wait_byte(laplink_state *st, uint8 *v)
252 status_t err;
253 do {
254 spin(LPTSPIN);
255 err = ll_check_byte(st, v);
256 } while (err < B_OK);// } while (err == B_TIMED_OUT);
257 return err;
260 #pragma mark // frame mode
262 // unframed
263 static inline status_t ll_send_byte_uf(laplink_state *st, uint8 v)
265 status_t err;
266 err = ll_send_lnibble(st, v);
267 if (!err)
268 err = ll_send_mnibble(st, v);
269 return err;
272 status_t ll_get_byte_uf(laplink_state *st, uint8 *v)
274 status_t err;
275 *v = 0;
276 err = ll_wait_lnibble(st, v);
277 if (!err)
278 err = ll_wait_mnibble(st, v);
279 return err;
282 status_t ll_send_frame(laplink_state *st, const uint8 *buff, size_t *len)
284 status_t err;
285 uint16 pktlen = *len;
286 uint8 cksum = 0;
287 *len = 0;
288 err = ll_send_sof(st);
289 if (err)
290 return err;
291 err = ll_send_byte_uf(st, pktlen & 0xff);
292 if (err)
293 goto err;
294 err = ll_send_byte_uf(st, pktlen >> 8);
295 if (err)
296 goto err;
297 for (*len = 0; *len < pktlen; (*len)++) {
298 err = ll_send_byte_uf(st, buff[*len]);
299 if (err)
300 goto err;
301 cksum += buff[*len];
303 err = ll_send_byte_uf(st, cksum);
304 if (err)
305 goto err;
307 /*err =*/ ll_send_eof(st);
308 err:
310 if (err) { // back to idle
311 *len = 0;
312 ll_send_eof(st);
314 return err;
317 status_t ll_check_frame(laplink_state *st, uint8 *buff, size_t *len)
319 status_t err;
320 uint16 pktlen = 0;
321 uint16 wanted;
322 uint8 cksum = 0;
323 uint8 byte;
324 int i;
325 err = ll_check_sof(st);
326 if (err)
327 goto err;
328 err = ll_ack_sof(st);
329 if (err)
330 goto err;
331 // pktlen
332 err = ll_get_byte_uf(st, &byte);
333 if (err)
334 goto err;
335 pktlen = byte;
336 err = ll_get_byte_uf(st, &byte);
337 if (err)
338 goto err;
339 pktlen |= byte << 8;
340 cksum = 0;
341 /*if (pktlen > *len) {
342 dprintf("laplink: check_frame: packet truncated from %d to %d\n", pktlen, *len);
344 wanted = MIN(pktlen, *len);
345 for (*len = 0; (*len < pktlen); (*len)++) {
346 err = ll_get_byte_uf(st, &byte);
347 if (err)
348 goto err;
349 if (*len < wanted)
350 buff[*len] = byte;
351 cksum += byte;
353 err = ll_get_byte_uf(st, &byte);
354 if (err)
355 goto err;
357 if (cksum != byte) {
358 dprintf("laplink: check_frame: wrong cksum\n");
360 err:
361 ll_send_eof(st);
362 return err;
365 status_t ll_wait_frame(laplink_state *st, uint8 *buff, size_t *len)
367 status_t err;
368 do {
369 spin(LPTSPIN);
370 err = ll_check_frame(st, buff, len);
371 } while (err < B_OK);// } while (err == B_TIMED_OUT);
372 return err;
375 #pragma mark // kdebug io handler
377 #if _BUILDING_kernel
378 #define BUFFSZ 256
380 static laplink_state llst;
381 static char laplink_in_buf[BUFFSZ];
382 static char *laplink_in_ptr;
383 static size_t laplink_in_avail;
384 static char laplink_out_buf[BUFFSZ];
386 //XXX: cleanup
387 static status_t debug_init_laplink(void *kernel_settings)
389 (void)kernel_settings;
390 llst.port = LPTBASE;
391 llst.rstate = st_sync;
392 llst.wstate = st_sync;
393 laplink_in_ptr = laplink_in_buf;
394 laplink_in_avail = 0;
395 return B_OK;
398 static int debug_write_laplink(int f, const char *buf, int count)
400 status_t err;
401 size_t len;
402 int tries;
403 int i, prev = 0;
405 // fix up CR LF issues... to a local buffer (which will get truncated)
406 if (count > 1) {
407 for (i = 0; (i < BUFFSZ-1) && count; i++, buf++, count--) {
408 if ((*buf == '\n') && (prev != '\r'))
409 laplink_out_buf[i++] = '\r';
410 laplink_out_buf[i] = *buf;
411 prev = *buf;
413 count = i;
414 buf = laplink_out_buf;
417 tries = 5;
418 do {
419 len = count;
420 err = ll_send_frame(&llst, (const uint8 *)buf, &len);
421 } while (err && tries--);
422 if (err)
423 return 0;
424 return len;
427 static int debug_read_laplink(void)
429 status_t err = B_OK;
430 while (laplink_in_avail < 1) {
431 laplink_in_avail = BUFFSZ;
432 laplink_in_ptr = laplink_in_buf;
433 err = ll_wait_frame(&llst, (uint8 *)laplink_in_buf, &laplink_in_avail);
434 if (err)
435 laplink_in_avail = 0;
437 laplink_in_avail--;
438 return *laplink_in_ptr++;
442 static int
443 debugger_puts(const char *s, int32 length)
445 return debug_write_laplink(0, s, (int)length);
449 static status_t
450 std_ops(int32 op, ...)
452 void *handle;
453 bool load = true;//false;
455 switch (op) {
456 case B_MODULE_INIT:
457 handle = load_driver_settings("kernel");
458 if (handle) {
459 load = get_driver_boolean_parameter(handle,
460 "laplinkll_debug_output", load, true);
461 unload_driver_settings(handle);
463 if (load) {
464 if (get_module(B_ISA_MODULE_NAME, (module_info **)&sISAModule) < B_OK)
465 return B_ERROR;
466 debug_init_laplink(NULL);
468 return load ? B_OK : B_ERROR;
469 case B_MODULE_UNINIT:
470 put_module(B_ISA_MODULE_NAME);
471 return B_OK;
473 return B_BAD_VALUE;
477 static struct debugger_module_info sModuleInfo = {
479 "debugger/laplinkll/v1",
481 &std_ops
483 NULL,
484 NULL,
485 debugger_puts,
486 NULL
489 module_info *modules[] = {
490 (module_info *)&sModuleInfo,
491 NULL
495 #endif