ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/AmigaOS/serial_amiga.cpp
Revision: 1.7
Committed: 2008-01-01T09:40:31Z (16 years, 4 months ago) by gbeauche
Branch: MAIN
CVS Tags: HEAD
Changes since 1.6: +1 -1 lines
Log Message:
Happy New Year!

File Contents

# Content
1 /*
2 * serial_amiga.cpp - Serial device driver, AmigaOS specific stuff
3 *
4 * Basilisk II (C) 1997-2008 Christian Bauer
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program 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 this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21 #include <exec/types.h>
22 #include <exec/memory.h>
23 #include <exec/errors.h>
24 #include <dos/dos.h>
25 #include <dos/dosextens.h>
26 #include <dos/dostags.h>
27 #include <devices/serial.h>
28 #include <devices/parallel.h>
29 #define __USE_SYSBASE
30 #include <proto/exec.h>
31 #include <proto/dos.h>
32 #include <inline/exec.h>
33 #include <inline/dos.h>
34
35 #include "sysdeps.h"
36 #include "cpu_emulation.h"
37 #include "main.h"
38 #include "macos_util.h"
39 #include "prefs.h"
40 #include "serial.h"
41 #include "serial_defs.h"
42
43 #define DEBUG 0
44 #include "debug.h"
45
46 #define MONITOR 0
47
48
49 // These messages are sent to the serial process
50 const uint32 MSG_QUERY = 'qery'; // Query port status, return status in control_io
51 const uint32 MSG_SET_PARAMS = 'setp'; // Set serial parameters (parameters in control_io)
52 const uint32 MSG_SET_PAR_PARAMS = 'pstp'; // Set parallel parameters (parameters in control_io)
53 const uint32 MSG_KILL_IO = 'kill'; // Kill pending I/O requests
54 const uint32 MSG_BREAK = 'brek'; // Send break
55 const uint32 MSG_RESET = 'rset'; // Reset channel
56 const uint32 MSG_PRIME_IN = 'prin'; // Data input
57 const uint32 MSG_PRIME_OUT = 'pout'; // Data output
58
59 struct SerMessage : public Message {
60 SerMessage(uint32 what_, const struct MsgPort *reply_port = NULL)
61 {
62 what = what_;
63 mn_ReplyPort = (struct MsgPort *)reply_port;
64 mn_Length = sizeof(*this);
65 }
66 uint32 what;
67 uint32 pb;
68 };
69
70
71 // Driver private variables
72 class ASERDPort : public SERDPort {
73 public:
74 ASERDPort(const char *dev)
75 {
76 device_name = dev;
77 if (dev && dev[0] == '*') {
78 is_parallel = true;
79 device_name++;
80 } else
81 is_parallel = false;
82 control_io = NULL;
83 serial_proc = NULL;
84 reply_port = NULL;
85 }
86
87 virtual ~ASERDPort()
88 {
89 }
90
91 virtual int16 open(uint16 config);
92 virtual int16 prime_in(uint32 pb, uint32 dce);
93 virtual int16 prime_out(uint32 pb, uint32 dce);
94 virtual int16 control(uint32 pb, uint32 dce, uint16 code);
95 virtual int16 status(uint32 pb, uint32 dce, uint16 code);
96 virtual int16 close(void);
97
98 private:
99 bool configure(uint16 config);
100 void set_handshake(uint32 s, bool with_dtr);
101 void send_to_proc(uint32 what, uint32 pb = 0);
102 bool query(void);
103 bool set_params(void);
104 bool set_par_params(void);
105 void conv_error(struct IOExtSer *io, uint32 dt);
106 static void serial_func(void);
107
108 const char *device_name; // Device name
109 bool is_parallel; // Flag: Port is parallel
110 IOExtSer *control_io; // IORequest for setting serial port characteristics etc.
111
112 struct Process *serial_proc; // Serial device handler process
113 bool proc_error; // Flag: process didn't initialize
114 struct MsgPort *proc_port; // Message port of process, for communication with main task
115 struct MsgPort *reply_port; // Reply port for communication with process
116
117 uint8 err_mask; // shkErrs
118 };
119
120
121 // Global variables
122 static void *proc_arg; // Argument to process
123 extern struct Task *MainTask; // Pointer to main task (from main_amiga.cpp)
124
125
126 /*
127 * Initialization
128 */
129
130 void SerialInit(void)
131 {
132 // Read serial preferences and create structs for both ports
133 the_serd_port[0] = new ASERDPort(PrefsFindString("seriala"));
134 the_serd_port[1] = new ASERDPort(PrefsFindString("serialb"));
135 }
136
137
138 /*
139 * Deinitialization
140 */
141
142 void SerialExit(void)
143 {
144 delete (ASERDPort *)the_serd_port[0];
145 delete (ASERDPort *)the_serd_port[1];
146 }
147
148
149 /*
150 * Open serial port
151 */
152
153 int16 ASERDPort::open(uint16 config)
154 {
155 // Don't open NULL name devices
156 if (device_name == NULL)
157 return openErr;
158
159 // Init variables
160 err_mask = 0;
161
162 // Create message port
163 reply_port = CreateMsgPort();
164 if (reply_port == NULL)
165 goto open_error;
166
167 // Start process
168 proc_error = false;
169 proc_arg = this;
170 SetSignal(0, SIGF_SINGLE);
171 serial_proc = CreateNewProcTags(
172 NP_Entry, (ULONG)serial_func,
173 NP_Name, (ULONG)"Basilisk II Serial Task",
174 NP_Priority, 1,
175 TAG_END
176 );
177 if (serial_proc == NULL)
178 goto open_error;
179
180 // Wait for signal from process
181 Wait(SIGF_SINGLE);
182
183 // Initialization error? Then bail out
184 if (proc_error)
185 goto open_error;
186
187 // Configure port
188 configure(config);
189 return noErr;
190
191 open_error:
192 serial_proc = NULL;
193 if (reply_port) {
194 DeleteMsgPort(reply_port);
195 reply_port = NULL;
196 }
197 return openErr;
198 }
199
200
201 /*
202 * Read data from port
203 */
204
205 int16 ASERDPort::prime_in(uint32 pb, uint32 dce)
206 {
207 // Send input command to serial process
208 D(bug("primein\n"));
209 read_done = false;
210 read_pending = true;
211 WriteMacInt32(input_dt + serdtDCE, dce);
212 send_to_proc(MSG_PRIME_IN, pb);
213 return 1; // Command in progress
214 }
215
216
217 /*
218 * Write data to port
219 */
220
221 int16 ASERDPort::prime_out(uint32 pb, uint32 dce)
222 {
223 // Send output command to serial process
224 D(bug("primeout\n"));
225 write_done = false;
226 write_pending = true;
227 WriteMacInt32(output_dt + serdtDCE, dce);
228 send_to_proc(MSG_PRIME_OUT, pb);
229 return 1; // Command in progress
230 }
231
232
233 /*
234 * Control calls
235 */
236
237 int16 ASERDPort::control(uint32 pb, uint32 dce, uint16 code)
238 {
239 D(bug("control(%ld)\n", (uint32)code));
240 switch (code) {
241 case 1: // KillIO
242 send_to_proc(MSG_KILL_IO);
243 return noErr;
244
245 case kSERDConfiguration:
246 if (configure(ReadMacInt16(pb + csParam)))
247 return noErr;
248 else
249 return paramErr;
250
251 case kSERDInputBuffer: {
252 if (is_parallel)
253 return noErr;
254 int buf = ReadMacInt16(pb + csParam + 4) & 0xffffffc0;
255 if (buf < 1024) // 1k minimum
256 buf = 1024;
257 D(bug(" buffer size is now %08lx\n", buf));
258 control_io->io_RBufLen = buf;
259 return set_params() ? noErr : paramErr;
260 }
261
262 case kSERDSerHShake:
263 set_handshake(pb + csParam, false);
264 return noErr;
265
266 case kSERDSetBreak:
267 if (!is_parallel)
268 send_to_proc(MSG_BREAK);
269 return noErr;
270
271 case kSERDClearBreak:
272 return noErr;
273
274 case kSERDBaudRate:
275 if (is_parallel)
276 return noErr;
277 control_io->io_Baud = ReadMacInt16(pb + csParam);
278 D(bug(" baud rate %ld\n", control_io->io_Baud));
279 return set_params() ? noErr : paramErr;
280
281 case kSERDHandshake:
282 case kSERDHandshakeRS232:
283 set_handshake(pb + csParam, true);
284 return noErr;
285
286 case kSERDClockMIDI:
287 if (is_parallel)
288 return noErr;
289 control_io->io_Baud = 31250;
290 control_io->io_SerFlags = SERF_XDISABLED | SERF_SHARED;
291 control_io->io_StopBits = 1;
292 control_io->io_ReadLen = control_io->io_WriteLen = 8;
293 return set_params() ? noErr : paramErr;
294
295 case kSERDMiscOptions:
296 case kSERDAssertDTR:
297 case kSERDNegateDTR:
298 case kSERDSetPEChar:
299 case kSERDSetPEAltChar:
300 case kSERDAssertRTS:
301 case kSERDNegateRTS:
302 return noErr; // Not supported under AmigaOS
303
304 case kSERD115KBaud:
305 if (is_parallel)
306 return noErr;
307 control_io->io_Baud = 115200;
308 return set_params() ? noErr : paramErr;
309
310 case kSERD230KBaud:
311 case kSERDSetHighSpeed:
312 if (is_parallel)
313 return noErr;
314 control_io->io_Baud = 230400;
315 return set_params() ? noErr : paramErr;
316
317 case kSERDResetChannel:
318 send_to_proc(MSG_RESET);
319 return noErr;
320
321 default:
322 printf("WARNING: SerialControl(): unimplemented control code %d\n", code);
323 return controlErr;
324 }
325 }
326
327
328 /*
329 * Status calls
330 */
331
332 int16 ASERDPort::status(uint32 pb, uint32 dce, uint16 code)
333 {
334 D(bug("status(%ld)\n", (uint32)code));
335 switch (code) {
336 case kSERDInputCount:
337 WriteMacInt32(pb + csParam, 0);
338 if (!is_parallel) {
339 if (!query())
340 return noErr;
341 D(bug("status(2) successful, returning %08lx\n", control_io->IOSer.io_Actual));
342 WriteMacInt32(pb + csParam, control_io->IOSer.io_Actual);
343 }
344 return noErr;
345
346 case kSERDStatus: {
347 uint32 p = pb + csParam;
348 WriteMacInt8(p + staCumErrs, cum_errors);
349 cum_errors = 0;
350 WriteMacInt8(p + staRdPend, read_pending);
351 WriteMacInt8(p + staWrPend, write_pending);
352 if (is_parallel) {
353 WriteMacInt8(p + staXOffSent, 0);
354 WriteMacInt8(p + staXOffHold, 0);
355 WriteMacInt8(p + staCtsHold, 0);
356 WriteMacInt8(p + staDsrHold, 0);
357 WriteMacInt8(p + staModemStatus, dsrEvent | dcdEvent | ctsEvent);
358 } else {
359 query();
360 WriteMacInt8(p + staXOffSent,
361 (control_io->io_Status & IO_STATF_XOFFREAD ? xOffWasSent : 0)
362 | (control_io->io_Status & (1 << 6) ? dtrNegated : 0)); // RTS
363 WriteMacInt8(p + staXOffHold, control_io->io_Status & IO_STATF_XOFFWRITE);
364 WriteMacInt8(p + staCtsHold, control_io->io_Status & (1 << 4)); // CTS
365 WriteMacInt8(p + staDsrHold, control_io->io_Status & (1 << 3)); // DSR
366 WriteMacInt8(p + staModemStatus,
367 (control_io->io_Status & (1 << 3) ? 0 : dsrEvent)
368 | (control_io->io_Status & (1 << 2) ? riEvent : 0)
369 | (control_io->io_Status & (1 << 5) ? 0 : dcdEvent)
370 | (control_io->io_Status & (1 << 4) ? 0 : ctsEvent)
371 | (control_io->io_Status & IO_STATF_READBREAK ? breakEvent : 0));
372 }
373 return noErr;
374 }
375
376 default:
377 printf("WARNING: SerialStatus(): unimplemented status code %d\n", code);
378 return statusErr;
379 }
380 }
381
382
383 /*
384 * Close serial port
385 */
386
387 int16 ASERDPort::close()
388 {
389 // Stop process
390 if (serial_proc) {
391 SetSignal(0, SIGF_SINGLE);
392 Signal(&serial_proc->pr_Task, SIGBREAKF_CTRL_C);
393 Wait(SIGF_SINGLE);
394 }
395
396 // Delete reply port
397 if (reply_port) {
398 DeleteMsgPort(reply_port);
399 reply_port = NULL;
400 }
401 return noErr;
402 }
403
404
405 /*
406 * Configure serial port with MacOS config word
407 */
408
409 bool ASERDPort::configure(uint16 config)
410 {
411 D(bug(" configure %04lx\n", (uint32)config));
412 if (is_parallel)
413 return true;
414
415 // Set number of stop bits
416 switch (config & 0xc000) {
417 case stop10:
418 control_io->io_StopBits = 1;
419 break;
420 case stop20:
421 control_io->io_StopBits = 2;
422 break;
423 default:
424 return false;
425 }
426
427 // Set parity mode
428 switch (config & 0x3000) {
429 case noParity:
430 control_io->io_SerFlags &= ~SERF_PARTY_ON;
431 break;
432 case oddParity:
433 control_io->io_SerFlags |= SERF_PARTY_ON | SERF_PARTY_ODD;
434 break;
435 case evenParity:
436 control_io->io_SerFlags |= SERF_PARTY_ON;
437 control_io->io_SerFlags &= ~SERF_PARTY_ODD;
438 break;
439 default:
440 return false;
441 }
442
443 // Set number of data bits
444 switch (config & 0x0c00) {
445 case data5:
446 control_io->io_ReadLen = control_io->io_WriteLen = 5;
447 break;
448 case data6:
449 control_io->io_ReadLen = control_io->io_WriteLen = 6;
450 break;
451 case data7:
452 control_io->io_ReadLen = control_io->io_WriteLen = 7;
453 break;
454 case data8:
455 control_io->io_ReadLen = control_io->io_WriteLen = 8;
456 break;
457 }
458
459 // Set baud rate
460 control_io->io_Baud = 115200 / ((config & 0x03ff) + 2);
461 return set_params();
462 }
463
464
465 /*
466 * Set serial handshaking
467 */
468
469 void ASERDPort::set_handshake(uint32 s, bool with_dtr)
470 {
471 D(bug(" set_handshake %02x %02x %02x %02x %02x %02x %02x %02x\n",
472 ReadMacInt8(s + 0), ReadMacInt8(s + 1), ReadMacInt8(s + 2), ReadMacInt8(s + 3),
473 ReadMacInt8(s + 4), ReadMacInt8(s + 5), ReadMacInt8(s + 6), ReadMacInt8(s + 7)));
474
475 err_mask = ReadMacInt8(s + shkErrs);
476
477 if (is_parallel) {
478
479 // Parallel handshake
480 if (with_dtr) {
481 if (ReadMacInt8(s + shkFCTS) || ReadMacInt8(s + shkFDTR))
482 ((IOExtPar *)control_io)->io_ParFlags |= PARF_ACKMODE;
483 else
484 ((IOExtPar *)control_io)->io_ParFlags &= ~PARF_ACKMODE;
485 } else {
486 if (ReadMacInt8(s + shkFCTS))
487 ((IOExtPar *)control_io)->io_ParFlags |= PARF_ACKMODE;
488 else
489 ((IOExtPar *)control_io)->io_ParFlags &= ~PARF_ACKMODE;
490 }
491 set_par_params();
492
493 } else {
494
495 // Serial handshake
496 if (ReadMacInt8(s + shkFXOn) || ReadMacInt8(s + shkFInX))
497 control_io->io_SerFlags &= ~SERF_XDISABLED;
498 else
499 control_io->io_SerFlags |= SERF_XDISABLED;
500
501 if (with_dtr) {
502 if (ReadMacInt8(s + shkFCTS) || ReadMacInt8(s + shkFDTR))
503 control_io->io_SerFlags |= SERF_7WIRE;
504 else
505 control_io->io_SerFlags &= ~SERF_7WIRE;
506 } else {
507 if (ReadMacInt8(s + shkFCTS))
508 control_io->io_SerFlags |= SERF_7WIRE;
509 else
510 control_io->io_SerFlags &= ~SERF_7WIRE;
511 }
512 control_io->io_CtlChar = ReadMacInt16(s + shkXOn) << 16;
513 set_params();
514 }
515 }
516
517
518 /*
519 * Send message to serial process
520 */
521
522 void ASERDPort::send_to_proc(uint32 what, uint32 pb)
523 {
524 D(bug("sending %08lx to serial_proc\n", what));
525 SerMessage msg(what, reply_port);
526 msg.pb = pb;
527 PutMsg(proc_port, &msg);
528 WaitPort(reply_port);
529 GetMsg(reply_port);
530 D(bug(" sent\n"));
531 }
532
533
534 /*
535 * Query serial port status
536 */
537
538 bool ASERDPort::query(void)
539 {
540 send_to_proc(MSG_QUERY);
541 return control_io->IOSer.io_Error == 0;
542 }
543
544
545 /*
546 * Set serial parameters
547 */
548
549 bool ASERDPort::set_params(void)
550 {
551 // Set/clear RadBoogie
552 UBYTE flags = control_io->io_SerFlags;
553 if (!(flags & SERF_PARTY_ON) && (flags & SERF_XDISABLED) && control_io->io_ReadLen == 8)
554 control_io->io_SerFlags |= SERF_RAD_BOOGIE;
555 else
556 control_io->io_SerFlags &= ~SERF_RAD_BOOGIE;
557
558 // Send message to serial process
559 send_to_proc(MSG_SET_PARAMS);
560 return control_io->IOSer.io_Error == 0;
561 }
562
563
564 /*
565 * Set parallel parameters
566 */
567
568 bool ASERDPort::set_par_params(void)
569 {
570 send_to_proc(MSG_SET_PAR_PARAMS);
571 return control_io->IOSer.io_Error == 0;
572 }
573
574
575 /*
576 * Convert AmigaOS error code to MacOS error code, set serdtResult and cum_errors
577 */
578
579 void ASERDPort::conv_error(struct IOExtSer *io, uint32 dt)
580 {
581 int16 oserr;
582 uint8 cum;
583
584 BYTE err = io->IOSer.io_Error;
585 if (err == 0 || err == IOERR_NOCMD) {
586 oserr = 0;
587 cum = 0;
588 } else {
589 if (is_parallel) {
590 oserr = (err_mask & framingErr) ? rcvrErr : 0;
591 cum = framingErr;
592 } else {
593 switch (io->IOSer.io_Error) {
594 case SerErr_DetectedBreak:
595 oserr = breakRecd;
596 cum = breakErr;
597 break;
598 case SerErr_ParityErr:
599 oserr = (err_mask & parityErr) ? rcvrErr : 0;
600 cum = parityErr;
601 break;
602 case SerErr_BufOverflow:
603 oserr = (err_mask & swOverrunErr) ? rcvrErr : 0;
604 cum = swOverrunErr;
605 break;
606 case SerErr_LineErr:
607 oserr = (err_mask & hwOverrunErr) ? rcvrErr : 0;
608 cum = hwOverrunErr;
609 break;
610 default:
611 oserr = (err_mask & framingErr) ? rcvrErr : 0;
612 cum = framingErr;
613 break;
614 }
615 }
616 }
617
618 WriteMacInt32(dt + serdtResult, oserr);
619 cum_errors |= cum;
620 }
621
622
623 /*
624 * Process for communication with the serial.device
625 */
626
627 __saveds void ASERDPort::serial_func(void)
628 {
629 struct ASERDPort *obj = (ASERDPort *)proc_arg;
630 struct MsgPort *proc_port = NULL, *io_port = NULL, *control_port = NULL;
631 struct IOExtSer *read_io = NULL, *write_io = NULL, *control_io = NULL;
632 uint8 orig_params[sizeof(struct IOExtSer)];
633 bool opened = false;
634 ULONG io_mask = 0, proc_port_mask = 0;
635
636 // Default: error occured
637 obj->proc_error = true;
638
639 // Create message port for communication with main task
640 proc_port = CreateMsgPort();
641 if (proc_port == NULL)
642 goto quit;
643 proc_port_mask = 1 << proc_port->mp_SigBit;
644
645 // Create message ports for serial.device I/O
646 io_port = CreateMsgPort();
647 if (io_port == NULL)
648 goto quit;
649 io_mask = 1 << io_port->mp_SigBit;
650 control_port = CreateMsgPort();
651 if (control_port == NULL)
652 goto quit;
653
654 // Create IORequests
655 read_io = (struct IOExtSer *)CreateIORequest(io_port, sizeof(struct IOExtSer));
656 write_io = (struct IOExtSer *)CreateIORequest(io_port, sizeof(struct IOExtSer));
657 control_io = (struct IOExtSer *)CreateIORequest(control_port, sizeof(struct IOExtSer));
658 if (read_io == NULL || write_io == NULL || control_io == NULL)
659 goto quit;
660 read_io->IOSer.io_Message.mn_Node.ln_Type = 0; // Avoid CheckIO() bug
661 write_io->IOSer.io_Message.mn_Node.ln_Type = 0;
662 control_io->IOSer.io_Message.mn_Node.ln_Type = 0;
663
664 // Parse device name
665 char dev_name[256];
666 ULONG dev_unit;
667 if (sscanf(obj->device_name, "%[^/]/%ld", dev_name, &dev_unit) < 2)
668 goto quit;
669
670 // Open device
671 if (obj->is_parallel)
672 ((IOExtPar *)read_io)->io_ParFlags = PARF_SHARED;
673 else
674 read_io->io_SerFlags = SERF_SHARED | SERF_7WIRE;
675 if (OpenDevice((UBYTE *) dev_name, dev_unit, (struct IORequest *)read_io, 0) || read_io->IOSer.io_Device == NULL)
676 goto quit;
677 opened = true;
678
679 // Copy IORequests
680 memcpy(write_io, read_io, sizeof(struct IOExtSer));
681 memcpy(control_io, read_io, sizeof(struct IOExtSer));
682
683 // Attach control_io to control_port and set default values
684 control_io->IOSer.io_Message.mn_ReplyPort = control_port;
685 if (!obj->is_parallel) {
686 control_io->io_CtlChar = SER_DEFAULT_CTLCHAR;
687 control_io->io_RBufLen = 64;
688 control_io->io_ExtFlags = 0;
689 control_io->io_Baud = 9600;
690 control_io->io_BrkTime = 250000;
691 control_io->io_ReadLen = control_io->io_WriteLen = 8;
692 control_io->io_StopBits = 1;
693 control_io->io_SerFlags = SERF_SHARED;
694 control_io->IOSer.io_Command = SDCMD_SETPARAMS;
695 DoIO((struct IORequest *)control_io);
696 memcpy(orig_params, &(control_io->io_CtlChar), (uint8 *)&(control_io->io_Status) - (uint8 *)&(control_io->io_CtlChar));
697 }
698
699 // Initialization went well, inform main task
700 obj->proc_port = proc_port;
701 obj->control_io = control_io;
702 obj->proc_error = false;
703 Signal(MainTask, SIGF_SINGLE);
704
705 // Main loop
706 for (;;) {
707
708 // Wait for I/O and messages (CTRL_C is used for quitting the task)
709 ULONG sig = Wait(proc_port_mask | io_mask | SIGBREAKF_CTRL_C);
710
711 // Main task wants to quit us
712 if (sig & SIGBREAKF_CTRL_C)
713 break;
714
715 // Main task sent a command to us
716 if (sig & proc_port_mask) {
717 struct SerMessage *msg;
718 while (msg = (SerMessage *)GetMsg(proc_port)) {
719 D(bug("serial_proc received %08lx\n", msg->what));
720 switch (msg->what) {
721 case MSG_QUERY:
722 control_io->IOSer.io_Command = SDCMD_QUERY;
723 DoIO((struct IORequest *)control_io);
724 D(bug(" query returned %08lx, actual %08lx\n", control_io->IOSer.io_Error, control_io->IOSer.io_Actual));
725 break;
726
727 case MSG_SET_PARAMS:
728 // Only send SDCMD_SETPARAMS when configuration has changed
729 if (memcmp(orig_params, &(control_io->io_CtlChar), (uint8 *)&(control_io->io_Status) - (uint8 *)&(control_io->io_CtlChar))) {
730 memcpy(orig_params, &(control_io->io_CtlChar), (uint8 *)&(control_io->io_Status) - (uint8 *)&(control_io->io_CtlChar));
731 memcpy(&(read_io->io_CtlChar), &(control_io->io_CtlChar), (uint8 *)&(control_io->io_Status) - (uint8 *)&(control_io->io_CtlChar));
732 memcpy(&(write_io->io_CtlChar), &(control_io->io_CtlChar), (uint8 *)&(control_io->io_Status) - (uint8 *)&(control_io->io_CtlChar));
733 control_io->IOSer.io_Command = SDCMD_SETPARAMS;
734 D(bug(" params %08lx %08lx %08lx %08lx %08lx %08lx\n", control_io->io_CtlChar, control_io->io_RBufLen, control_io->io_ExtFlags, control_io->io_Baud, control_io->io_BrkTime, *(uint32 *)((uint8 *)control_io + 76)));
735 DoIO((struct IORequest *)control_io);
736 D(bug(" set_parms returned %08lx\n", control_io->IOSer.io_Error));
737 }
738 break;
739
740 case MSG_SET_PAR_PARAMS:
741 control_io->IOSer.io_Command = PDCMD_SETPARAMS;
742 DoIO((struct IORequest *)control_io);
743 D(bug(" set_par_parms returned %08lx\n", control_io->IOSer.io_Error));
744 break;
745
746 case MSG_BREAK:
747 control_io->IOSer.io_Command = SDCMD_BREAK;
748 DoIO((struct IORequest *)control_io);
749 D(bug(" break returned %08lx\n", control_io->IOSer.io_Error));
750 break;
751
752 case MSG_RESET:
753 control_io->IOSer.io_Command = CMD_RESET;
754 DoIO((struct IORequest *)control_io);
755 D(bug(" reset returned %08lx\n", control_io->IOSer.io_Error));
756 break;
757
758 case MSG_KILL_IO:
759 AbortIO((struct IORequest *)read_io);
760 AbortIO((struct IORequest *)write_io);
761 WaitIO((struct IORequest *)read_io);
762 WaitIO((struct IORequest *)write_io);
763 obj->read_pending = obj->write_pending = false;
764 obj->read_done = obj->write_done = false;
765 break;
766
767 case MSG_PRIME_IN:
768 read_io->IOSer.io_Message.mn_Node.ln_Name = (char *)msg->pb;
769 read_io->IOSer.io_Data = Mac2HostAddr(ReadMacInt32(msg->pb + ioBuffer));
770 read_io->IOSer.io_Length = ReadMacInt32(msg->pb + ioReqCount);
771 read_io->IOSer.io_Actual = 0;
772 read_io->IOSer.io_Command = CMD_READ;
773 D(bug("serial_proc receiving %ld bytes from %08lx\n", read_io->IOSer.io_Length, read_io->IOSer.io_Data));
774 SendIO((struct IORequest *)read_io);
775 break;
776
777 case MSG_PRIME_OUT: {
778 write_io->IOSer.io_Message.mn_Node.ln_Name = (char *)msg->pb;
779 write_io->IOSer.io_Data = Mac2HostAddr(ReadMacInt32(msg->pb + ioBuffer));
780 write_io->IOSer.io_Length = ReadMacInt32(msg->pb + ioReqCount);
781 write_io->IOSer.io_Actual = 0;
782 write_io->IOSer.io_Command = CMD_WRITE;
783 D(bug("serial_proc transmitting %ld bytes from %08lx\n", write_io->IOSer.io_Length, write_io->IOSer.io_Data));
784 #if MONITOR
785 bug("Sending serial data:\n");
786 uint8 *adr = Mac2HostAddr(ReadMacInt32(msg->pb + ioBuffer));
787 for (int i=0; i<len; i++) {
788 bug("%02lx ", adr[i]);
789 }
790 bug("\n");
791 #endif
792 SendIO((struct IORequest *)write_io);
793 break;
794 }
795 }
796 D(bug(" serial_proc replying\n"));
797 ReplyMsg(msg);
798 }
799 }
800
801 // I/O operation completed
802 if (sig & io_mask) {
803 struct IOExtSer *io;
804 while (io = (struct IOExtSer *)GetMsg(io_port)) {
805 if (io == read_io) {
806 D(bug("read_io complete, %ld bytes received, error %ld\n", read_io->IOSer.io_Actual, read_io->IOSer.io_Error));
807 uint32 pb = (uint32)read_io->IOSer.io_Message.mn_Node.ln_Name;
808 #if MONITOR
809 bug("Receiving serial data:\n");
810 uint8 *adr = Mac2HostAddr(ReadMacInt32(msg->pb + ioBuffer));
811 for (int i=0; i<read_io->IOSer.io_Actual; i++) {
812 bug("%02lx ", adr[i]);
813 }
814 bug("\n");
815 #endif
816 WriteMacInt32(pb + ioActCount, read_io->IOSer.io_Actual);
817 obj->conv_error(read_io, obj->input_dt);
818 obj->read_done = true;
819 SetInterruptFlag(INTFLAG_SERIAL);
820 TriggerInterrupt();
821 } else if (io == write_io) {
822 D(bug("write_io complete, %ld bytes sent, error %ld\n", write_io->IOSer.io_Actual, write_io->IOSer.io_Error));
823 uint32 pb = (uint32)write_io->IOSer.io_Message.mn_Node.ln_Name;
824 WriteMacInt32(pb + ioActCount, write_io->IOSer.io_Actual);
825 obj->conv_error(write_io, obj->output_dt);
826 obj->write_done = true;
827 SetInterruptFlag(INTFLAG_SERIAL);
828 TriggerInterrupt();
829 }
830 }
831 }
832 }
833 quit:
834
835 // Close everything
836 if (opened) {
837 if (CheckIO((struct IORequest *)write_io) == 0) {
838 AbortIO((struct IORequest *)write_io);
839 WaitIO((struct IORequest *)write_io);
840 }
841 if (CheckIO((struct IORequest *)read_io) == 0) {
842 AbortIO((struct IORequest *)read_io);
843 WaitIO((struct IORequest *)read_io);
844 }
845 CloseDevice((struct IORequest *)read_io);
846 }
847 if (control_io)
848 DeleteIORequest(control_io);
849 if (write_io)
850 DeleteIORequest(write_io);
851 if (read_io)
852 DeleteIORequest(read_io);
853 if (control_port)
854 DeleteMsgPort(control_port);
855 if (io_port)
856 DeleteMsgPort(io_port);
857
858 // Send signal to main task to confirm termination
859 Forbid();
860 Signal(MainTask, SIGF_SINGLE);
861 }