rtems_device_driver video_open( rtems_device_major_number major, rtems_device_minor_number minor, void *arg ) { int i; int status; for(i=0;i<N_BUFFERS;i++) { status = posix_memalign(&buffers[i], 32, 2*FRAME_W*FRAME_H); if(status != 0) { i--; while(i > 0) { free(buffers[i]); i--; } return RTEMS_UNSATISFIED; } } last_buffer = -1; current_buffer = 0; MM_WRITE(MM_BT656_BASE, (unsigned int)buffers[current_buffer]); MM_WRITE(MM_BT656_FILTERSTATUS, BT656_FILTER_FIELD1); return RTEMS_SUCCESSFUL; }
void Clock_driver_support_initialize_hardware(void) { MM_WRITE(MM_TIMER0_COMPARE, (MM_READ(MM_FREQUENCY)/(1000000/rtems_configuration_get_microseconds_per_tick()))); MM_WRITE(MM_TIMER0_COUNTER, 0); MM_WRITE(MM_TIMER0_CONTROL, TIMER_ENABLE | TIMER_AUTORESTART); bsp_interrupt_vector_enable(MM_IRQ_TIMER0); }
static void record_start(struct snd_buffer *buf) { if (buf->nsamples > (AC97_MAX_DMASIZE/4)) buf->nsamples = AC97_MAX_DMASIZE/4; MM_WRITE(MM_AC97_UADDRESS, (unsigned int)buf->samples); MM_WRITE(MM_AC97_UREMAINING, buf->nsamples*4); MM_WRITE(MM_AC97_UCTL, AC97_SCTL_EN); }
int rtems_minimac_driver_attach(struct rtems_bsdnet_ifconfig *config, int attaching) { struct ifnet *ifp; rtems_isr_entry dummy; int i; static int registered; uint8_t *tx_buffer = (uint8_t *)MINIMAC_TX_BASE; if(!attaching) { printk("Minimac driver cannot be detached.\n"); return 0; } ifp = &(arpcom.ac_if); if(registered) { printk("Minimac driver already in use.\n"); return 0; } registered = 1; memcpy(arpcom.ac_enaddr, get_mac_address(), 6); ifp->if_mtu = ETHERMTU; ifp->if_unit = 0; ifp->if_name = "minimac"; ifp->if_init = minimac_init; ifp->if_ioctl = minimac_ioctl; ifp->if_start = minimac_start; ifp->if_output = ether_output; ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX; ifp->if_snd.ifq_maxlen = ifqmaxlen; if_attach(ifp); ether_ifattach(ifp); rx_daemon_id = rtems_bsdnet_newproc("mrxd", 4096, rx_daemon, NULL); tx_daemon_id = rtems_bsdnet_newproc("mtxd", 4096, tx_daemon, NULL); rtems_interrupt_catch(rx_interrupt_handler, MM_IRQ_ETHRX, &dummy); rtems_interrupt_catch(tx_interrupt_handler, MM_IRQ_ETHTX, &dummy); MM_WRITE(MM_MINIMAC_STATE0, MINIMAC_STATE_LOADED); MM_WRITE(MM_MINIMAC_STATE1, MINIMAC_STATE_LOADED); for(i=0;i<7; i++) tx_buffer[i] = 0x55; tx_buffer[7] = 0xd5; MM_WRITE(MM_MINIMAC_SETUP, 0); rtems_bsdnet_event_send(tx_daemon_id, CTS_EVENT); bsp_interrupt_vector_enable(MM_IRQ_ETHRX); bsp_interrupt_vector_enable(MM_IRQ_ETHTX); return 1; }
static int write_cr(unsigned int adr, unsigned int val) { rtems_status_code sc; MM_WRITE(MM_AC97_CRADDR, adr); MM_WRITE(MM_AC97_CRDATAOUT, val); MM_WRITE(MM_AC97_CRCTL, AC97_CRCTL_RQEN|AC97_CRCTL_WRITE); sc = rtems_semaphore_obtain(cr_write_sem, RTEMS_WAIT, CR_TIMEOUT); if (sc != RTEMS_SUCCESSFUL) return 0; return 1; }
static void i2c_write_bit(unsigned int bit) { if(bit) { MM_WRITE(MM_BT656_I2C, BT656_I2C_SDAOE|BT656_I2C_SDAOUT); } else { MM_WRITE(MM_BT656_I2C, BT656_I2C_SDAOE); } i2c_delay(); MM_WRITE(MM_BT656_I2C, MM_READ(MM_BT656_I2C) | BT656_I2C_SDC); i2c_delay(); MM_WRITE(MM_BT656_I2C, MM_READ(MM_BT656_I2C) & ~BT656_I2C_SDC); }
static void i2c_stop_cond(void) { /* set SDA to 0 */ MM_WRITE(MM_BT656_I2C, BT656_I2C_SDAOE); i2c_delay(); /* Clock stretching */ MM_WRITE(MM_BT656_I2C, BT656_I2C_SDAOE|BT656_I2C_SDC); /* SCL is high, set SDA from 0 to 1 */ MM_WRITE(MM_BT656_I2C, BT656_I2C_SDC); i2c_delay(); i2c_started = 0; }
static rtems_isr rx_interrupt_handler(rtems_vector_number vector) { /* Deassert IRQ line. * The RX daemon will then read all the slots we marked as empty. */ if(MM_READ(MM_MINIMAC_STATE0) == MINIMAC_STATE_PENDING) MM_WRITE(MM_MINIMAC_STATE0, MINIMAC_STATE_EMPTY); if(MM_READ(MM_MINIMAC_STATE1) == MINIMAC_STATE_PENDING) MM_WRITE(MM_MINIMAC_STATE1, MINIMAC_STATE_EMPTY); rtems_bsdnet_event_send(rx_daemon_id, RX_EVENT); lm32_interrupt_ack(1 << MM_IRQ_ETHRX); }
static int read_cr(unsigned int adr) { rtems_status_code sc; MM_WRITE(MM_AC97_CRADDR, adr); MM_WRITE(MM_AC97_CRCTL, AC97_CRCTL_RQEN); sc = rtems_semaphore_obtain(cr_write_sem, RTEMS_WAIT, CR_TIMEOUT); if (sc != RTEMS_SUCCESSFUL) return -1; sc = rtems_semaphore_obtain(cr_read_sem, RTEMS_WAIT, CR_TIMEOUT); if (sc != RTEMS_SUCCESSFUL) return -1; return MM_READ(MM_AC97_CRDATAIN); }
static rtems_isr mmconsole_interrupt(rtems_vector_number n) { char c; while (MM_READ(MM_UART_STAT) & UART_STAT_RX_EVT) { c = MM_READ(MM_UART_RXTX); MM_WRITE(MM_UART_STAT, UART_STAT_RX_EVT); rtems_termios_enqueue_raw_characters(tty, &c, 1); } if (MM_READ(MM_UART_STAT) & UART_STAT_TX_EVT) { MM_WRITE(MM_UART_STAT, UART_STAT_TX_EVT); rtems_termios_dequeue_characters(tty, 1); } lm32_interrupt_ack(1 << MM_IRQ_UART); }
static void i2c_start_cond(void) { if(i2c_started) { /* set SDA to 1 */ MM_WRITE(MM_BT656_I2C, BT656_I2C_SDAOE|BT656_I2C_SDAOUT); i2c_delay(); MM_WRITE(MM_BT656_I2C, MM_READ(MM_BT656_I2C) | BT656_I2C_SDC); } /* SCL is high, set SDA from 1 to 0 */ MM_WRITE(MM_BT656_I2C, BT656_I2C_SDAOE|BT656_I2C_SDC); i2c_delay(); MM_WRITE(MM_BT656_I2C, BT656_I2C_SDAOE); i2c_started = 1; }
/* I2C bit-banging functions from http://en.wikipedia.org/wiki/I2c */ static unsigned int i2c_read_bit(void) { unsigned int bit; /* Let the slave drive data */ MM_WRITE(MM_BT656_I2C, 0); i2c_delay(); MM_WRITE(MM_BT656_I2C, BT656_I2C_SDC); i2c_delay(); bit = MM_READ(MM_BT656_I2C) & BT656_I2C_SDAIN; i2c_delay(); MM_WRITE(MM_BT656_I2C, 0); return bit; }
static void icap_write(int val, unsigned int w) { while (!(MM_READ(MM_ICAP) & ICAP_READY)); if (!val) w |= ICAP_CE|ICAP_WRITE; MM_WRITE(MM_ICAP, w); }
rtems_device_driver usbinput_initialize( rtems_device_major_number major, rtems_device_minor_number minor, void *arg ) { rtems_status_code sc; rtems_isr_entry dummy; MM_WRITE(MM_SOFTUSB_CONTROL, SOFTUSB_CONTROL_RESET); mouse_consume = 0; keyboard_consume = 0; midi_consume = 0; sc = rtems_io_register_name(DEVICE_NAME, major, 0); RTEMS_CHECK_SC(sc, "create USB input device"); sc = rtems_message_queue_create( rtems_build_name('U', 'S', 'B', 'I'), 64, 8, 0, &event_q ); RTEMS_CHECK_SC(sc, "create USB event queue"); rtems_interrupt_catch(interrupt_handler, MM_IRQ_USB, &dummy); bsp_interrupt_vector_enable(MM_IRQ_USB); return RTEMS_SUCCESSFUL; }
static void rx_daemon(void *arg) { rtems_event_set events; while(1) { rtems_bsdnet_event_receive(RX_EVENT, RTEMS_EVENT_ANY | RTEMS_WAIT, RTEMS_NO_TIMEOUT, &events); if(MM_READ(MM_MINIMAC_STATE0) == MINIMAC_STATE_EMPTY) { receive_packet((uint8_t *)MINIMAC_RX0_BASE, MM_READ(MM_MINIMAC_COUNT0)); MM_WRITE(MM_MINIMAC_STATE0, MINIMAC_STATE_LOADED); } if(MM_READ(MM_MINIMAC_STATE1) == MINIMAC_STATE_EMPTY) { receive_packet((uint8_t *)MINIMAC_RX1_BASE, MM_READ(MM_MINIMAC_COUNT1)); MM_WRITE(MM_MINIMAC_STATE1, MINIMAC_STATE_LOADED); } } }
static ssize_t mmconsole_write(int minor, const char *buf, size_t n) { rtems_interrupt_level level; rtems_interrupt_disable(level); MM_WRITE(MM_UART_RXTX, *buf); rtems_interrupt_enable(level); return 0; }
static void load_firmware(const unsigned char *firmware, int length) { int i, nwords; volatile unsigned int *usb_dmem = (volatile unsigned int *)MM_SOFTUSB_DMEM_BASE; volatile unsigned int *usb_pmem = (volatile unsigned int *)MM_SOFTUSB_PMEM_BASE; MM_WRITE(MM_SOFTUSB_CONTROL, SOFTUSB_CONTROL_RESET); for(i=0;i<SOFTUSB_DMEM_SIZE/4;i++) usb_dmem[i] = 0; for(i=0;i<SOFTUSB_PMEM_SIZE/2;i++) usb_pmem[i] = 0; nwords = (length+1)/2; for(i=0;i<nwords;i++) usb_pmem[i] = ((unsigned int)(firmware[2*i])) |((unsigned int)(firmware[2*i+1]) << 8); MM_WRITE(MM_SOFTUSB_CONTROL, 0); }
rtems_device_driver video_close( rtems_device_major_number major, rtems_device_minor_number minor, void *arg ) { int i; MM_WRITE(MM_BT656_FILTERSTATUS, 0); while(MM_READ(MM_BT656_FILTERSTATUS) & BT656_FILTER_INFRAME); for(i=0;i<N_BUFFERS;i++) free(buffers[i]); return RTEMS_SUCCESSFUL; }
static rtems_status_code pfpu_execute(struct pfpu_td *td) { rtems_status_code sc; load_program(td->program, td->progsize); load_registers(td->registers); MM_WRITE(MM_PFPU_MESHBASE, (unsigned int)td->output); MM_WRITE(MM_PFPU_HMESHLAST, td->hmeshlast); MM_WRITE(MM_PFPU_VMESHLAST, td->vmeshlast); MM_WRITE(MM_PFPU_CTL, PFPU_CTL_START); sc = rtems_semaphore_obtain(done_sem, RTEMS_WAIT, 10); if (sc != RTEMS_SUCCESSFUL) return sc; if (td->update) update_registers(td->registers); if (td->invalidate) { __asm__ volatile( /* Invalidate Level-1 data cache */ "wcsr DCC, r0\n" "nop\n" ); }
static rtems_isr pcmplay_handler(rtems_vector_number n) { lm32_interrupt_ack(1 << MM_IRQ_AC97DMAR); rtems_message_queue_send(play_q_done, &play_q[play_consume], sizeof(void *)); play_consume = (play_consume + 1) & PLAY_Q_MASK; play_level--; if(play_level > 0) play_start(play_q[play_consume]); else MM_WRITE(MM_AC97_DCTL, 0); }
static void swap_buffers(void) { unsigned short int *p; /* Make sure last buffer swap has been executed */ while (MM_READ(MM_VGA_BASEADDRESS_ACT) != MM_READ(MM_VGA_BASEADDRESS)); p = frontbuffer; frontbuffer = backbuffer; backbuffer = lastbuffer; lastbuffer = p; fb_fix.smem_start = (volatile char *)backbuffer; MM_WRITE(MM_VGA_BASEADDRESS, (unsigned int)frontbuffer); }
static void load_program(unsigned int *program, int size) { int page; int word; volatile unsigned int *pfpu_prog = (unsigned int *)MM_PFPU_CODEBASE; for (page=0;page<(PFPU_PROGSIZE/PFPU_PAGESIZE);page++) { MM_WRITE(MM_PFPU_CODEPAGE, page); for (word=0;word<PFPU_PAGESIZE;word++) { if (size == 0) return; pfpu_prog[word] = *program; program++; size--; } } }
rtems_device_driver frame_buffer_control( rtems_device_major_number major, rtems_device_minor_number minor, void *arg ) { rtems_libio_ioctl_args_t *args = arg; switch (args->command) { case FBIOGET_FSCREENINFO: args->ioctl_return = get_fix_screen_info((struct fb_fix_screeninfo *)args->buffer); return RTEMS_SUCCESSFUL; case FBIOGET_VSCREENINFO: args->ioctl_return = get_var_screen_info((struct fb_var_screeninfo *)args->buffer); return RTEMS_SUCCESSFUL; case FBIOSWAPBUFFERS: swap_buffers(); args->ioctl_return = 0; return RTEMS_SUCCESSFUL; case FBIOSETBUFFERMODE: args->ioctl_return = 0; switch ((unsigned int)args->buffer) { case FB_SINGLE_BUFFERED: init_buffers(); fb_fix.smem_start = (volatile char *)frontbuffer; MM_WRITE(MM_VGA_BASEADDRESS, (unsigned int)frontbuffer); return RTEMS_SUCCESSFUL; case FB_TRIPLE_BUFFERED: fb_fix.smem_start = (volatile char *)backbuffer; return RTEMS_SUCCESSFUL; default: return RTEMS_UNSATISFIED; } case FBIOSETVIDEOMODE: set_video_mode((int)args->buffer); return RTEMS_SUCCESSFUL; default: args->ioctl_return = -1; return RTEMS_UNSATISFIED; } }
rtems_device_driver frame_buffer_initialize( rtems_device_major_number major, rtems_device_minor_number minor, void *arg ) { rtems_status_code status; init_buffers(); fb_fix.smem_start = (volatile char *)frontbuffer; MM_WRITE(MM_VGA_BASEADDRESS, (unsigned int)frontbuffer); status = rtems_io_register_name(FRAMEBUFFER_DEVICE_NAME, major, 0); if (status != RTEMS_SUCCESSFUL) { printk("Error registering frame buffer device!\n"); rtems_fatal_error_occurred( status ); } return RTEMS_SUCCESSFUL; }
static rtems_isr pcmrecord_handler(rtems_vector_number n) { lm32_interrupt_ack(1 << MM_IRQ_AC97DMAW); __asm__ volatile( /* Invalidate Level-1 data cache */ "wcsr DCC, r0\n" "nop\n" ); rtems_message_queue_send(record_q_done, &record_q[record_consume], sizeof(void *)); record_consume = (record_consume + 1) & RECORD_Q_MASK; record_level--; if(record_level > 0) record_start(record_q[record_consume]); else MM_WRITE(MM_AC97_UCTL, 0); }
rtems_device_driver console_initialize( rtems_device_major_number major, rtems_device_minor_number minor, void *arg ) { rtems_status_code status; rtems_isr_entry dummy; rtems_termios_initialize(); status = rtems_io_register_name("/dev/console", major, 0); if (status != RTEMS_SUCCESSFUL) rtems_fatal_error_occurred(status); rtems_interrupt_catch(mmconsole_interrupt, MM_IRQ_UART, &dummy); bsp_interrupt_vector_enable(MM_IRQ_UART); MM_WRITE(MM_UART_CTRL, UART_CTRL_RX_INT|UART_CTRL_TX_INT); return RTEMS_SUCCESSFUL; }
static void send_packet(struct ifnet *ifp, struct mbuf *m) { unsigned int len; unsigned int crc; uint8_t *tx_buffer = (uint8_t *)(MINIMAC_TX_BASE+8); len = copy_mbuf_chain(m, tx_buffer); for(;len<60;len++) tx_buffer[len] = 0x00; // Padding crc = ether_crc32_le(tx_buffer, len) ^ 0xffffffff; tx_buffer[len] = crc & 0xff; tx_buffer[len+1] = (crc & 0xff00) >> 8; tx_buffer[len+2] = (crc & 0xff0000) >> 16; tx_buffer[len+3] = crc >> 24; len += 4; // We add 4 bytes of CRC32 MM_WRITE(MM_MINIMAC_TXCOUNT, len + 8); }
static rtems_isr frame_handler(rtems_vector_number n) { int remaining_attempts; lm32_interrupt_ack(1 << MM_IRQ_VIDEOIN); last_buffer = current_buffer; /* get a new buffer */ remaining_attempts = N_BUFFERS; do { current_buffer++; if(current_buffer == N_BUFFERS) current_buffer = 0; remaining_attempts--; } while(buffers_locked[current_buffer] && (remaining_attempts > 0)); MM_WRITE(MM_BT656_BASE, (unsigned int)buffers[current_buffer]); if(buffers_locked[current_buffer]) printk("Failed to find unlocked buffer\n"); }
rtems_device_driver video_initialize( rtems_device_major_number major, rtems_device_minor_number minor, void *arg ) { rtems_status_code sc; rtems_isr_entry dummy; int i; MM_WRITE(MM_BT656_I2C, BT656_I2C_SDC); sc = rtems_io_register_name(DEVICE_NAME, major, 0); RTEMS_CHECK_SC(sc, "create video input device"); rtems_interrupt_catch(frame_handler, MM_IRQ_VIDEOIN, &dummy); bsp_interrupt_vector_enable(MM_IRQ_VIDEOIN); for(i=0;i<sizeof(vreg_addr);i++) write_reg(vreg_addr[i], vreg_dat[i]); return RTEMS_SUCCESSFUL; }
static void set_video_mode(int mode) { int hres, vres; MM_WRITE(MM_VGA_RESET, VGA_RESET); hres = vres = 0; switch(mode) { case 0: // 640x480, pixel clock: 25MHz hres = 640; vres = 480; MM_WRITE(MM_VGA_HSYNC_START, 656); MM_WRITE(MM_VGA_HSYNC_END, 752); MM_WRITE(MM_VGA_HSCAN, 799); MM_WRITE(MM_VGA_VSYNC_START, 491); MM_WRITE(MM_VGA_VSYNC_END, 493); MM_WRITE(MM_VGA_VSCAN, 523); MM_WRITE(MM_VGA_CLKSEL, 0); break; case 1: // 800x600, pixel clock: 50MHz hres = 800; vres = 600; MM_WRITE(MM_VGA_HSYNC_START, 848); MM_WRITE(MM_VGA_HSYNC_END, 976); MM_WRITE(MM_VGA_HSCAN, 1040); MM_WRITE(MM_VGA_VSYNC_START, 637); MM_WRITE(MM_VGA_VSYNC_END, 643); MM_WRITE(MM_VGA_VSCAN, 666); MM_WRITE(MM_VGA_CLKSEL, 1); break; case 2: // 1024x768, pixel clock: 65MHz hres = 1024; vres = 768; MM_WRITE(MM_VGA_HSYNC_START, 1048); MM_WRITE(MM_VGA_HSYNC_END, 1184); MM_WRITE(MM_VGA_HSCAN, 1344); MM_WRITE(MM_VGA_VSYNC_START, 771); MM_WRITE(MM_VGA_VSYNC_END, 777); MM_WRITE(MM_VGA_VSCAN, 806); MM_WRITE(MM_VGA_CLKSEL, 2); break; } if((hres != 0) && (vres != 0)) { MM_WRITE(MM_VGA_HRES, hres); MM_WRITE(MM_VGA_VRES, vres); fb_var.xres = hres; fb_var.yres = vres; memset(framebufferA, 0, hres*vres*2); memset(framebufferB, 0, hres*vres*2); memset(framebufferC, 0, hres*vres*2); MM_WRITE(MM_VGA_BURST_COUNT, hres*vres/16); MM_WRITE(MM_VGA_RESET, 0); } /* otherwise, leave the VGA controller in reset */ }