Annotation of qemu/hw/grlib_apbuart.c, revision 1.1.1.4

1.1       root        1: /*
                      2:  * QEMU GRLIB APB UART Emulator
                      3:  *
                      4:  * Copyright (c) 2010-2011 AdaCore
                      5:  *
                      6:  * Permission is hereby granted, free of charge, to any person obtaining a copy
                      7:  * of this software and associated documentation files (the "Software"), to deal
                      8:  * in the Software without restriction, including without limitation the rights
                      9:  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
                     10:  * copies of the Software, and to permit persons to whom the Software is
                     11:  * furnished to do so, subject to the following conditions:
                     12:  *
                     13:  * The above copyright notice and this permission notice shall be included in
                     14:  * all copies or substantial portions of the Software.
                     15:  *
                     16:  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
                     17:  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
                     18:  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
                     19:  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
                     20:  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
                     21:  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
                     22:  * THE SOFTWARE.
                     23:  */
                     24: 
                     25: #include "sysbus.h"
                     26: #include "qemu-char.h"
                     27: 
                     28: #include "trace.h"
                     29: 
                     30: #define UART_REG_SIZE 20     /* Size of memory mapped registers */
                     31: 
                     32: /* UART status register fields */
                     33: #define UART_DATA_READY           (1 <<  0)
                     34: #define UART_TRANSMIT_SHIFT_EMPTY (1 <<  1)
                     35: #define UART_TRANSMIT_FIFO_EMPTY  (1 <<  2)
                     36: #define UART_BREAK_RECEIVED       (1 <<  3)
                     37: #define UART_OVERRUN              (1 <<  4)
                     38: #define UART_PARITY_ERROR         (1 <<  5)
                     39: #define UART_FRAMING_ERROR        (1 <<  6)
                     40: #define UART_TRANSMIT_FIFO_HALF   (1 <<  7)
                     41: #define UART_RECEIVE_FIFO_HALF    (1 <<  8)
                     42: #define UART_TRANSMIT_FIFO_FULL   (1 <<  9)
                     43: #define UART_RECEIVE_FIFO_FULL    (1 << 10)
                     44: 
                     45: /* UART control register fields */
                     46: #define UART_RECEIVE_ENABLE          (1 <<  0)
                     47: #define UART_TRANSMIT_ENABLE         (1 <<  1)
                     48: #define UART_RECEIVE_INTERRUPT       (1 <<  2)
                     49: #define UART_TRANSMIT_INTERRUPT      (1 <<  3)
                     50: #define UART_PARITY_SELECT           (1 <<  4)
                     51: #define UART_PARITY_ENABLE           (1 <<  5)
                     52: #define UART_FLOW_CONTROL            (1 <<  6)
                     53: #define UART_LOOPBACK                (1 <<  7)
                     54: #define UART_EXTERNAL_CLOCK          (1 <<  8)
                     55: #define UART_RECEIVE_FIFO_INTERRUPT  (1 <<  9)
                     56: #define UART_TRANSMIT_FIFO_INTERRUPT (1 << 10)
                     57: #define UART_FIFO_DEBUG_MODE         (1 << 11)
                     58: #define UART_OUTPUT_ENABLE           (1 << 12)
                     59: #define UART_FIFO_AVAILABLE          (1 << 31)
                     60: 
                     61: /* Memory mapped register offsets */
                     62: #define DATA_OFFSET       0x00
                     63: #define STATUS_OFFSET     0x04
                     64: #define CONTROL_OFFSET    0x08
                     65: #define SCALER_OFFSET     0x0C  /* not supported */
                     66: #define FIFO_DEBUG_OFFSET 0x10  /* not supported */
                     67: 
1.1.1.4 ! root       68: #define FIFO_LENGTH 1024
        !            69: 
