/** * <Ring 1> This routine handles DEV_READ and DEV_WRITE message. * * @param p Message ptr. *****************************************************************************/ PRIVATE void hd_rdwt(MESSAGE * p) { // p->DEVICE 為 0x20,也就是 hd2a int pDev = p->DEVICE; int drive = DRV_OF_DEV(p->DEVICE); u64 pos = p->POSITION; assert((pos >> SECTOR_SIZE_SHIFT) < (1 << 31)); /** * We only allow to R/W from a SECTOR boundary: */ assert((pos & 0x1FF) == 0); u32 sect_nr = (u32)(pos >> SECTOR_SIZE_SHIFT); /* pos / SECTOR_SIZE */ //取出logic index int logidx = (p->DEVICE - MINOR_hd1a) % NR_SUB_PER_DRIVE; // 找出某個partition的LBA, // MAX_PRIM=9,代表Hd0~Hd9為primary的編號,超過9以上的編號都是logic sect_nr += p->DEVICE < MAX_PRIM ? hd_info[drive].primary[p->DEVICE].base : hd_info[drive].logical[logidx].base; ERIC_HD("\nHDRW=%x", sect_nr); struct hd_cmd cmd; cmd.features = 0; cmd.count = (p->CNT + SECTOR_SIZE - 1) / SECTOR_SIZE; cmd.lba_low = sect_nr & 0xFF; cmd.lba_mid = (sect_nr >> 8) & 0xFF; cmd.lba_high= (sect_nr >> 16) & 0xFF; cmd.device = MAKE_DEVICE_REG(1, drive, (sect_nr >> 24) & 0xF); cmd.command = (p->type == DEV_READ) ? ATA_READ : ATA_WRITE; hd_cmd_out(&cmd); int bytes_left = p->CNT; void * la = (void*)va2la(p->PROC_NR, p->BUF); while (bytes_left) { //一次只讀512 byte int bytes = min(SECTOR_SIZE, bytes_left); if (p->type == DEV_READ) { interrupt_wait(); port_read(REG_DATA, hdbuf, SECTOR_SIZE); phys_copy(la, (void*)va2la(TASK_HD, hdbuf), bytes); } else { if (!waitfor(STATUS_DRQ, STATUS_DRQ, HD_TIMEOUT)) panic("hd writing error."); port_write(REG_DATA, la, bytes); interrupt_wait(); } bytes_left -= SECTOR_SIZE; la += SECTOR_SIZE; } }
/* * <ring 1> this routine handles DEV_READ and DEV_WRITE message. * * @param msg - message */ static void hd_rdwt(MESSAGE *msg) { int drive = DRV_OF_DEV(msg->DEVICE); u64 pos = msg->POSITION; assert((pos >> SECTOR_SIZE_SHIFT) < (1 << 31)); assert((pos & 0x1ff) == 0); u32 sect_nr = (u32)(pos >> SECTOR_SIZE_SHIFT); int logidx = (msg->DEVICE - MINOR_hd1a) % NR_SUB_PER_DRIVE; sect_nr += msg->DEVICE < MAX_PRIM ? hd_info[drive].primary[msg->DEVICE].base : hd_info[drive].logical[logidx].base; struct hd_cmd cmd; cmd.features = 0; cmd.count = (msg->CNT + SECTOR_SIZE - 1) / SECTOR_SIZE; cmd.lba_low = sect_nr & 0xff; cmd.lba_mid = (sect_nr >> 8) & 0xff; cmd.lba_high = (sect_nr >> 16) & 0xff; cmd.device = MAKE_DEVICE_REG(1, drive, (sect_nr >> 24) & 0xf); cmd.command = (msg->type == DEV_READ) ? ATA_READ : ATA_WRITE; hd_cmd_out(&cmd); int bytes_left = msg->CNT; void *la = (void*)va2la(msg->PROC_NR, msg->BUF); while (bytes_left > 0) { int bytes = min(SECTOR_SIZE, bytes_left); if (msg->type == DEV_READ) { interrupt_wait(); port_read(REG_DATA, hdbuf, SECTOR_SIZE); phys_copy(la, (void*)va2la(TASK_HD, hdbuf), bytes); } else { if (!waitfor(STATUS_DRQ, STATUS_DRQ, HD_TIMEOUT)) { panic("hd writing error."); } port_write(REG_DATA, la, bytes); interrupt_wait(); } bytes_left -= SECTOR_SIZE; la += SECTOR_SIZE; } }
/* 1.函数内部需要注意:while(1),while(-1)都会执行循环体,只有while(0)时才跳出循环体 2.目前只能处理读写数据长度为SECTOR_SIZE整数倍的请求,否则会出错 */ static void hd_rdwt(MESSAGE *message){ int hd_index=HD_INDEX(message->device); int hd_part_index=HD_PART_INDEX(message->device); u64 position=message->position; #ifdef DEBUG_HD printl("position=%d\n",position); #endif assert((position>>SECTOR_SIZE_SHIFT)<(1<<31),""); assert(position%SECTOR_SIZE==0,"hd readwrite start position must be the multiple of SECTOR_SIZE");//读取的起始位置必须在扇区的起始位置 HD_COMMAND hd_command; u32 base=get_part_info(&hd_info[hd_index],hd_part_index)->base; u32 sector_index=base+(u32)(position>>SECTOR_SIZE_SHIFT); int sector_length=(message->length+SECTOR_SIZE-1)/SECTOR_SIZE; int cmd=(message->type==INFO_FS_READ)?ATA_READ:ATA_WRITE; set_command(&hd_command,hd_index,0,0,sector_length,sector_index,cmd); hd_command_out(&hd_command); int bytes_left=message->length; #ifdef DEBUG_HD printl("sector_index=%d sector_length=%d bytes_left=%d\n",sector_index,sector_length,bytes_left); #endif void *la=(void *)va2la(message->source_pid,message->arg_pointer); #ifdef DEBUG_HD printl("source_pid=%d la[0]=%d\n",message->source_pid,*(int*)la); #endif //此处需要注意:while(1),while(-1)都会执行循环体,只有while(0)时才跳出循环体 while(bytes_left>0){ int bytes=min(SECTOR_SIZE,bytes_left); if(message->type==INFO_FS_READ){ interrupt_wait(); port_read(REG_P_DATA,hdbuf,SECTOR_SIZE); memcpy(la,(void *)va2la(TASK_HD,hdbuf),bytes); }else{ if(!wait_for(STATUS_DRQ_MASK,STATUS_DRQ,HD_TIME_OUT)) panic("hd writing error!\n"); /* printl("bytes=%d",bytes); */ port_write(REG_P_DATA,la,bytes); /* printl("test1"); */ interrupt_wait(); /* printl("test2"); */ } bytes_left-=bytes; la+=bytes; /* printl("(bytes_left>0)=%d\n",bytes_left>0); */ } #ifdef DEBUG_HD printl("hd_rdwt ok!\n"); #endif }
/* 功能: 获取硬盘信息。主要是获取对应硬盘的容量,获取的信息保存在hd_info中 参数: device:系统统一设备编号 返回值: (无) */ static void hd_identify(int index){ int hd_index=HD_INDEX(index); struct s_hd_command cmd; cmd.device=MAKE_DEVICE_REG(0,hd_index,0); cmd.command=ATA_IDENTIFY; hd_command_out(&cmd); #ifdef DEBUG_HD printl("interrupt_wait\n"); #endif interrupt_wait(); port_read(REG_P_DATA,hdbuf,SECTOR_SIZE); #ifdef DEBUG_HD print_identify_info((u16*)hdbuf); #endif u16 *hdinfo=(u16*)hdbuf; //硬盘基址 hd_info[hd_index].primary[0].base=0; //硬盘扇区数 hd_info[hd_index].primary[0].size=((int)hdinfo[61]<<16)+hdinfo[60]; }
PRIVAATE void hd_rdwt(MESSAGE *p) { int drive = DRV_OF_DEV(p->DEVICE); u64_t pos = p->POSITION; u32_t sect_nr = (u32_t)(pos >> SECTOR_SIZE_SHIFT); int logidx = (p->DEVICE - MINOR_HD1a) % NR_SUB_PER_DRIVE; sect_nr += p->DEVICE < MAX_PRIM ? hd_info[drive].primary[p->DEVICE].base : hd_info[drive].logical[logidx].base; struct hd_cmd cmd; cmd.features = 0; cmd.count = (p->CNT + SECTOR_SIZE - 1) / SECTOR_SIZE; cmd.lba_low = sect_nr & 0xff; cmd.lba_mid = (sect_nr >> 8) & 0xff; cmd.lba_high = (sect_nr >> 16) & 0xff; cmd.device = MAKE_DEVICE_REG(1, drive, (sect_nr >> 24) & 0xf); cmd.command = (p->type == DEV_READ) ? ATA_READ : ATA_WRITE; hd_cmd_out(&cmd); int bytes_left = p->CNT; void *la = (void*)va2la(p->PROC_NR, p->BUF); while (bytes_left) { int bytes = min(SECTOR_SIZE, bytes_left); if (p->type == DEV_READ) { interrupt_wait(); port_read(REG_DATA, hdbuf, SECTOR_SIZE); phys_copy(la, (void*)va2la(TASK_HD, hdbuf), bytes); } else { if (!waitfor(STATUS_DRQ, STATUS_DRQ, HD_TIMEOUT)) { kprintf("[KERNEL ERROR]hd writing error.\n"); break; } port_write(REG_DATA, la, bytes); interrupt_wait(); } bytes_left -= SECTOR_SIZE; la += SECTOR_SIZE; } }
/** * <Ring 1> Get the disk information. * * @param drive Drive Nr. *****************************************************************************/ PRIVATE void hd_identify(int drive) { struct hd_cmd cmd; cmd.device = MAKE_DEVICE_REG(0, drive, 0); cmd.command = ATA_IDENTIFY; hd_cmd_out(&cmd); interrupt_wait(); port_read(REG_DATA, hdbuf, SECTOR_SIZE); print_identify_info((u16*)hdbuf); }
PRIVATE void hd_rdwt(MESSAGE* p_msg) { int drive = DRV_OF_DEV(p_msg -> DEVICE); u64 pos = p_msg -> POSITION; assert((pos & 0x1FF) == 0); /* 只允许从扇区边界开始读 */ u32 sect_nr = (u32)(pos >> SECTOR_SIZE_SHIFT); int logidx = (p_msg -> DEVICE - MINOR_hd1a) % NR_SUB_PER_DRIVE; sect_nr += p_msg -> DEVICE < MAX_PRIM ? hd_info[drive].primary[p_msg -> DEVICE].base : hd_info[drive].logical[logidx].base; HD_CMD cmd; cmd.features = 0; cmd.count = (p_msg -> CNT + SECTOR_SIZE - 1) / SECTOR_SIZE; cmd.lba_low = sect_nr & 0xFF; cmd.lba_mid = (sect_nr >> 8) & 0xFF; cmd.lba_high = (sect_nr >> 16) & 0xFF; cmd.device = MAKE_DEVICE_REG(1, drive, (sect_nr >> 24) & 0xF); cmd.command = (p_msg -> type == DEV_READ) ? ATA_READ : ATA_WRITE; hd_cmd_out(&cmd); int bytes_left = p_msg -> CNT; void* la = (void*)va2la(p_msg -> PROC_NR, p_msg -> BUF); while (bytes_left > 0) { int bytes = min(bytes_left, SECTOR_SIZE); if (p_msg -> type == DEV_READ) { /* 一次中断一个扇区 */ interrupt_wait(); port_read(REG_DATA, hdbuf, SECTOR_SIZE); memcpy(la, (void*)va2la(TASK_HD, hdbuf), bytes); } else { if (!waitfor(STATUS_DRQ, STATUS_DRQ, HD_TIMEOUT)) panic("HD writing error"); port_write(REG_DATA, la, bytes); interrupt_wait(); } la += bytes; bytes_left -= bytes; } }
/* * <ring 1> get the disk information */ static void hd_identify(int drive) { struct hd_cmd cmd; cmd.device = MAKE_DEVICE_REG(0, drive, 0); cmd.command = ATA_INDENTIFY; hd_cmd_out(&cmd); interrupt_wait(); port_read(REG_DATA, hdbuf, SECTOR_SIZE); print_identify_info((u16*)hdbuf); u16 * hdinfo = (u16*)hdbuf; hd_info[drive].primary[0].base = 0; hd_info[drive].primary[0].size = ((int)hdinfo[61] << 16) + hdinfo[60]; }
int netif_event_wait(spdid_t spdid, struct cos_array *d) { int ret_sz = 0; /* if (!cos_argreg_arr_intern(d)) return -EINVAL; */ /* if (d->sz < MTU) return -EINVAL; */ interrupt_wait(); NET_LOCK_TAKE(); if (interrupt_process(d->mem, d->sz, &ret_sz)) BUG(); NET_LOCK_RELEASE(); d->sz = ret_sz; return 0; }
PRIVATE void get_part_table(int drive, int sectnr, struct part_ent *entry) { struct hd_cmd cmd; cmd.features = 0; cmd.count = 1; cmd.lba_low = sect_nr & 0xff; cmd.lba_mid = (sect_nr >> 8) & 0xff; cmd.lba_high = (sect_nr >> 16) & 0xff; cmd.device = MAKE_DEVICE_REG(1, drive, (sect_nr >> 24) & 0xf); cmd.command = ATA_READ; hd_cmd_out(&cmd); interrupt_wait(); port_read(REG_DATA, hdbuf, SECTOR_SIZE); memcpy(entry, hdbuf + PARTITION_TABLE_OFFSET, sizeof (struct part_ent) * NR_PART_PER_DRIVE); }
void serialin(USART_TypeDef* uart, unsigned int intr) { int fd; char c; mkfifo("/dev/tty0/in", 0); fd = open("/dev/tty0/in", 0); USART_ITConfig(USART2, USART_IT_RXNE, ENABLE); while (1) { interrupt_wait(intr); if (USART_GetFlagStatus(uart, USART_FLAG_RXNE) == SET) { c = USART_ReceiveData(uart); write(fd, &c, 1); } } }
void serialin(volatile unsigned int* uart, unsigned int intr) { int fd; char c; mkfifo("/dev/tty0/in", 0); fd = open("/dev/tty0/in", 0); /* enable RX interrupt on UART */ *(uart + UARTIMSC) |= UARTIMSC_RXIM; while(1) { interrupt_wait(intr); *(uart + UARTICR) = UARTICR_RXIC; if(!(*(uart + UARTFR) & UARTFR_RXFE)) { c = *uart; write(fd, &c, 1); } } }
/* 功能: 获得一个分区内的完整分区表,即包含四项分区表信息 参数: entry: 返回值: (无) */ static void get_part_table(int index,int sector_index,struct s_hd_part_entry *entry,int entry_count){ int hd_index=HD_INDEX(DEVICE(index)); struct s_hd_command cmd; set_command(&cmd,hd_index,0,0,1,sector_index,ATA_READ); #ifdef DEBUG printl("feathures=%d count=%d lba_low=%d lba_mid=%d lba_high=%d device=%d command=%d\n",cmd.features,cmd.count,cmd.lba_low,cmd.lba_mid,cmd.lba_high,cmd.device,cmd.command); #endif hd_command_out(&cmd);//命令发出 interrupt_wait();//等待硬盘中断 port_read(REG_P_DATA,hdbuf,SECTOR_SIZE); memcpy(entry, hdbuf+PARTITION_TABLE_OFFSET, sizeof(struct s_hd_part_entry)*entry_count); }
PRIVATE void hd_identify(int drive) { HD_CMD cmd; cmd.device = MAKE_DEVICE_REG(0, drive, 0); cmd.command = ATA_IDENTIFY; /* 向硬盘发送IDENTIFY指令 */ hd_cmd_out(&cmd); interrupt_wait(); /* 中断结束 */ port_read(REG_DATA, hdbuf, SECTOR_SIZE); /* print_identify_info((u16*)hdbuf); */ u16* hdinfo = (u16*)hdbuf; hd_info[drive].primary[0].base = 0; hd_info[drive].primary[0].size = ((int)hdinfo[61] << 16) + hdinfo[60]; }
/** * <Ring 1> Get the disk information. * * @param drive Drive Nr. *****************************************************************************/ PRIVATE void hd_identify(int drive) { struct hd_cmd cmd; cmd.device = MAKE_DEVICE_REG(0, drive, 0); cmd.command = ATA_IDENTIFY; ERIC_DEBUG(",IdTB"); hd_cmd_out(&cmd); interrupt_wait(); ERIC_DEBUG(",ReadData"); port_read(REG_DATA, hdbuf, SECTOR_SIZE); print_identify_info((u16*)hdbuf); u16* hdinfo = (u16*)hdbuf; hd_info[drive].primary[0].base = 0; /* Total Nr of User Addressable Sectors */ hd_info[drive].primary[0].size = ((int)hdinfo[61] << 16) + hdinfo[60]; }
void serialout(USART_TypeDef* uart, unsigned int intr) { int fd; char c; mkfifo("/dev/tty0/out", 0); fd = open("/dev/tty0/out", 0); while (1) { read(fd, &c, 1); USART_ITConfig(USART2, USART_IT_TXE, ENABLE); while (USART_GetFlagStatus(uart, USART_FLAG_TXE) != SET) { interrupt_wait(intr); } USART_ITConfig(USART2, USART_IT_TXE, DISABLE); USART_SendData(USART2, c); } }
PRIVATE void get_part_table(int drive, int sect_nr, PART_ENT* entry) { HD_CMD cmd; /* 设置命令 */ cmd.features = 0; cmd.count = 1; cmd.lba_low = sect_nr & 0xFF; cmd.lba_mid = (sect_nr >> 8) & 0xFF; cmd.lba_high = (sect_nr >> 16) & 0xFF; cmd.device = MAKE_DEVICE_REG(1, drive, (sect_nr >> 24) & 0xF); /* LBA Mode */ cmd.command = ATA_READ; hd_cmd_out(&cmd); /* 等待中断发生 */ interrupt_wait(); /* 数据已经就绪 */ port_read(REG_DATA, hdbuf, SECTOR_SIZE); /* 分区表的偏移为PARTITION_TABLE_OFFSET = 0x1BE */ memcpy(entry, hdbuf + PARTITION_TABLE_OFFSET, sizeof(PART_ENT) * NR_PART_PER_DRIVE); }
void serialout(volatile unsigned int* uart, unsigned int intr) { int fd; char c; int doread = 1; mkfifo("/dev/tty0/out", 0); fd = open("/dev/tty0/out", 0); /* enable TX interrupt on UART */ *(uart + UARTIMSC) |= UARTIMSC_TXIM; while(1) { if(doread) read(fd, &c, 1); doread = 0; if(!(*(uart + UARTFR) & UARTFR_TXFF)) { *uart = c; doread = 1; } interrupt_wait(intr); *(uart + UARTICR) = UARTICR_TXIC; } }
void serialout(USART_TypeDef* uart, unsigned int intr) { int fd; char c; int doread = 1; mkfifo("/dev/tty0/out", 0); fd = open("/dev/tty0/out", 0); while (1) { if (doread) read(fd, &c, 1); doread = 0; if (USART_GetFlagStatus(uart, USART_FLAG_TXE) == SET) { USART_SendData(uart, c); USART_ITConfig(USART1, USART_IT_TXE, ENABLE); doread = 1; } interrupt_wait(intr); USART_ITConfig(USART1, USART_IT_TXE, DISABLE); } }
void serialin(void* arg) { int fd; char c; mkfifo("/dev/tty0/in", 0); fd = open("/dev/tty0/in", 0); USART_ITConfig(USART2, USART_IT_RXNE, ENABLE); while (1) { // interrupt_wait(intr); interrupt_wait(USART2_IRQn); /* if (USART_GetFlagStatus(uart, USART_FLAG_RXNE) == SET) { c = USART_ReceiveData(uart); */ if (USART_GetFlagStatus((USART_TypeDef *)USART2, USART_FLAG_RXNE) == SET) { c = USART_ReceiveData((USART_TypeDef *)USART2); write(fd, &c, 1); } } }
/** * <Ring 1> Get a partition table of a drive. * * @param drive Drive nr (0 for the 1st disk, 1 for the 2nd, ...)n * @param sect_nr The sector at which the partition table is located. * @param entry Ptr to part_ent struct. *****************************************************************************/ PRIVATE void get_part_table(int drive, int sect_nr, struct part_ent * entry) { ERIC_HD("\nGetPTable=%x", sect_nr); struct hd_cmd cmd; // ata read cmd ( 0x20 ) cmd.features = 0; cmd.count = 1; cmd.lba_low = sect_nr & 0xFF; cmd.lba_mid = (sect_nr >> 8) & 0xFF; cmd.lba_high = (sect_nr >> 16) & 0xFF; cmd.device = MAKE_DEVICE_REG(1, /* LBA mode*/ drive, (sect_nr >> 24) & 0xF); cmd.command = ATA_READ; hd_cmd_out(&cmd); interrupt_wait(); port_read(REG_DATA, hdbuf, SECTOR_SIZE); memcpy(entry, hdbuf + PARTITION_TABLE_OFFSET, sizeof(struct part_ent) * NR_PART_PER_DRIVE); }
int netif_event_wait(spdid_t spdid, char *mem, int sz) { int ret_sz = 0; if (sz < MTU) return -EINVAL; /* printc("before %d: I\n", cos_get_thd_id()); */ /* rdtscll(start); */ interrupt_wait(); /* rdtscll(end); */ /* pnums++; */ /* avg += end-start; */ /* if (pnums%100000 == 0) { */ /* printc("pnums %llu avg %llu\n", pnums, avg); */ /* } */ /* printc("after %d: I\n", cos_get_thd_id()); */ NET_LOCK_TAKE(); if (interrupt_process(mem, sz, &ret_sz)) BUG(); interrupt_process_cnt++; NET_LOCK_RELEASE(); return ret_sz; }
void * fpga_server(void * arg) { int rc; gpio_out_uni * temp_state = NULL; //If this variable is set, the server will deassert the output latch prctl(PR_SET_NAME, FPGA_SERVER, 0, 0, 0); record("-->FPGA Server thread started....\n"); /*initialize semaphore*/ sem_init(&dma_control_sem, 0, 0); //initialize semaphore to zero /*open fpga device*/ open_fpga(); /*Allocate buffer for image fragments*/ uint i; for (i = 0; i < NUM_FRAGMENT; i++) { allocate_buffer(&dma_params[i], &pci_buffer[i], &virt_buf[i]); } /*initialize GPIO pins*/ rc = init_gpio(); if (rc == FALSE) { record("Error initializing GPIO pins\n"); } /*initialize DMA pipeline*/ initializeDMA(); /*FPGA server main control loop*/ while (ts_alive) { U32 interrupt = 0; /*wait on interrupt for DMA and GPIO input*/ rc = interrupt_wait(&interrupt); if (rc == FALSE) { record(RED "Error during wait\n" NO_COLOR); } /** * Unlatch the power latch if it was latched before timeout * * This statement requires that the timeout on the interrupt wait must be * similar to the latch pulse length (66ms). */ if (temp_state) { /*deassert latch*/ temp_state->bf.latch = 0; /*Poke unlatched value to FPGA*/ rc = poke_gpio(OUTPUT_GPIO_ADDR, temp_state->val); if (rc == FALSE) { record(RED "Error writing GPIO output\n" NO_COLOR); } /*free gpio value*/ free(temp_state); //Free GPIO output struct from assert temp_state = NULL; } /*take action based off what type of interrupt*/ if (interrupt == INP_INT) { /*Call function to handle input interrupt from FPGA*/ record("Interrupt received\n"); rc = handle_fpga_input(); if (rc == FALSE) { record(RED "Error handling FPGA input\n" NO_COLOR); } else if (rc == DMA_AVAILABLE) { // DMA available in buffer, begin transfer /*Wake up science timeline waiting for readout completion*/ sem_post(&dma_control_sem); record("Perform DMA transfer from FPGA\n"); for (i = 0; i < NUM_FRAGMENT; i++) { dmaRead(dma_params[i], DMA_TIMEOUT); } // Return to IDLE state record("DMA Complete, Returning to IDLE state\n"); output_ddr2_ctrl &= 0x00FFFFFF; output_ddr2_ctrl |= (0x02 << 24); WriteDword(&fpga_dev, 2, OUTPUT_DDR2_CTRL_ADDR, output_ddr2_ctrl); output_ddr2_ctrl &= 0x00FFFFFF; output_ddr2_ctrl |= (0x00000000 << 24); WriteDword(&fpga_dev, 2, OUTPUT_DDR2_CTRL_ADDR, output_ddr2_ctrl); ; record("Sort image\n"); filter_sort(dma_image); record("Enqueue image to writer\n"); enqueue(&lqueue[fpga_image], dma_image); } } else if (interrupt == TIMEOUT_INT) { /*check if new GPIO output is available*/ if (occupied(&lqueue[gpio_out])) { gpio_out_uni * gpio_out_val = dequeue(&lqueue[gpio_out]); if (gpio_out_val != NULL) { /*Check if request or assert*/ if (gpio_out_val->val == REQ_POWER) { /*request pin values*/ rc = peek_gpio(OUTPUT_GPIO_ADDR, &(gpio_out_val->val)); if (rc == FALSE) { record(RED "Error reading GPIO request\n" NO_COLOR); } enqueue(&lqueue[gpio_req], gpio_out_val); } else { /*apply output if not request*/ rc = poke_gpio(OUTPUT_GPIO_ADDR, gpio_out_val->val); if (rc == FALSE) { record(RED "Error writing GPIO output\n" NO_COLOR); } usleep(1000); //sleep for 1ms before applying latch /*apply latch*/ gpio_out_val->bf.latch = 1; /*apply latched output*/ rc = poke_gpio(OUTPUT_GPIO_ADDR, gpio_out_val->val); if (rc == FALSE) { record(RED "Error writing GPIO output\n" NO_COLOR); } temp_state = gpio_out_val; //write to this variable so we know to delatch next timeout } } else { record("Received NULL GPIO output struct\n"); } } /*check if image input is available*/ if (occupied(&lqueue[scit_image])) { /*set FPGA into buffer mode to capture image from ROE*/ set_buffer_mode(); /*Wake up science timeline waiting to Readout from ROE*/ sem_post(&dma_control_sem); record("Dequeue new image\n"); dma_image = dequeue(&lqueue[scit_image]); /*If we're simulating an image, we have to trigger a frame from the VDX*/ if (config_values[image_sim_interface] == 0) { //Trigger a frame record("Trigger simulated frame\n"); gpio_out_state.bf.frame_trigger = 1; poke_gpio(OUTPUT_GPIO_ADDR, gpio_out_state.val); gpio_out_state.bf.frame_trigger = 0; poke_gpio(OUTPUT_GPIO_ADDR, gpio_out_state.val); } } } } return NULL; }