📄 plf_stub.c
字号:
//=============================================================================//// plf_stub.c//// Platform specific code for GDB stub support.////=============================================================================// - pjo, 28 sep 1999// - Copied ARM version for use with i386/pc.//####COPYRIGHTBEGIN####// // ------------------------------------------- // The contents of this file are subject to the Red Hat eCos Public License // Version 1.1 (the "License"); you may not use this file except in // compliance with the License. You may obtain a copy of the License at // http://www.redhat.com/ // // Software distributed under the License is distributed on an "AS IS" // basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the // License for the specific language governing rights and limitations under // the License. // // The Original Code is eCos - Embedded Configurable Operating System, // released September 30, 1998. // // The Initial Developer of the Original Code is Red Hat. // Portions created by Red Hat are // Copyright (C) 1998, 1999, 2000 Red Hat, Inc. // All Rights Reserved. // ------------------------------------------- // //####COPYRIGHTEND####//=============================================================================//#####DESCRIPTIONBEGIN####//// Author(s): gthomas (based on the old ARM/AEB hal_stub.c)// Contributors:gthomas, jskov, pjo, nickg// Date: 1999-02-15// Purpose: Platform specific code for GDB stub support.// //####DESCRIPTIONEND####////=============================================================================#include <pkgconf/hal.h>#ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS#include <cyg/hal/hal_stub.h>#include <cyg/hal/hal_io.h> // HAL IO macros#include <cyg/hal/hal_intr.h> // HAL interrupt macros#include <cyg/hal/plf_misc.h>#ifdef CYGPKG_IO_SERIAL#include <pkgconf/io_serial.h>#endif//-----------------------------------------------------------------------------// Serial definitions.// 38400, COM1#define CYG_DEVICE_SERIAL_RS232_BAUD_MSB 0#define CYG_DEVICE_SERIAL_RS232_BAUD_LSB 3// This is the base address of COM1.#define CYG_DEVICE_SERIAL_RS232_8250_BASE 0x3F8// Define the serial registers.#define CYG_DEVICE_SERIAL_RS232_8250_RBR \ (CYG_DEVICE_SERIAL_RS232_8250_BASE + 0x00) // receiver buffer register, read, dlab = 0#define CYG_DEVICE_SERIAL_RS232_8250_THR \ (CYG_DEVICE_SERIAL_RS232_8250_BASE + 0x00) // transmitter holding register, write, dlab = 0#define CYG_DEVICE_SERIAL_RS232_8250_DLL \ (CYG_DEVICE_SERIAL_RS232_8250_BASE + 0x00) // divisor latch (LS), read/write, dlab = 1#define CYG_DEVICE_SERIAL_RS232_8250_IER \ (CYG_DEVICE_SERIAL_RS232_8250_BASE + 0x01) // interrupt enable register, read/write, dlab = 0#define CYG_DEVICE_SERIAL_RS232_8250_DLM \ (CYG_DEVICE_SERIAL_RS232_8250_BASE + 0x01) // divisor latch (MS), read/write, dlab = 1#define CYG_DEVICE_SERIAL_RS232_8250_IIR \ (CYG_DEVICE_SERIAL_RS232_8250_BASE + 0x02) // interrupt identification register, read, dlab = 0#define CYG_DEVICE_SERIAL_RS232_8250_FCR \ (CYG_DEVICE_SERIAL_RS232_8250_BASE + 0x02) // fifo control register, write, dlab = 0#define CYG_DEVICE_SERIAL_RS232_8250_LCR \ (CYG_DEVICE_SERIAL_RS232_8250_BASE + 0x03) // line control register, read/write#define CYG_DEVICE_SERIAL_RS232_8250_MCR \ (CYG_DEVICE_SERIAL_RS232_8250_BASE + 0x4) // modem control register, read/write#define CYG_DEVICE_SERIAL_RS232_8250_LSR \ (CYG_DEVICE_SERIAL_RS232_8250_BASE + 0x5) // line status register, read#define CYG_DEVICE_SERIAL_RS232_8250_MSR \ (CYG_DEVICE_SERIAL_RS232_8250_BASE + 0x6) // modem status register, read# define CYGNUM_HAL_INTERRUPT_COM1 (4 + 32)// The interrupt enable register bits.#define SIO_IER_ERDAI 0x01 // enable received data available irq#define SIO_IER_ETHREI 0x02 // enable THR empty interrupt#define SIO_IER_ELSI 0x04 // enable receiver line status irq#define SIO_IER_EMSI 0x08 // enable modem status interrupt// The interrupt identification register bits.#define SIO_IIR_IP 0x01 // 0 if interrupt pending#define SIO_IIR_ID_MASK 0x0e // mask for interrupt ID bits// The line status register bits.#define SIO_LSR_DR 0x01 // data ready#define SIO_LSR_OE 0x02 // overrun error#define SIO_LSR_PE 0x04 // parity error#define SIO_LSR_FE 0x08 // framing error#define SIO_LSR_BI 0x10 // break interrupt#define SIO_LSR_THRE 0x20 // transmitter holding register empty#define SIO_LSR_TEMT 0x40 // transmitter register empty#define SIO_LSR_ERR 0x80 // any error condition// The modem status register bits.#define SIO_MSR_DCTS 0x01 // delta clear to send#define SIO_MSR_DDSR 0x02 // delta data set ready#define SIO_MSR_TERI 0x04 // trailing edge ring indicator#define SIO_MSR_DDCD 0x08 // delta data carrier detect#define SIO_MSR_CTS 0x10 // clear to send#define SIO_MSR_DSR 0x20 // data set ready#define SIO_MSR_RI 0x40 // ring indicator#define SIO_MSR_DCD 0x80 // data carrier detect// The line control register bits.#define SIO_LCR_WLS0 0x01 // word length select bit 0#define SIO_LCR_WLS1 0x02 // word length select bit 1#define SIO_LCR_STB 0x04 // number of stop bits#define SIO_LCR_PEN 0x08 // parity enable#define SIO_LCR_EPS 0x10 // even parity select#define SIO_LCR_SP 0x20 // stick parity#define SIO_LCR_SB 0x40 // set break#define SIO_LCR_DLAB 0x80 // divisor latch access bit// Interrupt Enable Register#define SIO_IER_RCV 0x01#define SIO_IER_XMT 0x02#define SIO_IER_LS 0x04#define SIO_IER_MS 0x08// Modem Control Register#define SIO_MCR_DTR 0x01#define SIO_MCR_RTS 0x02#define SIO_MCR_INT 0x08 // Enable interrupts// FIFO control register#define SIO_FCR_FE 0x01#define SIO_FCR_RFR 0x02#define SIO_FCR_TFR 0x04#define SIO_FCR_ENABLE (SIO_FCR_FE | SIO_FCR_RFR | SIO_FCR_TFR)#define SIO_FCR_DISABLE (0)#if 0 //def CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORTstatic cyg_interrupt gdb_interrupt;static cyg_handle_t gdb_interrupt_handle;#endifvoid hal_screen_putc(int c);//-----------------------------------------------------------------------------#ifdef CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORTCYG_ADDRWORD hal_pc_break_pc = 0 ;// This ISR is called only for serial receive interrupts.int cyg_hal_gdb_isr(CYG_WORD32 vector, CYG_ADDRWORD data, CYG_ADDRWORD *regs){ CYG_BYTE c; cyg_uint8 lsr; // Check for a character. If it has already been taken // just return with nothing to do. lsr = pc_inb(CYG_DEVICE_SERIAL_RS232_8250_LSR); if ((lsr & SIO_LSR_DR) == 0) { // Ensure that the interrupt will not reoccur. HAL_INTERRUPT_ACKNOWLEDGE(CYGNUM_HAL_INTERRUPT_COM1); return 0; } c = hal_pc_get_char(); // Fetch the character if( 3 == c ) { // ^C // Ctrl-C: set a breakpoint at PC so GDB will display the // correct program context when stopping rather than the // interrupt handler. hal_pc_break_pc = regs[9] ; #if 1 cyg_hal_gdb_interrupt (hal_pc_break_pc);#else asm("movl %0, %%eax movl %%eax, %%dr0 movl %%dr7, %%eax andl $0xFFF0FFFC, %%eax orl $0x00000002, %%eax movl %%eax, %%dr7" : /* No outputs */ : "m" (hal_pc_break_pc) : "eax");#endif HAL_INTERRUPT_ACKNOWLEDGE(CYGNUM_HAL_INTERRUPT_COM1); } return 0; // No need to run DSR}int hal_pc_interruptable(int state){ if (state) { HAL_INTERRUPT_UNMASK(CYGNUM_HAL_INTERRUPT_COM1); } else { HAL_INTERRUPT_MASK(CYGNUM_HAL_INTERRUPT_COM1); } return 0;}#endif//-----------------------------------------------------------------------------// Initialize the current serial port.void hal_pc_init_serial(void){ cyg_uint8 lcr; // 8-1-no parity. pc_outb(CYG_DEVICE_SERIAL_RS232_8250_LCR, SIO_LCR_WLS0 | SIO_LCR_WLS1);// lcr = pc_inb(CYG_DEVICE_SERIAL_RS232_8250_LCR); lcr = 3 ; pc_outb(CYG_DEVICE_SERIAL_RS232_8250_LCR, lcr | SIO_LCR_DLAB); pc_outb(CYG_DEVICE_SERIAL_RS232_8250_DLL, CYG_DEVICE_SERIAL_RS232_BAUD_LSB); pc_outb(CYG_DEVICE_SERIAL_RS232_8250_DLM, CYG_DEVICE_SERIAL_RS232_BAUD_MSB); pc_outb(CYG_DEVICE_SERIAL_RS232_8250_LCR, lcr); // Maybe enable FIFOs... rumor has it that 16550 FIFOs don't work but that // 16550As do. pc_outb(CYG_DEVICE_SERIAL_RS232_8250_FCR, SIO_FCR_ENABLE) ; if ((pc_inb(CYG_DEVICE_SERIAL_RS232_8250_FCR) & 0xC0) != 0xC0) pc_outb(CYG_DEVICE_SERIAL_RS232_8250_FCR, SIO_FCR_DISABLE) ; #if defined(CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT) && !defined(CYGPKG_IO_SERIAL_I386_PC_SERIAL0)#if 0 cyg_drv_interrupt_create(CYGNUM_HAL_INTERRUPT_COM1, 99, // Priority - what goes here? 0, // Data item passed to interrupt handler (CYG_ADDRESS)cyg_hal_gdb_isr, 0, &gdb_interrupt_handle, &gdb_interrupt); cyg_drv_interrupt_attach(gdb_interrupt_handle); cyg_drv_interrupt_unmask(CYGNUM_HAL_INTERRUPT_COM1);#endif HAL_INTERRUPT_ATTACH( CYGNUM_HAL_INTERRUPT_COM1, cyg_hal_gdb_isr, 0, 0); HAL_INTERRUPT_UNMASK( CYGNUM_HAL_INTERRUPT_COM1 ); pc_outb(CYG_DEVICE_SERIAL_RS232_8250_IER, SIO_IER_RCV); pc_outb(CYG_DEVICE_SERIAL_RS232_8250_MCR, SIO_MCR_INT|SIO_MCR_DTR|SIO_MCR_RTS);#endif}short * screenPointer = (short*) 0xB8000 ;int screenPosition = 0 ;// Write C to the current serial port.void hal_pc_put_char(int c){ cyg_uint8 lsr; screenPointer[screenPosition++] = 0x0700 | (c & 0xFF) ; screenPosition %= (80 * 25) ; do { lsr = pc_inb(CYG_DEVICE_SERIAL_RS232_8250_LSR); } while ((lsr & SIO_LSR_THRE) == 0); pc_outb(CYG_DEVICE_SERIAL_RS232_8250_THR, c);}// Read one character from the current serial port.int hal_pc_get_char(void){ char c; cyg_uint8 lsr; do { lsr = pc_inb(CYG_DEVICE_SERIAL_RS232_8250_LSR); } while ((lsr & SIO_LSR_DR) == 0); c = pc_inb(CYG_DEVICE_SERIAL_RS232_8250_RBR); screenPointer[screenPosition++] = 0x7000 | (c & 0xFF) ; screenPosition %= (80 * 25) ; return c;}//-----------------------------------------------------------------------------// All of this is borrowed from gdb/i386-stub.c.int hal_pc_exception_handler(int vector, void * routine){ short * p = (short*) 0 ; int i = vector * 4 ; int r = (int) routine ; /* Construct an interrupt gate for the spec'd vector. */ p[i++] = (r & 0xFFFF) ; p[i++] = 8 ; p[i++] = 0x8E00 ; p[i++] = (r >> 16) ; return 0 ;}int hal_pc_trap_registers[NUMREGS] ;int hal_pc_trap_number ;int gdb_i386errcode;/* GDB stores segment registers in 32-bit words (that's just the way m-i386v.h is written). So zero the appropriate areas in registers. */#define SAVE_REGISTERS1() \ asm ("movl %eax, hal_pc_trap_registers"); \ asm ("movl %ecx, hal_pc_trap_registers+4"); \ asm ("movl %edx, hal_pc_trap_registers+8"); \ asm ("movl %ebx, hal_pc_trap_registers+12"); \ asm ("movl %ebp, hal_pc_trap_registers+20"); \ asm ("movl %esi, hal_pc_trap_registers+24"); \ asm ("movl %edi, hal_pc_trap_registers+28"); \ asm ("movw $0, %ax"); \ asm ("movw %ds, hal_pc_trap_registers+48"); \ asm ("movw %ax, hal_pc_trap_registers+50"); \ asm ("movw %es, hal_pc_trap_registers+52"); \ asm ("movw %ax, hal_pc_trap_registers+54"); \ asm ("movw %fs, hal_pc_trap_registers+56"); \ asm ("movw %ax, hal_pc_trap_registers+58"); \ asm ("movw %gs, hal_pc_trap_registers+60"); \ asm ("movw %ax, hal_pc_trap_registers+62");#define SAVE_ERRCODE() \ asm ("popl %ebx"); \ asm ("movl %ebx, gdb_i386errcode");#define SAVE_REGISTERS2() \ asm ("popl %ebx"); /* old eip */ \ asm ("movl %ebx, hal_pc_trap_registers+32"); \ asm ("popl %ebx"); /* old cs */ \ asm ("movl %ebx, hal_pc_trap_registers+40"); \ asm ("movw %ax, hal_pc_trap_registers+42"); \ asm ("popl %ebx"); /* old eflags */ \ asm ("movl %ebx, hal_pc_trap_registers+36"); \/* Now that we've done the pops, we can save the stack pointer. */ \ asm ("movw %ss, hal_pc_trap_registers+44"); \ asm ("movw %ax, hal_pc_trap_registers+46"); \ asm ("movl %esp, hal_pc_trap_registers+16");#define CALL_HOOK() \ asm("popl %eax; movl %eax, hal_pc_trap_number; call __handle_exception; jmp hal_pc_trap_exit")asm(".text");asm(".globl return_to_prog");asm("hal_pc_trap_exit:");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -