Subject: Changes for review
To: None <port-macppc@netbsd.org>
From: Allen Briggs <briggs@wasabisystems.com>
List: port-macppc
Date: 02/17/2003 10:44:07
--tNQTSEo8WG/FKZ8E
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
Hi,
I've added support for the O'Hare-based 2400/3400 batteries in apm(4)
for macppc. I have also made changes to force detection of an ADB
console keyboard on the later tibooks (do the new iBooks need this,
too?).
To make these changes, I added a couple of new functions to machdep.c--
one to initially probe the model name and compatibility list from open
firmware, and another to match a passed-in string against the compatible
list.
I would appreciate any comments on the changes.
Thanks,
-allen
--
Allen Briggs briggs@wasabisystems.com
Wasabi Systems, Inc. http://www.wasabisystems.com/
--tNQTSEo8WG/FKZ8E
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename=diffs
Index: include/macppc.h
===================================================================
--- /dev/null Mon Feb 17 05:04:46 2003
+++ include/macppc.h Mon Feb 17 05:31:21 2003
@@ -0,0 +1,17 @@
+/* $NetBSD$ */
+
+#ifndef _MACHINE_MACPPC_H_
+#define _MACHINE_MACPPC_H_
+
+/*
+ * XXX - provide vectors for platform-specific functions that can not
+ * be auto-detected or easily hooked in via normal OFW probes --
+ * like brightness control, volume control, sleep, etc.
+ */
+
+/*
+ * macppc-specific glue;
+ */
+int macppc_iscompatible(const char *);
+
+#endif /* _MACHINE_MACPPC_H_ */
Index: dev/pm_direct.c
===================================================================
RCS file: /cvsroot/src/sys/arch/macppc/dev/pm_direct.c,v
retrieving revision 1.19
diff -u -p -r1.19 pm_direct.c
--- dev/pm_direct.c 2002/06/18 05:22:51 1.19
+++ dev/pm_direct.c 2003/02/17 15:34:03
@@ -46,6 +46,7 @@
#include <machine/adbsys.h>
#include <machine/cpu.h>
+#include <machine/macppc.h>
#include <macppc/dev/adbvar.h>
#include <macppc/dev/pm_direct.h>
@@ -88,6 +89,11 @@ u_int pm_LCD_brightness = 0x0;
u_int pm_LCD_contrast = 0x0;
u_int pm_counter = 0; /* clock count */
+u_int pm_battery_type = 0;
+#define PM_BATTERY_2400 0x01
+#define PM_BATTERY_3400 0x02
+#define PM_BATTERY_SMART 0x03
+
/* these values shows that number of data returned after 'send' cmd is sent */
signed char pm_send_cmd_type[] = {
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -257,6 +263,22 @@ void
pm_setup_adb()
{
pmHardware = PM_HW_PB5XX; /* XXX */
+
+ /*
+ * This is pulled from Linux. Apparently the "Comet" and "Hooper"
+ * variants are distinguished by the magic value.
+ */
+ if (macppc_iscompatible("AAPL,3400/2400")) {
+ uint32_t *mach_id_ptr = (uint32_t *) mapiodev(0xf3000034, 4);
+
+ if (mach_id_ptr && ((*mach_id_ptr) & 0x20000000)) {
+ pm_battery_type = PM_BATTERY_2400;
+ } else {
+ pm_battery_type = PM_BATTERY_3400;
+ }
+ } else {
+ pm_battery_type = PM_BATTERY_SMART;
+ }
}
@@ -1269,40 +1291,124 @@ pm_eject_pcmcia(slot)
/*
* Thanks to Paul Mackerras and Fabio Riccardi's Linux implementation
* for a clear description of the PMU results.
+ *
+ * Thanks to Linux implementation of done_battery_state_ohare for
+ * information on handling ohare batteries in the [23]400.
*/
int
pm_battery_info(int battery, struct pmu_battery_info *info)
{
PMData p;
+ long vchgd_max, vchging_max, lmax;
+ long vmax, current, charge, pcharge, vb;
- p.command = PMU_SMART_BATTERY_STATE;
- p.num_data = 1;
+ switch (pm_battery_type) {
+ case PM_BATTERY_2400:
+ case PM_BATTERY_3400:
+ p.command = PMU_BATTERY_STATE;
+ p.num_data = 0;
+ break;
+ default:
+ p.command = PMU_SMART_BATTERY_STATE;
+ p.num_data = 1;
+ p.data[0] = battery + 1;
+ break;
+ }
p.s_buf = p.r_buf = p.data;
- p.data[0] = battery + 1;
pmgrop(&p);
+
+ switch (pm_battery_type) {
+ case PM_BATTERY_2400:
+ case PM_BATTERY_3400:
+ /*
+ * p.data[0] == flags
+ * 1 << 0 plugged in
+ * 1 << 1 charging
+ * 1 << 2 battery present
+ * 1 << 5 fully charged
+ * 1 << 6 pcharge reset
+ * 1 << 7 battery exists (?)
+ * p.data[1][2] == battery voltage
+ * p.data[3] == CPU temperature
+ * p.data[4] == battery temperature
+ * p.data[5] == current
+ * p.data[6][7] == pcharge
+ * Linux code attributes this information as
+ * --tkoba
+ * XXX -- it would be nice to get the temps out in
+ * envsys so they're user-visible, too. Don't
+ * know units or anything there.
+ */
+ info->flags = p.data[0];
+
+ /* If battery isn't present, zero result and go */
+ if (!(info->flags & PMU_PWR_BATT_PRESENT)) {
+ info->cur_charge = 0;
+ info->max_charge = 0;
+ info->draw = 0;
+ info->voltage = 0;
+ break;
+ }
- info->flags = p.data[1];
+ if (pm_battery_type == PM_BATTERY_2400) {
+ vchgd_max = 189;
+ vchging_max = 189; /* Linux has 213 ? */
+ } else {
+ vchgd_max = 330;
+ vchging_max = 330;
+ }
- switch (p.data[0]) {
- case 3:
- case 4:
- info->cur_charge = p.data[2];
- info->max_charge = p.data[3];
- info->draw = *((signed char *)&p.data[4]);
- info->voltage = p.data[5];
- break;
- case 5:
- info->cur_charge = ((p.data[2] << 8) | (p.data[3]));
- info->max_charge = ((p.data[4] << 8) | (p.data[5]));
- info->draw = *((signed short *)&p.data[6]);
- info->voltage = ((p.data[8] << 8) | (p.data[7]));
+ lmax = 6500;
+ vb = (p.data[1] << 8) | p.data[2];
+ info->voltage = (vb * 265 + 72665) / 10;
+ current = p.data[5];
+
+ vmax = vchgd_max;
+ if (!(info->flags & PMU_PWR_AC_PRESENT)) {
+ if (current > 200)
+ vb += ((current - 200) * 15) / 100;
+ } else if (info->flags & PMU_PWR_BATT_CHARGING) {
+ vb = (vb * 97) / 100;
+ vmax = vchging_max;
+ }
+ charge = (100 * vb) / vmax;
+ if (info->flags & PMU_PWR_PCHARGE_RESET) {
+ pcharge = (p.data[6] << 8) | p.data[7];
+ if (pcharge > lmax)
+ pcharge = lmax;
+ pcharge = 100 - (pcharge * 100) / lmax;
+ if (pcharge < charge)
+ charge = pcharge;
+ }
+ info->cur_charge = charge;
+ info->draw = -current;
+ info->max_charge = 100;
break;
default:
- /* XXX - Error condition */
- info->cur_charge = 0;
- info->max_charge = 0;
- info->draw = 0;
- info->voltage = 0;
+ info->flags = p.data[1];
+
+ switch (p.data[0]) {
+ case 3:
+ case 4:
+ info->cur_charge = p.data[2];
+ info->max_charge = p.data[3];
+ info->draw = *((signed char *)&p.data[4]);
+ info->voltage = p.data[5];
+ break;
+ case 5:
+ info->cur_charge = ((p.data[2] << 8) | (p.data[3]));
+ info->max_charge = ((p.data[4] << 8) | (p.data[5]));
+ info->draw = *((signed short *)&p.data[6]);
+ info->voltage = ((p.data[8] << 8) | (p.data[7]));
+ break;
+ default:
+ /* XXX - Error condition */
+ info->cur_charge = 0;
+ info->max_charge = 0;
+ info->draw = 0;
+ info->voltage = 0;
+ break;
+ }
break;
}
Index: dev/pm_direct.h
===================================================================
RCS file: /cvsroot/src/sys/arch/macppc/dev/pm_direct.h,v
retrieving revision 1.6
diff -u -p -r1.6 pm_direct.h
--- dev/pm_direct.h 2002/06/18 05:22:51 1.6
+++ dev/pm_direct.h 2003/02/17 15:34:03
@@ -89,6 +89,7 @@ void pm_eject_pcmcia __P((int));
#define PMU_POWER_EVENTS 0x8f /* Send power-event commands to PMU */
#define PMU_SYSTEM_READY 0xdf /* tell PMU we are awake */
+#define PMU_BATTERY_STATE 0x6b /* Read battery state (older pmacs) */
#define PMU_SMART_BATTERY_STATE 0x6f /* Read battery state */
/* Bits in PMU interrupt and interrupt mask bytes */
@@ -125,5 +126,7 @@ enum {
/* PMU Power Information */
#define PMU_PWR_AC_PRESENT (1 << 0)
+#define PMU_PWR_BATT_CHARGING (1 << 1)
#define PMU_PWR_BATT_PRESENT (1 << 2)
+#define PMU_PWR_PCHARGE_RESET (1 << 6)
Index: macppc/machdep.c
===================================================================
RCS file: /cvsroot/src/sys/arch/macppc/macppc/machdep.c,v
retrieving revision 1.124
diff -u -p -r1.124 machdep.c
--- macppc/machdep.c 2003/02/03 17:09:57 1.124
+++ macppc/machdep.c 2003/02/17 15:34:04
@@ -76,6 +76,7 @@
#include <machine/autoconf.h>
#include <machine/bat.h>
+#include <machine/macppc.h>
#include <machine/powerpc.h>
#include <machine/trap.h>
#include <machine/bus.h>
@@ -105,6 +106,10 @@ static int chosen;
struct pmap ofw_pmap;
int ofkbd_ihandle;
+static int macppc_forceadb = 0;
+static char macppc_compat[128];
+static int macppc_compat_len;
+
#ifdef DDB
void *startsym, *endsym;
#endif
@@ -122,6 +127,7 @@ int lcsplx(int);
int save_ofmap(struct ofw_translations *, int);
void restore_ofmap(struct ofw_translations *, int);
static void dumpsys(void);
+static void macppc_identify(void);
void
initppc(startkernel, endkernel, args)
@@ -167,8 +173,16 @@ initppc(startkernel, endkernel, args)
BOOT_FLAG(*args++, boothowto);
}
+ /*
+ * Really would kind of like to do this later, after pmap_bootstrap(),
+ * but we want to get default keyboard type, which we need for console
+ * initialization, and console initialization notes that it must be
+ * done before pmap_bootstrap().
+ */
+ macppc_identify();
+
/*
- * i386 port says, that this shouldn't be here,
+ * i386 port says that this shouldn't be here,
* but I really think the console should be initialized
* as early as possible.
*/
@@ -596,6 +610,20 @@ cninit_kd()
}
#endif
+ /*
+ * New firmware does not have any *-kbd-ihandle[s] methods.
+ * If we've set macppc_forceadb (in macppc_identify()),
+ * assume ADB; otherwise, assume USB.
+ */
+#if NAKBD > 0
+ if (macppc_forceadb) {
+ printf("console keyboard type: ADB\n");
+ stdin = akbd;
+ akbd_cnattach();
+ goto kbd_found;
+ }
+#endif
+
#if NUKBD > 0
/*
* XXX Old firmware does not have `usb-kbd-ihandles method. Assume
@@ -726,3 +754,48 @@ mp_save_vec_lwp(l)
}
#endif /* ALTIVEC */
#endif /* MULTIPROCESSOR */
+
+int
+macppc_iscompatible(const char *comp)
+{
+ char *str;
+ int len, l;
+
+ str = macppc_compat;
+ len = macppc_compat_len;
+ while (len > 0) {
+ if (strcmp(str, comp) == 0)
+ return 1;
+ l = strlen(str) + 1;
+ str += l;
+ len -= l;
+ }
+ return 0;
+}
+
+static void
+macppc_identify(void)
+{
+ char mod[32];
+ int devtree, modlen;
+
+ devtree = OF_peer(0);
+ modlen = OF_getprop(devtree, "model", mod, sizeof mod);
+ if (modlen >= sizeof mod) {
+ strcpy(mod, "no_fit");
+ }
+
+ macppc_compat_len = OF_getprop(devtree, "compatible",
+ macppc_compat, sizeof macppc_compat);
+ if (macppc_compat_len >= sizeof macppc_compat) {
+ strcpy(macppc_compat, "no_fit");
+ }
+
+ /*
+ * Newer PowerBooks have firmware without any obvious ADB/USB
+ * detection methods available.
+ */
+ if ( (strcmp(mod, "PowerBook3,4") == 0)
+ || (strcmp(mod, "PowerBook3,5") == 0))
+ macppc_forceadb = 1;
+}
--tNQTSEo8WG/FKZ8E--