FreeCalypso > hg > freecalypso-tools
view loadtools/flutil.c @ 407:19e5a3e2f9c0
fcup-settime: moved time() retrieval a little closer to the output
A fundamental problem with all simple time transfer tools is that there is
always some delay between the time retrieval on the source system and that
transmitted time being set on the destination, and the resulting time
on the destination system is off by that delay amount. This delay cannot
be fully eliminated when working in a simple environment like ours,
but we should make our best effort to minimize it. In the present case,
moving the atinterf_init() call before the time() retrieval should make
a teensy-tiny improvement.
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Sat, 11 Aug 2018 21:52:17 +0000 |
parents | e7502631a0f9 |
children | 7bf0d909c87e |
line wrap: on
line source
/* * Miscellaneous utility functions for flash support */ #include <sys/types.h> #include <stdio.h> #include <stdint.h> #include <stdlib.h> #include "flash.h" extern struct flash_bank_info flash_bank_info[2]; extern struct flash_cmdset flash_cmdset_amd; extern struct flash_cmdset flash_cmdset_intel; static int cfi_read_byte(bi, off, ret16p) struct flash_bank_info *bi; int off; uint16_t *ret16p; { return do_r16(bi->base_addr + (off << 1), ret16p); } static int cfi_read_twobyte(bi, off, retptr) struct flash_bank_info *bi; int off; uint16_t *retptr; { uint16_t lo, hi; if (cfi_read_byte(bi, off, &lo) < 0) return(-1); lo &= 0xFF; if (cfi_read_byte(bi, off + 1, &hi) < 0) return(-1); hi &= 0xFF; *retptr = (hi << 8) | lo; return(0); } flash_get_cfi(bank) { struct flash_bank_info *bi; struct flash_geom *geom; struct flash_region_desc *reg; int nr; uint16_t rdval, cmdset_id; uint32_t size_check; bi = flash_bank_info + bank; if (bi->geom) return(0); printf("Performing CFI query\n"); if (do_w16(bi->base_addr + 0xAA, 0x98)) { fprintf(stderr, "unexpected response to w16 - aborting\n"); return(-1); } /* if do_r16() returns -1, error msg has already been printed */ if (cfi_read_byte(bi, 0x10, &rdval) < 0) return(-1); if (rdval != 'Q') { noqry: fprintf(stderr, "error: no QRY response from flash\n"); amd_reset_cmd(bi); return(-1); } if (cfi_read_byte(bi, 0x11, &rdval) < 0) return(-1); if (rdval != 'R') goto noqry; if (cfi_read_byte(bi, 0x12, &rdval) < 0) return(-1); if (rdval != 'Y') goto noqry; if (cfi_read_twobyte(bi, 0x13, &cmdset_id) < 0) return(-1); if (!bi->ops) { switch (cmdset_id) { case 2: bi->ops = &flash_cmdset_amd; break; case 3: bi->ops = &flash_cmdset_intel; break; default: fprintf(stderr, "error: command set %04X unsupported\n", cmdset_id); amd_reset_cmd(bi); return(-1); } } geom = malloc(sizeof(struct flash_geom)); if (!geom) { fprintf(stderr, "unable to malloc buffer for flash bank %d CFI geometry structure\n", bank); bi->ops->reset_cmd(bi); return(-1); } /* total device size */ if (cfi_read_byte(bi, 0x27, &rdval) < 0) { free_and_immed_out: free(geom); return(-1); } if (rdval < 20 || rdval > 24) { fprintf(stderr, "error: CFI reports unreasonable device size\n"); free_and_clean_out: free(geom); bi->ops->reset_cmd(bi); return(-1); } geom->total_size = 1 << rdval; if (geom->total_size > bi->bank_desc->align_size) { fprintf(stderr, "error: CFI device size 0x%lx exceeds configured maximum 0x%lx\n", (u_long) geom->total_size, bi->bank_desc->align_size); goto free_and_clean_out; } if (cfi_read_byte(bi, 0x2C, &rdval) < 0) goto free_and_immed_out; if (rdval < 1 || rdval > CFI_MAX_REGIONS) { fprintf(stderr, "error: CFI reports unreasonable # of erase regions\n"); goto free_and_clean_out; } geom->nregions = rdval; geom->total_sectors = 0; size_check = 0; for (nr = 0; nr < geom->nregions; nr++) { reg = geom->regions + nr; if (cfi_read_twobyte(bi, 0x2D + nr*4, &rdval) < 0) goto free_and_immed_out; if (rdval > 255) { fprintf(stderr, "error: CFI reports unreasonable # of sectors in region %d\n", nr); goto free_and_clean_out; } reg->nsectors = rdval + 1; geom->total_sectors += reg->nsectors; if (cfi_read_twobyte(bi, 0x2F + nr*4, &rdval) < 0) goto free_and_immed_out; if (rdval < 0x20 || rdval > 0x400) { fprintf(stderr, "error: CFI reports unreasonable sector size in region %d\n", nr); goto free_and_clean_out; } reg->sector_size = rdval << 8; size_check += reg->sector_size * reg->nsectors; } if (bi->ops->reset_cmd(bi) < 0) { /* error msg already printed */ free(geom); return(-1); } if (size_check != geom->total_size) { fprintf(stderr, "CFI error: added size of erase regions (%lx) != reported devive size (%lx)\n", (u_long) size_check, (u_long) geom->total_size); free(geom); return(-1); } /* all checks passed */ bi->geom = geom; printf( "CFI query successful: total size %lx, %u sectors, command set style %04X\n", (u_long) geom->total_size, geom->total_sectors, cmdset_id); return(1); } get_flash_sector_table(bank) { struct flash_bank_info *bi; struct flash_geom *geom; struct flash_region_desc *reg; struct sector_info *sp; uint32_t offset; int nr, i; bi = flash_bank_info + bank; if (bi->sectors) return(0); i = flash_get_cfi(bank); if (i < 0) return(i); geom = bi->geom; sp = (struct sector_info *) malloc(sizeof(struct sector_info) * (geom->total_sectors + 1)); if (!sp) { fprintf(stderr, "unable to malloc buffer for flash bank %d sector table\n", bank); return(-1); } bi->sectors = sp; /* now fill it */ offset = 0; for (nr = 0; nr < geom->nregions; nr++) { reg = geom->regions + nr; for (i = 0; i < reg->nsectors; i++) { sp->start = offset; sp->size = reg->sector_size; sp++; offset += reg->sector_size; } } /* sanity checks */ if (sp - bi->sectors != geom->total_sectors) { fprintf(stderr, "BUG in get_flash_sector_table(): wrong # of sectors at the end\n"); abort(); } if (offset != geom->total_size) { fprintf(stderr, "BUG in get_flash_sector_table(): wrong offset at the end\n"); abort(); } /* finish */ sp->start = 0; sp->size = 0; return(0); } flashcmd_sectors(argc, argv, bank) char **argv; { struct flash_bank_info *bi; struct sector_info *sp; if (argc > 2) { fprintf(stderr, "error: too many arguments\n"); return(-1); } if (get_flash_sector_table(bank) < 0) return(-1); bi = flash_bank_info + bank; printf("%u sectors in flash bank %d:\n", bi->geom->total_sectors, bank); printf("Offset Size\n"); for (sp = bi->sectors; sp->size; sp++) printf("%08lX %lx\n", (u_long) sp->start, (u_long) sp->size); return(0); } get_flash_sector_range(bi, useroff, userlen, startp, endp) struct flash_bank_info *bi; u_long useroff, userlen; struct sector_info **startp, **endp; { struct sector_info *sp; uint32_t remlen; for (sp = bi->sectors; sp->size; sp++) if (sp->start == useroff) break; if (!sp->size) { fprintf(stderr, "error: specified offset not aligned to a flash sector boundary\n"); return(-1); } *startp = sp; for (remlen = userlen; remlen; ) { if (remlen < sp->size) { fprintf(stderr, "error: specified length not aligned to a flash sector boundary\n"); return(-1); } remlen -= sp->size; sp++; } *endp = sp; return(0); } build_flashw_hex_string(bin, strbuf, nwords, m0src) u_char *bin; char *strbuf; int nwords, m0src; { int i; u_char *dp; char *s; for (dp = bin, s = strbuf, i = 0; i < nwords; dp += 2, s += 4, i++) { if (m0src) sprintf(s, "%02X%02X", dp[0], dp[1]); else sprintf(s, "%02X%02X", dp[1], dp[0]); } *s = '\0'; } flash_id_check(bank, repeat) { struct flash_bank_info *bi; struct flash_bank_desc *bd; struct flash_idcheck *id; int stat, fail; uint16_t rdval; unsigned cnt; bi = flash_bank_info + bank; if (bi->idcheck_done && !repeat) return(0); bd = bi->bank_desc; if (!bd->idcheck_table || !bd->idcheck_num) return(0); printf("Performing flash ID check\n"); stat = do_w16(bi->base_addr + 0xAAA, 0xAA); if (stat) { bad_w16: fprintf(stderr, "unexpected response to w16 in read ID cmd sequence - aborting\n"); return(-1); } stat = do_w16(bi->base_addr + 0x554, 0x55); if (stat) goto bad_w16; stat = do_w16(bi->base_addr + 0xAAA, 0x90); if (stat) goto bad_w16; id = bd->idcheck_table; fail = 0; for (cnt = 0; cnt < bd->idcheck_num; cnt++) { stat = do_r16(bi->base_addr + id->offset, &rdval); if (stat) return(stat); /* error msg already printed */ printf("offset %02X: %04X -- ", (int)id->offset, (int)rdval); if (rdval == id->expect_val) printf("PASS\n"); else { printf("FAIL: expected %04X\n", (int)id->expect_val); fail = 1; break; } id++; } /* reset flash to read mode */ stat = do_w16(bi->base_addr + 0xAAA, 0xF0); if (stat) { fprintf(stderr, "unexpected response to w16 when resetting flash to read mode!\n"); return(-1); } if (fail) return(-1); bi->idcheck_done = 1; return(0); }