/* Reset adapter's CPU. */ static int reset_cyc2x(void __iomem *addr) { writeb(0, addr + RST_ENABLE); delay_cycx(2); writeb(0, addr + RST_DISABLE); delay_cycx(2); return memory_exists(addr); }
/* Reset adapter's CPU. */ static int reset_cyc2x(u32 addr) { cyc2x_writeb(0, addr + RST_ENABLE); delay_cycx(2); cyc2x_writeb(0, addr + RST_DISABLE); delay_cycx(2); return memory_exists(addr); }
/* Load and boot reset code. */ static void cycx_reset_boot(void __iomem *addr, u8 *code, u32 len) { void __iomem *pt_start = addr + START_OFFSET; writeb(0xea, pt_start++); /* jmp to f000:3f00 */ writeb(0x00, pt_start++); writeb(0xfc, pt_start++); writeb(0x00, pt_start++); writeb(0xf0, pt_start); reset_load(addr, code, len); /* 80186 was in hold, go */ writeb(0, addr + START_CPU); delay_cycx(1); }
/* Reset board hardware. return 1 if memory exists at addr and 0 if not. */ static int memory_exists(void __iomem *addr) { int tries = 0; for (; tries < 3 ; tries++) { writew(TEST_PATTERN, addr + 0x10); if (readw(addr + 0x10) == TEST_PATTERN) if (readw(addr + 0x10) == TEST_PATTERN) return 1; delay_cycx(1); } return 0; }
/* Reset board hardware. return 1 if memory exists at addr and 0 if not. */ static int memory_exists(u32 addr) { int tries = 0; for (; tries < 3 ; tries++) { cyc2x_writew(TEST_PATTERN, addr + 0x10); if (cyc2x_readw(addr + 0x10) == TEST_PATTERN) if (cyc2x_readw(addr + 0x10) == TEST_PATTERN) return 1; delay_cycx(1); } return 0; }
/* Load adapter from the memory image of the CYCX firmware module. * o verify firmware integrity and compatibility * o start adapter up */ static int load_cyc2x(struct cycx_hw *hw, struct cycx_firmware *cfm, u32 len) { int i, j; struct cycx_fw_header *img_hdr; u8 *reset_image, *data_image, *code_image; void __iomem *pt_cycld = hw->dpmbase + 0x400; u16 cksum; /* Announce */ printk(KERN_INFO "%s: firmware signature=\"%s\"\n", modname, cfm->signature); /* Verify firmware signature */ if (strcmp(cfm->signature, CFM_SIGNATURE)) { printk(KERN_ERR "%s:load_cyc2x: not Cyclom-2X firmware!\n", modname); return -EINVAL; } printk(KERN_INFO "%s: firmware version=%u\n", modname, cfm->version); /* Verify firmware module format version */ if (cfm->version != CFM_VERSION) { printk(KERN_ERR "%s:%s: firmware format %u rejected! " "Expecting %u.\n", modname, __FUNCTION__, cfm->version, CFM_VERSION); return -EINVAL; } /* Verify firmware module length and checksum */ cksum = checksum((u8*)&cfm->info, sizeof(struct cycx_fw_info) + cfm->info.codesize); /* FIXME cfm->info.codesize is off by 2 if (((len - sizeof(struct cycx_firmware) - 1) != cfm->info.codesize) || */ if (cksum != cfm->checksum) { printk(KERN_ERR "%s:%s: firmware corrupted!\n", modname, __FUNCTION__); printk(KERN_ERR " cdsize = 0x%x (expected 0x%lx)\n", len - (int)sizeof(struct cycx_firmware) - 1, cfm->info.codesize); printk(KERN_ERR " chksum = 0x%x (expected 0x%x)\n", cksum, cfm->checksum); return -EINVAL; } /* If everything is ok, set reset, data and code pointers */ img_hdr = (struct cycx_fw_header *)&cfm->image; #ifdef FIRMWARE_DEBUG printk(KERN_INFO "%s:%s: image sizes\n", __FUNCTION__, modname); printk(KERN_INFO " reset=%lu\n", img_hdr->reset_size); printk(KERN_INFO " data=%lu\n", img_hdr->data_size); printk(KERN_INFO " code=%lu\n", img_hdr->code_size); #endif reset_image = ((u8 *)img_hdr) + sizeof(struct cycx_fw_header); data_image = reset_image + img_hdr->reset_size; code_image = data_image + img_hdr->data_size; /*---- Start load ----*/ /* Announce */ printk(KERN_INFO "%s: loading firmware %s (ID=%u)...\n", modname, cfm->descr[0] ? cfm->descr : "unknown firmware", cfm->info.codeid); for (i = 0 ; i < 5 ; i++) { /* Reset Cyclom hardware */ if (!reset_cyc2x(hw->dpmbase)) { printk(KERN_ERR "%s: dpm problem or board not found\n", modname); return -EINVAL; } /* Load reset.bin */ cycx_reset_boot(hw->dpmbase, reset_image, img_hdr->reset_size); /* reset is waiting for boot */ writew(GEN_POWER_ON, pt_cycld); delay_cycx(1); for (j = 0 ; j < 3 ; j++) if (!readw(pt_cycld)) goto reset_loaded; else delay_cycx(1); } printk(KERN_ERR "%s: reset not started.\n", modname); return -EINVAL; reset_loaded: /* Load data.bin */ if (cycx_data_boot(hw->dpmbase, data_image, img_hdr->data_size)) { printk(KERN_ERR "%s: cannot load data file.\n", modname); return -EINVAL; } /* Load code.bin */ if (cycx_code_boot(hw->dpmbase, code_image, img_hdr->code_size)) { printk(KERN_ERR "%s: cannot load code file.\n", modname); return -EINVAL; } /* Prepare boot-time configuration data */ cycx_bootcfg(hw); /* kick-off CPU */ cycx_start(hw->dpmbase); /* Arthur Ganzert's tip: wait a while after the firmware loading... seg abr 26 17:17:12 EST 1999 - acme */ delay_cycx(7); printk(KERN_INFO "%s: firmware loaded!\n", modname); /* enable interrupts */ cycx_inten(hw); return 0; }