Date: Wed, 2 Nov 2011 17:01:44 +0100 From: Tamas Szakaly <sghctoma@gmail.com> To: freebsd-drivers@freebsd.org Subject: ThinkPad battery charge control Message-ID: <20111102160144.GA487@izebigyomicsoda.praudit.hu>
next in thread | raw e-mail | index | archive | help
Hi, Two weaks ago a conversation started at freebsd-mobile about battery charge limiting. During this weekend I had some time to look up the ThinkPad 770 Technical Reference Manual (http://support.lenovo.com/en_US/detail.page?LegacyDocID=PFAN-3tuQQD), the ThinkPad Power Manager for Windows XP, and the tp_smapi Linux driver (http://sourceforge.net/projects/tpctl/files/tp_smap). I managed to write a kernel module that exposes the ThinkPad SMAPI features via the following sysctls: - hw.thinkpad_smapi.batX.start_threshold: charge start threshold (0-100) - hw.thinkpad_smapi.batX.stop_threshold: charge stop threshold (0-100) - hw.thinkpad_smapi.batX.force_discharge: enable/disable force discharge (0,1) - hw.thinkpad_smapi.batX.inhibit_charge_minutes: inhibit charge for given minutes (0-65535) X can be 0 or 1. The module works OK, but I have very-very little experience with kernel programming (added some sysctls to psm.c to control TrackPoint behaviour a year ago), and I have some concerns about how this functionality should be implemented correctly: - Is the sysctl way OK? Or should I expose those features via ioctl or character device read/write functions? - To access SMAPI, one have to write two I/O ports, 0xb2 and 0x4f. My problem is the following: the code works without mapping/allocating those two I/O ports, but I think, they should be mapped/allocated nevertheless. Am I right? - I used the term map/allocate, because I don't know what function to use to achieve this. At first I was using bus_space_map/bus_space_unmap like this: bus_space_map(X86_BUS_SPACE_IO, port, 1, 0, &bsh1) bus_space_map(X86_BUS_SPACE_IO, SMAPI_PORT, 1, 0, &bsh2) ... bus_space_unmap(X86_BUS_SPACE_IO, bsh1, 1) bus_space_unmap(X86_BUS_SPACE_IO, bsh2, 2) But neither of the drivers I saw use this pair of functions. Every one of them uses bus_alloc_resource/bus_release_resource. So I tried those functions as well: in identify: bus_set_resource(child, SYS_RES_IOPORT, 0, port, 1); bus_set_resource(child, SYS_RES_IOPORT, 1, SMAPI_PORT, 1); in probe: if (bus_get_resource_start(dev, SYS_RES_IOPORT, 0) == 0) return(ENXIO); if (bus_get_resource_start(dev, SYS_RES_IOPORT, 1) == 0) return(ENXIO); in attach: sc->rid1 = 0; sc->res1 = bus_alloc_resource(dev, SYS_RES_IOPORT, &sc->rid1, port, port, 1, RF_ACTIVE); sc->rid2 = 1; sc->res2 = bus_alloc_resource(dev, SYS_RES_IOPORT, &sc->rid2, SMAPI_PORT, SMAPI_PORT, 1, RF_ACTIVE); But the allocation fails. devinfo -r tells me, that I/O port 0xb2 is already allocated by acpi. So I tried to make acpi my driver's parent: DRIVER_MODULE(thinkpad_smapi, acpi, ... After this the allocation works, devinfo -r tells, that 0xb2 and 0x4f is allocted by my driver. But when I unload the module, and try to load it again, it fails. Please note, that bus_release_resource is called upon unloading the module and devinfo -r shows that 0xb2 is allocated by acpi again. What am I doing wrong? Sorry for the overly-long mail, and the possibly newbie questions, but I have read lots of man(9) pages, mailing list threads, and sources of drivers, and I am still confused. Any help is well appreciated. Thank you in advance! Regards, sghctoma --
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20111102160144.GA487>