Annotation of qemu/roms/openbios/drivers/adb_bus.c, revision 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.