📄 bf537_io.c
字号:
/* bf537_io.c - implementation of bf537 simulation. Copyright (C) 2003-2007 Skyeye Develop Group for help please send mail to <skyeye-developer@lists.sf.linuxforum.net> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option.) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA*//* * 12/16/2006 Michael.Kang <blackfin.kang@gmail.com> */#include "bfin-sim.h"#include "types.h"#include "bf533_io.h"#include "dma.h"#include "bf533_irq.h"#include "skyeye_config.h"#include <stdio.h>#include <fcntl.h>#include <signal.h>extern void dma_mem_cpy (unsigned int src, unsigned int dst, int size);/* 2007-01-18 added by Anthony Lee : for new uart device frame */#include "skyeye_uart.h"#define DEBUG 0#if DEBUG#define DBG_PRINT(a...) printf(##a)#else#define DBG_PRINT(a...)#endif#define IO_ERR {printf("\n%s bf537_io.error!!!addr=0x%x,pc=0x%x\n",__FUNCTION__,addr,PCREG);raise (SIGILL);}#define MALLOC_ERR {printf("\n%s malloc error!\n",__FUNCTION__);skyeye_exit(-1);}#define UART0_RX_IRQ 11#define UART0_TX_IRQ 12/*declare the device bf537_io.functbf537_io.s*/declare_device (uart)declare_device (wd)declare_device (core_int)declare_device (dma)declare_device (dpmc)declare_device (deu)declare_device (ebiu)declare_device (sic)declare_device (l1mem)declare_device (l1dmem)declare_device (rtc)declare_device (tbuf)declare_device (core_timer)declare_device (pf)declare_device (port)declare_device (eth)static void handle_irq ();static void bf537_disable_int ();static void bf537_enable_int (); typedef struct uart { bu16 rbr; bu16 thr; bu16 ier; bu16 iir; bu16 fcr; bu16 lcr; bu16 lsr; bu16 msr; bu16 scr; bu16 dll; bu16 dlh; bu16 gctl; } bf537_uart_t; static int uart_outfd; typedef struct dma_channel { bu32 next_desc_ptr; bu32 start_addr; bu32 x_count; bu32 x_modify; bu32 y_count; bu32 y_modify; bu32 curr_desc_ptr; bu32 curr_addr; bu32 irq_status; bu32 peripheral_map; bu32 curr_x_count; bu32 curr_y_count; } bf537_dma_channel_t; typedef struct l1mem { bu32 reg[L1MEM_IO_SIZE / 4]; } bf537_l1mem_t; typedef struct l1dmem { bu32 reg[L1DMEM_IO_SIZE / 4]; } bf537_l1dmem_t; typedef struct dma { bu16 tc_per; bu16 tc_cnt; bu32 bf537_dma_channel[16][14]; } bf537_dma_t; typedef struct ebiu { bu16 amgctl; bu16 ambctl0; bu16 ambctl1; bu16 sdgctl; bu16 sdbctl; bu16 sdrrc; bu16 sdstat; } bf537_ebiu_t; typedef struct core_int { bu32 evt[16]; bu32 imask; bu32 ipend; bu32 iprio; bu32 ilat; } bf537_core_int_t; typedef struct wd { bu16 ctl; bu32 cnt; bu32 stat; } bf537_wd_t; typedef struct tbuf { bu32 ctrl; bu32 stat; bu32 rix; bu32 rsel; bu32 wix; bu32 wsel; bu32 dbuf[16]; bu32 sbuf[16]; } bf537_tbuf_t; typedef struct deu { bu32 dspid; } bf537_deu_t; typedef struct dpmc { bu16 pll_ctl; bu16 pll_stat; bu16 pll_lockcnt; bu16 vr_ctl; bu16 pll_div; } bf537_dpmc_t; typedef struct sic { bu32 swrst; bu32 syscr; bu32 sic_imask; bu32 sic_iar[4]; bu32 sic_isr; bu32 sic_iwr; } bf537_sic_t; typedef struct rtc { bu32 stat; bu32 ictl; bu32 istat; bu32 swcnt; bu32 alarm; bu32 pren; } bf537_rtc_t; typedef struct core_timer { bu32 tcntl; bu32 tperio; bu32 tscale; bu32 tcount; } bf537_core_timer_t; typedef struct pf { bu32 fio_flag_d; bu32 fio_flag_c; bu32 fio_flag_s; bu32 fio_dir; bu32 fio_polar; bu32 fio_maska_c; bu32 fio_maskb_c; bu32 fio_inen; } bf537_pf_t;typedef struct bf537_port_s{ bu16 portf_fer; bu16 port_mux;}bf537_port_t;typedef struct bf537_eth_s{ bu32 emac_systat;}bf537_eth_t; typedef struct bf537_io { bf537_uart_t uart; /* Receive data register */ bf537_dma_t dma; bf537_ebiu_t ebiu; bf537_core_int_t core_int; bf537_wd_t wd; bf537_deu_t deu; bf537_dpmc_t dpmc; bf537_sic_t sic; bf537_l1mem_t l1mem; bf537_l1dmem_t l1dmem; bf537_rtc_t rtc; bf537_core_timer_t core_timer; bf537_pf_t pf; bf537_tbuf_t tbuf; bf537_port_t port; bf537_eth_t eth; } bf537_io_t;static bf537_io_t bf537_io;/*also be called by raise inst and except*/static void bf537_set_int (int irq){ if(irq != CORE_TIMER_IRQ & irq != 0) //fprintf(PF,"####################irq=%d,in %s\n",irq,__FUNCTION__); ; //if ((bf537_io.core_int.imask | 0x1f) & (1 << irq)) { //if(irq != CORE_TIMER_IRQ & irq != 0) // fprintf(PF,"####################irq=%d,in %s\n",irq,__FUNCTION__); /*set the corresponding int bit to 1 in ilat */ bf537_io.core_int.ilat |= (1 << irq); //}}static voidbf537_clear_int (int irq_no_use){ int irq; //fprintf(PF,"KSDBG:begin in %s,ipend=0x%x,ilat=0x%x,SPREG=0x%x,irq=%d\n",__FUNCTION__, bf537_io.core_int.ipend,bf537_io.core_int.ilat, SPREG, irq); /*fix me, trigger the corresponding int according to some prio check, */ for (irq = 0; irq < 16; irq++) { /* check there is a pending int for clear */ if ((bf537_io.core_int.ipend >> irq) & 0x1) { /*clear the int bit */ bf537_io.core_int.ipend &= ~(1 << irq); /*clear corresponding int in the device */ if (irq == CORE_TIMER_IRQ) { bf537_io.core_timer.tcntl &= ~0x8; } if (bf537_io.core_int.ipend == 0x0) { /*There is no interrupt to handle, switch mode */ //fprintf(PF,"KSDBG:mode switch,SPREG=0x%x,USPREG=0x%x\n",SPREG,USPREG); MODE = USR_MODE; OLDSPREG = SPREG; SPREG = USPREG; } else ; //fprintf(PF,"KSDBG:in super mode,ipend=0x%x,SPREG=0x%x,irq=%d\n",bf537_io.core_int.ipend, SPREG, irq); return; } } //fprintf(PF,"KSDBG:end in %s,ipend=0x%x,SPREG=0x%x,irq=%d\n",__FUNCTION__, bf537_io.core_int.ipend, SPREG, irq);}static voidhandle_irq (){ int irq = 0; if (OLDPCREG < 0x1000) { printf ("in %s,pc=%x,jump to 0x%x,olderpc=0x%x\n", __FUNCTION__, PCREG, OLDPCREG, OLDERPCREG); raise (SIGINT); } /*if global int is disabled,just return */ if (bf537_io.core_int.ipend & 0x10) { return; } /*fix me, trigger the corresponding int according to some prbf537_io.check, */ for (irq = 0; irq < 16; irq++) { if (((bf537_io.core_int.ilat&(bf537_io.core_int.imask|0x1f)) >> irq) & 0x1) { if (irq != CORE_TIMER_IRQ) //fprintf (PF, // "# in %s begin,irq=%d,pc=0x%x,ipend=0x%x,RETI=0x%x\n", // __FUNCTION__, irq, PCREG, bf537_io.core_int.ipend, RETIREG); /*current there is a higher or equal prbf537_io.ity pending int for handle,wait until it finish */ if(bf537_io.core_int.ipend&(~((~0x0) << irq))) return; /* set ipend bit , and clear ilat */ bf537_io.core_int.ilat &= ~(1 << irq); bf537_io.core_int.ipend |= (1 << irq); /*now if did_jump in interp.c is set, the following code is executed twice,maybe it not make something wrong */ if (LC1REG && OLDPCREG == LB1REG && --LC1REG) { //printf("int in the end of loop,PC=%x\n",PCREG); PCREG = LT1REG; } else if (LC0REG && OLDPCREG == LB0REG && --LC0REG) { //printf("int in the end of loop,PC=%x\n",PCREG); PCREG = LT0REG; } /*clear corresponding int in the device */ if (irq == CORE_TIMER_IRQ) { //return; bf537_io.core_timer.tcntl &= ~0x8;// fprintf(PF,"##Timer IRQ:PC=0x%x,\n",PCREG); } else { //fprintf (PF, "## Other IRQ:irq=%d,\n", irq); } /* switch mode */ if (MODE == USR_MODE) { MODE = SUPER_MODE; USPREG = SPREG; SPREG = OLDSPREG; } /*save pc to reti,jump to the corresponding vector */ if (irq == EXCEPT_IRQ) { //fprintf (PF, // "##System Call:PC=0x%x, sys_number=%d,ipend=0x%x\n", // PCREG, PREG (0), // bf537_io.core_int.ipend); saved_state.retx = PCREG; } else { saved_state.reti = PCREG; } PCREG = bf537_io.core_int.evt[irq]; if (irq != CORE_TIMER_IRQ) ; //fprintf (PF, // "## in %s end,irq=%d,pc=0x%x,ipend=0x%x\n", // __FUNCTION__, irq, PCREG, bf537_io.core_int.ipend); /*at the same time , disable global int for protecting reti */ bf537_disable_int (); return; } }}static voidbf537_disable_int (){ //printf("in %s\n",__FUNCTION__); bf537_io.core_int.ipend |= 0x10;}static voidbf537_enable_int (){ //printf("in %s\n",__FUNCTION__); bf537_io.core_int.ipend &= ~0x10;}static voidbf537_cli (bu32 * dreg){ *dreg = bf537_io.core_int.imask; //printf("cli,%x\n",*dreg); bf537_io.core_int.imask = 0x1f;}static voidbf537_sti (bu32 * dreg){ //printf("sti,%x\n",*dreg); bf537_io.core_int.imask = *dreg;}#define BF537_HZ 50static voidbf537_io_do_cycle (void * state){ static int sclk_count = 0; static int timer_count = BF537_HZ; //if (PCREG >= 0x7480048){ // fprintf(PF,"KSDBG:begin,pc=0x%x,insn@pc=0x%x,sp=0x%x,usp=0x%x,ipend=0x%x\n",(PCREG), get_long(saved_state.memory, PCREG), SPREG,USPREG,bf537_io.core_int.ipend); //} sclk_count++; /*if global int is disabled */ /* if(sclk_count == bf537_io.core_timer.tscale+1){ sclk_count = 0; bf537_io.core_timer.tcount--; if(bf537_io.core_timer.tcount == 0){ bf537_set_int(CORE_TIMER_IRQ); bf537_io.core_timer.tcount = bf537_io.core_timer.tperbf537_io.; } } */ if (sclk_count == bf537_io.core_timer.tscale + 1) { sclk_count = 0; timer_count--; if (timer_count == 0) { timer_count = BF537_HZ; /*if previs timer int handle is not finished , this int is lost */ /*If core_timer enabled? */ if ((bf537_io.core_timer.tcntl & 0x2)) { bf537_io.core_timer.tcntl |= 0x8; bf537_set_int (CORE_TIMER_IRQ); } } } if ((bf537_io.sic.sic_imask & 0x1000) && (bf537_io.uart.ier & 0x2)) { //printf("\nUART TX IRQ\n"); bf537_set_int (((bf537_io.sic.sic_iar[1] & 0xf0000) >> 16) + 7); bf537_io.uart.iir = 0x2; bf537_io.sic.sic_isr |= 0x1000; } if (!(bf537_io.uart.lsr & 0x1)) { /* 2007-01-18 modified by Anthony Lee : for new uart device frame */ struct timeval tv; unsigned char buf; tv.tv_sec = 0; tv.tv_usec = 0; //printf("\nUART RX IRQ before skyeye_uart_read\n"); if(skyeye_uart_read(-1, &buf, 1, &tv, NULL) > 0) { //printf ("\nUART RX IRQ,getchar=%c\n",buf); //printf("%c",buf); //putchar(buf); bf537_io.uart.rbr = buf; /*set DR bit in LSR */ bf537_io.uart.lsr |= 0x1; //printf("\nUART RX IRQ getchar\n"); } } if ((bf537_io.sic.sic_imask & 0x800) && (bf537_io.uart.ier & 0x1) && (bf537_io.uart.lsr & 0x1)) { bf537_io.uart.iir = 0x4; bf537_io.sic.sic_isr |= 0x800; bf537_set_int (((bf537_io.sic.sic_iar[1] & 0xf000) >> 12) + 7); } handle_irq ();}static bu8bf537_io_read_byte (void * p_state, bu32 addr){ switch (addr) { default: if (addr >= DMA_IO_START_ADDR && addr < DMA_IO_END_ADDR) { return dma_read_byte (addr); } else if (addr >= UART_IO_START_ADDR && addr < UART_IO_END_ADDR) { return uart_read_byte (addr); } else { IO_ERR; } }}static bu16bf537_io_read_word (void * state, bu32 addr){ switch (addr) { default: if (addr >= DMA_IO_START_ADDR && addr < DMA_IO_END_ADDR) { return dma_read_word (addr); } else if (addr >= UART_IO_START_ADDR && addr < UART_IO_END_ADDR) { return uart_read_word (addr); } else if (addr >= DPMC_IO_START_ADDR && addr < DPMC_IO_END_ADDR) { return dpmc_read_word (addr); } else if (addr >= EBIU_IO_START_ADDR && addr < EBIU_IO_END_ADDR) { return ebiu_read_word (addr); } else if (addr >= RTC_IO_START_ADDR && addr < RTC_IO_END_ADDR) { return rtc_read_word (addr); } else if (addr >= PF_IO_START_ADDR && addr < PF_IO_END_ADDR) { return pf_read_word (addr); } else if (addr >= PORT_IO_START_ADDR && addr <= PORT_IO_END_ADDR){ return port_read_word (addr); } else { IO_ERR; } }}static bu32bf537_io_read_long (void * state, bu32 addr){ switch (addr) { default: if (addr >= DMA_IO_START_ADDR && addr < DMA_IO_END_ADDR) { return dma_read_long (addr);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -