|
Lines 82-87
Link Here
|
| 82 |
#include <machine/resource.h> |
82 |
#include <machine/resource.h> |
| 83 |
|
83 |
|
| 84 |
#include <isa/sioreg.h> |
84 |
#include <isa/sioreg.h> |
|
|
85 |
#include <isa/siovar.h> |
| 85 |
|
86 |
|
| 86 |
#ifdef COM_ESP |
87 |
#ifdef COM_ESP |
| 87 |
#include <isa/ic/esp.h> |
88 |
#include <isa/ic/esp.h> |
|
Lines 167-279
Link Here
|
| 167 |
"tty-level buffer overflow", |
168 |
"tty-level buffer overflow", |
| 168 |
}; |
169 |
}; |
| 169 |
|
170 |
|
| 170 |
#define CE_NTYPES 3 |
|
|
| 171 |
#define CE_RECORD(com, errnum) (++(com)->delta_error_counts[errnum]) |
171 |
#define CE_RECORD(com, errnum) (++(com)->delta_error_counts[errnum]) |
| 172 |
|
172 |
|
| 173 |
/* types. XXX - should be elsewhere */ |
|
|
| 174 |
typedef u_int Port_t; /* hardware port */ |
| 175 |
typedef u_char bool_t; /* boolean */ |
| 176 |
|
| 177 |
/* queue of linear buffers */ |
| 178 |
struct lbq { |
| 179 |
u_char *l_head; /* next char to process */ |
| 180 |
u_char *l_tail; /* one past the last char to process */ |
| 181 |
struct lbq *l_next; /* next in queue */ |
| 182 |
bool_t l_queued; /* nonzero if queued */ |
| 183 |
}; |
| 184 |
|
| 185 |
/* com device structure */ |
| 186 |
struct com_s { |
| 187 |
u_int flags; /* Copy isa device flags */ |
| 188 |
u_char state; /* miscellaneous flag bits */ |
| 189 |
bool_t active_out; /* nonzero if the callout device is open */ |
| 190 |
u_char cfcr_image; /* copy of value written to CFCR */ |
| 191 |
#ifdef COM_ESP |
| 192 |
bool_t esp; /* is this unit a hayes esp board? */ |
| 193 |
#endif |
| 194 |
u_char extra_state; /* more flag bits, separate for order trick */ |
| 195 |
u_char fifo_image; /* copy of value written to FIFO */ |
| 196 |
bool_t hasfifo; /* nonzero for 16550 UARTs */ |
| 197 |
bool_t st16650a; /* Is a Startech 16650A or RTS/CTS compat */ |
| 198 |
bool_t loses_outints; /* nonzero if device loses output interrupts */ |
| 199 |
u_char mcr_image; /* copy of value written to MCR */ |
| 200 |
#ifdef COM_MULTIPORT |
| 201 |
bool_t multiport; /* is this unit part of a multiport device? */ |
| 202 |
#endif /* COM_MULTIPORT */ |
| 203 |
bool_t no_irq; /* nonzero if irq is not attached */ |
| 204 |
bool_t gone; /* hardware disappeared */ |
| 205 |
bool_t poll; /* nonzero if polling is required */ |
| 206 |
bool_t poll_output; /* nonzero if polling for output is required */ |
| 207 |
int unit; /* unit number */ |
| 208 |
int dtr_wait; /* time to hold DTR down on close (* 1/hz) */ |
| 209 |
u_int tx_fifo_size; |
| 210 |
u_int wopeners; /* # processes waiting for DCD in open() */ |
| 211 |
|
| 212 |
/* |
| 213 |
* The high level of the driver never reads status registers directly |
| 214 |
* because there would be too many side effects to handle conveniently. |
| 215 |
* Instead, it reads copies of the registers stored here by the |
| 216 |
* interrupt handler. |
| 217 |
*/ |
| 218 |
u_char last_modem_status; /* last MSR read by intr handler */ |
| 219 |
u_char prev_modem_status; /* last MSR handled by high level */ |
| 220 |
|
| 221 |
u_char hotchar; /* ldisc-specific char to be handled ASAP */ |
| 222 |
u_char *ibuf; /* start of input buffer */ |
| 223 |
u_char *ibufend; /* end of input buffer */ |
| 224 |
u_char *ibufold; /* old input buffer, to be freed */ |
| 225 |
u_char *ihighwater; /* threshold in input buffer */ |
| 226 |
u_char *iptr; /* next free spot in input buffer */ |
| 227 |
int ibufsize; /* size of ibuf (not include error bytes) */ |
| 228 |
int ierroff; /* offset of error bytes in ibuf */ |
| 229 |
|
| 230 |
struct lbq obufq; /* head of queue of output buffers */ |
| 231 |
struct lbq obufs[2]; /* output buffers */ |
| 232 |
|
| 233 |
Port_t data_port; /* i/o ports */ |
| 234 |
#ifdef COM_ESP |
| 235 |
Port_t esp_port; |
| 236 |
#endif |
| 237 |
Port_t int_id_port; |
| 238 |
Port_t iobase; |
| 239 |
Port_t modem_ctl_port; |
| 240 |
Port_t line_status_port; |
| 241 |
Port_t modem_status_port; |
| 242 |
Port_t intr_ctl_port; /* Ports of IIR register */ |
| 243 |
|
| 244 |
struct tty *tp; /* cross reference */ |
| 245 |
|
| 246 |
/* Initial state. */ |
| 247 |
struct termios it_in; /* should be in struct tty */ |
| 248 |
struct termios it_out; |
| 249 |
|
| 250 |
/* Lock state. */ |
| 251 |
struct termios lt_in; /* should be in struct tty */ |
| 252 |
struct termios lt_out; |
| 253 |
|
| 254 |
bool_t do_timestamp; |
| 255 |
bool_t do_dcd_timestamp; |
| 256 |
struct timeval timestamp; |
| 257 |
struct timeval dcd_timestamp; |
| 258 |
struct pps_state pps; |
| 259 |
|
| 260 |
u_long bytes_in; /* statistics */ |
| 261 |
u_long bytes_out; |
| 262 |
u_int delta_error_counts[CE_NTYPES]; |
| 263 |
u_long error_counts[CE_NTYPES]; |
| 264 |
|
| 265 |
struct resource *irqres; |
| 266 |
struct resource *ioportres; |
| 267 |
void *cookie; |
| 268 |
|
| 269 |
/* |
| 270 |
* Data area for output buffers. Someday we should build the output |
| 271 |
* buffer queue without copying data. |
| 272 |
*/ |
| 273 |
u_char obuf1[256]; |
| 274 |
u_char obuf2[256]; |
| 275 |
}; |
| 276 |
|
| 277 |
#ifdef COM_ESP |
173 |
#ifdef COM_ESP |
| 278 |
static int espattach __P((struct com_s *com, Port_t esp_port)); |
174 |
static int espattach __P((struct com_s *com, Port_t esp_port)); |
| 279 |
#endif |
175 |
#endif |
|
Lines 284-290
Link Here
|
| 284 |
static timeout_t siodtrwakeup; |
180 |
static timeout_t siodtrwakeup; |
| 285 |
static void comhardclose __P((struct com_s *com)); |
181 |
static void comhardclose __P((struct com_s *com)); |
| 286 |
static void sioinput __P((struct com_s *com)); |
182 |
static void sioinput __P((struct com_s *com)); |
| 287 |
static void siointr1 __P((struct com_s *com)); |
|
|
| 288 |
static void siointr __P((void *arg)); |
183 |
static void siointr __P((void *arg)); |
| 289 |
static int commctl __P((struct com_s *com, int bits, int how)); |
184 |
static int commctl __P((struct com_s *com, int bits, int how)); |
| 290 |
static int comparam __P((struct tty *tp, struct termios *t)); |
185 |
static int comparam __P((struct tty *tp, struct termios *t)); |
|
Lines 309-316
Link Here
|
| 309 |
|
204 |
|
| 310 |
/* table and macro for fast conversion from a unit number to its com struct */ |
205 |
/* table and macro for fast conversion from a unit number to its com struct */ |
| 311 |
static devclass_t sio_devclass; |
206 |
static devclass_t sio_devclass; |
| 312 |
#define com_addr(unit) ((struct com_s *) \ |
207 |
static struct com_s *p_com_addr[SIO_MAXUNITS]; |
| 313 |
devclass_get_softc(sio_devclass, unit)) |
208 |
#define com_addr(unit) (p_com_addr[unit]) |
| 314 |
|
209 |
|
| 315 |
static device_method_t sio_isa_methods[] = { |
210 |
static device_method_t sio_isa_methods[] = { |
| 316 |
/* Device interface */ |
211 |
/* Device interface */ |
|
Lines 969-1000
Link Here
|
| 969 |
return (sioattach(dev)); |
864 |
return (sioattach(dev)); |
| 970 |
} |
865 |
} |
| 971 |
|
866 |
|
| 972 |
static int |
867 |
int |
| 973 |
sioattach(dev) |
868 |
sio_attach_unit(com, unit, iobase, flags, no_irq) |
| 974 |
device_t dev; |
|
|
| 975 |
{ |
| 976 |
struct com_s *com; |
869 |
struct com_s *com; |
|
|
870 |
int unit; |
| 871 |
Port_t iobase; |
| 872 |
u_int flags; |
| 873 |
bool_t no_irq; |
| 874 |
{ |
| 977 |
#ifdef COM_ESP |
875 |
#ifdef COM_ESP |
| 978 |
Port_t *espp; |
876 |
Port_t *espp; |
| 979 |
#endif |
877 |
#endif |
| 980 |
Port_t iobase; |
878 |
if (unit >= SIO_MAXUNITS) |
| 981 |
int unit; |
879 |
return ENXIO; |
| 982 |
u_int flags; |
|
|
| 983 |
int rid; |
| 984 |
struct resource *port; |
| 985 |
int ret; |
| 986 |
|
| 987 |
rid = 0; |
| 988 |
port = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, |
| 989 |
0, ~0, IO_COMSIZE, RF_ACTIVE); |
| 990 |
if (!port) |
| 991 |
return (ENXIO); |
| 992 |
|
| 993 |
iobase = rman_get_start(port); |
| 994 |
unit = device_get_unit(dev); |
| 995 |
com = device_get_softc(dev); |
| 996 |
flags = device_get_flags(dev); |
| 997 |
|
| 998 |
if (unit >= sio_numunits) |
880 |
if (unit >= sio_numunits) |
| 999 |
sio_numunits = unit + 1; |
881 |
sio_numunits = unit + 1; |
| 1000 |
/* |
882 |
/* |
|
Lines 1011-1021
Link Here
|
| 1011 |
*/ |
893 |
*/ |
| 1012 |
bzero(com, sizeof *com); |
894 |
bzero(com, sizeof *com); |
| 1013 |
com->unit = unit; |
895 |
com->unit = unit; |
| 1014 |
com->ioportres = port; |
|
|
| 1015 |
com->cfcr_image = CFCR_8BITS; |
896 |
com->cfcr_image = CFCR_8BITS; |
| 1016 |
com->dtr_wait = 3 * hz; |
897 |
com->dtr_wait = 3 * hz; |
| 1017 |
com->loses_outints = COM_LOSESOUTINTS(flags) != 0; |
898 |
com->loses_outints = COM_LOSESOUTINTS(flags) != 0; |
| 1018 |
com->no_irq = bus_get_resource(dev, SYS_RES_IRQ, 0, NULL, NULL) != 0; |
899 |
com->no_irq = no_irq; |
| 1019 |
com->tx_fifo_size = 1; |
900 |
com->tx_fifo_size = 1; |
| 1020 |
com->obufs[0].l_head = com->obuf1; |
901 |
com->obufs[0].l_head = com->obuf1; |
| 1021 |
com->obufs[1].l_head = com->obuf2; |
902 |
com->obufs[1].l_head = com->obuf2; |
|
Lines 1052-1063
Link Here
|
| 1052 |
com->it_in.c_ispeed = com->it_in.c_ospeed = TTYDEF_SPEED; |
933 |
com->it_in.c_ispeed = com->it_in.c_ospeed = TTYDEF_SPEED; |
| 1053 |
if (siosetwater(com, com->it_in.c_ispeed) != 0) { |
934 |
if (siosetwater(com, com->it_in.c_ispeed) != 0) { |
| 1054 |
enable_intr(); |
935 |
enable_intr(); |
| 1055 |
/* |
|
|
| 1056 |
* Leave i/o resources allocated if this is a `cn'-level |
| 1057 |
* console, so that other devices can't snarf them. |
| 1058 |
*/ |
| 1059 |
if (iobase != siocniobase) |
| 1060 |
bus_release_resource(dev, SYS_RES_IOPORT, rid, port); |
| 1061 |
return (ENOMEM); |
936 |
return (ENOMEM); |
| 1062 |
} |
937 |
} |
| 1063 |
enable_intr(); |
938 |
enable_intr(); |
|
Lines 1164-1180
Link Here
|
| 1164 |
|
1039 |
|
| 1165 |
#ifdef COM_MULTIPORT |
1040 |
#ifdef COM_MULTIPORT |
| 1166 |
if (COM_ISMULTIPORT(flags)) { |
1041 |
if (COM_ISMULTIPORT(flags)) { |
| 1167 |
device_t masterdev; |
|
|
| 1168 |
|
| 1169 |
com->multiport = TRUE; |
1042 |
com->multiport = TRUE; |
| 1170 |
printf(" (multiport"); |
1043 |
printf(" (multiport"); |
| 1171 |
if (unit == COM_MPMASTER(flags)) |
1044 |
if (unit == COM_MPMASTER(flags)) |
| 1172 |
printf(" master"); |
1045 |
printf(" master"); |
| 1173 |
printf(")"); |
1046 |
printf(")"); |
| 1174 |
masterdev = devclass_get_device(sio_devclass, |
|
|
| 1175 |
COM_MPMASTER(flags)); |
| 1176 |
com->no_irq = (masterdev == NULL || bus_get_resource(masterdev, |
| 1177 |
SYS_RES_IRQ, 0, NULL, NULL) != 0); |
| 1178 |
} |
1047 |
} |
| 1179 |
#endif /* COM_MULTIPORT */ |
1048 |
#endif /* COM_MULTIPORT */ |
| 1180 |
if (unit == comconsole) |
1049 |
if (unit == comconsole) |
|
Lines 1183-1188
Link Here
|
| 1183 |
printf(" with a bogus IIR_TXRDY register"); |
1052 |
printf(" with a bogus IIR_TXRDY register"); |
| 1184 |
printf("\n"); |
1053 |
printf("\n"); |
| 1185 |
|
1054 |
|
|
|
1055 |
com_addr(unit) = com; |
| 1056 |
|
| 1186 |
if (!sio_registered) { |
1057 |
if (!sio_registered) { |
| 1187 |
register_swi(SWI_TTY, siopoll); |
1058 |
register_swi(SWI_TTY, siopoll); |
| 1188 |
sio_registered = TRUE; |
1059 |
sio_registered = TRUE; |
|
Lines 1203-1208
Link Here
|
| 1203 |
com->pps.ppscap = PPS_CAPTUREASSERT | PPS_CAPTURECLEAR; |
1074 |
com->pps.ppscap = PPS_CAPTUREASSERT | PPS_CAPTURECLEAR; |
| 1204 |
pps_init(&com->pps); |
1075 |
pps_init(&com->pps); |
| 1205 |
|
1076 |
|
|
|
1077 |
return (0); |
| 1078 |
} |
| 1079 |
|
| 1080 |
static int |
| 1081 |
sioattach(dev) |
| 1082 |
device_t dev; |
| 1083 |
{ |
| 1084 |
int rid, ret, no_irq; |
| 1085 |
struct resource *port; |
| 1086 |
struct com_s *com; |
| 1087 |
Port_t iobase; |
| 1088 |
u_int flags; |
| 1089 |
|
| 1090 |
rid = 0; |
| 1091 |
port = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, |
| 1092 |
0, ~0, IO_COMSIZE, RF_ACTIVE); |
| 1093 |
if (!port) |
| 1094 |
return (ENXIO); |
| 1095 |
|
| 1096 |
iobase = rman_get_start(port); |
| 1097 |
com = device_get_softc(dev); |
| 1098 |
flags = device_get_flags(dev); |
| 1099 |
|
| 1100 |
#ifdef COM_MULTIPORT |
| 1101 |
if (COM_ISMULTIPORT(flags)) { |
| 1102 |
device_t masterdev; |
| 1103 |
|
| 1104 |
masterdev = devclass_get_device(sio_devclass, |
| 1105 |
COM_MPMASTER(flags)); |
| 1106 |
no_irq = (masterdev == NULL || bus_get_resource(masterdev, |
| 1107 |
SYS_RES_IRQ, 0, NULL, NULL) != 0); |
| 1108 |
} else |
| 1109 |
#endif /* COM_MULTIPORT */ |
| 1110 |
no_irq = bus_get_resource(dev, SYS_RES_IRQ, 0, NULL, NULL) != 0; |
| 1111 |
|
| 1112 |
ret = sio_attach_unit(com, device_get_unit(dev), iobase, flags, no_irq); |
| 1113 |
if (ret != 0) { |
| 1114 |
/* Leave i/o resources allocated if this is a `cn'-level |
| 1115 |
* console, so that other devices can't snarf them. */ |
| 1116 |
if (iobase != siocniobase) |
| 1117 |
bus_release_resource(dev, SYS_RES_IOPORT, rid, port); |
| 1118 |
return ret; |
| 1119 |
} |
| 1120 |
|
| 1206 |
rid = 0; |
1121 |
rid = 0; |
| 1207 |
com->irqres = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 0ul, ~0ul, 1, |
1122 |
com->irqres = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 0ul, ~0ul, 1, |
| 1208 |
RF_ACTIVE); |
1123 |
RF_ACTIVE); |
|
Lines 1220-1227
Link Here
|
| 1220 |
if (ret) |
1135 |
if (ret) |
| 1221 |
device_printf(dev, "could not activate interrupt\n"); |
1136 |
device_printf(dev, "could not activate interrupt\n"); |
| 1222 |
} |
1137 |
} |
| 1223 |
|
1138 |
com->ioportres = port; |
| 1224 |
return (0); |
1139 |
return 0; |
| 1225 |
} |
1140 |
} |
| 1226 |
|
1141 |
|
| 1227 |
static int |
1142 |
static int |
|
Lines 1713-1719
Link Here
|
| 1713 |
#endif /* COM_MULTIPORT */ |
1628 |
#endif /* COM_MULTIPORT */ |
| 1714 |
} |
1629 |
} |
| 1715 |
|
1630 |
|
| 1716 |
static void |
1631 |
void |
| 1717 |
siointr1(com) |
1632 |
siointr1(com) |
| 1718 |
struct com_s *com; |
1633 |
struct com_s *com; |
| 1719 |
{ |
1634 |
{ |