(linenum→info "unix/slp.c:2238")

qemu/0.9.1/hw/max111x.c

    1: /*
    2:  * Maxim MAX1110/1111 ADC chip emulation.
    3:  *
    4:  * Copyright (c) 2006 Openedhand Ltd.
    5:  * Written by Andrzej Zaborowski <balrog@zabor.org>
    6:  *
    7:  * This code is licensed under the GNU GPLv2.
    8:  */
    9: 
   10: #include "hw.h"
   11: #include "i2c.h"
   12: 
   13: struct max111x_s {
   14:     qemu_irq interrupt;
   15:     uint8_t tb1, rb2, rb3;
   16:     int cycle;
   17: 
   18:     int input[8];
   19:     int inputs, com;
   20: };
   21: 
   22: /* Control-byte bitfields */
   23: #define CB_PD0          (1 << 0)
   24: #define CB_PD1          (1 << 1)
   25: #define CB_SGL          (1 << 2)
   26: #define CB_UNI          (1 << 3)
   27: #define CB_SEL0         (1 << 4)
   28: #define CB_SEL1         (1 << 5)
   29: #define CB_SEL2         (1 << 6)
   30: #define CB_START        (1 << 7)
   31: 
   32: #define CHANNEL_NUM(v, b0, b1, b2)      \
   33:                         ((((v) >> (2 + (b0))) & 4) | \
   34:                          (((v) >> (3 + (b1))) & 2) | \
   35:                          (((v) >> (4 + (b2))) & 1))
   36: 
   37: uint32_t max111x_read(void *opaque)
   38: {
   39:     struct max111x_s *s = (struct max111x_s *) opaque;
   40: 
   41:     if (!s->tb1)
   42:         return 0;
   43: 
   44:     switch (s->cycle ++) {
   45:     case 1:
   46:         return s->rb2;
   47:     case 2:
   48:         return s->rb3;
   49:     }
   50: 
   51:     return 0;
   52: }
   53: 
   54: /* Interpret a control-byte */
   55: void max111x_write(void *opaque, uint32_t value)
   56: {
   57:     struct max111x_s *s = (struct max111x_s *) opaque;
   58:     int measure, chan;
   59: 
   60:     /* Ignore the value if START bit is zero */
   61:     if (!(value & CB_START))
   62:         return;
   63: 
   64:     s->cycle = 0;
   65: 
   66:     if (!(value & CB_PD1)) {
   67:         s->tb1 = 0;
   68:         return;
   69:     }
   70: 
   71:     s->tb1 = value;
   72: 
   73:     if (s->inputs == 8)
   74:         chan = CHANNEL_NUM(value, 1, 0, 2);
   75:     else
   76:         chan = CHANNEL_NUM(value & ~CB_SEL0, 0, 1, 2);
   77: 
   78:     if (value & CB_SGL)
   79:         measure = s->input[chan] - s->com;
   80:     else
   81:         measure = s->input[chan] - s->input[chan ^ 1];
   82: 
   83:     if (!(value & CB_UNI))
   84:         measure ^= 0x80;
   85: 
   86:     s->rb2 = (measure >> 2) & 0x3f;
   87:     s->rb3 = (measure << 6) & 0xc0;
   88: 
   89:     if (s->interrupt)
   90:         qemu_irq_raise(s->interrupt);
   91: }
   92: 
   93: static void max111x_save(QEMUFile *f, void *opaque)
   94: {
   95:     struct max111x_s *s = (struct max111x_s *) opaque;
   96:     int i;
   97: 
   98:     qemu_put_8s(f, &s->tb1);
   99:     qemu_put_8s(f, &s->rb2);
  100:     qemu_put_8s(f, &s->rb3);
  101:     qemu_put_be32(f, s->inputs);
  102:     qemu_put_be32(f, s->com);
  103:     for (i = 0; i < s->inputs; i ++)
  104:         qemu_put_byte(f, s->input[i]);
  105: }
  106: 
  107: static int max111x_load(QEMUFile *f, void *opaque, int version_id)
  108: {
  109:     struct max111x_s *s = (struct max111x_s *) opaque;
  110:     int i;
  111: 
  112:     qemu_get_8s(f, &s->tb1);
  113:     qemu_get_8s(f, &s->rb2);
  114:     qemu_get_8s(f, &s->rb3);
  115:     if (s->inputs != qemu_get_be32(f))
  116:         return -EINVAL;
  117:     s->com = qemu_get_be32(f);
  118:     for (i = 0; i < s->inputs; i ++)
  119:         s->input[i] = qemu_get_byte(f);
  120: 
  121:     return 0;
  122: }
  123: 
  124: static int max111x_iid = 0;
  125: 
  126: static struct max111x_s *max111x_init(qemu_irq cb)
  127: {
  128:     struct max111x_s *s;
  129:     s = (struct max111x_s *)
  130:             qemu_mallocz(sizeof(struct max111x_s));
  131:     memset(s, 0, sizeof(struct max111x_s));
  132: 
  133:     s->interrupt = cb;
  134: 
  135:     /* TODO: add a user interface for setting these */
  136:     s->input[0] = 0xf0;
  137:     s->input[1] = 0xe0;
  138:     s->input[2] = 0xd0;
  139:     s->input[3] = 0xc0;
  140:     s->input[4] = 0xb0;
  141:     s->input[5] = 0xa0;
  142:     s->input[6] = 0x90;
  143:     s->input[7] = 0x80;
  144:     s->com = 0;
  145: 
  146:     register_savevm("max111x", max111x_iid ++, 0,
  147:                     max111x_save, max111x_load, s);
  148: 
  149:     return s;
  150: }
  151: 
  152: struct max111x_s *max1110_init(qemu_irq cb)
  153: {
  154:     struct max111x_s *s = max111x_init(cb);
  155:     s->inputs = 8;
  156:     return s;
  157: }
  158: 
  159: struct max111x_s *max1111_init(qemu_irq cb)
  160: {
  161:     struct max111x_s *s = max111x_init(cb);
  162:     s->inputs = 4;
  163:     return s;
  164: }
  165: 
  166: void max111x_set_input(struct max111x_s *s, int line, uint8_t value)
  167: {
  168:     if (line >= s->inputs) {
  169:         printf("%s: There's no input %i\n", __FUNCTION__, line);
  170:         return;
  171:     }
  172: 
  173:     s->input[line] = value;
  174: }
Syntax (Markdown)