int shandler(int port) { struct stty *t; int IntID, LineStatus, ModemStatus, intType, c; t = &stty[port]; /* IRQ 4 interrupt : COM1 = stty[0] */ IntID = in_byte(t->port+IIR); /* read InterruptID Reg */ LineStatus= in_byte(t->port+LSR); /* read LineStatus Reg */ ModemStatus=in_byte(t->port+MSR); /* read ModemStatus Reg */ intType = IntID & 7; /* mask out all except the lowest 3 bits */ switch(intType){ case 6 : do_errors(t); break; /* 110 = errors */ case 4 : do_rx(t); break; /* 100 = rx interrupt */ case 2 : do_tx(t); break; /* 010 = tx interrupt */ case 0 : do_modem(t); break; /* 000 = modem interrupt */ } out_byte(INT_CTL, ENABLE); /* reenable the 8259 controller */ }
int main(int argc, char *argv[]) { int fd; struct stat statbuf; off_t size; unsigned nr_workers; int workers_left_alive; struct pollfd *polls; struct worker *workers; unsigned x; int idx; int *poll_slots_to_workers; int offline; int prepopulate; int poll_slots_in_use; struct mallinfo mi; init_malloc(false); gettimeofday(&start, NULL); if (argc == 1) errx(1, "arguments are either --offline and a list of files, or a list of ip port1 port2 triples"); prepopulate = 0; if (!strcmp(argv[1], "--prepopulate")) { prepopulate = 1; argv++; argc--; } offline = 0; if (!strcmp(argv[1], "--offline")) offline = 1; if (!offline) { if ((argc - 2) % 3) errx(1, "non-integer number of workers?"); fd = open(argv[1], O_RDONLY); if (fd < 0) err(1, "open(%s)", argv[1]); if (fstat(fd, &statbuf) < 0) err(1, "stat(%s)", argv[1]); size = statbuf.st_size; nr_workers = (argc - 2) / 3; } else { fd = -1; size = 0; nr_workers = argc - 2; } workers = calloc(nr_workers, sizeof(workers[0])); polls = calloc(nr_workers, sizeof(polls[0])); poll_slots_to_workers = calloc(nr_workers, sizeof(polls[0])); for (x = 0; x < nr_workers; x++) { if (offline) { workers[x].to_worker_fd = -1; workers[x].from_worker_fd = open(argv[x + 2], O_RDONLY | O_NONBLOCK); if (workers[x].from_worker_fd < 0) err(1, "opening %s", argv[x + 2]); polls[x].fd = workers[x].from_worker_fd; polls[x].events = POLLIN; } else { connect_to_worker(argv[x * 3 + 2], argv[x * 3 + 3], argv[x * 3 + 4], &workers[x].to_worker_fd, &workers[x].from_worker_fd); polls[x].fd = workers[x].to_worker_fd; polls[x].events = POLLOUT; workers[x].send_offset = x * (size / nr_workers); if (x != 0) workers[x-1].end_of_chunk = workers[x].send_offset; } workers[x].finished_hash_entries = -1; poll_slots_to_workers[x] = x; } workers[nr_workers - 1].end_of_chunk = size; workers_left_alive = nr_workers; poll_slots_in_use = nr_workers; DBG("Start main loop\n"); while (workers_left_alive != 0) { int r = poll(polls, poll_slots_in_use, -1); if (r < 0) err(1, "poll()"); for (x = 0; x < poll_slots_in_use && r; x++) { if (!polls[x].revents) continue; r--; idx = poll_slots_to_workers[x]; assert(!(polls[x].revents & POLLNVAL)); if (polls[x].revents & POLLERR) errx(1, "error on worker %d", idx); if (polls[x].revents & POLLHUP) { if (workers[idx].to_worker_fd < 0) { polls[x].revents = POLLIN; warnx("worker %d hung up on us, but that's okay", idx); } else { errx(1, "worker %d hung up on us when it really shouldn't have done", idx); } } if (polls[x].revents & POLLOUT) { ssize_t s; assert(!offline); assert(workers[idx].send_offset < workers[idx].end_of_chunk); s = sendfile(workers[idx].to_worker_fd, fd, &workers[idx].send_offset, workers[idx].end_of_chunk - workers[idx].send_offset); if (s == 0) errx(1, "worker hung up on us"); if (s < 0) err(1, "sending to worker"); assert(workers[idx].send_offset <= workers[idx].end_of_chunk); if (workers[idx].send_offset == workers[idx].end_of_chunk) { DBG("Finished sending input to worker %d\n", idx); if (prepopulate) { memmove(poll_slots_to_workers + x, poll_slots_to_workers + x + 1, (poll_slots_in_use - x - 1) * sizeof(int)); memmove(polls + x, polls + x + 1, (poll_slots_in_use - x - 1) * sizeof(polls[0])); poll_slots_in_use--; if (poll_slots_in_use == 0) { /* Okay, we've done the prepopulate phase. Switch modes. */ DBG("Finished prepopulate phase\n"); for (idx = 0; idx < nr_workers; idx++) { polls[idx].events = POLLIN; polls[idx].revents = 0; polls[idx].fd = workers[idx].from_worker_fd; poll_slots_to_workers[idx] = idx; close(workers[idx].to_worker_fd); workers[idx].to_worker_fd = -1; } DBG("All workers go\n"); poll_slots_in_use = nr_workers; } } else { close(workers[idx].to_worker_fd); workers[idx].to_worker_fd = -1; polls[x].events = POLLIN; polls[x].revents = 0; polls[x].fd = workers[idx].from_worker_fd; } } } else if (polls[x].revents & POLLIN) { do_rx(workers + idx, idx == 0, idx == nr_workers - 1, idx); } } for (x = 0; x < poll_slots_in_use; x++) { idx = poll_slots_to_workers[x]; if (workers[idx].finished) { DBG("expunge worker %d\n", idx); memmove(poll_slots_to_workers + x, poll_slots_to_workers + x + 1, (poll_slots_in_use - x - 1) * sizeof(int)); memmove(polls + x, polls + x + 1, (poll_slots_in_use - x - 1) * sizeof(polls[0])); poll_slots_in_use--; workers_left_alive--; x--; } } mi = mallinfo(); if (mi.uordblks > TARGET_MAX_HEAP_SIZE) compact_heap(workers, nr_workers, polls); } DBG("All done\n"); for (idx = last_gced_hash_slot + 1; idx < NR_HASH_TABLE_SLOTS; idx++) { struct word *w; for (w = hash_table[idx]; w; w = w->next) { printf("%16d %.*s\n", w->counter, w->len, w->word); } } printf("Boundary screw ups:\n"); for (idx = 0; idx <= last_gced_hash_slot; idx++) { struct word *w; for (w = hash_table[idx]; w; w = w->next) { printf("%16d %.*s\n", w->counter, w->len, w->word); } } DBG("Finished producing output\n"); return 0; }
static void do_control_request(int direction) { switch (USB_ControlRequest.bRequest) { case REQUEST_REGISTER: do_register(direction, USB_ControlRequest.wValue); break; case REQUEST_FREQUENCY: do_frequency(direction, USB_ControlRequest.wValue); break; case REQUEST_RXTX_MODE: do_rxtx_mode(direction, USB_ControlRequest.wValue); break; case REQUEST_MODINDEX: do_modindex(direction, USB_ControlRequest.wValue); break; case REQUEST_CSMA_RSSI: do_csma_rssi(direction, USB_ControlRequest.wValue); break; case REQUEST_POWER: do_power(direction, USB_ControlRequest.wValue); break; case REQUEST_AFC: do_acf(direction, USB_ControlRequest.wValue); break; case REQUEST_IFBW: do_ifbw(direction, USB_ControlRequest.wValue); break; case REQUEST_TRAINING: do_training(direction, USB_ControlRequest.wValue); break; case REQUEST_SYNCWORD: do_syncword(direction, USB_ControlRequest.wValue); break; case REQUEST_BITRATE: do_bitrate(direction, USB_ControlRequest.wValue); break; case REQUEST_TX: do_tx(direction, USB_ControlRequest.wValue); break; case REQUEST_RX: do_rx(direction, USB_ControlRequest.wValue); break; case REQUEST_TX_FREQUENCY: do_tx_frequency(direction, USB_ControlRequest.wValue); break; case REQUEST_RX_FREQUENCY: do_rx_frequency(direction, USB_ControlRequest.wValue); break; case REQUEST_SERIALNUMBER: do_serialnumber(direction, USB_ControlRequest.wValue); break; case REQUEST_FWREVISION: do_fw_revision(direction, USB_ControlRequest.wValue); break; case REQUEST_RESET: reboot(); break; case REQUEST_DFU: jump_to_bootloader(); break; } }