skyeye分析报告 - huihoo.org  · web viewskyeye分析报告. skyeye/ 陈渝. chenyu/...

160
SkyEye 分分分分 http://hpclab.cs.tsinghua.edu.cn/~skyeye/ 分分 http://hpclab.cs.tsinghua.edu.cn/~chenyu/ [email protected] 分分分分分分分分分分分分分分

Upload: buidung

Post on 27-Mar-2019

240 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: SkyEye分析报告 - huihoo.org  · Web viewSkyEye分析报告. skyeye/ 陈渝. chenyu/ chenyu@hpclab.cs.tsinghua.edu.cn 清华大学计算机

SkyEye分析报告http://hpclab.cs.tsinghua.edu.cn/~skyeye/

陈渝http://hpclab.cs.tsinghua.edu.cn/~chenyu/

[email protected]

清华大学计算机系高性能计算所

Page 2: SkyEye分析报告 - huihoo.org  · Web viewSkyEye分析报告. skyeye/ 陈渝. chenyu/ chenyu@hpclab.cs.tsinghua.edu.cn 清华大学计算机

2003-01-22

Page 3: SkyEye分析报告 - huihoo.org  · Web viewSkyEye分析报告. skyeye/ 陈渝. chenyu/ chenyu@hpclab.cs.tsinghua.edu.cn 清华大学计算机

目录SkyEye分析报告.............................................................................................................................1前言..................................................................................................................................................4ARM7TDMI分析............................................................................................................................4

ARM的模式............................................................................................................................4Registers...................................................................................................................................4PSR相关..................................................................................................................................4

Program Status Registers..................................................................................................4PSR Transfer (MRS, MSR) 指令.....................................................................................4

AT91EB40分析................................................................................................................................4AT91X40启动引导说明(转载自英蓓特信息技术有限公司)................................................4

Armulator分析.................................................................................................................................4调试 armulator..........................................................................................................................4

当执行到 target sim时 (装入二进制映像文件)........................................................4执行 load后 armulator堆栈 (装入调试信息)...........................................................4

执行流程..................................................................................................................................4当执行到 target sim时初始化的情况.............................................................................4当执行到 load时..............................................................................................................4对读内存操作的处理.......................................................................................................4对写内存操作的处理.......................................................................................................4对中断向量读取的处理...................................................................................................4

配置..........................................................................................................................................4内存布局与 uclinux的关系.............................................................................................4

与AT91结构相关的文件........................................................................................................4时钟中断产生..................................................................................................................4armio.h..............................................................................................................................4armio.c..............................................................................................................................4armmem.h.........................................................................................................................4armmem.c.........................................................................................................................4armdefs.h..........................................................................................................................4

Uclinux for armulator 分析..............................................................................................................4编译信息..................................................................................................................................4

linux elf格式的生成........................................................................................................4二进制映像文件的生成...................................................................................................4

定位信息..................................................................................................................................4文件连接顺序..................................................................................................................4vmlinux.lds.......................................................................................................................4

配置信息..................................................................................................................................4

Page 4: SkyEye分析报告 - huihoo.org  · Web viewSkyEye分析报告. skyeye/ 陈渝. chenyu/ chenyu@hpclab.cs.tsinghua.edu.cn 清华大学计算机

代码信息..................................................................................................................................4ATMEL的 include文件中的信息...................................................................................4其它关键文件..................................................................................................................4初始化..............................................................................................................................4driver.................................................................................................................................4

Page 5: SkyEye分析报告 - huihoo.org  · Web viewSkyEye分析报告. skyeye/ 陈渝. chenyu/ chenyu@hpclab.cs.tsinghua.edu.cn 清华大学计算机

前言

SkyEye基于 armulator/GDB。本文档主要用于辅助 SkyEye项目开发和对 ucos、uclinux的进一步理解。文中存在不少错误和冗余的描述,欢迎指出!在阅读时,请注意红色和蓝色的文字,这些表示比较重要的地方。

ARM7TDMI分析

ARM的模式 User (usr): The normal ARM program execution state FIQ (fiq): Designed to support a data transfer or channel process IRQ (irq): Used for general-purpose interrupt handling Supervisor (svc): Protected mode for the operating system Abort mode (abt): Entered after a data or instruction prefetch abort System (sys): A privileged user mode for the operating system Undefined (und): Entered when an undefined instruction is executedMode changes may be made under software control, or may be brought about by external interrupts or exception processing. Most application programs will execute in User mode. The non-user modes - known as privileged modes - are entered in order to service interrupts or exceptions, or to access protected resources.

Registers

ARM7TDMI has a total of 37 registers - 31 general-purpose 32-bit registers and six status registers - but these cannot all be seen at once. The processor state and operating mode dictate which registers are available to the programmer.

Page 6: SkyEye分析报告 - huihoo.org  · Web viewSkyEye分析报告. skyeye/ 陈渝. chenyu/ chenyu@hpclab.cs.tsinghua.edu.cn 清华大学计算机

Register 14 is used as the subroutine link register. This receives a copy of R15 when a Branch and Link (BL) instruction is executed. At all other times it may be treated as a general-purpose register. The corresponding banked registers R14_svc, R14_irq, R14_fiq, R14_abt and 14_und are similarly used to hold the return values of R15 when interrupts and exceptions arise, or when Branch and Link instructions are executed within interrupt or exception routines.

Register 15 holds the Program Counter (PC). In ARM state, bits [1:0] of R15 are zero and bits [31:2] contain the PC. In THUMB state, bit [0] is zero and bits [31:1] contain the PC.

Register 16 is the CPSR (Current Program Status Register). This contains condition code flags and the current mode bits. FIQ mode has seven banked registers mapped to R8-14 (R8_fiq-R14_fiq). In ARM state, many FIQ handlers do not need to save any registers. User, IRQ, Supervisor, Abort and Undefined each have two banked registers mapped to R13 and R14, allowing each of these modes to have a private stack pointer and link registers.

PSR相关

Program Status Registers

The ARM7TDMI contains a Current Program Status Register (CPSR), plus five Saved Program Status Registers (SPSRs) for use by exception handlers. These registers

hold information about the most recently performed ALU operation control the enabling and disabling of interrupts set the processor operating mode

Page 7: SkyEye分析报告 - huihoo.org  · Web viewSkyEye分析报告. skyeye/ 陈渝. chenyu/ chenyu@hpclab.cs.tsinghua.edu.cn 清华大学计算机

The T bit This reflects the operating state. When this bit is set, the processor is executing in THUMB state, otherwise it is executing in ARM state. This is reflected on the TBIT external signal. Note that the software must never change the state of the TBIT in the CPSR. If this happens, the processor will enter an unpredictable state.

Interrupt disable bits: The I and F bits are the interrupt disable bits. When set, these disable the IRQ and FIQ interrupts respectively. The mode bits: The M4, M3, M2, M1 and M0 bits (M[4:0]) are the mode bits. These determine the processor’s operating mode, as shown in Table 3-1: PSR mode bit values on page 3-9. Not all combinations of the mode bits define a valid processor mode. Only those explicitly described shall be used. The user should be aware that if any illegal value is programmed into the mode bits, M[4:0], then the processor will enter an unrecoverable state. If this occurs, reset should be applied.

PSR Transfer (MRS, MSR) 指令The instruction is only executed if the condition is true. The various conditions are defined in Table 4-2: Condition code summary on page 4-5.The MRS and MSR instructions are formed from a subset of the Data Processing operations and are implemented using the TEQ, TST, CMN and CMP instructions without the S flag set. The encoding is shown in Figure 4-11: PSR transfer on page 4-19.These instructions allow access to the CPSR and SPSR registers. The MRS instruction allows the contents of the CPSR or SPSR_<mode> to be moved to a general register. The MSR instruction allows the contents of a general register to be moved to the CPSR or PSR_<mode> register.The MSR instruction also allows an immediate value or register contents to be transferred to the condition code flags (N,Z,C and V) of CPSR or SPSR_<mode> without affecting the control bits. In this case, the top four bits of the specified register contents or 32 bit immediate

Page 8: SkyEye分析报告 - huihoo.org  · Web viewSkyEye分析报告. skyeye/ 陈渝. chenyu/ chenyu@hpclab.cs.tsinghua.edu.cn 清华大学计算机

value are written to the top four bits of the relevant PSR.

Operand restrictions

In User mode, the control bits of the CPSR are protected from change, so only the condition code flags of the CPSR can be changed. In other (privileged) modes the entire CPSR can be changed. Note that the software must never change the state of the T bit

in the CPSR. If this happens, the processor will enter an unpredictable state. 注意!!! The SPSR register which is accessed depends on the mode at the time of execution. For

example, only SPSR_fiq is accessible when the processor is in FIQ mode. You must not specify R15 as the source or destination register. Also, do not attempt to access an SPSR in User mode, since no such register exists.

Page 9: SkyEye分析报告 - huihoo.org  · Web viewSkyEye分析报告. skyeye/ 陈渝. chenyu/ chenyu@hpclab.cs.tsinghua.edu.cn 清华大学计算机

AT91EB40分析

Evaluation BoardThe board consists of an AT91R40807 together with several peripherals: _ Two serial ports _ Reset button _ Three applicative buttons (FIQ, TIOB0, IRQ0)

Page 10: SkyEye分析报告 - huihoo.org  · Web viewSkyEye分析报告. skyeye/ 陈渝. chenyu/ chenyu@hpclab.cs.tsinghua.edu.cn 清华大学计算机

_ Three LEDs (TIOA0, TIOA1, TIOB0) _ 512K bytes 16-bit SRAM (upgradable to 2048K bytes) 2MB + 2MB _ 128K bytes 16-bit Flash (of which 64K bytes is available for user software) _ 20-pin JTAG interface connector

AT91X40启动引导说明(转载自英蓓特信息技术有限公司)

复位使AT91X40进入引导模式,初始化用户接口寄存器,使其变为缺省直。除了 PC为 0以外,ARM核内部的其它寄存器无定义。

AT91X40复位时,存储器映射将NVM放在 0页面,片内 RAM重定位到 0X00300000。片内32位NVM或片外的 8/16位NVM映射到 0X00000000(片外NVM由NCS0选择)。重映射命令,即重映射寄存器的 RCB位写 1,可以使AT91X40退出引导模式,存储器映射返回到常规的映射关系。此时 0页面处映射为片内 RAM,以存放动态的(可修改的)异常向量表。外部的存储器映射到用户在片选寄存器 0中定义的地址。注意: 如果这个寄存器没有写入相应的值,将会产生内部的冲突。

如果要访问外部芯片(即使用NCS1到NCS7),重映射命令是必须的。

重映射命令执行前后的AT91R40807 内存映射:

注意:在任何时间,内部的 RAM 和外部的引导存储器都在 2 个不同的地址。有两个不同的方法执行 Remap 命令。第一个是标准的。将在引导存储器(与 CS0 联接的)中的程序拷贝到片内 RAM 。然后 remap 能安全地执行。第二个是利用 ARM 核的流水线技术。下面的系列描述允许在不拷贝任何代码的情况下执行 remap 。这个例子被 AT91 库使用, 在文件 \Library\Init\in_reset.s 中。- 拷贝存储控制器的映像 ldr r10 , PtInitTableEBI mov r10 , r10 , LSL #12 mov r10 , r10 , LSR #12- 装载要跳转的地址ldr r12 , PtInitRemap- 拷贝片选寄存器映像到存储控制器和命令 remap ldmia r10 !,{ r0-r9 , r11 } stmia r11 !,{ r0-r9 }- 在它的新地址跳到 ROM

Page 11: SkyEye分析报告 - huihoo.org  · Web viewSkyEye分析报告. skyeye/ 陈渝. chenyu/ chenyu@hpclab.cs.tsinghua.edu.cn 清华大学计算机

mov pc, r12

PtInitTableEBIDCD InitTableEBI PtInitRemapDCD InitRemap PtInitVectorDCD __main - 程序启动InitRemap

在这种情况中, " MOV pc , r12 " 指令在前面的“ STMIA ”执行以前,映射到地址 0 的外部引导 ROM 中取指。然后 " MOV pc , lr " 执行并且这跳到外部的引导区 ROM 的连接地址。/*******************************************************************在复位期间,BMS和NTRI须保持一个有效的电平。NTRI的输入电平决定了AT91X40进入正常模式还是三态模式。BMS告诉芯片引导程序的位置。 BMS 启动模式 1 无片内NVM 外部 8位的存储器(CS0) 有片内NVM 内部的 32位NVM 0 外部的 16位存储器(CS0)看门狗引起的复位不重新检查 BMS和NTRI的电平值。

Armulator分析

调试 armulator

有用的命令gdb –cd DIRECTORY 就把DIRECTORY当作当前目录 否则把 ‘.’ 当作当前目录这样指定 boot.rom等的地址比较方便

Page 12: SkyEye分析报告 - huihoo.org  · Web viewSkyEye分析报告. skyeye/ 陈渝. chenyu/ chenyu@hpclab.cs.tsinghua.edu.cn 清华大学计算机

gdb armulatorrun后执行 armulatorbreak mem_rest 设置断点在 armulator中执行 file linux-2.4.x/linux后显示Reading symbols from ./linux-2.4.x/linux...done.

当执行到 target sim时 (装入二进制映像文件)#0 mem_reset (state=0x82d5368) at armmem.c:91#1 0x081137df in ARMul_Reset (state=0x82d5368) at arminit.c:197#2 0x08113689 in ARMul_NewState () at arminit.c:128#3 0x081127dd in init () at wrapper.c:65#4 0x08112c65 in sim_fetch_register (sd=0x1, rn=0, memory=0xbffff3b0 "`?\b", length=4) at wrapper.c:352 在 sim/arm中的文件#5 0x080da672 in gdbsim_fetch_register (regno=0) at remote-sim.c:304#6 0x080da615 in gdbsim_fetch_register (regno=-1) at remote-sim.c:296#7 0x080dabb2 in gdbsim_open (args=0x0, from_tty=1) at remote-sim.c:534#8 0x080b7561 in execute_command (p=0x81d8f1a "", from_tty=1) at top.c:1546#9 0x080952f1 in command_handler (command=0x81d8f10 "target sim") at event-top.c:515#10 0x08095929 in command_line_handler (rl=0x821bcb0 "惺\036\b") at event-top.c:811#11 0x08155f38 in rl_callback_read_char () at callback.c:122#12 0x080951d2 in stdin_event_handler (error=0, client_data=0x0) at event-top.c:422#13 0x080cecd4 in handle_file_event (event_file_desc=0) at event-loop.c:742#14 0x080ce7b4 in process_event () at event-loop.c:377#15 0x080ce7f9 in gdb_do_one_event (data=0x0) at event-loop.c:414#16 0x080b685d in catch_errors (func=0x80ce7d0 <gdb_do_one_event>, args=0x0, errstring=0x81742c0 "", mask=6) at top.c:615#17 0x080ce82c in start_event_loop () at event-loop.c:450#18 0x0806cc9a in captured_command_loop (data=0x0) at main.c:104#19 0x080b685d in catch_errors (func=0x806cc80 <captured_command_loop>, args=0x0, errstring=0x81742c0 "", mask=6) at top.c:615#20 0x0806d60b in captured_main (data=0xbffff9f0) at main.c:755#21 0x080b685d in catch_errors (func=0x806ccc8 <captured_main>, args=0xbffff9f0, errstring=0x81742c0 "", mask=6) at top.c:615#22 0x0806d637 in main (argc=1, argv=0xbffffa64) at main.c:767#23 0x40322306 in __libc_start_main (main=0x806d610 <main>, argc=1, ubp_av=0xbffffa64, init=0x806bf6c <_init>, fini=0x81607c0 <_fini>, rtld_fini=0x4000d2dc <_dl_fini>, stack_end=0xbffffa5c)

Page 13: SkyEye分析报告 - huihoo.org  · Web viewSkyEye分析报告. skyeye/ 陈渝. chenyu/ chenyu@hpclab.cs.tsinghua.edu.cn 清华大学计算机

at ../sysdeps/generic/libc-start.c:129

执行 load后 armulator堆栈 (装入调试信息)Breakpoint 1, sim_load_file (sd=0x1, myname=0x821bd10 "gdbsim", callback=0x81c12c0, prog=0x81f2040 "/tmp/uclinux/uClinux-dist-20020816/./linux-2.4.x/linux", prog_bfd=0x0, verbose_p=1, lma_p=0, do_write=0x81128d0 <sim_write>) at ./../common/sim-load.c:8080 if (prog_bfd != NULL)(gdb) where#0 sim_load_file (sd=0x1, myname=0x821bd10 "gdbsim", callback=0x81c12c0, prog=0x81f2040 "/tmp/uclinux/uClinux-dist-20020816/./linux-2.4.x/linux", prog_bfd=0x0, verbose_p=1, lma_p=0, do_write=0x81128d0 <sim_write>) at ./../common/sim-load.c:80#1 0x08112e1c in sim_load (sd=0x1, prog=0x81f2040 "/tmp/uclinux/uClinux-dist-20020816/./linux-2.4.x/linux", abfd=0x0, from_tty=1) at wrapper.c:444#2 0x080da8d2 in gdbsim_load (prog=0x81f2040 "/tmp/uclinux/uClinux-dist-20020816/./linux-2.4.x/linux", fromtty=1) at remote-sim.c:394#3 0x080a495e in target_load (arg=0x81f2040 "/tmp/uclinux/uClinux-dist-20020816/./linux-2.4.x/linux", from_tty=1) at target.c:278#4 0x080b7561 in execute_command (p=0x81d8f14 "", from_tty=1) at top.c:1546#5 0x080952f1 in command_handler (command=0x81d8f10 "load") at event-top.c:515#6 0x08095929 in command_line_handler (rl=0x821bcb0 "惺\036\b") at event-top.c:811#7 0x08155f38 in rl_callback_read_char () at callback.c:122#8 0x080951d2 in stdin_event_handler (error=0, client_data=0x0) at event-top.c:422#9 0x080cecd4 in handle_file_event (event_file_desc=0) at event-loop.c:742#10 0x080ce7b4 in process_event () at event-loop.c:377#11 0x080ce7f9 in gdb_do_one_event (data=0x0) at event-loop.c:414#12 0x080b685d in catch_errors (func=0x80ce7d0 <gdb_do_one_event>, args=0x0, errstring=0x81742c0 "", mask=6) at top.c:615#13 0x080ce82c in start_event_loop () at event-loop.c:450#14 0x0806cc9a in captured_command_loop (data=0x0) at main.c:104#15 0x080b685d in catch_errors (func=0x806cc80 <captured_command_loop>, args=0x0, errstring=0x81742c0 "", mask=6) at top.c:615

Page 14: SkyEye分析报告 - huihoo.org  · Web viewSkyEye分析报告. skyeye/ 陈渝. chenyu/ chenyu@hpclab.cs.tsinghua.edu.cn 清华大学计算机

#16 0x0806d60b in captured_main (data=0xbffff9f0) at main.c:755#17 0x080b685d in catch_errors (func=0x806ccc8 <captured_main>, args=0xbffff9f0, errstring=0x81742c0 "", mask=6) at top.c:615#18 0x0806d637 in main (argc=1, argv=0xbffffa64) at main.c:767#19 0x40322306 in __libc_start_main (main=0x806d610 <main>, argc=1, ubp_av=0xbffffa64, init=0x806bf6c <_init>, fini=0x81607c0 <_fini>, rtld_fini=0x4000d2dc <_dl_fini>, stack_end=0xbffffa5c) at ../sysdeps/generic/libc-start.c:129

执行流程

当执行到 target sim时初始化的情况sim/arm/wrapper.c的 init () ---------

ARMul_CoProInit (state); //????state->verbose = verbosity;done = 1;ARMul_SelectProcessor(state, ARM600); ARMul_SetCPSR(state, USER32MODE); //设置 cpsr和系统模式ARMul_Reset(state); Call this routine to set up the initial machine state

….mem_reset(state);io_reset(state);lcd_disable(state);

--------------------------end of ARMul_Reset

当执行到 load时target.c中的 target_load ----remote-sim.c中的 gdbsim-load ------wrapper.c中的 sim_load –----sim-load.c中的 sim_load_file 把 linux执行文件的三个段装入内存中。

Loading section .init, size 0x9000 vma 0x1000000Loading section .text, size 0xcefd0 vma 0x1009000Loading section .data, size 0x81b4 vma 0x10d8000Start address 0x1000000

Page 15: SkyEye分析报告 - huihoo.org  · Web viewSkyEye分析报告. skyeye/ 陈渝. chenyu/ chenyu@hpclab.cs.tsinghua.edu.cn 清华大学计算机

Transfer rate: 7343136 bits in <1 sec.

对读内存操作的处理

/***************************************************************************\* Read Byte (but don't tell anyone!) *\***************************************************************************/注意!Armvirt.c

ARMword ARMul_ReadByte (ARMul_State * state, ARMword address){ ARMword temp, offset;

temp = ARMul_ReadWord (state, address); offset = (((ARMword) state->bigendSig * 3) ^ (address & 3)) << 3; /* bit offset into the word */

return (temp >> offset & 0xffL);}要保证访问地址与字对齐(即最后两位为 0)。这样 offset为 0, 返回的值就对了。

对写内存操作的处理注意!Armvirt.cvoidARMul_WriteByte (ARMul_State * state, ARMword address, ARMword data){ ARMword temp, offset;

temp = ARMul_ReadWord (state, address); //所以在写之前有一个读 //bigendSig=0 address二进制的最后两位如果不为 0,则 offset不为 0

offset = (((ARMword) state->bigendSig * 3) ^ (address & 3)) << 3; /* bit offset into the word */

PutWord (state, address, (temp & ~(0xffL << offset)) | ((data & 0xffL) << offset));

Page 16: SkyEye分析报告 - huihoo.org  · Web viewSkyEye分析报告. skyeye/ 陈渝. chenyu/ chenyu@hpclab.cs.tsinghua.edu.cn 清华大学计算机

}一般 temp & ~(0xffL << offset)应该为 0,这样与大众的理解一致。所以要保证访问地址与字对齐(即最后两位为 0)。

如程序中有如下指令#define outb(v,a) (*(volatile unsigned char *)(a) = (v))#define AT91_NET_BASE (0xfffa0000)#define NE_BASE AT91_NET_BASE#define NE_CR (NE_BASE+0x0)

outb(0x22, NE_CR);

注意 0xfffa0000属于 IO内存空间则在 armulator的执行栈如下:#0 nic_read (state=0x820db08, offset=0 '\000') at skyeye-ne2k.c:236#1 0x08117e09 in io_read_word (state=0x820db08, addr=4294574080) at armio.c:501#2 0x081176f6 in mem_read_word (state=0x820db08, addr=4294574080) at armmem.c:310#3 0x08116be4 in mmu_read_word (state=0x820db08, virt_addr=4294574080, data=0xbffff09c) at armmmu.c:250#4 0x081162e0 in GetWord (state=0x820db08, address=4294574080, data=0xbffff09c) at armvirt.c:61#5 0x08116431 in ARMul_ReadWord (state=0x820db08, address=4294574080) at armvirt.c:265(这说明写操作中隐含了一个读操作)#6 0x08116675 in ARMul_WriteByte (state=0x820db08, address=4294574080, data=34) at armvirt.c:434#7 0x08127d69 in StoreByte (state=0x820db08, instr=3854577664, address=4294574080) at armemu.c:3407#8 0x081257cd in ARMul_Emulate32 (state=0x820db08) at armemu.c:1953#9 0x08114386 in ARMul_DoProg (state=0x820db08) at arminit.c:230#10 0x08112923 in sim_resume (sd=0x1, step=0, siggnal=0) at wrapper.c:213#11 0x080dacdf in gdbsim_wait (pid=-1, status=0xbffff370) at remote-sim.c:686#12 0x0808e9af in wait_for_inferior () at infrun.c:1287#13 0x0808e83a in proceed (addr=4294967295, siggnal=TARGET_SIGNAL_DEFAULT, step=0) at infrun.c:1084#14 0x0808c37b in continue_command (proc_count_exp=0x0, from_tty=1) at infcmd.c:412#15 0x080b7461 in execute_command (p=0x81de1f9 "", from_tty=1) at top.c:1546#16 0x080951f1 in command_handler (command=0x81de1f0 "continue ") at event-top.c:515#17 0x08095829 in command_line_handler (rl=0x8207ed0 "鄜 \b") at event-top.c:811#18 0x08156e00 in rl_callback_read_char () at callback.c:122#19 0x080950d2 in stdin_event_handler (error=0, client_data=0x0) at event-top.c:422#20 0x080cebd4 in handle_file_event (event_file_desc=0) at event-loop.c:742#21 0x080ce6b4 in process_event () at event-loop.c:377#22 0x080ce6f9 in gdb_do_one_event (data=0x0) at event-loop.c:414

Page 17: SkyEye分析报告 - huihoo.org  · Web viewSkyEye分析报告. skyeye/ 陈渝. chenyu/ chenyu@hpclab.cs.tsinghua.edu.cn 清华大学计算机

#23 0x080b675d in catch_errors (func=0x80ce6d0 <gdb_do_one_event>, args=0x0, errstring=0x8175260 "", mask=6) at top.c:615#24 0x080ce72c in start_event_loop () at event-loop.c:450#25 0x0806cb9a in captured_command_loop (data=0x0) at main.c:104#26 0x080b675d in catch_errors (func=0x806cb80 <captured_command_loop>, args=0x0, errstring=0x8175260 "", mask=6) at top.c:615#27 0x0806d50b in captured_main (data=0xbffff9b0) at main.c:755#28 0x080b675d in catch_errors (func=0x806cbc8 <captured_main>, args=0xbffff9b0, errstring=0x8175260 "", mask=6) at top.c:615#29 0x0806d537 in main (argc=1, argv=0xbffffa24) at main.c:767#30 0x400a3306 in __libc_start_main (main=0x806d510 <main>, argc=1, ubp_av=0xbffffa24, init=0x806bf60 <_init>, fini=0x8161690 <_fini>, rtld_fini=0x4000d2dc <_dl_fini>, stack_end=0xbffffa1c)---Type <return> to continue, or q <return> to quit---

at ../sysdeps/generic/libc-start.c:129

对中断向量读取的处理注意 skyeye对读取 IVR和 ISR的处理

static ARMword current_ivr = 0; /* mega hack, 2.0 needs this */ uclinux2.4.x也需要int i;

switch (addr) {case 0xfffff100: /* IVR */

data = unfix_int(state->io.intsr);DBG_PRINT("IVR irqs=%x ", data);for (i = 0; i < 32; i++)

if (data & (1 << i))break;

#if 0data = (i < 32) ? i : 0;

#elseif (i < 32) {

data = i;state->io.intsr &= ~fix_int(1 << data);//读完一个后,就把对应位清除

Page 18: SkyEye分析报告 - huihoo.org  · Web viewSkyEye分析报告. skyeye/ 陈渝. chenyu/ chenyu@hpclab.cs.tsinghua.edu.cn 清华大学计算机

update_int(state);} else

data = 0;current_ivr = data;

#endifDBG_PRINT("read IVR=%d\n", data);break;

case 0xfffff108: /* interrupt status register */ //仅仅读 current_irv的内容#if 0

data = unfix_int(state->io.intsr);for (i = 0; i < 32; i++)

if (data & (1 << i))break;

data = (i < 32) ? i : 0;state->io.intsr &= ~fix_int(1 << data);update_int(state);

#elsedata = current_ivr;

#endifDBG_PRINT("read ISR=%x,%x\n", data, state->io.intsr);break;

――――――――――――――――――――――――――――――――――通过对 skyeye的跟踪,可以看出 uclinux对发生中断向量的处理如下 类似于:

