/* Remote serial interface for local (hardwired) serial ports for Macintosh. Copyright 1994 Free Software Foundation, Inc. This file is part of GDB. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "defs.h" #include "serial.h" #include #include #include /* This is unused for now. We just return a placeholder. */ struct mac_ttystate { int bogus; }; static int mac_open PARAMS ((serial_t scb, const char *name)); static void mac_raw PARAMS ((serial_t scb)); static int mac_readchar PARAMS ((serial_t scb, int timeout)); static int mac_setbaudrate PARAMS ((serial_t scb, int rate)); static int mac_write PARAMS ((serial_t scb, const char *str, int len)); static void mac_close PARAMS ((serial_t scb)); static serial_ttystate mac_get_tty_state PARAMS ((serial_t scb)); static int mac_set_tty_state PARAMS ((serial_t scb, serial_ttystate state)); static char *aptr PARAMS ((short p)); short input_refnum; short output_refnum; char *mac_input_buffer; char *mac_output_buffer; static int mac_open (scb, name) serial_t scb; const char *name; { OSErr err; /* Alloc buffer space first - that way any allocation failures are intercepted before the serial driver gets involved. */ if (mac_input_buffer == NULL) mac_input_buffer = (char *) xmalloc (256); /* Match on a name and open a port. */ if (strcmp (name, "modem") == 0) { err = OpenDriver ("\p.AIn", &input_refnum); if (err != 0) { return (-1); } err = OpenDriver ("\p.AOut", &output_refnum); if (err != 0) { CloseDriver (input_refnum); return (-1); } } else if (strcmp (name, "printer") == 0) { err = OpenDriver ("\p.BIn", &input_refnum); if (err != 0) { return (-1); } err = OpenDriver ("\p.BOut", &output_refnum); if (err != 0) { CloseDriver (input_refnum); return (-1); } /* fake */ scb->fd = 1; return 0; } else { errno = ENOENT; return (-1); } /* We got something open. */ if (1 /* using custom buffer */) SerSetBuf (input_refnum, mac_input_buffer, 256); /* Set to a GDB-preferred state. */ SerReset (input_refnum, stop10|noParity|data8|baud9600); SerReset (output_refnum, stop10|noParity|data8|baud9600); { CntrlParam cb; struct SerShk *handshake; cb.ioCRefNum = output_refnum; cb.csCode = 14; handshake = (struct SerShk *) &cb.csParam[0]; handshake->fXOn = 0; handshake->fCTS = 0; handshake->xOn = 0; handshake->xOff = 0; handshake->errs = 0; handshake->evts = 0; handshake->fInX = 0; handshake->fDTR = 0; err = PBControl ((ParmBlkPtr) &cb, 0); if (err < 0) return (-1); } /* fake */ scb->fd = 1; return 0; } static int mac_noop (scb) serial_t scb; { return 0; } static void mac_raw (scb) serial_t scb; { /* Always effectively in raw mode. */ } /* Read a character with user-specified timeout. TIMEOUT is number of seconds to wait, or -1 to wait forever. Use timeout of 0 to effect a poll. Returns char if successful. Returns -2 if timeout expired, EOF if line dropped dead, or -3 for any other error (see errno in that case). */ static int mac_readchar (scb, timeout) serial_t scb; int timeout; { int status, n; /* time_t */ unsigned long starttime, now; OSErr err; CntrlParam cb; IOParam pb; if (scb->bufcnt-- > 0) return *scb->bufp++; time (&starttime); while (1) { cb.ioCRefNum = input_refnum; cb.csCode = 2; err = PBStatus ((ParmBlkPtr) &cb, 0); if (err < 0) return SERIAL_ERROR; n = *((long *) &cb.csParam[0]); if (n > 0) { pb.ioRefNum = input_refnum; pb.ioBuffer = (Ptr) (scb->buf); pb.ioReqCount = (n > 64 ? 64 : n); err = PBRead ((ParmBlkPtr) &pb, 0); if (err < 0) return SERIAL_ERROR; scb->bufcnt = pb.ioReqCount; scb->bufcnt--; scb->bufp = scb->buf; return *scb->bufp++; } else if (timeout == 0) return SERIAL_TIMEOUT; else if (timeout == -1) ; else { time (&now); if (now > starttime + timeout) { printf_unfiltered ("start %u, now %u, timeout %d\n", starttime, now, timeout); return SERIAL_TIMEOUT; } } } } /* mac_{get set}_tty_state() are both dummys to fill out the function vector. Someday, they may do something real... */ static serial_ttystate mac_get_tty_state (scb) serial_t scb; { struct mac_ttystate *state; state = (struct mac_ttystate *) xmalloc (sizeof *state); return (serial_ttystate) state; } static int mac_set_tty_state (scb, ttystate) serial_t scb; serial_ttystate ttystate; { return 0; } static int mac_noflush_set_tty_state (scb, new_ttystate, old_ttystate) serial_t scb; serial_ttystate new_ttystate; serial_ttystate old_ttystate; { return 0; } static void mac_print_tty_state (scb, ttystate) serial_t scb; serial_ttystate ttystate; { /* Nothing to print. */ return; } static int mac_set_baud_rate (scb, rate) serial_t scb; int rate; { return 0; } static int mac_write (scb, str, len) serial_t scb; const char *str; int len; { OSErr err; IOParam pb; pb.ioRefNum = output_refnum; pb.ioBuffer = (Ptr) str; pb.ioReqCount = len; err = PBWrite ((ParmBlkPtr) &pb, 0); if (err < 0) { return 1; } return 0; } static void mac_close (scb) serial_t scb; { if (input_refnum) { if (1 /* custom buffer */) SerSetBuf (input_refnum, mac_input_buffer, 0); CloseDriver (input_refnum); input_refnum = 0; } if (output_refnum) { if (0 /* custom buffer */) SetSetBuf (input_refnum, mac_output_buffer, 0); CloseDriver (output_refnum); output_refnum = 0; } } static struct serial_ops mac_ops = { "hardwire", 0, mac_open, mac_close, mac_readchar, mac_write, mac_noop, /* flush output */ mac_noop, /* flush input */ mac_noop, /* send break -- currently only for nindy */ mac_raw, mac_get_tty_state, mac_set_tty_state, mac_print_tty_state, mac_noflush_set_tty_state, mac_set_baud_rate, }; void _initialize_ser_mac () { serial_add_interface (&mac_ops); }