146283Sdfr/* $NetBSD: adb.c,v 1.53 2009/11/01 01:51:35 snj Exp $ */ 246283Sdfr 398944Sobrien/* 498944Sobrien * Copyright (C) 1994 Bradley A. Grantham 546283Sdfr * All rights reserved. 698944Sobrien * 746283Sdfr * Redistribution and use in source and binary forms, with or without 898944Sobrien * modification, are permitted provided that the following conditions 998944Sobrien * are met: 1098944Sobrien * 1. Redistributions of source code must retain the above copyright 1198944Sobrien * notice, this list of conditions and the following disclaimer. 1246283Sdfr * 2. Redistributions in binary form must reproduce the above copyright 1398944Sobrien * notice, this list of conditions and the following disclaimer in the 1498944Sobrien * documentation and/or other materials provided with the distribution. 1598944Sobrien * 1698944Sobrien * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 1746283Sdfr * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 1898944Sobrien * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 1998944Sobrien * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 2098944Sobrien * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 2198944Sobrien * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2298944Sobrien * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2346283Sdfr * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2446283Sdfr * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 2546283Sdfr * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2646283Sdfr */ 2746283Sdfr 2846283Sdfr#include <sys/cdefs.h> 2946283Sdfr__KERNEL_RCSID(0, "$NetBSD: adb.c,v 1.53 2009/11/01 01:51:35 snj Exp $"); 3046283Sdfr 3146283Sdfr#include "opt_adb.h" 3246283Sdfr 3346283Sdfr#include <sys/param.h> 3446283Sdfr#include <sys/device.h> 3546283Sdfr#include <sys/fcntl.h> 3698944Sobrien#include <sys/poll.h> 3798944Sobrien#include <sys/select.h> 3898944Sobrien#include <sys/proc.h> 3998944Sobrien#include <sys/signalvar.h> 4046283Sdfr#include <sys/systm.h> 4146283Sdfr#include <sys/cpu.h> 4246283Sdfr#include <sys/intr.h> 4346283Sdfr 4446283Sdfr#include <machine/autoconf.h> 4546283Sdfr 4646283Sdfr#include <mac68k/mac68k/macrom.h> 4746283Sdfr#include <mac68k/dev/adbvar.h> 4846283Sdfr#include <mac68k/dev/akbdvar.h> 4946283Sdfr 5046283Sdfr#include "aed.h" /* ADB Event Device for compatibility */ 5198944Sobrien 5246283Sdfr/* 5346283Sdfr * Function declarations. 5446283Sdfr */ 5598944Sobrienstatic int adbmatch(device_t, cfdata_t, void *); 5646283Sdfrstatic void adbattach(device_t, device_t, void *); 5798944Sobrienstatic int adbprint(void *, const char *); 5898944Sobrienvoid adb_config_interrupts(device_t); 5998944Sobrien 6098944Sobrienextern void adb_jadbproc(void); 6146283Sdfr 6298944Sobrien/* 6346283Sdfr * Global variables. 6498944Sobrien */ 6546283Sdfrint adb_polling = 0; /* Are we polling? (Debugger mode) */ 6698944Sobrien#ifdef ADB_DEBUG 6798944Sobrienint adb_debug = 0; /* Output debugging messages */ 6846283Sdfr#endif /* ADB_DEBUG */ 6998944Sobrien 7046283Sdfrextern struct mac68k_machine_S mac68k_machine; 7198944Sobrienextern int adbHardware; 7246283Sdfrextern char *adbHardwareDescr[]; 7398944Sobrien 7446283Sdfr/* 7598944Sobrien * Driver definition. 7646283Sdfr */ 7798944SobrienCFATTACH_DECL_NEW(adb, 0, 7846283Sdfr adbmatch, adbattach, NULL, NULL); 7998944Sobrien 8046283Sdfrstatic int 8198944Sobrienadbmatch(device_t parent, cfdata_t cf, void *aux) 8246283Sdfr{ 8398944Sobrien static bool adb_matched; 8446283Sdfr 8598944Sobrien /* Allow only one instance. */ 8646283Sdfr if (adb_matched) 8798944Sobrien return (0); 8846283Sdfr 8998944Sobrien adb_matched = true; 9046283Sdfr return (1); 9146283Sdfr} 9246283Sdfr 9346283Sdfrstatic void 9446283Sdfradbattach(device_t parent, device_t self, void *aux) 9546283Sdfr{ 9646283Sdfr 9746283Sdfr adb_softintr_cookie = softint_establish(SOFTINT_SERIAL, 9846283Sdfr (void (*)(void *))adb_soft_intr, NULL); 9946283Sdfr printf("\n"); 10046283Sdfr 10146283Sdfr /* 10246283Sdfr * Defer configuration until interrupts are enabled. 10398944Sobrien */ 10498944Sobrien config_interrupts(self, adb_config_interrupts); 10598944Sobrien} 10698944Sobrien 10798944Sobrienvoid 10898944Sobrienadb_config_interrupts(device_t self) 10998944Sobrien{ 11098944Sobrien ADBDataBlock adbdata; 11198944Sobrien struct adb_attach_args aa_args; 11298944Sobrien int totaladbs; 11398944Sobrien int adbindex, adbaddr; 11498944Sobrien 11546283Sdfr printf("%s", self->dv_xname); 11646283Sdfr adb_polling = 1; 11798944Sobrien 11898944Sobrien#ifdef MRG_ADB 11998944Sobrien if (!mrg_romready()) { 12098944Sobrien printf(": no ROM ADB driver in this kernel for this machine\n"); 12198944Sobrien return; 12298944Sobrien } 12398944Sobrien 12498944Sobrien#ifdef ADB_DEBUG 12546283Sdfr if (adb_debug) 12646283Sdfr printf("adb: call mrg_initadbintr\n"); 12746283Sdfr#endif 128130803Smarcel 12998944Sobrien mrg_initadbintr(); /* Mac ROM Glue okay to do ROM intr */ 13046283Sdfr#ifdef ADB_DEBUG 13146283Sdfr if (adb_debug) 13246283Sdfr printf("adb: returned from mrg_initadbintr\n"); 13346283Sdfr#endif 13446283Sdfr 135130803Smarcel /* ADBReInit pre/post-processing */ 13646283Sdfr JADBProc = adb_jadbproc; 13746283Sdfr 13846283Sdfr /* Initialize ADB */ 13946283Sdfr#ifdef ADB_DEBUG 14046283Sdfr if (adb_debug) 141130803Smarcel printf("adb: calling ADBAlternateInit.\n"); 14246283Sdfr#endif 14346283Sdfr 14446283Sdfr printf(" (mrg)"); 14546283Sdfr ADBAlternateInit(); 14646283Sdfr#else 14746283Sdfr ADBReInit(); 148130803Smarcel printf(" (direct, %s)", adbHardwareDescr[adbHardware]); 14946283Sdfr#endif /* MRG_ADB */ 15046283Sdfr 15146283Sdfr#ifdef ADB_DEBUG 15246283Sdfr if (adb_debug) 15346283Sdfr printf("adb: done with ADBReInit\n"); 15446283Sdfr#endif 15598944Sobrien 15646283Sdfr totaladbs = CountADBs(); 15798944Sobrien 15898944Sobrien printf(": %d target%s\n", totaladbs, (totaladbs == 1) ? "" : "s"); 15998944Sobrien 16098944Sobrien#if NAED > 0 16198944Sobrien /* ADB event device for compatibility */ 16246283Sdfr aa_args.origaddr = 0; 16346283Sdfr aa_args.adbaddr = 0; 16446283Sdfr aa_args.handler_id = 0; 16546283Sdfr (void)config_found(self, &aa_args, adbprint); 16646283Sdfr#endif 167130803Smarcel 16846283Sdfr /* for each ADB device */ 16946283Sdfr for (adbindex = 1; adbindex <= totaladbs; adbindex++) { 17046283Sdfr /* Get the ADB information */ 17146283Sdfr adbaddr = GetIndADB(&adbdata, adbindex); 17246283Sdfr 17346283Sdfr aa_args.origaddr = (int)(adbdata.origADBAddr); 17446283Sdfr aa_args.adbaddr = adbaddr; 175130803Smarcel aa_args.handler_id = (int)(adbdata.devType); 17698944Sobrien 17746283Sdfr (void)config_found(self, &aa_args, adbprint); 17846283Sdfr } 17946283Sdfr adb_polling = 0; 18046283Sdfr} 181130803Smarcel 18246283Sdfr 18398944Sobrienint 18446283Sdfradbprint(void *args, const char *name) 18546283Sdfr{ 18646283Sdfr struct adb_attach_args *aa_args = (struct adb_attach_args *)args; 18746283Sdfr int rv = UNCONF; 18846283Sdfr 18946283Sdfr if (name) { /* no configured device matched */ 19046283Sdfr rv = UNSUPP; /* most ADB device types are unsupported */ 19146283Sdfr 19246283Sdfr /* print out what kind of ADB device we have found */ 19398944Sobrien aprint_normal("%s addr %d: ", name, aa_args->adbaddr); 19446283Sdfr switch(aa_args->origaddr) { 19546283Sdfr#ifdef DIAGNOSTIC 19646283Sdfr case 0: 19798944Sobrien aprint_normal("ADB event device"); 19898944Sobrien rv = UNCONF; 19998944Sobrien break; 20046283Sdfr case ADBADDR_SECURE: 20146283Sdfr aprint_normal("security dongle (%d)", 20246283Sdfr aa_args->handler_id); 20346283Sdfr break; 20446283Sdfr#endif 20598944Sobrien case ADBADDR_MAP: 20698944Sobrien aprint_normal("mapped device (%d)", 20798944Sobrien aa_args->handler_id); 20898944Sobrien rv = UNCONF; 20998944Sobrien break; 21098944Sobrien case ADBADDR_REL: 21198944Sobrien aprint_normal("relative positioning device (%d)", 21298944Sobrien aa_args->handler_id); 21398944Sobrien rv = UNCONF; 21498944Sobrien break; 21598944Sobrien#ifdef DIAGNOSTIC 21698944Sobrien case ADBADDR_ABS: 21798944Sobrien switch (aa_args->handler_id) { 21898944Sobrien case ADB_ARTPAD: 21998944Sobrien aprint_normal("WACOM ArtPad II"); 22046283Sdfr break; 22146283Sdfr default: 22298944Sobrien aprint_normal("absolute positioning device (%d)", 22398944Sobrien aa_args->handler_id); 22446283Sdfr break; 22546283Sdfr } 22646283Sdfr break; 22746283Sdfr case ADBADDR_DATATX: 22898944Sobrien aprint_normal("data transfer device (modem?) (%d)", 22946283Sdfr aa_args->handler_id); 23046283Sdfr break; 23146283Sdfr case ADBADDR_MISC: 23246283Sdfr switch (aa_args->handler_id) { 23346283Sdfr case ADB_POWERKEY: 23446283Sdfr aprint_normal("Sophisticated Circuits PowerKey"); 23546283Sdfr break; 23646283Sdfr default: 23746283Sdfr aprint_normal("misc. device (remote control?) (%d)", 23846283Sdfr aa_args->handler_id); 23946283Sdfr break; 24046283Sdfr } 24146283Sdfr break; 24246283Sdfr default: 24346283Sdfr aprint_normal("unknown type device, (handler %d)", 24446283Sdfr aa_args->handler_id); 24546283Sdfr break; 24698944Sobrien#endif /* DIAGNOSTIC */ 247130803Smarcel } 24846283Sdfr } else /* a device matched and was configured */ 24946283Sdfr aprint_normal(" addr %d: ", aa_args->adbaddr); 25098944Sobrien 25198944Sobrien return (rv); 25246283Sdfr} 25346283Sdfr 25446283Sdfr 255130803Smarcel/* 25646283Sdfr * adb_op_sync 25746283Sdfr * 25846283Sdfr * This routine does exactly what the adb_op routine does, except that after 25946283Sdfr * the adb_op is called, it waits until the return value is present before 260130803Smarcel * returning. 26146283Sdfr * 26246283Sdfr * NOTE: The user specified compRout is ignored, since this routine specifies 26346283Sdfr * it's own to adb_op, which is why you really called this in the first place 26446283Sdfr * anyway. 265130803Smarcel */ 26646283Sdfrint 26746283Sdfradb_op_sync(Ptr buffer, Ptr compRout, Ptr data, short command) 26846283Sdfr{ 26946283Sdfr int result; 270130803Smarcel volatile int flag = 0; 27146283Sdfr 27246283Sdfr result = ADBOp(buffer, (void *)adb_op_comprout, __UNVOLATILE(&flag), 27346283Sdfr command); /* send command */ 27446283Sdfr if (result == 0) { /* send ok? */ 275130803Smarcel adb_spin(&flag); 27646283Sdfr if (!flag) 27746283Sdfr result = -2; 27846283Sdfr } 27946283Sdfr 28046283Sdfr return result; 281130803Smarcel} 28246283Sdfr 28346283Sdfr/* 28446283Sdfr * adb_spin 28546283Sdfr * 28646283Sdfr * Implements a spin-wait with timeout to be used for synchronous 28746283Sdfr * operations on the ADB bus. 28846283Sdfr * 28946283Sdfr * Total time to wait is calculated as follows: 29046283Sdfr * - Tlt (stop to start time): 260 usec 29146283Sdfr * - start bit: 100 usec 292130803Smarcel * - up to 8 data bytes: 64 * 100 usec = 6400 usec 29346283Sdfr * - stop bit (with SRQ): 140 usec 29446283Sdfr * Total: 6900 usec 29546283Sdfr * 29646283Sdfr * This is the total time allowed by the specification. Any device that 29798944Sobrien * doesn't conform to this will fail to operate properly on some Apple 29898944Sobrien * systems. In spite of this we double the time to wait; Cuda-based 29946283Sdfr * systems apparently queue commands and allow the main CPU to continue 300130803Smarcel * processing (how radical!). To be safe, allow time for two complete 30146283Sdfr * ADB transactions to occur. 30246283Sdfr */ 30346283Sdfrvoid 30446283Sdfradb_spin(volatile int *fp) 30546283Sdfr{ 30646283Sdfr int tmout; 307130803Smarcel 30846283Sdfr for (tmout = 13800; *fp == 0 && tmout >= 10; tmout -= 10) 30946283Sdfr delay(10); 31046283Sdfr if (*fp == 0 && tmout > 0) 31146283Sdfr delay(tmout); 31246283Sdfr} 31346283Sdfr 31446283Sdfr 31546283Sdfr/* 31646283Sdfr * adb_op_comprout 31746283Sdfr * 31846283Sdfr * This function is used by the adb_op_sync routine so it knows when the 31998944Sobrien * function is done. 32046283Sdfr */ 32146283Sdfrvoid 32246283Sdfradb_op_comprout(void) 32346283Sdfr{ 32446283Sdfr __asm("movw #1,%a2@ | update flag value"); 32598944Sobrien} 32646283Sdfr