/* Checks for commandline args, intializes globals, then begins code download. */ int main(int argc, char **argv) { nf2.device_name = DEFAULT_IFACE; processArgs(argc, argv); if (check_iface(&nf2)) { exit(1); } if (openDescriptor(&nf2)) { exit(1); } if (strncmp(log_file_name, "stdout",6)) { if ((log_file = fopen(log_file_name, "w")) == NULL) { printf("Error: unable to open logfile %s for writing.\n", log_file_name); exit(1); } } else log_file = stdout; InitGlobals(); BeginCodeDownload(bin_file_name); if (!cpci_reprog) ResetDevice(); /* reset the PHYs */ NF2_WR32(MDIO_0_CONTROL_REG, 0x8000); NF2_WR32(MDIO_1_CONTROL_REG, 0x8000); NF2_WR32(MDIO_2_CONTROL_REG, 0x8000); NF2_WR32(MDIO_3_CONTROL_REG, 0x8000); /* wait until the resets have been completed */ usleep(100); if (intr_enable) { /* PHY interrupt mask off for link status change */ NF2_WR32(MDIO_0_INTERRUPT_MASK_REG, 0xfffd); NF2_WR32(MDIO_1_INTERRUPT_MASK_REG, 0xfffd); NF2_WR32(MDIO_2_INTERRUPT_MASK_REG, 0xfffd); NF2_WR32(MDIO_3_INTERRUPT_MASK_REG, 0xfffd); } VerifyDevInfo(); fclose(log_file); closeDescriptor(&nf2); return SUCCESS; }
/* * Reset the device */ void ResetDevice(void) { u_int val; /* Read the current value of the control register so that we can modify * it to do a reset */ val = NF2_RD32(CPCI_CTRL); NF2_WR32(CPCI_CLK, freq); /* Write to the control register to reset it */ NF2_WR32(CPCI_CTRL, val | 0x100); //NF2_WR32(CPCI_CLK, 0x0); /* Sleep for a while to let the reset complete */ usleep(1); }
/* Given a block of bytes to write, and a bytecount, create 32 bit words from these bytes and write them to the programming RAM in the Virtex */ void DownloadCPCICodeBlock (u_char *code_data, int code_data_size) { u_int result; u_int data_word; int bytes_left; u_int count = 0; bytes_left = code_data_size; while (bytes_left) { data_word = ((u_int) (*code_data++)) << 24; bytes_left--; if (bytes_left) { data_word |= ((u_int) (*code_data++))<<16 ; bytes_left--;} if (bytes_left) { data_word |= ((u_int) (*code_data++))<<8 ; bytes_left--;} if (bytes_left) { data_word |= ((u_int) (*code_data++)) ; bytes_left--;} NF2_WR32(prog_addr, data_word); prog_addr += 4; } }
/* Given a block of bytes to write, and a bytecount, create 32 bit words from these bytes and write them to the Programming FIFO. After each 8 words stop and check that the FIFO is empty. */ void DownloadVirtexCodeBlock (u_char *code_data, int code_data_size) { u_int result; u_int data_word; int bytes_left; u_int count = 0; bytes_left = code_data_size; while (bytes_left) { data_word = (u_int) (*code_data++); bytes_left--; if (bytes_left) { data_word |= ((u_int) (*code_data++))<<8 ; bytes_left--;} if (bytes_left) { data_word |= ((u_int) (*code_data++))<<16 ; bytes_left--;} if (bytes_left) { data_word |= ((u_int) (*code_data++))<<24 ; bytes_left--;} NF2_WR32(CPCI_PROGRAMMING_DATA, data_word); /* Every 8 words we need to check the FIFO - should always be empty! * (or the done flag should be asserted) */ if (++count == 8) { count = 0; while (((result = NF2_RD32(CPCI_PROGRAMMING_STATUS)) & 0x10002) != 2 && (result & 0x100) != 0x100) { if (result & 0x10000) { fprintf(log_file, "INIT went active during programming - there was an error!\n"); exit(1); } fprintf(log_file, "Strange. FIFO wasnt empty... trying again.\n"); usleep(100); result = NF2_RD32(CPCI_PROGRAMMING_STATUS); if ((result & 0x10002) != 2) { fprintf(log_file, "Retrying ... FIFO still not empty. Giving up.\n"); fprintf(log_file, "Last status word read was 0x%0x\n", result); } } } } }
/* Download the codefile by writing it to the programming register in CPCI. */ void DownloadCode(FILE *code_file) { u_int result; u_int version; int code_data_size; unsigned char * code_data; u_int retries; int bytes_expected; /* * Identify what version of the board we are running */ version = NF2_RD32(CPCI_ID); version &= 0xffffff; if (!cpci_reprog) { /* First, make sure the download interface is reset. This flushes buffers, resets state machines etc. */ NF2_WR32(CPCI_PROGRAMMING_CONTROL, 1); /* Clear the error registers */ NF2_WR32(CPCI_ERROR, 0); /* Wait a while for the PROG_B cycle to finish. */ usleep(100); /* Read programming status: Check that DONE bit (bit 8) is zero and FIFO (bit 1) is empty (1). */ result = NF2_RD32(CPCI_PROGRAMMING_STATUS); if ((result & 0x102) != 0x2) { fprintf(log_file, "After resetting Programming interface, expected status to be 1 (FIFO empty).\n"); fprintf(log_file, "However status & 0x102 is 0x%0x\n", (result & 0x102)); FatalError(); } /* Check the error register */ fprintf(log_file, "Error Registers: %x\n", NF2_RD32(CPCI_ERROR)); fprintf(log_file, "Good, after resetting programming interface the FIFO is empty\n"); /* Sleep for a while to allow the INIT pin to be reset */ usleep(10000); retries = 3; while (NF2_RD32(CPCI_PROGRAMMING_STATUS) & 0x10002) { if ((NF2_RD32(CPCI_PROGRAMMING_STATUS) & 0x10000)) usleep(10000); else { break; } retries--; if (retries <= 0) { printf("CPCI's INIT signal did not clear in time, exiting\n"); printf ("CPCI_PROGRAMMING_STATUS: 0x%08x\n", NF2_RD32(CPCI_PROGRAMMING_STATUS)); exit(1); } } } // if (!cpci_reprog) /* Read the code file, and write it to the card. */ code_data = (unsigned char *) malloc(sizeof(unsigned char) * READ_BUFFER_SIZE); /* check num bytes read */ while (code_data_size = fread(code_data, sizeof(unsigned char), READ_BUFFER_SIZE, code_file)) { if (cpci_reprog) DownloadCPCICodeBlock(code_data, code_data_size); else DownloadVirtexCodeBlock(code_data, code_data_size); bytes_sent += code_data_size; } /* Free the code_data variable */ free(code_data); /* Work out how large the download should have been */ if (cpci_reprog) { bytes_expected = CPCI_BIN_SIZE; } else { switch (version) { case 1: bytes_expected = VIRTEX_BIN_SIZE_V2_0; break; case 2: case 3: case 4: bytes_expected = VIRTEX_BIN_SIZE_V2_1; break; default : bytes_expected = -1; } if (version < CPCI_MIN_VER || version > CPCI_MAX_VER) fprintf(log_file, "\n" "WARNING: Unkown CPCI version (%d).\n" " Known versions are between %d and %d inclusive.\n" " Expected number of bytes will be displayed as -1.\n\n", version, CPCI_MIN_VER, CPCI_MAX_VER); } fprintf(log_file, "Download completed - %d bytes. (expected %d).\n", bytes_sent, bytes_expected); /* * Kick off the programming process or wait for the process to complete */ if (cpci_reprog) { NF2_WR32(VIRTEX_PROGRAM_CTRL_ADDR, DISABLE_RESET | START_PROGRAMMING); fprintf(log_file, "Instructed CPCI reprogramming to start. Please reload PCI BARs.\n"); } else { /* Now wait to see that DONE goes high (bit 8) and INIT (16) is low */ for (retries=0; retries<3; retries++) { sleep(1); result = NF2_RD32(CPCI_PROGRAMMING_STATUS); if ((result & 0x100) == 0x100 ) { fprintf(log_file, "DONE went high - chip has been successfully programmed.\n"); return; } if ((result & 0x10000) == 0x10000 ) { fprintf(log_file, "INIT went high - appears to be a programming error.\n"); FatalError(); } if (retries == 2) { fprintf(log_file, "DONE has not gone high - looks like an error\n"); FatalError(); } } } }