blob: 04e15a846d7308fe01309b0aed1266f22ac65b14 [file] [log] [blame]
Urja Rannikko22915352009-06-23 11:33:43 +00001/*
2 * This file is part of the flashrom project.
3 *
4 * Copyright (C) 2009 Urja Rannikko <urjaman@gmail.com>
5 * Copyright (C) 2009 Carl-Daniel Hailfinger
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 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21
22#include <string.h>
23#include <stdlib.h>
24#include <ctype.h>
25#include <fcntl.h>
26#include <sys/types.h>
27#include <sys/socket.h>
28#include <arpa/inet.h>
29#include <netinet/in.h>
30#include <netinet/tcp.h>
31#include <netdb.h>
32#include <sys/stat.h>
33#include <errno.h>
34#include <stdio.h>
35#include <unistd.h>
36#include <inttypes.h>
37#include <termios.h>
38#include "flash.h"
39
40char *serprog_param = NULL;
41
Urja Rannikko22915352009-06-23 11:33:43 +000042#if SERPROG_SUPPORT == 1
Urja Rannikkof3196df2009-07-21 13:02:59 +000043
44#define MSGHEADER "serprog:"
45
46#define S_ACK 0x06
47#define S_NAK 0x15
48#define S_CMD_NOP 0x00 /* No operation */
49#define S_CMD_Q_IFACE 0x01 /* Query interface version */
50#define S_CMD_Q_CMDMAP 0x02 /* Query supported commands bitmap */
51#define S_CMD_Q_PGMNAME 0x03 /* Query programmer name */
52#define S_CMD_Q_SERBUF 0x04 /* Query Serial Buffer Size */
53#define S_CMD_Q_BUSTYPE 0x05 /* Query supported bustypes */
54#define S_CMD_Q_CHIPSIZE 0x06 /* Query supported chipsize (2^n format) */
55#define S_CMD_Q_OPBUF 0x07 /* Query operation buffer size */
56#define S_CMD_Q_WRNMAXLEN 0x08 /* Query opbuf-write-N maximum lenght */
57#define S_CMD_R_BYTE 0x09 /* Read a single byte */
58#define S_CMD_R_NBYTES 0x0A /* Read n bytes */
59#define S_CMD_O_INIT 0x0B /* Initialize operation buffer */
60#define S_CMD_O_WRITEB 0x0C /* Write opbuf: Write byte with address */
61#define S_CMD_O_WRITEN 0x0D /* Write to opbuf: Write-N */
62#define S_CMD_O_DELAY 0x0E /* Write opbuf: udelay */
63#define S_CMD_O_EXEC 0x0F /* Execute operation buffer */
64#define S_CMD_SYNCNOP 0x10 /* Special no-operation that returns NAK+ACK */
65#define S_CMD_Q_RDNMAXLEN 0x11 /* Query read-n maximum length */
66#define S_CMD_S_BUSTYPE 0x12 /* Set used bustype(s). */
67
68static int sp_fd;
69
70static uint16_t sp_device_serbuf_size = 16;
71static uint16_t sp_device_opbuf_size = 300;
72/* Bitmap of supported commands */
73static uint8_t sp_cmdmap[32];
74
75/* sp_prev_was_write used to detect writes with continouous addresses
76 and combine them to write-n's */
77static int sp_prev_was_write = 0;
78/* sp_write_n_addr used as the starting addr of the currently
79 combined write-n operation */
80static uint32_t sp_write_n_addr;
81/* The maximum length of an write_n operation; 0 = write-n not supported */
82static uint32_t sp_max_write_n = 0;
83/* The maximum length of a read_n operation; 0 = 2^24 */
84static uint32_t sp_max_read_n = 0;
85
86/* A malloc'd buffer for combining the operation's data
87 and a counter that tells how much data is there. */
88static uint8_t *sp_write_n_buf;
89static uint32_t sp_write_n_bytes = 0;
90
91/* sp_streamed_* used for flow control checking */
92static int sp_streamed_transmit_ops = 0;
93static int sp_streamed_transmit_bytes = 0;
94
95/* sp_opbuf_usage used for counting the amount of
96 on-device operation buffer used */
97static int sp_opbuf_usage = 0;
98/* if true causes sp_docommand to automatically check
99 whether the command is supported before doing it */
100static int sp_check_avail_automatic = 0;
101
102static void sp_die(char *msg)
103{
104 perror(msg);
105 exit(1);
106}
107
108static int sp_opensocket(char *ip, unsigned int port)
109{
110 int flag = 1;
111 struct hostent *hostPtr = NULL;
112 struct sockaddr_in sp;
113 int sock;
114 printf_debug(MSGHEADER "IP %s port %d\n", ip, port);
115 sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
116 if (sock < 0)
117 sp_die("Error: serprog cannot open socket");
118 hostPtr = gethostbyname(ip);
119 if (NULL == hostPtr) {
120 hostPtr = gethostbyaddr(ip, strlen(ip), AF_INET);
121 if (NULL == hostPtr)
122 sp_die("Error: cannot resolve");
123 }
124 memset(&sp, 0, sizeof(sp));
125 sp.sin_family = AF_INET;
126 sp.sin_port = htons(port);
127 (void)memcpy(&sp.sin_addr, hostPtr->h_addr, hostPtr->h_length);
128 if (connect(sock, (struct sockaddr *)&sp, sizeof(sp)) < 0) {
129 close(sock);
130 sp_die("Error: serprog cannot connect");
131 }
132 /* We are latency limited, and sometimes do write-write-read *
133 * (write-n) - so enable TCP_NODELAY. */
134 setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, &flag, sizeof(int));
135 return sock;
136}
137
138struct baudentry {
139 int flag;
140 unsigned int baud;
141};
142
143/* I'd like if the C preprocessor could have directives in macros */
144#define BAUDENTRY(baud) { B##baud, baud },
145static const struct baudentry sp_baudtable[] = {
146 BAUDENTRY(9600)
147 BAUDENTRY(19200)
148 BAUDENTRY(38400)
149 BAUDENTRY(57600)
150 BAUDENTRY(115200)
151#ifdef B230400
152 BAUDENTRY(230400)
153#endif
154#ifdef B460800
155 BAUDENTRY(460800)
156#endif
157#ifdef B500000
158 BAUDENTRY(500000)
159#endif
160#ifdef B576000
161 BAUDENTRY(576000)
162#endif
163#ifdef B921600
164 BAUDENTRY(921600)
165#endif
166#ifdef B1000000
167 BAUDENTRY(1000000)
168#endif
169#ifdef B1152000
170 BAUDENTRY(1152000)
171#endif
172#ifdef B1500000
173 BAUDENTRY(1500000)
174#endif
175#ifdef B2000000
176 BAUDENTRY(2000000)
177#endif
178#ifdef B2500000
179 BAUDENTRY(2500000)
180#endif
181#ifdef B3000000
182 BAUDENTRY(3000000)
183#endif
184#ifdef B3500000
185 BAUDENTRY(3500000)
186#endif
187#ifdef B4000000
188 BAUDENTRY(4000000)
189#endif
190 {0, 0} /* Terminator */
191};
192
193static int sp_openserport(char *dev, unsigned int baud)
194{
195 struct termios options;
196 int fd, i;
197 fd = open(dev, O_RDWR | O_NOCTTY | O_NDELAY);
198 if (fd < 0)
199 sp_die("Error: cannot open serial port");
200 fcntl(fd, F_SETFL, 0);
201 tcgetattr(fd, &options);
202 for (i = 0;; i++) {
203 if (sp_baudtable[i].baud == 0) {
204 close(fd);
205 fprintf(stderr,
206 "Error: cannot configure for baudrate %d\n",
207 baud);
208 exit(1);
209 }
210 if (sp_baudtable[i].baud == baud) {
211 cfsetispeed(&options, sp_baudtable[i].flag);
212 cfsetospeed(&options, sp_baudtable[i].flag);
213 break;
214 }
215 }
216 options.c_cflag &= ~PARENB;
217 options.c_cflag &= ~CSTOPB;
218 options.c_cflag &= ~CSIZE;
219 options.c_cflag |= CS8;
220 options.c_cflag &= ~CRTSCTS;
221 options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
222 options.c_iflag &= ~(IXON | IXOFF | IXANY | ICRNL | IGNCR | INLCR);
223 options.c_oflag &= ~OPOST;
224 options.c_cflag |= (CLOCAL | CREAD);
225 tcsetattr(fd, TCSANOW, &options);
226 return fd;
227}
228
229static void sp_flush_incoming(void)
230{
231 int i;
232 for (i=0;i<100;i++) { /* In case the device doesnt do EAGAIN, just read 0 */
233 unsigned char flush[16];
234 ssize_t rv;
235 rv = read(sp_fd, flush, sizeof(flush));
236 if ((rv == -1) && (errno == EAGAIN))
237 break;
238 if (rv == -1)
239 sp_die("flush read");
240 }
241 return;
242}
243
244static int sp_sync_read_timeout(int loops)
245{
246 int i;
247 unsigned char c;
248 for (i = 0; i < loops; i++) {
249 ssize_t rv;
250 rv = read(sp_fd, &c, 1);
251 if (rv == 1)
252 return c;
253 if ((rv == -1) && (errno != EAGAIN))
254 sp_die("read");
255 usleep(10 * 1000); /* 10ms units */
256 }
257 return -1;
258}
259
260/* Synchronize: a bit tricky algorhytm that tries to (and in my tests has *
261 * always succeeded in) bring the serial protocol to known waiting-for- *
262 * command state - uses nonblocking read - rest of the driver uses *
263 * blocking read - TODO: add an alarm() timer for the rest of the app on *
264 * serial operations, though not such a big issue as the first thing to *
265 * do is synchronize (eg. check that device is alive). */
266static void sp_synchronize(void)
267{
268 int i;
269 int flags = fcntl(sp_fd, F_GETFL);
270 unsigned char buf[8];
271 flags |= O_NONBLOCK;
272 fcntl(sp_fd, F_SETFL, flags);
273 /* First sends 8 NOPs, then flushes the return data - should cause *
274 * the device serial parser to get to a sane state, unless if it *
275 * is waiting for a real long write-n. */
276 memset(buf, S_CMD_NOP, 8);
277 if (write(sp_fd, buf, 8) != 8)
278 sp_die("flush write");
279 /* A second should be enough to get all the answers to the buffer */
280 usleep(1000 * 1000);
281 sp_flush_incoming();
282
283 /* Then try upto 8 times to send syncnop and get the correct special *
284 * return of NAK+ACK. Timing note: upto 10 characters, 10*50ms = *
285 * upto 500ms per try, 8*0.5s = 4s; +1s (above) = upto 5s sync *
286 * attempt, ~1s if immediate success. */
287 for (i = 0; i < 8; i++) {
288 int n;
289 unsigned char c = S_CMD_SYNCNOP;
290 if (write(sp_fd, &c, 1) != 1)
291 sp_die("sync write");
292 printf_debug(".");
293 fflush(stdout);
294 for (n = 0; n < 10; n++) {
295 c = sp_sync_read_timeout(5); /* wait upto 50ms */
296 if (c != S_NAK)
297 continue;
298 c = sp_sync_read_timeout(2);
299 if (c != S_ACK)
300 continue;
301 c = S_CMD_SYNCNOP;
302 if (write(sp_fd, &c, 1) != 1)
303 sp_die("sync write");
304 c = sp_sync_read_timeout(50);
305 if (c != S_NAK)
306 break; /* fail */
307 c = sp_sync_read_timeout(10);
308 if (c != S_ACK)
309 break; /* fail */
310 /* Ok, synchronized; back to blocking reads and return. */
311 flags &= ~O_NONBLOCK;
312 fcntl(sp_fd, F_SETFL, flags);
313 printf_debug("\n");
314 return;
315 }
316 }
317 fprintf(stderr,
318 "Error: cannot synchronize protocol\n"
319 "- check communications and reset device?\n");
320 exit(1);
321}
322
323static int sp_check_commandavail(uint8_t command)
324{
325 int byteoffs, bitoffs;
326 byteoffs = command / 8;
327 bitoffs = command % 8;
328 return (sp_cmdmap[byteoffs] & (1 << bitoffs)) ? 1 : 0;
329}
330
331static int sp_automatic_cmdcheck(uint8_t cmd)
332{
333 if ((sp_check_avail_automatic) && (sp_check_commandavail(cmd) == 0)) {
334 printf_debug ("Warning: Automatic command availability check"
335 " failed for cmd %d - wont execute cmd\n",cmd);
336 return 1;
337 }
338 return 0;
339}
340
341static int sp_docommand(uint8_t command, uint32_t parmlen,
342 uint8_t * params, uint32_t retlen, void *retparms)
343{
344 unsigned char *sendpacket;
345 unsigned char c;
346 if (sp_automatic_cmdcheck(command))
347 return 1;
348 sendpacket = malloc(1 + parmlen);
349 if (!sendpacket)
350 sp_die("Error: cannot malloc command buffer");
351 sendpacket[0] = command;
352 memcpy(&(sendpacket[1]), params, parmlen);
353 if (write(sp_fd, sendpacket, 1 + parmlen) != (1 + parmlen)) {
354 sp_die("Error: cannot write command");
355 }
356 free(sendpacket);
357 if (read(sp_fd, &c, 1) != 1)
358 sp_die("Error: cannot read from device");
359 if (c == S_NAK) return 1;
360 if (c != S_ACK) {
361 fprintf(stderr,
362 "Error: invalid response 0x%02X from device\n",c);
363 exit(1);
364 }
365 if (retlen) {
366 int rd_bytes = 0;
367 do {
368 int r;
369 r = read(sp_fd, retparms + rd_bytes,
370 retlen - rd_bytes);
371 if (r <= 0) sp_die
372 ("Error: cannot read return parameters");
373 rd_bytes += r;
374 } while (rd_bytes != retlen);
375 }
376 return 0;
377}
378
379static void sp_flush_stream(void)
380{
381 if (sp_streamed_transmit_ops)
382 do {
383 unsigned char c;
384 if (read(sp_fd, &c, 1) != 1) {
385 sp_die
386 ("Error: cannot read from device (flushing stream)");
387 }
388 if (c == S_NAK) {
389 fprintf(stderr,
390 "Error: NAK to a stream buffer operation\n");
391 exit(1);
392 }
393 if (c != S_ACK) {
394 fprintf(stderr,
395 "Error: Invalid reply 0x%02X from device\n",
396 c);
397 exit(1);
398 }
399 } while (--sp_streamed_transmit_ops);
400 sp_streamed_transmit_ops = 0;
401 sp_streamed_transmit_bytes = 0;
402}
403
404static int sp_stream_buffer_op(uint8_t cmd, uint32_t parmlen, uint8_t * parms)
405{
406 uint8_t *sp;
407 if (sp_automatic_cmdcheck(cmd))
408 return 1;
409 sp = malloc(1 + parmlen);
410 if (!sp) sp_die("Error: cannot malloc command buffer");
411 sp[0] = cmd;
412 memcpy(&(sp[1]), parms, parmlen);
413 if (sp_streamed_transmit_bytes >= (1 + parmlen + sp_device_serbuf_size))
414 sp_flush_stream();
415 if (write(sp_fd, sp, 1 + parmlen) != (1 + parmlen))
416 sp_die("Error: cannot write command");
417 free(sp);
418 sp_streamed_transmit_ops += 1;
419 sp_streamed_transmit_bytes += 1 + parmlen;
420 return 0;
421}
422
423int serprog_init(void)
424{
425 uint16_t iface;
426 int len;
427 unsigned char pgmname[17];
428 unsigned char rbuf[3];
429 unsigned char c;
430 char *num;
431 char *dev;
432 printf_debug("%s\n", __func__);
433 /* the parameter is either of format "/dev/device:baud" or "ip:port" */
434 if ((!serprog_param) || (!strlen(serprog_param))) {
435 nodevice:
436 fprintf(stderr,
437 "Error: No device/host given for the serial programmer driver.\n"
438 "Use flashrom -p serprog=/dev/device:baud or flashrom -p serprog=ip:port\n");
439 exit(1);
440 }
441 num = strstr(serprog_param, ":");
442 len = num - serprog_param;
443 if (!len) goto nodevice;
444 if (!num) {
445 fprintf(stderr,
446 "Error: No port or baudrate specified to serial programmer driver.\n"
447 "Use flashrom -p serprog=/dev/device:baud or flashrom -p serprog=ip:port\n");
448 exit(1);
449 }
450 len = num - serprog_param;
451 dev = malloc(len + 1);
452 if (!dev) sp_die("Error: memory allocation failure");
453 memcpy(dev, serprog_param, len);
454 dev[len] = 0;
455 num = strdup(num + 1);
456 if (!num) sp_die("Error: memory allocation failure");
457 free(serprog_param);
458 serprog_param = NULL;
459
460 if (dev[0] == '/') sp_fd = sp_openserport(dev, atoi(num));
461 else sp_fd = sp_opensocket(dev, atoi(num));
462
463 free(dev); dev = NULL;
464 free(num); num = NULL;
465
466 printf_debug(MSGHEADER "connected - attempting to synchronize\n");
467
468 sp_check_avail_automatic = 0;
469
470 sp_synchronize();
471
472 printf_debug(MSGHEADER "Synchronized\n");
473
474 if (sp_docommand(S_CMD_Q_IFACE, 0, NULL, 2, &iface)) {
475 fprintf(stderr, "Error: NAK to Query Interface version\n");
476 exit(1);
477 }
478
479 if (iface != 1) {
480 fprintf(stderr, "Error: Unknown interface version %d\n", iface);
481 exit(1);
482 }
483
484 printf_debug(MSGHEADER "Interface version ok.\n");
485
486 if (sp_docommand(S_CMD_Q_CMDMAP, 0, NULL, 32, sp_cmdmap)) {
487 fprintf(stderr, "Error: query command map not supported\n");
488 exit(1);
489 }
490
491 sp_check_avail_automatic = 1;
492
493 /* Check for the minimum operational set of commands */
494 if (sp_check_commandavail(S_CMD_R_BYTE) == 0) {
495 fprintf(stderr, "Error: Single byte read not supported\n");
496 exit(1);
497 }
498 /* This could be translated to single byte reads (if missing), *
499 * but now we dont support that. */
500 if (sp_check_commandavail(S_CMD_R_NBYTES) == 0) {
501 fprintf(stderr, "Error: Read n bytes not supported\n");
502 exit(1);
503 }
504 /* In the future one could switch to read-only mode if these *
505 * are not available. */
506 if (sp_check_commandavail(S_CMD_O_INIT) == 0) {
507 fprintf(stderr,
508 "Error: Initialize operation buffer not supported\n");
509 exit(1);
510 }
511 if (sp_check_commandavail(S_CMD_O_WRITEB) == 0) {
512 fprintf(stderr,
513 "Error: Write to opbuf: write byte not supported\n");
514 exit(1);
515 }
516 if (sp_check_commandavail(S_CMD_O_DELAY) == 0) {
517 fprintf(stderr, "Error: Write to opbuf: delay not supported\n");
518 exit(1);
519 }
520 if (sp_check_commandavail(S_CMD_O_EXEC) == 0) {
521 fprintf(stderr,
522 "Error: Execute operation buffer not supported\n");
523 exit(1);
524 }
525
526 if (sp_docommand(S_CMD_Q_PGMNAME, 0, NULL, 16, pgmname)) {
527 fprintf(stderr, "Warning: NAK to query programmer name\n");
528 strcpy((char *)pgmname, "(unknown)");
529 }
530 pgmname[16] = 0;
531 printf(MSGHEADER "Programmer name \"%s\"\n", pgmname);
532
533 if (sp_docommand(S_CMD_Q_SERBUF, 0, NULL, 2, &sp_device_serbuf_size)) {
534 fprintf(stderr, "Warning: NAK to query serial buffer size\n");
535 }
536 printf_debug(MSGHEADER "serial buffer size %d\n",
537 sp_device_serbuf_size);
538
539 if (sp_docommand(S_CMD_Q_OPBUF, 0, NULL, 2, &sp_device_opbuf_size)) {
540 fprintf(stderr,
541 "Warning: NAK to query operation buffer size\n");
542 }
543 printf_debug(MSGHEADER "operation buffer size %d\n",
544 sp_device_opbuf_size);
545
546 if (sp_docommand(S_CMD_Q_BUSTYPE, 0, NULL, 1, &c)) {
547 fprintf(stderr, "Warning: NAK to query supported buses\n");
548 c = CHIP_BUSTYPE_NONSPI; /* A reasonable default for now. */
549 }
550 buses_supported = c;
551
552 if (sp_docommand(S_CMD_O_INIT, 0, NULL, 0, NULL)) {
553 fprintf(stderr, "Error: NAK to initialize operation buffer\n");
554 exit(1);
555 }
556
557 if (sp_docommand(S_CMD_Q_WRNMAXLEN, 0, NULL, 3, rbuf)) {
558 printf_debug(MSGHEADER "Write-n not supported");
559 sp_max_write_n = 0;
560 } else {
561 sp_max_write_n = ((unsigned int)(rbuf[0]) << 0);
562 sp_max_write_n |= ((unsigned int)(rbuf[1]) << 8);
563 sp_max_write_n |= ((unsigned int)(rbuf[2]) << 16);
564 printf_debug(MSGHEADER "Maximum write-n length %d\n",
565 sp_max_write_n);
566 sp_write_n_buf = malloc(sp_max_write_n);
567 if (!sp_write_n_buf) {
568 fprintf(stderr,
569 "Error: cannot allocate memory for Write-n buffer\n");
570 exit(1);
571 }
572 sp_write_n_bytes = 0;
573 }
574
575 if ((sp_check_commandavail(S_CMD_Q_RDNMAXLEN))
576 &&((sp_docommand(S_CMD_Q_RDNMAXLEN,0,NULL, 3, rbuf) == 0))) {
577 sp_max_read_n = ((unsigned int)(rbuf[0]) << 0);
578 sp_max_read_n |= ((unsigned int)(rbuf[1]) << 8);
579 sp_max_read_n |= ((unsigned int)(rbuf[2]) << 16);
580 printf_debug(MSGHEADER "Maximum read-n length %d\n",
581 sp_max_read_n ? sp_max_read_n : (1<<24));
582 } else {
583 printf_debug(MSGHEADER "Maximum read-n length not reported\n");
584 sp_max_read_n = 0;
585 }
586
587 sp_prev_was_write = 0;
588 sp_streamed_transmit_ops = 0;
589 sp_streamed_transmit_bytes = 0;
590 sp_opbuf_usage = 0;
591 return 0;
592}
593
594/* Move an in flashrom buffer existing write-n operation to *
595 * the on-device operation buffer. */
596static void sp_pass_writen(void)
597{
598 unsigned char header[7];
599 printf_debug(MSGHEADER "Passing write-n bytes=%d addr=0x%x\n",
600 sp_write_n_bytes, sp_write_n_addr);
601 if (sp_streamed_transmit_bytes >=
602 (7 + sp_write_n_bytes + sp_device_serbuf_size))
603 sp_flush_stream();
604 /* In case it's just a single byte send it as a single write. */
605 if (sp_write_n_bytes == 1) {
606 sp_write_n_bytes = 0;
607 header[0] = (sp_write_n_addr >> 0) & 0xFF;
608 header[1] = (sp_write_n_addr >> 8) & 0xFF;
609 header[2] = (sp_write_n_addr >> 16) & 0xFF;
610 header[3] = sp_write_n_buf[0];
611 sp_stream_buffer_op(S_CMD_O_WRITEB, 4, header);
612 sp_opbuf_usage += 5;
613 return;
614 }
615 header[0] = S_CMD_O_WRITEN;
616 header[1] = (sp_write_n_bytes >> 0) & 0xFF;
617 header[2] = (sp_write_n_bytes >> 8) & 0xFF;
618 header[3] = (sp_write_n_bytes >> 16) & 0xFF;
619 header[4] = (sp_write_n_addr >> 0) & 0xFF;
620 header[5] = (sp_write_n_addr >> 8) & 0xFF;
621 header[6] = (sp_write_n_addr >> 16) & 0xFF;
622 if (write(sp_fd, header, 7) != 7)
623 sp_die("Error: cannot write write-n command\n");
624 if (write(sp_fd, sp_write_n_buf, sp_write_n_bytes) !=
625 sp_write_n_bytes)
626 sp_die("Error: cannot write write-n data");
627 sp_streamed_transmit_bytes += 7 + sp_write_n_bytes;
628 sp_streamed_transmit_ops += 1;
629 sp_opbuf_usage += 7 + sp_write_n_bytes;
630 sp_write_n_bytes = 0;
631 sp_prev_was_write = 0;
632}
633
634static void sp_execute_opbuf_noflush(void)
635{
636 if ((sp_max_write_n) && (sp_write_n_bytes))
637 sp_pass_writen();
638 sp_stream_buffer_op(S_CMD_O_EXEC, 0, 0);
639 printf_debug(MSGHEADER "Executed operation buffer of %d bytes\n",
640 sp_opbuf_usage);
641 sp_opbuf_usage = 0;
642 sp_prev_was_write = 0;
643 return;
644}
645
646static void sp_execute_opbuf(void)
647{
648 sp_execute_opbuf_noflush();
649 sp_flush_stream();
650}
651
652int serprog_shutdown(void)
653{
654 printf_debug("%s\n", __func__);
655 if ((sp_opbuf_usage) || (sp_max_write_n && sp_write_n_bytes))
656 sp_execute_opbuf();
657 close(sp_fd);
658 if (sp_max_write_n)
659 free(sp_write_n_buf);
660 return 0;
661}
662
663static void sp_check_opbuf_usage(int bytes_to_be_added)
664{
665 if (sp_device_opbuf_size <= (sp_opbuf_usage + bytes_to_be_added)) {
666 sp_execute_opbuf();
667 /* If this happens in the mid of an page load the page load *
668 * will propably fail. */
669 printf_debug(MSGHEADER
670 "Warning: executed operation buffer due to size reasons\n");
671 }
672}
673
674void serprog_chip_writeb(uint8_t val, chipaddr addr)
675{
676 printf_debug("%s\n", __func__);
677 if (sp_max_write_n) {
678 if ((sp_prev_was_write)
679 && (addr == (sp_write_n_addr + sp_write_n_bytes))) {
680 sp_write_n_buf[sp_write_n_bytes++] = val;
681 } else {
682 if ((sp_prev_was_write) && (sp_write_n_bytes))
683 sp_pass_writen();
684 sp_prev_was_write = 1;
685 sp_write_n_addr = addr;
686 sp_write_n_bytes = 1;
687 sp_write_n_buf[0] = val;
688 }
689 sp_check_opbuf_usage(7 + sp_write_n_bytes);
690 if (sp_write_n_bytes >= sp_max_write_n)
691 sp_pass_writen();
692 } else {
693 /* We will have to do single writeb ops. */
694 unsigned char writeb_parm[4];
695 sp_check_opbuf_usage(6);
696 writeb_parm[0] = (addr >> 0) & 0xFF;
697 writeb_parm[1] = (addr >> 8) & 0xFF;
698 writeb_parm[2] = (addr >> 16) & 0xFF;
699 writeb_parm[3] = val;
700 sp_stream_buffer_op(S_CMD_O_WRITEB, 4, writeb_parm);
701 sp_opbuf_usage += 5;
702 }
703}
704
705uint8_t serprog_chip_readb(const chipaddr addr)
706{
707 unsigned char c;
708 unsigned char buf[3];
709 /* Will stream the read operation - eg. add it to the stream buffer, *
710 * then flush the buffer, then read the read answer. */
711 if ((sp_opbuf_usage) || (sp_max_write_n && sp_write_n_bytes))
712 sp_execute_opbuf_noflush();
713 buf[0] = ((addr >> 0) & 0xFF);
714 buf[1] = ((addr >> 8) & 0xFF);
715 buf[2] = ((addr >> 16) & 0xFF);
716 sp_stream_buffer_op(S_CMD_R_BYTE, 3, buf);
717 sp_flush_stream();
718 if (read(sp_fd, &c, 1) != 1)
719 sp_die("readb byteread");
720 printf_debug("%s addr=0x%lx returning 0x%02X\n", __func__, addr, c);
721 return c;
722}
723
724/* Local version that really does the job, doesnt care of max_read_n. */
725static void sp_do_read_n(uint8_t * buf, const chipaddr addr, size_t len)
726{
727 int rd_bytes = 0;
728 unsigned char sbuf[6];
729 printf_debug("%s: addr=0x%lx len=%lu\n", __func__, addr, (unsigned long)len);
730 /* Stream the read-n -- as above. */
731 if ((sp_opbuf_usage) || (sp_max_write_n && sp_write_n_bytes))
732 sp_execute_opbuf_noflush();
733 sbuf[0] = ((addr >> 0) & 0xFF);
734 sbuf[1] = ((addr >> 8) & 0xFF);
735 sbuf[2] = ((addr >> 16) & 0xFF);
736 sbuf[3] = ((len >> 0) & 0xFF);
737 sbuf[4] = ((len >> 8) & 0xFF);
738 sbuf[5] = ((len >> 16) & 0xFF);
739 sp_stream_buffer_op(S_CMD_R_NBYTES, 6, sbuf);
740 sp_flush_stream();
741 do {
742 int r = read(sp_fd, buf + rd_bytes, len - rd_bytes);
743 if (r <= 0)
744 sp_die("Error: cannot read read-n data");
745 rd_bytes += r;
746 } while (rd_bytes != len);
747 return;
748}
749
750/* The externally called version that makes sure that max_read_n is obeyed. */
751void serprog_chip_readn(uint8_t * buf, const chipaddr addr, size_t len)
752{
753 size_t lenm = len;
754 chipaddr addrm = addr;
755 while ((sp_max_read_n)&&(lenm > sp_max_read_n)) {
756 sp_do_read_n(&(buf[addrm-addr]),addrm,sp_max_read_n);
757 addrm += sp_max_read_n;
758 lenm -= sp_max_read_n;
759 }
760 if (lenm) sp_do_read_n(&(buf[addrm-addr]),addrm,lenm);
761}
762
763void serprog_delay(int delay)
764{
765 unsigned char buf[4];
766 printf_debug("%s\n", __func__);
767 if ((sp_max_write_n) && (sp_write_n_bytes))
768 sp_pass_writen();
769 sp_check_opbuf_usage(5);
770 buf[0] = ((delay >> 0) & 0xFF);
771 buf[1] = ((delay >> 8) & 0xFF);
772 buf[2] = ((delay >> 16) & 0xFF);
773 buf[3] = ((delay >> 24) & 0xFF);
774 sp_stream_buffer_op(S_CMD_O_DELAY, 4, buf);
775 sp_opbuf_usage += 5;
776 sp_prev_was_write = 0;
777}
778
Urja Rannikko22915352009-06-23 11:33:43 +0000779#else
Urja Rannikkof3196df2009-07-21 13:02:59 +0000780
Urja Rannikko22915352009-06-23 11:33:43 +0000781int serprog_init(void)
782{
783 fprintf(stderr, "Serial programmer support was not compiled in\n");
784 exit(1);
785}
786
787int serprog_shutdown(void)
788{
789 fprintf(stderr, "Serial programmer support was not compiled in\n");
790 exit(1);
791}
792
793void serprog_chip_writeb(uint8_t val, chipaddr addr)
794{
795 fprintf(stderr, "Serial programmer support was not compiled in\n");
796 exit(1);
797}
798
799uint8_t serprog_chip_readb(const chipaddr addr)
800{
801 fprintf(stderr, "Serial programmer support was not compiled in\n");
802 exit(1);
803}
804
805void serprog_chip_readn(uint8_t *buf, const chipaddr addr, size_t len)
806{
807 fprintf(stderr, "Serial programmer support was not compiled in\n");
808 exit(1);
809}
810
811void serprog_delay(int delay)
812{
813 fprintf(stderr, "Serial programmer support was not compiled in\n");
814 exit(1);
815}
816#endif