Annotation of qemu/roms/openbios/drivers/adb_bus.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  *
                      3:  * Open Hack'Ware BIOS ADB bus support, ported to OpenBIOS
                      4:  *
                      5:  *  Copyright (c) 2005 Jocelyn Mayer
                      6:  *  Copyright (c) 2005 Stefan Reinauer
                      7:  *
                      8:  *   This program is free software; you can redistribute it and/or
                      9:  *   modify it under the terms of the GNU General Public License V2
                     10:  *   as published by the Free Software Foundation
                     11:  *
                     12:  *   This program is distributed in the hope that it will be useful,
                     13:  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
                     14:  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     15:  *   GNU General Public License for more details.
                     16:  *
                     17:  *   You should have received a copy of the GNU General Public License
                     18:  *   along with this program; if not, write to the Free Software
                     19:  *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA
                     20:  */
                     21: 
                     22: #include "config.h"
                     23: #include "libopenbios/bindings.h"
                     24: #include "libc/vsprintf.h"
                     25: 
                     26: #include "adb_bus.h"
                     27: #include "adb_kbd.h"
                     28: #include "adb_mouse.h"
                     29: 
                     30: DECLARE_UNNAMED_NODE( adb, INSTALL_OPEN, sizeof(int));
                     31: 
                     32: static void
                     33: adb_initialize (int *idx)
                     34: {
                     35:        phandle_t ph=get_cur_dev();
                     36: 
                     37:        push_str("adb");
                     38:        fword("device-type");
                     39: 
                     40:        set_property(ph, "compatible", "adb", 4);
                     41:        set_int_property(ph, "#address-cells", 1);
                     42:        set_int_property(ph, "#size-cells", 0);
                     43: }
                     44: 
                     45: static void
                     46: adb_open(int *idx)
                     47: {
                     48:        RET(-1);
                     49: }
                     50: 
                     51: static void
                     52: adb_close(int *idx)
                     53: {
                     54: }
                     55: 
                     56: NODE_METHODS( adb ) = {
                     57:        { NULL,                 adb_initialize          },
                     58:        { "open",               adb_open                },
                     59:        { "close",              adb_close               },
                     60: };
                     61: 
                     62: adb_bus_t *adb_bus_new (void *host,
                     63:                         int (*req)(void *host, const uint8_t *snd_buf,
                     64:                                    int len, uint8_t *rcv_buf))
                     65: {
                     66:     adb_bus_t *new;
                     67: 
                     68:     new = malloc(sizeof(adb_bus_t));
                     69:     if (new == NULL)
                     70:         return NULL;
                     71:     new->host = host;
                     72:     new->req = req;
                     73: 
                     74:     return new;
                     75: }
                     76: 
                     77: /* Check and relocate all ADB devices as suggested in
                     78:  * ADB_manager Apple documentation
                     79:  */
                     80: 
                     81: int adb_bus_init (char *path, adb_bus_t *bus)
                     82: {
                     83:     char buf[64];
                     84:     uint8_t buffer[ADB_BUF_SIZE];
                     85:     uint8_t adb_addresses[16] =
                     86:         { 8, 9, 10, 11, 12, 13, 14, -1, -1, -1, -1, -1, -1, -1, 0, };
                     87:     adb_dev_t tmp_device, **cur;
                     88:     int address;
                     89:     int reloc = 0, next_free = 7;
                     90:     int keep;
                     91: 
                     92:     snprintf(buf, sizeof(buf), "%s/adb", path);
                     93:     REGISTER_NAMED_NODE( adb, buf);
                     94:     /* Reset the bus */
                     95:     // ADB_DPRINTF("\n");
                     96:     adb_reset(bus);
                     97:     cur = &bus->devices;
                     98:     memset(&tmp_device, 0, sizeof(adb_dev_t));
                     99:     tmp_device.bus = bus;
                    100:     for (address = 1; address < 8 && adb_addresses[reloc] > 0;) {
                    101:         if (address == ADB_RES) {
                    102:             /* Reserved */
                    103:             address++;
                    104:             continue;
                    105:         }
                    106:         //ADB_DPRINTF("Check device on ADB address %d\n", address);
                    107:         tmp_device.addr = address;
                    108:         switch (adb_reg_get(&tmp_device, 3, buffer)) {
                    109:         case 0:
                    110:             //ADB_DPRINTF("No device on ADB address %d\n", address);
                    111:             /* Register this address as free */
                    112:             if (adb_addresses[next_free] != 0)
                    113:                 adb_addresses[next_free++] = address;
                    114:             /* Check next ADB address */
                    115:             address++;
                    116:             break;
                    117:         case 2:
                    118:            /* One device answered :
                    119:             * make it available and relocate it to a free address
                    120:             */
                    121:             if (buffer[0] == ADB_CHADDR) {
                    122:                 /* device self test failed */
                    123:                 ADB_DPRINTF("device on ADB address %d self-test failed "
                    124:                             "%02x %02x %02x\n", address,
                    125:                             buffer[0], buffer[1], buffer[2]);
                    126:                 keep = 0;
                    127:             } else {
                    128:                 //ADB_DPRINTF("device on ADB address %d self-test OK\n",
                    129:                 //            address);
                    130:                 keep = 1;
                    131:             }
                    132:             ADB_DPRINTF("Relocate device on ADB address %d to %d (%d)\n",
                    133:                         address, adb_addresses[reloc], reloc);
                    134:             buffer[0] = ((buffer[0] & 0x40) & ~0x90) | adb_addresses[reloc];
                    135:             if (keep == 1)
                    136:                 buffer[0] |= 0x20;
                    137:             buffer[1] = ADB_CHADDR_NOCOLL;
                    138:             if (adb_reg_set(&tmp_device, 3, buffer, 2) < 0) {
                    139:                 ADB_DPRINTF("ADB device relocation failed\n");
                    140:                 return -1;
                    141:             }
                    142:             if (keep == 1) {
                    143:                 *cur = malloc(sizeof(adb_dev_t));
                    144:                 if (*cur == NULL) {
                    145:                     return -1;
                    146:                 }
                    147:                 (*cur)->type = address;
                    148:                 (*cur)->bus = bus;
                    149:                 (*cur)->addr = adb_addresses[reloc++];
                    150:                 /* Flush buffers */
                    151:                 adb_flush(*cur);
                    152:                 switch ((*cur)->type) {
                    153:                 case ADB_PROTECT:
                    154:                     ADB_DPRINTF("Found one protected device\n");
                    155:                     break;
                    156:                 case ADB_KEYBD:
                    157:                     ADB_DPRINTF("Found one keyboard on address %d\n", address);
                    158:                     adb_kbd_new(buf, *cur);
                    159:                     break;
                    160:                 case ADB_MOUSE:
                    161:                     ADB_DPRINTF("Found one mouse on address %d\n", address);
                    162:                     adb_mouse_new(buf, *cur);
                    163:                     break;
                    164:                 case ADB_ABS:
                    165:                     ADB_DPRINTF("Found one absolute positioning device\n");
                    166:                     break;
                    167:                 case ADB_MODEM:
                    168:                     ADB_DPRINTF("Found one modem\n");
                    169:                     break;
                    170:                 case ADB_RES:
                    171:                     ADB_DPRINTF("Found one ADB res device\n");
                    172:                     break;
                    173:                 case ADB_MISC:
                    174:                     ADB_DPRINTF("Found one ADB misc device\n");
                    175:                     break;
                    176:                 }
                    177:                 cur = &((*cur)->next);
                    178:             }
                    179:             break;
                    180:         case 1:
                    181:         case 3 ... 7:
                    182:             /* SHOULD NOT HAPPEN : register 3 is always two bytes long */
                    183:             ADB_DPRINTF("Invalid returned len for ADB register 3\n");
                    184:             return -1;
                    185:         case -1:
                    186:             /* ADB ERROR */
                    187:             ADB_DPRINTF("error gettting ADB register 3\n");
                    188:             return -1;
                    189:         }
                    190:     }
                    191: 
                    192:     return 0;
                    193: }
                    194: 
                    195: int adb_cmd (adb_dev_t *dev, uint8_t cmd, uint8_t reg,
                    196:              uint8_t *buf, int len)
                    197: {
                    198:     uint8_t adb_send[ADB_BUF_SIZE], adb_rcv[ADB_BUF_SIZE];
                    199: 
                    200:     //ADB_DPRINTF("cmd: %d reg: %d len: %d\n", cmd, reg, len);
                    201:     if (dev->bus == NULL || dev->bus->req == NULL) {
                    202:         ADB_DPRINTF("ERROR: invalid bus !\n");
                    203:        for (;;);
                    204:     }
                    205:     /* Sanity checks */
                    206:     if (cmd != ADB_LISTEN && len != 0) {
                    207:         /* No buffer transmitted but for LISTEN command */
                    208:         ADB_DPRINTF("in buffer for cmd %d\n", cmd);
                    209:         return -1;
                    210:     }
                    211:     if (cmd == ADB_LISTEN && ((len < 2 || len > 8) || buf == NULL)) {
                    212:         /* Need a buffer with a regular register size for LISTEN command */
                    213:         ADB_DPRINTF("no/invalid buffer for ADB_LISTEN (%d)\n", len);
                    214:         return -1;
                    215:     }
                    216:     if ((cmd == ADB_TALK || cmd == ADB_LISTEN) && reg > 3) {
                    217:         /* Need a valid register number for LISTEN and TALK commands */
                    218:         ADB_DPRINTF("invalid reg for TALK/LISTEN command (%d %d)\n", cmd, reg);
                    219:         return -1;
                    220:     }
                    221:     switch (cmd) {
                    222:     case ADB_SEND_RESET:
                    223:         adb_send[0] = ADB_SEND_RESET;
                    224:         break;
                    225:     case ADB_FLUSH:
                    226:         adb_send[0] = (dev->addr << 4) | ADB_FLUSH;
                    227:         break;
                    228:     case ADB_LISTEN:
                    229:         memcpy(adb_send + 1, buf, len);
                    230:         /* No break here */
                    231:     case ADB_TALK:
                    232:         adb_send[0] = (dev->addr << 4) | cmd | reg;
                    233:         break;
                    234:     }
                    235:     memset(adb_rcv, 0, ADB_BUF_SIZE);
                    236:     len = (*dev->bus->req)(dev->bus->host, adb_send, len + 1, adb_rcv);
                    237: #ifdef DEBUG_ADB
                    238:     //printk("%x %x %x %x\n", adb_rcv[0], adb_rcv[1], adb_rcv[2], adb_rcv[3]);
                    239: #endif
                    240:     switch (len) {
                    241:     case 0:
                    242:         /* No data */
                    243:         break;
                    244:     case 2 ... 8:
                    245:         /* Register transmitted */
                    246:         if (buf != NULL)
                    247:             memcpy(buf, adb_rcv, len);
                    248:         break;
                    249:     default:
                    250:         /* Should never happen */
                    251:         //ADB_DPRINTF("Cmd %d returned %d bytes !\n", cmd, len);
                    252:         return -1;
                    253:     }
                    254:     //ADB_DPRINTF("retlen: %d\n", len);
                    255: 
                    256:     return len;
                    257: }

unix.superglobalmegacorp.com

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