Kyle Swenson | 8d8f654 | 2021-03-15 11:02:55 -0600 | [diff] [blame] | 1 | /************************************************************************ |
| 2 | * |
| 3 | * IONSP.H Definitions for I/O Networks Serial Protocol |
| 4 | * |
| 5 | * Copyright (C) 1997-1998 Inside Out Networks, Inc. |
| 6 | * |
| 7 | * This program is free software; you can redistribute it and/or modify |
| 8 | * it under the terms of the GNU General Public License as published by |
| 9 | * the Free Software Foundation; either version 2 of the License, or |
| 10 | * (at your option) any later version. |
| 11 | * |
| 12 | * These definitions are used by both kernel-mode driver and the |
| 13 | * peripheral firmware and MUST be kept in sync. |
| 14 | * |
| 15 | ************************************************************************/ |
| 16 | |
| 17 | /************************************************************************ |
| 18 | |
| 19 | The data to and from all ports on the peripheral is multiplexed |
| 20 | through a single endpoint pair (EP1 since it supports 64-byte |
| 21 | MaxPacketSize). Therefore, the data, commands, and status for |
| 22 | each port must be preceded by a short header identifying the |
| 23 | destination port. The header also identifies the bytes that follow |
| 24 | as data or as command/status info. |
| 25 | |
| 26 | Header format, first byte: |
| 27 | |
| 28 | CLLLLPPP |
| 29 | -------- |
| 30 | | | |------ Port Number: 0-7 |
| 31 | | |--------- Length: MSB bits of length |
| 32 | |----------- Data/Command: 0 = Data header |
| 33 | 1 = Cmd / Status (Cmd if OUT, Status if IN) |
| 34 | |
| 35 | This gives 2 possible formats: |
| 36 | |
| 37 | |
| 38 | Data header: 0LLLLPPP LLLLLLLL |
| 39 | ============ |
| 40 | |
| 41 | Where (LLLL,LLLLLLL) is 12-bit length of data that follows for |
| 42 | port number (PPP). The length is 0-based (0-FFF means 0-4095 |
| 43 | bytes). The ~4K limit allows the host driver (which deals in |
| 44 | transfer requests instead of individual packets) to write a |
| 45 | large chunk of data in a single request. Note, however, that |
| 46 | the length must always be <= the current TxCredits for a given |
| 47 | port due to buffering limitations on the peripheral. |
| 48 | |
| 49 | |
| 50 | Cmd/Status header: 1ccccPPP [ CCCCCCCC, Params ]... |
| 51 | ================== |
| 52 | |
| 53 | Where (cccc) or (cccc,CCCCCCCC) is the cmd or status identifier. |
| 54 | Frequently-used values are encoded as (cccc), longer ones using |
| 55 | (cccc,CCCCCCCC). Subsequent bytes are optional parameters and are |
| 56 | specific to the cmd or status code. This may include a length |
| 57 | for command and status codes that need variable-length parameters. |
| 58 | |
| 59 | |
| 60 | In addition, we use another interrupt pipe (endpoint) which the host polls |
| 61 | periodically for flow control information. The peripheral, when there has |
| 62 | been a change, sends the following 10-byte packet: |
| 63 | |
| 64 | RRRRRRRRRRRRRRRR |
| 65 | T0T0T0T0T0T0T0T0 |
| 66 | T1T1T1T1T1T1T1T1 |
| 67 | T2T2T2T2T2T2T2T2 |
| 68 | T3T3T3T3T3T3T3T3 |
| 69 | |
| 70 | The first field is the 16-bit RxBytesAvail field, which indicates the |
| 71 | number of bytes which may be read by the host from EP1. This is necessary: |
| 72 | (a) because OSR2.1 has a bug which causes data loss if the peripheral returns |
| 73 | fewer bytes than the host expects to read, and (b) because, on Microsoft |
| 74 | platforms at least, an outstanding read posted on EP1 consumes about 35% of |
| 75 | the CPU just polling the device for data. |
| 76 | |
| 77 | The next 4 fields are the 16-bit TxCredits for each port, which indicate how |
| 78 | many bytes the host is allowed to send on EP1 for transmit to a given port. |
| 79 | After an OPEN_PORT command, the Edgeport sends the initial TxCredits for that |
| 80 | port. |
| 81 | |
| 82 | All 16-bit fields are sent in little-endian (Intel) format. |
| 83 | |
| 84 | ************************************************************************/ |
| 85 | |
| 86 | // |
| 87 | // Define format of InterruptStatus packet returned from the |
| 88 | // Interrupt pipe |
| 89 | // |
| 90 | |
| 91 | struct int_status_pkt { |
| 92 | __u16 RxBytesAvail; // Additional bytes available to |
| 93 | // be read from Bulk IN pipe |
| 94 | __u16 TxCredits[MAX_RS232_PORTS]; // Additional space available in |
| 95 | // given port's TxBuffer |
| 96 | }; |
| 97 | |
| 98 | |
| 99 | #define GET_INT_STATUS_SIZE(NumPorts) (sizeof(__u16) + (sizeof(__u16) * (NumPorts))) |
| 100 | |
| 101 | |
| 102 | |
| 103 | // |
| 104 | // Define cmd/status header values and macros to extract them. |
| 105 | // |
| 106 | // Data: 0LLLLPPP LLLLLLLL |
| 107 | // Cmd/Stat: 1ccccPPP CCCCCCCC |
| 108 | |
| 109 | #define IOSP_DATA_HDR_SIZE 2 |
| 110 | #define IOSP_CMD_HDR_SIZE 2 |
| 111 | |
| 112 | #define IOSP_MAX_DATA_LENGTH 0x0FFF // 12 bits -> 4K |
| 113 | |
| 114 | #define IOSP_PORT_MASK 0x07 // Mask to isolate port number |
| 115 | #define IOSP_CMD_STAT_BIT 0x80 // If set, this is command/status header |
| 116 | |
| 117 | #define IS_CMD_STAT_HDR(Byte1) ((Byte1) & IOSP_CMD_STAT_BIT) |
| 118 | #define IS_DATA_HDR(Byte1) (!IS_CMD_STAT_HDR(Byte1)) |
| 119 | |
| 120 | #define IOSP_GET_HDR_PORT(Byte1) ((__u8) ((Byte1) & IOSP_PORT_MASK)) |
| 121 | #define IOSP_GET_HDR_DATA_LEN(Byte1, Byte2) ((__u16) (((__u16)((Byte1) & 0x78)) << 5) | (Byte2)) |
| 122 | #define IOSP_GET_STATUS_CODE(Byte1) ((__u8) (((Byte1) & 0x78) >> 3)) |
| 123 | |
| 124 | |
| 125 | // |
| 126 | // These macros build the 1st and 2nd bytes for a data header |
| 127 | // |
| 128 | #define IOSP_BUILD_DATA_HDR1(Port, Len) ((__u8) (((Port) | ((__u8) (((__u16) (Len)) >> 5) & 0x78)))) |
| 129 | #define IOSP_BUILD_DATA_HDR2(Port, Len) ((__u8) (Len)) |
| 130 | |
| 131 | |
| 132 | // |
| 133 | // These macros build the 1st and 2nd bytes for a command header |
| 134 | // |
| 135 | #define IOSP_BUILD_CMD_HDR1(Port, Cmd) ((__u8) (IOSP_CMD_STAT_BIT | (Port) | ((__u8) ((Cmd) << 3)))) |
| 136 | |
| 137 | |
| 138 | //-------------------------------------------------------------- |
| 139 | // |
| 140 | // Define values for commands and command parameters |
| 141 | // (sent from Host to Edgeport) |
| 142 | // |
| 143 | // 1ccccPPP P1P1P1P1 [ P2P2P2P2P2 ]... |
| 144 | // |
| 145 | // cccc: 00-07 2-byte commands. Write UART register 0-7 with |
| 146 | // value in P1. See 16650.H for definitions of |
| 147 | // UART register numbers and contents. |
| 148 | // |
| 149 | // 08-0B 3-byte commands: ==== P1 ==== ==== P2 ==== |
| 150 | // 08 available for expansion |
| 151 | // 09 1-param commands Command Code Param |
| 152 | // 0A available for expansion |
| 153 | // 0B available for expansion |
| 154 | // |
| 155 | // 0C-0D 4-byte commands. P1 = extended cmd and P2,P3 = params |
| 156 | // Currently unimplemented. |
| 157 | // |
| 158 | // 0E-0F N-byte commands: P1 = num bytes after P1 (ie, TotalLen - 2) |
| 159 | // P2 = extended cmd, P3..Pn = parameters. |
| 160 | // Currently unimplemented. |
| 161 | // |
| 162 | |
| 163 | #define IOSP_WRITE_UART_REG(n) ((n) & 0x07) // UartReg[ n ] := P1 |
| 164 | |
| 165 | // Register numbers and contents |
| 166 | // defined in 16554.H. |
| 167 | |
| 168 | // 0x08 // Available for expansion. |
| 169 | #define IOSP_EXT_CMD 0x09 // P1 = Command code (defined below) |
| 170 | |
| 171 | // P2 = Parameter |
| 172 | |
| 173 | // |
| 174 | // Extended Command values, used with IOSP_EXT_CMD, may |
| 175 | // or may not use parameter P2. |
| 176 | // |
| 177 | |
| 178 | #define IOSP_CMD_OPEN_PORT 0x00 // Enable ints, init UART. (NO PARAM) |
| 179 | #define IOSP_CMD_CLOSE_PORT 0x01 // Disable ints, flush buffers. (NO PARAM) |
| 180 | #define IOSP_CMD_CHASE_PORT 0x02 // Wait for Edgeport TX buffers to empty. (NO PARAM) |
| 181 | #define IOSP_CMD_SET_RX_FLOW 0x03 // Set Rx Flow Control in Edgeport |
| 182 | #define IOSP_CMD_SET_TX_FLOW 0x04 // Set Tx Flow Control in Edgeport |
| 183 | #define IOSP_CMD_SET_XON_CHAR 0x05 // Set XON Character in Edgeport |
| 184 | #define IOSP_CMD_SET_XOFF_CHAR 0x06 // Set XOFF Character in Edgeport |
| 185 | #define IOSP_CMD_RX_CHECK_REQ 0x07 // Request Edgeport to insert a Checkpoint into |
| 186 | |
| 187 | // the receive data stream (Parameter = 1 byte sequence number) |
| 188 | |
| 189 | #define IOSP_CMD_SET_BREAK 0x08 // Turn on the BREAK (LCR bit 6) |
| 190 | #define IOSP_CMD_CLEAR_BREAK 0x09 // Turn off the BREAK (LCR bit 6) |
| 191 | |
| 192 | |
| 193 | // |
| 194 | // Define macros to simplify building of IOSP cmds |
| 195 | // |
| 196 | |
| 197 | #define MAKE_CMD_WRITE_REG(ppBuf, pLen, Port, Reg, Val) \ |
| 198 | do { \ |
| 199 | (*(ppBuf))[0] = IOSP_BUILD_CMD_HDR1((Port), \ |
| 200 | IOSP_WRITE_UART_REG(Reg)); \ |
| 201 | (*(ppBuf))[1] = (Val); \ |
| 202 | \ |
| 203 | *ppBuf += 2; \ |
| 204 | *pLen += 2; \ |
| 205 | } while (0) |
| 206 | |
| 207 | #define MAKE_CMD_EXT_CMD(ppBuf, pLen, Port, ExtCmd, Param) \ |
| 208 | do { \ |
| 209 | (*(ppBuf))[0] = IOSP_BUILD_CMD_HDR1((Port), IOSP_EXT_CMD); \ |
| 210 | (*(ppBuf))[1] = (ExtCmd); \ |
| 211 | (*(ppBuf))[2] = (Param); \ |
| 212 | \ |
| 213 | *ppBuf += 3; \ |
| 214 | *pLen += 3; \ |
| 215 | } while (0) |
| 216 | |
| 217 | |
| 218 | |
| 219 | //-------------------------------------------------------------- |
| 220 | // |
| 221 | // Define format of flow control commands |
| 222 | // (sent from Host to Edgeport) |
| 223 | // |
| 224 | // 11001PPP FlowCmd FlowTypes |
| 225 | // |
| 226 | // Note that the 'FlowTypes' parameter is a bit mask; that is, |
| 227 | // more than one flow control type can be active at the same time. |
| 228 | // FlowTypes = 0 means 'no flow control'. |
| 229 | // |
| 230 | |
| 231 | // |
| 232 | // IOSP_CMD_SET_RX_FLOW |
| 233 | // |
| 234 | // Tells Edgeport how it can stop incoming UART data |
| 235 | // |
| 236 | // Example for Port 0 |
| 237 | // P0 = 11001000 |
| 238 | // P1 = IOSP_CMD_SET_RX_FLOW |
| 239 | // P2 = Bit mask as follows: |
| 240 | |
| 241 | #define IOSP_RX_FLOW_RTS 0x01 // Edgeport drops RTS to stop incoming data |
| 242 | #define IOSP_RX_FLOW_DTR 0x02 // Edgeport drops DTR to stop incoming data |
| 243 | #define IOSP_RX_FLOW_DSR_SENSITIVITY 0x04 // Ignores Rx data unless DSR high |
| 244 | |
| 245 | // Not currently implemented by firmware. |
| 246 | #define IOSP_RX_FLOW_XON_XOFF 0x08 // Edgeport sends XOFF char to stop incoming data. |
| 247 | |
| 248 | // Host must have previously programmed the |
| 249 | // XON/XOFF values with SET_XON/SET_XOFF |
| 250 | // before enabling this bit. |
| 251 | |
| 252 | // |
| 253 | // IOSP_CMD_SET_TX_FLOW |
| 254 | // |
| 255 | // Tells Edgeport what signal(s) will stop it from transmitting UART data |
| 256 | // |
| 257 | // Example for Port 0 |
| 258 | // P0 = 11001000 |
| 259 | // P1 = IOSP_CMD_SET_TX_FLOW |
| 260 | // P2 = Bit mask as follows: |
| 261 | |
| 262 | #define IOSP_TX_FLOW_CTS 0x01 // Edgeport stops Tx if CTS low |
| 263 | #define IOSP_TX_FLOW_DSR 0x02 // Edgeport stops Tx if DSR low |
| 264 | #define IOSP_TX_FLOW_DCD 0x04 // Edgeport stops Tx if DCD low |
| 265 | #define IOSP_TX_FLOW_XON_XOFF 0x08 // Edgeport stops Tx upon receiving XOFF char. |
| 266 | |
| 267 | // Host must have previously programmed the |
| 268 | // XON/XOFF values with SET_XON/SET_XOFF |
| 269 | // before enabling this bit. |
| 270 | #define IOSP_TX_FLOW_XOFF_CONTINUE 0x10 // If not set, Edgeport stops Tx when |
| 271 | |
| 272 | // sending XOFF in order to fix broken |
| 273 | // systems that interpret the next |
| 274 | // received char as XON. |
| 275 | // If set, Edgeport continues Tx |
| 276 | // normally after transmitting XOFF. |
| 277 | // Not currently implemented by firmware. |
| 278 | #define IOSP_TX_TOGGLE_RTS 0x20 // Edgeport drives RTS as a true half-duplex |
| 279 | |
| 280 | // Request-to-Send signal: it is raised before |
| 281 | // beginning transmission and lowered after |
| 282 | // the last Tx char leaves the UART. |
| 283 | // Not currently implemented by firmware. |
| 284 | |
| 285 | // |
| 286 | // IOSP_CMD_SET_XON_CHAR |
| 287 | // |
| 288 | // Sets the character which Edgeport transmits/interprets as XON. |
| 289 | // Note: This command MUST be sent before sending a SET_RX_FLOW or |
| 290 | // SET_TX_FLOW with the XON_XOFF bit set. |
| 291 | // |
| 292 | // Example for Port 0 |
| 293 | // P0 = 11001000 |
| 294 | // P1 = IOSP_CMD_SET_XON_CHAR |
| 295 | // P2 = 0x11 |
| 296 | |
| 297 | |
| 298 | // |
| 299 | // IOSP_CMD_SET_XOFF_CHAR |
| 300 | // |
| 301 | // Sets the character which Edgeport transmits/interprets as XOFF. |
| 302 | // Note: This command must be sent before sending a SET_RX_FLOW or |
| 303 | // SET_TX_FLOW with the XON_XOFF bit set. |
| 304 | // |
| 305 | // Example for Port 0 |
| 306 | // P0 = 11001000 |
| 307 | // P1 = IOSP_CMD_SET_XOFF_CHAR |
| 308 | // P2 = 0x13 |
| 309 | |
| 310 | |
| 311 | // |
| 312 | // IOSP_CMD_RX_CHECK_REQ |
| 313 | // |
| 314 | // This command is used to assist in the implementation of the |
| 315 | // IOCTL_SERIAL_PURGE Windows IOCTL. |
| 316 | // This IOSP command tries to place a marker at the end of the RX |
| 317 | // queue in the Edgeport. If the Edgeport RX queue is full then |
| 318 | // the Check will be discarded. |
| 319 | // It is up to the device driver to timeout waiting for the |
| 320 | // RX_CHECK_RSP. If a RX_CHECK_RSP is received, the driver is |
| 321 | // sure that all data has been received from the edgeport and |
| 322 | // may now purge any internal RX buffers. |
| 323 | // Note tat the sequence numbers may be used to detect lost |
| 324 | // CHECK_REQs. |
| 325 | |
| 326 | // Example for Port 0 |
| 327 | // P0 = 11001000 |
| 328 | // P1 = IOSP_CMD_RX_CHECK_REQ |
| 329 | // P2 = Sequence number |
| 330 | |
| 331 | |
| 332 | // Response will be: |
| 333 | // P1 = IOSP_EXT_RX_CHECK_RSP |
| 334 | // P2 = Request Sequence number |
| 335 | |
| 336 | |
| 337 | |
| 338 | //-------------------------------------------------------------- |
| 339 | // |
| 340 | // Define values for status and status parameters |
| 341 | // (received by Host from Edgeport) |
| 342 | // |
| 343 | // 1ssssPPP P1P1P1P1 [ P2P2P2P2P2 ]... |
| 344 | // |
| 345 | // ssss: 00-07 2-byte status. ssss identifies which UART register |
| 346 | // has changed value, and the new value is in P1. |
| 347 | // Note that the ssss values do not correspond to the |
| 348 | // 16554 register numbers given in 16554.H. Instead, |
| 349 | // see below for definitions of the ssss numbers |
| 350 | // used in this status message. |
| 351 | // |
| 352 | // 08-0B 3-byte status: ==== P1 ==== ==== P2 ==== |
| 353 | // 08 LSR_DATA: New LSR Errored byte |
| 354 | // 09 1-param responses Response Code Param |
| 355 | // 0A OPEN_RSP: InitialMsr TxBufferSize |
| 356 | // 0B available for expansion |
| 357 | // |
| 358 | // 0C-0D 4-byte status. P1 = extended status code and P2,P3 = params |
| 359 | // Not currently implemented. |
| 360 | // |
| 361 | // 0E-0F N-byte status: P1 = num bytes after P1 (ie, TotalLen - 2) |
| 362 | // P2 = extended status, P3..Pn = parameters. |
| 363 | // Not currently implemented. |
| 364 | // |
| 365 | |
| 366 | /**************************************************** |
| 367 | * SSSS values for 2-byte status messages (0-8) |
| 368 | ****************************************************/ |
| 369 | |
| 370 | #define IOSP_STATUS_LSR 0x00 // P1 is new value of LSR register. |
| 371 | |
| 372 | // Bits defined in 16554.H. Edgeport |
| 373 | // returns this in order to report |
| 374 | // line status errors (overrun, |
| 375 | // parity, framing, break). This form |
| 376 | // is used when a errored receive data |
| 377 | // character was NOT present in the |
| 378 | // UART when the LSR error occurred |
| 379 | // (ie, when LSR bit 0 = 0). |
| 380 | |
| 381 | #define IOSP_STATUS_MSR 0x01 // P1 is new value of MSR register. |
| 382 | |
| 383 | // Bits defined in 16554.H. Edgeport |
| 384 | // returns this in order to report |
| 385 | // changes in modem status lines |
| 386 | // (CTS, DSR, RI, CD) |
| 387 | // |
| 388 | |
| 389 | // 0x02 // Available for future expansion |
| 390 | // 0x03 // |
| 391 | // 0x04 // |
| 392 | // 0x05 // |
| 393 | // 0x06 // |
| 394 | // 0x07 // |
| 395 | |
| 396 | |
| 397 | /**************************************************** |
| 398 | * SSSS values for 3-byte status messages (8-A) |
| 399 | ****************************************************/ |
| 400 | |
| 401 | #define IOSP_STATUS_LSR_DATA 0x08 // P1 is new value of LSR register (same as STATUS_LSR) |
| 402 | |
| 403 | // P2 is errored character read from |
| 404 | // RxFIFO after LSR reported an error. |
| 405 | |
| 406 | #define IOSP_EXT_STATUS 0x09 // P1 is status/response code, param in P2. |
| 407 | |
| 408 | |
| 409 | // Response Codes (P1 values) for 3-byte status messages |
| 410 | |
| 411 | #define IOSP_EXT_STATUS_CHASE_RSP 0 // Reply to CHASE_PORT cmd. P2 is outcome: |
| 412 | #define IOSP_EXT_STATUS_CHASE_PASS 0 // P2 = 0: All Tx data drained successfully |
| 413 | #define IOSP_EXT_STATUS_CHASE_FAIL 1 // P2 = 1: Timed out (stuck due to flow |
| 414 | |
| 415 | // control from remote device). |
| 416 | |
| 417 | #define IOSP_EXT_STATUS_RX_CHECK_RSP 1 // Reply to RX_CHECK cmd. P2 is sequence number |
| 418 | |
| 419 | |
| 420 | #define IOSP_STATUS_OPEN_RSP 0x0A // Reply to OPEN_PORT cmd. |
| 421 | |
| 422 | // P1 is Initial MSR value |
| 423 | // P2 is encoded TxBuffer Size: |
| 424 | // TxBufferSize = (P2 + 1) * 64 |
| 425 | |
| 426 | // 0x0B // Available for future expansion |
| 427 | |
| 428 | #define GET_TX_BUFFER_SIZE(P2) (((P2) + 1) * 64) |
| 429 | |
| 430 | |
| 431 | |
| 432 | |
| 433 | /**************************************************** |
| 434 | * SSSS values for 4-byte status messages |
| 435 | ****************************************************/ |
| 436 | |
| 437 | #define IOSP_EXT4_STATUS 0x0C // Extended status code in P1, |
| 438 | |
| 439 | // Params in P2, P3 |
| 440 | // Currently unimplemented. |
| 441 | |
| 442 | // 0x0D // Currently unused, available. |
| 443 | |
| 444 | |
| 445 | |
| 446 | // |
| 447 | // Macros to parse status messages |
| 448 | // |
| 449 | |
| 450 | #define IOSP_GET_STATUS_LEN(code) ((code) < 8 ? 2 : ((code) < 0x0A ? 3 : 4)) |
| 451 | |
| 452 | #define IOSP_STATUS_IS_2BYTE(code) ((code) < 0x08) |
| 453 | #define IOSP_STATUS_IS_3BYTE(code) (((code) >= 0x08) && ((code) <= 0x0B)) |
| 454 | #define IOSP_STATUS_IS_4BYTE(code) (((code) >= 0x0C) && ((code) <= 0x0D)) |
| 455 | |