in serial/icom.c [340:502]
static void load_code(struct icom_port *icom_port)
{
const struct firmware *fw;
char __iomem *iram_ptr;
int index;
int status = 0;
void __iomem *dram_ptr = icom_port->dram;
dma_addr_t temp_pci;
unsigned char *new_page = NULL;
unsigned char cable_id = NO_CABLE;
struct pci_dev *dev = icom_port->adapter->pci_dev;
/* Clear out any pending interrupts */
writew(0x3FFF, icom_port->int_reg);
trace(icom_port, "CLEAR_INTERRUPTS", 0);
/* Stop processor */
stop_processor(icom_port);
/* Zero out DRAM */
memset_io(dram_ptr, 0, 512);
/* Load Call Setup into Adapter */
if (request_firmware(&fw, "icom_call_setup.bin", &dev->dev) < 0) {
dev_err(&dev->dev,"Unable to load icom_call_setup.bin firmware image\n");
status = -1;
goto load_code_exit;
}
if (fw->size > ICOM_DCE_IRAM_OFFSET) {
dev_err(&dev->dev, "Invalid firmware image for icom_call_setup.bin found.\n");
release_firmware(fw);
status = -1;
goto load_code_exit;
}
iram_ptr = (char __iomem *)icom_port->dram + ICOM_IRAM_OFFSET;
for (index = 0; index < fw->size; index++)
writeb(fw->data[index], &iram_ptr[index]);
release_firmware(fw);
/* Load Resident DCE portion of Adapter */
if (request_firmware(&fw, "icom_res_dce.bin", &dev->dev) < 0) {
dev_err(&dev->dev,"Unable to load icom_res_dce.bin firmware image\n");
status = -1;
goto load_code_exit;
}
if (fw->size > ICOM_IRAM_SIZE) {
dev_err(&dev->dev, "Invalid firmware image for icom_res_dce.bin found.\n");
release_firmware(fw);
status = -1;
goto load_code_exit;
}
iram_ptr = (char __iomem *) icom_port->dram + ICOM_IRAM_OFFSET;
for (index = ICOM_DCE_IRAM_OFFSET; index < fw->size; index++)
writeb(fw->data[index], &iram_ptr[index]);
release_firmware(fw);
/* Set Hardware level */
if (icom_port->adapter->version == ADAPTER_V2)
writeb(V2_HARDWARE, &(icom_port->dram->misc_flags));
/* Start the processor in Adapter */
start_processor(icom_port);
writeb((HDLC_PPP_PURE_ASYNC | HDLC_FF_FILL),
&(icom_port->dram->HDLCConfigReg));
writeb(0x04, &(icom_port->dram->FlagFillIdleTimer)); /* 0.5 seconds */
writeb(0x00, &(icom_port->dram->CmdReg));
writeb(0x10, &(icom_port->dram->async_config3));
writeb((ICOM_ACFG_DRIVE1 | ICOM_ACFG_NO_PARITY | ICOM_ACFG_8BPC |
ICOM_ACFG_1STOP_BIT), &(icom_port->dram->async_config2));
/*Set up data in icom DRAM to indicate where personality
*code is located and its length.
*/
new_page = dma_alloc_coherent(&dev->dev, 4096, &temp_pci, GFP_KERNEL);
if (!new_page) {
dev_err(&dev->dev, "Can not allocate DMA buffer\n");
status = -1;
goto load_code_exit;
}
if (request_firmware(&fw, "icom_asc.bin", &dev->dev) < 0) {
dev_err(&dev->dev,"Unable to load icom_asc.bin firmware image\n");
status = -1;
goto load_code_exit;
}
if (fw->size > ICOM_DCE_IRAM_OFFSET) {
dev_err(&dev->dev, "Invalid firmware image for icom_asc.bin found.\n");
release_firmware(fw);
status = -1;
goto load_code_exit;
}
for (index = 0; index < fw->size; index++)
new_page[index] = fw->data[index];
writeb((char) ((fw->size + 16)/16), &icom_port->dram->mac_length);
writel(temp_pci, &icom_port->dram->mac_load_addr);
release_firmware(fw);
/*Setting the syncReg to 0x80 causes adapter to start downloading
the personality code into adapter instruction RAM.
Once code is loaded, it will begin executing and, based on
information provided above, will start DMAing data from
shared memory to adapter DRAM.
*/
/* the wait loop below verifies this write operation has been done
and processed
*/
writeb(START_DOWNLOAD, &icom_port->dram->sync);
/* Wait max 1 Sec for data download and processor to start */
for (index = 0; index < 10; index++) {
msleep(100);
if (readb(&icom_port->dram->misc_flags) & ICOM_HDW_ACTIVE)
break;
}
if (index == 10)
status = -1;
/*
* check Cable ID
*/
cable_id = readb(&icom_port->dram->cable_id);
if (cable_id & ICOM_CABLE_ID_VALID) {
/* Get cable ID into the lower 4 bits (standard form) */
cable_id = (cable_id & ICOM_CABLE_ID_MASK) >> 4;
icom_port->cable_id = cable_id;
} else {
dev_err(&dev->dev,"Invalid or no cable attached\n");
icom_port->cable_id = NO_CABLE;
}
load_code_exit:
if (status != 0) {
/* Clear out any pending interrupts */
writew(0x3FFF, icom_port->int_reg);
/* Turn off port */
writeb(ICOM_DISABLE, &(icom_port->dram->disable));
/* Stop processor */
stop_processor(icom_port);
dev_err(&icom_port->adapter->pci_dev->dev,"Port not operational\n");
}
if (new_page != NULL)
dma_free_coherent(&dev->dev, 4096, new_page, temp_pci);
}