forked from Imagelibrary/binutils-gdb
Initial creation of sourceware repository
This commit is contained in:
470
gdb/ser-e7kpc.c
Normal file
470
gdb/ser-e7kpc.c
Normal file
@@ -0,0 +1,470 @@
|
||||
/* Remote serial interface using Hitachi E7000 PC ISA card in a PC
|
||||
Copyright 1994, 1999 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
#if defined __GO32__ || defined _WIN32
|
||||
#include "defs.h"
|
||||
#include "serial.h"
|
||||
#include "gdb_string.h"
|
||||
|
||||
/* MSVC uses strnicmp instead of strncasecmp */
|
||||
#ifdef _MSC_VER
|
||||
#define strncasecmp strnicmp
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#ifdef __GO32__
|
||||
#include <sys/dos.h>
|
||||
#endif
|
||||
|
||||
static int e7000pc_open PARAMS ((serial_t scb, const char *name));
|
||||
static void e7000pc_raw PARAMS ((serial_t scb));
|
||||
static int e7000pc_readchar PARAMS ((serial_t scb, int timeout));
|
||||
static int e7000pc_setbaudrate PARAMS ((serial_t scb, int rate));
|
||||
static int e7000pc_write PARAMS ((serial_t scb, const char *str, int len));
|
||||
static void e7000pc_close PARAMS ((serial_t scb));
|
||||
static serial_ttystate e7000pc_get_tty_state PARAMS ((serial_t scb));
|
||||
static int e7000pc_set_tty_state PARAMS ((serial_t scb, serial_ttystate state));
|
||||
|
||||
#define OFF_DPD 0x0000
|
||||
#define OFF_DDP 0x1000
|
||||
#define OFF_CPD 0x2000
|
||||
#define OFF_CDP 0x2400
|
||||
#define OFF_FA 0x3000
|
||||
#define OFF_FB 0x3002
|
||||
#define OFF_FC 0x3004
|
||||
#define OFF_IRQTOD 0x3008
|
||||
#define OFF_IRQTOP 0x300a
|
||||
#define OFF_READY 0x300c
|
||||
#define OFF_PON 0x300e
|
||||
|
||||
#define IDLE 0x0000
|
||||
#define CMD_CI 0x4349
|
||||
#define CMD_CO 0x434f
|
||||
#define CMD_LO 0x4c4f
|
||||
#define CMD_LS 0x4c53
|
||||
#define CMD_SV 0x5356
|
||||
#define CMD_SS 0x5353
|
||||
#define CMD_OK 0x4f4b
|
||||
#define CMD_ER 0x4552
|
||||
#define CMD_NF 0x4e46
|
||||
#define CMD_AB 0x4142
|
||||
#define CMD_ED 0x4544
|
||||
#define CMD_CE 0x4345
|
||||
|
||||
static unsigned long fa;
|
||||
static unsigned long irqtod;
|
||||
static unsigned long ready;
|
||||
static unsigned long fb;
|
||||
static unsigned long cpd ;
|
||||
static unsigned long cdp ;
|
||||
static unsigned long ready;
|
||||
static unsigned long pon;
|
||||
static unsigned long irqtop;
|
||||
static unsigned long board_at;
|
||||
|
||||
#ifdef __GO32__
|
||||
|
||||
#define SET_BYTE(x,y) { char _buf = y;dosmemput(&_buf,1, x);}
|
||||
#define SET_WORD(x,y) { short _buf = y;dosmemput(&_buf,2, x);}
|
||||
#define GET_BYTE(x) ( dosmemget(x,1,&bb), bb)
|
||||
#define GET_WORD(x) ( dosmemget(x,2,&sb), sb)
|
||||
static unsigned char bb;
|
||||
static unsigned short sb;
|
||||
|
||||
#else /* win32 */
|
||||
|
||||
#define SET_BYTE(x,y) *(volatile unsigned char *)(x) = (y)
|
||||
#define SET_WORD(x,y) *(volatile unsigned short *)(x) = (y)
|
||||
#define GET_BYTE(x) (*(volatile unsigned char *)(x))
|
||||
#define GET_WORD(x) (*(volatile unsigned short *)(x))
|
||||
#define dosmemget(FROM, LEN, TO) memcpy ((void *)(TO), (void *)(FROM), (LEN))
|
||||
#define dosmemput(FROM, LEN, TO) memcpy ((void *)(TO), (void *)(FROM), (LEN))
|
||||
#endif
|
||||
|
||||
static struct sw
|
||||
{
|
||||
int sw;
|
||||
int addr;
|
||||
} sigs[] = {
|
||||
{0x14, 0xd0000},
|
||||
{0x15, 0xd4000},
|
||||
{0x16, 0xd8000},
|
||||
{0x17, 0xdc000},
|
||||
0};
|
||||
|
||||
#ifdef _MSC_VER
|
||||
/* Get the base of the data segment. This is needed to calculate the offset
|
||||
between data segment addresses and the base of linear memory, which is where
|
||||
device registers reside. Note that this is really only necessary for
|
||||
Win32s, since Win95 and NT keep the data segment at linear 0. */
|
||||
|
||||
static unsigned long
|
||||
get_ds_base (void)
|
||||
{
|
||||
unsigned short dsval;
|
||||
LDT_ENTRY ldt;
|
||||
unsigned long dsbase;
|
||||
|
||||
__asm
|
||||
{
|
||||
mov dsval,ds
|
||||
}
|
||||
|
||||
dsbase = 0;
|
||||
|
||||
GetThreadSelectorEntry (GetCurrentThread(), dsval, &ldt);
|
||||
|
||||
dsbase = ldt.HighWord.Bits.BaseHi << 24 | ldt.HighWord.Bits.BaseMid << 16
|
||||
| ldt.BaseLow;
|
||||
|
||||
return dsbase;
|
||||
}
|
||||
#else /* !_MSC_VER */
|
||||
#define get_ds_base() 0
|
||||
#endif /* _MSC_VER */
|
||||
|
||||
static int
|
||||
e7000pc_init ()
|
||||
{
|
||||
int try;
|
||||
unsigned long dsbase;
|
||||
|
||||
dsbase = get_ds_base ();
|
||||
|
||||
/* Look around in memory for the board's signature */
|
||||
|
||||
for (try = 0; sigs[try].sw; try++)
|
||||
{
|
||||
int val;
|
||||
board_at = sigs[try].addr - dsbase;
|
||||
fa = board_at + OFF_FA;
|
||||
fb = board_at + OFF_FB;
|
||||
cpd = board_at + OFF_CPD;
|
||||
cdp = board_at + OFF_CDP;
|
||||
ready =board_at + OFF_READY;
|
||||
pon = board_at + OFF_PON;
|
||||
irqtop = board_at + OFF_IRQTOP;
|
||||
irqtod = board_at + OFF_IRQTOD;
|
||||
|
||||
val = GET_WORD (ready);
|
||||
|
||||
if (val == (0xaaa0 | sigs[try].sw))
|
||||
{
|
||||
if (GET_WORD (pon) & 0xf)
|
||||
{
|
||||
SET_WORD (fa, 0);
|
||||
SET_WORD (fb, 0);
|
||||
|
||||
SET_WORD (irqtop, 1); /* Disable interrupts from e7000 */
|
||||
SET_WORD (ready, 1);
|
||||
printf_filtered ("\nConnected to the E7000PC at address 0x%x\n",
|
||||
sigs[try].addr);
|
||||
return 1;
|
||||
}
|
||||
error ("The E7000 PC board is working, but the E7000 is turned off.\n");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
error ("GDB cannot connect to the E7000 PC board, check that it is installed\n\
|
||||
and that the switch settings are correct. Some other DOS programs can \n\
|
||||
stop the board from working. Try starting from a very minimal boot, \n\
|
||||
perhaps you need to disable EMM386 over the region where the board has\n\
|
||||
its I/O space, remove other unneeded cards, etc etc\n");
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
static int pbuf_size;
|
||||
static int pbuf_index;
|
||||
|
||||
/* Return next byte from cdp. If no more, then return -1. */
|
||||
|
||||
static int
|
||||
e7000_get (void)
|
||||
{
|
||||
static char pbuf[1000];
|
||||
char tmp[1000];
|
||||
int x;
|
||||
|
||||
if (pbuf_index < pbuf_size)
|
||||
{
|
||||
x = pbuf[pbuf_index++];
|
||||
}
|
||||
else if ((GET_WORD (fb) & 1))
|
||||
{
|
||||
int i;
|
||||
pbuf_size = GET_WORD (cdp + 2);
|
||||
|
||||
dosmemget (cdp + 8, pbuf_size + 1, tmp);
|
||||
|
||||
/* Tell the E7000 we've eaten */
|
||||
SET_WORD (fb, 0);
|
||||
/* Swap it around */
|
||||
for (i = 0; i < pbuf_size; i++)
|
||||
{
|
||||
pbuf[i] = tmp[i^1];
|
||||
}
|
||||
pbuf_index = 0;
|
||||
x = pbuf[pbuf_index++];
|
||||
}
|
||||
else
|
||||
{
|
||||
x = -1;
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
/* Works just like read(), except that it takes a TIMEOUT in seconds. Note
|
||||
that TIMEOUT == 0 is a poll, and TIMEOUT == -1 means wait forever. */
|
||||
|
||||
static int
|
||||
dosasync_read (fd, buf, len, timeout)
|
||||
int fd;
|
||||
char *buf;
|
||||
int len;
|
||||
int timeout;
|
||||
|
||||
{
|
||||
long now;
|
||||
long then;
|
||||
int i = 0;
|
||||
|
||||
/* Then look for some more if we're still hungry */
|
||||
time (&now);
|
||||
then = now + timeout;
|
||||
while (i < len)
|
||||
{
|
||||
int ch = e7000_get();
|
||||
|
||||
/* While there's room in the buffer, and we've already
|
||||
read the stuff in, suck it over */
|
||||
if (ch != -1)
|
||||
{
|
||||
buf[i++] = ch;
|
||||
while (i < len && pbuf_index < pbuf_size )
|
||||
{
|
||||
ch = e7000_get();
|
||||
if (ch == -1)
|
||||
break;
|
||||
buf[i++] = ch;
|
||||
}
|
||||
}
|
||||
|
||||
time (&now);
|
||||
|
||||
if (timeout == 0)
|
||||
return i;
|
||||
if (now >= then && timeout > 0)
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
dosasync_write (fd, buf, len)
|
||||
int fd;
|
||||
const char *buf;
|
||||
int len;
|
||||
{
|
||||
int i;
|
||||
char dummy[1000];
|
||||
|
||||
/* Construct copy locally */
|
||||
((short *)dummy)[0] = CMD_CI;
|
||||
((short *)dummy)[1] = len;
|
||||
((short *)dummy)[2] = 0;
|
||||
((short *)dummy)[3] = 0;
|
||||
for (i = 0; i < len ; i++)
|
||||
{
|
||||
dummy[8 + i ^ 1] = buf[i];
|
||||
}
|
||||
|
||||
/* Wait for the card to get ready */
|
||||
while (GET_WORD (fa) & 1) ;
|
||||
|
||||
/* Blast onto the ISA card */
|
||||
dosmemput (dummy, 8 + len + 1, cpd);
|
||||
|
||||
SET_WORD (fa, 1);
|
||||
SET_WORD (irqtod, 1); /* Interrupt the E7000 */
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static int
|
||||
e7000pc_open (scb, name)
|
||||
serial_t scb;
|
||||
const char *name;
|
||||
{
|
||||
if (strncasecmp (name, "pc", 2) != 0)
|
||||
{
|
||||
errno = ENOENT;
|
||||
return -1;
|
||||
}
|
||||
|
||||
scb->fd = e7000pc_init ();
|
||||
|
||||
if (!scb->fd)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
e7000pc_noop (scb)
|
||||
serial_t scb;
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
e7000pc_raw (scb)
|
||||
serial_t scb;
|
||||
{
|
||||
/* Always in raw mode */
|
||||
}
|
||||
|
||||
static int
|
||||
e7000pc_readchar (scb, timeout)
|
||||
serial_t scb;
|
||||
int timeout;
|
||||
{
|
||||
char buf;
|
||||
|
||||
top:
|
||||
|
||||
if (dosasync_read (scb->fd, &buf, 1, timeout))
|
||||
{
|
||||
if (buf == 0) goto top;
|
||||
return buf;
|
||||
}
|
||||
else
|
||||
return SERIAL_TIMEOUT;
|
||||
}
|
||||
|
||||
struct e7000pc_ttystate {
|
||||
int dummy;
|
||||
};
|
||||
|
||||
/* e7000pc_{get set}_tty_state() are both dummys to fill out the function
|
||||
vector. Someday, they may do something real... */
|
||||
|
||||
static serial_ttystate
|
||||
e7000pc_get_tty_state (scb)
|
||||
serial_t scb;
|
||||
{
|
||||
struct e7000pc_ttystate *state;
|
||||
|
||||
state = (struct e7000pc_ttystate *) xmalloc (sizeof *state);
|
||||
|
||||
return (serial_ttystate) state;
|
||||
}
|
||||
|
||||
static int
|
||||
e7000pc_set_tty_state (scb, ttystate)
|
||||
serial_t scb;
|
||||
serial_ttystate ttystate;
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
e7000pc_noflush_set_tty_state (scb, new_ttystate, old_ttystate)
|
||||
serial_t scb;
|
||||
serial_ttystate new_ttystate;
|
||||
serial_ttystate old_ttystate;
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
e7000pc_print_tty_state (scb, ttystate)
|
||||
serial_t scb;
|
||||
serial_ttystate ttystate;
|
||||
{
|
||||
/* Nothing to print. */
|
||||
return;
|
||||
}
|
||||
|
||||
static int
|
||||
e7000pc_setbaudrate (scb, rate)
|
||||
serial_t scb;
|
||||
int rate;
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
e7000pc_write (scb, str, len)
|
||||
serial_t scb;
|
||||
const char *str;
|
||||
int len;
|
||||
{
|
||||
dosasync_write (scb->fd, str, len);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
e7000pc_close (scb)
|
||||
serial_t scb;
|
||||
{
|
||||
}
|
||||
|
||||
static struct serial_ops e7000pc_ops =
|
||||
{
|
||||
"pc",
|
||||
0,
|
||||
e7000pc_open,
|
||||
e7000pc_close,
|
||||
e7000pc_readchar,
|
||||
e7000pc_write,
|
||||
e7000pc_noop, /* flush output */
|
||||
e7000pc_noop, /* flush input */
|
||||
e7000pc_noop, /* send break -- currently used only for nindy */
|
||||
e7000pc_raw,
|
||||
e7000pc_get_tty_state,
|
||||
e7000pc_set_tty_state,
|
||||
e7000pc_print_tty_state,
|
||||
e7000pc_noflush_set_tty_state,
|
||||
e7000pc_setbaudrate,
|
||||
e7000pc_noop, /* wait for output to drain */
|
||||
};
|
||||
|
||||
void
|
||||
_initialize_ser_e7000pc ()
|
||||
{
|
||||
serial_add_interface (&e7000pc_ops);
|
||||
}
|
||||
#else
|
||||
|
||||
void
|
||||
_initialize_ser_e7000pc ()
|
||||
{
|
||||
|
||||
}
|
||||
#endif
|
||||
Reference in New Issue
Block a user