1.1       root       70: typedef struct UART {
                     71:     SysBusDevice busdev;
1.1.1.4 ! root       72:     MemoryRegion iomem;
1.1       root       73:     qemu_irq irq;
                     74: 
                     75:     CharDriverState *chr;
                     76: 
                     77:     /* registers */
                     78:     uint32_t receive;
                     79:     uint32_t status;
                     80:     uint32_t control;
1.1.1.4 ! root       81: 
        !            82:     /* FIFO */
        !            83:     char buffer[FIFO_LENGTH];
        !            84:     int  len;
        !            85:     int  current;
1.1       root       86: } UART;
                     87: 
1.1.1.4 ! root       88: static int uart_data_to_read(UART *uart)
        !            89: {
        !            90:     return uart->current < uart->len;
        !            91: }
        !            92: 
        !            93: static char uart_pop(UART *uart)
        !            94: {
        !            95:     char ret;
        !            96: 
        !            97:     if (uart->len == 0) {
        !            98:         uart->status &= ~UART_DATA_READY;
        !            99:         return 0;
        !           100:     }
        !           101: 
        !           102:     ret = uart->buffer[uart->current++];
        !           103: 
        !           104:     if (uart->current >= uart->len) {
        !           105:         /* Flush */
        !           106:         uart->len     = 0;
        !           107:         uart->current = 0;
        !           108:     }
        !           109: 
        !           110:     if (!uart_data_to_read(uart)) {
        !           111:         uart->status &= ~UART_DATA_READY;
        !           112:     }
        !           113: 
        !           114:     return ret;
        !           115: }
        !           116: 
        !           117: static void uart_add_to_fifo(UART          *uart,
        !           118:                              const uint8_t *buffer,
        !           119:                              int            length)
        !           120: {
        !           121:     if (uart->len + length > FIFO_LENGTH) {
        !           122:         abort();
        !           123:     }
        !           124:     memcpy(uart->buffer + uart->len, buffer, length);
        !           125:     uart->len += length;
        !           126: }
        !           127: 
1.1       root      128: static int grlib_apbuart_can_receive(void *opaque)
                    129: {
                    130:     UART *uart = opaque;
                    131: 
1.1.1.4 ! root      132:     return FIFO_LENGTH - uart->len;
1.1       root      133: }
                    134: 
                    135: static void grlib_apbuart_receive(void *opaque, const uint8_t *buf, int size)
                    136: {
                    137:     UART *uart = opaque;
                    138: 
1.1.1.4 ! root      139:     uart_add_to_fifo(uart, buf, size);
        !           140: 
        !           141:     uart->status |= UART_DATA_READY;
1.1       root      142: 
                    143:     if (uart->control & UART_RECEIVE_INTERRUPT) {
                    144:         qemu_irq_pulse(uart->irq);
                    145:     }
                    146: }
                    147: 
                    148: static void grlib_apbuart_event(void *opaque, int event)
                    149: {
                    150:     trace_grlib_apbuart_event(event);
                    151: }
                    152: 
1.1.1.4 ! root      153: 
        !           154: static uint64_t grlib_apbuart_read(void *opaque, target_phys_addr_t addr,
        !           155:                                    unsigned size)
        !           156: {
        !           157:     UART     *uart = opaque;
        !           158: 
        !           159:     addr &= 0xff;
        !           160: 
        !           161:     /* Unit registers */
        !           162:     switch (addr) {
        !           163:     case DATA_OFFSET:
        !           164:     case DATA_OFFSET + 3:       /* when only one byte read */
        !           165:         return uart_pop(uart);
        !           166: 
        !           167:     case STATUS_OFFSET:
        !           168:         /* Read Only */
        !           169:         return uart->status;
        !           170: 
        !           171:     case CONTROL_OFFSET:
        !           172:         return uart->control;
        !           173: 
        !           174:     case SCALER_OFFSET:
        !           175:         /* Not supported */
        !           176:         return 0;
        !           177: 
        !           178:     default:
        !           179:         trace_grlib_apbuart_readl_unknown(addr);
        !           180:         return 0;
        !           181:     }
        !           182: }
        !           183: 
        !           184: static void grlib_apbuart_write(void *opaque, target_phys_addr_t addr,
        !           185:                                 uint64_t value, unsigned size)
