1 /*
2  * Copyright 1996, 1997, 1998, 1999 by Daniel B. Suthers,
3  * Pleasanton Ca. 94588 USA
4  * E-MAIL dbs@tanj.com
5  *
6  */
7 
8 /*
9  *   This program is free software: you can redistribute it and/or modify
10  *   it under the terms of the GNU General Public License as published by
11  *   the Free Software Foundation, either version 3 of the License, or
12  *   (at your option) any later version.
13  *
14  *   This program is distributed in the hope that it will be useful,
15  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
16  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  *   GNU General Public License for more details.
18  *
19  *   You should have received a copy of the GNU General Public License
20  *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
21  *
22  */
23 
24 
25 #include <stdio.h>
26 #include <string.h>
27 #include <stdlib.h>
28 #include <unistd.h>
29 #include "eeprom.h"
30 #include "process.h"
31 
32 extern int tty;
33 extern int sptty;
34 extern int display();
35 extern int send_buffer ( unsigned char *, int, int, int, int );
36 
37 /*-----------------------------------------------------------------+
38  | This function erases the eeprom.                                |
39  |  0 = 0                                                          |
40  |  1 = 3 (start of macros                                         |
41  |  2 = 0xff (end of timer initiators)                             |
42  |  3 = 0xff (end of macro initiators)                             |
43  |                                                                 |
44  | It does it by writing the value 0xff to all memory positions    |
45  | past the 3rd.  We start by writing bytes 3 through 18 to 0xff,  |
46  | and then byte 0 to 0 and 1 to 3.                                |
47  |                                                                 |
48  | We want to avoid having a timer trigger to an invalid position. |
49  | We want all memory to be initialized just in case.              |
50  +-----------------------------------------------------------------*/
51 
eraseall(void)52 int eraseall ( void )
53 {
54     unsigned char block[20];
55     int           blockno;
56     int           x;
57     extern void   error();
58     extern void   remove_record_file();
59     extern int    c_setclock();
60 
61 
62     block[0] = 0;
63     block[1] = 3;
64 
65     for ( x = 2; x < 16; x++ )
66         block[x] = (unsigned char) 0xff;
67 
68     /* Write the first block */
69     if ( sendpacket(0, block) < 0 )  {
70         error("Erase failed to write the first block\n");
71     }
72     fputc( '.', stdout);
73     fflush(stdout);
74 
75     /* fill the block */
76     for(x=0; x < 16; x++)
77 	block[x] = (unsigned char) 0xff;
78 
79     /* For each 16 byte block... */
80     for ( blockno = 1; blockno < (PROMSIZE / 16); blockno++ )  {
81 	if ( sendpacket((blockno * 16)  , block) < 0 )  {
82 	    char tmpstr[100];
83 	    sprintf( tmpstr, "Erase failed to write block %d\n", blockno);
84 	    error(tmpstr);
85 	}
86 	fputc( '.', stdout);
87 	fflush(stdout);
88     }
89 
90     /*
91      * Delete the X10 Record File and reset the cm11a clock.
92      * (In the absence of record file, the clock is set to
93      * system standard time.)
94      *
95      */
96 
97     remove_record_file();
98     (void) c_setclock(1, NULL);
99 
100     return 0;
101 }
102 
103 
104 /*-----------------------------------------------------------------+
105  | sendpacket sends the packet from a 19 byte string and handles   |
106  | locking and handshake.                                          |
107  |    loc = eeprom address (0 relative )                           |
108  |    dat = 16 btyes of data.                                      |
109  |    Return 0 on success, -1 on error.                            |
110  +-----------------------------------------------------------------*/
sendpacket(int loc,unsigned char * dat)111 int sendpacket ( int loc, unsigned char *dat)
112 {
113     unsigned char buf[23];
114     extern int    xwrite();
115     int           rtn;
116     unsigned char sum;
117     int           timeout;
118     extern int    xwrite(), exread(), check4poll();
119     extern unsigned char checksum();
120 
121 
122     /* timeout = 10; */
123     timeout = 3;
124 
125     buf[0] = (char) 0xfb;	/* write to eeprom command */
126     buf[1] = loc / 256;         /* hi byte of eeprom address */
127     buf[2] = loc % 256;         /* low byte of eeprom address */
128     memcpy(&buf[3], dat, 16);
129 
130     rtn = xwrite(tty, buf, 19);
131     if ( rtn < 0 )
132         return rtn;
133 
134     /* the checksum covers the data... Not the leading 0xfb */
135     sum = checksum(buf + 1, 18) ;
136 
137     /* read back the check sum */
138     rtn = exread(sptty, buf, 1, timeout);
139     if ( rtn < 0 )
140         return rtn;
141 
142     if ( sum != buf[0] )  {
143 	fprintf(stderr, "Checksum failure sending eeprom command\n");
144 	fprintf( stderr, "Expected %0x, got %0x\n", sum, buf[0]);
145 	return -2;
146     }
147 
148     /* check sums match */
149     rtn= xwrite(tty, "\00" , 1);  /* WRMI (we really mean it) */
150     if ( rtn < 0 )
151         return(rtn);
152 
153     buf[0] = 0;
154     rtn = exread(sptty, buf, 1, timeout);
155     if ( rtn == 1 ) {
156         if ( buf[0] != 0x55 ) {
157             fprintf(stderr,
158                "Ack after execution = 0x%02x, It should be 0x55)\n", buf[0]);
159             rtn = 0;
160         }
161     }
162 
163     if ( rtn != 1 )  {
164        if ( rtn == 0 && sum == 0x5a )  /* Workaround for 0x5a checksum problem */
165           return 0;
166        else {
167           fprintf(stderr,
168            "Interface not ready after sending data for location  %0x)\n", loc);
169           fprintf(stderr, "rtn = %0x\n", rtn);
170           return -1;
171        }
172     }
173 
174     return 0;
175 
176 }
177 
178 
179 /*-----------------------------------------------------------------+
180  | Upload the 1024 byte memory image 'prommap' to the CM11A EEPROM.|
181  | Start by nulling out the header block.  Then upload backwards   |
182  | so everything will be in place when the new header block is     |
183  | uploaded.                                                       |
184  +-----------------------------------------------------------------*/
upload_eeprom_image_old(unsigned char * prommap)185 void upload_eeprom_image_old ( unsigned char *prommap )
186 {
187     unsigned char emptyprom[32];
188     extern int verbose;
189     extern void error();
190     int x;
191 
192     /* Zero out the initiators to null the header block */
193 
194     emptyprom[0] = (unsigned char)0;
195     emptyprom[1] = (unsigned char)3;
196     for ( x = 2; x < 16; x++)
197 	emptyprom[x] = (unsigned char)0xff;
198 
199 
200     /* erase the old eeprom header information */
201     if ( sendpacket(0 , emptyprom) < 0 ) {
202         (void)error("load_macro() failed to erase initiator block");
203         /* error() exits */
204     }
205 
206     /* Copy the data from the array 'prommap' to the CM11A */
207     /* Load backwards
208      * This is so the timers at the end of the eeprom are there when
209      * the initiators are loaded at the start of the eeprom
210      */
211 
212     fprintf(stdout, "Uploading %d block memory image to interface.\n",
213     		PROMSIZE / 16 );
214 
215     for ( x = 0; x < (PROMSIZE/16); x++ )
216         fputc( '.', stdout);
217     fputc( '\r', stdout);
218     fflush(stdout);
219 
220     for ( x = (PROMSIZE / 16) - 1; x >= 0; x-- ) {
221         if (verbose)
222             fprintf( stderr, "Loading %d\n", x * 16 );
223 
224         if ( sendpacket((x * 16), prommap + (x*16)) < 0 ) {
225             char tmpstr[100];
226             sprintf( tmpstr, "Upload failed to write block %d\n", x);
227 		error(tmpstr);
228         }
229         fputc( '#', stdout);
230         fflush(stdout);
231     }
232     fputc('\n', stdout);
233 
234     return;
235 }
236 
237 /*-----------------------------------------------------------------+
238  | Upload the 1024 byte memory image 'prommap' to the CM11A EEPROM.|
239  | Start by nulling out the header block.  Then upload backwards   |
240  | so everything will be in place when the new header block is     |
241  | uploaded.                                                       |
242  +-----------------------------------------------------------------*/
upload_eeprom_image(unsigned char * prommap)243 void upload_eeprom_image ( unsigned char *prommap )
244 {
245     extern int    verbose;
246     unsigned char buffer[32];
247     unsigned int  loc;
248     int           j, k, block, chkoff, result, timeout = 3;
249 
250     /* Offset checksum from beginning of buffer - the initial */
251     /* 0xfb is not included in the checksum.                  */
252     chkoff = 1;
253 
254     /* Zero out the initiators to null the header block */
255 
256     buffer[0] = 0xfb;
257     buffer[1] = 0x00;
258     buffer[2] = 0x03;
259     for ( j = 3; j < 19; j++)
260 	buffer[j] = 0xff;
261 
262     /* erase the old eeprom header information */
263     if ( send_buffer(buffer, 19, chkoff, timeout, NO_SYNC) != 0 ) {
264        fprintf(stderr, "upload_eeprom_image() failed to erase initiator block.\n");
265        exit(1);
266     }
267 
268     /* Copy the data from the array 'prommap' to the CM11A */
269     /* Load backwards
270      * This is so the timers at the end of the eeprom are there when
271      * the initiators are loaded at the start of the eeprom
272      */
273 
274     fprintf(stdout, "Uploading %d block memory image to interface.\n",
275     		PROMSIZE / 16 );
276 
277     for ( j = 0; j < (PROMSIZE/16); j++ )
278         fputc( '.', stdout);
279     fputc( '\r', stdout);
280     fflush(stdout);
281 
282     for ( block = (PROMSIZE / 16) - 1; block >= 0; block-- ) {
283         loc = block * 16;
284 
285         buffer[0] = 0xfb;
286         buffer[1] = loc / 256;
287         buffer[2] = loc % 256;
288         memcpy(&buffer[3], prommap + loc, 16);
289 
290         result = 0;  /* Keep compiler happy */
291         for ( k = 0; k < 3; k++ ) {
292            if (verbose)
293                fprintf(stderr, "Uploading block %d to address 0x%03x\n", block, loc );
294 
295            if ( (result = send_buffer(buffer, 19, chkoff, timeout, NO_SYNC)) == 0 )
296               break;
297            sleep(2);
298         }
299         if ( result != 0 ) {
300            fprintf(stderr, "Upload failed to write block %d to address 0x%03x\n", block, loc);
301            exit(1);
302         }
303 
304         fputc( '#', stdout);
305         fflush(stdout);
306     }
307     fputc('\n', stdout);
308 
309     return;
310 }
311 
312