tmp1=__arch_getl(AIC_IVR); tmp2=__arch_getl(AIC_ISR);所以我们的 ucos在 do_IRQ中读取中断向量也为int at91_get_irq(void){ unsigned int tmp1,tmp2; //unsigned int irqnum; tmp1=tmp2=0; tmp1=__arch_getl(AIC_IVR); tmp2=__arch_getl(AIC_ISR); //irqnum=fix_int(tmp1); return tmp1; }

void do_IRQ(void){

Page 19: SkyEye分析报告 - huihoo.org  · Web viewSkyEye分析报告. skyeye/ 陈渝. chenyu/ chenyu@hpclab.cs.tsinghua.edu.cn 清华大学计算机

int irqnum;//chy 2003-01-18 NOTICE: the sequence is important first hte smallest irq then the bigger, ... last the biggestlabel_do: irqnum=0;

while((irqnum=at91_get_irq())!=0){ //yangye 2003-1-19 //chy has //no timer int in this test if(irqnum==KERNEL_TIMER_IRQ_NUM) { OSTimeTick(); atmel_timer_interrupt(); goto label_do; }

//chy 2003-01-18 #ifdef NETENABLE if(irqnum==AT91_NET_IRQNUM) { //first mask net irq at91_mask_irq(AT91_NET_IRQNUM); // the real ne2k isr process in ne2kif.c ne2k_isr(); //unmask net irq and enable net irq again at91_unmask_irq(AT91_NET_IRQNUM); __arch_putl(AT91_NET_IRQNUM,AIC_EOICR); goto label_do; } #endif }}

Page 20: SkyEye分析报告 - huihoo.org  · Web viewSkyEye分析报告. skyeye/ 陈渝. chenyu/ chenyu@hpclab.cs.tsinghua.edu.cn 清华大学计算机

配置

内存布局与 uclinux的关系{ real_read_word, real_write_word, 0x01000000, 0x00400000, }, .text{ real_read_word, _write_word, 0x01400000, 0x00400000, "boot.rom"},{ real_read_word, real_write_word, 0x02000000, 0x00400000, },{ real_read_word, real_write_word, 0x02400000, 0x00001000, },{ real_read_word, _write_word, 0x04000000, 0x00400000, "boot.rom"},{ real_read_word, real_write_word, 0x00000000, 0x00004000, },{ io_read_word, io_write_word, 0xf0000000, 0x10000000, },

arm-elf-readelf –S linux的输出Section Headers: [Nr] Name Type Addr Off Size ES Flg Lk Inf Al [ 0] NULL 00000000 000000 000000 00 0 0 0 [ 1] .init PROGBITS 01000000 008000 009000 00 WAX 0 0 32 [ 2] .text PROGBITS 01009000 011000 0cefd0 00 AX 0 0 32 [ 3] .data PROGBITS 010d8000 0e0000 0081b4 00 WA 0 0 32 [ 4] .bss NOBITS 010e01c0 0e81c0 020a18 00 WA 0 0 32 [ 5] .debug_abbrev PROGBITS 00000000 0e81c0 0393b3 00 0 0 1 [ 6] .debug_info PROGBITS 00000000 121573 167963c 00 0 0 1 [ 7] .debug_line PROGBITS 00000000 179abaf 307908 00 0 0 1 [ 8] .debug_pubnames PROGBITS 00000000 1aa24b7 00b3b1 00 0 0 1 [ 9] .debug_aranges PROGBITS 00000000 1aad868 002280 00 0 0 1 [10] .shstrtab STRTAB 00000000 1aafae8 000077 00 0 0 1 [11] .symtab SYMTAB 00000000 1aafd68 014ec0 10 12 be4 4 [12] .strtab STRTAB 00000000 1ac4c28 0115fe 00 0 0 1Key to Flags: W (write), A (alloc), X (execute), M (merge), S (strings) I (info), L (link order), O (extra OS processing required) o (os specific), p (processor specific) x (unknown)

与AT91结构相关的文件

ar rc libsim.a callback.o syscall.o targ-map.o armcopro.o armemu26.o armemu32.o arminit.o armos.o armsupp.o armvirt.o bag.o thumbemu.o wrapper.o sim-load.o armmmu.o armmem.o armio.o armlcd.o

Page 21: SkyEye分析报告 - huihoo.org  · Web viewSkyEye分析报告. skyeye/ 陈渝. chenyu/ chenyu@hpclab.cs.tsinghua.edu.cn 清华大学计算机

主要包括 armio.[hc[ armmem.[h|c]

ARMul_Emulate32-> io_do_cycle

时钟中断产生io_do_cycle (armio.c)

根据对 skyeye的调试,可知skyeye初始化时t=0 or 1state->io.tc_prescale=50 state->io.tcd_reload[t]=65535

state->io.tc_prescale * state->io.tcd_reload[t] =产生时钟中断的节拍数当 state->io.tc_prescale<0&& state->io.tcd[t] == 0后产生时钟中断。并处理 uart接收,/* uart receive - do this at the timers' prescaled rate for performance reasons */

当执行 ucos (at91_init.c)or uclinux的程序时,有初始化时钟的地方tc->rc = ((ARM_CLK/128)/HZ - 1); /* load the count limit into the CR register */

HZ=100执行完这句话则 state->io.tcd_reload[0]=2559=((ARM_CLK/128)/HZ - 1)

io_write_word函数中case TC1D:

state->io.tcd[0] = state->io.tcd_reload[0] = data & 0xffff;DBG_PRINT("TC1D 0x%x\n", data & 0xffff);break;

这说明产生时钟中断的节拍数与ARM_CLK有关。======== 2003-01-22 13:09:00 您在来信中写道: ========

请问:include/asm/arch-atmel/hardware.h和 timex.h中分别定义了:#define ARM_CLK 32768000

#define CLOCK_TICK_RATE 0x270f

这两个之间有没有关系?是怎么得到相应数值的?谢谢。

Page 22: SkyEye分析报告 - huihoo.org  · Web viewSkyEye分析报告. skyeye/ 陈渝. chenyu/ chenyu@hpclab.cs.tsinghua.edu.cn 清华大学计算机

中断处理(IntPending -> ARMul_Abort

Armsupp.c/***************************************************************************\* Return TRUE if an interrupt is pending, FALSE otherwise. *\***************************************************************************/unsigned IntPending (ARMul_State * state)

arminit.c/***************************************************************************\* This routine causes an Abort to occur, including selecting the correct ** mode, register bank, and the saving of registers. Call with the ** appropriate vector's memory address (0,4,8 ....) *\***************************************************************************/void ARMul_Abort (ARMul_State * state, ARMword vector)

armio.h

#ifndef _ARMIO_H_#define _ARMIO_H_

typedef struct io_state_t {ARMword syscon; /* System control */ARMword sysflg; /* System status flags */ARMword intmr; /* Interrupt status reg */ARMword intsr; /* Interrupt mask reg */ARMword tcd[2]; /* Timer/counter data */ARMword tcd_reload[2]; /* Last value written */int tc_prescale;ARMword uartdr; /* Receive data register */ARMword lcdcon; /* LCD control */ARMword lcd_limit; /* 0xc0000000 <= LCD buffer < lcd_limit */

} io_state_t;

void io_reset(ARMul_State *state);void io_do_cycle(ARMul_State *state);

Page 23: SkyEye分析报告 - huihoo.org  · Web viewSkyEye分析报告. skyeye/ 陈渝. chenyu/ chenyu@hpclab.cs.tsinghua.edu.cn 清华大学计算机

ARMword io_read_word(ARMul_State *state, ARMword addr);void io_write_word(ARMul_State *state, ARMword addr, ARMword data);

#endif /* _ARMIO_H_ */

armio.c

IntPending-> ARMul_Abort/***************************************************************************\* Return TRUE if an interrupt is pending, FALSE otherwise. *\***************************************************************************/

unsignedIntPending (ARMul_State * state)

/***************************************************************************\* This routine causes an Abort to occur, including selecting the correct ** mode, register bank, and the saving of registers. Call with the ** appropriate vector's memory address (0,4,8 ....) *\***************************************************************************/

voidARMul_Abort (ARMul_State * state, ARMword vector)

/* armio.c - I/O registers and interrupt controller. ARMulator extensions for the ARM7100 family. Copyright (C) 1999 Ben Williamson

Changes to support running uClinux/Atmel AT91 targets Copyright (C) 2002 David McCullough <[email protected]>

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

Page 24: SkyEye分析报告 - huihoo.org  · Web viewSkyEye分析报告. skyeye/ 陈渝. chenyu/ chenyu@hpclab.cs.tsinghua.edu.cn 清华大学计算机

(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*/

#include <sys/time.h>#include <sys/types.h>#include <unistd.h>

#include "armdefs.h"#include "clps7110.h"

#define DEBUG 0#if DEBUG #define DBG_PRINT(a...) fprintf(stderr, ##a)#else #define DBG_PRINT(a...)#endif#define DBG_PRINT1 printf

// #define TC_DIVISOR (8150) /* Set your BogoMips here :) */#define TC_DIVISOR (50) /* Set your BogoMips here :) */// #define TC_DIVISOR (5) /* Set your BogoMips here :) */

extern int big_endian;

static void update_int(ARMul_State *state){

ARMword requests = state->io.intsr & state->io.intmr;

state->NfiqSig = (requests & 0x000f) ? LOW : HIGH;state->NirqSig = (requests & 0xfff0) ? LOW : HIGH;

}

static void update_lcd(ARMul_State *state){

Page 25: SkyEye分析报告 - huihoo.org  · Web viewSkyEye分析报告. skyeye/ 陈渝. chenyu/ chenyu@hpclab.cs.tsinghua.edu.cn 清华大学计算机

#if BENW_PATCHlcd_disable(state);if (state->io.syscon & LCDEN) {

ARMword lcdcon = state->io.lcdcon;ARMword vbufsiz = lcdcon & VBUFSIZ;

ARMword linelen = (lcdcon & LINELEN) >> LINELEN_SHIFT;int width, height, depth;

switch (lcdcon & (GSEN|GSMD)) {case GSEN:

depth = 2;break;

case GSEN|GSMD:depth = 4;break;

default:depth = 1;break;

}width = (linelen + 1) * 16;height = (vbufsiz + 1) * 128 / depth / width;lcd_enable(state, width, height, depth);

}#endif}

voidio_reset(ARMul_State *state){

state->io.syscon = 0;state->io.sysflg = URXFE;state->io.intmr = 0;state->io.intsr = UTXINT; /* always ready to transmit */state->io.tcd[0] = 0xffff;state->io.tcd[1] = 0xffff;state->io.tcd_reload[0] = 0xffff;state->io.tcd_reload[1] = 0xffff;state->io.tc_prescale = TC_DIVISOR;state->io.uartdr = 0;state->io.lcdcon = 0;state->io.lcd_limit = 0;state->Exception = TRUE;

Page 26: SkyEye分析报告 - huihoo.org  · Web viewSkyEye分析报告. skyeye/ 陈渝. chenyu/ chenyu@hpclab.cs.tsinghua.edu.cn 清华大学计算机

}

static unsigned charmem_read_char(ARMul_State *state, ARMword addr){

union {unsigned char buf[4];ARMword w;

} tmp;

tmp.w = mem_read_word(state, addr & ~0x3);if (big_endian)

return(tmp.buf[3 - (addr & 0x3)]);return(tmp.buf[addr & 0x3]);

}

static voidmem_write_char(ARMul_State *state, ARMword addr, unsigned char c){

union {unsigned char buf[4];ARMword w;

} tmp;

tmp.w = mem_read_word(state, addr & ~0x3);if (big_endian)

tmp.buf[3 - (addr & 0x3)] = c;else

tmp.buf[addr & 0x3] = c;mem_write_word(state, addr & ~0x3, tmp.w);

}

static ARMword rpr;int rcr;

voidio_do_cycle(ARMul_State *state){

int t;

/* timer/counters */

Page 27: SkyEye分析报告 - huihoo.org  · Web viewSkyEye分析报告. skyeye/ 陈渝. chenyu/ chenyu@hpclab.cs.tsinghua.edu.cn 清华大学计算机

state->io.tc_prescale--;if (state->io.tc_prescale < 0) {

state->io.tc_prescale = TC_DIVISOR;/* decrement the timer/counters, interrupt on underflow */for (t = 0; t < 2; t++) {

if (state->io.tcd[t] == 0) {/* underflow */if (state->io.syscon & (t ? TC2M : TC1M)) {

/* prescale */state->io.tcd[t] = state->io.tcd_reload[t];

} else {state->io.tcd[t] = 0xffff;

}DBG_PRINT(stderr, "[%d]", t);state->io.intsr |= (t ? TC2OI : TC1OI);update_int(state);

} else {state->io.tcd[t]--;

}}/* uart receive - do this at the timers' prescaled rate for performance reasons */if (rcr > 0 && !(state->io.intsr & URXINT)) {

fd_set rfds;struct timeval tv;

FD_ZERO(&rfds);FD_SET(0, &rfds);tv.tv_sec = 0;tv.tv_usec = 0;

if (select(0+1, &rfds, NULL, NULL, &tv) == 1) {unsigned char buf[16];int n, i;

n = read(0, buf, rcr > sizeof(buf) ? sizeof(buf) : rcr);

for (i = 0; i < n; i++, rcr--, rpr++)mem_write_char(state, rpr, buf[i]);

if (rcr == 0)state->io.sysflg &= ~URXFE;

if (n) {state->io.intsr |= URXINT;update_int(state);

Page 28: SkyEye分析报告 - huihoo.org  · Web viewSkyEye分析报告. skyeye/ 陈渝. chenyu/ chenyu@hpclab.cs.tsinghua.edu.cn 清华大学计算机

}DBG_PRINT("uart_receive(rpr=0x%x, rcr=%d)\n", rpr, rcr);

}}

#if BENW_PATCH/* keep the UI alive */lcd_cycle(state);

#endif}

}

/* * Some routines to translate from Atmel IRQ's to ARM7100 IRQ's * and back */

ARMwordfix_int(ARMword val){

ARMword ret = 0;if (val & (1 << 2))

ret |= URXINT;if (val & (1 << 5))

ret |= TC1OI;if (val & (1 << 6))

ret |= TC2OI;return(ret);

}

ARMwordunfix_int(ARMword val){

ARMword ret = 0;if (val & URXINT)

ret |= (1 << 2);if (val & TC1OI)

ret |= (1 << 5);if (val & TC2OI)

ret |= (1 << 6);return(ret);

}

/* * Atmel serial support for uClinux console.

Page 29: SkyEye分析报告 - huihoo.org  · Web viewSkyEye分析报告. skyeye/ 陈渝. chenyu/ chenyu@hpclab.cs.tsinghua.edu.cn 清华大学计算机

*/

static char *uart_reg[] = {"CR","MR","IER","IDR","IMR","CSR","RHR","THR","BRGR","RTOR","TTGR","RES1","RPR","RCR","TPR","TCR",

};

ARMworduart_read(ARMul_State *state, ARMword addr){

ARMword data;

switch ((addr & 0xfff) >> 2) {case 0xd: // RCR

data = rcr;break;

case 0xf: // TCRdata = 0;break;

case 0x5: // CSRdata = (1<<9) | (1<<1) | /* always empty and ready */

(rcr ? ((1 << 3) | (1 << 0)) : 0);break;

case 0x0: // CRcase 0x1: // MRcase 0x2: // IERcase 0x3: // IDRcase 0x4: // IMRcase 0x6: // RHRcase 0x7: // THR

Page 30: SkyEye分析报告 - huihoo.org  · Web viewSkyEye分析报告. skyeye/ 陈渝. chenyu/ chenyu@hpclab.cs.tsinghua.edu.cn 清华大学计算机

case 0x8: // BRGRcase 0x9: // RTORcase 0xa: // TTGRcase 0xb: // RES1case 0xc: // RPRcase 0xe: // TPR

DBG_PRINT("uart_read(%s=0x%08x)\n", uart_reg[(addr&0xfff) >> 2], addr);

break;}return(data);

}

voiduart_write(ARMul_State *state, ARMword addr, ARMword data){

static ARMword tx_buf = 0;

DBG_PRINT("uart_write(0x%x, 0x%x)\n", (addr & 0xfff) >> 2, data);switch ((addr & 0xfff) >> 2) {case 0x0: // CRcase 0x3: // IDRcase 0x9: // RTORcase 0x2: // IER

break;case 0x1: // MRcase 0x4: // IMRcase 0x5: // CSRcase 0x6: // RHR

DBG_PRINT("uart_write(%s=0x%x) = 0x%08x\n",uart_reg[(addr & 0xfff) >> 2], addr, data);

break;case 0x7: // THR

printf("%c", data); fflush(stdout);break;

case 0x8: // BRGRcase 0xa: // TTGRcase 0xb: // RES1

DBG_PRINT("uart_write(%s=0x%x) = 0x%08x\n",uart_reg[(addr & 0xfff) >> 2], addr, data);

break;case 0xd: // RCR

rcr = data;

Page 31: SkyEye分析报告 - huihoo.org  · Web viewSkyEye分析报告. skyeye/ 陈渝. chenyu/ chenyu@hpclab.cs.tsinghua.edu.cn 清华大学计算机

if (rcr == 0)state->io.sysflg &= ~URXFE;

elsestate->io.sysflg |= URXFE;

break;case 0xc: // RPR

DBG_PRINT("uart_write(%s=0x%x) = 0x%08x\n",uart_reg[(addr & 0xfff) >> 2], addr, data);

rpr = data;break;

case 0xe: // TPRtx_buf = data;break;

case 0xf: // TCRfor (; tx_buf && data > 0; data--)

printf("%c", mem_read_char(state, tx_buf++));fflush(stdout);tx_buf = 0;break;

}}

/* Internal registers from 0x80000000 to 0x80002000. We also define a "debug I/O" register thereafter. */

ARMwordio_read_word(ARMul_State *state, ARMword addr){#if BENW_PATCH

ARMword data = 0;

switch (addr - 0x80000000) {// case PADR:// case PBDR:// case PCDR: *// case PDDR: *// case PADDR:// case PBDDR:// case PCDDR:// case PDDDR: *// case PEDR:// case PEDDR:

case SYSCON:

Page 32: SkyEye分析报告 - huihoo.org  · Web viewSkyEye分析报告. skyeye/ 陈渝. chenyu/ chenyu@hpclab.cs.tsinghua.edu.cn 清华大学计算机

data = state->io.syscon;break;

case SYSFLG:data = state->io.sysflg;break;

// case MEMCFG1:// case MEMCFG2:// case /* DRFPR */:

case INTSR:data = state->io.intsr;break;

case INTMR:data = state->io.intmr;break;

case LCDCON:data = state->io.lcdcon;break;

case TC1D:data = state->io.tcd[0];break;

case TC2D:data = state->io.tcd[1];break;

// case RTCDR:// case RTCMR:// case /* PMPCON */:// case CODR:

case UARTDR:data = state->io.uartdr;state->io.sysflg |= URXFE;state->io.intsr &= ~URXINT;update_int(state);break;

// case UBRLCR: *case SYNCIO:

/* if we return zero here, the battery voltage calculation results in a divide-by-zero that messes up the kernel */data = 1;break;

// case PALLSW:// case PALMSW:

/* write-only: */case STFCLR:

Page 33: SkyEye分析报告 - huihoo.org  · Web viewSkyEye分析报告. skyeye/ 陈渝. chenyu/ chenyu@hpclab.cs.tsinghua.edu.cn 清华大学计算机

case BLEOI:case MCEOI:case TEOI:case TC1EOI:case TC2EOI:case RTCEOI:case UMSEOI:case COEOI:case HALT:case STDBY:

break;default:

DBG_PRINT("io_read_word(0x%08x) = 0x%08x\n", addr, data);break;

}return data;

#else/* * The Atmel system registers */

ARMword data = -1;static ARMword current_ivr = 0; /* mega hack, 2.0 needs this */int i;

switch (addr) {case 0xfffff100: /* IVR */

data = unfix_int(state->io.intsr);DBG_PRINT("IVR irqs=%x ", data);for (i = 0; i < 32; i++)

if (data & (1 << i))break;

#if 0data = (i < 32) ? i : 0;

#elseif (i < 32) {

data = i;state->io.intsr &= ~fix_int(1 << data);update_int(state);

} elsedata = 0;

current_ivr = data;#endif

DBG_PRINT("read IVR=%d\n", data);

Page 34: SkyEye分析报告 - huihoo.org  · Web viewSkyEye分析报告. skyeye/ 陈渝. chenyu/ chenyu@hpclab.cs.tsinghua.edu.cn 清华大学计算机

break;case 0xfffff108: /* interrupt status register */

#if 0data = unfix_int(state->io.intsr);for (i = 0; i < 32; i++)

if (data & (1 << i))break;

data = (i < 32) ? i : 0;state->io.intsr &= ~fix_int(1 << data);update_int(state);

#elsedata = current_ivr;

#endifDBG_PRINT("read ISR=%x,%x\n", data, state->io.intsr);break;

case 0xfffff110: /* IMR */data = unfix_int(state->io.intmr);DBG_PRINT("read IMR=%x,%x\n", data,state->io.intmr);break;

case 0xfffff114: /* CORE interrupt status register */data = unfix_int(state->io.intsr);DBG_PRINT("read CISR=%x,%x\n", data,state->io.intsr);break;

case 0xfffff120: /* IECR */data = unfix_int(state->io.intmr);DBG_PRINT("read IECR=%x,%x\n", data,state->io.intmr);break;

case 0xfffff124: /* IDCR */break;

case 0xfff00000: /* CPU ID */data = 0x2078aa0;data = 0x14000040;break;

case 0xfffe00c0: /* TIMER 1 BCR */DBG_PRINT("T1-BCR io_read_word(0x%08x) = 0x%08x\n", addr, data);break;

case 0xfffe00c4: /* TIMER 1 BMR */DBG_PRINT("T1-BMR io_read_word(0x%08x) = 0x%08x\n", addr,

data);break;

case 0xfffe0040: /* TIMER 1 CCR */DBG_PRINT("T1-CCR io_read_word(0x%08x) = 0x%08x\n", addr, data);break;

case 0xfffe0044: /* TIMER 1 CMR */

Page 35: SkyEye分析报告 - huihoo.org  · Web viewSkyEye分析报告. skyeye/ 陈渝. chenyu/ chenyu@hpclab.cs.tsinghua.edu.cn 清华大学计算机

DBG_PRINT("T1-CMR io_read_word(0x%08x) = 0x%08x\n", addr, data);

break;case 0xfffe0068: /* TIMER 1 IDR */

DBG_PRINT("T1-IDR io_read_word(0x%08x) = 0x%08x\n", addr, data);break;

case 0xfffe0050: /* TIMER 1 CV */DBG_PRINT("T1-CV io_read_word(0x%08x) = 0x%08x\n", addr, data);data = state->io.tcd[0];break;

case 0xfffe005c: /* TIMER 1 RC */DBG_PRINT("T1-RC io_read_word(0x%08x) = 0x%08x\n", addr, data);data = state->io.tcd[0];break;

case 0xfffe0060: /* TIMER 1 SR */DBG_PRINT("T1-SR io_read_word(0x%08x) = 0x%08x\n", addr, data);state->io.intsr &= ~TC1OI;break;

case 0xfffe0064: /* TIMER 1 IER */DBG_PRINT("T1-IER io_read_word(0x%08x) = 0x%08x\n", addr, data);break;

default:if ((addr & 0xffffff00) == 0xfffff000)

break;if ((addr & 0xfffff000) == 0xfffd0000) {

data = uart_read(state, addr);break;

}if ((addr & 0xfffff000) == 0xfffcc000) {

// data = uart_read(state, addr);break;

}DBG_PRINT("io_read_word(0x%08x) = 0x%08x\n", addr, data);ARMul_Debug(state, 0, 0);break;

}return data;

#endif}

voidio_write_word(ARMul_State *state, ARMword addr, ARMword data){#if BENW_PATCH

Page 36: SkyEye分析报告 - huihoo.org  · Web viewSkyEye分析报告. skyeye/ 陈渝. chenyu/ chenyu@hpclab.cs.tsinghua.edu.cn 清华大学计算机

ARMword tmp;

switch (addr - 0x80000000) {// case PADR:// case PBDR:// case PCDR: *// case PDDR: *// case PADDR:// case PBDDR:// case PCDDR:// case PDDDR: *// case PEDR:// case PEDDR:

case SYSCON:tmp = state->io.syscon;state->io.syscon = data;if ((tmp & LCDEN) != (data & LCDEN)) {

update_lcd(state);}

// printf("SYSCON = 0x%08x\n", data);break;

case SYSFLG:break;

// case MEMCFG1:// case MEMCFG2:// case /* DRFPR */:

case INTSR:break;

case INTMR:state->io.intmr = data;update_int(state);

// printf("INTMR = 0x%08x\n", data);break;

case LCDCON:tmp = state->io.lcdcon;state->io.lcdcon = data;if ((tmp & (VBUFSIZ|LINELEN|GSEN|GSMD)) != (tmp & (VBUFSIZ|

LINELEN|GSEN|GSMD))) {update_lcd(state);

}break;

case TC1D:state->io.tcd[0] = state->io.tcd_reload[0] = data & 0xffff;DBG_PRINT("TC1D 0x%x\n", data & 0xffff);

Page 37: SkyEye分析报告 - huihoo.org  · Web viewSkyEye分析报告. skyeye/ 陈渝. chenyu/ chenyu@hpclab.cs.tsinghua.edu.cn 清华大学计算机

break;case TC2D:

state->io.tcd[1] = state->io.tcd_reload[1] = data & 0xffff;DBG_PRINT("TC2D 0x%x\n", data & 0xffff);break;

// case RTCDR:// case RTCMR:// case /* PMPCON */:// case CODR:

case UARTDR:/* The UART writes chars to console */printf("%c", (char)data);fflush(stdout);break;

// case UBRLCR: *// case SYNCIO: *// case PALLSW:// case PALMSW:// case STFCLR:

case BLEOI: printf("BLEOI\n"); break;case MCEOI: printf("MCEOI\n"); break;case TEOI: printf("TEOI\n"); break;case TC1EOI:

state->io.intsr &= ~TC1OI;update_int(state);DBG_PRINT("TC1EOI\n");break;

case TC2EOI:state->io.intsr &= ~TC2OI;update_int(state);DBG_PRINT("TC2EOI\n");break;

case RTCEOI printf("RTCEOI\n"); break;:case UMSEOI: printf("UMSEOI\n"); break;case COEOI: printf("COEOI\n"); break;

// case HALT:// case STDBY:

case 0x2000:/* Not a real register, for debugging only: */DBG_PRINT("io_write_word debug: 0x%08lx\n", data);break;

default:// printf("io_write_word(0x%08x, 0x%08x)\n", addr, data);

}

Page 38: SkyEye分析报告 - huihoo.org  · Web viewSkyEye分析报告. skyeye/ 陈渝. chenyu/ chenyu@hpclab.cs.tsinghua.edu.cn 清华大学计算机

#else/* * The Atmel system registers */switch (addr) {case 0xfffff108: /* ISR */

DBG_PRINT("write ISR=0x%x\n", data);state->io.intsr = fix_int(data);break;

case 0xfffff110: /* IMR */state->io.intmr = fix_int(data);DBG_PRINT("write IMR=%x,%x\n", data,state->io.intsr);break;

case 0xfffff114: /* CORE interrupt status register */DBG_PRINT("write CISR=0x%x\n", data);// state->io.intsr = fix_int(data);break;

case 0xfffff120: /* IECR */DBG_PRINT("IECR=0x%x\n", data);state->io.intmr |= fix_int(data);break;

case 0xfffff124: /* IDCR */DBG_PRINT("IDCR=0x%x\n", data);state->io.intmr &= ~fix_int(data);break;

case 0xfffff128: /* CLEAR interrupts */DBG_PRINT("ICCR=0x%x\n", data);state->io.intsr &= ~fix_int(data);break;

case 0xfffff130: /* EOI */DBG_PRINT(stderr, "EOI=0x%x\n", data);state->io.intsr &= ~fix_int(data);update_int(state);break;

case 0xfff00000: /* CPU ID */break;

case 0xfffe00c0: /* TIMER 1 BCR */DBG_PRINT("T1-BCR io_write_word(0x%08x) = 0x%08x\n", addr,

data);break;

case 0xfffe00c4: /* TIMER 1 BMR */DBG_PRINT("T1-BMR io_write_word(0x%08x) = 0x%08x\n", addr,

data);break;

Page 39: SkyEye分析报告 - huihoo.org  · Web viewSkyEye分析报告. skyeye/ 陈渝. chenyu/ chenyu@hpclab.cs.tsinghua.edu.cn 清华大学计算机

case 0xfffe0040: /* TIMER 1 CCR */DBG_PRINT("T1-CCR io_write_word(0x%08x) = 0x%08x\n", addr,

data);if (data & 0x2) {

state->io.syscon &= ~TC1M;} else {

state->io.syscon |= TC1M;}break;

case 0xfffe0044: /* TIMER 1 CMR */DBG_PRINT("T1-CMR io_write_word(0x%08x) = 0x%08x\n", addr,

data);break;

case 0xfffe0068: /* TIMER 1 IDR */DBG_PRINT("T1-IDR io_write_word(0x%08x) = 0x%08x\n", addr, data);break;

case 0xfffe0050: /* TIMER 1 CV */DBG_PRINT("T1-CV io_write_word(0x%08x) = 0x%08x\n", addr, data);state->io.tcd[0] = state->io.tcd_reload[0] = data & 0xffff;break;

case 0xfffe005c: /* TIMER 1 RC */DBG_PRINT("T1-RC io_write_word(0x%08x) = 0x%08x\n", addr, data);state->io.tcd[0] = state->io.tcd_reload[0] = data & 0xffff;break;

case 0xfffe0060: /* TIMER 1 SR */DBG_PRINT("T1-SR io_write_word(0x%08x) = 0x%08x\n", addr, data);break;

case 0xfffe0064: /* TIMER 1 IER */DBG_PRINT("T1-IER io_write_word(0x%08x) = 0x%08x\n", addr, data);break;

default:if ((addr & 0xfffff000) == 0xfffd0000) {

uart_write(state, addr, data);break;

}if ((addr & 0xfffff000) == 0xfffcc000) {

// uart_write(state, addr, data);break;

}if ((addr & 0xffffff00) == 0xfffff000)

break;if ((addr & 0xffff0000) == 0xffff0000) {

DBG_PRINT("io_write_word(0x%08x) = 0x%08x\n", addr, data);break;

Page 40: SkyEye分析报告 - huihoo.org  · Web viewSkyEye分析报告. skyeye/ 陈渝. chenyu/ chenyu@hpclab.cs.tsinghua.edu.cn 清华大学计算机

}DBG_PRINT("io_write_word(0x%08x) = 0x%08x\n", addr, data);ARMul_Debug(state, 0, 0);break;

}#endif}

armmem.h

#ifndef _ARMMEM_H_#define _ARMMEM_H_

#define DRAM_BITS (23) /* 8MB of DRAM */#define ROM_BANKS 16#define ROM_BITS (28) /* 0x10000000 each bank */ 支持 256MB

typedef struct mem_state_t {ARMword * dram;ARMword * rom[ROM_BANKS];long rom_size[ROM_BANKS];

} mem_state_t;

void mem_reset(ARMul_State *state);ARMword mem_read_word(ARMul_State *state, ARMword addr);void mem_write_word(ARMul_State *state, ARMword addr, ARMword data);

#endif /* _ARMMEM_H_ */

armmem.c

#include "armdefs.h"

ARMword fail_read_word(ARMul_State *state, ARMword addr);

Page 41: SkyEye分析报告 - huihoo.org  · Web viewSkyEye分析报告. skyeye/ 陈渝. chenyu/ chenyu@hpclab.cs.tsinghua.edu.cn 清华大学计算机

void fail_write_word(ARMul_State *state, ARMword addr, ARMword data);ARMword warn_read_word(ARMul_State *state, ARMword addr);void warn_write_word(ARMul_State *state, ARMword addr, ARMword data);ARMword _read_word(ARMul_State *state, ARMword addr);void _write_word(ARMul_State *state, ARMword addr, ARMword data);ARMword real_read_word(ARMul_State *state, ARMword addr);void real_write_word(ARMul_State *state, ARMword addr, ARMword data);ARMword io_read_word(ARMul_State *state, ARMword addr);void io_write_word(ARMul_State *state, ARMword addr, ARMword data);

typedef struct mem_bank_t {ARMword (*read_word)(ARMul_State *state, ARMword addr);void (*write_word)(ARMul_State *state, ARMword addr, ARMword data);unsigned long addr, len;char *filename;

} mem_bank_t;

/* Memory map for the CL-PS7111 */

static mem_bank_t mem_banks[] = {#if BENW_PATCH

{ rom_read_word, _write_word }, /* 0x00000000 */{ _read_word, _write_word }, /* 0x10000000 */{ _read_word, _write_word }, /* 0x20000000 */{ _read_word, _write_word }, /* 0x30000000 */{ _read_word, _write_word }, /* 0x40000000 */{ _read_word, _write_word }, /* 0x50000000 */{ sram_read_word, sram_write_word },/* 0x60000000 */{ boot_read_word, boot_write_word }, /* 0x70000000 */{ io_read_word, io_write_word }, /* 0x80000000 */{ _read_word, _write_word }, /* 0x90000000 */{ _read_word, _write_word }, /* 0xA0000000 */{ _read_word, _write_word }, /* 0xB0000000 */{ dram_read_word, dram_write_word }, /* 0xC0000000 */{ _read_word, _write_word }, /* 0xD0000000 */{ _read_word, _write_word }, /* 0xE0000000 */{ _read_word, _write_word } /* 0xF0000000 */

#else/* the yuk's below are to work around a uClinux/mount options problem */

{ real_read_word, real_write_word, 0x01000000, 0x00400000, }, /* 2.4 */与 uclinux中的设置一致

Page 42: SkyEye分析报告 - huihoo.org  · Web viewSkyEye分析报告. skyeye/ 陈渝. chenyu/ chenyu@hpclab.cs.tsinghua.edu.cn 清华大学计算机

{ real_read_word, _write_word, 0x01400000, 0x00400000, "boot.rom"},与 uclinux中的设置一致

{ real_read_word, real_write_word, 0x02000000, 0x00400000, }, /* 2.0 */{ real_read_word, real_write_word, 0x02400000, 0x00001000, }, /* yuk!*/{ real_read_word, _write_word, 0x04000000, 0x00400000, "boot.rom"},{ real_read_word, real_write_word, 0x00000000, 0x00004000, },{ io_read_word, io_write_word, 0xf0000000, 0x10000000, },与 uclinux 中

的设置不一致?#endif

{ fail_read_word, fail_write_word, 0, 0 }};

extern int big_endian;

voidmem_reset(ARMul_State *state){

FILE *f;unsigned char *p;long s;int bank;ARMword swap;

for (bank = 0; bank < mem_banks[bank].len; bank++) {if (state->mem.rom[bank])

free(state->mem.rom[bank]);state->mem.rom[bank] = malloc(mem_banks[bank].len);state->mem.rom_size[bank] = mem_banks[bank].len;if (mem_banks[bank].filename &&

(f = fopen(mem_banks[bank].filename,"r"))) {if (fread(state->mem.rom[bank], 1, mem_banks[bank].len, f) <= 0) {

perror("fread");fprintf(stderr, "Failed to load '%s'\n",

mem_banks[bank].filename);}fclose(f);/* * We need to put the ROM into target endian oder */p = (char *)state->mem.rom[bank];s = 0;while (s < state->mem.rom_size[bank]) {

if (big_endian)swap = ((ARMword)p[3]) | (((ARMword)p[2]) << 8) |

Page 43: SkyEye分析报告 - huihoo.org  · Web viewSkyEye分析报告. skyeye/ 陈渝. chenyu/ chenyu@hpclab.cs.tsinghua.edu.cn 清华大学计算机

(((ARMword)p[1]) << 16) | (((ARMword)p[0]) << 24);else

swap = ((ARMword)p[0]) | (((ARMword)p[1]) << 8) |(((ARMword)p[2]) << 16) | (((ARMword)p[3]) << 24);

* (ARMword *) p = swap;p += 4;s += 4;

}printf("Loaded ROM %s\n", mem_banks[bank].filename);

} else if (mem_banks[bank].filename) {perror(mem_banks[bank].filename);fprintf(stderr, "Couldn't open boot ROM %s - execution will "

"commence with the debugee.\n", mem_banks[bank].filename);}

}}

mem_bank_t *bank_ptr(ARMword addr){

mem_bank_t *mbp;for (mbp = mem_banks; mbp->len; mbp++)

if (mbp->addr <= addr && (addr - mbp->addr) < mbp->len)return(mbp);

return(mbp);}

ARMwordmem_read_word(ARMul_State *state, ARMword addr){

return bank_ptr(addr)->read_word(state, addr);}

voidmem_write_word(ARMul_State *state, ARMword addr, ARMword data){

bank_ptr(addr)->write_word(state, addr, data);}

/* if you want a wanring about strange accesses put this on the region */

ARMwordwarn_read_word(ARMul_State *state, ARMword addr){

fprintf(stderr, "WARNING: illegal read from 0x%x @ 0x%x\n",addr,state->pc);

Page 44: SkyEye分析报告 - huihoo.org  · Web viewSkyEye分析报告. skyeye/ 陈渝. chenyu/ chenyu@hpclab.cs.tsinghua.edu.cn 清华大学计算机

return(0xffffffff);}

voidwarn_write_word(ARMul_State *state, ARMword addr, ARMword data){

fprintf(stderr, "WARNING: illegal write to 0x%x of 0x%x @ 0x%x\n",addr, data, state->pc);

}

/* Accesses that map to gaps in the memory map go here: */

ARMwordfail_read_word(ARMul_State *state, ARMword addr){

fprintf(stderr, "illegal read from 0x%x\n", addr);ARMul_Debug(state, 0, 0);return(0xffffffff);

}

voidfail_write_word(ARMul_State *state, ARMword addr, ARMword data){

fprintf(stderr, "illegal write to 0x%x of 0x%x\n", addr, data);ARMul_Debug(state, 0, 0);

}

ARMword_read_word(ARMul_State *state, ARMword addr){

fprintf(stderr, "undefined read from 0x%x\n", addr);return(0xffffffff);

}

void_write_word(ARMul_State *state, ARMword addr, ARMword data){

fprintf(stderr, "undefined write to 0x%x of 0x%x\n", addr, data);}

Page 45: SkyEye分析报告 - huihoo.org  · Web viewSkyEye分析报告. skyeye/ 陈渝. chenyu/ chenyu@hpclab.cs.tsinghua.edu.cn 清华大学计算机

ARMwordreal_read_word(ARMul_State *state, ARMword addr){

ARMword data;mem_bank_t *mbp = bank_ptr(addr);data = state->mem.rom[mbp - mem_banks][(addr - mbp->addr) >> 2];return data;

}

voidreal_write_word(ARMul_State *state, ARMword addr, ARMword data){

mem_bank_t *mbp = bank_ptr(addr);data = state->mem.rom[mbp - mem_banks][(addr - mbp->addr) >> 2] = data;

}

armdefs.h

#ifndef _ARMDEFS_H_#define _ARMDEFS_H_

#include <stdio.h>#include <stdlib.h>

#ifndef FALSE#define FALSE 0#define TRUE 1#endif#define LOW 0#define HIGH 1#define LOWHIGH 1#define HIGHLOW 2

#ifndef __STDC__typedef char *VoidStar;#endif

typedef unsigned long ARMword; /* must be 32 bits wide */typedef struct ARMul_State ARMul_State;

Page 46: SkyEye分析报告 - huihoo.org  · Web viewSkyEye分析报告. skyeye/ 陈渝. chenyu/ chenyu@hpclab.cs.tsinghua.edu.cn 清华大学计算机

#include "armmmu.h"#include "armmem.h"#include "armio.h"#include "armlcd.h"

//与协处理器相关---------------------------------typedef unsigned ARMul_CPInits (ARMul_State * state);typedef unsigned ARMul_CPExits (ARMul_State * state);typedef unsigned ARMul_LDCs (ARMul_State * state, unsigned type,

ARMword instr, ARMword value);typedef unsigned ARMul_STCs (ARMul_State * state, unsigned type,

ARMword instr, ARMword * value);typedef unsigned ARMul_MRCs (ARMul_State * state, unsigned type,

ARMword instr, ARMword * value);typedef unsigned ARMul_MCRs (ARMul_State * state, unsigned type,

ARMword instr, ARMword value);typedef unsigned ARMul_CDPs (ARMul_State * state, unsigned type,

ARMword instr);typedef unsigned ARMul_CPReads (ARMul_State * state, unsigned reg,

ARMword * value);typedef unsigned ARMul_CPWrites (ARMul_State * state, unsigned reg,

ARMword value);//-------------------------------------------------------struct ARMul_State{ ARMword Emulate; /* to start and stop emulation */ unsigned EndCondition; /* reason for stopping */ unsigned ErrorCode; /* type of illegal instruction */ ARMword Reg[16]; /* the current register file */ ARMword RegBank[7][16]; /* all the registers */ ARMword Cpsr; /* the current psr */ ARMword Spsr[7]; /* the exception psr's */ ARMword NFlag, ZFlag, CFlag, VFlag, IFFlags; /* dummy flags for speed */#ifdef MODET ARMword TFlag; /* Thumb state */#endif ARMword Bank; /* the current register bank */ ARMword Mode; /* the current mode */ ARMword instr, pc, temp; /* saved register state */ ARMword loaded, decoded; /* saved pipeline state */ unsigned long NumScycles, NumNcycles, NumIcycles, NumCcycles, NumFcycles; /* emulated cycles used */ unsigned long NumInstrs; /* the number of instructions executed */

Page 47: SkyEye分析报告 - huihoo.org  · Web viewSkyEye分析报告. skyeye/ 陈渝. chenyu/ chenyu@hpclab.cs.tsinghua.edu.cn 清华大学计算机

unsigned NextInstr; unsigned VectorCatch; /* caught exception mask */ unsigned CallDebug; /* set to call the debugger */ unsigned CanWatch; /* set by memory interface if its willing to suffer the

overhead of checking for watchpoints on each memory access */

unsigned MemReadDebug, MemWriteDebug; unsigned long StopHandle;

unsigned char *MemInPtr; /* the Data In bus */ unsigned char *MemOutPtr; /* the Data Out bus (which you may not need */ unsigned char *MemSparePtr; /* extra space */ ARMword MemSize;

unsigned char *OSptr; /* OS Handle */ char *CommandLine; /* Command Line from ARMsd */

ARMul_CPInits *CPInit[16]; /* coprocessor initialisers */ ARMul_CPExits *CPExit[16]; /* coprocessor finalisers */ ARMul_LDCs *LDC[16]; /* LDC instruction */ ARMul_STCs *STC[16]; /* STC instruction */ ARMul_MRCs *MRC[16]; /* MRC instruction */ ARMul_MCRs *MCR[16]; /* MCR instruction */ ARMul_CDPs *CDP[16]; /* CDP instruction */ ARMul_CPReads *CPRead[16]; /* Read CP register */ ARMul_CPWrites *CPWrite[16];/* Write CP register */ unsigned char *CPData[16]; /* Coprocessor data */ unsigned char const *CPRegWords[16]; /* map of coprocessor register sizes */

unsigned EventSet; /* the number of events in the queue */ unsigned long Now; /* time to the nearest cycle */ struct EventNode **EventPtr; /* the event list */

unsigned Exception; /* enable the next four values */ unsigned Debug; /* show instructions as they are executed */ unsigned NresetSig; /* reset the processor */ unsigned NfiqSig; unsigned NirqSig;

unsigned abortSig; unsigned NtransSig; unsigned bigendSig; unsigned prog32Sig; unsigned data32Sig;

Page 48: SkyEye分析报告 - huihoo.org  · Web viewSkyEye分析报告. skyeye/ 陈渝. chenyu/ chenyu@hpclab.cs.tsinghua.edu.cn 清华大学计算机

unsigned lateabtSig; ARMword Vector; /* synthesize aborts in cycle modes */ ARMword Aborted; /* sticky flag for aborts */ ARMword Reseted; /* sticky flag for Reset */ ARMword Inted, LastInted; /* sticky flags for interrupts */ ARMword Base; /* extra hand for base writeback */ ARMword AbortAddr; /* to keep track of Prefetch aborts */

const struct Dbg_HostosInterface *hostif;

int verbose; /* non-zero means print various messages like the banner */ //重要 mmu_state_t mmu; mem_state_t mem; io_state_t io;};

#define ResetPin NresetSig#define FIQPin NfiqSig#define IRQPin NirqSig#define AbortPin abortSig#define TransPin NtransSig#define BigEndPin bigendSig#define Prog32Pin prog32Sig#define Data32Pin data32Sig#define LateAbortPin lateabtSig

/***************************************************************************\* Types of ARM we know about *\***************************************************************************/

/* The bitflags */#define ARM_Fix26_Prop 0x01#define ARM_Nexec_Prop 0x02#define ARM_Debug_Prop 0x10#define ARM_Isync_Prop ARM_Debug_Prop#define ARM_Lock_Prop 0x20

/* ARM2 family */#define ARM2 (ARM_Fix26_Prop)#define ARM2as ARM2#define ARM61 ARM2#define ARM3 ARM2

Page 49: SkyEye分析报告 - huihoo.org  · Web viewSkyEye分析报告. skyeye/ 陈渝. chenyu/ chenyu@hpclab.cs.tsinghua.edu.cn 清华大学计算机

#ifdef ARM60 /* previous definition in armopts.h */#undef ARM60#endif

/* ARM6 family */#define ARM6 (ARM_Lock_Prop)#define ARM60 ARM6#define ARM600 ARM6#define ARM610 ARM6#define ARM620 ARM6

/***************************************************************************\* Macros to extract instruction fields *\***************************************************************************/

#define BIT(n) ( (ARMword)(instr>>(n))&1) /* bit n of instruction */#define BITS(m,n) ( (ARMword)(instr<<(31-(n))) >> ((31-(n))+(m)) ) /* bits m to n of instr */#define TOPBITS(n) (instr >> (n)) /* bits 31 to n of instr */

/***************************************************************************\* The hardware vector addresses *\***************************************************************************/

The hardware vector addresses

应该从 0x0地址算#define ARMResetV 0L #define ARMUndefinedInstrV 4L#define ARMSWIV 8L#define ARMPrefetchAbortV 12L#define ARMDataAbortV 16L#define ARMAddrExceptnV 20L#define ARMIRQV 24L#define ARMFIQV 28L#define ARMErrorV 32L /* This is an offset, not an address ! */

#define ARMul_ResetV ARMResetV#define ARMul_UndefinedInstrV ARMUndefinedInstrV#define ARMul_SWIV ARMSWIV#define ARMul_PrefetchAbortV ARMPrefetchAbortV

Page 50: SkyEye分析报告 - huihoo.org  · Web viewSkyEye分析报告. skyeye/ 陈渝. chenyu/ chenyu@hpclab.cs.tsinghua.edu.cn 清华大学计算机

#define ARMul_DataAbortV ARMDataAbortV#define ARMul_AddrExceptnV ARMAddrExceptnV#define ARMul_IRQV ARMIRQV#define ARMul_FIQV ARMFIQV

/***************************************************************************\* Mode and Bank Constants *\***************************************************************************/#define USER26MODE 0L#define FIQ26MODE 1L#define IRQ26MODE 2L#define SVC26MODE 3L#define USER32MODE 16L#define FIQ32MODE 17L#define IRQ32MODE 18L#define SVC32MODE 19L#define ABORT32MODE 23L#define UNDEF32MODE 27L

#define ARM32BITMODE (state->Mode > 3)#define ARM26BITMODE (state->Mode <= 3)#define ARMMODE (state->Mode)#define ARMul_MODEBITS 0x1fL#define ARMul_MODE32BIT ARM32BITMODE#define ARMul_MODE26BIT ARM26BITMODE

#define USERBANK 0#define FIQBANK 1#define IRQBANK 2#define SVCBANK 3#define ABORTBANK 4#define UNDEFBANK 5#define DUMMYBANK 6

/***************************************************************************\* Definitons of things in the emulator *\***************************************************************************/

extern void ARMul_EmulateInit (void);extern ARMul_State *ARMul_NewState (void);extern void ARMul_Reset (ARMul_State * state);extern ARMword ARMul_DoProg (ARMul_State * state);extern ARMword ARMul_DoInstr (ARMul_State * state);

Page 51: SkyEye分析报告 - huihoo.org  · Web viewSkyEye分析报告. skyeye/ 陈渝. chenyu/ chenyu@hpclab.cs.tsinghua.edu.cn 清华大学计算机

/***************************************************************************\* Definitons of things for event handling *\***************************************************************************/

extern void ARMul_ScheduleEvent (ARMul_State * state, unsigned long delay, unsigned (*func) ());

extern void ARMul_EnvokeEvent (ARMul_State * state);extern unsigned long ARMul_Time (ARMul_State * state);

/***************************************************************************\* Useful support routines *\***************************************************************************/

extern ARMword ARMul_GetReg (ARMul_State * state, unsigned mode, unsigned reg);

extern void ARMul_SetReg (ARMul_State * state, unsigned mode, unsigned reg, ARMword value);

extern ARMword ARMul_GetPC (ARMul_State * state);extern ARMword ARMul_GetNextPC (ARMul_State * state);extern void ARMul_SetPC (ARMul_State * state, ARMword value);extern ARMword ARMul_GetR15 (ARMul_State * state);extern void ARMul_SetR15 (ARMul_State * state, ARMword value);

extern ARMword ARMul_GetCPSR (ARMul_State * state);extern void ARMul_SetCPSR (ARMul_State * state, ARMword value);extern ARMword ARMul_GetSPSR (ARMul_State * state, ARMword mode);extern void ARMul_SetSPSR (ARMul_State * state, ARMword mode, ARMword value);

/***************************************************************************\* Definitons of things to handle aborts *\***************************************************************************/

extern void ARMul_Abort (ARMul_State * state, ARMword address);#define ARMul_ABORTWORD 0xefffffff /* SWI -1 */#define ARMul_PREFETCHABORT(address) if (state->AbortAddr == 1) \ state->AbortAddr = (address & ~3L)#define ARMul_DATAABORT(address) state->abortSig = HIGH ; \ state->Aborted = ARMul_DataAbortV ;#define ARMul_CLEARABORT state->abortSig = LOW

/***************************************************************************\* Definitons of things in the memory interface *\***************************************************************************/

Page 52: SkyEye分析报告 - huihoo.org  · Web viewSkyEye分析报告. skyeye/ 陈渝. chenyu/ chenyu@hpclab.cs.tsinghua.edu.cn 清华大学计算机

extern unsigned ARMul_MemoryInit (ARMul_State * state, unsigned long initmemsize);

extern void ARMul_MemoryExit (ARMul_State * state);

extern ARMword ARMul_LoadInstrS (ARMul_State * state, ARMword address, ARMword isize);

extern ARMword ARMul_LoadInstrN (ARMul_State * state, ARMword address, ARMword isize);

extern ARMword ARMul_ReLoadInstr (ARMul_State * state, ARMword address, ARMword isize);

extern ARMword ARMul_LoadWordS (ARMul_State * state, ARMword address);extern ARMword ARMul_LoadWordN (ARMul_State * state, ARMword address);extern ARMword ARMul_LoadHalfWord (ARMul_State * state, ARMword address);extern ARMword ARMul_LoadByte (ARMul_State * state, ARMword address);

extern void ARMul_StoreWordS (ARMul_State * state, ARMword address, ARMword data);

extern void ARMul_StoreWordN (ARMul_State * state, ARMword address, ARMword data);

extern void ARMul_StoreHalfWord (ARMul_State * state, ARMword address, ARMword data);

extern void ARMul_StoreByte (ARMul_State * state, ARMword address, ARMword data);

extern ARMword ARMul_SwapWord (ARMul_State * state, ARMword address, ARMword data);

extern ARMword ARMul_SwapByte (ARMul_State * state, ARMword address, ARMword data);

extern void ARMul_Icycles (ARMul_State * state, unsigned number, ARMword address);

extern void ARMul_Ccycles (ARMul_State * state, unsigned number, ARMword address);

extern ARMword ARMul_ReadWord (ARMul_State * state, ARMword address);extern ARMword ARMul_ReadByte (ARMul_State * state, ARMword address);extern void ARMul_WriteWord (ARMul_State * state, ARMword address,

ARMword data);extern void ARMul_WriteByte (ARMul_State * state, ARMword address,

ARMword data);

extern ARMword ARMul_MemAccess (ARMul_State * state, ARMword, ARMword,ARMword, ARMword, ARMword, ARMword, ARMword,

Page 53: SkyEye分析报告 - huihoo.org  · Web viewSkyEye分析报告. skyeye/ 陈渝. chenyu/ chenyu@hpclab.cs.tsinghua.edu.cn 清华大学计算机

ARMword, ARMword, ARMword);

/***************************************************************************\* Definitons of things in the co-processor interface *\***************************************************************************/

#define ARMul_FIRST 0#define ARMul_TRANSFER 1#define ARMul_BUSY 2#define ARMul_DATA 3#define ARMul_INTERRUPT 4#define ARMul_DONE 0#define ARMul_CANT 1#define ARMul_INC 3

extern unsigned ARMul_CoProInit (ARMul_State * state);extern void ARMul_CoProExit (ARMul_State * state);extern void ARMul_CoProAttach (ARMul_State * state, unsigned number,

ARMul_CPInits * init, ARMul_CPExits * exit, ARMul_LDCs * ldc, ARMul_STCs * stc, ARMul_MRCs * mrc, ARMul_MCRs * mcr, ARMul_CDPs * cdp, ARMul_CPReads * read, ARMul_CPWrites * write);

extern void ARMul_CoProDetach (ARMul_State * state, unsigned number);

/***************************************************************************\* Definitons of things in the host environment *\***************************************************************************/

extern unsigned ARMul_OSInit (ARMul_State * state);extern void ARMul_OSExit (ARMul_State * state);extern unsigned ARMul_OSHandleSWI (ARMul_State * state, ARMword number);extern ARMword ARMul_OSLastErrorP (ARMul_State * state);

extern ARMword ARMul_Debug (ARMul_State * state, ARMword pc, ARMword instr);extern unsigned ARMul_OSException (ARMul_State * state, ARMword vector,

ARMword pc);extern int rdi_log;

/***************************************************************************\* Host-dependent stuff *\***************************************************************************/

#ifdef macintosh

Page 54: SkyEye分析报告 - huihoo.org  · Web viewSkyEye分析报告. skyeye/ 陈渝. chenyu/ chenyu@hpclab.cs.tsinghua.edu.cn 清华大学计算机

pascal void SpinCursor (short increment); /* copied from CursorCtl.h */# define HOURGLASS SpinCursor( 1 )# define HOURGLASS_RATE 1023 /* 2^n - 1 */#endif

#endif /* _ARMDEFS_H_ */

extern void ARMul_UndefInstr (ARMul_State *, ARMword);extern void ARMul_FixCPSR (ARMul_State *, ARMword, ARMword);extern void ARMul_FixSPSR (ARMul_State *, ARMword, ARMword);extern void ARMul_ConsolePrint (ARMul_State *, const char *, ...);extern void ARMul_SelectProcessor (ARMul_State *, unsigned);

Uclinux for armulator 分析

编译信息

linux elf格式的生成arm-elf-ld -p -X -T arch/armnommu/vmlinux.lds arch/armnommu/kernel/head-armv.o arch/armnommu/kernel/init_task.o init/main.o init/version.o \ --start-group \ arch/armnommu/kernel/kernel.o arch/armnommu/mm/mm.o arch/armnommu/mach-atmel/atmel.o kernel/kernel.o mmnommu/mmnommu.o fs/fs.o ipc/ipc.o \ drivers/char/char.o drivers/block/block.o drivers/misc/misc.o drivers/net/net.o drivers/media/media.o \ net/network.o \ arch/armnommu/lib/lib.a /tmp/uclinux/uClinux-dist-20020816/linux-2.4.x/lib/lib.a /usr/local/lib/gcc-lib/arm-elf/2.95.3/libgcc.a \ --end-group \ -o linuxarm-elf-nm linux | grep -v '\(compiled\)\|\(\.o$\)\|\( [aUw] \)\|\(\.\.ng$\)\|\(LASH[RL]DI\)' | sort > System.map

Page 55: SkyEye分析报告 - huihoo.org  · Web viewSkyEye分析报告. skyeye/ 陈渝. chenyu/ chenyu@hpclab.cs.tsinghua.edu.cn 清华大学计算机

二进制映像文件的生成arm-elf-objcopy -O binary --remove-section=.romvec \ --remove-section=.text --remove-section=.ramvec \ --remove-section=.bss --remove-section=.eram \ /tmp/uclinux/uClinux-dist-20020816/linux-2.4.x/linux /tmp/uclinux/uClinux-dist-20020816/images/linux.dataarm-elf-objcopy -O binary --remove-section=.ramvec \ --remove-section=.bss --remove-section=.data \ --remove-section=.eram \ --set-section-flags=.romvec=CONTENTS,ALLOC,LOAD,READONLY,CODE \ /tmp/uclinux/uClinux-dist-20020816/linux-2.4.x/linux /tmp/uclinux/uClinux-dist-20020816/images/linux.textcat /tmp/uclinux/uClinux-dist-20020816/images/linux.text /tmp/uclinux/uClinux-dist-20020816/images/linux.data /tmp/uclinux/uClinux-dist-20020816/images/romfs.img > /tmp/uclinux/uClinux-dist-20020816/images/image.binmake[1]: Leaving directory `/tmp/uclinux/uClinux-dist-20020816/vendors/GDB/ARMulator'[root@hpclab uClinux-dist-20020816]#

定位信息

文件连接顺序

arch/armnommu/kernel/head-armv.o arch/armnommu/kernel/init_task.o init/main.o init/version.o \

--start-group \arch/armnommu/kernel/kernel.o arch/armnommu/mm/mm.oarch/armnommu/mach-atmel/atmel.o kernel/kernel.o

Page 56: SkyEye分析报告 - huihoo.org  · Web viewSkyEye分析报告. skyeye/ 陈渝. chenyu/ chenyu@hpclab.cs.tsinghua.edu.cn 清华大学计算机

mmnommu/mmnommu.o fs/fs.o ipc/ipc.odrivers/char/char.odrivers/block/block.odrivers/misc/misc.odrivers/net/net.odrivers/media/media.o \net/network.o \arch/armnommu/lib/lib.a/tmp/uclinux/uClinux-dist-20020816/linux-2.4.x/lib/lib.a /usr/local/lib/gcc-lib/arm-elf/2.95.3/libgcc.a \--end-group \生成文件-o linux

vmlinux.lds

/* ld script to make ARM Linux kernel * taken from the i386 version by Russell King * Written by Martin Mares <[email protected]> */OUTPUT_ARCH(arm)ENTRY(stext)SECTIONS{

. = 0x1000000;

.init : { /* Init code and data */_stext = .;__init_begin = .;

*(.text.init)__proc_info_begin = .;

*(.proc.info)__proc_info_end = .;__arch_info_begin = .;

*(.arch.info)__arch_info_end = .;

*(.data.init). = ALIGN(16);__setup_start = .;

*(.setup.init)__setup_end = .;

Page 57: SkyEye分析报告 - huihoo.org  · Web viewSkyEye分析报告. skyeye/ 陈渝. chenyu/ chenyu@hpclab.cs.tsinghua.edu.cn 清华大学计算机

__initcall_start = .;*(.initcall.init)

__initcall_end = .;. = ALIGN(4096);__init_end = .;

}

/DISCARD/ : { /* Exit code and data */*(.text.exit)*(.data.exit)*(.exitcall.exit)

}

.text : { /* Real text segment */_text = .; /* Text and read-only data */

*(.text)*(.fixup)*(.gnu.warning)*(.text.lock) /* out-of-line lock text */*(.rodata)*(.glue_7)*(.glue_7t)*(.kstrtab)

. = ALIGN(16);__start___ex_table = .; /* Exception table */

*(__ex_table)__stop___ex_table = .;

__start___ksymtab = .; /* Kernel symbol table */*(__ksymtab)

__stop___ksymtab = .;

__start___kallsyms = .; /* All kernel symbols */*(__kallsyms)

__stop___kallsyms = .;

*(.got) /* Global offset table */

_etext = .; /* End of text section */}

. = ALIGN(8192);

.data : {

Page 58: SkyEye分析报告 - huihoo.org  · Web viewSkyEye分析报告. skyeye/ 陈渝. chenyu/ chenyu@hpclab.cs.tsinghua.edu.cn 清华大学计算机

/* * first, the init task union, aligned * to an 8192 byte boundary. */*(.init.task)

/* * then the cacheline aligned data */. = ALIGN(32);*(.data.cacheline_aligned)

/* * and the usual data section */*(.data)CONSTRUCTORS

_edata = .;}

.bss : {__bss_start = .; /* BSS */*(.bss)*(COMMON)_end = . ;

}

. = ALIGN(8192);_end_kernel = . ;

/* Stabs debugging sections. */.stab 0 : { *(.stab) }.stabstr 0 : { *(.stabstr) }.stab.excl 0 : { *(.stab.excl) }.stab.exclstr 0 : { *(.stab.exclstr) }.stab.index 0 : { *(.stab.index) }.stab.indexstr 0 : { *(.stab.indexstr) }.comment 0 : { *(.comment) }.debug_abbrev 0 : { *(.debug_abbrev) }.debug_info 0 : { *(.debug_info) }.debug_line 0 : { *(.debug_line) }.debug_pubnames 0 : { *(.debug_pubnames) }.debug_aranges 0 : { *(.debug_aranges) }

Page 59: SkyEye分析报告 - huihoo.org  · Web viewSkyEye分析报告. skyeye/ 陈渝. chenyu/ chenyu@hpclab.cs.tsinghua.edu.cn 清华大学计算机

}

配置信息uClinux-dist/vendors/GDB/ARMulator/config.linux-2.4.x处定义了模拟的 CPU和MEM的情况# System TypeCONFIG_ARCH_ATMEL=yCONFIG_SET_MEM_PARAM=yDRAM_BASE=01000000 与 armulator中的设置一致DRAM_SIZE=00400000 与 armulator中的设置一致 4MBFLASH_MEM_BASE=01400000 与 armulator中的设置一致 FLASH_SIZE=00400000 与 armulator中的设置一致 4MBCONFIG_NO_PGT_CACHE=yCONFIG_CPU_ARM710=yCONFIG_CPU_32=yCONFIG_CPU_32v4=yCONFIG_SERIAL_ATMEL=yCONFIG_MEM16_BASE=03000000 armulator中?CONFIG_MEM8_BASE=03000000 armulator中?CONFIG_IO16_BASE=02000000 armulator中?CONFIG_IO8_BASE=02000000 armulator中?CONFIG_CPU_AT91X40=y# CONFIG_ATMEL_DEBUG is not set 有什么用?调试内核用。

代码信息在那里最后注册并可用来执行 printk? 这里注册!这里执行,关键结构函数 atmel_console_write设备 atmel_console_device设置函数 atmel_console_setup中断处理 __irq_svc ->do_IRQ

Page 60: SkyEye分析报告 - huihoo.org  · Web viewSkyEye分析报告. skyeye/ 陈渝. chenyu/ chenyu@hpclab.cs.tsinghua.edu.cn 清华大学计算机

ATMEL的 include文件中的信息

可能有用的!

timex.h好像没有用到#define CLOCK_TICK_RATE 0x270f 好像没有用到

dma.h 好像没有用到#define MAX_DMA_ADDRESS 0x01000000#define MAX_DMA_CHANNELS 13#define arch_dma_init(dma_chan)

hardware.h 主要是一些 IO寄存器的定义tc sreial/* * linux/include/asm-arm/arch-atmel/hardware.h * for Atmel AT91 series * 2001 Erwin Authried */

#ifndef __ASM_ARCH_HARDWARE_H#define __ASM_ARCH_HARDWARE_H

/* 0=TC0, 1=TC1, 2=TC2 */#define KERNEL_TIMER 1定义出处./linux-2.4.x/include/linux/autoconf.h:#define CONFIG_CPU_AT91X40 1 #define CONFIG_ARCH_ATMEL 1

Page 61: SkyEye分析报告 - huihoo.org  · Web viewSkyEye分析报告. skyeye/ 陈渝. chenyu/ chenyu@hpclab.cs.tsinghua.edu.cn 清华大学计算机

./linux-2.4.x/include/config/cpu/at91x40.h:#define CONFIG_CPU_AT91X40 1 只有这一句话。!?#ifdef CONFIG_CPU_AT91X40/* ******************* AT91x40xxx ******************** */

#define ARM_CLK (32768000)

#define AT91_USART_CNT 2#define AT91_USART0_BASE (0xfffd0000) 被串口驱动访问#define AT91_USART1_BASE (0xfffcc000)#define AT91_TC_BASE (0xfffe0000)#define AIC_BASE (0xfffff000)#define AT91_PIOA_BASE (0xffff0000)#define AT91_SF_CIDR (0xfff00000)

#define HARD_RESET_NOW()

#define HW_AT91_TIMER_INIT(timer) /* no PMC */

串口初始化/* enable US0,US1 */#define HW_AT91_USART_INIT ((volatile struct pio_regs *)AT91_PIOA_BASE)->pdr = \

PIOA_RXD0|PIOA_TXD0|PIOA_RXD1|PIOA_TXD1;

/* PIOA bit allocation */#define PIOA_TCLK0 (1<<0)#define PIOA_TI0A0 (1<<1)#define PIOA_TI0B0 (1<<2)#define PIOA_TCLK1 (1<<3)#define PIOA_TIOA1 (1<<4)#define PIOA_TIOB1 (1<<5)#define PIOA_TCLK2 (1<<6)#define PIOA_TIOA2 (1<<7)#define PIOA_TIOB2 (1<<8)#define PIOA_IRQ0 (1<<9)#define PIOA_IRQ1 (1<<10)#define PIOA_IRQ2 (1<<11)#define PIOA_FIQ (1<<12)#define PIOA_SCK0 (1<<13)#define PIOA_TXD0 (1<<14)#define PIOA_RXD0 (1<<15)

Page 62: SkyEye分析报告 - huihoo.org  · Web viewSkyEye分析报告. skyeye/ 陈渝. chenyu/ chenyu@hpclab.cs.tsinghua.edu.cn 清华大学计算机

#define PIOA_SCK1 (1<<20)#define PIOA_TXD1 (1<<21)#define PIOA_RXD1 (1<<22)

#define PIOA_MCK0 (1<<25)#define PIOA_NCS2 (1<<26)#define PIOA_NCS3 (1<<27)

#define PIOA_A20_CS7 (1<<28)#define PIOA_A21_CS6 (1<<29)#define PIOA_A22_CS5 (1<<30)#define PIOA_A23_CS4 (1<<31)

#elif CONFIG_CPU_AT91X63/* ******************* AT91x63xxx ******************** */

#define ARM_CLK (25000000)

#define AT91_USART_CNT 2#define AT91_USART0_BASE (0xfffc0000)#define AT91_USART1_BASE (0xfffc4000)#define AT91_TC_BASE (0xfffd0000)#define AIC_BASE (0xfffff000)#define AT91_PIOA_BASE (0xfffec000)#define AT91_PIOB_BASE (0xffff0000)#define AT91_PMC_BASE (0xffff4000)

#define HARD_RESET_NOW()

/* enable US0,US1 */#define HW_AT91_USART_INIT ((volatile struct pmc_regs *)AT91_PMC_BASE)->pcer = \

(1<<2) | (1<<3) | (1<<13); \ ((volatile struct pio_regs *)AT91_PIOA_BASE)->pdr = \

PIOA_RXD0|PIOA_TXD0|PIOA_RXD1|PIOA_TXD1;

#define HW_AT91_TIMER_INIT(timer) ((volatile struct pmc_regs *)AT91_PMC_BASE)->pcer = \

1<<(timer+6);

/* PIOA bit allocation */#define PIOA_TCLK3 (1<<0)

Page 63: SkyEye分析报告 - huihoo.org  · Web viewSkyEye分析报告. skyeye/ 陈渝. chenyu/ chenyu@hpclab.cs.tsinghua.edu.cn 清华大学计算机

#define PIOA_TI0A3 (1<<1)#define PIOA_TI0B3 (1<<2)#define PIOA_TCLK4 (1<<3)#define PIOA_TI0A4 (1<<4)#define PIOA_TI0B4 (1<<5)#define PIOA_TCLK5 (1<<6)#define PIOA_TI0A5 (1<<7)#define PIOA_TI0B5 (1<<8)#define PIOA_IRQ0 (1<<9)#define PIOA_IRQ1 (1<<10)#define PIOA_IRQ2 (1<<11)#define PIOA_IRQ3 (1<<12)#define PIOA_FIQ (1<<13)#define PIOA_SCK0 (1<<14)#define PIOA_TXD0 (1<<15)#define PIOA_RXD0 (1<<16)#define PIOA_SCK1 (1<<17)#define PIOA_TXD1 (1<<18)#define PIOA_RXD1 (1<<19)#define PIOA_SCK2 (1<<20)#define PIOA_TXD2 (1<<21)#define PIOA_RXD2 (1<<22)#define PIOA_SPCK (1<<23)#define PIOA_MISO (1<<24)#define PIOA_MOSI (1<<25)#define PIOA_NPCS0 (1<<26)#define PIOA_NPCS1 (1<<27)#define PIOA_NPCS2 (1<<28)#define PIOA_NPCS3 (1<<29)

/* PIOB bit allocation */#define PIOB_MPI_NOE (1<<0)#define PIOB_MPI_NLB (1<<1)#define PIOB_MPI_NUB (1<<2)

#define PIOB_MCK0 (1<<17)#define PIOB_BMS (1<<18)#define PIOB_TCLK0 (1<<19)#define PIOB_TIOA0 (1<<20)#define PIOB_TIOB0 (1<<21)#define PIOB_TCLK1 (1<<22)#define PIOB_TIOA1 (1<<23)#define PIOB_TIOB1 (1<<24)#define PIOB_TCLK2 (1<<25)

Page 64: SkyEye分析报告 - huihoo.org  · Web viewSkyEye分析报告. skyeye/ 陈渝. chenyu/ chenyu@hpclab.cs.tsinghua.edu.cn 清华大学计算机

#define PIOB_TIOA2 (1<<26)#define PIOB_TIOB2 (1<<27)#else #error "Configuration error: No CPU defined"#endif

/* ******************* COMMON PART ******************** */#define AIC_SMR(i) (AIC_BASE+i*4)#define AIC_IVR (AIC_BASE+0x100)#define AIC_FVR (AIC_BASE+0x104)#define AIC_ISR (AIC_BASE+0x108)#define AIC_IPR (AIC_BASE+0x10C)#define AIC_IMR (AIC_BASE+0x110)#define AIC_CISR (AIC_BASE+0x114)#define AIC_IECR (AIC_BASE+0x120)#define AIC_IDCR (AIC_BASE+0x124)#define AIC_ICCR (AIC_BASE+0x128)#define AIC_ISCR (AIC_BASE+0x12C)#define AIC_EOICR (AIC_BASE+0x130)

#ifndef __ASSEMBLER__struct at91_timer_channel{

unsigned long ccr; // channel control register (WO)unsigned long cmr; // channel mode register (RW)unsigned long reserved[2];unsigned long cv; // counter value (RW)unsigned long ra; // register A (RW)unsigned long rb; // register B (RW)unsigned long rc; // register C (RW)unsigned long sr; // status register (RO)unsigned long ier; // interrupt enable register (WO)unsigned long idr; // interrupt disable register (WO)unsigned long imr; // interrupt mask register (RO)

};

struct at91_timers{

struct {struct at91_timer_channel ch;unsigned char padding[0x40-sizeof(struct at91_timer_channel)];

Page 65: SkyEye分析报告 - huihoo.org  · Web viewSkyEye分析报告. skyeye/ 陈渝. chenyu/ chenyu@hpclab.cs.tsinghua.edu.cn 清华大学计算机

} chans[3];unsigned long bcr; // block control register (WO)unsigned long bmr; // block mode register (RW)

};#endif

/* TC control register */#define TC_SYNC (1)

/* TC mode register */#define TC2XC2S(x) (x & 0x3)#define TC1XC1S(x) (x<<2 & 0xc)#define TC0XC0S(x) (x<<4 & 0x30)#define TCNXCNS(timer,v) ((v) << (timer<<1))

/* TC channel control */#define TC_CLKEN (1)#define TC_CLKDIS (1<<1)#define TC_SWTRG (1<<2)

/* TC interrupts enable/disable/mask and status registers */#define TC_MTIOB (1<<18)#define TC_MTIOA (1<<17)#define TC_CLKSTA (1<<16)

#define TC_ETRGS (1<<7)#define TC_LDRBS (1<<6)#define TC_LDRAS (1<<5)#define TC_CPCS (1<<4)#define TC_CPBS (1<<3)#define TC_CPAS (1<<2)#define TC_LOVRS (1<<1)#define TC_COVFS (1)

/* * USART registers */

#ifndef __ASSEMBLER__struct atmel_usart_regs{

unsigned long cr; // control unsigned long mr; // modeunsigned long ier; // interrupt enableunsigned long idr; // interrupt disable

Page 66: SkyEye分析报告 - huihoo.org  · Web viewSkyEye分析报告. skyeye/ 陈渝. chenyu/ chenyu@hpclab.cs.tsinghua.edu.cn 清华大学计算机

unsigned long imr; // interrupt maskunsigned long csr; // channel statusunsigned long rhr; // receive holding unsigned long thr; // tramsmit holdingunsigned long brgr; // baud rate generatorunsigned long rtor; // rx time-outunsigned long ttgr; // tx time-guardunsigned long res1;unsigned long rpr; // rx pointerunsigned long rcr; // rx counterunsigned long tpr; // tx pointerunsigned long tcr; // tx counter

};#endif

/* US control register */#define US_SENDA (1<<12)#define US_STTO (1<<11)#define US_STPBRK (1<<10)#define US_STTBRK (1<<9)#define US_RSTSTA (1<<8)#define US_TXDIS(1<<7)#define US_TXEN (1<<6)#define US_RXDIS (1<<5)#define US_RXEN (1<<4)#define US_RSTTX (1<<3)#define US_RSTRX (1<<2)

/* US mode register */#define US_CLK0 (1<<18)#define US_MODE9 (1<<17)#define US_CHMODE(x)(x<<14 & 0xc000)#define US_NBSTOP(x)(x<<12 & 0x3000)#define US_PAR(x) (x<<9 & 0xe00)#define US_SYNC (1<<8)#define US_CHRL(x) (x<<6 & 0xc0)#define US_USCLKS(x)(x<<4 & 0x30)

/* US interrupts enable/disable/mask and status register */#define US_DMSI (1<<10)#define US_TXEMPTY (1<<9)#define US_TIMEOUT (1<<8)#define US_PARE (1<<7)#define US_FRAME (1<<6)

Page 67: SkyEye分析报告 - huihoo.org  · Web viewSkyEye分析报告. skyeye/ 陈渝. chenyu/ chenyu@hpclab.cs.tsinghua.edu.cn 清华大学计算机

#define US_OVRE (1<<5)#define US_ENDTX (1<<4)#define US_ENDRX (1<<3)#define US_RXBRK (1<<2)#define US_TXRDY (1<<1)#define US_RXRDY (1)

#define US_ALL_INTS (US_DMSI|US_TXEMPTY|US_TIMEOUT|US_PARE|US_FRAME|US_OVRE|US_ENDTX|US_ENDRX|US_RXBRK|US_TXRDY|US_RXRDY)

#define PIO(i) (1<<i)

#ifndef __ASSEMBLER__struct pio_regs{

unsigned long per;unsigned long pdr;unsigned long psr;unsigned long res1;unsigned long oer;unsigned long odr;unsigned long osr;unsigned long res2;unsigned long ifer;unsigned long ifdr;unsigned long ifsr;unsigned long res3;unsigned long sodr;unsigned long codr;unsigned long odsr;unsigned long pdsr;unsigned long ier;unsigned long idr;unsigned long imr;unsigned long isr;

};#endif

#ifndef __ASSEMBLER__struct pmc_regs{

unsigned long scer;unsigned long scdr;unsigned long scsr;unsigned long reserved;unsigned long pcer;

Page 68: SkyEye分析报告 - huihoo.org  · Web viewSkyEye分析报告. skyeye/ 陈渝. chenyu/ chenyu@hpclab.cs.tsinghua.edu.cn 清华大学计算机

unsigned long pcdr;unsigned long pcsr;

};#endif

#endif /* _ASM_ARCH_HARDWARE_H */

io.h 好像用处不大/* * linux/include/asm-armnommu/arch-dsc21/io.h * * Copyright (C) 1997-1999 Russell King * * Modifications: * 06-12-1997RMK Created. * 07-04-1999RMK Major cleanup * 02-19-2001 gjm Leveraged for armnommu/dsc21 */#ifndef __ASM_ARM_ARCH_IO_H#define __ASM_ARM_ARCH_IO_H

/* * kernel/resource.c uses this to initialize the global ioport_resource struct * which is used in all calls to request_resource(), allocate_resource(), etc. * --gmcnutt */#define IO_SPACE_LIMIT 0xffffffff

/* * If we define __io then asm/io.h will take care of most of the inb & friends * macros. It still leaves us some 16bit macros to deal with ourselves, though. * We don't have PCI or ISA on the dsc21 so I dropped __mem_pci & __mem_isa. * --gmcnutt */#define __io(a) (CONFIG_IO16_BASE + (a))#define __iob(a) (CONFIG_IO8_BASE + (a)) // byte io address

#define __arch_getw(a) (*(volatile unsigned short *)(a))#define __arch_putw(v,a) (*(volatile unsigned short *)(a) = (v))

/*

Page 69: SkyEye分析报告 - huihoo.org  · Web viewSkyEye分析报告. skyeye/ 陈渝. chenyu/ chenyu@hpclab.cs.tsinghua.edu.cn 清华大学计算机

* Defining these two gives us ioremap for free. See asm/io.h. * --gmcnutt */#define iomem_valid_addr(iomem,sz) (1)#define iomem_to_phys(iomem) (iomem)

/** needed for PCMCIA .... */

u8 __readb(void *addr);u16 __readw(void *addr);u32 __readl(void *addr);

#define readb(b) __readb(b)#define readw(b) __readw(b)#define readl(b) __readl(b)

void __writeb(u8 val, void *addr);void __writew(u16 val, void *addr);void __writel(u32 val, void *addr);

#define writeb(v,b) __writeb(v,b)#define writew(v,b) __writew(v,b)#define writel(v,b) __writel(v,b)

#endif

irq.h

/* * asm/arch-atmel/irq.h: * 2001 Erwin Authried */

#ifndef __ASM_ARCH_IRQ_H__#define __ASM_ARCH_IRQ_H__

#include <asm/hardware.h>#include <asm/io.h>

Page 70: SkyEye分析报告 - huihoo.org  · Web viewSkyEye分析报告. skyeye/ 陈渝. chenyu/ chenyu@hpclab.cs.tsinghua.edu.cn 清华大学计算机

#include <asm/mach/irq.h>#include <asm/arch/irqs.h>

#define fixup_irq(x) (x)

extern void at91_mask_irq(unsigned int irq);extern void at91_unmask_irq(unsigned int irq);extern void at91_mask_ack_irq(unsigned int irq);extern void at91_init_aic(void);

static __inline__ void irq_init_irq(void){

int irq;

at91_init_aic();

for (irq = 0; irq < NR_IRQS; irq++) {

if (!VALID_IRQ(irq)) continue;

irq_desc[irq].valid = 1;irq_desc[irq].probe_ok = 1;irq_desc[irq].mask_ack = at91_mask_ack_irq;irq_desc[irq].mask = at91_mask_irq;irq_desc[irq].unmask = at91_unmask_irq;

}}

#endif /* __ASM_ARCH_IRQ_H__ */

irqs.h

/* * asm/arch-p52/irqs.h: * 2001 Mindspeed */#ifndef __ASM_ARCH_IRQS_H__

Page 71: SkyEye分析报告 - huihoo.org  · Web viewSkyEye分析报告. skyeye/ 陈渝. chenyu/ chenyu@hpclab.cs.tsinghua.edu.cn 清华大学计算机

#define __ASM_ARCH_IRQS_H__

#ifdef CONFIG_CPU_AT91X40/* ******************* AT91x40xxx ******************** */

#define NR_IRQS 24#define VALID_IRQ(i) (i<=8 ||(i>=16 && i<NR_IRQS))

#define IRQ_FIQ 0#define IRQ_SWI 1#define IRQ_USART0 2#define IRQ_USART1 3#define IRQ_TC0 4#define IRQ_TC1 5#define IRQ_TC2 6#define IRQ_WD 7#define IRQ_PIOA 8

#define IRQ_EXT0 16#define IRQ_EXT1 17#define IRQ_EXT2 18

#elif CONFIG_CPU_AT91X63/* ******************* AT91x63xxx ******************** */

#define NR_IRQS 32#define VALID_IRQ(i) (i<=14 ||(i>=28 && i<NR_IRQS))

#define IRQ_FIQ 0#define IRQ_SWI 1#define IRQ_USART0 2#define IRQ_USART1 3#define IRQ_USART2 4#define IRQ_SP 5#define IRQ_TC0 6#define IRQ_TC1 7#define IRQ_TC2 8#define IRQ_TC3 9

Page 72: SkyEye分析报告 - huihoo.org  · Web viewSkyEye分析报告. skyeye/ 陈渝. chenyu/ chenyu@hpclab.cs.tsinghua.edu.cn 清华大学计算机

#define IRQ_TC4 10#define IRQ_TC5 11#define IRQ_WD 12#define IRQ_PIOA 13#define IRQ_PIOB 14

#define IRQ_EXT031#define IRQ_EXT130#define IRQ_EXT229#define IRQ_EXT328

#else #error "Configuration error: No CPU defined"#endif

#endif /* __ASM_ARCH_IRQS_H__ */

memory.h 感觉没用#ifndef __ASM_ARCH_MEMORY_H#define __ASM_ARCH_MEMORY_H

#include <asm/page.h>

#define TASK_SIZE (0x01a00000UL)#define TASK_SIZE_26 TASK_SIZE

#define PHYS_OFFSET(DRAM_BASE)#define PAGE_OFFSET PHYS_OFFSET#define END_MEM (DRAM_BASE + DRAM_SIZE)#endif

/* * linux/include/asm-arm/arch-p52/time.h * 2001 Mindspeed */

Page 73: SkyEye分析报告 - huihoo.org  · Web viewSkyEye分析报告. skyeye/ 陈渝. chenyu/ chenyu@hpclab.cs.tsinghua.edu.cn 清华大学计算机

time.h 应该重要初始化时钟#ifndef __ASM_ARCH_TIME_H__#define __ASM_ARCH_TIME_H__

#include <asm/uaccess.h>#include <asm/io.h>#include <asm/hardware.h>#include <asm/arch/timex.h>

extern struct irqaction timer_irq;

extern unsigned long atmel_gettimeoffset(void);extern void atmel_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs);

#if (KERNEL_TIMER==0)# define KERNEL_TIMER_IRQ_NUM IRQ_TC0#elif (KERNEL_TIMER==1)# define KERNEL_TIMER_IRQ_NUM IRQ_TC1#elif (KERNEL_TIMER==2)# define KERNEL_TIMER_IRQ_NUM IRQ_TC2#else#error Wierd -- KERNEL_TIMER is not defined or something....#endif

extern __inline__ void setup_timer (void) //真正初始化时钟的地方 { register volatile struct at91_timers* tt = (struct at91_timers*) (AT91_TC_BASE); register volatile struct at91_timer_channel* tc = &tt->chans[KERNEL_TIMER].ch; unsigned long v;

/* enable Kernel timer */HW_AT91_TIMER_INIT(KERNEL_TIMER) //X40这里是空操作

/* No SYNC */ tt->bcr = 0; /* program NO signal on XC1 */ v = tt->bmr;

v &= ~TCNXCNS(KERNEL_TIMER,3);v |= TCNXCNS(KERNEL_TIMER,1);

tt->bmr = v;

Page 74: SkyEye分析报告 - huihoo.org  · Web viewSkyEye分析报告. skyeye/ 陈渝. chenyu/ chenyu@hpclab.cs.tsinghua.edu.cn 清华大学计算机

tc->ccr = 2; /* disable the channel */

/* select ACLK/128 as inupt frequency for TC1 and enable CPCTRG */ tc->cmr = 3 | (1 << 14);

tc->idr = ~0ul; /* disable all interrupt */ tc->rc = ((ARM_CLK/128)/HZ - 1); /* load the count limit into the CR register */ tc->ier = TC_CPCS; /* enable CPCS interrupt */

/* enable the channel */ tc->ccr = TC_SWTRG|TC_CLKEN;

gettimeoffset = atmel_gettimeoffset; timer_irq.handler = atmel_timer_interrupt;

setup_arm_irq(KERNEL_TIMER_IRQ_NUM, &timer_irq);}

#endif /* __ASM_ARCH_TIME_H__ */

proc-armv/中的.h文件linux/asm-arm/proc-armv/assembler.h

/* * linux/asm-arm/proc-armv/assembler.h * * Copyright (C) 1996-2000 Russell King * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * This file contains ARM processor specifics for * the ARM6 and better processors. */#define MODE_USR USR_MODE#define MODE_FIQ FIQ_MODE#define MODE_IRQ IRQ_MODE

Page 75: SkyEye分析报告 - huihoo.org  · Web viewSkyEye分析报告. skyeye/ 陈渝. chenyu/ chenyu@hpclab.cs.tsinghua.edu.cn 清华大学计算机

#define MODE_SVC SVC_MODE

#define DEFAULT_FIQ MODE_FIQ

/* * LOADREGS - ldm with PC in register list (eg, ldmfd sp!, {pc}) */#ifdef __STDC__#define LOADREGS(cond, base, reglist...)\

ldm##cond base,reglist#else#define LOADREGS(cond, base, reglist...)\

ldm/**/cond base,reglist#endif

/* * Build a return instruction for this processor type. */#define RETINSTR(instr, regs...)\

instr regs

/* * Save the current IRQ state and disable IRQs. Note that this macro * assumes FIQs are enabled, and that the processor is in SVC mode. */

.macro save_and_disable_irqs, oldcpsr, tempmrs \oldcpsr, cpsrmov \temp, #I_BIT | MODE_SVCmsr cpsr_c, \temp.endm

/* * Restore interrupt state previously stored in a register. We don't * guarantee that this will preserve the flags. */

.macro restore_irqs, oldcpsrmsr cpsr_c, \oldcpsr.endm

/* * These two are used to save LR/restore PC over a user-based access. * The old 26-bit architecture requires that we do. On 32-bit * architecture, we can safely ignore this requirement. */

Page 76: SkyEye分析报告 - huihoo.org  · Web viewSkyEye分析报告. skyeye/ 陈渝. chenyu/ chenyu@hpclab.cs.tsinghua.edu.cn 清华大学计算机

.macro save_lr

.endm

.macro restore_pcmov pc, lr.endm

#define USER(x...) \9999: x; \

.section __ex_table,"a"; \

.align 3; \

.long 9999b,9001f; \

.previous

system.h 有用!Enable IRQ等的实现

/* * linux/include/asm-arm/proc-armv/system.h * * Copyright (C) 1996 Russell King * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */#ifndef __ASM_PROC_SYSTEM_H#define __ASM_PROC_SYSTEM_H

#include <linux/config.h>

#define set_cr(x) \__asm__ __volatile__( \"mcrp15, 0, %0, c1, c0 @ set CR" \: : "r" (x))

#define CR_M(1 << 0) /* MMU enable */#define CR_A (1 << 1) /* Alignment abort enable */

Page 77: SkyEye分析报告 - huihoo.org  · Web viewSkyEye分析报告. skyeye/ 陈渝. chenyu/ chenyu@hpclab.cs.tsinghua.edu.cn 清华大学计算机

#define CR_C (1 << 2) /* Dcache enable */#define CR_W (1 << 3) /* Write buffer enable */#define CR_P (1 << 4) /* 32-bit exception handler */#define CR_D (1 << 5) /* 32-bit data address range */#define CR_L (1 << 6) /* Implementation defined */#define CD_B (1 << 7) /* Big endian */#define CR_S (1 << 8) /* System MMU protection */#define CD_R (1 << 9) /* ROM MMU protection */#define CR_F (1 << 10) /* Implementation defined */#define CR_Z (1 << 11) /* Implementation defined */#define CR_I (1 << 12) /* Icache enable */#define CR_V (1 << 13) /* Vectors relocated to 0xffff0000 */#define CR_RR (1 << 14) /* Round Robin cache replacement */

extern unsigned long cr_no_alignment; /* defined in entry-armv.S */extern unsigned long cr_alignment; /* defined in entry-armv.S */

#ifdef __ARM_ARCH_4__#define vectors_base() ((cr_alignment & CR_V) ? 0xffff0000 : 0)#else#define vectors_base() (0)#endif

/* * A couple of speedups for the ARM */

/* * Save the current interrupt enable state & disable IRQs */#define __save_flags_cli(x) \

({ \unsigned long temp; \

__asm__ __volatile__( \"mrs%0, cpsr @ save_flags_cli\n" \

" orr %1, %0, #128\n" \" msr cpsr_c, %1" \

: "=r" (x), "=r" (temp) \: \: "memory"); \})

/* * Enable IRQs

Page 78: SkyEye分析报告 - huihoo.org  · Web viewSkyEye分析报告. skyeye/ 陈渝. chenyu/ chenyu@hpclab.cs.tsinghua.edu.cn 清华大学计算机

*/#define __sti() \

({ \unsigned long temp; \

__asm__ __volatile__( \"mrs%0, cpsr @ sti\n" \

" bic %0, %0, #128\n" \" msr cpsr_c, %0" \

: "=r" (temp) \: \: "memory"); \})

/* * Disable IRQs */#define __cli() \

({ \unsigned long temp; \

__asm__ __volatile__( \"mrs%0, cpsr @ cli\n" \

" orr %0, %0, #128\n" \" msr cpsr_c, %0" \

: "=r" (temp) \: \: "memory"); \})

/* * Enable FIQs */#define __stf() \

({ \unsigned long temp; \

__asm__ __volatile__( \"mrs%0, cpsr @ stf\n" \

" bic %0, %0, #64\n" \" msr cpsr_c, %0" \

: "=r" (temp) \: \: "memory"); \})

/*

Page 79: SkyEye分析报告 - huihoo.org  · Web viewSkyEye分析报告. skyeye/ 陈渝. chenyu/ chenyu@hpclab.cs.tsinghua.edu.cn 清华大学计算机

* Disable FIQs */#define __clf() \

({ \unsigned long temp; \

__asm__ __volatile__( \"mrs%0, cpsr @ clf\n" \

" orr %0, %0, #64\n" \" msr cpsr_c, %0" \

: "=r" (temp) \: \: "memory"); \})

/* * save current IRQ & FIQ state */#define __save_flags(x) \

__asm__ __volatile__( \"mrs%0, cpsr @ save_flags\n" \ : "=r" (x) \ : \ : "memory")

/* * restore saved IRQ & FIQ state */#define __restore_flags(x) \

__asm__ __volatile__( \"msrcpsr_c, %0 @ restore_flags\n" \: \: "r" (x) \: "memory")

#if defined(CONFIG_CPU_SA1100) || defined(CONFIG_CPU_SA110)/* * On the StrongARM, "swp" is terminally broken since it bypasses the * cache totally. This means that the cache becomes inconsistent, and, * since we use normal loads/stores as well, this is really bad. * Typically, this causes oopsen in filp_close, but could have other, * more disasterous effects. There are two work-arounds: * 1. Disable interrupts and emulate the atomic swap * 2. Clean the cache, perform atomic swap, flush the cache *

Page 80: SkyEye分析报告 - huihoo.org  · Web viewSkyEye分析报告. skyeye/ 陈渝. chenyu/ chenyu@hpclab.cs.tsinghua.edu.cn 清华大学计算机

* We choose (1) since its the "easiest" to achieve here and is not * dependent on the processor type. */#define swp_is_buggy#endif

extern __inline__ unsigned long __xchg(unsigned long x, volatile void *ptr, int size){

extern void __bad_xchg(volatile void *, int);unsigned long ret;

#ifdef swp_is_buggyunsigned long flags;

#endif

switch (size) {#ifdef swp_is_buggy

case 1:__save_flags_cli(flags);ret = *(volatile unsigned char *)ptr;*(volatile unsigned char *)ptr = x;__restore_flags(flags);break;

case 4:__save_flags_cli(flags);ret = *(volatile unsigned long *)ptr;*(volatile unsigned long *)ptr = x;__restore_flags(flags);break;

#elsecase 1: __asm__ __volatile__ ("swpb %0, %1, [%2]"

: "=r" (ret): "r" (x), "r" (ptr): "memory");

break;case 4: __asm__ __volatile__ ("swp %0, %1, [%2]"

: "=r" (ret): "r" (x), "r" (ptr): "memory");

break;#endif

default: __bad_xchg(ptr, size);}

Page 81: SkyEye分析报告 - huihoo.org  · Web viewSkyEye分析报告. skyeye/ 陈渝. chenyu/ chenyu@hpclab.cs.tsinghua.edu.cn 清华大学计算机

return ret;}

#endif

在 arch/armnommu/mach-atmel下的文件

time.c atmel_gettimeoffset atmel_timer_interrupt的实现

/* * time.c Timer functions for Atmel AT91 */

#include <linux/time.h>#include <linux/timex.h>#include <linux/types.h>#include <linux/sched.h>#include <asm/io.h>#include <asm/arch/hardware.h>

unsigned long atmel_gettimeoffset (void){

struct at91_timers* tt = (struct trio_timers*) (AT91_TC_BASE);struct at91_timer_channel* tc = &tt->chans[KERNEL_TIMER].ch;return tc->cv * (1000*1000)/(ARM_CLK/128);

}

void atmel_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs){

struct at91_timers* tt = (struct trio_timers*) (AT91_TC_BASE);volatile struct at91_timer_channel* tc = &tt->chans[KERNEL_TIMER].ch;unsigned long v = tc->sr;

do_timer(regs);}

Page 82: SkyEye分析报告 - huihoo.org  · Web viewSkyEye分析报告. skyeye/ 陈渝. chenyu/ chenyu@hpclab.cs.tsinghua.edu.cn 清华大学计算机

io.c

/* * linux/arch/armnommu/mach-atmel/io.c * * BRIEF MODULE DESCRIPTION * io functions */ #include <linux/kernel.h>#include <asm/io.h>

#define __MEM_OFF(x) ((u32)x + CONFIG_MEM8_BASE)

/* * read[bwl] and write[bwl] */u8 __readb(void *addr){ return __arch_getb(__MEM_OFF(addr));}

u16 __readw(void *addr){ return __arch_getw(__MEM_OFF(addr));}

u32 __readl(void *addr){ return __arch_getl(__MEM_OFF(addr));}

void __writeb(u8 val, void *addr){

__arch_putb(val, __MEM_OFF(addr));}

void __writew(u16 val, void *addr){

__arch_putw(val, __MEM_OFF(addr));}

Page 83: SkyEye分析报告 - huihoo.org  · Web viewSkyEye分析报告. skyeye/ 陈渝. chenyu/ chenyu@hpclab.cs.tsinghua.edu.cn 清华大学计算机

irq.c linux-2.4.x/arch/armnommu/mach-atmel at91_mask_irq

at91_unmask_irq at91_init_aic

/* * linux/arch/arm/mach-integrator/irq.c * */#include <linux/init.h>

#include <asm/mach/irq.h>#include <asm/hardware.h>#include <asm/io.h>#include <asm/irq.h>#include <asm/system.h>

extern struct irqdesc irq_desc[];

/* Internal Sources */#define LevelSensitive (0<<5)#define EdgeTriggered (1<<5)

/* External Sources */#define LowLevel (0<<5)#define NegativeEdge (1<<5)#define HighLevel (2<<5)#define PositiveEdge (3<<5)

static unsigned char eb01_irq_prtable[32] = { 7 << 5, /* FIQ */ 0 << 5, /* SWIRQ */ 0 << 5, /* US0IRQ */ 0 << 5, /* US1IRQ */ 1 << 5, /* TC0IRQ */ 1 << 5, /* TC1IRQ */ 1 << 5, /* TC2IRQ */ 0 << 5, /* WDIRQ */ 0 << 5, /* PIOAIRQ */ 0 << 5, /* reserved */ 0 << 5, /* reserved */

Page 84: SkyEye分析报告 - huihoo.org  · Web viewSkyEye分析报告. skyeye/ 陈渝. chenyu/ chenyu@hpclab.cs.tsinghua.edu.cn 清华大学计算机

0 << 5, /* reserved */ 0 << 5, /* reserved */ 0 << 5, /* reserved */ 0 << 5, /* reserved */ 0 << 5, /* reserved */ 1 << 5, /* IRQ0 */

0 << 5, /* IRQ1 */ 0 << 5, /* IRQ2 */};

static unsigned char eb01_irq_type[32] = { EdgeTriggered, EdgeTriggered, EdgeTriggered, EdgeTriggered, EdgeTriggered, EdgeTriggered, EdgeTriggered, EdgeTriggered, EdgeTriggered, EdgeTriggered, EdgeTriggered, EdgeTriggered, EdgeTriggered, EdgeTriggered, EdgeTriggered, EdgeTriggered,

EdgeTriggered, /* IRQ0 = neg. edge */ EdgeTriggered, EdgeTriggered, EdgeTriggered, EdgeTriggered, EdgeTriggered, EdgeTriggered, EdgeTriggered, EdgeTriggered, EdgeTriggered, EdgeTriggered, EdgeTriggered, EdgeTriggered, EdgeTriggered, EdgeTriggered, EdgeTriggered,

Page 85: SkyEye分析报告 - huihoo.org  · Web viewSkyEye分析报告. skyeye/ 陈渝. chenyu/ chenyu@hpclab.cs.tsinghua.edu.cn 清华大学计算机

};

void at91_mask_irq(unsigned int irq){

unsigned long mask = 1 << (irq);__arch_putl(mask, AIC_IDCR);

}

void at91_unmask_irq(unsigned int irq){

unsigned long mask = 1 << (irq);__arch_putl(mask, AIC_IECR);

}

void at91_mask_ack_irq(unsigned int irq){

at91_mask_irq(irq); __arch_putl(0, AIC_EOICR); /* value=don't care */}

void at91_init_aic() //真正初始化中断的地方{ int irqno;

/* Disable all interrupts */ __arch_putl(0xFFFFFFFF, AIC_IDCR);

/* Clear all interrupts */ __arch_putl(0xFFFFFFFF, AIC_ICCR);

for ( irqno = 0 ; irqno < 32 ; irqno++ ) { __arch_putl(irqno, AIC_EOICR); }

for ( irqno = 0 ; irqno < 32 ; irqno++ ) { __arch_putl((eb01_irq_prtable[irqno] >> 5) | eb01_irq_type[irqno],

AIC_SMR(irqno)); }}

Page 86: SkyEye分析报告 - huihoo.org  · Web viewSkyEye分析报告. skyeye/ 陈渝. chenyu/ chenyu@hpclab.cs.tsinghua.edu.cn 清华大学计算机

arch.c

/* * linux/arch/arm/mach-p52/arch.c * * Architecture specific fixups. This is where any * parameters in the params struct are fixed up, or * any additional architecture specific information * is pulled from the params struct. */#include <linux/tty.h>#include <linux/delay.h>#include <linux/pm.h>#include <linux/init.h>

#include <asm/elf.h>#include <asm/setup.h>#include <asm/mach-types.h>#include <asm/mach/arch.h>

extern void genarch_init_irq(void);

MACHINE_START(ATMEL, "EB01") MAINTAINER("Erwin Authried") INITIRQ(genarch_init_irq)MACHINE_END

其它关键文件

irq.c linux-2.4.x/arch/armnommu/kernel 包括 init_IRQ do_IRQ,

request_irq 等关键函数init_IRQ 初始化 irq

Page 87: SkyEye分析报告 - huihoo.org  · Web viewSkyEye分析报告. skyeye/ 陈渝. chenyu/ chenyu@hpclab.cs.tsinghua.edu.cn 清华大学计算机

do_IRQ /* * do_IRQ handles all normal device IRQ's */

request_irq/** * request_irq - allocate an interrupt line * @irq: Interrupt line to allocate * @handler: Function to be called when the IRQ occurs * @irqflags: Interrupt type flags * @devname: An ascii name for the claiming device * @dev_id: A cookie passed back to the handler function * * This call allocates interrupt resources and enables the * interrupt line and IRQ handling. From the point this * call is made your handler function may be invoked. Since * your handler function must clear any interrupt the board * raises, you must take care both to initialise your hardware * and to set up the interrupt handler in the right order. * * Dev_id must be globally unique. Normally the address of the * device data structure is used as the cookie. Since the handler * receives this value it makes sense to use it. * * If your interrupt is shared you must pass a non NULL dev_id * as this is required when freeing the interrupt. * * Flags: * * SA_SHIRQ Interrupt is shared * * SA_INTERRUPT Disable local interrupts while processing * * SA_SAMPLE_RANDOM The interrupt can be used for entropy *

初始化

/arch/armnommu/kernel/head-armv.S

#include <linux/config.h>

Page 88: SkyEye分析报告 - huihoo.org  · Web viewSkyEye分析报告. skyeye/ 陈渝. chenyu/ chenyu@hpclab.cs.tsinghua.edu.cn 清华大学计算机

#include <linux/linkage.h>#include <asm/assembler.h>#include <asm/mach-types.h>#include <asm/mach/arch.h>

#define K(a,b,c) ((a) << 24 | (b) << 12 | (c))

/* * Kernel startup entry point. * * The rules are: * r0 - should be 0 * r1 - unique architecture number * MMU - off * I-cache - on or off * D-cache - off * * See linux/arch/arm/tools/mach-types for the complete list of numbers * for r1. */

.section ".text.init",#alloc,#execinstr.typestext, #function

ENTRY(stext) //入口点mov r12, r0

mov r0, #F_BIT | I_BIT | MODE_SVC @ make sure svc mode 为 0xd3 或 211msr cpsr_c, r0 @ and all irqs disabled

#if defined(CONFIG_ARCH_ATMEL)

adr r5, LC0 ldmia r5, {r5, r6, r8, r9, sp} @ Setup stack

/* Copy data sections to their new home. */

/* Clear BSS */ mov r4, #01: cmp r5, r8 strcc r4, [r5],#4

Page 89: SkyEye分析报告 - huihoo.org  · Web viewSkyEye分析报告. skyeye/ 陈渝. chenyu/ chenyu@hpclab.cs.tsinghua.edu.cn 清华大学计算机

bcc 1b

/* Pretend we know what our processor code is (for arm_id) */ldr r2, L_AT91_SF_CIDR 即 ldr r2, =0x41000000ldr r2, [r2] @ read processor id

str r2, [r6]mov r2, #MACH_TYPE_ATMEL 0x59 89str r2, [r9]

mov fp, #0 fp=r11 b start_kernel //调用 init/main.c中的 start_kernel 函数 去了! LC0: .long __bss_start .long processor_id .long _end

.long __machine_arch_type .long init_task_union+8192#endif

bl __lookup_processor_typeteq r10, #0 @ invalid processor?moveq r0, #'p' @ yes, error 'p'beq __errorbl __lookup_architecture_typeteq r7, #0 @ invalid architecture?moveq r0, #'a' @ yes, error 'a'beq __error

adr lr, __ret @ return addressadd pc, r10, #12 @ initialise processor

@ (return control reg)

__switch_data: .long __mmap_switched.long SYMBOL_NAME(compat).long SYMBOL_NAME(__bss_start).long SYMBOL_NAME(_end).long SYMBOL_NAME(processor_id).long SYMBOL_NAME(__machine_arch_type).long SYMBOL_NAME(cr_alignment).long SYMBOL_NAME(init_task_union)+8192

__ret: ldr lr, __switch_data

Page 90: SkyEye分析报告 - huihoo.org  · Web viewSkyEye分析报告. skyeye/ 陈渝. chenyu/ chenyu@hpclab.cs.tsinghua.edu.cn 清华大学计算机

mov pc, lr

/* * This code follows on after the page * table switch and jump above. * * r0 = processor control register * r1 = machine ID * r9 = processor ID */.align 5

__mmap_switched:adr r3, __switch_data + 4ldmia r3, {r2, r4, r5, r6, r7, r8, sp}@ r2 = compat

@ sp = stack pointerstr r12, [r2]

mov fp, #0 @ Clear BSS (and zero fp)1: cmp r4, r5

strcc fp, [r4],#4bcc 1b

str r9, [r6] @ Save processor IDstr r1, [r7] @ Save machine type

#ifdef CONFIG_ALIGNMENT_TRAPorr r0, r0, #2 @ ...........A.

#endifbic r2, r0, #2 @ Clear 'A' bitstmia r8, {r0, r2} @ Save control register valuesb SYMBOL_NAME(start_kernel)

/* * Exception handling. Something went wrong and we can't * proceed. We ought to tell the user, but since we * don't have any guarantee that we're even running on * the right architecture, we do virtually nothing. * r0 = ascii error character: * a = invalid architecture * p = invalid processor * i = invalid calling convention * * Generally, only serious errors cause this.

Page 91: SkyEye分析报告 - huihoo.org  · Web viewSkyEye分析报告. skyeye/ 陈渝. chenyu/ chenyu@hpclab.cs.tsinghua.edu.cn 清华大学计算机

*/__error:1: mov r0, r0

b 1b

/* * Read processor ID register (CP#15, CR0), and look up in the linker-built * supported processor list. Note that we can't use the absolute addresses * for the __proc_info lists since we aren't running with the MMU on * (and therefore, we are not in the correct address space). We have to * calculate the offset. * * Returns: * r5, r6, r7 corrupted * r8 = page table flags * r9 = processor ID * r10 = pointer to processor structure */__lookup_processor_type:

adr r5, 2fldmia r5, {r7, r9, r10}sub r5, r5, r10 @ convert addressesadd r7, r7, r5 @ to our address spaceadd r10, r9, r5

#ifdef CONFIG_CPU_WITH_MCR_INSTRUCTIONmrc p15, 0, r9, c0, c0 @ get processor id

#else# warning "FIXME: Get Processor ID without MCR Instruction"

@ A possible code@ldr r9, PROCESSOR_ID_MEM_LOCATION@ldr r9, [r9]

#endif1: ldmia r10, {r5, r6, r8} @ value, mask, mmuflags

and r6, r6, r9 @ mask wanted bitsteq r5, r6moveq pc, lradd r10, r10, #36 @ sizeof(proc_info_list)cmp r10, r7blt 1bmov r10, #0 @ unknown processormov pc, lr

/*

Page 92: SkyEye分析报告 - huihoo.org  · Web viewSkyEye分析报告. skyeye/ 陈渝. chenyu/ chenyu@hpclab.cs.tsinghua.edu.cn 清华大学计算机

* Look in include/asm-arm/procinfo.h and arch/arm/kernel/arch.[ch] for * more information about the __proc_info and __arch_info structures. */2: .long __proc_info_end

.long __proc_info_begin

.long 2b

.long __arch_info_begin

.long __arch_info_end

/* * Lookup machine architecture in the linker-build list of architectures. * Note that we can't use the absolute addresses for the __arch_info * lists since we aren't running with the MMU on (and therefore, we are * not in the correct address space). We have to calculate the offset. * * r1 = machine architecture number * Returns: * r2, r3, r4 corrupted * r5 = physical start address of RAM * r6 = physical address of IO * r7 = byte offset into page tables for IO */__lookup_architecture_type:

adr r4, 2bldmia r4, {r2, r3, r5, r6, r7} @ throw away r2, r3sub r5, r4, r5 @ convert addressesadd r4, r6, r5 @ to our address spaceadd r7, r7, r5

1: ldr r5, [r4] @ get machine typeteq r5, r1beq 2fadd r4, r4, #SIZEOF_MACHINE_DESCcmp r4, r7blt 1bmov r7, #0 @ unknown architecturemov pc, lr

2: ldmib r4, {r5, r6, r7} @ found, get resultsmov r7, r7, lsr #18 @ pagetable byte offsetmov pc, lr

L_AT91_SF_CIDR: .long 0xfff00000

Page 93: SkyEye分析报告 - huihoo.org  · Web viewSkyEye分析报告. skyeye/ 陈渝. chenyu/ chenyu@hpclab.cs.tsinghua.edu.cn 清华大学计算机

Init/main.c中的 start_kernel

/* * Activate the first processor. */

asmlinkage void __init start_kernel(void){

char * command_line;unsigned long mempages;extern char saved_command_line[];

/* * Interrupts are still disabled. Do necessary setups, then * enable them */

lock_kernel();printk(linux_banner);setup_arch(&command_line);printk("Kernel command line: %s\n", saved_command_line);parse_options(command_line);trap_init();init_IRQ(); //会调用 irq_init_irq(void) -》at91_init_aic();sched_init();softirq_init();time_init(); //会调 setup_timer 真正初始化 at91时钟的地方。/* * HACK ALERT! This is early. We're enabling the console before * we've done PCI setups etc, and console_init() must be aware of * this. But we do want output early, in case something goes wrong. */console_init(); console_init () at tty_io.c:2170 -> atmel_console_init () at

serial_atmel.c:2133start_kernel->console_init->atmel_console_init()->register_console(&atmel_driver), 然 后 把buffer中的数据打印了出来。#ifdef CONFIG_MODULES

init_modules();#endif

if (prof_shift) {unsigned int size;

Page 94: SkyEye分析报告 - huihoo.org  · Web viewSkyEye分析报告. skyeye/ 陈渝. chenyu/ chenyu@hpclab.cs.tsinghua.edu.cn 清华大学计算机

/* only text is profiled */prof_len = (unsigned long) &_etext - (unsigned long) &_stext;prof_len >>= prof_shift;

size = prof_len * sizeof(unsigned int) + PAGE_SIZE-1;prof_buffer = (unsigned int *) alloc_bootmem(size);

}

kmem_cache_init();sti();calibrate_delay();

#ifdef CONFIG_BLK_DEV_INITRDif (initrd_start && !initrd_below_start_ok &&

initrd_start < min_low_pfn << PAGE_SHIFT) {printk(KERN_CRIT "initrd overwritten (0x%08lx < 0x%08lx) - " "disabling it.\n",initrd_start,min_low_pfn << PAGE_SHIFT);initrd_start = 0;

}#endif

mem_init();kmem_cache_sizes_init();pgtable_cache_init();

mempages = num_physpages;

fork_init(mempages);proc_caches_init();vfs_caches_init(mempages);buffer_init(mempages);page_cache_init(mempages);

#if defined(CONFIG_ARCH_S390)ccwcache_init();

#endifsignals_init();

#ifdef CONFIG_PROC_FSproc_root_init();

#endif#if defined(CONFIG_SYSVIPC)

ipc_init();#endif

check_bugs();printk("POSIX conformance testing by UNIFIX\n");

/*

Page 95: SkyEye分析报告 - huihoo.org  · Web viewSkyEye分析报告. skyeye/ 陈渝. chenyu/ chenyu@hpclab.cs.tsinghua.edu.cn 清华大学计算机

* We count on the initial thread going ok * Like idlers init is an unlocked kernel thread, which will * make syscalls (and thus be locked). */smp_init();rest_init();

}

网络设备初始化 linux-2.4.x/driver/net/space.c net_init.c

space.c/* * Unified ethernet device probe, segmented per architecture and * per bus interface. This drives the legacy devices only for now. */ static int __init ethif_probe(struct net_device *dev)

net_init.cregister_netdevunregister_netdev

不过我认为比较复杂,想直接在 at91的 setup_timer执行 setup_net就可以了。但这个方法比较土。有什么更好的方法?driver

serial 方面

AT91_USART0_BASE AT91_USART1_BASE console_print_atmel HW_AT91_USART_INIT

serial-atmel.h

/* serial-atmel.h: Definitions for the Atmel serial driver.

Page 96: SkyEye分析报告 - huihoo.org  · Web viewSkyEye分析报告. skyeye/ 陈渝. chenyu/ chenyu@hpclab.cs.tsinghua.edu.cn 清华大学计算机

* * Copyright (C) 1998 Kenneth Albanowski <[email protected]>, * D. Jeff Dionne <[email protected]>, * The Silver Hammer Group, Ltd. * * Based on: * * drivers/char/68328serial.h * * Copyright (C) 1995 David S. Miller ([email protected]) */

#ifndef _ATMEL_SERIAL_H#define _ATMEL_SERIAL_H

#include <linux/config.h>#include <asm/page.h>#include <asm/arch/hardware.h>

/* * For the close wait times, 0 means wait forever for serial port to * flush its output. 65535 means don't wait at all. */#define S_CLOSING_WAIT_INF 0#define S_CLOSING_WAIT_NONE 65535

/* * Definitions for S_struct (and serial_struct) flags field */#define S_HUP_NOTIFY 0x0001 /* Notify getty on hangups and closes

on the callout port */#define S_FOURPORT 0x0002 /* Set OU1, OUT2 per AST Fourport settings */#define S_SAK 0x0004 /* Secure Attention Key (Orange book) */#define S_SPLIT_TERMIOS 0x0008 /* Separate termios for dialin/callout */

#define S_SPD_MASK 0x0030#define S_SPD_HI 0x0010 /* Use 56000 instead of 38400 bps */

#define S_SPD_VHI 0x0020 /* Use 115200 instead of 38400 bps */#define S_SPD_CUST 0x0030 /* Use user-specified divisor */

#define S_SKIP_TEST 0x0040 /* Skip UART test during autoconfiguration */#define S_AUTO_IRQ 0x0080 /* Do automatic IRQ during autoconfiguration */#define S_SESSION_LOCKOUT 0x0100 /* Lock out cua opens based on session

Page 97: SkyEye分析报告 - huihoo.org  · Web viewSkyEye分析报告. skyeye/ 陈渝. chenyu/ chenyu@hpclab.cs.tsinghua.edu.cn 清华大学计算机

*/#define S_PGRP_LOCKOUT 0x0200 /* Lock out cua opens based on pgrp */#define S_CALLOUT_NOHUP 0x0400 /* Don't do hangups for cua device */

#define S_FLAGS 0x0FFF /* Possible legal S flags */#define S_USR_MASK 0x0430 /* Legal flags that non-privileged

* users can set or reset */

/* Internal flags used only by kernel/chr_drv/serial.c */#define S_INITIALIZED 0x80000000 /* Serial port was initialized */#define S_CALLOUT_ACTIVE 0x40000000 /* Call out device is active */#define S_NORMAL_ACTIVE 0x20000000 /* Normal device is active */#define S_BOOT_AUTOCONF 0x10000000 /* Autoconfigure port on bootup */#define S_CLOSING 0x08000000 /* Serial port is closing */#define S_CTS_FLOW 0x04000000 /* Do CTS flow control */#define S_CHECK_CD 0x02000000 /* i.e., CLOCAL */

#define RS_EVENT_WRITE_WAKEUP 0#define SERIAL_MAGIC 0x5301

/* Software state per channel */

/* * This is our internal structure for each serial port's state. * * Many fields are paralleled by the structure used by the serial_struct * structure. * * For definitions of the flags field, see tty.h */

struct atmel_serial {char soft_carrier; /* Use soft carrier on this channel */char break_abort; /* Is serial console in, so process brk/abrt */

#if 0char cons_keyb; /* Channel runs the keyboard */char cons_mouse; /* Channel runs the mouse */char kgdb_channel; /* Kgdb is running on this channel */

#endifchar is_cons; /* Is this our console. */

/* We need to know the current clock divisor * to read the bps rate the chip has currently

Page 98: SkyEye分析报告 - huihoo.org  · Web viewSkyEye分析报告. skyeye/ 陈渝. chenyu/ chenyu@hpclab.cs.tsinghua.edu.cn 清华大学计算机

* loaded. */unsigned char clk_divisor; /* May be 1, 16, 32, or 64 */int baud;int magic;int baud_base;int port;int irq;int irqmask;int flags; /* defined in tty.h */int type; /* UART type */int use_ints;volatile struct atmel_usart_regs *usart;int cts_state;struct tty_struct *tty;int read_status_mask;int ignore_status_mask;int timeout;int xmit_fifo_size;int custom_divisor;int x_char; /* xon/xoff character */int close_delay;unsigned short closing_wait;unsigned short closing_wait2;unsigned long event;unsigned long last_active;int line;int count; /* # of fd on device */int blocked_open; /* # of blocked opens */long session; /* Session of opening process */long pgrp; /* pgrp of opening process */unsigned char *xmit_buf;unsigned char *rx_buf;int xmit_head;int xmit_tail;int xmit_cnt;struct tq_struct tqueue;struct tq_struct tqueue_hangup;struct termios normal_termios;struct termios callout_termios;wait_queue_head_t open_wait;wait_queue_head_t close_wait;

};

Page 99: SkyEye分析报告 - huihoo.org  · Web viewSkyEye分析报告. skyeye/ 陈渝. chenyu/ chenyu@hpclab.cs.tsinghua.edu.cn 清华大学计算机

#endif /* !(_MC683XX_SERIAL_H) */

serial_atmel.c

: atmel_console_init ()at 2133start_kernel->console_init->atmel_console_init()->register_console(&atmel_driver),然后把 buffer中的数据打印了出来。c代码/* serial port driver for the Atmel AT91 series builtin USARTs * * Copyright (C) 2000, 2001 Erik Andersen <[email protected]> * * Based on: * drivers/char/68302serial.c * and also based on trioserial.c from Aplio, though this driver * has been extensively changed since then. No author was * listed in trioserial.c. */

/* Enable this to force this driver to always operate at 57600 */#undef FORCE_57600

#include <linux/config.h>#include <linux/version.h>#include <linux/types.h>#include <linux/serial.h>#include <linux/errno.h>#include <linux/signal.h>#include <linux/sched.h>#include <linux/timer.h>#include <linux/interrupt.h>#include <linux/tty.h>#include <linux/tty_flip.h>#include <linux/config.h>#include <linux/major.h>#include <linux/string.h>#include <linux/fcntl.h>#include <linux/mm.h>#include <linux/kernel.h>#include <linux/init.h>

Page 100: SkyEye分析报告 - huihoo.org  · Web viewSkyEye分析报告. skyeye/ 陈渝. chenyu/ chenyu@hpclab.cs.tsinghua.edu.cn 清华大学计算机

#include <linux/console.h>

#include <asm/io.h>#include <asm/irq.h>#include <asm/arch/irq.h>#include <asm/system.h>#include <asm/segment.h>#include <asm/bitops.h>#include <asm/delay.h>#include <asm/uaccess.h>#include "serial_atmel.h"

#define USE_INTS 1#define UART_CLOCK (ARM_CLK/16)

#define SERIAL_XMIT_SIZE PAGE_SIZE#define RX_SERIAL_SIZE 256

/* serial subtype definitions */#define SERIAL_TYPE_NORMAL 1#define SERIAL_TYPE_CALLOUT 2

/* number of characters left in xmit buffer before we ask for more */#define WAKEUP_CHARS 256

/* Debugging... DEBUG_INTR is bad to use when one of the zs * lines is your console ;( */#undef SERIAL_DEBUG_INTR#undef SERIAL_DEBUG_OPEN#undef SERIAL_DEBUG_FLOW

#define RS_ISR_PASS_LIMIT 256

#define _INLINE_

#ifndef MIN#define MIN(a,b) ((a) < (b) ? (a) : (b))#endif

static volatile struct atmel_usart_regs *usarts[AT91_USART_CNT] = {(volatile struct atmel_usart_regs *) AT91_USART0_BASE,(volatile struct atmel_usart_regs *) AT91_USART1_BASE

Page 101: SkyEye分析报告 - huihoo.org  · Web viewSkyEye分析报告. skyeye/ 陈渝. chenyu/ chenyu@hpclab.cs.tsinghua.edu.cn 清华大学计算机

};static struct atmel_serial atmel_info[AT91_USART_CNT];

/* * tmp_buf is used as a temporary buffer by serial_write. We need to * lock it in case the memcpy_fromfs blocks while swapping in a page, * and some other program tries to do a serial write at the same time. * Since the lock will only come under contention when the system is * swapping and available memory is low, it makes sense to share one * buffer across all the serial ports, since it significantly saves * memory if large numbers of serial ports are open. */static unsigned char tmp_buf[SERIAL_XMIT_SIZE]; /* This is cheating */DECLARE_MUTEX(tmp_buf_sem);

static unsigned char * rx_buf_table[AT91_USART_CNT];

static unsigned char rx_buf1[RX_SERIAL_SIZE];static unsigned char rx_buf2[RX_SERIAL_SIZE];

/* Console hooks... */struct atmel_serial *atmel_consinfo = 0;

DECLARE_TASK_QUEUE(tq_atmel_serial);

static struct tq_struct serialpoll;static struct tty_driver serial_driver, callout_driver;static int serial_refcount;

static void serpoll(void *data);

static void change_speed(struct atmel_serial *info);

static struct tty_struct *serial_table[AT91_USART_CNT];static struct termios *serial_termios[AT91_USART_CNT];static struct termios *serial_termios_locked[AT91_USART_CNT];

static char prompt0;static void xmit_char(struct atmel_serial *info, char ch);static void xmit_string(struct atmel_serial *info, char *p, int len);static void start_rx(struct atmel_serial *info);static void wait_EOT(volatile struct atmel_usart_regs *);static void uart_init(struct atmel_serial *info);static void uart_speed(struct atmel_serial *info, unsigned cflag);

Page 102: SkyEye分析报告 - huihoo.org  · Web viewSkyEye分析报告. skyeye/ 陈渝. chenyu/ chenyu@hpclab.cs.tsinghua.edu.cn 清华大学计算机

static void tx_enable(volatile struct atmel_usart_regs *uart);static void rx_enable(volatile struct atmel_usart_regs *uart);static void tx_disable(volatile struct atmel_usart_regs *uart);static void rx_disable(volatile struct atmel_usart_regs *uart);static void tx_stop(volatile struct atmel_usart_regs *uart);static void tx_start(volatile struct atmel_usart_regs *uart, int ints);static void rx_stop(volatile struct atmel_usart_regs *uart);static void rx_start(volatile struct atmel_usart_regs *uart, int ints);static void set_ints_mode(int yes, struct atmel_serial *info);static void rs_interrupt(struct atmel_serial *info);extern void show_net_buffers(void);extern void hard_reset_now(void);static void handle_termios_tcsets(struct termios * ptermios, struct atmel_serial * ptty);

static int global;

static void coucou1(void){

global = 0;}

static void coucou2(void){

global = 1;}static void _INLINE_ tx_enable(volatile struct atmel_usart_regs *uart){

uart->ier = US_TXEMPTY;}static void _INLINE_ rx_enable(volatile struct atmel_usart_regs *uart){

uart->ier = US_ENDRX | US_TIMEOUT;}static void _INLINE_ tx_disable(volatile struct atmel_usart_regs *uart){

uart->idr = US_TXEMPTY;}static void _INLINE_ rx_disable(volatile struct atmel_usart_regs *uart){

uart->idr = US_ENDRX | US_TIMEOUT;}static void _INLINE_ tx_stop(volatile struct atmel_usart_regs *uart)

Page 103: SkyEye分析报告 - huihoo.org  · Web viewSkyEye分析报告. skyeye/ 陈渝. chenyu/ chenyu@hpclab.cs.tsinghua.edu.cn 清华大学计算机

{tx_disable(uart);uart->tcr = 0;uart->cr = US_TXDIS;

}static void _INLINE_ tx_start(volatile struct atmel_usart_regs *uart, int ints){

if (ints) {tx_enable(uart);

}uart->cr = US_TXEN;

}static void _INLINE_ rx_stop(volatile struct atmel_usart_regs *uart){

rx_disable(uart);uart->rtor = 0;uart->rcr = 0;uart->cr = US_RXDIS;

}static void _INLINE_ rx_start(volatile struct atmel_usart_regs *uart, int ints){

uart->cr = US_RXEN | US_STTO;uart->rtor = 20;if (ints) {

rx_enable(uart);}

}static void _INLINE_ reset_status(volatile struct atmel_usart_regs *uart){

uart->cr = US_RSTSTA;}static void set_ints_mode(int yes, struct atmel_serial *info){

info->use_ints = yes;// FIXME: check#if 0

(yes) ? unmask_irq(info->irq) : mask_irq(info->irq);#endif}

#ifdef US_RTS 好像没用static void atmel_cts_off(struct atmel_serial *info){

volatile struct atmel_usart_regs *uart;

Page 104: SkyEye分析报告 - huihoo.org  · Web viewSkyEye分析报告. skyeye/ 陈渝. chenyu/ chenyu@hpclab.cs.tsinghua.edu.cn 清华大学计算机

uart = info->usart;uart->mc &= ~(unsigned long) US_RTS;info->cts_state = 0;

}static void atmel_cts_on(struct atmel_serial *info){

volatile struct atmel_usart_regs *uart;

uart = info->usart;uart->mc |= US_RTS;info->cts_state = 1;

}/* Sets or clears DTR/RTS on the requested line */static inline void atmel_rtsdtr(struct atmel_serial *ss, int set){ volatile struct atmel_usart_regs *uart;

uart = ss->usart; if (set) { uart->mc |= US_DTR | US_RTS; } else { uart->mc &= ~(unsigned long) (US_DTR | US_RTS); } return;}#endif /* US_RTS */

static inline int serial_paranoia_check(struct atmel_serial *info,dev_t device, const char *routine)

{#ifdef SERIAL_PARANOIA_CHECK

static const char *badmagic ="Warning: bad magic number for serial struct (%d, %d) in %s\n";

static const char *badinfo ="Warning: null atmel_serial struct for (%d, %d) in %s\n";

if (!info) {printk(badinfo, MAJOR(device), MINOR(device), routine);return 1;

}if (info->magic != SERIAL_MAGIC) {

printk(badmagic, MAJOR(device), MINOR(device), routine);return 1;

Page 105: SkyEye分析报告 - huihoo.org  · Web viewSkyEye分析报告. skyeye/ 陈渝. chenyu/ chenyu@hpclab.cs.tsinghua.edu.cn 清华大学计算机

}#endif

return 0;}

/* * ------------------------------------------------------------ * rs_stop() and rs_start() * * This routines are called before setting or resetting tty->stopped. * They enable or disable transmitter interrupts, as necessary. * ------------------------------------------------------------ */static void rs_stop(struct tty_struct *tty){

struct atmel_serial *info = (struct atmel_serial *) tty->driver_data;unsigned long flags;

if (serial_paranoia_check(info, tty->device, "rs_stop"))return;

save_flags(flags);cli();tx_stop(info->usart);rx_stop(info->usart);restore_flags(flags);

}

static void rs_put_char(struct atmel_serial *info, char ch){

int flags = 0;

save_flags(flags);cli();xmit_char(info, ch);wait_EOT(info->usart);restore_flags(flags);

}

static void rs_start(struct tty_struct *tty){

struct atmel_serial *info = (struct atmel_serial *) tty->driver_data;unsigned long flags;

Page 106: SkyEye分析报告 - huihoo.org  · Web viewSkyEye分析报告. skyeye/ 陈渝. chenyu/ chenyu@hpclab.cs.tsinghua.edu.cn 清华大学计算机

if (serial_paranoia_check(info, tty->device, "rs_start"))return;

save_flags(flags);cli();tx_start(info->usart, info->use_ints);rx_start(info->usart, info->use_ints);/* FIXME */

// start_rx(info);restore_flags(flags);

}

/* Drop into either the boot monitor or kadb upon receiving a break * from keyboard/console input. */static void batten_down_hatches(void){#if 0

/* If we are doing kadb, we call the debugger * else we just drop into the boot monitor. * Note that we must flush the user windows * first before giving up control. */if ((((unsigned long) linux_dbvec) >= DEBUG_FIRSTVADDR) &&

(((unsigned long) linux_dbvec) <= DEBUG_LASTVADDR))sp_enter_debugger();

elsepanic("atmel_serial: batten_down_hatches");

return;#endif}

/* * ---------------------------------------------------------------------- * * Here starts the interrupt handling routines. All of the following * subroutines are declared as inline and are folded into * rs_interrupt(). They were separated out for readability's sake. * * Note: rs_interrupt() is a "fast" interrupt, which means that it * runs with interrupts turned off. People who may want to modify * rs_interrupt() should try to keep the interrupt handler as fast as * possible. After you are done making modifications, it is not a bad * idea to do:

Page 107: SkyEye分析报告 - huihoo.org  · Web viewSkyEye分析报告. skyeye/ 陈渝. chenyu/ chenyu@hpclab.cs.tsinghua.edu.cn 清华大学计算机

* * gcc -S -DKERNEL -Wall -Wstrict-prototypes -O6 -fomit-frame-pointer serial.c * * and look at the resulting assembly code in serial.s. * * - Ted Ts'o ([email protected]), 7-Mar-93 * ----------------------------------------------------------------------- */

/* * This routine is used by the interrupt handler to schedule * processing in the software interrupt portion of the driver. */static _INLINE_ void rs_sched_event(struct atmel_serial *info, int event){

info->event |= 1 << event;queue_task(&info->tqueue, &tq_atmel_serial);mark_bh(SERIAL_BH);

}

extern void breakpoint(void); /* For the KGDB frame character */

static _INLINE_ void receive_chars(struct atmel_serial *info, unsigned long status){// unsigned char ch; FIXME

int count;volatile struct atmel_usart_regs *uart = info->usart;

#if 0// hack to receive chars by polling from anywherestruct atmel_serial *info1 = &atmel_info;struct tty_struct *tty = info1->tty;

if (!(info->flags & S_INITIALIZED))return;

#elsestruct tty_struct *tty = info->tty;

if (!(info->flags & S_INITIALIZED))return;

#endifcount = RX_SERIAL_SIZE - uart->rcr;// hack to receive chars by polling only BD fields

Page 108: SkyEye分析报告 - huihoo.org  · Web viewSkyEye分析报告. skyeye/ 陈渝. chenyu/ chenyu@hpclab.cs.tsinghua.edu.cn 清华大学计算机

if (!count) {return;

}#if 0

ch = info->rx_buf[0];if (info->is_cons) {

if (status & US_RXBRK) { /* whee, break received */batten_down_hatches();/*rs_recv_clear(info->atmel_channel); */return;

} else if (ch == 0x10) {/* ^P */show_state();show_free_areas();show_buffers();show_net_buffers();return;

} else if (ch == 0x12) {/* ^R */hard_reset_now();return;

}/* It is a 'keyboard interrupt' ;-) */wake_up(&keypress_wait);

}#endif

#if 0/* Look for kgdb 'stop' character, consult the gdb documentation * for remote target debugging and arch/sparc/kernel/sparc-stub.c * to see how all this works. */if((info->kgdb_channel) && (ch =='\003')) { breakpoint(); goto clear_and_exit;}

#endif

if (!tty)goto clear_and_exit;

if (tty->flip.count >= TTY_FLIPBUF_SIZE)queue_task(&tty->flip.tqueue, &tq_timer);

if ((count + tty->flip.count) >= TTY_FLIPBUF_SIZE) {#ifdef US_RTS

Page 109: SkyEye分析报告 - huihoo.org  · Web viewSkyEye分析报告. skyeye/ 陈渝. chenyu/ chenyu@hpclab.cs.tsinghua.edu.cn 清华大学计算机

atmel_cts_off(info);#endif

serialpoll.data = (void *) info;queue_task(&serialpoll, &tq_timer);

}memset(tty->flip.flag_buf_ptr, 0, count);memcpy(tty->flip.char_buf_ptr, info->rx_buf, count);tty->flip.char_buf_ptr += count;

if (status & US_PARE)*(tty->flip.flag_buf_ptr - 1) = TTY_PARITY;

else if (status & US_OVRE)*(tty->flip.flag_buf_ptr - 1) = TTY_OVERRUN;

else if (status & US_FRAME)*(tty->flip.flag_buf_ptr - 1) = TTY_FRAME;

tty->flip.count += count;

queue_task(&tty->flip.tqueue, &tq_timer);

clear_and_exit:start_rx(info);return;

}

static _INLINE_ void transmit_chars(struct atmel_serial *info){

if (info->x_char) {/* Send next char */xmit_char(info, info->x_char);info->x_char = 0;goto clear_and_return;

}

if ((info->xmit_cnt <= 0) || info->tty->stopped) {/* That's peculiar... */tx_stop(info->usart);goto clear_and_return;

}

if (info->xmit_tail + info->xmit_cnt < SERIAL_XMIT_SIZE) {xmit_string(info, info->xmit_buf + info->xmit_tail,

info->xmit_cnt);info->xmit_tail =

Page 110: SkyEye分析报告 - huihoo.org  · Web viewSkyEye分析报告. skyeye/ 陈渝. chenyu/ chenyu@hpclab.cs.tsinghua.edu.cn 清华大学计算机

(info->xmit_tail + info->xmit_cnt) & (SERIAL_XMIT_SIZE - 1);info->xmit_cnt = 0;

} else {coucou1();xmit_string(info, info->xmit_buf + info->xmit_tail,

SERIAL_XMIT_SIZE - info->xmit_tail);//xmit_string(info, info->xmit_buf, info->xmit_tail + info->xmit_cnt -

SERIAL_XMIT_SIZE);info->xmit_cnt =

info->xmit_cnt - (SERIAL_XMIT_SIZE - info->xmit_tail);info->xmit_tail = 0;

}

#if 0/* Send char */xmit_char(info, info->xmit_buf[info->xmit_tail++]);info->xmit_tail = info->xmit_tail & (SERIAL_XMIT_SIZE - 1);info->xmit_cnt--;

#endif

if (info->xmit_cnt < WAKEUP_CHARS)rs_sched_event(info, RS_EVENT_WRITE_WAKEUP);

if (info->xmit_cnt <= 0) {//tx_stop(info->usart);goto clear_and_return;

}

clear_and_return:/* Clear interrupt (should be auto) */return;

}

static _INLINE_ void status_handle(struct atmel_serial *info, unsigned long status){#if 0

if (status & DCD) {if ((info->tty->termios->c_cflag & CRTSCTS) &&

((info->curregs[3] & AUTO_ENAB) == 0)) {info->curregs[3] |= AUTO_ENAB;info->pendregs[3] |= AUTO_ENAB;write_zsreg(info->atmel_channel, 3, info->curregs[3]);

}

Page 111: SkyEye分析报告 - huihoo.org  · Web viewSkyEye分析报告. skyeye/ 陈渝. chenyu/ chenyu@hpclab.cs.tsinghua.edu.cn 清华大学计算机

} else {if ((info->curregs[3] & AUTO_ENAB)) {

info->curregs[3] &= ~AUTO_ENAB;info->pendregs[3] &= ~AUTO_ENAB;write_zsreg(info->atmel_channel, 3, info->curregs[3]);

}}

#endif/* Whee, if this is console input and this is a * 'break asserted' status change interrupt, call * the boot prom. */if ((status & US_RXBRK) && info->break_abort)

batten_down_hatches();

/* XXX Whee, put in a buffer somewhere, the status information * XXX whee whee whee... Where does the information go... */reset_status(info->usart);return;

}

/* * This is the serial driver's generic interrupt routine */static void rs_interrupta(int irq, void *dev_id, struct pt_regs *regs){

rs_interrupt(&atmel_info[0]);}static void rs_interruptb(int irq, void *dev_id, struct pt_regs *regs){

rs_interrupt(&atmel_info[1]);}static void rs_interrupt(struct atmel_serial *info){

unsigned long status;

status = info->usart->csr;if (status & (US_ENDRX | US_TIMEOUT)) {

receive_chars(info, status);}if (status & (US_TXEMPTY)) {

transmit_chars(info);

Page 112: SkyEye分析报告 - huihoo.org  · Web viewSkyEye分析报告. skyeye/ 陈渝. chenyu/ chenyu@hpclab.cs.tsinghua.edu.cn 清华大学计算机

}status_handle(info, status);

#ifdef US_RTSif (!info->cts_state) {

if (info->tty->flip.count < TTY_FLIPBUF_SIZE - RX_SERIAL_SIZE) {atmel_cts_on(info);

}}

#endifif (!info->use_ints) {

serialpoll.data = (void *) info;queue_task(&serialpoll, &tq_timer);

}return;

}static void serpoll(void *data){

struct atmel_serial *info = data;

rs_interrupt(info);}

/* * ------------------------------------------------------------------- * Here ends the serial interrupt routines. * ------------------------------------------------------------------- */

/* * This routine is used to handle the "bottom half" processing for the * serial driver, known also the "software interrupt" processing. * This processing is done at the kernel interrupt level, after the * rs_interrupt() has returned, BUT WITH INTERRUPTS TURNED ON. This * is where time-consuming activities which can not be done in the * interrupt driver proper are done; the interrupt driver schedules * them using rs_sched_event(), and they get done here. */static void do_serial_bh(void){

run_task_queue(&tq_atmel_serial);}

static void do_softint(void *private_)

Page 113: SkyEye分析报告 - huihoo.org  · Web viewSkyEye分析报告. skyeye/ 陈渝. chenyu/ chenyu@hpclab.cs.tsinghua.edu.cn 清华大学计算机

{struct atmel_serial *info = (struct atmel_serial *) private_;struct tty_struct *tty;

tty = info->tty;if (!tty)

return;#if 0 // FIXME - CHECK

if (clear_bit(RS_EVENT_WRITE_WAKEUP, &info->event)) {if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&

tty->ldisc.write_wakeup) (tty->ldisc.write_wakeup) (tty);wake_up_interruptible(&tty->write_wait);

}#endif}

/* * This routine is called from the scheduler tqueue when the interrupt * routine has signalled that a hangup has occurred. The path of * hangup processing is: * * serial interrupt routine -> (scheduler tqueue) -> * do_serial_hangup() -> tty->hangup() -> rs_hangup() * */static void do_serial_hangup(void *private_){

struct atmel_serial *info = (struct atmel_serial *) private_;struct tty_struct *tty;

tty = info->tty;if (!tty)

return;

tty_hangup(tty);}

/* * This subroutine is called when the RS_TIMER goes off. It is used * by the serial driver to handle ports that do not have an interrupt * (irq=0). This doesn't work at all for 16450's, as a sun has a Z8530. */#if 0

Page 114: SkyEye分析报告 - huihoo.org  · Web viewSkyEye分析报告. skyeye/ 陈渝. chenyu/ chenyu@hpclab.cs.tsinghua.edu.cn 清华大学计算机

static void rs_timer(void){

panic("rs_timer called\n");return;

}#endif

static unsigned long calcCD(unsigned long br){

return (UART_CLOCK / br);}

static void uart_init(struct atmel_serial *info){

volatile struct atmel_usart_regs *uart;

if (info) {uart = info->usart;

} else {uart = usarts[0];

}

/* Reset the USART */uart->cr = US_TXDIS | US_RXDIS | US_RSTTX | US_RSTRX;/* clear Rx receive and Tx sent counters */uart->rcr = 0;uart->tcr = 0;

/* Disable interrups till we say we want them */tx_disable(info->usart);rx_disable(info->usart);

/* Set the serial port into a safe sane state */uart->mr = US_USCLKS(0) | US_CLK0 | US_CHMODE(0) | US_NBSTOP(0) |

US_PAR(4) | US_CHRL(3);

#ifndef FORCE_57600uart->brgr = calcCD(9600);

#elseuart->brgr = calcCD(57600);

#endif

uart->rtor = 20; // timeout = value * 4 *bit perioduart->ttgr = 0; // no guard time

Page 115: SkyEye分析报告 - huihoo.org  · Web viewSkyEye分析报告. skyeye/ 陈渝. chenyu/ chenyu@hpclab.cs.tsinghua.edu.cn 清华大学计算机

uart->rcr = 0;uart->rpr = 0;uart->tcr = 0;uart->tpr = 0;

#ifdef US_RTSuart->mc = 0;

#endif}

/* It is the responsibilty of whoever calls this function to be sure * that that have called * tx_stop(uart); rx_stop(uart); * before calling the function. Failure to do this will cause messy * things to happen. You have been warned. */static void uart_speed(struct atmel_serial *info, unsigned cflag){

unsigned baud = info->baud;volatile struct atmel_usart_regs *uart = info->usart;

// disable tx and rxuart->cr = US_TXDIS | US_RXDIS;

// disable interruptstx_disable(uart);rx_disable(uart);

#ifndef FORCE_57600uart->brgr = calcCD(baud);

#elseuart->brgr = calcCD(57600);

#endif/* FIXME */#if 0

/* probably not needed */uart->US_RTOR = 20; // timeout = value * 4 *bit perioduart->US_TTGR = 0; // no guard timeuart->US_RPR = 0;uart->US_RCR = 0;uart->US_TPR = 0;uart->US_TCR = 0;

#endif

/* FIXME */

Page 116: SkyEye分析报告 - huihoo.org  · Web viewSkyEye分析报告. skyeye/ 陈渝. chenyu/ chenyu@hpclab.cs.tsinghua.edu.cn 清华大学计算机

#if 0uart->mc = 0;if (cflag != 0xffff) {

uart->mr = US_USCLKS(0) | US_CLK0 | US_CHMODE(0) | US_NBSTOP(0) |

US_PAR(0);

if ((cflag & CSIZE) == CS8)uart->mr |= US_CHRL(3); // 8 bit char

elseuart->mr |= US_CHRL(2); // 7 bit char

if (cflag & CSTOPB)uart->mr |= US_NBSTOP(2); // 2 stop bits

if (!(cflag & PARENB))uart->mr |= US_PAR(4);// parity disabled

else if (cflag & PARODD)uart->mr |= US_PAR(1);// odd parity

}#endif

/* FIXME */#if 0

// enable tx and rxuart->cr = US_TXEN | US_RXEN;

// enable interruptstx_enable();rx_enable();

#endiftx_start(uart, info->use_ints);start_rx(info);

}

static void wait_EOT(volatile struct atmel_usart_regs *uart){

// make sure tx is enableduart->cr = US_TXEN;

// wait until all chars sent FIXME - is this sane ?while (1) {

if (uart->csr & US_TXEMPTY)break;

Page 117: SkyEye分析报告 - huihoo.org  · Web viewSkyEye分析报告. skyeye/ 陈渝. chenyu/ chenyu@hpclab.cs.tsinghua.edu.cn 清华大学计算机

}}static int startup(struct atmel_serial *info){

unsigned long flags;

if (info->flags & S_INITIALIZED)return 0;

if (!info->xmit_buf) {info->xmit_buf = (unsigned char *) get_free_page(GFP_KERNEL);if (!info->xmit_buf)

return -ENOMEM;}if (!info->rx_buf) { //info->rx_buf = (unsigned char *) get_free_page(GFP_KERNEL);

//info->rx_buf = rx_buf1;if (!info->rx_buf)

return -ENOMEM;}save_flags(flags);cli();

#ifdef SERIAL_DEBUG_OPENprintk("starting up ttyS%d (irq %d)...\n", info->line, info->irq);

#endif/* * Clear the FIFO buffers and disable them * (they will be reenabled in change_speed()) */

if (info->tty)clear_bit(TTY_IO_ERROR, &info->tty->flags);

info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;

/* * and set the speed of the serial port */

uart_init(info);//set_ints_mode(0, info);change_speed(info);info->flags |= S_INITIALIZED;restore_flags(flags);return 0;

Page 118: SkyEye分析报告 - huihoo.org  · Web viewSkyEye分析报告. skyeye/ 陈渝. chenyu/ chenyu@hpclab.cs.tsinghua.edu.cn 清华大学计算机

}

/* * This routine will shutdown a serial port; interrupts are disabled, and * DTR is dropped if the hangup on close termio flag is on. */static void shutdown(struct atmel_serial *info){

unsigned long flags;

tx_disable(info->usart);rx_disable(info->usart);rx_stop(info->usart); /* All off! */if (!(info->flags & S_INITIALIZED))

return;

#ifdef SERIAL_DEBUG_OPENprintk("Shutting down serial port %d (irq %d)....\n", info->line,

info->irq);#endif

save_flags(flags);cli(); /* Disable interrupts */

if (info->xmit_buf) {free_page((unsigned long) info->xmit_buf);info->xmit_buf = 0;

}

if (info->tty)set_bit(TTY_IO_ERROR, &info->tty->flags);

info->flags &= ~S_INITIALIZED;restore_flags(flags);

}

/* rate = 1036800 / ((65 - prescale) * (1<<divider)) */

static int baud_table[] = {0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800,9600, 19200, 38400, 57600, 115200, 0

};

/*

Page 119: SkyEye分析报告 - huihoo.org  · Web viewSkyEye分析报告. skyeye/ 陈渝. chenyu/ chenyu@hpclab.cs.tsinghua.edu.cn 清华大学计算机

* This routine is called to set the UART divisor registers to match * the specified baud rate for a serial port. */static void change_speed(struct atmel_serial *info){

unsigned cflag;int i;

if (!info->tty || !info->tty->termios)return;

cflag = info->tty->termios->c_cflag;

// disable tx and rxinfo->usart->cr = US_TXDIS | US_RXDIS;

/* First disable the interrupts */tx_stop(info->usart);rx_stop(info->usart);

/* set the baudrate */i = cflag & CBAUD;

info->baud = baud_table[i];uart_speed(info, cflag);tx_start(info->usart, info->use_ints);rx_start(info->usart, info->use_ints);

// enable tx and rxinfo->usart->cr = US_TXEN | US_RXEN;

return;}

static void start_rx(struct atmel_serial *info){

volatile struct atmel_usart_regs *uart = info->usart;

rx_stop(uart);/* FIXME - rehnberg

if (info->rx_buf == rx_buf1) {info->rx_buf = rx_buf2;

} else {info->rx_buf = rx_buf1;

}

Page 120: SkyEye分析报告 - huihoo.org  · Web viewSkyEye分析报告. skyeye/ 陈渝. chenyu/ chenyu@hpclab.cs.tsinghua.edu.cn 清华大学计算机

*/uart->rpr = (unsigned long) info->rx_buf;uart->rcr = (unsigned long) RX_SERIAL_SIZE;rx_start(uart, info->use_ints);

}static void xmit_char(struct atmel_serial *info, char ch){

prompt0 = ch;xmit_string(info, &prompt0, 1);

}static void xmit_string(struct atmel_serial *info, char *p, int len){

info->usart->tcr = 0;info->usart->tpr = (unsigned long) p;info->usart->tcr = (unsigned long) len;tx_start(info->usart, info->use_ints);

}

/* * atmel_console_print is registered for printk. */int atmel_console_initialized;

static void init_console(struct atmel_serial *info){

memset(info, 0, sizeof(struct atmel_serial));

#ifdef CONFIG_SWAP_ATMEL_PORTSinfo->usart = (volatile struct atmel_usart_regs *) AT91_USART1_BASE;info->irqmask = AIC_URT1;info->irq = IRQ_USART1;

#elseinfo->usart = (volatile struct atmel_usart_regs *) AT91_USART0_BASE;info->irqmask = 1<<IRQ_USART0;info->irq = IRQ_USART0;

#endifinfo->tty = 0;info->port = 0;info->use_ints = 0;info->cts_state = 1;info->is_cons = 1;atmel_console_initialized = 1;

}

Page 121: SkyEye分析报告 - huihoo.org  · Web viewSkyEye分析报告. skyeye/ 陈渝. chenyu/ chenyu@hpclab.cs.tsinghua.edu.cn 清华大学计算机

void console_print_atmel(const char *p){

char c;struct atmel_serial *info;

#ifdef CONFIG_SWAP_ATMEL_PORTSinfo = &atmel_info[1];

#elseinfo = &atmel_info[0];

#endif

if (!atmel_console_initialized) {init_console(info);uart_init(info);info->baud = 9600;tx_stop(info->usart);rx_stop(info->usart);uart_speed(info, 0xffff);tx_start(info->usart, info->use_ints);rx_start(info->usart, info->use_ints);

}

while ((c = *(p++)) != 0) {if (c == '\n')

rs_put_char(info, '\r');rs_put_char(info, c);

}

/* Comment this if you want to have a strict interrupt-driven output */#if 0

if (!info->use_ints) rs_fair_output(info);

#endif

return;}

static void rs_set_ldisc(struct tty_struct *tty){

struct atmel_serial *info = (struct atmel_serial *) tty->driver_data;

if (serial_paranoia_check(info, tty->device, "rs_set_ldisc"))return;

Page 122: SkyEye分析报告 - huihoo.org  · Web viewSkyEye分析报告. skyeye/ 陈渝. chenyu/ chenyu@hpclab.cs.tsinghua.edu.cn 清华大学计算机

info->is_cons = (tty->termios->c_line == N_TTY);

printk("ttyS%d console mode %s\n", info->line, info->is_cons ? "on" : "off");

}

static void rs_flush_chars(struct tty_struct *tty){

struct atmel_serial *info = (struct atmel_serial *) tty->driver_data;unsigned long flags;

if (serial_paranoia_check(info, tty->device, "rs_flush_chars"))return;

if (!info->use_ints) {for (;;) {

if (info->xmit_cnt <= 0 || tty->stopped || tty->hw_stopped ||!info->xmit_buf) return;

/* Enable transmitter */save_flags(flags);cli();tx_start(info->usart, info->use_ints);

}} else {

if (info->xmit_cnt <= 0 || tty->stopped || tty->hw_stopped ||!info->xmit_buf) return;

/* Enable transmitter */save_flags(flags);cli();tx_start(info->usart, info->use_ints);

}

if (!info->use_ints)wait_EOT(info->usart);

/* Send char */xmit_char(info, info->xmit_buf[info->xmit_tail++]);info->xmit_tail = info->xmit_tail & (SERIAL_XMIT_SIZE - 1);info->xmit_cnt--;

restore_flags(flags);}

Page 123: SkyEye分析报告 - huihoo.org  · Web viewSkyEye分析报告. skyeye/ 陈渝. chenyu/ chenyu@hpclab.cs.tsinghua.edu.cn 清华大学计算机

extern void console_printn(const char *b, int count);

static int rs_write(struct tty_struct *tty, int from_user,const unsigned char *buf, int count)

{int c, total = 0;struct atmel_serial *info = (struct atmel_serial *) tty->driver_data;unsigned long flags;

if (serial_paranoia_check(info, tty->device, "rs_write"))return 0;

if (!tty || !info->xmit_buf)return 0;

save_flags(flags);while (1) {

cli();c = MIN(count, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,

SERIAL_XMIT_SIZE - info->xmit_head));if (c <= 0)

break;

if (from_user) {down(&tmp_buf_sem);copy_from_user(tmp_buf, buf, c);memcpy(info->xmit_buf + info->xmit_head, tmp_buf, c);up(&tmp_buf_sem);

} else {memcpy(info->xmit_buf + info->xmit_head, buf, c);

}info->xmit_head = (info->xmit_head + c) & (SERIAL_XMIT_SIZE - 1);info->xmit_cnt += c;restore_flags(flags);buf += c;count -= c;total += c;

}

if (info->xmit_cnt && !tty->stopped && !tty->hw_stopped) {/* Enable transmitter */

cli();/*printk("Enabling transmitter\n"); */

Page 124: SkyEye分析报告 - huihoo.org  · Web viewSkyEye分析报告. skyeye/ 陈渝. chenyu/ chenyu@hpclab.cs.tsinghua.edu.cn 清华大学计算机

if (!info->use_ints) {while (info->xmit_cnt) {

wait_EOT(info->usart);/* Send char */xmit_char(info, info->xmit_buf[info->xmit_tail++]);wait_EOT(info->usart);info->xmit_tail = info->xmit_tail & (SERIAL_XMIT_SIZE - 1);info->xmit_cnt--;

}} else {

if (info->xmit_cnt) {/* Send char */wait_EOT(info->usart);if (info->xmit_tail + info->xmit_cnt < SERIAL_XMIT_SIZE) {

xmit_string(info, info->xmit_buf + info->xmit_tail,info->xmit_cnt);

info->xmit_tail =(info->xmit_tail + info->xmit_cnt) & (SERIAL_XMIT_SIZE - 1);

info->xmit_cnt = 0;} else {

coucou2();xmit_string(info, info->xmit_buf + info->xmit_tail,

SERIAL_XMIT_SIZE - info->xmit_tail);//xmit_string(info, info->xmit_buf, info->xmit_tail + info-

>xmit_cnt - SERIAL_XMIT_SIZE);info->xmit_cnt =

info->xmit_cnt - (SERIAL_XMIT_SIZE - info->xmit_tail);info->xmit_tail = 0;

}}

}} else {

/*printk("Skipping transmit\n"); */}

#if 0printk("Enabling stuff anyhow\n");tx_start(0);

if (SCC_EOT(0, 0)) {printk("TX FIFO empty.\n");/* Send char */

Page 125: SkyEye分析报告 - huihoo.org  · Web viewSkyEye分析报告. skyeye/ 陈渝. chenyu/ chenyu@hpclab.cs.tsinghua.edu.cn 清华大学计算机

atmel_xmit_char(info->usart, info->xmit_buf[info->xmit_tail++]);info->xmit_tail = info->xmit_tail & (SERIAL_XMIT_SIZE - 1);info->xmit_cnt--;

}#endif

restore_flags(flags);return total;

}

static int rs_write_room(struct tty_struct *tty){

struct atmel_serial *info = (struct atmel_serial *) tty->driver_data;int ret;

if (serial_paranoia_check(info, tty->device, "rs_write_room"))return 0;

ret = SERIAL_XMIT_SIZE - info->xmit_cnt - 1;if (ret < 0)

ret = 0;return ret;

}

static int rs_chars_in_buffer(struct tty_struct *tty){

struct atmel_serial *info = (struct atmel_serial *) tty->driver_data;

if (serial_paranoia_check(info, tty->device, "rs_chars_in_buffer"))return 0;

return info->xmit_cnt;}

static void rs_flush_buffer(struct tty_struct *tty){

unsigned long flags;struct atmel_serial *info = (struct atmel_serial *) tty->driver_data;

if (serial_paranoia_check(info, tty->device, "rs_flush_buffer"))return;

save_flags(flags);cli();info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;restore_flags(flags);wake_up_interruptible(&tty->write_wait);

Page 126: SkyEye分析报告 - huihoo.org  · Web viewSkyEye分析报告. skyeye/ 陈渝. chenyu/ chenyu@hpclab.cs.tsinghua.edu.cn 清华大学计算机

if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&tty->ldisc.write_wakeup) (tty->ldisc.write_wakeup) (tty);

}

/* * ------------------------------------------------------------ * rs_throttle() * * This routine is called by the upper-layer tty layer to signal that * incoming characters should be throttled. * ------------------------------------------------------------ */static void rs_throttle(struct tty_struct *tty){

struct atmel_serial *info = (struct atmel_serial *) tty->driver_data;

#ifdef SERIAL_DEBUG_THROTTLEchar buf[64];

printk("throttle %s: %d....\n", _tty_name(tty, buf), tty->ldisc.chars_in_buffer(tty));

#endif

if (serial_paranoia_check(info, tty->device, "rs_throttle"))return;

if (I_IXOFF(tty))info->x_char = STOP_CHAR(tty);

/* Turn off RTS line (do this atomic) */}

static void rs_unthrottle(struct tty_struct *tty){

struct atmel_serial *info = (struct atmel_serial *) tty->driver_data;

#ifdef SERIAL_DEBUG_THROTTLEchar buf[64];

printk("unthrottle %s: %d....\n", _tty_name(tty, buf), tty->ldisc.chars_in_buffer(tty));

#endif

if (serial_paranoia_check(info, tty->device, "rs_unthrottle"))

Page 127: SkyEye分析报告 - huihoo.org  · Web viewSkyEye分析报告. skyeye/ 陈渝. chenyu/ chenyu@hpclab.cs.tsinghua.edu.cn 清华大学计算机

return;

if (I_IXOFF(tty)) {if (info->x_char)

info->x_char = 0;else

info->x_char = START_CHAR(tty);}

/* Assert RTS line (do this atomic) */}

/* * ------------------------------------------------------------ * rs_ioctl() and friends * ------------------------------------------------------------ */

static int get_serial_info(struct atmel_serial *info, struct serial_struct *retinfo)

{struct serial_struct tmp;

if (!retinfo)return -EFAULT;

memset(&tmp, 0, sizeof(tmp));tmp.type = info->type;tmp.line = info->line;tmp.irq = info->irq;tmp.port = info->port;tmp.flags = info->flags;tmp.baud_base = info->baud_base;tmp.close_delay = info->close_delay;tmp.closing_wait = info->closing_wait;tmp.custom_divisor = info->custom_divisor;copy_to_user(retinfo, &tmp, sizeof(*retinfo));return 0;

}

static int set_serial_info(struct atmel_serial *info, struct serial_struct *new_info)

{struct serial_struct new_serial;struct atmel_serial old_info;

Page 128: SkyEye分析报告 - huihoo.org  · Web viewSkyEye分析报告. skyeye/ 陈渝. chenyu/ chenyu@hpclab.cs.tsinghua.edu.cn 清华大学计算机

int retval = 0;

if (!new_info)return -EFAULT;

copy_from_user(&new_serial, new_info, sizeof(new_serial));old_info = *info;

if (!suser()) {if ((new_serial.baud_base != info->baud_base) ||

(new_serial.type != info->type) ||(new_serial.close_delay != info->close_delay) ||((new_serial.flags & ~S_USR_MASK) != (info->flags & ~S_USR_MASK))) return -EPERM;

info->flags = ((info->flags & ~S_USR_MASK) | (new_serial.flags & S_USR_MASK));

info->custom_divisor = new_serial.custom_divisor;goto check_and_exit;

}

if (info->count > 1)return -EBUSY;

/* * OK, past this point, all the error checking has been done. * At this point, we start making changes..... */

info->baud_base = new_serial.baud_base;info->flags = ((info->flags & ~S_FLAGS) |

(new_serial.flags & S_FLAGS));info->type = new_serial.type;info->close_delay = new_serial.close_delay;info->closing_wait = new_serial.closing_wait;

check_and_exit://retval = startup(info);change_speed(info);retval = 0;return retval;

}

/* * get_lsr_info - get line status register info *

Page 129: SkyEye分析报告 - huihoo.org  · Web viewSkyEye分析报告. skyeye/ 陈渝. chenyu/ chenyu@hpclab.cs.tsinghua.edu.cn 清华大学计算机

* Purpose: Let user call ioctl() to get info when the UART physically * is emptied. On bus types like RS485, the transmitter must * release the bus after transmitting. This must be done when * the transmit shift register is empty, not be done when the * transmit holding register is empty. This functionality * allows an RS485 driver to be written in user space. */static int get_lsr_info(struct atmel_serial *info, unsigned int *value){

unsigned char status;

cli();status = info->usart->csr;status &= US_TXEMPTY;sti();put_user(status, value);return 0;

}

/* * This routine sends a break character out the serial port. */static void send_break(struct atmel_serial *info, int duration){ unsigned long flags; if (!info->port) return;

current->state = TASK_INTERRUPTIBLE;save_flags(flags); cli();info->usart->cr = US_STTBRK;if (!info->use_ints) {

while (US_TXRDY != (info->usart->csr & US_TXRDY)) {; // this takes max 2ms at 9600

}info->usart->cr = US_STPBRK;

}restore_flags(flags);

}

static int rs_ioctl(struct tty_struct *tty, struct file *file,unsigned int cmd, unsigned long arg)

{int error;struct atmel_serial *info = (struct atmel_serial *) tty->driver_data;

Page 130: SkyEye分析报告 - huihoo.org  · Web viewSkyEye分析报告. skyeye/ 陈渝. chenyu/ chenyu@hpclab.cs.tsinghua.edu.cn 清华大学计算机

int retval;

if (serial_paranoia_check(info, tty->device, "rs_ioctl"))return -ENODEV;

if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&(cmd != TIOCSERCONFIG) && (cmd != TIOCSERGWILD) &&(cmd != TIOCSERSWILD) && (cmd != TIOCSERGSTRUCT)) {if (tty->flags & (1 << TTY_IO_ERROR))

return -EIO;}

switch (cmd) {case TCSBRK: /* SVID version: non-zero arg --> no break */

retval = tty_check_change(tty);if (retval)

return retval;tty_wait_until_sent(tty, 0);if (!arg)

send_break(info, HZ / 4); /* 1/4 second */return 0;

case TCSBRKP: /* support for POSIX tcsendbreak() */retval = tty_check_change(tty);if (retval)

return retval;tty_wait_until_sent(tty, 0);send_break(info, arg ? arg * (HZ / 10) : HZ / 4);return 0;

case TIOCGSOFTCAR:error = verify_area(VERIFY_WRITE, (void *) arg, sizeof(long));

if (error)return error;

put_user(C_CLOCAL(tty) ? 1 : 0, (unsigned long *) arg);return 0;

case TIOCSSOFTCAR:arg = get_user(arg,(unsigned long *) arg);tty->termios->c_cflag = ((tty->termios->c_cflag & ~CLOCAL) | (arg ?

CLOCAL : 0));return 0;

case TIOCGSERIAL:error = verify_area(VERIFY_WRITE, (void *) arg, sizeof(struct

serial_struct));if (error)

Page 131: SkyEye分析报告 - huihoo.org  · Web viewSkyEye分析报告. skyeye/ 陈渝. chenyu/ chenyu@hpclab.cs.tsinghua.edu.cn 清华大学计算机

return error;return get_serial_info(info, (struct serial_struct *) arg);

case TIOCSSERIAL:return set_serial_info(info, (struct serial_struct *) arg);

case TIOCSERGETLSR: /* Get line status register */error = verify_area(VERIFY_WRITE, (void *) arg,

sizeof(unsigned int));if (error)

return error;else

return get_lsr_info(info, (unsigned int *) arg);

case TIOCSERGSTRUCT:error = verify_area(VERIFY_WRITE, (void *) arg,

sizeof(struct atmel_serial));if (error)

return error;copy_to_user((struct atmel_serial *) arg, info,

sizeof(struct atmel_serial));return 0;

case TCSETS:handle_termios_tcsets((struct termios *)arg, info);// return set_serial_info(info, (struct serial_struct *) arg);break;

default:return -ENOIOCTLCMD;

}return 0;

}

static void handle_termios_tcsets(struct termios * ptermios, struct atmel_serial * pinfo ){

/* * hmmmm.... */if (pinfo->tty->termios->c_cflag != ptermios->c_cflag)

pinfo->tty->termios->c_cflag = ptermios->c_cflag;change_speed(pinfo);

}

static void rs_set_termios(struct tty_struct *tty,struct termios *old_termios)

Page 132: SkyEye分析报告 - huihoo.org  · Web viewSkyEye分析报告. skyeye/ 陈渝. chenyu/ chenyu@hpclab.cs.tsinghua.edu.cn 清华大学计算机

{struct atmel_serial *info = (struct atmel_serial *) tty->driver_data;

if (tty->termios->c_cflag == old_termios->c_cflag)return;

change_speed(info);

if ((old_termios->c_cflag & CRTSCTS) &&!(tty->termios->c_cflag & CRTSCTS)) {tty->hw_stopped = 0;rs_start(tty);

}

}

/* * ------------------------------------------------------------ * rs_close() * * This routine is called when the serial port gets closed. First, we * wait for the last remaining data to be sent. Then, we unlink its * S structure from the interrupt chain if necessary, and we free * that IRQ if nothing is left in the chain. * ------------------------------------------------------------ */static void rs_close(struct tty_struct *tty, struct file *filp){

struct atmel_serial *info = (struct atmel_serial *) tty->driver_data;unsigned long flags;

if (!info || serial_paranoia_check(info, tty->device, "rs_close"))return;

save_flags(flags);cli();

if (tty_hung_up_p(filp)) {restore_flags(flags);return;

}#ifdef SERIAL_DEBUG_OPEN

printk("rs_close ttyS%d, count = %d\n", info->line, info->count);#endif

Page 133: SkyEye分析报告 - huihoo.org  · Web viewSkyEye分析报告. skyeye/ 陈渝. chenyu/ chenyu@hpclab.cs.tsinghua.edu.cn 清华大学计算机

if ((tty->count == 1) && (info->count != 1)) {/* * Uh, oh. tty->count is 1, which means that the tty * structure will be freed. Info->count should always * be one in these conditions. If it's greater than * one, we've got real problems, since it means the * serial port won't be shutdown. */printk("rs_close: bad serial port count; tty->count is 1, "

"info->count is %d\n", info->count);info->count = 1;

}if (--info->count < 0) {

printk("rs_close: bad serial port count for ttyS%d: %d\n", info->line, info->count);

info->count = 0;}if (info->count) {

restore_flags(flags);return;

}// closing port so disable interruptsset_ints_mode(0, info);

info->flags |= S_CLOSING;/* * Save the termios structure, since this port may have * separate termios for callout and dialin. */if (info->flags & S_NORMAL_ACTIVE)

info->normal_termios = *tty->termios;if (info->flags & S_CALLOUT_ACTIVE)

info->callout_termios = *tty->termios;/* * Now we wait for the transmit buffer to clear; and we notify * the line discipline to only process XON/XOFF characters. */tty->closing = 1;if (info->closing_wait != S_CLOSING_WAIT_NONE)

tty_wait_until_sent(tty, info->closing_wait);/* * At this point we stop accepting input. To do this, we * disable the receive line status interrupts, and tell the * interrupt driver to stop checking the data ready bit in the

Page 134: SkyEye分析报告 - huihoo.org  · Web viewSkyEye分析报告. skyeye/ 陈渝. chenyu/ chenyu@hpclab.cs.tsinghua.edu.cn 清华大学计算机

* line status register. */

shutdown(info);if (tty->driver.flush_buffer)

tty->driver.flush_buffer(tty);if (tty->ldisc.flush_buffer)

tty->ldisc.flush_buffer(tty);tty->closing = 0;info->event = 0;info->tty = 0;if (tty->ldisc.num != ldiscs[N_TTY].num) {

if (tty->ldisc.close)(tty->ldisc.close) (tty);

tty->ldisc = ldiscs[N_TTY];tty->termios->c_line = N_TTY;if (tty->ldisc.open)

(tty->ldisc.open) (tty);}if (info->blocked_open) {

if (info->close_delay) {current->state = TASK_INTERRUPTIBLE;schedule_timeout(info->close_delay);

}wake_up_interruptible(&info->open_wait);

}info->flags &= ~(S_NORMAL_ACTIVE | S_CALLOUT_ACTIVE | S_CLOSING);wake_up_interruptible(&info->close_wait);restore_flags(flags);

}

/* * rs_hangup() --- called by tty_hangup() when a hangup is signaled. */static void rs_hangup(struct tty_struct *tty){

struct atmel_serial *info = (struct atmel_serial *) tty->driver_data;

if (serial_paranoia_check(info, tty->device, "rs_hangup"))return;

rs_flush_buffer(tty);shutdown(info);info->event = 0;

Page 135: SkyEye分析报告 - huihoo.org  · Web viewSkyEye分析报告. skyeye/ 陈渝. chenyu/ chenyu@hpclab.cs.tsinghua.edu.cn 清华大学计算机

info->count = 0;info->flags &= ~(S_NORMAL_ACTIVE | S_CALLOUT_ACTIVE);info->tty = 0;wake_up_interruptible(&info->open_wait);

}

/* * ------------------------------------------------------------ * rs_open() and friends * ------------------------------------------------------------ */static int block_til_ready(struct tty_struct *tty, struct file *filp,

struct atmel_serial *info){

DECLARE_WAITQUEUE(wait, current); int retval;int do_clocal = 0;

/* * If the device is in the middle of being closed, then block * until it's done, and then try again. */if (info->flags & S_CLOSING) {

interruptible_sleep_on(&info->close_wait);#ifdef SERIAL_DO_RESTART

if (info->flags & S_HUP_NOTIFY)return -EAGAIN;

elsereturn -ERESTARTSYS;

#elsereturn -EAGAIN;

#endif}

/* * If this is a callout device, then just make sure the normal * device isn't being used. */if (tty->driver.subtype == SERIAL_TYPE_CALLOUT) {

if (info->flags & S_NORMAL_ACTIVE)return -EBUSY;

if ((info->flags & S_CALLOUT_ACTIVE) &&(info->flags & S_SESSION_LOCKOUT) &&(info->session != current->session)) return -EBUSY;

Page 136: SkyEye分析报告 - huihoo.org  · Web viewSkyEye分析报告. skyeye/ 陈渝. chenyu/ chenyu@hpclab.cs.tsinghua.edu.cn 清华大学计算机

if ((info->flags & S_CALLOUT_ACTIVE) &&(info->flags & S_PGRP_LOCKOUT) &&(info->pgrp != current->pgrp)) return -EBUSY;

info->flags |= S_CALLOUT_ACTIVE;return 0;

}

/* * If non-blocking mode is set, or the port is not enabled, * then make the check up front and then exit. */if ((filp->f_flags & O_NONBLOCK) || (tty->flags & (1 << TTY_IO_ERROR))) {

if (info->flags & S_CALLOUT_ACTIVE)return -EBUSY;

info->flags |= S_NORMAL_ACTIVE;return 0;

}

if (info->flags & S_CALLOUT_ACTIVE) {if (info->normal_termios.c_cflag & CLOCAL)

do_clocal = 1;} else {

if (tty->termios->c_cflag & CLOCAL)do_clocal = 1;

}

/* * Block waiting for the carrier detect and the line to become * free (i.e., not in use by the callout). While we are in * this loop, info->count is dropped by one, so that * rs_close() knows when to free things. We restore it upon * exit, either normal or abnormal. */retval = 0;add_wait_queue(&info->open_wait, &wait);

#ifdef SERIAL_DEBUG_OPENprintk("block_til_ready before block: ttyS%d, count = %d\n",

info->line, info->count);#endif

info->count--;info->blocked_open++;while (1) {

#ifdef US_RTSsave_flags(flags);

Page 137: SkyEye分析报告 - huihoo.org  · Web viewSkyEye分析报告. skyeye/ 陈渝. chenyu/ chenyu@hpclab.cs.tsinghua.edu.cn 清华大学计算机

cli();if (!(info->flags & S_CALLOUT_ACTIVE))

atmel_rtsdtr(info, 1);restore_flags(flags);

#endifcurrent->state = TASK_INTERRUPTIBLE;if (tty_hung_up_p(filp) || !(info->flags & S_INITIALIZED)) {

#ifdef SERIAL_DO_RESTARTif (info->flags & S_HUP_NOTIFY)

retval = -EAGAIN;else

retval = -ERESTARTSYS;#else

retval = -EAGAIN;#endif

break;}if (!(info->flags & S_CALLOUT_ACTIVE) &&

!(info->flags & S_CLOSING) && do_clocal)break;

if (signal_pending(current)) {retval = -ERESTARTSYS;break;

}#ifdef SERIAL_DEBUG_OPEN

printk("block_til_ready blocking: ttyS%d, count = %d\n", info->line, info->count);

#endifschedule();

}current->state = TASK_RUNNING;remove_wait_queue(&info->open_wait, &wait);if (!tty_hung_up_p(filp))

info->count++;info->blocked_open--;

#ifdef SERIAL_DEBUG_OPENprintk("block_til_ready after blocking: ttyS%d, count = %d\n",

info->line, info->count);#endif

if (retval)return retval;

info->flags |= S_NORMAL_ACTIVE;if (!info->use_ints) {

serialpoll.data = (void *) info;

Page 138: SkyEye分析报告 - huihoo.org  · Web viewSkyEye分析报告. skyeye/ 陈渝. chenyu/ chenyu@hpclab.cs.tsinghua.edu.cn 清华大学计算机

queue_task(&serialpoll, &tq_timer);}return 0;

}

/* * This routine is called whenever a serial port is opened. It * enables interrupts for a serial port, linking in its S structure into * the IRQ chain. It also performs the serial-specific * initialization for the tty structure. */int rs_open(struct tty_struct *tty, struct file *filp){

struct atmel_serial *info;int retval, line;

line = MINOR(tty->device) - tty->driver.minor_start;

// check if line is saneif (line < 0 || line >= AT91_USART_CNT)

return -ENODEV;

info = &atmel_info[line];#if 0

/* Is the kgdb running over this line? */if (info->kgdb_channel)

return -ENODEV;#endif

if (serial_paranoia_check(info, tty->device, "rs_open"))return -ENODEV;

#ifdef SERIAL_DEBUG_OPENprintk("rs_open %s%d, count = %d\n", tty->driver.name, info->line,

info->count);#endif

info->count++;tty->driver_data = info;info->tty = tty;

/* * Start up serial port */set_ints_mode(1, info);

retval = startup(info);

Page 139: SkyEye分析报告 - huihoo.org  · Web viewSkyEye分析报告. skyeye/ 陈渝. chenyu/ chenyu@hpclab.cs.tsinghua.edu.cn 清华大学计算机

if (retval)return retval;

retval = block_til_ready(tty, filp, info);if (retval) {

#ifdef SERIAL_DEBUG_OPENprintk("rs_open returning after block_til_ready with %d\n",

retval);#endif

return retval;}

if ((info->count == 1) && (info->flags & S_SPLIT_TERMIOS)) {if (tty->driver.subtype == SERIAL_TYPE_NORMAL)

*tty->termios = info->normal_termios;else

*tty->termios = info->callout_termios;change_speed(info);

}

info->session = current->session;info->pgrp = current->pgrp;

#ifdef SERIAL_DEBUG_OPENprintk("rs_open ttyS%d successful...\n", info->line);

#endifreturn 0;

}

#if 0

static inline void rs_cons_check(struct atmel_serial *ss, int channel){

int i, o, io;static consout_registered = 0;static msg_printed = 0;

i = o = io = 0;

/* Is this one of the serial console lines? */if ((atmel_cons_chanout != channel) && (atmel_cons_chanin != channel))

return;atmel_conschan = ss->atmel_channel;

Page 140: SkyEye分析报告 - huihoo.org  · Web viewSkyEye分析报告. skyeye/ 陈渝. chenyu/ chenyu@hpclab.cs.tsinghua.edu.cn 清华大学计算机

atmel_consinfo = ss;

/* Register the console output putchar, if necessary */if ((atmel_cons_chanout == channel)) {

o = 1;/* double whee.. */if (!consout_registered) {

register_console(atmel_console_print);consout_registered = 1;

}}

/* If this is console input, we handle the break received * status interrupt on this line to mean prom_halt(). */if (atmel_cons_chanin == channel) {

ss->break_abort = 1;i = 1;

}if (o && i)

io = 1;if (ss->baud != 9600)

panic("Console baud rate weirdness");

/* Set flag variable for this port so that it cannot be * opened for other uses by accident. */ss->is_cons = 1;

if (io) {if (!msg_printed) {

printk("zs%d: console I/O\n", ((channel >> 1) & 1));msg_printed = 1;

}} else {

printk("zs%d: console %s\n", ((channel >> 1) & 1), (i == 1 ? "input" : (o == 1 ? "output" : "WEIRD")));

}}#endif

static struct irqaction irq_usart0 ={ rs_interrupta, 0, 0, "usart0", NULL, NULL };

static struct irqaction irq_usart1 =

Page 141: SkyEye分析报告 - huihoo.org  · Web viewSkyEye分析报告. skyeye/ 陈渝. chenyu/ chenyu@hpclab.cs.tsinghua.edu.cn 清华大学计算机

{ rs_interruptb, 0, 0, "usart1", NULL, NULL };

extern int setup_arm_irq(int, struct irqaction *);

static void interrupts_init(void){

setup_arm_irq(IRQ_USART0, &irq_usart0);setup_arm_irq(IRQ_USART1, &irq_usart1);

}

static void show_serial_version(void){

printk("Atmel USART driver version 0.99\n");}

/* rs_init inits the driver */static int __init rs_atmel_init(void){

int flags, i;struct atmel_serial *info;

/* initialise PIO for serial port */HW_AT91_USART_INIT

/* Setup base handler, and timer table. */init_bh(SERIAL_BH, do_serial_bh);//xxx timer_table[RS_TIMER].fn = rs_timer;//xxx timer_table[RS_TIMER].expires = 0;

// FIXME - do this rightrx_buf_table[0] = rx_buf1;rx_buf_table[1] = rx_buf2;

show_serial_version();

/* Initialize the tty_driver structure */

// set the tty_struct pointers to NULL to let the layer// above allocate the structs.for (i=0; i < AT91_USART_CNT; i++)

serial_table[i] = NULL;

memset(&serial_driver, 0, sizeof(struct tty_driver));

Page 142: SkyEye分析报告 - huihoo.org  · Web viewSkyEye分析报告. skyeye/ 陈渝. chenyu/ chenyu@hpclab.cs.tsinghua.edu.cn 清华大学计算机

serial_driver.magic = TTY_DRIVER_MAGIC;serial_driver.name = "ttyS";serial_driver.major = TTY_MAJOR;serial_driver.minor_start = 64;

#ifdef CONFIG_CONSOLE_ON_SC28L91serial_driver.minor_start += 1;

#endifserial_driver.num = 2;serial_driver.type = TTY_DRIVER_TYPE_SERIAL;serial_driver.subtype = SERIAL_TYPE_NORMAL;serial_driver.init_termios = tty_std_termios;

serial_driver.init_termios.c_cflag =B9600 | CS8 | CREAD | HUPCL | CLOCAL;

serial_driver.flags = TTY_DRIVER_REAL_RAW;serial_driver.refcount = &serial_refcount;serial_driver.table = serial_table;serial_driver.termios = serial_termios;serial_driver.termios_locked = serial_termios_locked;

serial_driver.open = rs_open;serial_driver.close = rs_close;serial_driver.write = rs_write;serial_driver.flush_chars = rs_flush_chars;serial_driver.write_room = rs_write_room;serial_driver.chars_in_buffer = rs_chars_in_buffer;serial_driver.flush_buffer = rs_flush_buffer;serial_driver.ioctl = rs_ioctl;serial_driver.throttle = rs_throttle;serial_driver.unthrottle = rs_unthrottle;serial_driver.set_termios = rs_set_termios;serial_driver.stop = rs_stop;serial_driver.start = rs_start;serial_driver.hangup = rs_hangup;serial_driver.set_ldisc = rs_set_ldisc;

/* * The callout device is just like normal device except for * major number and the subtype code. */callout_driver = serial_driver;callout_driver.name = "cua";callout_driver.major = TTYAUX_MAJOR;callout_driver.subtype = SERIAL_TYPE_CALLOUT;

Page 143: SkyEye分析报告 - huihoo.org  · Web viewSkyEye分析报告. skyeye/ 陈渝. chenyu/ chenyu@hpclab.cs.tsinghua.edu.cn 清华大学计算机

if (tty_register_driver(&serial_driver))panic("Couldn't register serial driver\n");

if (tty_register_driver(&callout_driver))panic("Couldn't register callout driver\n");

save_flags(flags);cli();for (i = 0; i < 2; i++) {

info = &atmel_info[i];info->magic = SERIAL_MAGIC;info->usart = usarts[i];info->tty = 0;info->irqmask = (i) ? (1<<IRQ_USART1) : (1<<IRQ_USART0);info->irq = (i) ? IRQ_USART1 : IRQ_USART0;

#ifdef CONFIG_SWAP_ATMEL_PORTSinfo->port = (i) ? 2 : 1;info->line = !i;

#ifdef CONFIG_CONSOLE_ON_ATMELinfo->is_cons = i;

#elseinfo->is_cons = 0;

#endif#else

info->port = (i) ? 1 : 2;info->line = i;

#ifdef CONFIG_CONSOLE_ON_ATMELinfo->is_cons = !i;

#elseinfo->is_cons = 0;

#endif#endif#ifdef CONFIG_CONSOLE_ON_SC28L91

info->line += 1;#endif

set_ints_mode(0, info);info->custom_divisor = 16;info->close_delay = 50;info->closing_wait = 3000;info->cts_state = 1;info->x_char = 0;info->event = 0;info->count = 0;info->blocked_open = 0;

Page 144: SkyEye分析报告 - huihoo.org  · Web viewSkyEye分析报告. skyeye/ 陈渝. chenyu/ chenyu@hpclab.cs.tsinghua.edu.cn 清华大学计算机

info->tqueue.routine = do_softint;info->tqueue.data = info;info->tqueue_hangup.routine = do_serial_hangup;info->tqueue_hangup.data = info;info->callout_termios = callout_driver.init_termios;info->normal_termios = serial_driver.init_termios;init_waitqueue_head(&info->open_wait);init_waitqueue_head(&info->close_wait);info->rx_buf = rx_buf_table[i];

printk("%s%d at 0x%p (irq = %d)", serial_driver.name, info->line, info->usart, info->irq);

printk(" is a builtin Atmel APB USART\n");}

// FIXMEinfo->usart->cr = 0x1ac; // reset, disableinfo->usart->idr = 0xffffffff; // disable all interruptsinfo->usart->tcr = 0; // stop transmitinfo->usart->rcr = 0; // stop receive

interrupts_init();

restore_flags(flags);// hack to do pollingserialpoll.routine = serpoll;serialpoll.data = 0;

return 0;}

module_init(rs_atmel_init);

#if 0/* * register_serial and unregister_serial allows for serial ports to be * configured at run-time, to support PCMCIA modems. *//* SPARC: Unused at this time, just here to make things link. */static int register_serial(struct serial_struct *req){

return -1;}

Page 145: SkyEye分析报告 - huihoo.org  · Web viewSkyEye分析报告. skyeye/ 陈渝. chenyu/ chenyu@hpclab.cs.tsinghua.edu.cn 清华大学计算机

static void unregister_serial(int line){

return;}

static void dbg_putc(int ch){

static char tmp[2];#define US_TPR (0x38) /* Transmit Pointer Register */#define US_TCR (0x3C) /* Transmit Counter Register */

tmp[0] = ch;

outl_t((unsigned long) tmp, (USART0_BASE + US_TPR) );outl_t(1, (USART0_BASE + US_TCR) );

while (inl_t((USART0_BASE + US_TCR) )) {}

}

static void dbg_print(const char *str){

const char *p;

for (p = str; *p; p++) {if (*p == '\n') {

dbg_putc('\r');}dbg_putc(*p);

}}

static void dbg_printk(const char *fmt, ...){

char tmp[256];va_list args;

va_start(args, fmt);vsprintf(tmp, fmt, args);va_end(args);dbg_print(tmp);

}

static void rs_atmel_print(const char *str)

Page 146: SkyEye分析报告 - huihoo.org  · Web viewSkyEye分析报告. skyeye/ 陈渝. chenyu/ chenyu@hpclab.cs.tsinghua.edu.cn 清华大学计算机

{dbg_printk(str);

}

static void dump_a(unsigned long a, unsigned int s){

unsigned long q;

for (q = 0; q < s; q++) {if (q % 16 == 0) {

dbg_printk("%08X: ", q + a);}if (q % 16 == 7) {

dbg_printk("%02X-", *(unsigned char *) (q + a));} else {

dbg_printk("%02X ", *(unsigned char *) (q + a));}if (q % 16 == 15) {

dbg_printk(" :\n");}

}if (q % 16) {

dbg_printk(" :\n");}

}#endif

static kdev_t atmel_console_device(struct console *c){

return MKDEV(TTY_MAJOR, 64 + c->index);}

int atmel_console_setup(void){ HW_AT91_USART_INIT return 0;}

void atmel_console_write (struct console *co, const char *str, unsigned int count)

{char c;struct atmel_serial *info;

Page 147: SkyEye分析报告 - huihoo.org  · Web viewSkyEye分析报告. skyeye/ 陈渝. chenyu/ chenyu@hpclab.cs.tsinghua.edu.cn 清华大学计算机

#ifdef CONFIG_SWAP_ATMEL_PORTSinfo = &atmel_info[1];

#elseinfo = &atmel_info[0];

#endif

if (!atmel_console_initialized) {init_console(info);uart_init(info);info->baud = 9600;tx_stop(info->usart);rx_stop(info->usart);uart_speed(info, 0xffff);tx_start(info->usart, info->use_ints);rx_start(info->usart, info->use_ints);

}

while (count--) { if (*str == '\n') rs_put_char(info,'\r'); rs_put_char(info, *str++ ); }}

static struct console atmel_driver = {name: "ttyS",write: atmel_console_write,read: NULL,device: atmel_console_device,wait_key: NULL,unblank: NULL,setup: atmel_console_setup,flags: CON_PRINTBUFFER,index: -1,cflag: 0,next: NULL

};

void atmel_console_init(void){

register_console(&atmel_driver);}

Page 148: SkyEye分析报告 - huihoo.org  · Web viewSkyEye分析报告. skyeye/ 陈渝. chenyu/ chenyu@hpclab.cs.tsinghua.edu.cn 清华大学计算机

bug

(gdb) i rr0 0x10070cc 16806092r1 0x1007918 16808216r2 0x1 1r3 0x1 1r4 0x1 1r5 0x0 0r6 0x1006064 16801892r7 0x0 0r8 0x0 0r9 0x0 0r10 0x20000013 536870931r11 0x10088e4 16812260r12 0x1007070 16806000sp 0x10088e4 16812260lr 0x10009cc 16779724pc 0x1000404 16778244fps 0x0 0cpsr 0x20000093 536871059

Page 149: SkyEye分析报告 - huihoo.org  · Web viewSkyEye分析报告. skyeye/ 陈渝. chenyu/ chenyu@hpclab.cs.tsinghua.edu.cn 清华大学计算机

(gdb) disasDump of assembler code for function ARMEnableInt:0x1000400 <ARMEnableInt>: ldmia sp!, {r10}0x1000404 <ARMEnableInt+4>: msr cpsr_ctl, r100x1000408 <ARMEnableInt+8>: mov pc, lr0x100040c <ARMEnableInt+12>: streqh r7, [r0, -r4]0x1000410 <ARMEnableInt+16>: tsteq r0, r4, asr #10x1000414 <ARMEnableInt+20>: tsteq r0, r4, lsr #10x1000418 <ARMEnableInt+24>: tsteq r0, r8, lsr #10x100041c <ARMEnableInt+28>: streqh r7, [r0, -r12]0x1000420 <ARMEnableInt+32>: tsteq r0, r4, asr #10x1000424 <ARMEnableInt+36>: tsteq r0, r8, asr r00x1000428 <ARMEnableInt+40>: tsteq r0, r8, asr r00x100042c <ARMEnableInt+44>: streqh r7, [r0, -r12]End of assembler dump.(gdb) si

Breakpoint 1, ARMul_CPSRAltered (state=0x82160f0) at armsupp.c:292292 if (state->prog32Sig == LOW)(gdb) where#0 ARMul_CPSRAltered (state=0x82160f0) at armsupp.c:292#1 0x081226f0 in ARMul_Emulate32 (state=0x82160f0) at armemu.c:1125#2 0x08113927 in ARMul_DoInstr (state=0x82160f0) at arminit.c:252#3 0x08112a29 in sim_resume (sd=0x1, step=1, siggnal=0) at wrapper.c:184#4 0x080dae3f in gdbsim_wait (pid=-1, status=0xbffff3a0) at remote-sim.c:686#5 0x0808eb0f in wait_for_inferior () at infrun.c:1287#6 0x0808e99a in proceed (addr=4294967295, siggnal=TARGET_SIGNAL_DEFAULT, step=1) at infrun.c:1084#7 0x0808c72d in step_1 (skip_subroutines=0, single_inst=1, count_string=0x0) at infcmd.c:542#8 0x0808c51e in stepi_command (count_string=0x0, from_tty=1) at infcmd.c:445#9 0x080b75c1 in execute_command (p=0x81db652 "", from_tty=1) at top.c:1546#10 0x08095351 in command_handler (command=0x81db650 "si") at event-top.c:515#11 0x08095989 in command_line_handler (rl=0x81e8438 "H\204\036\b") at event-top.c:811#12 0x08156598 in rl_callback_read_char () at callback.c:122#13 0x08095232 in stdin_event_handler (error=0, client_data=0x0) at event-top.c:422#14 0x080ced34 in handle_file_event (event_file_desc=0) at event-loop.c:742#15 0x080ce814 in process_event () at event-loop.c:377#16 0x080ce859 in gdb_do_one_event (data=0x0) at event-loop.c:414#17 0x080b68bd in catch_errors (func=0x80ce830 <gdb_do_one_event>, args=0x0, errstring=0x8174920 "", mask=6) at top.c:615#18 0x080ce88c in start_event_loop () at event-loop.c:450#19 0x0806ccfa in captured_command_loop (data=0x0) at main.c:104#20 0x080b68bd in catch_errors (func=0x806cce0 <captured_command_loop>, args=0x0, errstring=0x8174920 "", mask=6)

Page 150: SkyEye分析报告 - huihoo.org  · Web viewSkyEye分析报告. skyeye/ 陈渝. chenyu/ chenyu@hpclab.cs.tsinghua.edu.cn 清华大学计算机

at top.c:615#21 0x0806d66b in captured_main (data=0xbffffa00) at main.c:755#22 0x080b68bd in catch_errors (func=0x806cd28 <captured_main>, args=0xbffffa00, errstring=0x8174920 "", mask=6) at top.c:615#23 0x0806d697 in main (argc=1, argv=0xbffffa74) at main.c:767#24 0x40322306 in __libc_start_main (main=0x806d670 <main>, argc=1, ubp_av=0xbffffa74, init=0x806bfd0 <_init>, fini=0x8160e20 <_fini>, rtld_fini=0x4000d2dc <_dl_fini>, stack_end=0xbffffa6c) at ../sysdeps/generic/libc-start.c:129(gdb)

0x10003fc <OSTickISR+72>: ldmia sp!, {r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12, pc}^End of assembler dump.

reakpoint 1, ARMul_CPSRAltered (state=0x8215f58) at armsupp.c:292292 if (state->prog32Sig == LOW)(gdb) where#0 ARMul_CPSRAltered (state=0x8215f58) at armsupp.c:292#1 0x08127812 in LoadSMult (state=0x8215f58, instr=3908935679, address=16793560, WBBase=16793616) at armemu.c:3544#2 0x08126336 in ARMul_Emulate32 (state=0x8215f58) at armemu.c:2512#3 0x08113927 in ARMul_DoInstr (state=0x8215f58) at arminit.c:252#4 0x08112a29 in sim_resume (sd=0x1, step=1, siggnal=0) at wrapper.c:184#5 0x080dae3f in gdbsim_wait (pid=-1, status=0xbffff3b0) at remote-sim.c:686#6 0x0808eb0f in wait_for_inferior () at infrun.c:1287#7 0x0808e99a in proceed (addr=4294967295, siggnal=TARGET_SIGNAL_DEFAULT, step=1) at infrun.c:1084#8 0x0808c72d in step_1 (skip_subroutines=1, single_inst=1, count_string=0x0) at infcmd.c:542#9 0x0808c532 in nexti_command (count_string=0x0, from_tty=1) at infcmd.c:454#10 0x080b75c1 in execute_command (p=0x81db652 "", from_tty=1) at top.c:1546#11 0x08095351 in command_handler (command=0x81db650 "ni") at event-top.c:515#12 0x080958cc in command_line_handler (rl=0x8222a18 "") at event-top.c:779#13 0x08156598 in rl_callback_read_char () at callback.c:122#14 0x08095232 in stdin_event_handler (error=0, client_data=0x0) at event-top.c:422#15 0x080ced34 in handle_file_event (event_file_desc=0) at event-loop.c:742#16 0x080ce814 in process_event () at event-loop.c:377#17 0x080ce859 in gdb_do_one_event (data=0x0) at event-loop.c:414#18 0x080b68bd in catch_errors (func=0x80ce830 <gdb_do_one_event>, args=0x0, errstring=0x8174920 "", mask=6)

Page 151: SkyEye分析报告 - huihoo.org  · Web viewSkyEye分析报告. skyeye/ 陈渝. chenyu/ chenyu@hpclab.cs.tsinghua.edu.cn 清华大学计算机

at top.c:615#19 0x080ce88c in start_event_loop () at event-loop.c:450#20 0x0806ccfa in captured_command_loop (data=0x0) at main.c:104#21 0x080b68bd in catch_errors (func=0x806cce0 <captured_command_loop>, args=0x0, errstring=0x8174920 "", mask=6) at top.c:615#22 0x0806d66b in captured_main (data=0xbffffa10) at main.c:755#23 0x080b68bd in catch_errors (func=0x806cd28 <captured_main>, args=0xbffffa10, errstring=0x8174920 "", mask=6) at top.c:615#24 0x0806d697 in main (argc=1, argv=0xbffffa84) at main.c:767#25 0x40322306 in __libc_start_main (main=0x806d670 <main>, argc=1, ubp_av=0xbffffa84, init=0x806bfd0 <_init>, fini=0x8160e20 <_fini>, rtld_fini=0x4000d2dc <_dl_fini>, stack_end=0xbffffa7c) at ../sysdeps/generic/libc-start.c:129(gdb)