1.1       root      186: {
                    187:     UART          *uart = opaque;
                    188:     unsigned char  c    = 0;
                    189: 
                    190:     addr &= 0xff;
                    191: 
                    192:     /* Unit registers */
                    193:     switch (addr) {
                    194:     case DATA_OFFSET:
1.1.1.4 ! root      195:     case DATA_OFFSET + 3:       /* When only one byte write */
1.1       root      196:         c = value & 0xFF;
1.1.1.3   root      197:         qemu_chr_fe_write(uart->chr, &c, 1);
1.1       root      198:         return;
                    199: 
                    200:     case STATUS_OFFSET:
                    201:         /* Read Only */
                    202:         return;
                    203: 
                    204:     case CONTROL_OFFSET:
1.1.1.4 ! root      205:         uart->control = value;
1.1       root      206:         return;
                    207: 
                    208:     case SCALER_OFFSET:
                    209:         /* Not supported */
                    210:         return;
                    211: 
                    212:     default:
                    213:         break;
                    214:     }
                    215: 
1.1.1.2   root      216:     trace_grlib_apbuart_writel_unknown(addr, value);
1.1       root      217: }
                    218: 
1.1.1.4 ! root      219: static const MemoryRegionOps grlib_apbuart_ops = {
        !           220:     .write      = grlib_apbuart_write,
        !           221:     .read       = grlib_apbuart_read,
        !           222:     .endianness = DEVICE_NATIVE_ENDIAN,
1.1       root      223: };
                    224: 
                    225: static int grlib_apbuart_init(SysBusDevice *dev)
                    226: {
1.1.1.4 ! root      227:     UART *uart = FROM_SYSBUS(typeof(*uart), dev);
1.1       root      228: 
                    229:     qemu_chr_add_handlers(uart->chr,
                    230:                           grlib_apbuart_can_receive,
                    231:                           grlib_apbuart_receive,
                    232:                           grlib_apbuart_event,
                    233:                           uart);
                    234: 
                    235:     sysbus_init_irq(dev, &uart->irq);
                    236: 
1.1.1.4 ! root      237:     memory_region_init_io(&uart->iomem, &grlib_apbuart_ops, uart,
        !           238:                           "uart", UART_REG_SIZE);
1.1       root      239: 
1.1.1.4 ! root      240:     sysbus_init_mmio(dev, &uart->iomem);
1.1       root      241: 
                    242:     return 0;
                    243: }
                    244: 
1.1.1.4 ! root      245: static Property grlib_gptimer_properties[] = {
        !           246:     DEFINE_PROP_CHR("chrdev", UART, chr),
        !           247:     DEFINE_PROP_END_OF_LIST(),
        !           248: };
        !           249: 
        !           250: static void grlib_gptimer_class_init(ObjectClass *klass, void *data)
        !           251: {
        !           252:     DeviceClass *dc = DEVICE_CLASS(klass);
        !           253:     SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
        !           254: 
        !           255:     k->init = grlib_apbuart_init;
        !           256:     dc->props = grlib_gptimer_properties;
        !           257: }
        !           258: 
        !           259: static TypeInfo grlib_gptimer_info = {
        !           260:     .name          = "grlib,apbuart",
        !           261:     .parent        = TYPE_SYS_BUS_DEVICE,
        !           262:     .instance_size = sizeof(UART),
        !           263:     .class_init    = grlib_gptimer_class_init,
1.1       root      264: };
                    265: 
1.1.1.4 ! root      266: static void grlib_gptimer_register_types(void)
1.1       root      267: {
1.1.1.4 ! root      268:     type_register_static(&grlib_gptimer_info);
1.1       root      269: }
                    270: 
1.1.1.4 ! root      271: type_init(grlib_gptimer_register_types)

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.