From 54845d7d91ede831c0515e3331be2f1317c7b214 Mon Sep 17 00:00:00 2001 From: imp Date: Wed, 13 Oct 1999 23:48:35 +0000 Subject: [PATCH] Allow in/out to work in DOS programs. Submitted by: Parag Patel PR: bin/8486 --- usr.bin/doscmd/config.c | 15 +++++++++++++++ usr.bin/doscmd/doscmd.1 | 25 +++++++++++++++++++++++++ usr.bin/doscmd/doscmd.c | 37 +++++++++++++++++++++++++++++++++++-- usr.bin/doscmd/doscmd.h | 5 ++++- usr.bin/doscmd/port.c | 15 +++++++++++++++ 5 files changed, 94 insertions(+), 3 deletions(-) diff --git a/usr.bin/doscmd/config.c b/usr.bin/doscmd/config.c index d20aa1579a17..dd1316faaee7 100644 --- a/usr.bin/doscmd/config.c +++ b/usr.bin/doscmd/config.c @@ -238,6 +238,21 @@ read_config(FILE *fp) fprintf(stderr, "Boot drive must be either A: or C:\n"); quit(1); } + } else if (!strcasecmp(av[0], "portmap")) { + int p, c; + if (ac < 2 || ac > 3 || !isdigit(av[1][0]) || + (ac == 3 && !isdigit(av[2][0]))) { + fprintf(stderr, "Usage: portmap port [count]\n"); + quit(1); + } + p = strtol(av[1], 0, 0); + c = (ac == 3) ? strtol(av[2], 0, 0) : 1; + iomap_port(p, c); + + while (c-- > 0) { + define_input_port_handler(p++, inb_port); + define_output_port_handler(p++, outb_port); + } } else if (!strcasecmp(av[0], "setver")) { int v; if (ac != 3 || !(v = strtol(av[2], 0, 0))) { diff --git a/usr.bin/doscmd/doscmd.1 b/usr.bin/doscmd/doscmd.1 index 4d039a4b0b66..0fa73f4a029a 100644 --- a/usr.bin/doscmd/doscmd.1 +++ b/usr.bin/doscmd/doscmd.1 @@ -188,6 +188,18 @@ to .\" .\" .\" +.It Fl p Ar port Ns Xo +.Op : Ns Ar cnt +.Xc +Map the requested io +.Ar port +(with optional range up to to +.Ar port+cnt Ns No -1 ) +to the real hardware I/O port(s). +This will likely require root privs to access them. +.\" +.\" +.\" .It Fl P Enable tracing of io port calls (such as .Li inb , @@ -434,6 +446,19 @@ This code is lightly tested and may not suit all needs. .\" .\" .\" +.It Cm portmap Xo +.Ar port +.Op Ar count +.Xc +Map the requested io +.Ar port +(with optional range up to to +.Ar port+count Ns No -1 ) +to the real hardware I/O port(s). +This will likely require root privs to access them. +.\" +.\" +.\" .It Cm "setver command version" Cause doscmd, when emulating DOS, to report .Cm version diff --git a/usr.bin/doscmd/doscmd.c b/usr.bin/doscmd/doscmd.c index 77b9e133b57c..4340731e157e 100644 --- a/usr.bin/doscmd/doscmd.c +++ b/usr.bin/doscmd/doscmd.c @@ -480,7 +480,7 @@ do_args(int argc, char *argv[]) FILE *fp; char *col; - while ((c = getopt (argc, argv, "234Oc:TkCIEMPRLAU:S:HDtzvVxXYfbri:o:d:")) != -1) { + while ((c = getopt (argc, argv, "234Oc:TkCIEMPRLAU:S:HDtzvVxXYfbri:o:p:d:")) != -1) { switch (c) { case 'd': if (fp = fopen(optarg, "w")) { @@ -515,6 +515,7 @@ do_args(int argc, char *argv[]) i = strtol(col, 0, 0); } p = strtol(optarg, 0, 0); + iomap_port(p, i); while (i-- > 0) define_input_port_handler(p++, inb_traceport); @@ -526,10 +527,25 @@ do_args(int argc, char *argv[]) i = strtol(col, 0, 0); } p = strtol(optarg, 0, 0); + iomap_port(p, i); while (i-- > 0) define_output_port_handler(p++, outb_traceport); break; + case 'p': + i = 1; + if (col = strchr(optarg, ':')) { + *col++ = 0; + i = strtol(col, 0, 0); + } + p = strtol(optarg, 0, 0); + iomap_port(p, i); + + while (i-- > 0) { + define_input_port_handler(p++, inb_port); + define_output_port_handler(p++, outb_port); + } + break; case 'r': raw_kbd = 1; @@ -834,6 +850,9 @@ struct io_range { int enable; }; +/* This is commented out as it is never called. Turn it back on if needed. + */ +#if COMMENTED_OUT static void iomap_init(void) { @@ -844,6 +863,7 @@ iomap_init(void) { 0x1c80, 2, 1 }, /* 0x1c80 - 0x1c81 */ { 0x2c80, 2, 1 }, /* 0x2c80 - 0x2c81 */ { 0x3c80, 2, 1 }, /* 0x3c80 - 0x3c81 */ + { 0x378, 8, 1 }, /* 0x378 - 0x37F */ { 0x3c4, 2, 1 }, /* 0x3c4 - 0x3c5 */ { 0x3c5, 2, 1 }, /* 0x3ce - 0x3cf */ #else @@ -851,8 +871,21 @@ iomap_init(void) #endif { 0, 0, 0 } }; - + for (i = 0; io[i].length; i++) if (i386_set_ioperm(io[i].start, io[i].length, io[i].enable) < 0) err(1, "i386_set_ioperm"); } +#endif + +/* This is used to map in only the specified port range, instead of all + the ports or only certain port ranges. + */ +void +iomap_port(int port, int count) +{ + if (i386_set_ioperm(port, count, 1) < 0) + err(1, "i386_set_ioperm"); + + debug(D_PORT,"mapped I/O port: port=%#x count=%d\n", port, count); +} diff --git a/usr.bin/doscmd/doscmd.h b/usr.bin/doscmd/doscmd.h index 44d06c9f343f..8d5af631e5b5 100644 --- a/usr.bin/doscmd/doscmd.h +++ b/usr.bin/doscmd/doscmd.h @@ -150,7 +150,8 @@ extern int open_prog(char *name); extern void done(regcontext_t *REGS, int val); extern void quit(int); extern void call_on_quit(void (*)(void *), void *); - +extern void iomap_port(int port, int count); + /* signal.c */ extern struct sigframe *saved_sigframe; extern regcontext_t *saved_regcontext; @@ -288,4 +289,6 @@ void video_setborder(int); void outb_traceport(int, unsigned char); unsigned char inb_traceport(int); +void outb_port(int, unsigned char); +unsigned char inb_port(int); diff --git a/usr.bin/doscmd/port.c b/usr.bin/doscmd/port.c index 915932137750..fe5b5a86e215 100644 --- a/usr.bin/doscmd/port.c +++ b/usr.bin/doscmd/port.c @@ -158,6 +158,21 @@ inb_traceport(int port) return(byte); } +/* + * Real input/output to (hopefully) iomapped port + */ +void +outb_port(int port, unsigned char byte) +{ + out(port, byte); +} + +unsigned char +inb_port(int port) +{ + return in(port); +} + /* * Fake input/output ports */