#include "flash.h" #include "debug.h" #include "hv.h" #include "time.h" /* flash device only allows 256K writes */ #define FLASH_WRITE_UNIT (256*1024) static __inline__ int check_otheros_flash(unsigned char *buf) { int i; for(i=0; i<16; i++) if(buf[i] != "cell_ext_os_area"[i]) return 0; return *(int *)(buf+16) == 1; } static int wait_for_io(unsigned long device_id, unsigned long tag, unsigned long *status, unsigned long timeout) { unsigned long rtag; long r; for(;;) { r = lv1_storage_get_async_status(device_id, &rtag, status); if(!r && rtag == tag) return 1; if(!timeout) { DBG(" TIMEOUT "); break; } else if(timeout > 25000) { usleep(25000); timeout -= 25000; } else { usleep(timeout); timeout = 0; } } return 0; } int set_boot_flag(int boot_flag) { long r; unsigned long v1, v2, ndev, nreg, blk_size, nblks, dma_addr, tag, status; int bus_index; unsigned long dev_index, reg_index; unsigned long bus_id, device_id, region_id; static unsigned char buf[FLASH_WRITE_UNIT] __attribute__((section(".bss.page_aligned"))); int rc = 0; /* Find storage bus */ for(bus_index=0; bus_index<128; bus_index++) { r = lv1_get_repository_node_value(1, 0x0000000062757300+bus_index, /* "bus" */ 0x7479706500000000, /* "type" */ 0, 0, &v1, &v2); if(r) return 0; if(v1 != 5 /* storage type */) continue; r = lv1_get_repository_node_value(1, 0x0000000062757300+bus_index, /* "bus" */ 0x6964000000000000, /* "id" */ 0, 0, &v1, &v2); if(r) return 0; bus_id = v1; r = lv1_get_repository_node_value(1, 0x0000000062757300+bus_index, /* "bus" */ 0x6e756d5f64657600, /* "num_dev" */ 0, 0, &v1, &v2); if(r) return 0; ndev = v1; /* Look for flash devices */ for(dev_index=0; dev_index sizeof(buf)) continue; nblks = sizeof(buf)/blk_size; r = lv1_get_repository_node_value(1, 0x0000000062757300+bus_index, /* "bus" */ 0x6465760000000000+dev_index, /* "dev" */ 0x6964000000000000, /* "id" */ 0, &v1, &v2); device_id = v1; r = lv1_get_repository_node_value(1, 0x0000000062757300+bus_index, /* "bus" */ 0x6465760000000000+dev_index, /* "dev" */ 0x6e5f726567730000, /* "n_regs" */ 0, &v1, &v2); if(r) return 0; nreg = v1; r = lv1_open_device(bus_id, device_id, 0); if(r) continue; r = lv1_allocate_device_dma_region(bus_id, device_id, 128*1024*1024, 12, 0, &dma_addr); if(r) { lv1_close_device(bus_id, device_id); continue; } r = lv1_map_device_dma_region(bus_id, device_id, 0, dma_addr, 128*1024*1024, 0xf800000000000000UL); if(r) { lv1_free_device_dma_region(bus_id, device_id, dma_addr); lv1_close_device(bus_id, device_id); continue; } for(reg_index=0; reg_index %ld [%lx]\n", r, tag); if(r) break; if(!wait_for_io(device_id, tag, &status, 5000000) || status != 0) break; DBG("Bootflag successfully set to %d!\n", boot_flag); rc = 1; break; } lv1_unmap_device_dma_region(bus_id, device_id, dma_addr, 128*1024*1024); lv1_free_device_dma_region(bus_id, device_id, dma_addr); lv1_close_device(bus_id, device_id); if(rc) return rc; } } return 0; }