void v_hook_spiral(void) { h_pos = 0; pal_mutex = 1; do_dma(DMA_68K, DMA_DST_VRAM, (u32 *)hscroll_buf, 0xfc00, 0x380); if(sprite_ram_mutex == 1) { do_dma(DMA_68K, DMA_DST_VRAM, (u32 *)sprite_ram, SPRITE_BASE, 80); sprite_ram_mutex = 0; } pal_mutex = 0; }
/* * drain_dma_poll - Drain all outstanding DMA operations for a particular * DMA channel via polling. * @chan - DMA channel * Return 0 on success and -errno on error. */ int drain_dma_poll(struct dma_channel *chan) { int cookie, err; unsigned long ts; if (chan) { if ((err = request_dma_channel(chan))) goto error; if ((cookie = do_dma(chan, DO_DMA_POLLING, 0, 0, 0, NULL)) < 0) { err = cookie; free_dma_channel(chan); goto error; } free_dma_channel(chan); ts = jiffies; while (1 != poll_dma_completion(cookie, chan)) { cpu_relax(); if (time_after(jiffies,ts + DMA_TO)) { err = -EBUSY; break; } } error: if (err) printk(KERN_ERR "%s %d err %d\n", __func__, __LINE__, err); } else { err = -EINVAL; } return err; }
void snesc_vblank(void) { /* stuff pending for DMA? */ unsigned char do_flags = snesc_do_copy; if(do_flags) { snesc_do_copy = 0; do_dma(do_flags); do_flags &= 0x3f; /* mask out palette and sprite flags (used by do_dma) */ if (do_flags) { int x = 0; while (do_flags) { switch(snesc_dma_transfers[x].src.c.type) { /* type of transfer */ case 0: /* VRAM */ *((unsigned short*)0x4300) = 0x1801; /* 2 regs write once, Bus B addr $2118 (VRAM data write) */ *((unsigned short*)0x2116) = snesc_dma_transfers[x].dest; /* VRAM address */ break; case 1: /* OAM */ *((unsigned short*)0x4300) = 0x400; /* DMA OAM write */ *((unsigned short*)0x2102) = snesc_dma_transfers[x].dest; /* OAM address */ break; case 2: /* CGRAM */ *((unsigned short*)0x4300) = 0x2200; /* CGRAM write */ *((unsigned char*)0x2121) = snesc_dma_transfers[x].dest; /* CGRAM address (trunc'd to 8 bits) */ break; } *((unsigned short*)0x4302) = snesc_dma_transfers[x].src.c.addr; /* DMA source address (16-bit) */ *((unsigned short*)0x4305) = snesc_dma_transfers[x].size; /* DMA size */ *((unsigned char*)0x4304) = snesc_dma_transfers[x].src.c.bank; /* DMA source address (bank) */ *((unsigned char*)0x420b) = 1; /* enable DMA 0 */ x++; do_flags--; } } } while(*((unsigned char*)0x4212) & 1) {} /* update input buffers */ unsigned int pad; for(pad = 0; pad < 4 ; pad++) { snesc_controllers[pad] |= ((unsigned short*)0x4218)[pad]; } /* timer ticks */ unsigned char timers_enabled = snesc_timer_enabled; unsigned int tc = 0; while(timers_enabled & 1) { snesc_timers[tc]++; tc++; timers_enabled >>= 1; } }
void AiLenChanged(usf_state_t *state) { unsigned int duration = get_dma_duration(state); if (AI_STATUS_REG & AI_STATUS_BUSY) { state->fifo[1].address = AI_DRAM_ADDR_REG; state->fifo[1].length = AI_LEN_REG; state->fifo[1].duration = duration; if (state->enableFIFOfull) AI_STATUS_REG |= AI_STATUS_FULL; else do_dma(state, &state->fifo[1]); } else { state->fifo[0].address = AI_DRAM_ADDR_REG; state->fifo[0].length = AI_LEN_REG; state->fifo[0].duration = duration; AI_STATUS_REG |= AI_STATUS_BUSY; do_dma(state, &state->fifo[0]); } }
void AiTimerDone(usf_state_t *state) { if (AI_STATUS_REG & AI_STATUS_FULL) { state->fifo[0].address = state->fifo[1].address; state->fifo[0].length = state->fifo[1].length; state->fifo[0].duration = state->fifo[1].duration; AI_STATUS_REG &= ~AI_STATUS_FULL; do_dma(state, &state->fifo[0]); } else { AI_STATUS_REG &= ~AI_STATUS_BUSY; } }
void v_bottom_test2(void) { scanline = 0; if(sprite_ram_mutex == 1) { do_dma(DMA_68K, DMA_DST_VRAM, (u32 *)sprite_ram, SPRITE_BASE, 80*8); sprite_ram_mutex = 0; } theta++; if(theta == 0) theta = 1; if(theta==0xff) theta = 1; looper++; }
static void fifo_pop(struct ai_controller* ai) { if (ai->regs[AI_STATUS_REG] & AI_STATUS_FULL) { ai->fifo[0].address = ai->fifo[1].address; ai->fifo[0].length = ai->fifo[1].length; ai->fifo[0].duration = ai->fifo[1].duration; ai->regs[AI_STATUS_REG] &= ~AI_STATUS_FULL; do_dma(ai, &ai->fifo[0]); } else { ai->regs[AI_STATUS_REG] &= ~AI_STATUS_BUSY; } }
static void fifo_push(struct ai_controller* ai) { unsigned int duration = get_dma_duration(ai); if (ai->regs[AI_STATUS_REG] & AI_STATUS_BUSY) { ai->fifo[1].address = ai->regs[AI_DRAM_ADDR_REG]; ai->fifo[1].length = ai->regs[AI_LEN_REG]; ai->fifo[1].duration = duration; ai->regs[AI_STATUS_REG] |= AI_STATUS_FULL; } else { ai->fifo[0].address = ai->regs[AI_DRAM_ADDR_REG]; ai->fifo[0].length = ai->regs[AI_LEN_REG]; ai->fifo[0].duration = duration; ai->regs[AI_STATUS_REG] |= AI_STATUS_BUSY; do_dma(ai, &ai->fifo[0]); } }
static int sscape_download_boot(struct sscape_info *devc, unsigned char *block, int size, int flag) { unsigned long flags; unsigned char temp; volatile int done, timeout_val; static unsigned char codec_dma_bits = 0; if (flag & CPF_FIRST) { /* * First block. Have to allocate DMA and to reset the board * before continuing. */ save_flags(flags); cli(); codec_dma_bits = sscape_read(devc, GA_CDCFG_REG); if (devc->dma_allocated == 0) devc->dma_allocated = 1; restore_flags(flags); sscape_write(devc, GA_HMCTL_REG, (temp = sscape_read(devc, GA_HMCTL_REG)) & 0x3f); /*Reset */ for (timeout_val = 10000; timeout_val > 0; timeout_val--) sscape_read(devc, GA_HMCTL_REG); /* Delay */ /* Take board out of reset */ sscape_write(devc, GA_HMCTL_REG, (temp = sscape_read(devc, GA_HMCTL_REG)) | 0x80); } /* * Transfer one code block using DMA */ if (audio_devs[devc->codec_audiodev]->dmap_out->raw_buf == NULL) { printk(KERN_WARNING "soundscape: DMA buffer not available\n"); return 0; } memcpy(audio_devs[devc->codec_audiodev]->dmap_out->raw_buf, block, size); save_flags(flags); cli(); /******** INTERRUPTS DISABLED NOW ********/ do_dma(devc, SSCAPE_DMA_A, audio_devs[devc->codec_audiodev]->dmap_out->raw_buf_phys, size, DMA_MODE_WRITE); /* * Wait until transfer completes. */ done = 0; timeout_val = 30; while (!done && timeout_val-- > 0) { int resid; if (HZ / 50) sleep(HZ / 50); clear_dma_ff(devc->dma); if ((resid = get_dma_residue(devc->dma)) == 0) done = 1; } restore_flags(flags); if (!done) return 0; if (flag & CPF_LAST) { /* * Take the board out of reset */ outb((0x00), PORT(HOST_CTRL)); outb((0x00), PORT(MIDI_CTRL)); temp = sscape_read(devc, GA_HMCTL_REG); temp |= 0x40; sscape_write(devc, GA_HMCTL_REG, temp); /* Kickstart the board */ /* * Wait until the ODB wakes up */ save_flags(flags); cli(); done = 0; timeout_val = 5 * HZ; while (!done && timeout_val-- > 0) { unsigned char x; sleep(1); x = inb(PORT(HOST_DATA)); if (x == 0xff || x == 0xfe) /* OBP startup acknowledge */ { DDB(printk("Soundscape: Acknowledge = %x\n", x)); done = 1; } } sscape_write(devc, GA_CDCFG_REG, codec_dma_bits); restore_flags(flags); if (!done) { printk(KERN_ERR "soundscape: The OBP didn't respond after code download\n"); return 0; } save_flags(flags); cli(); done = 0; timeout_val = 5 * HZ; while (!done && timeout_val-- > 0) { sleep(1); if (inb(PORT(HOST_DATA)) == 0xfe) /* Host startup acknowledge */ done = 1; } restore_flags(flags); if (!done) { printk(KERN_ERR "soundscape: OBP Initialization failed.\n"); return 0; } printk(KERN_INFO "SoundScape board initialized OK\n"); set_control(devc, CTL_MASTER_VOL, 100); set_control(devc, CTL_SYNTH_VOL, 100); #ifdef SSCAPE_DEBUG3 /* * Temporary debugging aid. Print contents of the registers after * downloading the code. */ { int i; for (i = 0; i < 13; i++) printk("I%d = %02x (new value)\n", i, sscape_read(devc, i)); } #endif } return 1; }
void UPD71071::write_io8(uint32 addr, uint32 data) { switch(addr & 0x0f) { case 0x00: if(data & 1) { // dma reset for(int i = 0; i < 4; i++) { dma[i].mode = 0; } selch = base = 0; cmd = tmp = 0; sreq = tc = 0; mask = 0x0f; } b16 = data & 2; break; case 0x01: selch = data & 3; base = data & 4; break; case 0x02: dma[selch].bcreg = (dma[selch].bcreg & 0xff00) | data; // if(!base) { dma[selch].creg = (dma[selch].creg & 0xff00) | data; // } break; case 0x03: dma[selch].bcreg = (dma[selch].bcreg & 0xff) | (data << 8); // if(!base) { dma[selch].creg = (dma[selch].creg & 0xff) | (data << 8); // } break; case 0x04: dma[selch].bareg = (dma[selch].bareg & 0xffff00) | data; // if(!base) { dma[selch].areg = (dma[selch].areg & 0xffff00) | data; // } break; case 0x05: dma[selch].bareg = (dma[selch].bareg & 0xff00ff) | (data << 8); // if(!base) { dma[selch].areg = (dma[selch].areg & 0xff00ff) | (data << 8); // } break; case 0x06: dma[selch].bareg = (dma[selch].bareg & 0xffff) | (data << 16); // if(!base) { dma[selch].areg = (dma[selch].areg & 0xffff) | (data << 16); // } break; case 0x08: cmd = (cmd & 0xff00) | data; break; case 0x09: cmd = (cmd & 0xff) | (data << 8); break; case 0x0a: dma[selch].mode = data; break; case 0x0e: if((sreq = data) != 0) { #ifndef SINGLE_MODE_DMA do_dma(); #endif } break; case 0x0f: mask = data; break; } }
void do_write(int argc, char *argv[], char *envp[]) { uint32_t vmeaddr; int am; int dps; int eln; void *buf = NULL; uint8_t *cp; uint16_t *sp; uint32_t *ip; uint64_t *lp; int i = 0; if (argc < 6) { usage: printf("Usage: w <VME Address> <Address Modifier>" " <Data Port Size> [-- <elements to write>] [<filename>]\n"); exit(EXIT_FAILURE); } while (strcmp(argv[i], "--")) { if (i == 5) { buf = get_data_from_file(argv[i]); break; } ++i; } if (!(argc - (++i)) && !buf) goto usage; get_obligitary_params(argv, &vmeaddr, &am, &dps); if (!buf) { eln = argc - i; buf = get_data_from_cmd_line(argv, i, dps, eln); } printf("Will write %d element(s)@%x ", eln, vmeaddr); i = 0; switch (dps) { case 8: printf("one byte long:\n"); cp = buf; while (i < eln) printf("[%d] --> %#x\n", i++, *cp++); break; case 16: printf("2 bytes long:\n"); sp = buf; while (i < eln) printf("[%d] --> %#x\n", i++, *sp++); break; case 32: printf("4 bytes long:\n"); ip = buf; while (i < eln) printf("[%d] --> %#x\n", i++, *ip++); break; case 64: printf("8 bytes long:\n"); lp = buf; while (i < eln) printf("[%d] --> %#lx\n", i++, *lp++); break; } do_dma('w', vmeaddr, am, dps, buf, eln); }
void do_read(int argc, char *argv[], char *envp[]) { uint32_t vmeaddr; int am; int dps; int eln; void *buf; uint8_t *cp; uint16_t *sp; uint32_t *ip; uint64_t *lp; int i; if (argc != 6) { printf("Usage: r <VME Address> <Address Modifier>" " <Data Port Size> <number of elements>\n"); exit(EXIT_FAILURE); } get_obligitary_params(argv, &vmeaddr, &am, &dps); sscanf(argv[5], "%d", &eln); if (!(buf = calloc(eln, dps/8))) { perror("calloc"); exit(1); } do_dma('r', vmeaddr, am, dps, buf, eln); printf("Read %d elements ", eln); switch (dps) { case 8: printf("one byte long:\n"); cp = buf; for (i = 0; i < eln; i++, cp++) printf("[%d] --> %#x\n", i, *cp); break; case 16: printf("2 bytes long:\n"); sp = buf; for (i = 0; i < eln; i++, sp++) printf("[%d] --> %#x\n", i, *sp); break; case 32: printf("4 bytes long:\n"); ip = buf; for (i = 0; i < eln; i++, ip++) printf("[%d] --> %#x\n", i, *ip); break; case 64: printf("8 bytes long:\n"); lp = buf; for (i = 0; i < eln; i++, lp++) printf("[%d] --> %#lx\n", i, *lp); break; default: break; } free(buf); }
static int sscape_download_boot (struct sscape_info *devc, unsigned char *block, int size, int flag) { unsigned long flags; unsigned char temp; int done, timeout_val; static unsigned char codec_dma_bits = 0; if (flag & CPF_FIRST) { /* * First block. Have to allocate DMA and to reset the board * before continuing. */ save_flags (flags); cli (); codec_dma_bits = sscape_read (devc, GA_CDCFG_REG); #if 0 sscape_write (devc, GA_CDCFG_REG, codec_dma_bits & ~0x08); /* Disable codec DMA */ #endif if (devc->dma_allocated == 0) { devc->dma_allocated = 1; } restore_flags (flags); sscape_write (devc, GA_HMCTL_REG, (temp = sscape_read (devc, GA_HMCTL_REG)) & 0x3f); /*Reset */ for (timeout_val = 10000; timeout_val > 0; timeout_val--) sscape_read (devc, GA_HMCTL_REG); /* Delay */ /* Take board out of reset */ sscape_write (devc, GA_HMCTL_REG, (temp = sscape_read (devc, GA_HMCTL_REG)) | 0x80); } /* * Transfer one code block using DMA */ memcpy (audio_devs[devc->my_audiodev]->dmap_out->raw_buf, block, size); save_flags (flags); cli (); /******** INTERRUPTS DISABLED NOW ********/ do_dma (devc, SSCAPE_DMA_A, audio_devs[devc->my_audiodev]->dmap_out->raw_buf_phys, size, DMA_MODE_WRITE); /* * Wait until transfer completes. */ sscape_sleep_flag.flags = WK_NONE; done = 0; timeout_val = 100; while (!done && timeout_val-- > 0) { int resid; { unsigned long tlimit; if (1) current_set_timeout (tlimit = jiffies + (1)); else tlimit = (unsigned long) -1; sscape_sleep_flag.flags = WK_SLEEP; module_interruptible_sleep_on (&sscape_sleeper); if (!(sscape_sleep_flag.flags & WK_WAKEUP)) { if (jiffies >= tlimit) sscape_sleep_flag.flags |= WK_TIMEOUT; } sscape_sleep_flag.flags &= ~WK_SLEEP; }; clear_dma_ff (devc->dma); if ((resid = get_dma_residue (devc->dma)) == 0) { done = 1; } } restore_flags (flags); if (!done) return 0; if (flag & CPF_LAST) { /* * Take the board out of reset */ outb (0x00, PORT (HOST_CTRL)); outb (0x00, PORT (MIDI_CTRL)); temp = sscape_read (devc, GA_HMCTL_REG); temp |= 0x40; sscape_write (devc, GA_HMCTL_REG, temp); /* Kickstart the board */ /* * Wait until the ODB wakes up */ save_flags (flags); cli (); done = 0; timeout_val = 5 * HZ; while (!done && timeout_val-- > 0) { { unsigned long tlimit; if (1) current_set_timeout (tlimit = jiffies + (1)); else tlimit = (unsigned long) -1; sscape_sleep_flag.flags = WK_SLEEP; module_interruptible_sleep_on (&sscape_sleeper); if (!(sscape_sleep_flag.flags & WK_WAKEUP)) { if (jiffies >= tlimit) sscape_sleep_flag.flags |= WK_TIMEOUT; } sscape_sleep_flag.flags &= ~WK_SLEEP; }; if (inb (PORT (HOST_DATA)) == 0xff) /* OBP startup acknowledge */ done = 1; } sscape_write (devc, GA_CDCFG_REG, codec_dma_bits); restore_flags (flags); if (!done) { printk ("SoundScape: The OBP didn't respond after code download\n"); return 0; } save_flags (flags); cli (); done = 0; timeout_val = 5 * HZ; while (!done && timeout_val-- > 0) { { unsigned long tlimit; if (1) current_set_timeout (tlimit = jiffies + (1)); else tlimit = (unsigned long) -1; sscape_sleep_flag.flags = WK_SLEEP; module_interruptible_sleep_on (&sscape_sleeper); if (!(sscape_sleep_flag.flags & WK_WAKEUP)) { if (jiffies >= tlimit) sscape_sleep_flag.flags |= WK_TIMEOUT; } sscape_sleep_flag.flags &= ~WK_SLEEP; }; if (inb (PORT (HOST_DATA)) == 0xfe) /* Host startup acknowledge */ done = 1; } restore_flags (flags); if (!done) { printk ("SoundScape: OBP Initialization failed.\n"); return 0; } printk ("SoundScape board of type %d initialized OK\n", get_board_type (devc)); set_control (devc, CTL_MASTER_VOL, 100); set_control (devc, CTL_SYNTH_VOL, 100); #ifdef SSCAPE_DEBUG3 /* * Temporary debugging aid. Print contents of the registers after * downloading the code. */ { int i; for (i = 0; i < 13; i++) printk ("I%d = %02x (new value)\n", i, sscape_read (devc, i)); } #endif } return 1; }
static int sscape_download_boot(struct sscape_info * devc, u_char *block, int size, int flag) { u_long flags; u_char temp; int done, timeout_val; if (flag & CPF_FIRST) { /* * First block. Have to allocate DMA and to reset the board * before continuing. */ flags = splhigh(); if (devc->dma_allocated == 0) { devc->dma_allocated = 1; } splx(flags); sscape_write(devc, GA_HMCTL_REG, (temp = sscape_read(devc, GA_HMCTL_REG)) & 0x3f); /* Reset */ for (timeout_val = 10000; timeout_val > 0; timeout_val--) sscape_read(devc, GA_HMCTL_REG); /* Delay */ /* Take board out of reset */ sscape_write(devc, GA_HMCTL_REG, (temp = sscape_read(devc, GA_HMCTL_REG)) | 0x80); } /* * Transfer one code block using DMA */ bcopy(block, audio_devs[devc->my_audiodev]->dmap_out->raw_buf, size); flags = splhigh(); /******** INTERRUPTS DISABLED NOW ********/ do_dma(devc, SSCAPE_DMA_A, audio_devs[devc->my_audiodev]->dmap_out->raw_buf_phys, size, 1); /* * Wait until transfer completes. */ sscape_sleep_flag.aborting = 0; sscape_sleep_flag.mode = WK_NONE; done = 0; timeout_val = 100; while (!done && timeout_val-- > 0) { int chn; sscape_sleeper = &chn; DO_SLEEP(chn, sscape_sleep_flag, 1); done = 1; } splx(flags); if (!done) return 0; if (flag & CPF_LAST) { /* * Take the board out of reset */ outb(PORT(HOST_CTRL), 0x00); outb(PORT(MIDI_CTRL), 0x00); temp = sscape_read(devc, GA_HMCTL_REG); temp |= 0x40; sscape_write(devc, GA_HMCTL_REG, temp); /* Kickstart the board */ /* * Wait until the ODB wakes up */ flags = splhigh(); done = 0; timeout_val = 5 * hz; while (!done && timeout_val-- > 0) { int chn; sscape_sleeper = &chn; DO_SLEEP(chn, sscape_sleep_flag, 1); if (inb(PORT(HOST_DATA)) == 0xff) /* OBP startup acknowledge */ done = 1; } splx(flags); if (!done) { printf("SoundScape: The OBP didn't respond after code download\n"); return 0; } flags = splhigh(); done = 0; timeout_val = 5 * hz; while (!done && timeout_val-- > 0) { int chn; sscape_sleeper = &chn; DO_SLEEP(chn, sscape_sleep_flag, 1); if (inb(PORT(HOST_DATA)) == 0xfe) /* Host startup acknowledge */ done = 1; } splx(flags); if (!done) { printf("SoundScape: OBP Initialization failed.\n"); return 0; } printf("SoundScape board of type %d initialized OK\n", get_board_type(devc)); set_control(devc, CTL_MASTER_VOL, 100); set_control(devc, CTL_SYNTH_VOL, 100); #ifdef SSCAPE_DEBUG3 /* * Temporary debugging aid. Print contents of the registers * after downloading the code. */ { int i; for (i = 0; i < 13; i++) printf("I%d = %02x (new value)\n", i, sscape_read(devc, i)); } #endif } return 1; }
/** ******************************************************************************* @brief Main program code. @param argument_count Number of command line arguments passed to executable. @param arguments Address of array containing command line arguments. @retval EXIT_SUCCESS Success. @retval EXIT_FAILURE Failure. ******************************************************************************/ int main(int argument_count, char **arguments) { DM7820_Error dm7820_status; uint16_t *temp_buf = NULL; uint16_t read_data; int status; uint32_t i; struct option options[] = { {"help", 0, 0, 1}, {"minor", 1, 0, 2}, {0, 0, 0, 0} }; struct sigaction signal_action; uint8_t help_option = 0x00; uint8_t minor_option = 0x00; unsigned long int minor_number = 0; program_name = arguments[0]; signal_action.sa_handler = sigint_handler; sigfillset(&(signal_action.sa_mask)); signal_action.sa_flags = 0; if (sigaction(SIGINT, &signal_action, NULL) < 0) { error(EXIT_FAILURE, errno, "ERROR: sigaction() FAILED"); } fprintf(stdout, "\n"); fprintf(stdout, "\tDM7820 DMA Capture Example Program\n"); fprintf(stdout, "\n"); /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Process command line options %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% */ while (1) { /* * Parse the next command line option and any arguments it may require */ status = getopt_long(argument_count, arguments, "", options, NULL); /* * If getopt_long() returned -1, then all options have been processed */ if (status == -1) { break; } /* * Figure out what getopt_long() found */ switch (status) { /*################################################################# User entered '--help' ############################################################## */ case 1: /* * Refuse to accept duplicate '--help' options */ if (help_option) { error(0, 0, "ERROR: Duplicate option '--help'"); usage(); } /* * '--help' option has been seen */ help_option = 0xFF; break; /*################################################################# User entered '--minor' ############################################################## */ case 2:{ char *invalid_char_p; /* * Refuse to accept duplicate '--minor' options */ if (minor_option) { error(0, 0, "ERROR: Duplicate option '--minor'"); usage(); } /* * Convert option argument string to unsigned long integer */ errno = 0; minor_number = strtoul(optarg, &invalid_char_p, 10); /* * Catch unsigned long int overflow */ if ((minor_number == ULONG_MAX) && (errno == ERANGE)) { error(0, 0, "ERROR: Device minor number caused numeric overflow"); usage(); } /* * Catch argument strings with valid decimal prefixes, for * example "1q", and argument strings which cannot be converted, * for example "abc1" */ if ((*invalid_char_p != '\0') || (invalid_char_p == optarg)) { error(0, 0, "ERROR: Non-decimal device minor number"); usage(); } /* * '--minor' option has been seen */ minor_option = 0xFF; break; } /*################################################################# User entered unsupported option ############################################################## */ case '?': usage(); break; /*################################################################# getopt_long() returned unexpected value ############################################################## */ default: error(EXIT_FAILURE, 0, "ERROR: getopt_long() returned unexpected value %#x", status); break; } } /* * Recognize '--help' option before any others */ if (help_option) { usage(); } /* * '--minor' option must be given */ if (minor_option == 0x00) { error(0, 0, "ERROR: Option '--minor' is required"); usage(); } /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Device initialization %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% */ fprintf(stdout, "Opening device with minor number %lu ...\n", minor_number); dm7820_status = DM7820_General_Open_Board(minor_number, &board); DM7820_Return_Status(dm7820_status, "DM7820_General_Open_Board()"); /* * Reset device */ fprintf(stdout, "Resetting device ...\n"); dm7820_status = DM7820_General_Reset(board); DM7820_Return_Status(dm7820_status, "DM7820_General_Reset()"); /* * Make sure FIFO 1 empty interrupt is disabled to prevent stray interrupts */ fprintf(stdout, "Disabling FIFO 1 empty interrupt ...\n"); dm7820_status = DM7820_General_Enable_Interrupt(board, DM7820_INTERRUPT_FIFO_1_EMPTY, 0x00); DM7820_Return_Status(dm7820_status, "DM7820_General_Enable_Interrupt()"); do_digital_io(); do_incenc(); do_8254(); do_pwm(); do_fifo(); do_dma(); /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Main processing %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% */ /* * Create a large buffer to place data from DMA. This should be done AFTER * the driver has created its buffers as the kernel space DMA buffers must * be contiguous and ours do not have to be. */ dm7820_status = DM7820_FIFO_DMA_Create_Buffer(&temp_buf, DMA_BUF_SIZE * 8); DM7820_Return_Status(dm7820_status, "DM7820_FIFO_DMA_Create_Buffer()"); fprintf(stdout, "Installing user ISR ...\n"); dm7820_status = DM7820_General_InstallISR(board, ISR); DM7820_Return_Status(dm7820_status, "DM7820_General_InstallISR()"); fprintf(stdout, "Setting ISR priority ...\n"); dm7820_status = DM7820_General_SetISRPriority(board, 99); DM7820_Return_Status(dm7820_status, "DM7820_General_SetISRPriority()"); /* * Enable FIFO */ fprintf(stdout, "Enabling FIFO 1 ...\n"); dm7820_status = DM7820_FIFO_Enable(board, DM7820_FIFO_QUEUE_1, 0xFF); DM7820_Return_Status(dm7820_status, "DM7820_FIFO_Enable()"); /* * Enabling DMA channel 0 */ fprintf(stdout, "Enabling and Starting DMA 1 ...\n"); dm7820_status = DM7820_FIFO_DMA_Enable(board, DM7820_FIFO_QUEUE_1, 0xFF, 0xFF); DM7820_Return_Status(dm7820_status, "DM7820_FIFO_DMA_Enable()"); /*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ * Gather the data from the device and place it in our user buffer @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ int temp_interrupts = dma_done_interrupts; /* * Loop here waiting for 4 of the 8 buffers we allocated to fill with * data from the FIFO/DMA. This will be equivalent to a FIFO half-full * DMA transfer. The ISR in the driver will keep the DMA/FIFO going while * we take some time to read the data from the DMA buffer in the device and * place this data in our buffer. */ fprintf(stdout, "Waiting to receive all data from DMA ...\n\n"); uint32_t offset = 0; do { /* * Check to see if we received an interrupt this time */ if (dma_done_interrupts != temp_interrupts) { temp_interrupts = dma_done_interrupts; /* * Check to see if 4 DMA transfers have successfully completed. * This also denotes our FIFO was half full and has been transferred * to DMA in 4 small transfers (based on our DMA configuration). */ if ((temp_interrupts % 4 == 0) && (temp_interrupts > 0)) { /* * Read the 4 buffers that have completed transfer. * Also the offset must be adjusted here so the DMA data is read * into the next block of our buffer. */ dm7820_status = DM7820_FIFO_DMA_Read(board, DM7820_FIFO_QUEUE_1, (temp_buf + (BUF_SIZE * offset)), 4); DM7820_Return_Status(dm7820_status, "DM7820_FIFO_DMA_Read()"); fprintf(stdout, "Retrieved DMA data ... \n"); /* * Increase the offset of the user-space buffer to which our DMA * data will be copied. */ offset += 2; } } /* * Loop until we receive 8 megs or 4M samples. */ } while (temp_interrupts < 32 && !exit_program); /* * Uninstall the user ISR */ fprintf(stdout, "\nInterrupts received removing user ISR ...\n"); dm7820_status = DM7820_General_RemoveISR(board); DM7820_Return_Status(dm7820_status, "DM7820_General_RemoveISR()"); /*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ * Verify data has been successfully sent @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ fprintf(stdout, "Read Complete ... Testing Data ...\n"); fprintf(stdout, "\n\t INDEX\tVALUE\n"); /* * Loop Buffer Size*2 times to print out all the samples. */ for (i = 1; i < DMA_BUF_SIZE * 2; i++) { /* * Read each sample from the buffer and print it. */ read_data = temp_buf[i] - temp_buf[i - 1]; fprintf(stdout, "\t %d\t%6.2f ns\n", i, (float)(read_data) * 1000. * ((float)UTC_RATE / 5)); } fprintf(stdout, "\n%d samples received.\n", i); /*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ * Clean up and exit. @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ /* * Free our large buffer */ dm7820_status = DM7820_FIFO_DMA_Free_Buffer(&temp_buf, DMA_BUF_SIZE * 8); DM7820_Return_Status(dm7820_status, "DM7820_FIFO_DMA_Free_Buffer()"); clean_up(); fprintf(stdout, "\n"); fprintf(stdout, "Successful end of example program.\n"); exit(EXIT_SUCCESS); }