⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 slavio_serial.c.svn-base

📁 我们自己开发的一个OSEK操作系统!不知道可不可以?
💻 SVN-BASE
📖 第 1 页 / 共 2 页
字号:
/* * QEMU Sparc SLAVIO serial port emulation * * Copyright (c) 2003-2005 Fabrice Bellard * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */#include "hw.h"#include "sun4m.h"#include "qemu-char.h"#include "console.h"/* debug serial *///#define DEBUG_SERIAL/* debug keyboard *///#define DEBUG_KBD/* debug mouse *///#define DEBUG_MOUSE/* * This is the serial port, mouse and keyboard part of chip STP2001 * (Slave I/O), also produced as NCR89C105. See * http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/NCR89C105.txt * * The serial ports implement full AMD AM8530 or Zilog Z8530 chips, * mouse and keyboard ports don't implement all functions and they are * only asynchronous. There is no DMA. * *//* * Modifications: *  2006-Aug-10  Igor Kovalenko :   Renamed KBDQueue to SERIOQueue, implemented *                                  serial mouse queue. *                                  Implemented serial mouse protocol. */#ifdef DEBUG_SERIAL#define SER_DPRINTF(fmt, args...) \do { printf("SER: " fmt , ##args); } while (0)#else#define SER_DPRINTF(fmt, args...)#endif#ifdef DEBUG_KBD#define KBD_DPRINTF(fmt, args...) \do { printf("KBD: " fmt , ##args); } while (0)#else#define KBD_DPRINTF(fmt, args...)#endif#ifdef DEBUG_MOUSE#define MS_DPRINTF(fmt, args...) \do { printf("MSC: " fmt , ##args); } while (0)#else#define MS_DPRINTF(fmt, args...)#endiftypedef enum {    chn_a, chn_b,} chn_id_t;#define CHN_C(s) ((s)->chn == chn_b? 'b' : 'a')typedef enum {    ser, kbd, mouse,} chn_type_t;#define SERIO_QUEUE_SIZE 256typedef struct {    uint8_t data[SERIO_QUEUE_SIZE];    int rptr, wptr, count;} SERIOQueue;#define SERIAL_REGS 16typedef struct ChannelState {    qemu_irq irq;    int reg;    int rxint, txint, rxint_under_svc, txint_under_svc;    chn_id_t chn; // this channel, A (base+4) or B (base+0)    chn_type_t type;    struct ChannelState *otherchn;    uint8_t rx, tx, wregs[SERIAL_REGS], rregs[SERIAL_REGS];    SERIOQueue queue;    CharDriverState *chr;    int e0_mode, led_mode, caps_lock_mode, num_lock_mode;    int disabled;} ChannelState;struct SerialState {    struct ChannelState chn[2];};#define SERIAL_MAXADDR 7#define SERIAL_SIZE (SERIAL_MAXADDR + 1)#define SERIAL_CTRL 0#define SERIAL_DATA 1#define W_CMD     0#define CMD_PTR_MASK   0x07#define CMD_CMD_MASK   0x38#define CMD_HI         0x08#define CMD_CLR_TXINT  0x28#define CMD_CLR_IUS    0x38#define W_INTR    1#define INTR_INTALL    0x01#define INTR_TXINT     0x02#define INTR_RXMODEMSK 0x18#define INTR_RXINT1ST  0x08#define INTR_RXINTALL  0x10#define W_IVEC    2#define W_RXCTRL  3#define RXCTRL_RXEN    0x01#define W_TXCTRL1 4#define TXCTRL1_PAREN  0x01#define TXCTRL1_PAREV  0x02#define TXCTRL1_1STOP  0x04#define TXCTRL1_1HSTOP 0x08#define TXCTRL1_2STOP  0x0c#define TXCTRL1_STPMSK 0x0c#define TXCTRL1_CLK1X  0x00#define TXCTRL1_CLK16X 0x40#define TXCTRL1_CLK32X 0x80#define TXCTRL1_CLK64X 0xc0#define TXCTRL1_CLKMSK 0xc0#define W_TXCTRL2 5#define TXCTRL2_TXEN   0x08#define TXCTRL2_BITMSK 0x60#define TXCTRL2_5BITS  0x00#define TXCTRL2_7BITS  0x20#define TXCTRL2_6BITS  0x40#define TXCTRL2_8BITS  0x60#define W_SYNC1   6#define W_SYNC2   7#define W_TXBUF   8#define W_MINTR   9#define MINTR_STATUSHI 0x10#define MINTR_RST_MASK 0xc0#define MINTR_RST_B    0x40#define MINTR_RST_A    0x80#define MINTR_RST_ALL  0xc0#define W_MISC1  10#define W_CLOCK  11#define CLOCK_TRXC     0x08#define W_BRGLO  12#define W_BRGHI  13#define W_MISC2  14#define MISC2_PLLDIS   0x30#define W_EXTINT 15#define EXTINT_DCD     0x08#define EXTINT_SYNCINT 0x10#define EXTINT_CTSINT  0x20#define EXTINT_TXUNDRN 0x40#define EXTINT_BRKINT  0x80#define R_STATUS  0#define STATUS_RXAV    0x01#define STATUS_ZERO    0x02#define STATUS_TXEMPTY 0x04#define STATUS_DCD     0x08#define STATUS_SYNC    0x10#define STATUS_CTS     0x20#define STATUS_TXUNDRN 0x40#define STATUS_BRK     0x80#define R_SPEC    1#define SPEC_ALLSENT   0x01#define SPEC_BITS8     0x06#define R_IVEC    2#define IVEC_TXINTB    0x00#define IVEC_LONOINT   0x06#define IVEC_LORXINTA  0x0c#define IVEC_LORXINTB  0x04#define IVEC_LOTXINTA  0x08#define IVEC_HINOINT   0x60#define IVEC_HIRXINTA  0x30#define IVEC_HIRXINTB  0x20#define IVEC_HITXINTA  0x10#define R_INTR    3#define INTR_EXTINTB   0x01#define INTR_TXINTB    0x02#define INTR_RXINTB    0x04#define INTR_EXTINTA   0x08#define INTR_TXINTA    0x10#define INTR_RXINTA    0x20#define R_IPEN    4#define R_TXCTRL1 5#define R_TXCTRL2 6#define R_BC      7#define R_RXBUF   8#define R_RXCTRL  9#define R_MISC   10#define R_MISC1  11#define R_BRGLO  12#define R_BRGHI  13#define R_MISC1I 14#define R_EXTINT 15static void handle_kbd_command(ChannelState *s, int val);static int serial_can_receive(void *opaque);static void serial_receive_byte(ChannelState *s, int ch);static inline void set_txint(ChannelState *s);static void clear_queue(void *opaque){    ChannelState *s = opaque;    SERIOQueue *q = &s->queue;    q->rptr = q->wptr = q->count = 0;}static void put_queue(void *opaque, int b){    ChannelState *s = opaque;    SERIOQueue *q = &s->queue;    SER_DPRINTF("channel %c put: 0x%02x\n", CHN_C(s), b);    if (q->count >= SERIO_QUEUE_SIZE)        return;    q->data[q->wptr] = b;    if (++q->wptr == SERIO_QUEUE_SIZE)        q->wptr = 0;    q->count++;    serial_receive_byte(s, 0);}static uint32_t get_queue(void *opaque){    ChannelState *s = opaque;    SERIOQueue *q = &s->queue;    int val;    if (q->count == 0) {        return 0;    } else {        val = q->data[q->rptr];        if (++q->rptr == SERIO_QUEUE_SIZE)            q->rptr = 0;        q->count--;    }    SER_DPRINTF("channel %c get 0x%02x\n", CHN_C(s), val);    if (q->count > 0)        serial_receive_byte(s, 0);    return val;}static int slavio_serial_update_irq_chn(ChannelState *s){    if ((s->wregs[W_INTR] & INTR_INTALL) && // interrupts enabled        (((s->wregs[W_INTR] & INTR_TXINT) && s->txint == 1) ||         // tx ints enabled, pending         ((((s->wregs[W_INTR] & INTR_RXMODEMSK) == INTR_RXINT1ST) ||           ((s->wregs[W_INTR] & INTR_RXMODEMSK) == INTR_RXINTALL)) &&          s->rxint == 1) || // rx ints enabled, pending         ((s->wregs[W_EXTINT] & EXTINT_BRKINT) &&          (s->rregs[R_STATUS] & STATUS_BRK)))) { // break int e&p        return 1;    }    return 0;}static void slavio_serial_update_irq(ChannelState *s){    int irq;    irq = slavio_serial_update_irq_chn(s);    irq |= slavio_serial_update_irq_chn(s->otherchn);    SER_DPRINTF("IRQ = %d\n", irq);    qemu_set_irq(s->irq, irq);}static void slavio_serial_reset_chn(ChannelState *s){    int i;    s->reg = 0;    for (i = 0; i < SERIAL_SIZE; i++) {        s->rregs[i] = 0;        s->wregs[i] = 0;    }    s->wregs[W_TXCTRL1] = TXCTRL1_1STOP; // 1X divisor, 1 stop bit, no parity    s->wregs[W_MINTR] = MINTR_RST_ALL;    s->wregs[W_CLOCK] = CLOCK_TRXC; // Synch mode tx clock = TRxC    s->wregs[W_MISC2] = MISC2_PLLDIS; // PLL disabled    s->wregs[W_EXTINT] = EXTINT_DCD | EXTINT_SYNCINT | EXTINT_CTSINT |        EXTINT_TXUNDRN | EXTINT_BRKINT; // Enable most interrupts    if (s->disabled)        s->rregs[R_STATUS] = STATUS_TXEMPTY | STATUS_DCD | STATUS_SYNC |            STATUS_CTS | STATUS_TXUNDRN;    else        s->rregs[R_STATUS] = STATUS_TXEMPTY | STATUS_TXUNDRN;    s->rregs[R_SPEC] = SPEC_BITS8 | SPEC_ALLSENT;    s->rx = s->tx = 0;    s->rxint = s->txint = 0;    s->rxint_under_svc = s->txint_under_svc = 0;    s->e0_mode = s->led_mode = s->caps_lock_mode = s->num_lock_mode = 0;    clear_queue(s);}static void slavio_serial_reset(void *opaque){    SerialState *s = opaque;    slavio_serial_reset_chn(&s->chn[0]);    slavio_serial_reset_chn(&s->chn[1]);}static inline void clr_rxint(ChannelState *s){    s->rxint = 0;    s->rxint_under_svc = 0;    if (s->chn == chn_a) {        if (s->wregs[W_MINTR] & MINTR_STATUSHI)            s->otherchn->rregs[R_IVEC] = IVEC_HINOINT;        else            s->otherchn->rregs[R_IVEC] = IVEC_LONOINT;        s->rregs[R_INTR] &= ~INTR_RXINTA;    } else {        if (s->wregs[W_MINTR] & MINTR_STATUSHI)            s->rregs[R_IVEC] = IVEC_HINOINT;        else            s->rregs[R_IVEC] = IVEC_LONOINT;        s->otherchn->rregs[R_INTR] &= ~INTR_RXINTB;    }    if (s->txint)        set_txint(s);    slavio_serial_update_irq(s);}static inline void set_rxint(ChannelState *s){    s->rxint = 1;    if (!s->txint_under_svc) {        s->rxint_under_svc = 1;        if (s->chn == chn_a) {            if (s->wregs[W_MINTR] & MINTR_STATUSHI)                s->otherchn->rregs[R_IVEC] = IVEC_HIRXINTA;            else                s->otherchn->rregs[R_IVEC] = IVEC_LORXINTA;        } else {            if (s->wregs[W_MINTR] & MINTR_STATUSHI)                s->rregs[R_IVEC] = IVEC_HIRXINTB;            else                s->rregs[R_IVEC] = IVEC_LORXINTB;        }    }    if (s->chn == chn_a)        s->rregs[R_INTR] |= INTR_RXINTA;    else        s->otherchn->rregs[R_INTR] |= INTR_RXINTB;    slavio_serial_update_irq(s);}static inline void clr_txint(ChannelState *s){    s->txint = 0;    s->txint_under_svc = 0;    if (s->chn == chn_a) {        if (s->wregs[W_MINTR] & MINTR_STATUSHI)            s->otherchn->rregs[R_IVEC] = IVEC_HINOINT;        else            s->otherchn->rregs[R_IVEC] = IVEC_LONOINT;        s->rregs[R_INTR] &= ~INTR_TXINTA;    } else {        if (s->wregs[W_MINTR] & MINTR_STATUSHI)            s->rregs[R_IVEC] = IVEC_HINOINT;        else            s->rregs[R_IVEC] = IVEC_LONOINT;        s->otherchn->rregs[R_INTR] &= ~INTR_TXINTB;    }    if (s->rxint)        set_rxint(s);    slavio_serial_update_irq(s);}static inline void set_txint(ChannelState *s){    s->txint = 1;    if (!s->rxint_under_svc) {        s->txint_under_svc = 1;        if (s->chn == chn_a) {            if (s->wregs[W_MINTR] & MINTR_STATUSHI)                s->otherchn->rregs[R_IVEC] = IVEC_HITXINTA;            else                s->otherchn->rregs[R_IVEC] = IVEC_LOTXINTA;        } else {            s->rregs[R_IVEC] = IVEC_TXINTB;        }    }    if (s->chn == chn_a)        s->rregs[R_INTR] |= INTR_TXINTA;    else        s->otherchn->rregs[R_INTR] |= INTR_TXINTB;    slavio_serial_update_irq(s);}static void slavio_serial_update_parameters(ChannelState *s){    int speed, parity, data_bits, stop_bits;    QEMUSerialSetParams ssp;    if (!s->chr || s->type != ser)        return;    if (s->wregs[W_TXCTRL1] & TXCTRL1_PAREN) {        if (s->wregs[W_TXCTRL1] & TXCTRL1_PAREV)            parity = 'E';        else            parity = 'O';    } else {        parity = 'N';    }    if ((s->wregs[W_TXCTRL1] & TXCTRL1_STPMSK) == TXCTRL1_2STOP)        stop_bits = 2;    else        stop_bits = 1;    switch (s->wregs[W_TXCTRL2] & TXCTRL2_BITMSK) {    case TXCTRL2_5BITS:        data_bits = 5;        break;    case TXCTRL2_7BITS:        data_bits = 7;        break;    case TXCTRL2_6BITS:        data_bits = 6;        break;    default:    case TXCTRL2_8BITS:        data_bits = 8;        break;    }    speed = 2457600 / ((s->wregs[W_BRGLO] | (s->wregs[W_BRGHI] << 8)) + 2);    switch (s->wregs[W_TXCTRL1] & TXCTRL1_CLKMSK) {    case TXCTRL1_CLK1X:        break;    case TXCTRL1_CLK16X:        speed /= 16;        break;    case TXCTRL1_CLK32X:        speed /= 32;        break;    default:    case TXCTRL1_CLK64X:        speed /= 64;        break;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -