2 * Copyright 2008, Haiku, Inc. All Rights Reserved.
3 * Distributed under the terms of the MIT License.
6 * François Revol, revol@free.fr
8 * Copyright 2005, François Revol.
12 Description: Implements a tty on top of the parallel port,
13 using PLIP-like byte-by-byte protocol.
19 //#include <parallel_driver.h>
20 #include <KernelExport.h>
21 #include <driver_settings.h>
26 #include <sys/types.h>
30 //XXX: move to Jamfile when adding driver
31 #define _BUILDING_kernel 1
37 #include "laplinkll.h"
40 st_sync
= 0, // syncing...
46 static isa_module_info
*sISAModule
;
48 #pragma mark // raw access
50 static inline uint8
read_status(uint32 port
)
53 val
= sISAModule
->read_io_8(port
+1);
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
)
72 int tries
= LPTSOFTRIES
;
73 if (st
->rstate
!= st_sync
|| st
->wstate
!= st_sync
)
76 if ((read_status(st
->port
) & 0xf8) != 0x80)
79 write_data(st
->port
, 0x08);
82 v
= read_status(st
->port
);
83 if (st
->rstate
!= st_sync
)
87 } while (!(v
& 0x08));
92 status_t
ll_check_sof(laplink_state
*st
)
95 if (st
->rstate
!= st_sync
|| st
->wstate
!= st_sync
)
97 v
= read_status(st
->port
);
98 if ((v
& 0xf8) != 0xc0)
103 status_t
ll_ack_sof(laplink_state
*st
)
105 write_data(st
->port
, 0x01); // ack the sof
110 status_t
ll_send_eof(laplink_state
*st
)
113 if (st->rstate != st_sync || st->wstate != st_sync)
116 st
->rstate
= st_sync
;
117 st
->wstate
= st_sync
;
118 write_data(st
->port
, 0x00);
122 #pragma mark // nibbles
124 status_t
ll_send_lnibble(laplink_state
*st
, uint8 v
)
126 int tries
= LPTNIBTRIES
;
128 if (st
->rstate
!= st_sync
)
130 if (st
->wstate
!= st_lsb
)
132 write_data(st
->port
, v
& 0x0f);
134 write_data(st
->port
, (v
& 0x0f) | 0x10);
137 s
= read_status(st
->port
);
145 st
->wstate
= st_sync
;
149 status_t
ll_send_mnibble(laplink_state
*st
, uint8 v
)
151 int tries
= LPTNIBTRIES
;
153 if (st
->rstate
!= st_sync
)
155 if (st
->wstate
!= st_msb
)
157 write_data(st
->port
, (v
>> 4) | 0x10);
159 write_data(st
->port
, (v
>> 4));
162 s
= read_status(st
->port
);
166 } while (!(s
& 0x80));
167 st
->wstate
= st_lsb
;//st_sync;
170 st
->wstate
= st_sync
;
174 status_t
ll_wait_lnibble(laplink_state
*st
, uint8
*v
)
176 int tries
= LPTNIBTRIES
;
180 s
= read_status(st
->port
);
184 } while ((s
& 0x80) || (s
!= read_status(st
->port
)));
186 *v
= (s
>> 3) & 0x0f;
188 // tell we got that one
189 write_data(st
->port
, 0x10);
192 st
->rstate
= st_sync
;
196 status_t
ll_wait_mnibble(laplink_state
*st
, uint8
*v
)
198 int tries
= LPTNIBTRIES
;
202 s
= read_status(st
->port
);
206 } while (!(s
& 0x80) || (s
!= read_status(st
->port
)));
208 *v
|= (s
<< (4-3)) & 0xf0;
209 st
->rstate
= st_sync
;
210 // tell we got that one
211 write_data(st
->port
, 0x00);
214 st
->rstate
= st_sync
;
218 #pragma mark // byte mode
220 status_t
ll_send_byte(laplink_state
*st
, uint8 v
)
223 err
= ll_send_sof(st
);
225 err
= ll_send_lnibble(st
, v
);
227 err
= ll_send_mnibble(st
, v
);
229 err
= ll_send_eof(st
);
233 status_t
ll_check_byte(laplink_state
*st
, uint8
*v
)
237 err
= ll_check_sof(st
);
240 err
= ll_ack_sof(st
);
242 err
= ll_wait_lnibble(st
, v
);
244 err
= ll_wait_mnibble(st
, v
);
246 err
= ll_send_eof(st
);
250 status_t
ll_wait_byte(laplink_state
*st
, uint8
*v
)
255 err
= ll_check_byte(st
, v
);
256 } while (err
< B_OK
);// } while (err == B_TIMED_OUT);
260 #pragma mark // frame mode
263 static inline status_t
ll_send_byte_uf(laplink_state
*st
, uint8 v
)
266 err
= ll_send_lnibble(st
, v
);
268 err
= ll_send_mnibble(st
, v
);
272 status_t
ll_get_byte_uf(laplink_state
*st
, uint8
*v
)
276 err
= ll_wait_lnibble(st
, v
);
278 err
= ll_wait_mnibble(st
, v
);
282 status_t
ll_send_frame(laplink_state
*st
, const uint8
*buff
, size_t *len
)
285 uint16 pktlen
= *len
;
288 err
= ll_send_sof(st
);
291 err
= ll_send_byte_uf(st
, pktlen
& 0xff);
294 err
= ll_send_byte_uf(st
, pktlen
>> 8);
297 for (*len
= 0; *len
< pktlen
; (*len
)++) {
298 err
= ll_send_byte_uf(st
, buff
[*len
]);
303 err
= ll_send_byte_uf(st
, cksum
);
307 /*err =*/ ll_send_eof(st
);
310 if (err
) { // back to idle
317 status_t
ll_check_frame(laplink_state
*st
, uint8
*buff
, size_t *len
)
325 err
= ll_check_sof(st
);
328 err
= ll_ack_sof(st
);
332 err
= ll_get_byte_uf(st
, &byte
);
336 err
= ll_get_byte_uf(st
, &byte
);
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
);
353 err
= ll_get_byte_uf(st
, &byte
);
358 dprintf("laplink: check_frame: wrong cksum\n");
365 status_t
ll_wait_frame(laplink_state
*st
, uint8
*buff
, size_t *len
)
370 err
= ll_check_frame(st
, buff
, len
);
371 } while (err
< B_OK
);// } while (err == B_TIMED_OUT);
375 #pragma mark // kdebug io handler
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
];
387 static status_t
debug_init_laplink(void *kernel_settings
)
389 (void)kernel_settings
;
391 llst
.rstate
= st_sync
;
392 llst
.wstate
= st_sync
;
393 laplink_in_ptr
= laplink_in_buf
;
394 laplink_in_avail
= 0;
398 static int debug_write_laplink(int f
, const char *buf
, int count
)
405 // fix up CR LF issues... to a local buffer (which will get truncated)
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
;
414 buf
= laplink_out_buf
;
420 err
= ll_send_frame(&llst
, (const uint8
*)buf
, &len
);
421 } while (err
&& tries
--);
427 static int debug_read_laplink(void)
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
);
435 laplink_in_avail
= 0;
438 return *laplink_in_ptr
++;
443 debugger_puts(const char *s
, int32 length
)
445 return debug_write_laplink(0, s
, (int)length
);
450 std_ops(int32 op
, ...)
453 bool load
= true;//false;
457 handle
= load_driver_settings("kernel");
459 load
= get_driver_boolean_parameter(handle
,
460 "laplinkll_debug_output", load
, true);
461 unload_driver_settings(handle
);
464 if (get_module(B_ISA_MODULE_NAME
, (module_info
**)&sISAModule
) < B_OK
)
466 debug_init_laplink(NULL
);
468 return load
? B_OK
: B_ERROR
;
469 case B_MODULE_UNINIT
:
470 put_module(B_ISA_MODULE_NAME
);
477 static struct debugger_module_info sModuleInfo
= {
479 "debugger/laplinkll/v1",
489 module_info
*modules
[] = {
490 (module_info
*)&sModuleInfo
,