edt_xilinx.c

00001 /*
00002 * FPGA header read and other utilities
00003 * 
00004 * Originally written it was only Xilinx (hence the name), now encompasses Alterra, may
00005 * include in FPGA types in the future; nevertheless Xilinx will likely be found here
00006 * and there for a long time used generically for all types of FPGAs.   
00007 */
00008 #include "edtinc.h"
00009 #include "edt_bitload.h"
00010 #include "pciload.h"
00011 #include <stdlib.h>
00012 #include <ctype.h>
00013 
00014 #ifdef DOXYGEN_SHOW_UNDOC
00015 
00019 #endif
00020 
00021 typedef struct {
00022     u_char fi[8];
00023     u_char name[MAXPATH];
00024     u_char id[32];
00025     u_char date[16];
00026     u_char time[16];
00027     u_long dsize; /* get_long_size puts 4-byte dsize here */
00028 } XHEADER;
00029 XHEADER Xh;
00030 
00031 u_int ida_4013e(u_long dmy, int sector);
00032 u_int ida_4013xla(u_long dmy, int sector);
00033 u_int ida_4028xla(u_long dmy, int sector); /* and xc2s150 */
00034 u_int ida_xc2s100(u_long dmy, int sector); /* and 200 and 300e */
00035 u_int ida_xc3s1200e(u_long dmy, int sector);
00036 u_int ida_xc2s1200e(u_long dmy, int sector);
00037 u_int ida_xc5vlx30t(u_long edt_p, int dmy); /* and 50t and ep2sgx30d */
00038 u_int edt_get_fpga_info_index(EdtDev *edt_p);
00039 
00040 static int xb_get_magic(u_char *buf);
00041 static int xa_get_magic(u_char **ba);
00042 static int xf_get_magic(FILE *fp);
00043 
00044 /* Xilinx magic number (first 13 bytes) is always the same ( so far... ) */
00045 #define MGK_SIZE 13
00046 u_char Xmh[MGK_SIZE] = {0x00, 0x09, 0x0f, 0xf0, 0x0f, 0xf0, 0x0f, 0xf0, 0x0f, 0xf0, 0x00, 0x00, 0x01 };
00047 #define MGK_X 1
00048 
00049 /* EDT magic number used for Alterra parts, different number but same size as Xilinx, for compatability */
00050 u_char Emh[MGK_SIZE] = {0x00, 0x0e, 0x0d, 0x0f, 0x0a, 0x0l, 0x0f, 0x0e, 0x08, 0x08, 0x0a, 0x00, 0x01 };
00051 #define MGK_A 2
00052 
00053 /* get from edt_get_prominfo */
00054 /*   name             FPGA                bus     type      magic    sectsize   sectsperseg defaultseg id_addr()  */
00055 Edt_prominfo EPinfo[16] =
00056 {
00057     {"unknown [0]",  "na",               "na",    0,         0,      0,                0,    0,    NULL},               /*  0 */
00058     {"4013e",        "AMD 29F010",       "PCI",   XTYPE_X,   MGK_X,  E_SECTOR_SIZE,    8,    0,    ida_4013e},          /*  1 */
00059     {"4013xla",      "AMD 29F010",       "PCI",   XTYPE_X,   MGK_X,  XLA_SECTOR_SIZE,  1,    1,    ida_4013xla},        /*  2 */
00060     {"4028xla",      "AMD 29F010",       "PCI",   XTYPE_BT,  MGK_X,  XLA_SECTOR_SIZE,  2,    2,    ida_4028xla},        /*  3 */
00061     {"xc2s150",      "AMD 29LV040B",     "PCI",   XTYPE_BT,  MGK_X,  XLA_SECTOR_SIZE,  2,    2,    ida_4028xla},        /*  4 */
00062     {"xc2s200",      "AMD 29LV040B 4MB", "PCI",   XTYPE_BT,  MGK_X,  XLA_SECTOR_SIZE,  4,    2,    ida_xc2s100},        /*  5 */
00063     {"xc2s200",      "AMD 29LV081B 8MB", "PCI",   XTYPE_BT,  MGK_X,  XLA_SECTOR_SIZE,  4,    2,    ida_xc2s100},        /*  6 */
00064     {"xc2s100",      "AMD 29LV081B 8MB", "PCI",   XTYPE_BT,  MGK_X,  XLA_SECTOR_SIZE,  4,    2,    ida_xc2s100},        /*  7 */
00065     {"xc2s300e",     "AMD 29LV081B 8MB", "PCI",   XTYPE_LTX, MGK_X,  XLA_SECTOR_SIZE,  4,    2,    ida_xc2s100},        /*  8 */
00066     {"xc3s1200e",    "SPI W25P16",       "PCIe",  XTYPE_SPI, MGK_X,  SPI_SECTOR_SIZE,  32,   0,    ida_xc3s1200e},      /*  9 */ 
00067     {"xc5vlx30t",    "AMD S29GL064N",    "PCIe",  XTYPE_BT2, MGK_X,  XLA_SECTOR_SIZE,  32,   3,    ida_xc5vlx30t},      /* 10 */
00068     {"xc5vlx50t",    "AMD S29GL064N",    "PCIe",  XTYPE_BT2, MGK_X,  XLA_SECTOR_SIZE,  32,   3,    ida_xc5vlx30t},      /* 11 */
00069     {"ep2sgx30d",    "AMD S29GL128N",    "PCIe",  XTYPE_BT2, MGK_A,  XLA_SECTOR_SIZE,  32,   3,    ida_xc5vlx30t},      /* 12 */  /* EDT_MAX_PROMCODE */
00070     {"unknown [13]", "na",               "na",    0,         0,      0,                0,    0,    NULL},
00071     {"unknown [14]", "na",               "na",    0,         0,      0,                0,    0,    NULL},
00072     {"unknown [15]", "na",               "na",    0,         0,      0,                0,    0,    NULL},
00073 };
00074 
00075 #define EDT_MAX_PROMCODE 12 /* MUST match last promcode defined above */
00076 
00077 
00078 /* shorthand debug level */
00079 #define DEBUG1 EDTLIB_MSG_INFO_1
00080 #define DEBUG2 EDTLIB_MSG_INFO_2
00081 
00082 static int do_fast = 0;
00083 static int force_slow = 0;
00084 static int debug_fast = 0;
00085 static int hubload = 0;
00086 
00087 /* SPI DEBUG  FLAGS */
00088 static u_short dbgflg =0;
00089 static u_short spi_verbose = 0;
00090 
00091 /* SPI WORKING VARIABLES */
00092 unsigned char  Spi_wbufa[260];          /* Need 3 addr + 256 data for PP */
00093 unsigned char* Spi_wbuf=Spi_wbufa+3;            /* Just the 256 bytes of data */
00094 unsigned char  Spi_rbuf[260];           /* Read buffer, could use 256 Kbytes? */
00095 volatile caddr_t Spi_mapaddr = 0;
00096 
00097 
00098 static int      spi_block_program(EdtDev *edt_p, int addr0, int size, u_char *spibuf, int verify_only);
00099 static int      spi_write(EdtDev *edt_p, u_int addr, int wcnt);
00100 static void     spi_read(EdtDev *edt_p, int addr, u_char *rbuf, int rcnt);
00101 static int      spi_reset(EdtDev *edt_p);
00102 static int      spi_sector_erase(EdtDev *edt_p, u_int sector);
00103 static void     spi_print16(EdtDev *edt_p, u_int addr);
00104 static void     spiprim(EdtDev *edt_p, int opcode, int wbytes, int rbytes, unsigned char* wbuf, unsigned char* rbuf);
00105 static void     spi_xwr(EdtDev *edt_p, int val);
00106 static int      spi_xrd(EdtDev *edt_p);
00107 static void     spi_xw(EdtDev *edt_p, u_int addr, u_int data);
00108 static u_int    spi_xr(EdtDev *edt_p, u_int addr);
00109 
00110 static void   bt_write(EdtDev *edt_p, uint_t desc, u_int addr, u_char val);
00111 static u_char bt_read(EdtDev *edt_p, uint_t desc, u_int addr);
00112 static int    bt_byte_program(EdtDev *edt_p, int xtype, uint_t desc, u_int addr, u_char data);
00113 static void   bt_reset(EdtDev *edt_p, uint_t desc);
00114 static u_char bt_readstat(EdtDev *edt_p, uint_t desc);
00115 static void   bt_print16(EdtDev *edt_p, uint_t desc, u_int addr);
00116 static int    bt_sector_erase(EdtDev *edt_p, u_int sector, u_int sec_size, uint_t desc);
00117 
00118 static int    bt2_byte_program(EdtDev *edt_p, int xtype, uint_t desc, u_int addr, u_char data);
00119 static void   bt2_reset(EdtDev *edt_p, uint_t desc);
00120 static int    bt2_sector_erase(EdtDev *edt_p, u_int sector, u_int sec_size, uint_t desc);
00121 
00122 static void   xwrite(EdtDev *edt_p, u_int addr, u_char val);
00123 static u_char xread(EdtDev *edt_p, u_int addr);
00124 static int    xbyte_program(EdtDev * edt_p, u_int addr, u_char data);
00125 static void   xreset(EdtDev *edt_p);
00126 static u_char xreadstat(EdtDev *edt_p);
00127 static void   xprint16(EdtDev *edt_p, u_int addr);
00128 static int    xsector_erase(EdtDev * edt_p, u_int sector, u_int sec_size);
00129 
00130 static void   tst_write(EdtDev * edt_p, uint_t desc, uint_t val);
00131 #if 0
00132 static int    default_segment(int promcode);
00133 #endif
00134 
00135 int
00136 edt_ltx_hub(EdtDev *edt_p)
00137 {
00138     if (hubload)
00139         return edt_p->hubidx;
00140     return -1;
00141 }
00142 
00143 void
00144 edt_set_ltx_hub(EdtDev *edt_p, int hub)
00145 {
00146     hubload = 1;
00147     edt_p->hubidx = hub;
00148 }
00149 
00150 int
00151 edt_get_debug_fast()
00152 {
00153     return (debug_fast) ;
00154 }
00155 int
00156 edt_set_debug_fast(int val)
00157 {
00158     (debug_fast = val) ;
00159     return val;
00160 }
00161 int
00162 edt_get_do_fast()
00163 {
00164     return (do_fast) ;
00165 }
00166 void
00167 edt_set_do_fast(int val)
00168 {
00169     do_fast = val ;
00170 }
00171 int
00172 edt_get_force_slow()
00173 {
00174     return (force_slow) ;
00175 }
00176 void
00177 edt_set_force_slow(int val)
00178 {
00179     force_slow = val ;
00180 }
00181 
00192 char *edt_fmt_pn(char *pn, char *str)
00193 {
00194     if (strlen(pn) == 10)
00195         sprintf(str, "%c%c%c-%c%c%c%c%c-%c%c",
00196         pn[0],pn[1],pn[2],pn[3],pn[4],pn[5],pn[6],pn[7],pn[8],pn[9]);
00197     else if (strlen(pn) < 10)
00198         strcpy(str, pn);
00199     else strcpy(str, "0");
00200     return str;
00201 }
00202 
00203 /*
00204 * xilinx header decoder -- file (see below for array version)
00205 */
00206 static int
00207 xf_get_magic(FILE *fp)
00208 {
00209     u_char buf[512];
00210     int i, j;
00211     size_t n;
00212 
00213     if ((n = fread(buf, 1, MGK_SIZE, fp)) != MGK_SIZE)
00214     {
00215         edt_msg(EDT_MSG_FATAL, "unexpected EOF of xilinx file (%d bytes in)\n", n);
00216         return -1;
00217     }
00218 
00219     return xb_get_magic(buf);
00220 }
00221 
00222 
00223 static int
00224 xf_get_field_id(FILE *fp, u_char *fi)
00225 {
00226     size_t n;
00227 
00228     if ((n = fread(fi, 1, 1, fp)) != 1)
00229     {
00230         edt_msg(DEBUG1, "invalid xilinx field ID\n");
00231         return -1;
00232     }
00233 
00234     return 0;
00235 }
00236 
00237 static int
00238 xf_get_string(FILE *fp, u_char *str, u_int maxcount)
00239 {
00240     u_char tmpcount[2];
00241     u_short count;
00242     size_t n;
00243 
00244     if ((n = fread(&tmpcount, 1, 2, fp)) != 2)
00245     {
00246         edt_msg(DEBUG1, "missing field string count in xilinx header\n");
00247         return -1;
00248     }
00249 
00250     count = tmpcount[0] << 8 | tmpcount[1];
00251 
00252 
00253     if ((count > maxcount) || ((n = fread(str, sizeof(u_char), count, fp)) != count))
00254     {
00255         edt_msg(DEBUG1, "invalid xilinx header string (count %d)\n", count);
00256         return -1;
00257     }
00258     return 0;
00259 }
00260 
00261 static int
00262 xf_get_long_size(FILE *fp, u_long *size)
00263 {
00264     size_t n;
00265     u_char tmpsize[4];
00266 
00267     if ((n = fread(tmpsize, 1, 4, fp)) != 4)
00268     {
00269         edt_msg(DEBUG1, "invalid xilinx header size (%d s/b 4)\n", n);
00270         return -1;
00271     }
00272     *size =  (tmpsize[0] << 24) | (tmpsize[1] << 16) | (tmpsize[2] << 8) | (tmpsize[3]);
00273     /* printf("size %08x tmpsize %02x %02x %02x %02x\n",
00274     *size, tmpsize[0], tmpsize[2], tmpsize[1], tmpsize[0]); */
00275 
00276     return 0;
00277 }
00278 
00279 /*
00280 * get the xilinx header  (FILE version)
00281 *
00282 * open the file, get the header, and close, and return the # of bytes into
00283 * the file of the first byte of data.
00284 */
00285 long
00286 edt_get_x_file_header_magic(char *fname, char *header, int *size, int *magic)
00287 {
00288     FILE *infd = fopen(fname, "rb");
00289     long start_of_data;
00290     int ret = 0;
00291 
00292     if (infd == NULL)
00293     {
00294         edt_msg_perror(EDT_MSG_FATAL, fname);
00295         return(-1);
00296     }
00297 
00298     if ((ret = edt_get_x_header_magic(infd, header, size, magic)) != 0)
00299         ret = -1;
00300     else start_of_data = ftell(infd);
00301 
00302     fclose(infd);
00303 
00304     if (ret)
00305         return ret;
00306 
00307     return start_of_data;
00308 }
00309 
00310 /*
00311  * compat
00312  */
00313 long 
00314 edt_get_x_file_header(char *fname, char *header, int *size)
00315 {
00316     int dmy;
00317     return edt_get_x_file_header_magic(fname, header, size, &dmy);
00318 }
00319 
00320 /*
00321  * get the xilinx header from a FILE -- backwards compat (no magic #)
00322  *
00323  * takes as an argument an already open file pointer. for this reason, not to be
00324  * called directly by an application, ony from within the library. application 
00325  * programs should instead use edt_get_x_file_header.
00326  *
00327  * At the end of this function, the file position will be set to the
00328  * beginning of the file.
00329  *
00330  * Returns 0 on success, -1 on failure.
00331  */
00332 edt_get_x_header(FILE *fp, char *header, int *size)
00333 {
00334         int dmy;
00335         
00336         return edt_get_x_header_magic(fp, header, size, &dmy);
00337 }
00338 
00339 /*
00340  * get the xilinx header from a FILE, including magic number
00341  *
00342  * takes as an argument an already open file pointer. for this reason, not to be
00343  * called directly by an application, ony from within the library. application 
00344  * programs should instead use edt_get_x_file_header.
00345  *
00346  * At the end of this function, the file position will be set to the
00347  * beginning of the file.
00348  *
00349  * update for 4.1.8.9 (5/5/2008 rwh): look for semicolon & truncate name & id
00350  *
00351  * Returns 0 on success, -1 on failure.
00352  */
00353 int
00354 edt_get_x_header_magic(FILE *fp, char *header, int *size, int *magic)
00355 {
00356     int     i;
00357     char   *p;
00358     long start, end;
00359 
00360     edt_msg(DEBUG2, "edt_get_x_header:\n");
00361 
00362     *size = 0;
00363 
00364     if ((*magic = xf_get_magic(fp)) < 0)
00365     {
00366         edt_msg(EDT_MSG_FATAL, "invalid FPGA magic bytes in file\n");
00367         return  -1;
00368     }
00369     else edt_msg(DEBUG1, "magic=%s (%d)\n", (*magic == MGK_X)?"XILINX":(*magic == MGK_A)?"ALTERRA":"UNKNOWN (WTF?)", *magic);
00370 
00371     if ((xf_get_field_id(fp, &Xh.fi[0]) != 0)
00372         || (xf_get_string(fp, Xh.name, sizeof(Xh.name)) != 0)
00373         || (xf_get_field_id(fp, &Xh.fi[1]) != 0)
00374         || (xf_get_string(fp, Xh.id, sizeof(Xh.id)) != 0)
00375         || (xf_get_field_id(fp, &Xh.fi[2]) != 0)
00376         || (xf_get_string(fp, Xh.date, sizeof(Xh.date)) != 0)
00377         || (xf_get_field_id(fp, &Xh.fi[3]) != 0)
00378         || (xf_get_string(fp, Xh.time, sizeof(Xh.time)) != 0)
00379         || (xf_get_field_id(fp, &Xh.fi[4]) != 0)
00380         || (xf_get_long_size(fp, &Xh.dsize) != 0))
00381     {
00382         edt_msg(EDT_MSG_FATAL, "Error: bad xilinx header\n");
00383 #if 0
00384         edt_msg(DEBUG2, "%c) '%s'  %c) '%s'  %c) '%s'  %c) '%s'  %c) %d\n",
00385             Xh.fi[0], Xh.name,
00386             Xh.fi[1], Xh.id,
00387             Xh.fi[2], Xh.date,
00388             Xh.fi[3], Xh.time,
00389             Xh.fi[4], Xh.dsize);
00390         return  -1;
00391 #endif
00392     }
00393 
00394     for (i=0; i < 5; i++)
00395     {
00396         if (Xh.fi[i] != 'a' + i)
00397         {
00398             edt_msg(EDT_MSG_FATAL, "invalid xilinx field id: '%c' (0x%02x) s/b '%c' (0x%02x)\n", Xh.fi[i], Xh.fi[i], 'a'+i, 'a'+i);
00399             return -1;
00400         }
00401     }
00402 
00403     /* 
00404      * work around a new BUG (?) in xilinx tools; they're sticking debug or some such in
00405      * the #@*&ing xilinx header nowadays (something like EP2SGS30D;DEBUG_HANDLE=2)
00406      */
00407     if ((p = strchr(Xh.name, ';')) != NULL)
00408     {
00409         edt_msg(DEBUG2, "FIXING: Xh.name %s => ", Xh.name);
00410         *p = '\0';
00411         edt_msg(DEBUG2, "%s\n", Xh.name);
00412     }
00413     if ((p = strchr(Xh.id, ';')) != NULL)
00414     {
00415         edt_msg(DEBUG2, "FIXING: Xh.id %s => ", Xh.id);
00416         *p = '\0';
00417         edt_msg(DEBUG2, "%s\n", Xh.id);
00418     }
00419 
00420     edt_msg(DEBUG2, "%c) '%s'  %c) '%s'  %c) '%s'  %c) '%s'  %c) %d\n",
00421         Xh.fi[0], Xh.name,
00422         Xh.fi[1], Xh.id,
00423         Xh.fi[2], Xh.date,
00424         Xh.fi[3], Xh.time,
00425         Xh.fi[4], Xh.dsize);
00426 
00427     /*
00428     * check remaining size of file against dsize, then rewind file
00429     * pointer back to start of data 
00430     */
00431     start = ftell(fp);
00432     fseek(fp, Xh.dsize, SEEK_CUR);
00433     end = ftell(fp);
00434     if (Xh.dsize < (unsigned long)(end-start))
00435         edt_msg(EDT_MSG_WARNING, "Warning! dsize/file size mismatch (dsize %u, EOF @ +%u (may work anyway)\n", Xh.dsize, end-start);
00436     else if (Xh.dsize > (unsigned long)(end-start))
00437         edt_msg(EDT_MSG_FATAL, "Error! dsize/file size mismatch -- dsize %u but EOF at +%u\n", Xh.dsize, end-start);
00438     fseek(fp, start, SEEK_SET);
00439 
00440     *size = Xh.dsize;
00441 
00442     sprintf(header, "%s %s %s %s", Xh.name, Xh.id, Xh.date, Xh.time );
00443 
00444     return 0;
00445 }
00446 
00447 
00448 /*
00449 * get magic number, return 1 if Xilinx, 2 if EDT-Alterra
00450 */
00451 static int
00452 xa_get_magic(u_char **ba)
00453 {
00454     u_char buf[512];
00455 
00456     if (*ba == NULL)
00457     {
00458         edt_msg(EDT_MSG_FATAL, "unexpected short xilinx array  pointer\n");
00459         return -1;
00460     }
00461 
00462     memcpy(buf, *ba, MGK_SIZE);
00463     *ba += MGK_SIZE;
00464 
00465     return xb_get_magic(buf);
00466 
00467 }
00468 
00469 /*
00470  * get magic from buffer (called by xa_get_magic and xf_get_magic, on buf
00471  * or array 
00472  * buf has been read in)
00473  */
00474 static int
00475 xb_get_magic(u_char *buf)
00476 {
00477     int i;
00478     int is_xmh = 1;
00479     int is_emh = 1;
00480 
00481     for (i=0; i<MGK_SIZE; i++)
00482     {
00483         if (buf[i] != Xmh[i])
00484             is_xmh = 0;
00485         if (buf[i] != Emh[i])
00486             is_emh = 0;
00487     }
00488 
00489     if (is_xmh)
00490         return MGK_X;
00491     if (is_emh)
00492         return MGK_A;
00493 
00494     return -1;
00495 }
00496 
00497 
00498 static int
00499 xa_get_field_id(u_char **ba, u_char *fi)
00500 {
00501     memcpy(fi, *ba, 1);
00502     ++(*ba);
00503     return 0;
00504 }
00505 
00506 static int
00507 xa_get_string(u_char **ba, u_char *str, u_int maxcount)
00508 {
00509     u_char tmpcount[2];
00510     u_short count;
00511 
00512     memcpy(tmpcount, *ba, 2);
00513     *ba += 2;
00514 
00515     count = tmpcount[0] << 8 | tmpcount[1];
00516     if (count > maxcount)
00517     {
00518         edt_msg(DEBUG1, "invalid xilinx header string (count %d)\n", count);
00519         return -1;
00520     }
00521     memcpy(str, *ba, count);
00522     *ba += count;
00523     return 0;
00524 }
00525 
00526 static int
00527 xa_get_long_size(u_char **ba, u_long *size)
00528 {
00529     u_char tmpsize[4];
00530 
00531     memcpy(tmpsize, *ba, 4);
00532     *ba += 4;
00533 
00534     *size =  (tmpsize[0] << 24) | (tmpsize[1] << 16) | (tmpsize[2] << 8) | (tmpsize[3]);
00535     /* printf("size %08x tmpsize %02x %02x %02x %02x\n",
00536     *size, tmpsize[0], tmpsize[2], tmpsize[1], tmpsize[0]); */
00537 
00538     return 0;
00539 }
00540 
00541 /*
00542  * get the xilinx header (ARRAY version), with magic #
00543  *
00544  * open the array, get the header, and close, and return the # of bytes into
00545  * the file of the first byte of data.
00546  */
00547 u_char *
00548 edt_get_x_array_header_magic(u_char *ba, char *header, int *size, int *magic)
00549 {
00550     u_char *start_of_data;
00551 
00552     if ((start_of_data = edt_get_xa_header_magic(ba, header, size, magic)) == NULL)
00553         start_of_data = ba;
00554 
00555     return start_of_data;
00556 }
00557 
00558 /*
00559  * get the xilinx header (ARRAY version), no magic # (compat)
00560  *
00561  * open the array, get the header, and close, and return the # of bytes into
00562  * the file of the first byte of data.
00563  */
00564 u_char *
00565 edt_get_x_array_header(u_char *ba, char *header, int *size)
00566 {
00567     int dmy;
00568 
00569     return edt_get_x_array_header_magic(ba, header, size, &dmy);
00570 }
00571 
00572 
00573 /*
00574  * get the xilinx header 
00575  *
00576  * extract the xilinx header (OR faked one for alterra, etc.)
00577  * takes as an argument an array pointer. for this reason, not to be
00578  * called directly by an application, ony from within the library. application 
00579  * programs should instead use edt_get_x_file_header.
00580  */
00581 u_char *
00582 edt_get_xa_header_magic(u_char *ba, char *header, int *size, int *magic)
00583 {
00584     int     i;
00585     u_char *ta[1], *start, *end;
00586 
00587     edt_msg(DEBUG1, "edt_get_xa_header_magic:\n");
00588 
00589     *size = 0;
00590     start = ba;
00591     *ta = ba;
00592 
00593     if ((*magic = xa_get_magic(ta)) < 0)
00594     {
00595         edt_msg(EDT_MSG_FATAL, "invalid FPGA magic bytes in array\n");
00596         return  NULL;
00597     }
00598     else edt_msg(DEBUG1, "magic=%s (%d)\n", (*magic == MGK_X)?"XILINX":(*magic == MGK_A)?"ALTERRA":"UNKNOWN (WTF?)", *magic);
00599 
00600     if ((xa_get_field_id(ta, &Xh.fi[0]) != 0)
00601         || (xa_get_string(ta, Xh.name, 128) != 0)
00602         || (xa_get_field_id(ta, &Xh.fi[1]) != 0)
00603         || (xa_get_string(ta, Xh.id, 32) != 0)
00604         || (xa_get_field_id(ta, &Xh.fi[2]) != 0)
00605         || (xa_get_string(ta, Xh.date, 16) != 0)
00606         || (xa_get_field_id(ta, &Xh.fi[3]) != 0)
00607         || (xa_get_string(ta, Xh.time, 16) != 0)
00608         || (xa_get_field_id(ta, &Xh.fi[4]) != 0)
00609         || (xa_get_long_size(ta, &Xh.dsize) != 0))
00610     {
00611         edt_msg(EDT_MSG_FATAL, "Error: bad xilinx header\n");
00612 #if 0
00613         edt_msg(DEBUG1, "%c) '%s'  %c) '%s'  %c) '%s'  %c) '%s'  %c) %d\n",
00614             Xh.fi[0], Xh.name,
00615             Xh.fi[1], Xh.id,
00616             Xh.fi[2], Xh.date,
00617             Xh.fi[3], Xh.time,
00618             Xh.fi[4], Xh.dsize);
00619         return  -1;
00620 #endif
00621     }
00622 
00623     for (i=0; i < 5; i++)
00624     {
00625         if (Xh.fi[i] != 'a' + i)
00626         {
00627             edt_msg(EDT_MSG_FATAL, "invalid xilinx field id: '%c' (0x%02x) s/b '%c' (0x%02x)\n", Xh.fi[i], Xh.fi[i], 'a'+i, 'a'+i);
00628             return NULL;
00629         }
00630     }
00631 
00632     edt_msg(DEBUG1, "%c) '%s'  %c) '%s'  %c) '%s'  %c) '%s'  %c) %d\n",
00633         Xh.fi[0], Xh.name,
00634         Xh.fi[1], Xh.id,
00635         Xh.fi[2], Xh.date,
00636         Xh.fi[3], Xh.time,
00637         Xh.fi[4], Xh.dsize);
00638 
00639     /*
00640     * check remaining size of file against dsize, then rewind file
00641     * pointer back to start of data 
00642     */
00643     start = *ta;
00644     *ta += Xh.dsize;
00645     end = *ta;
00646     if (Xh.dsize < (unsigned long)(end-start))
00647         edt_msg(EDT_MSG_WARNING, "Warning! dsize/file size mismatch (dsize %u, EOF @ +%u (may work anyway)\n", Xh.dsize, end-start);
00648     else if (Xh.dsize > (unsigned long)(end-start))
00649         edt_msg(EDT_MSG_FATAL, "Error! dsize/file size mismatch -- dsize %u but EOF at +%u\n", Xh.dsize, end-start);
00650     *ta = start;
00651 
00652     *size = Xh.dsize;
00653 
00654     sprintf(header, "%s %s %s %s", Xh.name, Xh.id, Xh.date, Xh.time );
00655 
00656     return start;
00657 }
00658 
00659 u_char *
00660 edt_get_xa_header(u_char *ba, char *header, int *size)
00661 {
00662     int dmy;
00663     return edt_get_xa_header_magic(ba, header, size, &dmy);
00664 }
00665 
00666 /*
00667  * extract the xilinx header, rcxload-specific
00668  * derived from edt_get_xa_header (edt_xilinx.c) but instead of returning a
00669  * string pointer, just returns the status (pass or fail) and skips debug output
00670  *
00671  * takes as an argument an array pointer. 
00672  */
00673 int
00674 edt_get_x_array_header_rstat(u_char *ba, char *header, int *size)
00675 {
00676     int     i, magic;
00677     u_char *ta[1], *start, *end;
00678 
00679     edt_msg(DEBUG2, "rcxload_get_xa_header:\n");
00680 
00681     *size = 0;
00682     start = ba;
00683     *ta = ba;
00684 
00685     if ((magic = xa_get_magic(ta)) < 0)
00686     {
00687         edt_msg(DEBUG2, "invalid FPGA magic bytes\n");
00688         return  -1;
00689     }
00690 
00691     if ((xa_get_field_id(ta, &Xh.fi[0]) != 0)
00692         || (xa_get_string(ta, Xh.name, 128) != 0)
00693         || (xa_get_field_id(ta, &Xh.fi[1]) != 0)
00694         || (xa_get_string(ta, Xh.id, 32) != 0)
00695         || (xa_get_field_id(ta, &Xh.fi[2]) != 0)
00696         || (xa_get_string(ta, Xh.date, 16) != 0)
00697         || (xa_get_field_id(ta, &Xh.fi[3]) != 0)
00698         || (xa_get_string(ta, Xh.time, 16) != 0)
00699         || (xa_get_field_id(ta, &Xh.fi[4]) != 0)
00700         || (xa_get_long_size(ta, &Xh.dsize) != 0))
00701     {
00702         edt_msg(DEBUG2, "bad xilinx header\n");
00703         return -1;
00704 #if 0
00705         edt_msg(DEBUG2, "%c) '%s'  %c) '%s'  %c) '%s'  %c) '%s'  %c) %d\n",
00706             Xh.fi[0], Xh.name,
00707             Xh.fi[1], Xh.id,
00708             Xh.fi[2], Xh.date,
00709             Xh.fi[3], Xh.time,
00710             Xh.fi[4], Xh.dsize);
00711         return  -1;
00712 #endif
00713     }
00714 
00715     for (i=0; i < 5; i++)
00716     {
00717         if (Xh.fi[i] != 'a' + i)
00718         {
00719             edt_msg(DEBUG2, "invalid xilinx field id: '%c' (0x%02x) s/b '%c' (0x%02x)\n", Xh.fi[i], Xh.fi[i], 'a'+i, 'a'+i);
00720             return -1;
00721         }
00722     }
00723 
00724     /*
00725     * check remaining size of file against dsize, then rewind file
00726     * pointer back to start of data 
00727     */
00728     start = *ta;
00729     *ta += Xh.dsize;
00730     end = *ta;
00731     if (Xh.dsize < (unsigned long)(end-start))
00732         edt_msg(EDT_MSG_WARNING, "Warning! dsize/file size mismatch (dsize %u, EOF @ +%u (may work anyway)\n", Xh.dsize, end-start);
00733     else if (Xh.dsize > (unsigned long)(end-start))
00734         edt_msg(EDT_MSG_FATAL, "Error! dsize/file size mismatch -- dsize %u but EOF at +%u\n", Xh.dsize, end-start);
00735     *ta = start;
00736 
00737     *size = Xh.dsize;
00738 
00739     sprintf(header, "%s %s %s %s", Xh.name, Xh.id, Xh.date, Xh.time );
00740 
00741     return 0;
00742 }
00743 
00744 static char *device_name[NUM_DEVICE_TYPES] = {"pcd", "pdv", "p11w", "p16d", "p53b"};
00745 char *read_x_string(EdtDev *edt_p, u_int addr, char *buf, int size, int xtype);
00746 
00747 
00748 /*
00749 * command bits for the 4028xla boot controller
00750 */
00751 #define BT_EN_READ      0x8000
00752 
00753 /*
00754 * bit to set in all prom addresses to enable the upper 2 bits of prom
00755 * address after we have read the status (jumper and 5/3.3v)
00756 */
00757 #define EN_HIGH_ADD     0x00800000
00758 
00759 /* what are these? */
00760 #define DQ7 0x80
00761 #define DQ5 0x20
00762 #define DQ3 0x08
00763 static int maxloops = 0;
00764 
00765 volatile caddr_t dmyaddr = 0;
00766 volatile u_int *cfgaddr ;
00767 volatile u_int *tstaddr ;
00768 int needswap ;
00769 
00770 /* not particularly safe -- use at own risk! */
00771 u_char
00772 mmap_intfc_read(volatile u_char * mapaddr, u_int desc)
00773 {
00774         volatile u_char * off_p ;
00775         volatile u_char * data_p ;
00776     u_char val ;
00777     /* interface must set offset then read data */
00778     off_p = mapaddr + (EDT_REMOTE_OFFSET & 0xff) ;
00779     data_p = mapaddr + (EDT_REMOTE_DATA & 0xff) ;
00780     *off_p = desc & 0xff ;
00781     /* to flush */
00782     val = *off_p ;
00783     val = *data_p ;
00784     return(val) ;
00785 }
00786 
00787 /* not particularly safe -- use at own risk! */
00788 void
00789 mmap_intfc_write(volatile u_char * mapaddr, u_int desc, u_char val)
00790 {
00791         volatile u_char * off_p ;
00792         volatile u_char * data_p ;
00793     u_char tmp ;
00794     /* interface must set offset then read data */
00795     off_p = mapaddr + (EDT_REMOTE_OFFSET & 0xff) ;
00796     data_p = mapaddr + (EDT_REMOTE_DATA & 0xff) ;
00797     *off_p = desc & 0xff ;
00798     /* to flush */
00799     tmp = *off_p ;
00800     *data_p = val ;
00801 }
00802 
00803 int
00804 ltx_tst_init(EdtDev * edt_p)
00805 {
00806 
00807     if ((dmyaddr != 0) && (edt_p->mapaddr != 0))
00808         return 0;
00809 
00810     dmyaddr = (caddr_t)edt_mapmem(edt_p, 0, 0x10000);
00811     if (dmyaddr == 0)
00812     {
00813         printf("edt_mapmem failed\n");
00814         return -1;
00815     }
00816 
00817     if (edt_get_mappable_size(edt_p) > 0)
00818         edt_p->mapaddr = (caddr_t) edt_mapmem(edt_p, 0x10000, edt_get_mappable_size(edt_p));
00819     else edt_p->mapaddr = 0;
00820 
00821     (void)tst_write(edt_p, 0xf00004, 0xFF);
00822     return 0;
00823 }
00824 
00825 
00826 int 
00827 ltx_check_mmap(EdtDev * edt_p, int space)
00828 {
00829     if (ltx_tst_init(edt_p) < 0)
00830         return -1;
00831     if (space == 0)
00832     {
00833         if (dmyaddr == 0)
00834         {
00835             fprintf(stderr, "bad mmap for space 0\n");
00836             return (1);
00837         }
00838         else
00839             return (0);
00840     }
00841     else
00842     {
00843         if (edt_p->mapaddr == 0)
00844         {
00845             fprintf(stderr, "bad mmap for space 1\n");
00846             return (1);
00847         }
00848         else
00849             return (0);
00850     }
00851 }
00852 
00853 u_int
00854 swap32(u_int val)
00855 {
00856     /* already set hardware swap if LTX hub */
00857     if (hubload)
00858         return val;
00859 
00860     return (
00861         ((val & 0x000000ff) << 24)
00862         | ((val & 0x0000ff00) << 8)
00863         | ((val & 0x00ff0000) >> 8)
00864         | ((val & 0xff000000) >> 24));
00865 }
00866 
00867 #if 0 /* not used anywhere? */
00868 void
00869 prog_write(u_int val)
00870 {
00871     if(needswap) *cfgaddr = swap32(val) ;
00872     else *cfgaddr = val ;
00873 }
00874 
00875 u_int
00876 prog_read()
00877 {
00878     if(needswap) return (swap32(*cfgaddr)) ;
00879     else return (*cfgaddr) ;
00880 }
00881 #endif
00882 
00883 void tst_init(EdtDev *edt_p, int verbose)
00884 {
00885     edt_p->mapaddr = (caddr_t)edt_mapmem(edt_p, 0, 256) ;
00886     cfgaddr = (volatile u_int *)(edt_p->mapaddr + (EDT_DMA_CFG & 0xff)) ;
00887 
00888     if (hubload)
00889     {
00890         printf("HUBLOAD INTERNAL ERROR: should never call tst_init\n");
00891         exit(1);
00892     }
00893 
00894     needswap = !edt_little_endian();
00895 #ifdef sgi
00896     needswap = 0 ;
00897 #endif
00898 
00899     if (verbose )
00900         printf("  mapaddr %p cfgaddr %p needswap %d\n",edt_p->mapaddr,cfgaddr,needswap) ;
00901 }
00902 
00903 void
00904 tst_write(EdtDev * edt_p, uint_t desc, uint_t val)
00905 {
00906     u_int dmy;
00907 
00908     if (hubload || do_fast)
00909     {
00910         if (debug_fast & 0x10)
00911             edt_msleep(1);
00912 
00913         if (hubload)
00914             tstaddr = (volatile u_int *)(edt_p->mapaddr + desc);
00915         else tstaddr = (volatile u_int *)(edt_p->mapaddr + (desc & 0xff)) ;
00916 
00917 
00918         if (needswap)
00919         {
00920             *tstaddr = swap32(val) ;
00921             /* printf("DEBUG tst_write desc %x mapaddr %x tstaddr %x val %x (SWAP)\n", desc, edt_p->mapaddr, tstaddr, val); */
00922 
00923             /* debug: try writing a few more times */
00924             if (debug_fast & 0x1)
00925             {
00926                 *tstaddr = swap32(val) ;
00927                 *tstaddr = swap32(val) ;
00928                 *tstaddr = swap32(val) ;
00929                 *tstaddr = swap32(val) ;
00930             }
00931         }
00932         else
00933         {
00934             *tstaddr = val ;
00935 
00936             /* printf("DEBUG tst_write desc %x mapaddr %x tstaddr %x val %x\n", desc, edt_p->mapaddr, tstaddr, val); */
00937 
00938             /* debug: try writing a few more times */
00939             if (debug_fast & 0x1)
00940             {
00941                 *tstaddr = val ;
00942                 *tstaddr = val ;
00943                 *tstaddr = val ;
00944                 *tstaddr = val ;
00945             }
00946         }
00947 
00948         dmy = *tstaddr;
00949 
00950         /* okay do a few more reads while things settle down if needed (-F 2) */
00951         if (debug_fast & 0x2)
00952         {
00953             dmy = *tstaddr;
00954             dmy = *tstaddr;
00955             dmy = *tstaddr;
00956             dmy = *tstaddr;
00957             dmy = *tstaddr;
00958         }
00959     }
00960     else 
00961     {
00962         edt_reg_write(edt_p, desc, val) ;
00963         dmy = edt_reg_read(edt_p, desc) ;
00964     }
00965 }
00966 
00967 uint_t
00968 tst_read(EdtDev * edt_p, uint_t desc)
00969 {
00970     u_int       ret;
00971 
00972     if (do_fast || hubload)
00973     {
00974         if (debug_fast & 0x20)
00975             edt_msleep(1);
00976         if (hubload)
00977             tstaddr = (volatile u_int *)(edt_p->mapaddr + desc) ;
00978         else tstaddr = (volatile u_int *)(edt_p->mapaddr + (desc & 0xff)) ;
00979 
00980         if (needswap)
00981         {
00982             ret = (swap32(*tstaddr)) ;
00983         }
00984         else ret =  (*tstaddr) ;
00985 
00986 
00987         /* debug: try reading a few more times */
00988         if (debug_fast & 0x4)
00989         {
00990             ret = *tstaddr;
00991             ret = *tstaddr;
00992             ret = *tstaddr;
00993             ret = *tstaddr;
00994         }
00995 
00996         /* printf("DEBUG tst_read desc %x mapaddr %x tstaddr %x ret %x\n", desc, edt_p->mapaddr, tstaddr, ret); */
00997 
00998         return ret;
00999     }
01000     else return(edt_reg_read(edt_p, desc)) ;
01001 }
01002 
01003 void tst_pflash(EdtDev *edt_p, uint_t addr, uint_t val)
01004 {
01005     if (hubload)
01006     {
01007         printf("ERROR -- tst_pflash with hubload N/A!\n");
01008         return;
01009     }
01010 
01011     tst_write(edt_p, EDT_FLASHROM_DATA, (u_char) 0xaa);
01012     (void) tst_read(edt_p, EDT_FLASHROM_ADDR);
01013     tst_write(edt_p, EDT_FLASHROM_ADDR, (u_int) (0x5555 | EDT_WRITECMD));
01014     (void) tst_read(edt_p, EDT_FLASHROM_ADDR);
01015     tst_write(edt_p, EDT_FLASHROM_DATA, (u_char) 0x55);
01016     (void) tst_read(edt_p, EDT_FLASHROM_ADDR);
01017     tst_write(edt_p, EDT_FLASHROM_ADDR, (u_int) (0x2aaa | EDT_WRITECMD));
01018     (void) tst_read(edt_p, EDT_FLASHROM_ADDR);
01019     tst_write(edt_p, EDT_FLASHROM_DATA, (u_char) 0xa0);
01020     (void) tst_read(edt_p, EDT_FLASHROM_ADDR);
01021     tst_write(edt_p, EDT_FLASHROM_ADDR, (u_int) (0x5555 | EDT_WRITECMD));
01022     (void) tst_read(edt_p, EDT_FLASHROM_ADDR);
01023     tst_write(edt_p, EDT_FLASHROM_DATA, (u_char) val);
01024     (void) tst_read(edt_p, EDT_FLASHROM_ADDR);
01025     tst_write(edt_p, EDT_FLASHROM_ADDR, 
01026         (u_int) (EN_HIGH_ADD | addr | EDT_WRITECMD));
01027     (void) tst_read(edt_p, EDT_FLASHROM_ADDR);
01028 }
01029 
01030 /*
01031 * check ltx hub. return -1 if not an SS4, 0 if is an SS4 but no hub found, 1 if ok
01032 */
01033 int
01034 edt_check_ltx_hub(EdtDev *edt_p)
01035 {
01036     if ((!edt_p) || ((edt_p->devid != PSS4_ID) && (edt_p->devid != PCDFOX_ID)))
01037         return -1;
01038     if (ltx_tst_init(edt_p) < 0)
01039         return -1;
01040     if (tst_read(edt_p, EDT_FLASHROM_LTXHUB(edt_p->hubidx)) == 0xdeaddead)
01041         return -1;
01042     return 0;
01043 }
01044 
01045 static struct
01046 {
01047     u_int   mid;
01048     u_int   devid;
01049     u_int   prom;
01050 }       older_devices[] =
01051 
01052 {
01053     {
01054         0x1, 0x20, AMD_4013E
01055     },
01056     {
01057         0x1, 0x4f, AMD_4013XLA
01058     },
01059         {
01060             0x20, 0xe3, AMD_4013XLA
01061         },
01062         {
01063             0x00, 0x00, 0
01064         }
01065 };
01066 
01067 
01068 /* write a byte to the PCI interface prom (only 4013E and 4013XLA) */
01069 void
01070 xwrite(EdtDev * edt_p, u_int addr, u_char val)
01071 {
01072     edt_buf buf;
01073 
01074     if (hubload)
01075     {
01076         printf("ERROR -- xwrite with hubload N/A!\n");
01077         return;
01078     }
01079 
01080     if (do_fast)
01081     {
01082         (void)tst_read(edt_p, EDT_FLASHROM_ADDR);
01083         tst_write(edt_p, EDT_FLASHROM_DATA, val) ;
01084         (void)tst_read(edt_p, EDT_FLASHROM_ADDR);
01085         tst_write(edt_p, EDT_FLASHROM_ADDR, EN_HIGH_ADD | addr | EDT_WRITECMD) ;
01086     }
01087     else
01088     {
01089         buf.desc = EN_HIGH_ADD | addr;
01090         buf.value = val;
01091         edt_ioctl(edt_p, EDTS_FLASH, &buf);
01092     }
01093 }
01094 
01095 /* read a byte from the PCI interface prom (only 4013E and 4013XLA) */
01096 u_char
01097 xread(EdtDev * edt_p, u_int addr)
01098 {
01099     u_char  val;
01100     edt_buf buf;
01101 
01102     if (do_fast)
01103     {
01104         (void)tst_read(edt_p, EDT_FLASHROM_ADDR);
01105         tst_write(edt_p, EDT_FLASHROM_ADDR, EN_HIGH_ADD | addr) ;
01106         (void)tst_read(edt_p, EDT_FLASHROM_ADDR);
01107         return(tst_read(edt_p, EDT_FLASHROM_DATA));
01108     }
01109     else
01110     {
01111         buf.desc = EN_HIGH_ADD | addr;
01112         edt_ioctl(edt_p, EDTG_FLASH, &buf);
01113         val = (u_char) buf.value;
01114         return (val);
01115     }
01116 }
01117 
01118 /* ?reset? 4013e or 4013xla */
01119 void 
01120 xreset(EdtDev * edt_p)
01121 {
01122     xwrite(edt_p, 0x5555, 0xaa);
01123     xwrite(edt_p, 0x2aaa, 0x55);
01124     xwrite(edt_p, 0x5555, 0xf0);
01125 }
01126 
01127 /*
01128 * write a byte to the PROM thru the boot controller on the 4028xla
01129 */
01130 static void
01131 bt_write(EdtDev * edt_p, uint_t desc, u_int addr, u_char val)
01132 {
01133     /* write the address out in three chunks to the boot controller */
01134     /* first all commands are off */
01135     tst_write(edt_p, desc, 0);
01136     /* first byte of address */
01137     tst_write(edt_p, desc, BT_LD_LO | (addr & 0xff));
01138     tst_write(edt_p, desc, 0);
01139     /* second byte of address */
01140     tst_write(edt_p, desc, BT_LD_MID | ((addr >> 8) & 0xff));
01141     tst_write(edt_p, desc, 0);
01142 
01143     /* third byte of address */
01144     tst_write(edt_p, desc, BT_LD_HI | ((addr >> 16) & 0xff));
01145     tst_write(edt_p, desc, 0);
01146 
01147     tst_write(edt_p, desc, BT_LD_ROM | (val & 0xff));
01148     tst_write(edt_p, desc, 0);
01149 }
01150 
01151 
01152 /*
01153 * read a byte from the 4028xla prom through the boot controller.
01154 */
01155 static u_char
01156 bt_read(EdtDev * edt_p, uint_t desc, u_int addr)
01157 {
01158     u_char  stat;
01159 
01160     /* write the address out in three chunks to the boot controller */
01161     /* first all commands are off */
01162     tst_write(edt_p, desc, 0);
01163     /* first byte of address */
01164     tst_write(edt_p, desc, BT_LD_LO | (addr & 0xff));
01165     /* clear BT_LD_LO */
01166     tst_write(edt_p, desc, 0);
01167     /* second byte of address */
01168     tst_write(edt_p, desc, BT_LD_MID | ((addr >> 8) & 0xff));
01169     /* clear BT_LD_MID */
01170     tst_write(edt_p, desc, 0);
01171     /* third byte of address */
01172     tst_write(edt_p, desc, BT_LD_HI | ((addr >> 16) & 0xff));
01173     /* clear BT_LD_HI , set rd command and disable output buffer */
01174     tst_write(edt_p, desc, BT_RD_ROM);
01175 
01176     /* read the byte */
01177     stat = (u_char) tst_read(edt_p, desc);
01178     /* all commands are off */
01179     tst_write(edt_p, desc, 0);
01180     return (stat);
01181 }
01182 
01183 
01184 /* ?reset? the 4028xla */
01185 static void 
01186 bt_reset(EdtDev * edt_p, uint_t desc)
01187 {
01188     bt_write(edt_p, desc, 0x555, 0xaa);
01189     bt_write(edt_p, desc, 0x2aa, 0x55);
01190     bt_write(edt_p, desc, 0x555, 0xf0);
01191 }
01192 
01193 /* ?reset? for xc5vlx30t, xc5vlx50t, ep2sgx30d */
01194 static void 
01195 bt2_reset(EdtDev * edt_p, uint_t desc)
01196 {
01197     bt_write(edt_p, desc, 0x0, 0xf0);
01198 }
01199 
01200 /*
01201 * read the jumper position and bus voltage from the boot controller
01202 */
01203 static u_char
01204 bt_readstat(EdtDev * edt_p, uint_t desc)
01205 {
01206     u_char  stat;
01207     uint_t rdval;
01208 
01209     /*
01210     * read the boot controller status A0 and A1 low with read asserted -
01211     * enables boot controller on bus
01212     */
01213     tst_write(edt_p, desc, 0);
01214     tst_write(edt_p, desc, BT_EN_READ | BT_READ);
01215     rdval = tst_read(edt_p, desc);
01216     stat = (u_char) rdval;
01217     /* reset all boot command */
01218     tst_write(edt_p, desc, 0);
01219     return (stat);
01220 }
01221 
01222 
01223 u_char
01224 xreadstat(EdtDev * edt_p)
01225 {
01226     u_char  stat;
01227     uint_t  rdval;
01228 
01229     if (hubload)
01230     {
01231         printf("ERROR -- xreadstat with hubload N/A!\n");
01232         return 0;
01233     }
01234 
01235 
01236     /*
01237     * disable the high address drive by writing 0 to bit24 of FPROM address
01238     * register.
01239     */
01240     tst_write(edt_p, EDT_FLASHROM_ADDR, 0);
01241     rdval = tst_read(edt_p, EDT_FLASHROM_DATA);
01242     stat = (u_char) (rdval >> 8);
01243     return (stat);
01244 }
01245 
01246 u_char
01247 edt_x_read(EdtDev * edt_p, u_int addr, int xtype)
01248 {
01249     u_char  val;
01250 
01251     switch(xtype)
01252     {
01253     case XTYPE_SPI:
01254         spi_read(edt_p, addr, &val, 1);
01255         return val;
01256         break;
01257     case XTYPE_BT:
01258     case XTYPE_BT2:
01259         return bt_read(edt_p, EDT_FLASHROM_DATA, addr);
01260         break;
01261     case XTYPE_X:
01262         return xread(edt_p, addr);
01263         break;
01264     case XTYPE_LTX:
01265         return bt_read(edt_p, EDT_FLASHROM_LTXHUB(edt_p->hubidx), addr);
01266         break;
01267     }
01268 
01269     return 0;
01270 }
01271 
01272 void
01273 edt_x_print16(EdtDev * edt_p, u_int addr, int xtype)
01274 {
01275     switch(xtype)
01276     {
01277     case XTYPE_SPI:
01278         spi_print16(edt_p, (u_int)addr);
01279         break;
01280     case XTYPE_BT:
01281     case XTYPE_BT2:
01282         bt_print16(edt_p, EDT_FLASHROM_DATA, addr);
01283         break;
01284     case XTYPE_X:
01285         xprint16(edt_p, addr);
01286         break;
01287     case XTYPE_LTX:
01288         bt_print16(edt_p, EDT_FLASHROM_LTXHUB(edt_p->hubidx), addr);
01289         break;
01290     }
01291 }
01292 
01293 /*
01294 * print 16 bytes at the address passed read from 4028xla boot controller
01295 */
01296 void
01297 bt_print16(EdtDev * edt_p, uint_t desc, u_int addr)
01298 {
01299     int     i;
01300 
01301     printf("%08x ", addr);
01302     for (i = 1; i < 16; i++)
01303     {
01304         printf(" %02x", bt_read(edt_p, desc, addr));
01305         addr++;
01306     }
01307     printf("\n");
01308 }
01309 
01310 /*
01311 * print 16 bytes at the address passed
01312 */
01313 void
01314 xprint16(EdtDev * edt_p, u_int addr)
01315 {
01316     int     i;
01317 
01318     printf("%08x ", addr);
01319     for (i = 1; i < 16; i++)
01320     {
01321         printf(" %02x", xread(edt_p, addr));
01322         addr++;
01323     }
01324     printf("\n");
01325 }
01326 
01327 /*
01328 * print 16 bytes at the address passed
01329 */
01330 void
01331 spi_print16(EdtDev * edt_p, u_int addr)
01332 {
01333     int     i;
01334     u_char val;
01335 
01336     printf("%08x ", addr);
01337     for (i = 1; i < 16; i++)
01338     {
01339         spi_read(edt_p, (u_int)addr, &val, 1);
01340         printf(" %02x", val);
01341         addr++;
01342     }
01343     printf("\n");
01344 }
01345 
01346 int
01347 edt_sector_erase(EdtDev * edt_p, u_int sector, u_int sec_size, int xtype)
01348 {
01349     switch(xtype)
01350     {
01351     case XTYPE_SPI:
01352         spi_sector_erase(edt_p, sector << 16);
01353         break;
01354     case XTYPE_BT:
01355         bt_sector_erase(edt_p, sector, sec_size, EDT_FLASHROM_DATA);
01356         break;
01357     case XTYPE_BT2:
01358         bt2_sector_erase(edt_p, sector, sec_size, EDT_FLASHROM_DATA);
01359         break;
01360     case XTYPE_X:
01361         xsector_erase(edt_p, sector, sec_size);
01362         break;
01363     case XTYPE_LTX:
01364         bt_sector_erase(edt_p, sector, sec_size, EDT_FLASHROM_LTXHUB(edt_p->hubidx));
01365         break;
01366     }
01367     return 0;
01368 }
01369 
01370 /*
01371 * sector erase for AMD 29LV0XXX
01372 */
01373 static int
01374 bt_sector_erase(EdtDev * edt_p, u_int sector, u_int sec_size, uint_t desc)
01375 {
01376     u_int   addr;
01377     int     done = 0;
01378     int     loops = 0;
01379     u_char  val;
01380 
01381     addr = sector * sec_size;
01382     bt_write(edt_p, desc, 0x5555, 0xaa);
01383     bt_write(edt_p, desc, 0x2aaa, 0x55);
01384     bt_write(edt_p, desc, 0x5555, 0x80);
01385     bt_write(edt_p, desc, 0x5555, 0xaa);
01386     bt_write(edt_p, desc, 0x2aaa, 0x55);
01387     bt_write(edt_p, desc, addr, 0x30);
01388     done = 0;
01389     while (!done)
01390     {
01391         val = bt_read(edt_p, desc, addr);
01392         loops++;
01393         if (val & DQ7)
01394         {
01395             done = 1;
01396         }
01397     }
01398     return 0;
01399 }
01400 
01401 /*
01402  * sector erase for AMD S29GL64N, S29GL128N
01403  */
01404 static int
01405 bt2_sector_erase(EdtDev * edt_p, u_int sector, u_int sec_size, uint_t desc)
01406 {
01407     u_int   addr;
01408     int     done = 0;
01409     int     loops = 0;
01410     u_char  val;
01411 
01412     addr = sector * sec_size;
01413     bt_write(edt_p, desc, 0xaaa, 0xaa);
01414     bt_write(edt_p, desc, 0x555, 0x55);
01415     bt_write(edt_p, desc, 0xaaa, 0x80);
01416     bt_write(edt_p, desc, 0xaaa, 0xaa);
01417     bt_write(edt_p, desc, 0x555, 0x55);
01418     bt_write(edt_p, desc, addr, 0x30);
01419     done = 0;
01420     while (!done)
01421     {
01422         val = bt_read(edt_p, desc, addr);
01423         loops++;
01424         if (val & DQ7)
01425         {
01426             done = 1;
01427         }
01428     }
01429     return 0;
01430 }
01431 
01432 static int
01433 xsector_erase(EdtDev * edt_p, u_int sector, u_int sec_size)
01434 {
01435     u_int   addr;
01436     int     done = 0;
01437     int     loops = 0;
01438     u_char  val;
01439 
01440     addr = sector * sec_size;
01441     xwrite(edt_p, 0x5555, 0xaa);
01442     xwrite(edt_p, 0x2aaa, 0x55);
01443     xwrite(edt_p, 0x5555, 0x80);
01444     xwrite(edt_p, 0x5555, 0xaa);
01445     xwrite(edt_p, 0x2aaa, 0x55);
01446     xwrite(edt_p, addr, 0x30);
01447     done = 0;
01448     while (!done)
01449     {
01450         val = xread(edt_p, addr);
01451         loops++;
01452         if (val & DQ7)
01453         {
01454             done = 1;
01455             break;
01456         }
01457     }
01458     return 0;
01459 }
01460 
01461 
01462 /*
01463 * for 4028xla, xc2s100, xc2s200
01464 */
01465 static int
01466 bt_byte_program(EdtDev * edt_p, int xtype, uint_t desc, u_int addr, u_char data)
01467 {
01468     u_char  val;
01469     int     done = 0;
01470     int     loops = 0;
01471 
01472     bt_write(edt_p, desc, 0x5555, 0xaa);
01473     bt_write(edt_p, desc, 0x2aaa, 0x55);
01474     bt_write(edt_p, desc, 0x5555, 0xa0);
01475     bt_write(edt_p, desc, addr, data);
01476     tst_write(edt_p, desc, BT_RD_ROM);
01477 
01478     while (!done)
01479     {
01480         val = (u_char) tst_read(edt_p, desc);
01481 
01482         if (val == data)
01483             done = 1;
01484         if (loops > 1000)
01485         {
01486             printf("bt_byte_program: failed on %x data %x val %x\n",
01487                 addr, data, val);
01488             bt_reset(edt_p, desc);
01489             bt_write(edt_p, desc, 0x555, 0xaa);
01490             bt_write(edt_p, desc, 0x2aa, 0x55);
01491             bt_write(edt_p, desc, 0x555, 0xa0);
01492             bt_write(edt_p, desc, addr, data);
01493             tst_write(edt_p, desc, BT_RD_ROM);
01494             loops = 0;
01495         }
01496         loops++;
01497     }
01498     if (loops > maxloops)
01499     {
01500         maxloops = loops;
01501     }
01502     if (done)
01503         return (0);
01504     else
01505         return (addr);
01506 }
01507 
01508 /*
01509  * for xc5vlx30t, xc5vlx50t, ep2sgx30d
01510  */
01511 static int
01512 bt2_byte_program(EdtDev * edt_p, int xtype, uint_t desc, u_int addr, u_char data)
01513 {
01514     u_char  val;
01515     int     done = 0;
01516     int     loops = 0;
01517     int     failures = 0;
01518 
01519     bt_write(edt_p, desc, 0xaaa, 0xaa);
01520     bt_write(edt_p, desc, 0x555, 0x55);
01521     bt_write(edt_p, desc, 0xaaa, 0xa0);
01522     bt_write(edt_p, desc, addr, data);
01523     tst_write(edt_p, desc, BT_RD_ROM);
01524 
01525     while (!done)
01526     {
01527         val = (u_char) tst_read(edt_p, desc);
01528 
01529         if (val == data)
01530             done = 1;
01531         if (loops > 1000)
01532         {
01533             bt2_reset(edt_p, desc);
01534             bt_write(edt_p, desc, 0xaaa, 0xaa);
01535             bt_write(edt_p, desc, 0x555, 0x55);
01536             bt_write(edt_p, desc, 0xaaa, 0xa0);
01537             bt_write(edt_p, desc, addr, data);
01538             tst_write(edt_p, desc, BT_RD_ROM);
01539             loops = 0;
01540             failures++;
01541         }
01542         loops++;
01543         if (failures > 5)
01544         {
01545             printf("bt2_byte_program: failed on %x data %x val %x\n", addr, data, val);
01546             break;
01547         }
01548     }
01549     if (loops > maxloops)
01550     {
01551         maxloops = loops;
01552     }
01553     if (done)
01554         return (0);
01555     else
01556         return (addr);
01557 }
01558 
01559 void
01560 edt_ltx_reboot(EdtDev *edt_p)
01561 {
01562     tst_write(edt_p, EDT_FLASHROM_LTXHUB(edt_p->hubidx), 0x4000);
01563 }
01564 
01565 /*
01566 * for 4013e and others
01567 */
01568 
01569 /* return 0 for success */
01570 int
01571 xbyte_program(EdtDev * edt_p, u_int addr, u_char data)
01572 {
01573     u_char  val;
01574     edt_buf buf;
01575     int     done = 0;
01576     int     loops = 0;
01577 
01578     if (do_fast)
01579     {
01580         tst_pflash(edt_p, addr, data) ;
01581     }
01582     else
01583     {
01584         buf.desc = EN_HIGH_ADD | addr;
01585         buf.value = data;
01586         edt_ioctl(edt_p, EDT_PFLASH, &buf);
01587     }
01588     while (!done)
01589     {
01590         loops++;
01591         val = xread(edt_p, addr);
01592         if (val == data)
01593             done = 1;
01594         if (loops > 100)
01595         {
01596             printf("xbyte_program: failed on %x data %x val %x\n",
01597                 addr, data, val);
01598             loops = 0;
01599         }
01600     }