27 #include "../switchtec_priv.h" 32 #include <sys/types.h> 34 #include <sys/ioctl.h> 109 struct switchtec_uart{
110 struct switchtec_dev dev;
114 #define to_switchtec_uart(d) \ 115 ((struct switchtec_uart *) \ 116 ((char *)(d) - offsetof(struct switchtec_uart, dev))) 118 #define UART_MAX_WRITE_BYTES 100 119 #define UART_MAX_READ_BYTES 1024 121 #define SWITCHTEC_UART_BAUDRATE (B230400) 123 static int send_cmd(
int fd,
const char *fmt,
int write_bytes, ...)
133 va_start(argp, write_bytes);
136 write_data = va_arg(argp, uint8_t *);
137 write_crc = va_arg(argp, uint32_t);
140 cnt = vsnprintf(cmd,
sizeof(cmd), fmt, argp);
143 for (i = 0; i< write_bytes; i++) {
144 cnt += snprintf(cmd + cnt,
sizeof(cmd) - cnt,
145 "%02x", write_data[write_bytes - 1 - i]);
148 cnt += snprintf(cmd + cnt,
sizeof(cmd) - cnt,
149 " 0x%x\r", write_crc);
154 ret = write(fd, cmd, cnt);
166 static int read_resp_line(
int fd,
char *str)
172 ret = read(fd, str + cnt,
sizeof(str));
180 if (strrchr(str,
':') + 5 == strrchr(str,
'>'))
187 static int cli_control(
struct switchtec_dev *dev,
const char *str)
191 struct switchtec_uart *udev = to_switchtec_uart(dev);
193 ret = send_cmd(udev->fd, str, 0);
197 ret = read_resp_line(udev->fd, rtn);
205 #define __force __attribute__((force)) 210 static void uart_close(
struct switchtec_dev *dev)
212 struct switchtec_uart *udev = to_switchtec_uart(dev);
213 cli_control(dev,
"echo 1\r");
216 munmap((
void __force *)dev->gas_map,
219 flock(udev->fd, LOCK_UN);
224 static int map_gas(
struct switchtec_dev *dev)
227 dev->gas_map_size = 4 << 20;
229 addr = mmap(NULL, dev->gas_map_size,
230 PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
231 if (addr == MAP_FAILED)
234 dev->gas_map = (
gasptr_t __force)addr;
241 static gasptr_t uart_gas_map(
struct switchtec_dev *dev,
int writeable,
245 *map_size = dev->gas_map_size;
250 static void uart_gas_read(
struct switchtec_dev *dev,
void *dest,
251 const void __gas *src,
size_t n)
254 int raddr, rnum, rcrc;
257 struct switchtec_uart *udev = to_switchtec_uart(dev);
258 uint32_t addr = (uint32_t)(src - (
void __gas *)dev->gas_map);
261 char gas_rd_rtn[4096];
263 for (i = 0; i < RETRY_NUM; i++) {
264 ret = send_cmd(udev->fd,
"gasrd -c -s 0x%x %zu\r", 0, addr, n);
268 ret = read_resp_line(udev->fd, gas_rd_rtn);
273 if (strstr(gas_rd_rtn,
"No access beyond the Total GAS Section")){
274 memset(dest, 0xff, n);
278 if (strchr(gas_rd_rtn,
',')) {
279 if (sscanf(gas_rd_rtn,
280 "%*[^<]<0x%x> [%d Byte]%*[^,],%*[^:]: 0x" 282 &raddr, &rnum, &rcrc) != 3)
286 if (sscanf(gas_rd_rtn,
287 "%*[^<]<0x%x> [%d Byte]%*[^:]: 0x%x%*[^:]:",
288 &raddr, &rnum, &rcrc) != 3)
292 if ((raddr != addr) || (rnum != n))
295 pos = strchr(gas_rd_rtn,
']');
296 if (strchr(gas_rd_rtn,
','))
297 pos = strchr(gas_rd_rtn,
',') + strlen(
"not hit");
301 for (j = 0; j < n; j++)
302 *ptr++ = strtol(pos, &pos, 16);
304 addr = htobe32(addr);
305 cal = crc8((uint8_t *)&addr,
sizeof(addr), 0,
true);
306 cal = crc8(dest, n, cal,
false);
315 static void uart_memcpy_from_gas(
struct switchtec_dev *dev,
void *dest,
316 const void __gas *src,
size_t n)
321 cnt = n > UART_MAX_READ_BYTES? UART_MAX_READ_BYTES : n;
322 uart_gas_read(dev, dest, src, cnt);
329 #define create_gas_read(type, suffix) \ 330 static type uart_gas_read ## suffix(struct switchtec_dev *dev, \ 334 uart_gas_read(dev, &ret, addr, sizeof(ret)); \ 337 create_gas_read(uint8_t, 8);
338 create_gas_read(uint16_t, 16);
339 create_gas_read(uint32_t, 32);
340 create_gas_read(uint64_t, 64);
342 static void uart_gas_write(
struct switchtec_dev *dev,
void __gas *dest,
343 const void *src,
size_t n)
347 char gas_wr_rtn[4096];
350 struct switchtec_uart *udev = to_switchtec_uart(dev);
351 uint32_t addr = (uint32_t)(dest - (
void __gas *)dev->gas_map);
353 addr = htobe32(addr);
354 crc = crc8((uint8_t *)&addr,
sizeof(addr), 0,
true);
355 for (i = n; i > 0; i--)
356 crc = crc8((uint8_t *)src + i - 1,
sizeof(uint8_t), crc,
false);
358 addr = htobe32(addr);
359 for (i = 0; i < RETRY_NUM; i++) {
360 ret = send_cmd(udev->fd,
"gaswr -c -s 0x%x 0x",
365 ret = read_resp_line(udev->fd, gas_wr_rtn);
370 if (strstr(gas_wr_rtn,
"Error with gas_reg_write()"))
373 if (strchr(gas_wr_rtn,
',')) {
374 if (sscanf(gas_wr_rtn,
"%*[^,],%*[^:]: [0x%x/0x%x]%*[^:]:",
379 if (sscanf(gas_wr_rtn,
"%*[^:]: [0x%x/0x%x]%*[^:]:",
383 if ((exp == cal) && (cal == crc))
391 static void uart_memcpy_to_gas(
struct switchtec_dev *dev,
void __gas *dest,
392 const void *src,
size_t n)
397 cnt = n > UART_MAX_WRITE_BYTES ? UART_MAX_WRITE_BYTES : n;
398 uart_gas_write(dev, dest, src, cnt);
405 #define create_gas_write(type, suffix) \ 406 static void uart_gas_write ## suffix(struct switchtec_dev *dev, \ 407 type val, type __gas *addr) \ 409 uart_gas_write(dev, addr, &val, sizeof(type)); \ 412 create_gas_write(uint8_t, 8);
413 create_gas_write(uint16_t, 16);
414 create_gas_write(uint32_t, 32);
415 create_gas_write(uint64_t, 64);
417 static ssize_t uart_write_from_gas(
struct switchtec_dev *dev,
int fd,
418 const void __gas *src,
size_t n)
425 uart_memcpy_from_gas(dev, buf, src, n);
426 ret = write(fd, buf, n);
433 static const struct switchtec_ops uart_ops = {
434 .flags = SWITCHTEC_OPS_FLAG_NO_MFG,
437 .gas_map = uart_gas_map,
440 .get_device_id = gasop_get_device_id,
441 .get_fw_version = gasop_get_fw_version,
442 .pff_to_port = gasop_pff_to_port,
443 .port_to_pff = gasop_port_to_pff,
444 .flash_part = gasop_flash_part,
445 .event_summary = gasop_event_summary,
446 .event_ctl = gasop_event_ctl,
447 .event_wait_for = gasop_event_wait_for,
449 .gas_read8 = uart_gas_read8,
450 .gas_read16 = uart_gas_read16,
451 .gas_read32 = uart_gas_read32,
452 .gas_read64 = uart_gas_read64,
453 .gas_write8 = uart_gas_write8,
454 .gas_write16 = uart_gas_write16,
455 .gas_write32 = uart_gas_write32,
456 .gas_write32_no_retry = uart_gas_write32,
457 .gas_write64 = uart_gas_write64,
459 .memcpy_to_gas = uart_memcpy_to_gas,
460 .memcpy_from_gas = uart_memcpy_from_gas,
461 .write_from_gas = uart_write_from_gas,
464 static int set_uart_attribs(
int fd,
int speed,
int parity)
467 struct termios uart_attribs;
468 memset(&uart_attribs, 0,
sizeof(uart_attribs));
470 ret = tcgetattr(fd, &uart_attribs);
474 cfsetospeed(&uart_attribs, speed);
475 cfsetispeed(&uart_attribs, speed);
477 uart_attribs.c_iflag &= ~IGNBRK;
478 uart_attribs.c_iflag &= ~(IXON | IXOFF | IXANY);
479 uart_attribs.c_lflag = 0;
480 uart_attribs.c_oflag = 0;
481 uart_attribs.c_cflag = (uart_attribs.c_cflag & ~CSIZE) | CS8;
482 uart_attribs.c_cflag |= (CLOCAL | CREAD);
483 uart_attribs.c_cflag &= ~(PARENB | PARODD);
484 uart_attribs.c_cflag |= parity;
485 uart_attribs.c_cflag &= ~CSTOPB;
486 uart_attribs.c_cflag &= ~CRTSCTS;
487 uart_attribs.c_cc[VMIN] = 0;
488 uart_attribs.c_cc[VTIME] = 50;
490 ret = tcsetattr(fd, TCSANOW, &uart_attribs);
500 struct switchtec_uart *udev;
502 udev = malloc(
sizeof(*udev));
510 ret = flock(udev->fd, LOCK_EX | LOCK_NB);
514 ret = set_uart_attribs(udev->fd, SWITCHTEC_UART_BAUDRATE, 0);
518 ret = cli_control(&udev->dev,
"pscdbg 0 all\r");
522 ret = cli_control(&udev->dev,
"echo 0\r");
526 if (map_gas(&udev->dev))
529 udev->dev.ops = &uart_ops;
530 gasop_set_partition_info(&udev->dev);
__gas struct switchtec_gas * gasptr_t
Shortform for a pointer to the GAS register space.
struct switchtec_dev * switchtec_open_uart(int fd)
Open a switchtec device behind a uart device.