Index: stable/11/share/man/man4/Makefile =================================================================== --- stable/11/share/man/man4/Makefile (revision 359075) +++ stable/11/share/man/man4/Makefile (revision 359076) @@ -1,1020 +1,1021 @@ # @(#)Makefile 8.1 (Berkeley) 6/18/93 # $FreeBSD$ .include PACKAGE=runtime-manuals MAN= aac.4 \ aacraid.4 \ acpi.4 \ ${_acpi_asus.4} \ ${_acpi_asus_wmi.4} \ ${_acpi_dock.4} \ ${_acpi_fujitsu.4} \ ${_acpi_hp.4} \ ${_acpi_ibm.4} \ ${_acpi_panasonic.4} \ ${_acpi_rapidstart.4} \ ${_acpi_sony.4} \ acpi_thermal.4 \ + acpi_battery.4 \ ${_acpi_toshiba.4} \ acpi_video.4 \ ${_acpi_wmi.4} \ ada.4 \ adv.4 \ adw.4 \ ae.4 \ ${_aesni.4} \ age.4 \ agp.4 \ aha.4 \ ahb.4 \ ahc.4 \ ahci.4 \ ahd.4 \ ${_aibs.4} \ aio.4 \ alc.4 \ ale.4 \ alpm.4 \ altera_atse.4 \ altera_avgen.4 \ altera_jtag_uart.4 \ altera_sdcard.4 \ altq.4 \ amdpm.4 \ ${_amdsbwd.4} \ ${_amdsmb.4} \ ${_amdsmn.4} \ ${_amdtemp.4} \ ${_bxe.4} \ amr.4 \ an.4 \ ${_aout.4} \ ${_apic.4} \ arcmsr.4 \ ${_asmc.4} \ at45d.4 \ ata.4 \ ath.4 \ ath_ahb.4 \ ath_hal.4 \ ath_pci.4 \ atkbd.4 \ atkbdc.4 \ atp.4 \ ${_atf_test_case.4} \ ${_atrtc.4} \ ${_attimer.4} \ audit.4 \ auditpipe.4 \ aue.4 \ axe.4 \ axge.4 \ bce.4 \ bcma.4 \ bfe.4 \ bge.4 \ ${_bhyve.4} \ bhnd.4 \ bhndb.4 \ bktr.4 \ blackhole.4 \ bnxt.4 \ bpf.4 \ bridge.4 \ bt.4 \ bwi.4 \ bwn.4 \ ${_bytgpio.4} \ ${_chvgpio.4} \ capsicum.4 \ cardbus.4 \ carp.4 \ cas.4 \ cc_cdg.4 \ cc_chd.4 \ cc_cubic.4 \ cc_dctcp.4 \ cc_hd.4 \ cc_htcp.4 \ cc_newreno.4 \ cc_vegas.4 \ ${_ccd.4} \ ccr.4 \ cd.4 \ cdce.4 \ cfi.4 \ cfumass.4 \ ch.4 \ chromebook_platform.4 \ ciss.4 \ cloudabi.4 \ cm.4 \ cmx.4 \ ${_coretemp.4} \ ${_cpuctl.4} \ cpufreq.4 \ crypto.4 \ ctl.4 \ cue.4 \ cxgb.4 \ cxgbe.4 \ cxgbev.4 \ cy.4 \ cyapa.4 \ da.4 \ dc.4 \ dcons.4 \ dcons_crom.4 \ ddb.4 \ de.4 \ devctl.4 \ digi.4 \ disc.4 \ divert.4 \ ${_dpms.4} \ dpt.4 \ ds1307.4 \ ds3231.4 \ ${_dtrace_io.4} \ ${_dtrace_ip.4} \ ${_dtrace_proc.4} \ ${_dtrace_sched.4} \ ${_dtrace_tcp.4} \ ${_dtrace_udp.4} \ dummynet.4 \ ed.4 \ edsc.4 \ ehci.4 \ em.4 \ en.4 \ ena.4 \ enc.4 \ epair.4 \ esp.4 \ est.4 \ et.4 \ etherswitch.4 \ eventtimers.4 \ exca.4 \ fatm.4 \ fd.4 \ fdc.4 \ fdt.4 \ fdt_pinctrl.4 \ fdtbus.4 \ ffclock.4 \ filemon.4 \ firewire.4 \ fpa.4 \ full.4 \ fwe.4 \ fwip.4 \ fwohci.4 \ fxp.4 \ gbde.4 \ gdb.4 \ gem.4 \ geom.4 \ geom_fox.4 \ geom_linux_lvm.4 \ geom_map.4 \ geom_uzip.4 \ gif.4 \ gpio.4 \ gpioiic.4 \ gpioled.4 \ gre.4 \ h_ertt.4 \ hatm.4 \ hifn.4 \ hme.4 \ hpet.4 \ ${_hpt27xx.4} \ ${_hptiop.4} \ ${_hptmv.4} \ ${_hptnr.4} \ ${_hptrr.4} \ ${_hv_kvp.4} \ ${_hv_netvsc.4} \ ${_hv_storvsc.4} \ ${_hv_utils.4} \ ${_hv_vmbus.4} \ hv_vss.4 \ hwpmc.4 \ ichsmb.4 \ ${_ichwd.4} \ icmp.4 \ icmp6.4 \ ida.4 \ if_ipsec.4 \ ifmib.4 \ ig4.4 \ igb.4 \ igmp.4 \ iic.4 \ iicbb.4 \ iicbus.4 \ iicsmb.4 \ iir.4 \ ${_imcsmb.4} \ inet.4 \ inet6.4 \ intpm.4 \ intro.4 \ ${_io.4} \ ${_ioat.4} \ ip.4 \ ip6.4 \ ipfirewall.4 \ ipheth.4 \ ${_ipmi.4} \ ips.4 \ ipsec.4 \ ipw.4 \ ipwfw.4 \ isci.4 \ isl.4 \ ismt.4 \ isp.4 \ ispfw.4 \ iwi.4 \ iwifw.4 \ iwm.4 \ iwmfw.4 \ iwn.4 \ iwnfw.4 \ ixgb.4 \ ixgbe.4 \ ixl.4 \ ixlv.4 \ jedec_dimm.4 \ jedec_ts.4 \ jme.4 \ joy.4 \ kbdmux.4 \ keyboard.4 \ kld.4 \ ksyms.4 \ ktr.4 \ kue.4 \ lagg.4 \ le.4 \ led.4 \ lge.4 \ ${_linux.4} \ ${_liquidio.4} \ lm75.4 \ lmc.4 \ lo.4 \ lp.4 \ lpbb.4 \ lpt.4 \ mac.4 \ mac_biba.4 \ mac_bsdextended.4 \ mac_ifoff.4 \ mac_lomac.4 \ mac_mls.4 \ mac_none.4 \ mac_partition.4 \ mac_portacl.4 \ mac_seeotheruids.4 \ mac_stub.4 \ mac_test.4 \ malo.4 \ mcd.4 \ md.4 \ mdio.4 \ me.4 \ mem.4 \ meteor.4 \ mfi.4 \ miibus.4 \ mk48txx.4 \ mld.4 \ mlx.4 \ mlx4en.4 \ mlx5en.4 \ mly.4 \ mmc.4 \ mmcsd.4 \ mn.4 \ mod_cc.4 \ mos.4 \ mouse.4 \ mpr.4 \ mps.4 \ mpt.4 \ mrsas.4 \ msk.4 \ mtio.4 \ multicast.4 \ mvs.4 \ mwl.4 \ mwlfw.4 \ mx25l.4 \ mxge.4 \ my.4 \ nand.4 \ nandsim.4 \ natm.4 \ natmip.4 \ ncr.4 \ ncv.4 \ ${_ndis.4} \ net80211.4 \ netfpga10g_nf10bmac.4 \ netgraph.4 \ netintro.4 \ netmap.4 \ ${_nfe.4} \ ${_nfsmb.4} \ ng_async.4 \ ng_atm.4 \ ngatmbase.4 \ ng_atmllc.4 \ ng_bpf.4 \ ng_bridge.4 \ ng_bt3c.4 \ ng_btsocket.4 \ ng_car.4 \ ng_ccatm.4 \ ng_cisco.4 \ ng_deflate.4 \ ng_device.4 \ nge.4 \ ng_echo.4 \ ng_eiface.4 \ ng_etf.4 \ ng_ether.4 \ ng_ether_echo.4 \ ng_frame_relay.4 \ ng_gif.4 \ ng_gif_demux.4 \ ng_h4.4 \ ng_hci.4 \ ng_hole.4 \ ng_hub.4 \ ng_iface.4 \ ng_ipfw.4 \ ng_ip_input.4 \ ng_ksocket.4 \ ng_l2cap.4 \ ng_l2tp.4 \ ng_lmi.4 \ ng_mppc.4 \ ng_nat.4 \ ng_netflow.4 \ ng_one2many.4 \ ng_patch.4 \ ng_ppp.4 \ ng_pppoe.4 \ ng_pptpgre.4 \ ng_pred1.4 \ ng_rfc1490.4 \ ng_socket.4 \ ng_source.4 \ ng_split.4 \ ng_sppp.4 \ ng_sscfu.4 \ ng_sscop.4 \ ng_tag.4 \ ng_tcpmss.4 \ ng_tee.4 \ ng_tty.4 \ ng_ubt.4 \ ng_UI.4 \ ng_uni.4 \ ng_vjc.4 \ ng_vlan.4 \ nmdm.4 \ nsp.4 \ ${_ntb.4} \ ${_ntb_hw_intel.4} \ ${_ntb_hw_plx.4} \ ${_ntb_transport.4} \ ${_if_ntb.4} \ null.4 \ numa.4 \ ${_nvd.4} \ ${_nvme.4} \ ${_nvram.4} \ ${_nvram2env.4} \ ${_nxge.4} \ oce.4 \ ocs_fc.4\ ohci.4 \ orm.4 \ ow.4 \ ow_temp.4 \ owc.4 \ ${_padlock.4} \ pass.4 \ patm.4 \ pccard.4 \ pccbb.4 \ pcf.4 \ pci.4 \ pcib.4 \ pcic.4 \ pcm.4 \ pcn.4 \ ${_pf.4} \ ${_pflog.4} \ ${_pfsync.4} \ pim.4 \ pms.4 \ polling.4 \ ppbus.4 \ ppc.4 \ ppi.4 \ procdesc.4 \ proto.4 \ psm.4 \ pst.4 \ pt.4 \ pts.4 \ pty.4 \ puc.4 \ ${_qlxge.4} \ ${_qlxgb.4} \ ${_qlxgbe.4} \ ${_qlnxe.4} \ ral.4 \ random.4 \ rc.4 \ rctl.4 \ re.4 \ rgephy.4 \ rights.4 \ rl.4 \ rndtest.4 \ route.4 \ rp.4 \ rtwn.4 \ rtwnfw.4 \ rue.4 \ rum.4 \ run.4 \ runfw.4 \ sa.4 \ safe.4 \ sbp.4 \ sbp_targ.4 \ scc.4 \ scd.4 \ sched_4bsd.4 \ sched_ule.4 \ screen.4 \ scsi.4 \ sctp.4 \ sdhci.4 \ sem.4 \ send.4 \ ses.4 \ sf.4 \ ${_sfxge.4} \ sge.4 \ si.4 \ siba.4 \ siftr.4 \ siis.4 \ simplebus.4 \ sio.4 \ sis.4 \ sk.4 \ ${_smartpqi.4} \ smb.4 \ smbus.4 \ smp.4 \ smsc.4 \ sn.4 \ snd_ad1816.4 \ snd_als4000.4 \ snd_atiixp.4 \ snd_cmi.4 \ snd_cs4281.4 \ snd_csa.4 \ snd_ds1.4 \ snd_emu10k1.4 \ snd_emu10kx.4 \ snd_envy24.4 \ snd_envy24ht.4 \ snd_es137x.4 \ snd_ess.4 \ snd_fm801.4 \ snd_gusc.4 \ snd_hda.4 \ snd_hdspe.4 \ snd_ich.4 \ snd_maestro3.4 \ snd_maestro.4 \ snd_mss.4 \ snd_neomagic.4 \ snd_sbc.4 \ snd_solo.4 \ snd_spicds.4 \ snd_t4dwave.4 \ snd_uaudio.4 \ snd_via8233.4 \ snd_via82c686.4 \ snd_vibes.4 \ snp.4 \ spic.4 \ spigen.4 \ ${_spkr.4} \ splash.4 \ sppp.4 \ ste.4 \ stf.4 \ stg.4 \ stge.4 \ sym.4 \ syncache.4 \ syncer.4 \ syscons.4 \ sysmouse.4 \ tap.4 \ targ.4 \ tcp.4 \ tdfx.4 \ terasic_mtl.4 \ termios.4 \ textdump.4 \ ti.4 \ timecounters.4 \ tl.4 \ ${_tpm.4} \ trm.4 \ tty.4 \ tun.4 \ twa.4 \ twe.4 \ tws.4 \ tx.4 \ txp.4 \ udp.4 \ udplite.4 \ ure.4 \ vale.4 \ vga.4 \ vge.4 \ viapm.4 \ ${_viawd.4} \ ${_virtio.4} \ ${_virtio_balloon.4} \ ${_virtio_blk.4} \ ${_virtio_console.4} \ ${_virtio_random.4} \ ${_virtio_scsi.4} \ vkbd.4 \ vlan.4 \ vxlan.4 \ ${_vmx.4} \ vpo.4 \ vr.4 \ vt.4 \ vte.4 \ ${_vtnet.4} \ ${_vxge.4} \ watchdog.4 \ wb.4 \ ${_wbwd.4} \ wi.4 \ witness.4 \ wlan.4 \ wlan_acl.4 \ wlan_amrr.4 \ wlan_ccmp.4 \ wlan_tkip.4 \ wlan_wep.4 \ wlan_xauth.4 \ wmt.4 \ ${_wpi.4} \ wsp.4 \ xe.4 \ ${_xen.4} \ xhci.4 \ xl.4 \ ${_xnb.4} \ xpt.4 \ zero.4 \ zyd.4 MLINKS= ae.4 if_ae.4 MLINKS+=age.4 if_age.4 MLINKS+=agp.4 agpgart.4 MLINKS+=alc.4 if_alc.4 MLINKS+=ale.4 if_ale.4 MLINKS+=altera_atse.4 atse.4 MLINKS+=altera_sdcard.4 altera_sdcardc.4 MLINKS+=altq.4 ALTQ.4 MLINKS+=ath.4 if_ath.4 MLINKS+=ath_pci.4 if_ath_pci.4 MLINKS+=an.4 if_an.4 MLINKS+=aue.4 if_aue.4 MLINKS+=axe.4 if_axe.4 MLINKS+=bce.4 if_bce.4 MLINKS+=bfe.4 if_bfe.4 MLINKS+=bge.4 if_bge.4 MLINKS+=bktr.4 brooktree.4 MLINKS+=bnxt.4 if_bnxt.4 MLINKS+=bridge.4 if_bridge.4 MLINKS+=bwi.4 if_bwi.4 MLINKS+=bwn.4 if_bwn.4 MLINKS+=${_bxe.4} ${_if_bxe.4} MLINKS+=cas.4 if_cas.4 MLINKS+=cdce.4 if_cdce.4 MLINKS+=cfi.4 cfid.4 MLINKS+=cloudabi.4 cloudabi32.4 \ cloudabi.4 cloudabi64.4 MLINKS+=crypto.4 cryptodev.4 MLINKS+=cue.4 if_cue.4 MLINKS+=cxgb.4 if_cxgb.4 MLINKS+=cxgbe.4 if_cxgbe.4 \ cxgbe.4 vcxgbe.4 \ cxgbe.4 if_vcxgbe.4 \ cxgbe.4 cxl.4 \ cxgbe.4 if_cxl.4 \ cxgbe.4 vcxl.4 \ cxgbe.4 if_vcxl.4 \ cxgbe.4 cc.4 \ cxgbe.4 if_cc.4 \ cxgbe.4 vcc.4 \ cxgbe.4 if_vcc.4 MLINKS+=cxgbev.4 if_cxgbev.4 \ cxgbev.4 cxlv.4 \ cxgbev.4 if_cxlv.4 \ cxgbev.4 ccv.4 \ cxgbev.4 if_ccv.4 MLINKS+=dc.4 if_dc.4 MLINKS+=de.4 if_de.4 MLINKS+=disc.4 if_disc.4 MLINKS+=ed.4 if_ed.4 MLINKS+=edsc.4 if_edsc.4 MLINKS+=em.4 if_em.4 MLINKS+=en.4 if_en.4 MLINKS+=enc.4 if_enc.4 MLINKS+=epair.4 if_epair.4 MLINKS+=et.4 if_et.4 MLINKS+=fatm.4 if_fatm.4 MLINKS+=fd.4 stderr.4 \ fd.4 stdin.4 \ fd.4 stdout.4 MLINKS+=fdt.4 FDT.4 MLINKS+=firewire.4 ieee1394.4 MLINKS+=fpa.4 fea.4 MLINKS+=fwe.4 if_fwe.4 MLINKS+=fwip.4 if_fwip.4 MLINKS+=fxp.4 if_fxp.4 MLINKS+=gem.4 if_gem.4 MLINKS+=geom.4 GEOM.4 MLINKS+=gif.4 if_gif.4 MLINKS+=gpio.4 gpiobus.4 MLINKS+=gre.4 if_gre.4 MLINKS+=hatm.4 if_hatm.4 MLINKS+=hme.4 if_hme.4 MLINKS+=hpet.4 acpi_hpet.4 MLINKS+=${_hptrr.4} ${_rr232x.4} MLINKS+=${_attimer.4} ${_i8254.4} MLINKS+=igb.4 if_igb.4 MLINKS+=ip.4 rawip.4 MLINKS+=ipfirewall.4 ipaccounting.4 \ ipfirewall.4 ipacct.4 \ ipfirewall.4 ipfw.4 MLINKS+=ipheth.4 if_ipheth.4 MLINKS+=ipw.4 if_ipw.4 MLINKS+=iwi.4 if_iwi.4 MLINKS+=iwm.4 if_iwm.4 MLINKS+=iwn.4 if_iwn.4 MLINKS+=ixgb.4 if_ixgb.4 MLINKS+=ixgbe.4 ix.4 MLINKS+=ixgbe.4 if_ix.4 MLINKS+=ixgbe.4 if_ixgbe.4 MLINKS+=ixl.4 if_ixl.4 MLINKS+=ixlv.4 if_ixlv.4 MLINKS+=jme.4 if_jme.4 MLINKS+=kue.4 if_kue.4 MLINKS+=lagg.4 trunk.4 MLINKS+=lagg.4 if_lagg.4 MLINKS+=le.4 if_le.4 MLINKS+=lge.4 if_lge.4 MLINKS+=lmc.4 if_lmc.4 MLINKS+=lo.4 loop.4 MLINKS+=lp.4 plip.4 MLINKS+=malo.4 if_malo.4 MLINKS+=md.4 vn.4 MLINKS+=mem.4 kmem.4 MLINKS+=mfi.4 mfi_linux.4 \ mfi.4 mfip.4 MLINKS+=mlx5en.4 mce.4 MLINKS+=mn.4 if_mn.4 MLINKS+=mos.4 if_mos.4 MLINKS+=msk.4 if_msk.4 MLINKS+=mwl.4 if_mwl.4 MLINKS+=mxge.4 if_mxge.4 MLINKS+=my.4 if_my.4 MLINKS+=${_ndis.4} ${_if_ndis.4} MLINKS+=netfpga10g_nf10bmac.4 if_nf10bmac.4 MLINKS+=netintro.4 net.4 \ netintro.4 networking.4 MLINKS+=${_nfe.4} ${_if_nfe.4} MLINKS+=nge.4 if_nge.4 MLINKS+=${_nxge.4} ${_if_nxge.4} MLINKS+=ow.4 onewire.4 MLINKS+=patm.4 if_patm.4 MLINKS+=pccbb.4 cbb.4 MLINKS+=pcm.4 snd.4 \ pcm.4 sound.4 MLINKS+=pcn.4 if_pcn.4 MLINKS+=pms.4 pmspcv.4 MLINKS+=ral.4 if_ral.4 MLINKS+=re.4 if_re.4 MLINKS+=rl.4 if_rl.4 MLINKS+=rue.4 if_rue.4 MLINKS+=rum.4 if_rum.4 MLINKS+=run.4 if_run.4 MLINKS+=scsi.4 CAM.4 \ scsi.4 cam.4 \ scsi.4 scbus.4 \ scsi.4 SCSI.4 MLINKS+=sf.4 if_sf.4 MLINKS+=sge.4 if_sge.4 MLINKS+=sis.4 if_sis.4 MLINKS+=sk.4 if_sk.4 MLINKS+=smp.4 SMP.4 MLINKS+=smsc.4 if_smsc.4 MLINKS+=sn.4 if_sn.4 MLINKS+=snd_envy24.4 snd_ak452x.4 MLINKS+=snd_sbc.4 snd_sb16.4 \ snd_sbc.4 snd_sb8.4 MLINKS+=${_spkr.4} ${_speaker.4} MLINKS+=splash.4 screensaver.4 MLINKS+=ste.4 if_ste.4 MLINKS+=stf.4 if_stf.4 MLINKS+=stge.4 if_stge.4 MLINKS+=syncache.4 syncookies.4 MLINKS+=syscons.4 sc.4 MLINKS+=tap.4 if_tap.4 \ tap.4 vmnet.4 \ tap.4 if_vmnet.4 MLINKS+=tdfx.4 tdfx_linux.4 MLINKS+=ti.4 if_ti.4 MLINKS+=tl.4 if_tl.4 MLINKS+=tun.4 if_tun.4 MLINKS+=tx.4 if_tx.4 MLINKS+=txp.4 if_txp.4 MLINKS+=ure.4 if_ure.4 MLINKS+=vge.4 if_vge.4 MLINKS+=vlan.4 if_vlan.4 MLINKS+=vxlan.4 if_vxlan.4 MLINKS+=${_vmx.4} ${_if_vmx.4} MLINKS+=vpo.4 imm.4 MLINKS+=vr.4 if_vr.4 MLINKS+=vte.4 if_vte.4 MLINKS+=${_vtnet.4} ${_if_vtnet.4} MLINKS+=${_vxge.4} ${_if_vxge.4} MLINKS+=watchdog.4 SW_WATCHDOG.4 MLINKS+=wb.4 if_wb.4 MLINKS+=wi.4 if_wi.4 MLINKS+=${_wpi.4} ${_if_wpi.4} MLINKS+=xe.4 if_xe.4 MLINKS+=xl.4 if_xl.4 MLINKS+=zyd.4 if_zyd.4 .if ${MACHINE_CPUARCH} == "amd64" || ${MACHINE_CPUARCH} == "i386" _acpi_asus.4= acpi_asus.4 _acpi_asus_wmi.4= acpi_asus_wmi.4 _acpi_dock.4= acpi_dock.4 _acpi_fujitsu.4=acpi_fujitsu.4 _acpi_hp.4= acpi_hp.4 _acpi_ibm.4= acpi_ibm.4 _acpi_panasonic.4=acpi_panasonic.4 _acpi_rapidstart.4=acpi_rapidstart.4 _acpi_sony.4= acpi_sony.4 _acpi_toshiba.4=acpi_toshiba.4 _acpi_wmi.4= acpi_wmi.4 _aesni.4= aesni.4 _aout.4= aout.4 _apic.4= apic.4 _atrtc.4= atrtc.4 _attimer.4= attimer.4 _aibs.4= aibs.4 _amdsbwd.4= amdsbwd.4 _amdsmb.4= amdsmb.4 _amdsmn.4= amdsmn.4 _amdtemp.4= amdtemp.4 _asmc.4= asmc.4 _bxe.4= bxe.4 _bytgpio.4= bytgpio.4 _chvgpio.4= chvgpio.4 _coretemp.4= coretemp.4 _cpuctl.4= cpuctl.4 _dpms.4= dpms.4 _hpt27xx.4= hpt27xx.4 _hptiop.4= hptiop.4 _hptmv.4= hptmv.4 _hptnr.4= hptnr.4 _hptrr.4= hptrr.4 _hv_kvp.4= hv_kvp.4 _hv_netvsc.4= hv_netvsc.4 _hv_storvsc.4= hv_storvsc.4 _hv_utils.4= hv_utils.4 _hv_vmbus.4= hv_vmbus.4 _i8254.4= i8254.4 _ichwd.4= ichwd.4 _if_bxe.4= if_bxe.4 _if_ndis.4= if_ndis.4 _if_nfe.4= if_nfe.4 _if_nxge.4= if_nxge.4 _if_urtw.4= if_urtw.4 _if_vmx.4= if_vmx.4 _if_vtnet.4= if_vtnet.4 _if_vxge.4= if_vxge.4 _if_wpi.4= if_wpi.4 _imcsmb.4= imcsmb.4 _ipmi.4= ipmi.4 _io.4= io.4 _linux.4= linux.4 _liquidio.4= liquidio.4 _ndis.4= ndis.4 _nfe.4= nfe.4 _nfsmb.4= nfsmb.4 _nvd.4= nvd.4 _nvme.4= nvme.4 _nvram.4= nvram.4 _nxge.4= nxge.4 _padlock.4= padlock.4 _rr232x.4= rr232x.4 _speaker.4= speaker.4 _spkr.4= spkr.4 _tpm.4= tpm.4 _urtw.4= urtw.4 _viawd.4= viawd.4 _virtio.4= virtio.4 _virtio_balloon.4=virtio_balloon.4 _virtio_blk.4= virtio_blk.4 _virtio_console.4=virtio_console.4 _virtio_random.4= virtio_random.4 _virtio_scsi.4= virtio_scsi.4 _vmx.4= vmx.4 _vtnet.4= vtnet.4 _vxge.4= vxge.4 _wbwd.4= wbwd.4 _wpi.4= wpi.4 _xen.4= xen.4 _xnb.4= xnb.4 .endif .if ${MACHINE_CPUARCH} == "amd64" _if_ntb.4= if_ntb.4 _ioat.4= ioat.4 _ntb.4= ntb.4 _ntb_hw_intel.4= ntb_hw_intel.4 _ntb_hw_plx.4= ntb_hw_plx.4 _ntb_transport.4=ntb_transport.4 _qlxge.4= qlxge.4 _qlxgb.4= qlxgb.4 _qlxgbe.4= qlxgbe.4 _qlnxe.4= qlnxe.4 _sfxge.4= sfxge.4 _smartpqi.4= smartpqi.4 MLINKS+=qlxge.4 if_qlxge.4 MLINKS+=qlxgb.4 if_qlxgb.4 MLINKS+=qlxgbe.4 if_qlxgbe.4 MLINKS+=qlnxe.4 if_qlnxe.4 MLINKS+=sfxge.4 if_sfxge.4 .if ${MK_BHYVE} != "no" _bhyve.4= bhyve.4 .endif .endif .if ${MACHINE_CPUARCH} == "mips" _nvram2env.4= nvram2env.4 .endif .if exists(${.CURDIR}/man4.${MACHINE_CPUARCH}) SUBDIR= man4.${MACHINE_CPUARCH} .endif .if ${MK_BLUETOOTH} != "no" MAN+= ng_bluetooth.4 .endif .if ${MK_CCD} != "no" _ccd.4= ccd.4 .endif .if ${MK_CDDL} != "no" _dtrace_io.4= dtrace_io.4 _dtrace_ip.4= dtrace_ip.4 _dtrace_proc.4= dtrace_proc.4 _dtrace_sched.4= dtrace_sched.4 _dtrace_tcp.4= dtrace_tcp.4 _dtrace_udp.4= dtrace_udp.4 .endif .if ${MK_ISCSI} != "no" MAN+= cfiscsi.4 MAN+= iscsi.4 MAN+= iscsi_initiator.4 MAN+= iser.4 .endif .if ${MK_OFED} != "no" MAN+= mlx4ib.4 MAN+= mlx5ib.4 .endif .if ${MK_MLX5TOOL} != "no" MAN+= mlx5io.4 .endif .if ${MK_TESTS} != "no" ATF= ${.CURDIR}/../../../contrib/atf .PATH: ${ATF}/doc _atf_test_case.4= atf-test-case.4 .endif .if ${MK_PF} != "no" _pf.4= pf.4 _pflog.4= pflog.4 _pfsync.4= pfsync.4 .endif .if ${MK_USB} != "no" MAN+= \ otus.4 \ otusfw.4 \ rsu.4 \ rsufw.4 \ u3g.4 \ uark.4 \ uart.4 \ uath.4 \ ubsa.4 \ ubsec.4 \ ubser.4 \ ubtbcmfw.4 \ uchcom.4 \ ucom.4 \ ucycom.4 \ udav.4 \ udbp.4 \ udl.4 \ uep.4 \ ufm.4 \ ufoma.4 \ uftdi.4 \ ugen.4 \ ugold.4 \ uhci.4 \ uhid.4 \ uhso.4 \ uipaq.4 \ ukbd.4 \ uled.4 \ ulpt.4 \ umass.4 \ umcs.4 \ umct.4 \ umodem.4 \ umoscom.4 \ ums.4 \ unix.4 \ upgt.4 \ uplcom.4 \ ural.4 \ urio.4 \ urndis.4 \ ${_urtw.4} \ urtwn.4 \ urtwnfw.4 \ usb.4 \ usb_quirk.4 \ usb_template.4 \ usfs.4 \ uslcom.4 \ utopia.4 \ uvisor.4 \ uvscom.4 \ MLINKS+=otus.4 if_otus.4 MLINKS+=rsu.4 if_rsu.4 MLINKS+=u3g.4 u3gstub.4 MLINKS+=uath.4 if_uath.4 MLINKS+=udav.4 if_udav.4 MLINKS+=upgt.4 if_upgt.4 MLINKS+=ural.4 if_ural.4 MLINKS+=urndis.4 if_urndis.4 MLINKS+=${_urtw.4} ${_if_urtw.4} MLINKS+=urtwn.4 if_urtwn.4 .endif .include Index: stable/11/share/man/man4/acpi_battery.4 =================================================================== --- stable/11/share/man/man4/acpi_battery.4 (nonexistent) +++ stable/11/share/man/man4/acpi_battery.4 (revision 359076) @@ -0,0 +1,380 @@ +.\" +.\" Copyright (c) 2019 Takanori Watanabe +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $FreeBSD$ +.\" +.Dd February 16, 2020 +.Dt ACPI_BATTERY 4 +.Os +.Sh NAME +.Nm acpi_battery +.Nd ACPI battery management subsystem +.Sh SYNOPSIS +.Cd "device acpi" +.Sh DESCRIPTION +The +.Nm +is a driver for battery management features of the ACPI module. +.Pp +An ACPI-compatible battery device supports either a Control +Method Battery interface or a Smart Battery subsystem interface. +The former is accessed by the AML +.Pq ACPI Machine Language +code control methods, +and the latter is controlled directly through the ACPI EC +.Pq Embedded Controller +typically via an SMBus interface. +.Pp +This driver supports the +.Xr sysctl 8 +and +.Xr ioctl 2 +interfaces as well as the +.Xr devd 8 +event notification interface. +.Sh IOCTLS +Every ioctl for the +.Nm +driver takes a single integer value for the battery unit +number as an argument, +and returns a specific structure for each request. +A special unit number +.Dv ACPI_BATTERY_ALL_UNITS +specifies all of the attached units +and reports accumulated information. +.Bl -tag -width indent +.It Dv ACPIIO_BATT_GET_UNITS Vt int +Returns the number of battery units in the system. +The unit number argument will be ignored. +.It Dv ACPIIO_BATT_GET_BATTINFO Vt struct acpi_battinfo +Returns the following: +.Bl -tag -width indent +.It Va cap +Battery capacity in percent, +.It Va min +Remaining battery life in minutes, +.It Va state +Current status of the battery encoded in the following: +.Bl -tag -width indent +.It Dv ACPI_BATT_STAT_DISCHARG Pq 0x0001 +Battery is discharging, +.It Dv ACPI_BATT_STAT_CHARGING Pq 0x0002 +Battery is being charged, or +.It Dv ACPI_BATT_STAT_CRITICAL Pq 0x0004 +Remaining battery life is critically low. +.El +.Pp +Note that the status bits of each battery will be +consolidated when +.Dv ACPI_BATTERY_ALL_UNITS +is specified. +.It Va rate +Current battery discharging rate in mW. +.Li -1 +means not discharging right now. +.El +.It Dv ACPIIO_BATT_GET_BIX Vt struct acpi_bix +Returns battery information given by the ACPI +.Li _BIX Pq Battery Information +object, +which is the static portion of the Control Method +Battery information. +In the case of a Smart Battery attached to +SMBus or a Control Method Battery with a +.Li _BIF +object, +this ioctl will build a +.Vt struct acpi_bix +structure based on the obtained information +and return it. +.Bl -tag -width indent +.It Va rev +Revision number of the object. +There are the following well-known values: +.Bl -tag -width indent +.It Dv ACPI_BIX_REV_0 Pq 0x0000 +A +.Li _BIX +object in ACPI 4.0. +.It Dv ACPI_BIX_REV_1 Pq 0x0001 +A +.Li _BIX +object in ACPI 6.0. +.It Dv ACPI_BIX_REV_BIF Pq 0xffff +A +.Li _BIX +object built from the +.Li _BIF +object found on the system. +.El +.Pp +Note that this field should be checked by using +.Fn ACPI_BIX_REV_MIN_CHECK var rev +macro when checking the minimum revision number. +.It Va units +Indicates the units used by the battery to report its +capacity and charge rate encoded in the following: +.Bl -tag -width indent +.It ACPI_BIX_UNITS_MW Pq 0x00000000 +in mW +.Pq power +.It ACPI_BIX_UNITS_MA Pq 0x00000001 +in mA +.Pq current +.El +.Pp +Note that capacity is expressed in mWh or mAh, +and rate is expressed in mW or mA, +respectively. +.It Va dcap +The Battery's design capacity, +which is the nominal capacity of a new battery. +This is expressed as power or current depending on +the value of +.Va units . +.It Va lfcap +Predicted battery capacity when fully charged. +Typically this will decrease every charging cycle. +.It btech +Battery technology: +.Bl -tag -width indent +.It 0x00000000 Primary cell Pq non-rechargable +.It 0x00000001 Secondary cell Pq rechargable +.El +.It Va dvol +Design voltage in mV, +which is the nominal voltage of a new battery. +.It Va wcap +Design capacity of warning. +When a discharging battery device reaches this capacity, +notification is sent to the system. +.It Va lcap +Design capacity of low. +.It Va cycles +.Pq rev 0 or newer +The number of cycles the battery has experienced. +A cycle means an amount of discharge occurred which was +approximately equal to the value of Design Capacity. +.It Va accuracy +.Pq rev 0 or newer +The accuracy of the battery capacity measurement, +in thousandth of a percent. +.It Va stmax +.Pq rev 0 or newer +The Maximum Sampling Time of the battery in +milliseconds. +This is the maximum duration between two consecutive +measurements of the battery's capacities specified in +.Li _BST . +If two succeeding readings of +.Li _BST +beyond this duration occur, +two different results can be returned. +.It Va stmin +.Pq rev 0 or newer +The Minimum Sampling Time of the battery in +milliseconds. +.It Va aimax +.Pq rev 0 or newer +The Maximum Average Interval of the battery in +milliseconds. +This is the length of time within which the battery +averages the capacity measurements specified in +.Li _BST . +The Sampling Time specifies the frequency of measurements, +and the Average Interval specifies the width of the time +window of every measurement. +.It Va aimin +.Pq rev 0 or newer +The Minimum Average Interval of the battery in +milliseconds. +.It Va gra1 +Battery capacity granularity between +.Va low +and +.Va warning . +This is expressed as power or current depending on +the value of +.Va units . +.It Va gra2 +Battery capacity granularity between +.Va warning +and +.Va full . +This is expressed as power or current depending on +the value of +.Va units . +.It Va model +Model number of the battery as a string. +.It Va serial +Serial number of the battery as a string. +.It Va type +Type identifier of the battery as a string. +.It Va oeminfo +OEM-specific information of the battery as a string. +.It Va scap +.Pq rev 1 or newer +Battery swapping capability encoded in the following: +.Bl -tag -width indent +.It ACPI_BIX_SCAP_NO Pq 0x00000000 +Non-swappable +.It ACPI_BIX_SCAP_COLD Pq 0x00000001 +Cold-swappable +.It ACPI_BIX_SCAP_HOT Pq 0x00000010 +Hot-swappable +.El +.El +.It Dv ACPIIO_BATT_GET_BIF Vt struct acpi_bif +.Pq deprecated +Returns battery information given by the ACPI +.Li _BIF Pq Battery Information +object, +which was deprecated in ACPI 4.0 specification. +The data structure is a subset of +.Vt struct acpi_bix . +.Pp +Note that this ioctl will built a +.Vt struct acpi_bif +structure based on the obtained information +even if this object is not available and a +.Li _BIX +object is found. +.It ACPIIO_BATT_GET_BST Vt struct acpi_bst +Returns battery information given by the ACPI +.Li _BST Pq Battery Status +object, +which is the present battery status. +In the case of a Smart Battery attached to SMBus, +this ioctl will build a +.Vt struct acpi_bst +structure based on the obtained information +and return it. +.Bl -tag -width indent +.It Va state +Battery state. +The value is encoded in the same way as +.Va state +of +.Vt struct acpi_battinfo . +.It Va rate +Battery present rate of charging or discharging. +The unit of the value depends on +.Va unit +of +.Vt struct acpi_bif . +.It Va cap +Battery remaining capacity. +The unit of this value depends on +.Va unit +of +.Vt struct acpi_bif . +.It Va volt +Battery present voltage. +.El +.El +.Sh SYSCTL VARIABLES +The following +.Xr sysctl 8 +variables export battery status. +Note that they are accumulated status of all of the +connected batteries: +.Bl -tag -width indent +.It Va hw.acpi.battery.info_expire +Information cache expiration time in seconds. +The battery information obtained by +.Li _BIX +or +.Li _BIF +object will be stored and reused for successive +read access to this MIB within the specified period. +.It Va hw.acpi.battery.units +Number of battery units in the system. +.It Va hw.acpi.battery.state +Current battery charging status. +This is same as +.Va state +of +.Vt struct acpi_battinfo . +.It Va hw.acpi.battery.rate +Current battery discharging rate in mW. +.It Va hw.acpi.battery.time +Remaining battery life in minutes. +If the battery is not discharging, +the value shows +.Li -1 . +.It Va hw.acpi.battery.life +Battery capacity in percent. +.El +.Sh EVENT NOTIFICATIONS +Battery-related event notifications are sent +to the userland via the +.Xr devd 8 +interface. +See +.Pa /etc/devd.conf +and +.Xr devd.conf 5 +for more details. +Note that notifications are supported only by +the Control Method Battery. +.Pp +The +.Nm +driver sends events with the following attributes: +.Pp +.Bl -tag -width "subsystem" -compact +.It system +.Li ACPI +.It subsystem +.Li CMBAT +.It type +The fully qualified battery object path as in the ASL. +.It notify +An integer designating the event: +.Pp +.Bl -tag -width indent -compact +.It Li 0x80 +Battery status was changed. +.It Li 0x81 +Battery information was changed. +.El +.El +.Sh SEE ALSO +.Xr acpi 4 , +.Xr acpiconf 8 +.Sh AUTHORS +.An -nosplit +.An Nate Lawson Aq Mt njl@FreeBSD.org , +.An Munehiro Matsuda , +.An Takanori Watanabe Aq Mt takawata@FreeBSD.org , +.An Mitsuru IWASAKI Aq Mt iwasaki@FreeBSD.org , +.An Hans Petter Selasky Aq Mt hselasky@FreeBSD.org , +and +.An Hiroki Sato Aq Mt hrs@FreeBSD.org . +.Pp +This manual page was written by +.An Takanori Watanabe Aq Mt takawata@FreeBSD.org +and +.An Hiroki Sato Aq Mt hrs@FreeBSD.org . Property changes on: stable/11/share/man/man4/acpi_battery.4 ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: stable/11/sys/dev/acpica/acpi_battery.c =================================================================== --- stable/11/sys/dev/acpica/acpi_battery.c (revision 359075) +++ stable/11/sys/dev/acpica/acpi_battery.c (revision 359076) @@ -1,521 +1,541 @@ /*- * Copyright (c) 2005 Nate Lawson * Copyright (c) 2000 Mitsuru IWASAKI * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include "opt_acpi.h" #include #include #include #include #include #include #include #include #include /* Default seconds before re-sampling the battery state. */ #define ACPI_BATTERY_INFO_EXPIRE 5 -static int acpi_batteries_initted; +static int acpi_batteries_initialized; static int acpi_battery_info_expire = ACPI_BATTERY_INFO_EXPIRE; static struct acpi_battinfo acpi_battery_battinfo; static struct sysctl_ctx_list acpi_battery_sysctl_ctx; static struct sysctl_oid *acpi_battery_sysctl_tree; ACPI_SERIAL_DECL(battery, "ACPI generic battery"); static void acpi_reset_battinfo(struct acpi_battinfo *info); static void acpi_battery_clean_str(char *str, int len); static device_t acpi_battery_find_dev(u_int logical_unit); static int acpi_battery_ioctl(u_long cmd, caddr_t addr, void *arg); static int acpi_battery_sysctl(SYSCTL_HANDLER_ARGS); static int acpi_battery_units_sysctl(SYSCTL_HANDLER_ARGS); static int acpi_battery_init(void); int acpi_battery_register(device_t dev) { int error; - error = 0; ACPI_SERIAL_BEGIN(battery); - if (!acpi_batteries_initted) - error = acpi_battery_init(); + error = acpi_battery_init(); ACPI_SERIAL_END(battery); + return (error); } int acpi_battery_remove(device_t dev) { return (0); } int acpi_battery_get_units(void) { devclass_t batt_dc; batt_dc = devclass_find("battery"); if (batt_dc == NULL) return (0); return (devclass_get_count(batt_dc)); } int acpi_battery_get_info_expire(void) { return (acpi_battery_info_expire); } /* Check _BST results for validity. */ int acpi_battery_bst_valid(struct acpi_bst *bst) { return (bst->state != ACPI_BATT_STAT_NOT_PRESENT && bst->cap != ACPI_BATT_UNKNOWN && bst->volt != ACPI_BATT_UNKNOWN); } -/* Check _BIF results for validity. */ +/* Check _BI[FX] results for validity. */ int -acpi_battery_bif_valid(struct acpi_bif *bif) +acpi_battery_bix_valid(struct acpi_bix *bix) { - return (bif->lfcap != 0); + + return (bix->lfcap != 0); } /* Get info about one or all batteries. */ int acpi_battery_get_battinfo(device_t dev, struct acpi_battinfo *battinfo) { int batt_stat, devcount, dev_idx, error, i; int total_cap, total_lfcap, total_min, valid_rate, valid_units; devclass_t batt_dc; device_t batt_dev; struct acpi_bst *bst; - struct acpi_bif *bif; + struct acpi_bix *bix; struct acpi_battinfo *bi; /* * Get the battery devclass and max unit for battery devices. If there * are none or error, return immediately. */ batt_dc = devclass_find("battery"); if (batt_dc == NULL) return (ENXIO); devcount = devclass_get_maxunit(batt_dc); if (devcount == 0) return (ENXIO); /* * Allocate storage for all _BST data, their derived battinfo data, - * and the current battery's _BIF data. + * and the current battery's _BIX (or _BIF) data. */ bst = malloc(devcount * sizeof(*bst), M_TEMP, M_WAITOK | M_ZERO); bi = malloc(devcount * sizeof(*bi), M_TEMP, M_WAITOK | M_ZERO); - bif = malloc(sizeof(*bif), M_TEMP, M_WAITOK | M_ZERO); + bix = malloc(sizeof(*bix), M_TEMP, M_WAITOK | M_ZERO); /* * Pass 1: for each battery that is present and valid, get its status, * calculate percent capacity remaining, and sum all the current * discharge rates. */ dev_idx = -1; batt_stat = valid_rate = valid_units = 0; total_cap = total_lfcap = 0; for (i = 0; i < devcount; i++) { /* Default info for every battery is "not present". */ acpi_reset_battinfo(&bi[i]); /* * Find the device. Since devcount is in terms of max units, this * may be a sparse array so skip devices that aren't present. */ batt_dev = devclass_get_device(batt_dc, i); if (batt_dev == NULL) continue; /* If examining a specific battery and this is it, record its index. */ if (dev != NULL && dev == batt_dev) dev_idx = i; /* * Be sure we can get various info from the battery. Note that * acpi_BatteryIsPresent() is not enough because smart batteries only * return that the device is present. */ if (!acpi_BatteryIsPresent(batt_dev) || ACPI_BATT_GET_STATUS(batt_dev, &bst[i]) != 0 || - ACPI_BATT_GET_INFO(batt_dev, bif) != 0) + ACPI_BATT_GET_INFO(batt_dev, bix, sizeof(*bix)) != 0) continue; /* If a battery is not installed, we sometimes get strange values. */ if (!acpi_battery_bst_valid(&bst[i]) || - !acpi_battery_bif_valid(bif)) + !acpi_battery_bix_valid(bix)) continue; /* * Record current state. If both charging and discharging are set, * ignore the charging flag. */ valid_units++; if ((bst[i].state & ACPI_BATT_STAT_DISCHARG) != 0) bst[i].state &= ~ACPI_BATT_STAT_CHARGING; batt_stat |= bst[i].state; bi[i].state = bst[i].state; /* * If the battery info is in terms of mA, convert to mW by * multiplying by the design voltage. If the design voltage * is 0 (due to some error reading the battery), skip this * conversion. */ - if (bif->units == ACPI_BIF_UNITS_MA && bif->dvol != 0 && dev == NULL) { - bst[i].rate = (bst[i].rate * bif->dvol) / 1000; - bst[i].cap = (bst[i].cap * bif->dvol) / 1000; - bif->lfcap = (bif->lfcap * bif->dvol) / 1000; + if (bix->units == ACPI_BIX_UNITS_MA && bix->dvol != 0 && dev == NULL) { + bst[i].rate = (bst[i].rate * bix->dvol) / 1000; + bst[i].cap = (bst[i].cap * bix->dvol) / 1000; + bix->lfcap = (bix->lfcap * bix->dvol) / 1000; } /* - * The calculation above may set bif->lfcap to zero. This was + * The calculation above may set bix->lfcap to zero. This was * seen on a laptop with a broken battery. The result of the * division was rounded to zero. */ - if (!acpi_battery_bif_valid(bif)) + if (!acpi_battery_bix_valid(bix)) continue; /* * Some laptops report the "design-capacity" instead of the * "real-capacity" when the battery is fully charged. That breaks * the above arithmetic as it needs to be 100% maximum. */ - if (bst[i].cap > bif->lfcap) - bst[i].cap = bif->lfcap; + if (bst[i].cap > bix->lfcap) + bst[i].cap = bix->lfcap; /* Calculate percent capacity remaining. */ - bi[i].cap = (100 * bst[i].cap) / bif->lfcap; + bi[i].cap = (100 * bst[i].cap) / bix->lfcap; /* If this battery is not present, don't use its capacity. */ if (bi[i].cap != -1) { total_cap += bst[i].cap; - total_lfcap += bif->lfcap; + total_lfcap += bix->lfcap; } /* * On systems with more than one battery, they may get used * sequentially, thus bst.rate may only signify the one currently * in use. For the remaining batteries, bst.rate will be zero, * which makes it impossible to calculate the total remaining time. * Therefore, we sum the bst.rate for batteries in the discharging * state and use the sum to calculate the total remaining time. */ if (bst[i].rate != ACPI_BATT_UNKNOWN && (bst[i].state & ACPI_BATT_STAT_DISCHARG) != 0) valid_rate += bst[i].rate; } /* If the caller asked for a device but we didn't find it, error. */ if (dev != NULL && dev_idx == -1) { error = ENXIO; goto out; } /* Pass 2: calculate capacity and remaining time for all batteries. */ total_min = 0; for (i = 0; i < devcount; i++) { /* * If any batteries are discharging, use the sum of the bst.rate * values. Otherwise, we are on AC power, and there is infinite * time remaining for this battery until we go offline. */ if (valid_rate > 0) bi[i].min = (60 * bst[i].cap) / valid_rate; else bi[i].min = 0; total_min += bi[i].min; } /* * Return total battery percent and time remaining. If there are * no valid batteries, report values as unknown. */ if (valid_units > 0) { if (dev == NULL) { battinfo->cap = (total_cap * 100) / total_lfcap; battinfo->min = total_min; battinfo->state = batt_stat; battinfo->rate = valid_rate; } else { battinfo->cap = bi[dev_idx].cap; battinfo->min = bi[dev_idx].min; battinfo->state = bi[dev_idx].state; battinfo->rate = bst[dev_idx].rate; } /* * If the queried battery has no discharge rate or is charging, * report that we don't know the remaining time. */ if (valid_rate == 0 || (battinfo->state & ACPI_BATT_STAT_CHARGING)) battinfo->min = -1; } else acpi_reset_battinfo(battinfo); error = 0; out: - if (bi) - free(bi, M_TEMP); - if (bif) - free(bif, M_TEMP); - if (bst) - free(bst, M_TEMP); + free(bi, M_TEMP); + free(bix, M_TEMP); + free(bst, M_TEMP); return (error); } static void acpi_reset_battinfo(struct acpi_battinfo *info) { info->cap = -1; info->min = -1; info->state = ACPI_BATT_STAT_NOT_PRESENT; info->rate = -1; } /* Make string printable, removing invalid chars. */ static void acpi_battery_clean_str(char *str, int len) { int i; for (i = 0; i < len && *str != '\0'; i++, str++) { if (!isprint(*str)) *str = '?'; } /* NUL-terminate the string if we reached the end. */ if (i == len) *str = '\0'; } /* * The battery interface deals with devices and methods but userland * expects a logical unit number. Convert a logical unit to a device_t. */ static device_t acpi_battery_find_dev(u_int logical_unit) { int found_unit, i, maxunit; device_t dev; devclass_t batt_dc; dev = NULL; found_unit = 0; batt_dc = devclass_find("battery"); maxunit = devclass_get_maxunit(batt_dc); for (i = 0; i < maxunit; i++) { dev = devclass_get_device(batt_dc, i); if (dev == NULL) continue; if (logical_unit == found_unit) break; found_unit++; dev = NULL; } return (dev); } static int acpi_battery_ioctl(u_long cmd, caddr_t addr, void *arg) { union acpi_battery_ioctl_arg *ioctl_arg; int error, unit; device_t dev; /* For commands that use the ioctl_arg struct, validate it first. */ error = ENXIO; unit = 0; dev = NULL; ioctl_arg = NULL; - if (IOCPARM_LEN(cmd) == sizeof(*ioctl_arg)) { + if (IOCPARM_LEN(cmd) == sizeof(union acpi_battery_ioctl_arg) || + IOCPARM_LEN(cmd) == sizeof(union acpi_battery_ioctl_arg_v1)) { ioctl_arg = (union acpi_battery_ioctl_arg *)addr; unit = ioctl_arg->unit; if (unit != ACPI_BATTERY_ALL_UNITS) dev = acpi_battery_find_dev(unit); } /* * No security check required: information retrieval only. If * new functions are added here, a check might be required. */ + /* Unit check */ switch (cmd) { case ACPIIO_BATT_GET_UNITS: *(int *)addr = acpi_battery_get_units(); error = 0; break; case ACPIIO_BATT_GET_BATTINFO: + case ACPIIO_BATT_GET_BATTINFO_V1: if (dev != NULL || unit == ACPI_BATTERY_ALL_UNITS) { bzero(&ioctl_arg->battinfo, sizeof(ioctl_arg->battinfo)); error = acpi_battery_get_battinfo(dev, &ioctl_arg->battinfo); } break; case ACPIIO_BATT_GET_BIF: if (dev != NULL) { bzero(&ioctl_arg->bif, sizeof(ioctl_arg->bif)); - error = ACPI_BATT_GET_INFO(dev, &ioctl_arg->bif); - - /* - * Remove invalid characters. Perhaps this should be done - * within a convenience function so all callers get the - * benefit. - */ - acpi_battery_clean_str(ioctl_arg->bif.model, - sizeof(ioctl_arg->bif.model)); - acpi_battery_clean_str(ioctl_arg->bif.serial, - sizeof(ioctl_arg->bif.serial)); - acpi_battery_clean_str(ioctl_arg->bif.type, - sizeof(ioctl_arg->bif.type)); - acpi_battery_clean_str(ioctl_arg->bif.oeminfo, - sizeof(ioctl_arg->bif.oeminfo)); + error = ACPI_BATT_GET_INFO(dev, &ioctl_arg->bif, + sizeof(ioctl_arg->bif)); } break; + case ACPIIO_BATT_GET_BIX: + if (dev != NULL) { + bzero(&ioctl_arg->bix, sizeof(ioctl_arg->bix)); + error = ACPI_BATT_GET_INFO(dev, &ioctl_arg->bix, + sizeof(ioctl_arg->bix)); + } + break; case ACPIIO_BATT_GET_BST: + case ACPIIO_BATT_GET_BST_V1: if (dev != NULL) { bzero(&ioctl_arg->bst, sizeof(ioctl_arg->bst)); error = ACPI_BATT_GET_STATUS(dev, &ioctl_arg->bst); } break; default: error = EINVAL; } + /* Sanitize the string members. */ + switch (cmd) { + case ACPIIO_BATT_GET_BIX: + case ACPIIO_BATT_GET_BIF: + /* + * Remove invalid characters. Perhaps this should be done + * within a convenience function so all callers get the + * benefit. + */ + acpi_battery_clean_str(ioctl_arg->bix.model, + sizeof(ioctl_arg->bix.model)); + acpi_battery_clean_str(ioctl_arg->bix.serial, + sizeof(ioctl_arg->bix.serial)); + acpi_battery_clean_str(ioctl_arg->bix.type, + sizeof(ioctl_arg->bix.type)); + acpi_battery_clean_str(ioctl_arg->bix.oeminfo, + sizeof(ioctl_arg->bix.oeminfo)); + }; + return (error); } static int acpi_battery_sysctl(SYSCTL_HANDLER_ARGS) { int val, error; acpi_battery_get_battinfo(NULL, &acpi_battery_battinfo); val = *(u_int *)oidp->oid_arg1; error = sysctl_handle_int(oidp, &val, 0, req); return (error); } static int acpi_battery_units_sysctl(SYSCTL_HANDLER_ARGS) { int count, error; count = acpi_battery_get_units(); error = sysctl_handle_int(oidp, &count, 0, req); return (error); } static int acpi_battery_init(void) { struct acpi_softc *sc; device_t dev; int error; ACPI_SERIAL_ASSERT(battery); + if (acpi_batteries_initialized) + return(0); + error = ENXIO; dev = devclass_get_device(devclass_find("acpi"), 0); if (dev == NULL) goto out; sc = device_get_softc(dev); - error = acpi_register_ioctl(ACPIIO_BATT_GET_UNITS, acpi_battery_ioctl, - NULL); - if (error != 0) - goto out; - error = acpi_register_ioctl(ACPIIO_BATT_GET_BATTINFO, acpi_battery_ioctl, - NULL); - if (error != 0) - goto out; - error = acpi_register_ioctl(ACPIIO_BATT_GET_BIF, acpi_battery_ioctl, NULL); - if (error != 0) - goto out; - error = acpi_register_ioctl(ACPIIO_BATT_GET_BST, acpi_battery_ioctl, NULL); - if (error != 0) - goto out; +#define ACPI_REGISTER_IOCTL(a, b, c) do { \ + error = acpi_register_ioctl(a, b, c); \ + if (error) \ + goto out; \ + } while (0) + ACPI_REGISTER_IOCTL(ACPIIO_BATT_GET_UNITS, acpi_battery_ioctl, NULL); + ACPI_REGISTER_IOCTL(ACPIIO_BATT_GET_BATTINFO, acpi_battery_ioctl, NULL); + ACPI_REGISTER_IOCTL(ACPIIO_BATT_GET_BATTINFO_V1, acpi_battery_ioctl, NULL); + ACPI_REGISTER_IOCTL(ACPIIO_BATT_GET_BIF, acpi_battery_ioctl, NULL); + ACPI_REGISTER_IOCTL(ACPIIO_BATT_GET_BIX, acpi_battery_ioctl, NULL); + ACPI_REGISTER_IOCTL(ACPIIO_BATT_GET_BST, acpi_battery_ioctl, NULL); + ACPI_REGISTER_IOCTL(ACPIIO_BATT_GET_BST_V1, acpi_battery_ioctl, NULL); +#undef ACPI_REGISTER_IOCTL + sysctl_ctx_init(&acpi_battery_sysctl_ctx); acpi_battery_sysctl_tree = SYSCTL_ADD_NODE(&acpi_battery_sysctl_ctx, SYSCTL_CHILDREN(sc->acpi_sysctl_tree), OID_AUTO, "battery", CTLFLAG_RD, 0, "battery status and info"); SYSCTL_ADD_PROC(&acpi_battery_sysctl_ctx, SYSCTL_CHILDREN(acpi_battery_sysctl_tree), OID_AUTO, "life", CTLTYPE_INT | CTLFLAG_RD, &acpi_battery_battinfo.cap, 0, acpi_battery_sysctl, "I", "percent capacity remaining"); SYSCTL_ADD_PROC(&acpi_battery_sysctl_ctx, SYSCTL_CHILDREN(acpi_battery_sysctl_tree), OID_AUTO, "time", CTLTYPE_INT | CTLFLAG_RD, &acpi_battery_battinfo.min, 0, acpi_battery_sysctl, "I", "remaining time in minutes"); SYSCTL_ADD_PROC(&acpi_battery_sysctl_ctx, SYSCTL_CHILDREN(acpi_battery_sysctl_tree), OID_AUTO, "rate", CTLTYPE_INT | CTLFLAG_RD, &acpi_battery_battinfo.rate, 0, acpi_battery_sysctl, "I", "present rate in mW"); SYSCTL_ADD_PROC(&acpi_battery_sysctl_ctx, SYSCTL_CHILDREN(acpi_battery_sysctl_tree), OID_AUTO, "state", CTLTYPE_INT | CTLFLAG_RD, &acpi_battery_battinfo.state, 0, acpi_battery_sysctl, "I", "current status flags"); SYSCTL_ADD_PROC(&acpi_battery_sysctl_ctx, SYSCTL_CHILDREN(acpi_battery_sysctl_tree), OID_AUTO, "units", CTLTYPE_INT | CTLFLAG_RD, NULL, 0, acpi_battery_units_sysctl, "I", "number of batteries"); SYSCTL_ADD_INT(&acpi_battery_sysctl_ctx, SYSCTL_CHILDREN(acpi_battery_sysctl_tree), OID_AUTO, "info_expire", CTLFLAG_RW, &acpi_battery_info_expire, 0, "time in seconds until info is refreshed"); - acpi_batteries_initted = TRUE; + acpi_batteries_initialized = TRUE; out: - if (error != 0) { + if (error) { acpi_deregister_ioctl(ACPIIO_BATT_GET_UNITS, acpi_battery_ioctl); acpi_deregister_ioctl(ACPIIO_BATT_GET_BATTINFO, acpi_battery_ioctl); + acpi_deregister_ioctl(ACPIIO_BATT_GET_BATTINFO_V1, acpi_battery_ioctl); acpi_deregister_ioctl(ACPIIO_BATT_GET_BIF, acpi_battery_ioctl); + acpi_deregister_ioctl(ACPIIO_BATT_GET_BIX, acpi_battery_ioctl); acpi_deregister_ioctl(ACPIIO_BATT_GET_BST, acpi_battery_ioctl); + acpi_deregister_ioctl(ACPIIO_BATT_GET_BST_V1, acpi_battery_ioctl); } return (error); } Index: stable/11/sys/dev/acpica/acpi_cmbat.c =================================================================== --- stable/11/sys/dev/acpica/acpi_cmbat.c (revision 359075) +++ stable/11/sys/dev/acpica/acpi_cmbat.c (revision 359076) @@ -1,507 +1,593 @@ /*- * Copyright (c) 2005 Nate Lawson * Copyright (c) 2000 Munehiro Matsuda * Copyright (c) 2000 Takanori Watanabe * Copyright (c) 2000 Mitsuru IWASAKI * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include "opt_acpi.h" #include #include #include #include #include #include #include #include #include #include #include static MALLOC_DEFINE(M_ACPICMBAT, "acpicmbat", "ACPI control method battery data"); /* Number of times to retry initialization before giving up. */ #define ACPI_CMBAT_RETRY_MAX 6 /* Check the battery once a minute. */ #define CMBAT_POLLRATE (60 * hz) /* Hooks for the ACPI CA debugging infrastructure */ #define _COMPONENT ACPI_BATTERY ACPI_MODULE_NAME("BATTERY") #define ACPI_BATTERY_BST_CHANGE 0x80 #define ACPI_BATTERY_BIF_CHANGE 0x81 +#define ACPI_BATTERY_BIX_CHANGE ACPI_BATTERY_BIF_CHANGE struct acpi_cmbat_softc { device_t dev; int flags; - struct acpi_bif bif; + struct acpi_bix bix; struct acpi_bst bst; struct timespec bst_lastupdated; }; ACPI_SERIAL_DECL(cmbat, "ACPI cmbat"); static int acpi_cmbat_probe(device_t dev); static int acpi_cmbat_attach(device_t dev); static int acpi_cmbat_detach(device_t dev); static int acpi_cmbat_resume(device_t dev); static void acpi_cmbat_notify_handler(ACPI_HANDLE h, UINT32 notify, void *context); static int acpi_cmbat_info_expired(struct timespec *lastupdated); static void acpi_cmbat_info_updated(struct timespec *lastupdated); static void acpi_cmbat_get_bst(void *arg); -static void acpi_cmbat_get_bif_task(void *arg); -static void acpi_cmbat_get_bif(void *arg); -static int acpi_cmbat_bst(device_t dev, struct acpi_bst *bstp); -static int acpi_cmbat_bif(device_t dev, struct acpi_bif *bifp); +static void acpi_cmbat_get_bix_task(void *arg); +static void acpi_cmbat_get_bix(void *arg); +static int acpi_cmbat_bst(device_t, struct acpi_bst *); +static int acpi_cmbat_bix(device_t, void *, size_t); static void acpi_cmbat_init_battery(void *arg); static device_method_t acpi_cmbat_methods[] = { /* Device interface */ DEVMETHOD(device_probe, acpi_cmbat_probe), DEVMETHOD(device_attach, acpi_cmbat_attach), DEVMETHOD(device_detach, acpi_cmbat_detach), DEVMETHOD(device_resume, acpi_cmbat_resume), /* ACPI battery interface */ - DEVMETHOD(acpi_batt_get_info, acpi_cmbat_bif), + DEVMETHOD(acpi_batt_get_info, acpi_cmbat_bix), DEVMETHOD(acpi_batt_get_status, acpi_cmbat_bst), DEVMETHOD_END }; static driver_t acpi_cmbat_driver = { "battery", acpi_cmbat_methods, sizeof(struct acpi_cmbat_softc), }; static devclass_t acpi_cmbat_devclass; DRIVER_MODULE(acpi_cmbat, acpi, acpi_cmbat_driver, acpi_cmbat_devclass, 0, 0); MODULE_DEPEND(acpi_cmbat, acpi, 1, 1, 1); static int acpi_cmbat_probe(device_t dev) { static char *cmbat_ids[] = { "PNP0C0A", NULL }; if (acpi_disabled("cmbat") || ACPI_ID_PROBE(device_get_parent(dev), dev, cmbat_ids) == NULL) return (ENXIO); device_set_desc(dev, "ACPI Control Method Battery"); return (0); } static int acpi_cmbat_attach(device_t dev) { int error; ACPI_HANDLE handle; struct acpi_cmbat_softc *sc; sc = device_get_softc(dev); handle = acpi_get_handle(dev); sc->dev = dev; timespecclear(&sc->bst_lastupdated); error = acpi_battery_register(dev); if (error != 0) { device_printf(dev, "registering battery failed\n"); return (error); } /* * Install a system notify handler in addition to the device notify. * Toshiba notebook uses this alternate notify for its battery. */ AcpiInstallNotifyHandler(handle, ACPI_ALL_NOTIFY, acpi_cmbat_notify_handler, dev); AcpiOsExecute(OSL_NOTIFY_HANDLER, acpi_cmbat_init_battery, dev); return (0); } static int acpi_cmbat_detach(device_t dev) { ACPI_HANDLE handle; handle = acpi_get_handle(dev); AcpiRemoveNotifyHandler(handle, ACPI_ALL_NOTIFY, acpi_cmbat_notify_handler); acpi_battery_remove(dev); /* * Force any pending notification handler calls to complete by * requesting cmbat serialisation while freeing and clearing the * softc pointer: */ ACPI_SERIAL_BEGIN(cmbat); device_set_softc(dev, NULL); ACPI_SERIAL_END(cmbat); return (0); } static int acpi_cmbat_resume(device_t dev) { AcpiOsExecute(OSL_NOTIFY_HANDLER, acpi_cmbat_init_battery, dev); return (0); } static void acpi_cmbat_notify_handler(ACPI_HANDLE h, UINT32 notify, void *context) { struct acpi_cmbat_softc *sc; device_t dev; dev = (device_t)context; sc = device_get_softc(dev); switch (notify) { case ACPI_NOTIFY_DEVICE_CHECK: case ACPI_BATTERY_BST_CHANGE: /* * Clear the last updated time. The next call to retrieve the * battery status will get the new value for us. */ timespecclear(&sc->bst_lastupdated); break; case ACPI_NOTIFY_BUS_CHECK: - case ACPI_BATTERY_BIF_CHANGE: + case ACPI_BATTERY_BIX_CHANGE: /* * Queue a callback to get the current battery info from thread * context. It's not safe to block in a notify handler. */ - AcpiOsExecute(OSL_NOTIFY_HANDLER, acpi_cmbat_get_bif_task, dev); + AcpiOsExecute(OSL_NOTIFY_HANDLER, acpi_cmbat_get_bix_task, dev); break; } acpi_UserNotify("CMBAT", h, notify); } static int acpi_cmbat_info_expired(struct timespec *lastupdated) { struct timespec curtime; ACPI_SERIAL_ASSERT(cmbat); if (lastupdated == NULL) return (TRUE); if (!timespecisset(lastupdated)) return (TRUE); getnanotime(&curtime); timespecsub(&curtime, lastupdated); return (curtime.tv_sec < 0 || curtime.tv_sec > acpi_battery_get_info_expire()); } static void acpi_cmbat_info_updated(struct timespec *lastupdated) { ACPI_SERIAL_ASSERT(cmbat); if (lastupdated != NULL) getnanotime(lastupdated); } static void acpi_cmbat_get_bst(void *arg) { struct acpi_cmbat_softc *sc; ACPI_STATUS as; ACPI_OBJECT *res; ACPI_HANDLE h; ACPI_BUFFER bst_buffer; device_t dev; ACPI_SERIAL_ASSERT(cmbat); dev = arg; sc = device_get_softc(dev); h = acpi_get_handle(dev); bst_buffer.Pointer = NULL; bst_buffer.Length = ACPI_ALLOCATE_BUFFER; if (!acpi_cmbat_info_expired(&sc->bst_lastupdated)) goto end; as = AcpiEvaluateObject(h, "_BST", NULL, &bst_buffer); if (ACPI_FAILURE(as)) { ACPI_VPRINT(dev, acpi_device_get_parent_softc(dev), - "error fetching current battery status -- %s\n", - AcpiFormatException(as)); + "error fetching current battery status -- %s\n", + AcpiFormatException(as)); goto end; } res = (ACPI_OBJECT *)bst_buffer.Pointer; if (!ACPI_PKG_VALID(res, 4)) { ACPI_VPRINT(dev, acpi_device_get_parent_softc(dev), - "battery status corrupted\n"); + "battery status corrupted\n"); goto end; } if (acpi_PkgInt32(res, 0, &sc->bst.state) != 0) goto end; if (acpi_PkgInt32(res, 1, &sc->bst.rate) != 0) goto end; if (acpi_PkgInt32(res, 2, &sc->bst.cap) != 0) goto end; if (acpi_PkgInt32(res, 3, &sc->bst.volt) != 0) goto end; acpi_cmbat_info_updated(&sc->bst_lastupdated); /* Clear out undefined/extended bits that might be set by hardware. */ sc->bst.state &= ACPI_BATT_STAT_BST_MASK; if ((sc->bst.state & ACPI_BATT_STAT_INVALID) == ACPI_BATT_STAT_INVALID) ACPI_VPRINT(dev, acpi_device_get_parent_softc(dev), "battery reports simultaneous charging and discharging\n"); /* XXX If all batteries are critical, perhaps we should suspend. */ if (sc->bst.state & ACPI_BATT_STAT_CRITICAL) { if ((sc->flags & ACPI_BATT_STAT_CRITICAL) == 0) { sc->flags |= ACPI_BATT_STAT_CRITICAL; device_printf(dev, "critically low charge!\n"); } } else sc->flags &= ~ACPI_BATT_STAT_CRITICAL; end: - if (bst_buffer.Pointer != NULL) - AcpiOsFree(bst_buffer.Pointer); + AcpiOsFree(bst_buffer.Pointer); } /* XXX There should be a cleaner way to do this locking. */ static void -acpi_cmbat_get_bif_task(void *arg) +acpi_cmbat_get_bix_task(void *arg) { ACPI_SERIAL_BEGIN(cmbat); - acpi_cmbat_get_bif(arg); + acpi_cmbat_get_bix(arg); ACPI_SERIAL_END(cmbat); } static void -acpi_cmbat_get_bif(void *arg) +acpi_cmbat_get_bix(void *arg) { struct acpi_cmbat_softc *sc; ACPI_STATUS as; ACPI_OBJECT *res; ACPI_HANDLE h; - ACPI_BUFFER bif_buffer; + ACPI_BUFFER bix_buffer; device_t dev; + int i, n; + const struct { + enum { _BIX, _BIF } type; + char *name; + } bobjs[] = { + { _BIX, "_BIX"}, + { _BIF, "_BIF"}, + }; ACPI_SERIAL_ASSERT(cmbat); dev = arg; sc = device_get_softc(dev); h = acpi_get_handle(dev); - bif_buffer.Pointer = NULL; - bif_buffer.Length = ACPI_ALLOCATE_BUFFER; + bix_buffer.Pointer = NULL; + bix_buffer.Length = ACPI_ALLOCATE_BUFFER; - as = AcpiEvaluateObject(h, "_BIF", NULL, &bif_buffer); - if (ACPI_FAILURE(as)) { + for (n = 0; n < sizeof(bobjs); n++) { + as = AcpiEvaluateObject(h, bobjs[n].name, NULL, &bix_buffer); + if (!ACPI_FAILURE(as)) { + res = (ACPI_OBJECT *)bix_buffer.Pointer; + break; + } + AcpiOsFree(bix_buffer.Pointer); + bix_buffer.Pointer = NULL; + bix_buffer.Length = ACPI_ALLOCATE_BUFFER; + } + /* Both _BIF and _BIX were not found. */ + if (n == sizeof(bobjs)) { ACPI_VPRINT(dev, acpi_device_get_parent_softc(dev), - "error fetching current battery info -- %s\n", - AcpiFormatException(as)); + "error fetching current battery info -- %s\n", + AcpiFormatException(as)); goto end; } - res = (ACPI_OBJECT *)bif_buffer.Pointer; - if (!ACPI_PKG_VALID(res, 13)) { - ACPI_VPRINT(dev, acpi_device_get_parent_softc(dev), - "battery info corrupted\n"); - goto end; + /* + * ACPI _BIX and _BIF revision mismatch check: + * + * 1. _BIF has no revision field. The number of fields must be 13. + * + * 2. _BIX has a revision field. As of ACPI 6.3 it must be "0" or + * "1". The number of fields will be checked---20 and 21, + * respectively. + * + * If the revision number is grater than "1" and the number of + * fields is grater than 21, it will be treated as compatible with + * ACPI 6.0 _BIX. If not, it will be ignored. + */ + i = 0; + switch (bobjs[n].type) { + case _BIX: + if (acpi_PkgInt16(res, i++, &sc->bix.rev) != 0) { + ACPI_VPRINT(dev, acpi_device_get_parent_softc(dev), + "_BIX revision error\n"); + goto end; + } +#define ACPI_BIX_REV_MISMATCH_ERR(x, r) do { \ + ACPI_VPRINT(dev, acpi_device_get_parent_softc(dev), \ + "_BIX revision mismatch (%u != %u)\n", x, r); \ + goto end; \ + } while (0) + + if (ACPI_PKG_VALID_EQ(res, 21)) { /* ACPI 6.0 _BIX */ + /* + * Some models have rev.0 _BIX with 21 members. + * In that case, treat the first 20 members as rev.0 _BIX. + */ + if (sc->bix.rev != ACPI_BIX_REV_0 && + sc->bix.rev != ACPI_BIX_REV_1) + ACPI_BIX_REV_MISMATCH_ERR(sc->bix.rev, ACPI_BIX_REV_1); + } else if (ACPI_PKG_VALID_EQ(res, 20)) {/* ACPI 4.0 _BIX */ + if (sc->bix.rev != ACPI_BIX_REV_0) + ACPI_BIX_REV_MISMATCH_ERR(sc->bix.rev, ACPI_BIX_REV_0); + } else if (ACPI_PKG_VALID(res, 22)) { + /* _BIX with 22 or more members. */ + if (ACPI_BIX_REV_MIN_CHECK(sc->bix.rev, ACPI_BIX_REV_1 + 1)) { + /* + * Unknown revision number. + * Assume 21 members are compatible with 6.0 _BIX. + */ + ACPI_VPRINT(dev, acpi_device_get_parent_softc(dev), + "Unknown _BIX revision(%u). " + "Assuming compatible with revision %u.\n", + sc->bix.rev, ACPI_BIX_REV_1); + } else { + /* + * Known revision number. Ignore the extra members. + */ + ACPI_VPRINT(dev, acpi_device_get_parent_softc(dev), + "Extra objects found in _BIX were ignored.\n"); + } + } else { + /* Invalid _BIX. Ignore it. */ + ACPI_VPRINT(dev, acpi_device_get_parent_softc(dev), + "Invalid _BIX found (rev=%u, count=%u). Ignored.\n", + sc->bix.rev, res->Package.Count); + goto end; + } + break; +#undef ACPI_BIX_REV_MISMATCH_ERR + case _BIF: + if (ACPI_PKG_VALID_EQ(res, 13)) /* _BIF */ + sc->bix.rev = ACPI_BIX_REV_BIF; + else { + ACPI_VPRINT(dev, acpi_device_get_parent_softc(dev), + "Invalid _BIF found (count=%u). Ignored.\n", + res->Package.Count); + goto end; + } + break; } - if (acpi_PkgInt32(res, 0, &sc->bif.units) != 0) - goto end; - if (acpi_PkgInt32(res, 1, &sc->bif.dcap) != 0) - goto end; - if (acpi_PkgInt32(res, 2, &sc->bif.lfcap) != 0) - goto end; - if (acpi_PkgInt32(res, 3, &sc->bif.btech) != 0) - goto end; - if (acpi_PkgInt32(res, 4, &sc->bif.dvol) != 0) - goto end; - if (acpi_PkgInt32(res, 5, &sc->bif.wcap) != 0) - goto end; - if (acpi_PkgInt32(res, 6, &sc->bif.lcap) != 0) - goto end; - if (acpi_PkgInt32(res, 7, &sc->bif.gra1) != 0) - goto end; - if (acpi_PkgInt32(res, 8, &sc->bif.gra2) != 0) - goto end; - if (acpi_PkgStr(res, 9, sc->bif.model, ACPI_CMBAT_MAXSTRLEN) != 0) - goto end; - if (acpi_PkgStr(res, 10, sc->bif.serial, ACPI_CMBAT_MAXSTRLEN) != 0) - goto end; - if (acpi_PkgStr(res, 11, sc->bif.type, ACPI_CMBAT_MAXSTRLEN) != 0) - goto end; - if (acpi_PkgStr(res, 12, sc->bif.oeminfo, ACPI_CMBAT_MAXSTRLEN) != 0) - goto end; + ACPI_VPRINT(dev, acpi_device_get_parent_softc(dev), + "rev = %04x\n", sc->bix.rev); +#define BIX_GETU32(NAME) do { \ + ACPI_VPRINT(dev, acpi_device_get_parent_softc(dev), \ + #NAME " = %u\n", sc->bix.NAME); \ + if (acpi_PkgInt32(res, i++, &sc->bix.NAME) != 0) \ + goto end; \ + } while (0) + BIX_GETU32(units); + BIX_GETU32(dcap); + BIX_GETU32(lfcap); + BIX_GETU32(btech); + BIX_GETU32(dvol); + BIX_GETU32(wcap); + BIX_GETU32(lcap); + if (ACPI_BIX_REV_MIN_CHECK(sc->bix.rev, ACPI_BIX_REV_0)) { + BIX_GETU32(cycles); + BIX_GETU32(accuracy); + BIX_GETU32(stmax); + BIX_GETU32(stmin); + BIX_GETU32(aimax); + BIX_GETU32(aimin); + } + BIX_GETU32(gra1); + BIX_GETU32(gra2); + if (acpi_PkgStr(res, i++, sc->bix.model, ACPI_CMBAT_MAXSTRLEN) != 0) + goto end; + if (acpi_PkgStr(res, i++, sc->bix.serial, ACPI_CMBAT_MAXSTRLEN) != 0) + goto end; + if (acpi_PkgStr(res, i++, sc->bix.type, ACPI_CMBAT_MAXSTRLEN) != 0) + goto end; + if (acpi_PkgStr(res, i++, sc->bix.oeminfo, ACPI_CMBAT_MAXSTRLEN) != 0) + goto end; + if (ACPI_BIX_REV_MIN_CHECK(sc->bix.rev, ACPI_BIX_REV_1)) + BIX_GETU32(scap); +#undef BIX_GETU32 end: - if (bif_buffer.Pointer != NULL) - AcpiOsFree(bif_buffer.Pointer); + AcpiOsFree(bix_buffer.Pointer); } static int -acpi_cmbat_bif(device_t dev, struct acpi_bif *bifp) +acpi_cmbat_bix(device_t dev, void *bix, size_t len) { struct acpi_cmbat_softc *sc; + if (len != sizeof(struct acpi_bix) && + len != sizeof(struct acpi_bif)) + return (-1); + sc = device_get_softc(dev); /* * Just copy the data. The only value that should change is the * last-full capacity, so we only update when we get a notify that says * the info has changed. Many systems apparently take a long time to - * process a _BIF call so we avoid it if possible. + * process a _BI[FX] call so we avoid it if possible. */ ACPI_SERIAL_BEGIN(cmbat); - bifp->units = sc->bif.units; - bifp->dcap = sc->bif.dcap; - bifp->lfcap = sc->bif.lfcap; - bifp->btech = sc->bif.btech; - bifp->dvol = sc->bif.dvol; - bifp->wcap = sc->bif.wcap; - bifp->lcap = sc->bif.lcap; - bifp->gra1 = sc->bif.gra1; - bifp->gra2 = sc->bif.gra2; - strncpy(bifp->model, sc->bif.model, sizeof(sc->bif.model)); - strncpy(bifp->serial, sc->bif.serial, sizeof(sc->bif.serial)); - strncpy(bifp->type, sc->bif.type, sizeof(sc->bif.type)); - strncpy(bifp->oeminfo, sc->bif.oeminfo, sizeof(sc->bif.oeminfo)); + memcpy(bix, &sc->bix, len); ACPI_SERIAL_END(cmbat); return (0); } static int -acpi_cmbat_bst(device_t dev, struct acpi_bst *bstp) +acpi_cmbat_bst(device_t dev, struct acpi_bst *bst) { struct acpi_cmbat_softc *sc; sc = device_get_softc(dev); ACPI_SERIAL_BEGIN(cmbat); if (acpi_BatteryIsPresent(dev)) { acpi_cmbat_get_bst(dev); - bstp->state = sc->bst.state; - bstp->rate = sc->bst.rate; - bstp->cap = sc->bst.cap; - bstp->volt = sc->bst.volt; + memcpy(bst, &sc->bst, sizeof(*bst)); } else - bstp->state = ACPI_BATT_STAT_NOT_PRESENT; + bst->state = ACPI_BATT_STAT_NOT_PRESENT; ACPI_SERIAL_END(cmbat); return (0); } static void acpi_cmbat_init_battery(void *arg) { struct acpi_cmbat_softc *sc; int retry, valid; device_t dev; dev = (device_t)arg; ACPI_VPRINT(dev, acpi_device_get_parent_softc(dev), - "battery initialization start\n"); + "battery enitialization start\n"); /* * Try repeatedly to get valid data from the battery. Since the * embedded controller isn't always ready just after boot, we may have * to wait a while. */ for (retry = 0; retry < ACPI_CMBAT_RETRY_MAX; retry++, AcpiOsSleep(10000)) { /* * Batteries on DOCK can be ejected w/ DOCK during retrying. * * If there is a valid softc pointer the device may be in * attaching, attached or detaching state. If the state is * different from attached retry getting the device state * until it becomes stable. This solves a race if the ACPI * notification handler is called during attach, because * device_is_attached() doesn't return non-zero until after * the attach code has been executed. */ ACPI_SERIAL_BEGIN(cmbat); sc = device_get_softc(dev); if (sc == NULL) { ACPI_SERIAL_END(cmbat); return; } if (!acpi_BatteryIsPresent(dev) || !device_is_attached(dev)) { ACPI_SERIAL_END(cmbat); continue; } /* * Only query the battery if this is the first try or the specific * type of info is still invalid. */ if (retry == 0 || !acpi_battery_bst_valid(&sc->bst)) { timespecclear(&sc->bst_lastupdated); acpi_cmbat_get_bst(dev); } - if (retry == 0 || !acpi_battery_bif_valid(&sc->bif)) - acpi_cmbat_get_bif(dev); + if (retry == 0 || !acpi_battery_bix_valid(&sc->bix)) + acpi_cmbat_get_bix(dev); valid = acpi_battery_bst_valid(&sc->bst) && - acpi_battery_bif_valid(&sc->bif); + acpi_battery_bix_valid(&sc->bix); ACPI_SERIAL_END(cmbat); if (valid) break; } if (retry == ACPI_CMBAT_RETRY_MAX) { ACPI_VPRINT(dev, acpi_device_get_parent_softc(dev), - "battery initialization failed, giving up\n"); + "battery initialization failed, giving up\n"); } else { ACPI_VPRINT(dev, acpi_device_get_parent_softc(dev), - "battery initialization done, tried %d times\n", retry + 1); + "battery initialization done, tried %d times\n", retry + 1); } } Index: stable/11/sys/dev/acpica/acpi_if.m =================================================================== --- stable/11/sys/dev/acpica/acpi_if.m (revision 359075) +++ stable/11/sys/dev/acpica/acpi_if.m (revision 359076) @@ -1,224 +1,227 @@ #- # Copyright (c) 2004 Nate Lawson # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF # SUCH DAMAGE. # # $FreeBSD$ # #include #include #include INTERFACE acpi; # # Callback function for each child handle traversed in acpi_scan_children(). # # ACPI_HANDLE h: current child device being considered # # device_t *dev: pointer to the child's original device_t or NULL if there # was none. The callback should store a new device in *dev if it has # created one. The method implementation will automatically clean up the # previous device and properly associate the current ACPI_HANDLE with it. # # level: current level being scanned # # void *arg: argument passed in original call to acpi_scan_children() # # Returns: AE_OK if the scan should continue, otherwise an error # HEADER { typedef ACPI_STATUS (*acpi_scan_cb_t)(ACPI_HANDLE h, device_t *dev, int level, void *arg); + struct acpi_bix; struct acpi_bif; struct acpi_bst; }; # # Default implementation for acpi_id_probe(). # CODE { static char * acpi_generic_id_probe(device_t bus, device_t dev, char **ids) { return (NULL); } }; # # Check a device for a match in a list of ID strings. The strings can be # EISA PNP IDs or ACPI _HID/_CID values. # # device_t bus: parent bus for the device # # device_t dev: device being considered # # char **ids: array of ID strings to consider # # Returns: ID string matched or NULL if no match # METHOD char * id_probe { device_t bus; device_t dev; char **ids; } DEFAULT acpi_generic_id_probe; # # Evaluate an ACPI method or object, given its path. # # device_t bus: parent bus for the device # # device_t dev: evaluate the object relative to this device's handle. # Specify NULL to begin the search at the ACPI root. # # ACPI_STRING pathname: absolute or relative path to this object # # ACPI_OBJECT_LIST *parameters: array of arguments to pass to the object. # Specify NULL if there are none. # # ACPI_BUFFER *ret: the result (if any) of the evaluation # Specify NULL if there is none. # # Returns: AE_OK or an error value # METHOD ACPI_STATUS evaluate_object { device_t bus; device_t dev; ACPI_STRING pathname; ACPI_OBJECT_LIST *parameters; ACPI_BUFFER *ret; }; # # Get the highest power state (D0-D3) that is usable for a device when # suspending/resuming. If a bus calls this when suspending a device, it # must also call it when resuming. # # device_t bus: parent bus for the device # # device_t dev: check this device's appropriate power state # # int *dstate: if successful, contains the highest valid sleep state # # Returns: 0 on success or some other error value. # METHOD int pwr_for_sleep { device_t bus; device_t dev; int *dstate; }; # # Rescan a subtree and optionally reattach devices to handles. Users # specify a callback that is called for each ACPI_HANDLE of type Device # that is a child of "dev". # # device_t bus: parent bus for the device # # device_t dev: begin the scan starting with this device's handle. # Specify NULL to begin the scan at the ACPI root. # # int max_depth: number of levels to traverse (i.e., 1 means just the # immediate children. # # acpi_scan_cb_t user_fn: called for each child handle # # void *arg: argument to pass to the callback function # # Returns: AE_OK or an error value, based on the callback return value # METHOD ACPI_STATUS scan_children { device_t bus; device_t dev; int max_depth; acpi_scan_cb_t user_fn; void *arg; }; # # Query a given driver for its supported feature(s). This should be # called by the parent bus before the driver is probed. # # driver_t *driver: child driver # # u_int *features: returned bitmask of all supported features # STATICMETHOD int get_features { driver_t *driver; u_int *features; }; # # Read embedded controller (EC) address space # # device_t dev: EC device # u_int addr: Address to read from in EC space # UINT64 *val: Location to store read value # int width: Size of area to read in bytes # METHOD int ec_read { device_t dev; u_int addr; UINT64 *val; int width; }; # # Write embedded controller (EC) address space # # device_t dev: EC device # u_int addr: Address to write to in EC space # UINT64 val: Value to write # int width: Size of value to write in bytes # METHOD int ec_write { device_t dev; u_int addr; UINT64 val; int width; }; # -# Get battery information (_BIF format) +# Get battery information (_BIF or _BIX format) # # device_t dev: Battery device -# struct acpi_bif *bif: Pointer to storage for _BIF results +# void *bix: Pointer to storage for _BIF or _BIX results +# size_t len: length of acpi_bif or acpi_bix. # METHOD int batt_get_info { device_t dev; - struct acpi_bif *bif; + void *bix; + size_t len; }; # # Get battery status (_BST format) # # device_t dev: Battery device # struct acpi_bst *bst: Pointer to storage for _BST results # METHOD int batt_get_status { device_t dev; struct acpi_bst *bst; }; Index: stable/11/sys/dev/acpica/acpi_package.c =================================================================== --- stable/11/sys/dev/acpica/acpi_package.c (revision 359075) +++ stable/11/sys/dev/acpica/acpi_package.c (revision 359076) @@ -1,173 +1,186 @@ /*- * Copyright (c) 2003 Nate Lawson * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include /* * Package manipulation convenience functions */ int acpi_PkgInt(ACPI_OBJECT *res, int idx, UINT64 *dst) { ACPI_OBJECT *obj; obj = &res->Package.Elements[idx]; if (obj->Type != ACPI_TYPE_INTEGER) return (EINVAL); *dst = obj->Integer.Value; return (0); } int acpi_PkgInt32(ACPI_OBJECT *res, int idx, uint32_t *dst) { UINT64 tmp; int error; error = acpi_PkgInt(res, idx, &tmp); if (error == 0) *dst = (uint32_t)tmp; return (error); } int +acpi_PkgInt16(ACPI_OBJECT *res, int idx, uint16_t *dst) +{ + UINT64 tmp; + int error; + + error = acpi_PkgInt(res, idx, &tmp); + if (error == 0) + *dst = (uint16_t)tmp; + + return (error); +} + +int acpi_PkgStr(ACPI_OBJECT *res, int idx, void *dst, size_t size) { ACPI_OBJECT *obj; void *ptr; size_t length; obj = &res->Package.Elements[idx]; if (obj == NULL) return (EINVAL); switch (obj->Type) { case ACPI_TYPE_STRING: ptr = obj->String.Pointer; length = obj->String.Length; break; case ACPI_TYPE_BUFFER: ptr = obj->Buffer.Pointer; length = obj->Buffer.Length; break; default: return (EINVAL); } /* Make sure string will fit, including terminating NUL */ if (++length > size) return (E2BIG); strlcpy(dst, ptr, length); return (0); } int acpi_PkgGas(device_t dev, ACPI_OBJECT *res, int idx, int *type, int *rid, struct resource **dst, u_int flags) { ACPI_GENERIC_ADDRESS gas; ACPI_OBJECT *obj; obj = &res->Package.Elements[idx]; if (obj == NULL || obj->Type != ACPI_TYPE_BUFFER || obj->Buffer.Length < sizeof(ACPI_GENERIC_ADDRESS) + 3) return (EINVAL); memcpy(&gas, obj->Buffer.Pointer + 3, sizeof(gas)); return (acpi_bus_alloc_gas(dev, type, rid, &gas, dst, flags)); } int acpi_PkgFFH_IntelCpu(ACPI_OBJECT *res, int idx, int *vendor, int *class, uint64_t *address, int *accsize) { ACPI_GENERIC_ADDRESS gas; ACPI_OBJECT *obj; obj = &res->Package.Elements[idx]; if (obj == NULL || obj->Type != ACPI_TYPE_BUFFER || obj->Buffer.Length < sizeof(ACPI_GENERIC_ADDRESS) + 3) return (EINVAL); memcpy(&gas, obj->Buffer.Pointer + 3, sizeof(gas)); if (gas.SpaceId != ACPI_ADR_SPACE_FIXED_HARDWARE) return (ERESTART); *vendor = gas.BitWidth; *class = gas.BitOffset; *address = gas.Address; *accsize = gas.AccessWidth; return (0); } ACPI_HANDLE acpi_GetReference(ACPI_HANDLE scope, ACPI_OBJECT *obj) { ACPI_HANDLE h; if (obj == NULL) return (NULL); switch (obj->Type) { case ACPI_TYPE_LOCAL_REFERENCE: case ACPI_TYPE_ANY: h = obj->Reference.Handle; break; case ACPI_TYPE_STRING: /* * The String object usually contains a fully-qualified path, so * scope can be NULL. * * XXX This may not always be the case. */ if (ACPI_FAILURE(AcpiGetHandle(scope, obj->String.Pointer, &h))) h = NULL; break; default: h = NULL; break; } return (h); } Index: stable/11/sys/dev/acpica/acpi_smbat.c =================================================================== --- stable/11/sys/dev/acpica/acpi_smbat.c (revision 359075) +++ stable/11/sys/dev/acpica/acpi_smbat.c (revision 359076) @@ -1,490 +1,496 @@ /*- * Copyright (c) 2005 Hans Petter Selasky * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include "opt_acpi.h" #include #include #include #include #include #include #include #include /* Transactions have failed after 500 ms. */ #define SMBUS_TIMEOUT 50 struct acpi_smbat_softc { uint8_t sb_base_addr; device_t ec_dev; - struct acpi_bif bif; + struct acpi_bix bix; struct acpi_bst bst; - struct timespec bif_lastupdated; + struct timespec bix_lastupdated; struct timespec bst_lastupdated; }; static int acpi_smbat_probe(device_t dev); static int acpi_smbat_attach(device_t dev); static int acpi_smbat_shutdown(device_t dev); static int acpi_smbat_info_expired(struct timespec *lastupdated); static void acpi_smbat_info_updated(struct timespec *lastupdated); -static int acpi_smbat_get_bif(device_t dev, struct acpi_bif *bif); +static int acpi_smbat_get_bix(device_t dev, void *, size_t); static int acpi_smbat_get_bst(device_t dev, struct acpi_bst *bst); ACPI_SERIAL_DECL(smbat, "ACPI Smart Battery"); static SYSCTL_NODE(_debug_acpi, OID_AUTO, batt, CTLFLAG_RD, NULL, "Battery debugging"); /* On some laptops with smart batteries, enabling battery monitoring * software causes keystrokes from atkbd to be lost. This has also been * reported on Linux, and is apparently due to the keyboard and I2C line * for the battery being routed through the same chip. Whether that's * accurate or not, adding extra sleeps to the status checking code * causes the problem to go away. * * If you experience that problem, try a value of 10ms and move up * from there. */ static int batt_sleep_ms; SYSCTL_INT(_debug_acpi_batt, OID_AUTO, batt_sleep_ms, CTLFLAG_RW, &batt_sleep_ms, 0, "Sleep during battery status updates to prevent keystroke loss."); static device_method_t acpi_smbat_methods[] = { /* device interface */ DEVMETHOD(device_probe, acpi_smbat_probe), DEVMETHOD(device_attach, acpi_smbat_attach), DEVMETHOD(device_shutdown, acpi_smbat_shutdown), /* ACPI battery interface */ DEVMETHOD(acpi_batt_get_status, acpi_smbat_get_bst), - DEVMETHOD(acpi_batt_get_info, acpi_smbat_get_bif), + DEVMETHOD(acpi_batt_get_info, acpi_smbat_get_bix), DEVMETHOD_END }; static driver_t acpi_smbat_driver = { "battery", acpi_smbat_methods, sizeof(struct acpi_smbat_softc), }; static devclass_t acpi_smbat_devclass; DRIVER_MODULE(acpi_smbat, acpi, acpi_smbat_driver, acpi_smbat_devclass, 0, 0); MODULE_DEPEND(acpi_smbat, acpi, 1, 1, 1); static int acpi_smbat_probe(device_t dev) { static char *smbat_ids[] = {"ACPI0001", "ACPI0005", NULL}; ACPI_STATUS status; if (acpi_disabled("smbat") || ACPI_ID_PROBE(device_get_parent(dev), dev, smbat_ids) == NULL) return (ENXIO); status = AcpiEvaluateObject(acpi_get_handle(dev), "_EC", NULL, NULL); if (ACPI_FAILURE(status)) return (ENXIO); device_set_desc(dev, "ACPI Smart Battery"); return (0); } static int acpi_smbat_attach(device_t dev) { struct acpi_smbat_softc *sc; uint32_t base; sc = device_get_softc(dev); if (ACPI_FAILURE(acpi_GetInteger(acpi_get_handle(dev), "_EC", &base))) { device_printf(dev, "cannot get EC base address\n"); return (ENXIO); } sc->sb_base_addr = (base >> 8) & 0xff; /* XXX Only works with one EC, but nearly all systems only have one. */ sc->ec_dev = devclass_get_device(devclass_find("acpi_ec"), 0); if (sc->ec_dev == NULL) { device_printf(dev, "cannot find EC device\n"); return (ENXIO); } - timespecclear(&sc->bif_lastupdated); + timespecclear(&sc->bix_lastupdated); timespecclear(&sc->bst_lastupdated); if (acpi_battery_register(dev) != 0) { device_printf(dev, "cannot register battery\n"); return (ENXIO); } return (0); } static int acpi_smbat_shutdown(device_t dev) { acpi_battery_remove(dev); return (0); } static int acpi_smbat_info_expired(struct timespec *lastupdated) { struct timespec curtime; ACPI_SERIAL_ASSERT(smbat); if (lastupdated == NULL) return (TRUE); if (!timespecisset(lastupdated)) return (TRUE); getnanotime(&curtime); timespecsub(&curtime, lastupdated); return (curtime.tv_sec < 0 || curtime.tv_sec > acpi_battery_get_info_expire()); } static void acpi_smbat_info_updated(struct timespec *lastupdated) { ACPI_SERIAL_ASSERT(smbat); if (lastupdated != NULL) getnanotime(lastupdated); } static int acpi_smbus_read_2(struct acpi_smbat_softc *sc, uint8_t addr, uint8_t cmd, uint16_t *ptr) { int error, to; UINT64 val; ACPI_SERIAL_ASSERT(smbat); if (batt_sleep_ms) AcpiOsSleep(batt_sleep_ms); val = addr; error = ACPI_EC_WRITE(sc->ec_dev, sc->sb_base_addr + SMBUS_ADDR, val, 1); if (error) goto out; val = cmd; error = ACPI_EC_WRITE(sc->ec_dev, sc->sb_base_addr + SMBUS_CMD, val, 1); if (error) goto out; val = 0x09; /* | 0x80 if PEC */ error = ACPI_EC_WRITE(sc->ec_dev, sc->sb_base_addr + SMBUS_PRTCL, val, 1); if (error) goto out; if (batt_sleep_ms) AcpiOsSleep(batt_sleep_ms); for (to = SMBUS_TIMEOUT; to != 0; to--) { error = ACPI_EC_READ(sc->ec_dev, sc->sb_base_addr + SMBUS_PRTCL, &val, 1); if (error) goto out; if (val == 0) break; AcpiOsSleep(10); } if (to == 0) { error = ETIMEDOUT; goto out; } error = ACPI_EC_READ(sc->ec_dev, sc->sb_base_addr + SMBUS_STS, &val, 1); if (error) goto out; if (val & SMBUS_STS_MASK) { printf("%s: AE_ERROR 0x%x\n", __FUNCTION__, (int)(val & SMBUS_STS_MASK)); error = EIO; goto out; } error = ACPI_EC_READ(sc->ec_dev, sc->sb_base_addr + SMBUS_DATA, &val, 2); if (error) goto out; *ptr = val; out: return (error); } static int acpi_smbus_read_multi_1(struct acpi_smbat_softc *sc, uint8_t addr, uint8_t cmd, uint8_t *ptr, uint16_t len) { UINT64 val; uint8_t to; int error; ACPI_SERIAL_ASSERT(smbat); if (batt_sleep_ms) AcpiOsSleep(batt_sleep_ms); val = addr; error = ACPI_EC_WRITE(sc->ec_dev, sc->sb_base_addr + SMBUS_ADDR, val, 1); if (error) goto out; val = cmd; error = ACPI_EC_WRITE(sc->ec_dev, sc->sb_base_addr + SMBUS_CMD, val, 1); if (error) goto out; val = 0x0B /* | 0x80 if PEC */ ; error = ACPI_EC_WRITE(sc->ec_dev, sc->sb_base_addr + SMBUS_PRTCL, val, 1); if (error) goto out; if (batt_sleep_ms) AcpiOsSleep(batt_sleep_ms); for (to = SMBUS_TIMEOUT; to != 0; to--) { error = ACPI_EC_READ(sc->ec_dev, sc->sb_base_addr + SMBUS_PRTCL, &val, 1); if (error) goto out; if (val == 0) break; AcpiOsSleep(10); } if (to == 0) { error = ETIMEDOUT; goto out; } error = ACPI_EC_READ(sc->ec_dev, sc->sb_base_addr + SMBUS_STS, &val, 1); if (error) goto out; if (val & SMBUS_STS_MASK) { printf("%s: AE_ERROR 0x%x\n", __FUNCTION__, (int)(val & SMBUS_STS_MASK)); error = EIO; goto out; } /* get length */ error = ACPI_EC_READ(sc->ec_dev, sc->sb_base_addr + SMBUS_BCNT, &val, 1); if (error) goto out; val = (val & 0x1f) + 1; bzero(ptr, len); if (len > val) len = val; if (batt_sleep_ms) AcpiOsSleep(batt_sleep_ms); while (len--) { error = ACPI_EC_READ(sc->ec_dev, sc->sb_base_addr + SMBUS_DATA + len, &val, 1); if (error) goto out; ptr[len] = val; if (batt_sleep_ms) AcpiOsSleep(batt_sleep_ms); } out: return (error); } static int acpi_smbat_get_bst(device_t dev, struct acpi_bst *bst) { struct acpi_smbat_softc *sc; int error; uint32_t factor; int16_t val; uint8_t addr; ACPI_SERIAL_BEGIN(smbat); addr = SMBATT_ADDRESS; error = ENXIO; sc = device_get_softc(dev); if (!acpi_smbat_info_expired(&sc->bst_lastupdated)) { error = 0; goto out; } if (acpi_smbus_read_2(sc, addr, SMBATT_CMD_BATTERY_MODE, &val)) goto out; if (val & SMBATT_BM_CAPACITY_MODE) factor = 10; else factor = 1; /* get battery status */ if (acpi_smbus_read_2(sc, addr, SMBATT_CMD_BATTERY_STATUS, &val)) goto out; sc->bst.state = 0; if (val & SMBATT_BS_DISCHARGING) sc->bst.state |= ACPI_BATT_STAT_DISCHARG; if (val & SMBATT_BS_REMAINING_CAPACITY_ALARM) sc->bst.state |= ACPI_BATT_STAT_CRITICAL; /* * If the rate is negative, it is discharging. Otherwise, * it is charging. */ if (acpi_smbus_read_2(sc, addr, SMBATT_CMD_CURRENT, &val)) goto out; if (val > 0) { sc->bst.rate = val * factor; sc->bst.state &= ~SMBATT_BS_DISCHARGING; sc->bst.state |= ACPI_BATT_STAT_CHARGING; } else if (val < 0) sc->bst.rate = (-val) * factor; else sc->bst.rate = 0; if (acpi_smbus_read_2(sc, addr, SMBATT_CMD_REMAINING_CAPACITY, &val)) goto out; sc->bst.cap = val * factor; if (acpi_smbus_read_2(sc, addr, SMBATT_CMD_VOLTAGE, &val)) goto out; sc->bst.volt = val; acpi_smbat_info_updated(&sc->bst_lastupdated); error = 0; out: if (error == 0) memcpy(bst, &sc->bst, sizeof(sc->bst)); ACPI_SERIAL_END(smbat); return (error); } static int -acpi_smbat_get_bif(device_t dev, struct acpi_bif *bif) +acpi_smbat_get_bix(device_t dev, void *bix, size_t len) { struct acpi_smbat_softc *sc; int error; uint32_t factor; uint16_t val; uint8_t addr; + if (len != sizeof(struct acpi_bix) && + len != sizeof(struct acpi_bif)) + return (-1); + ACPI_SERIAL_BEGIN(smbat); addr = SMBATT_ADDRESS; error = ENXIO; sc = device_get_softc(dev); - if (!acpi_smbat_info_expired(&sc->bif_lastupdated)) { + if (!acpi_smbat_info_expired(&sc->bix_lastupdated)) { error = 0; goto out; } + sc->bix.rev = ACPI_BIX_REV_BIF; + if (acpi_smbus_read_2(sc, addr, SMBATT_CMD_BATTERY_MODE, &val)) goto out; if (val & SMBATT_BM_CAPACITY_MODE) { factor = 10; - sc->bif.units = ACPI_BIF_UNITS_MW; + sc->bix.units = ACPI_BIX_UNITS_MW; } else { factor = 1; - sc->bif.units = ACPI_BIF_UNITS_MA; + sc->bix.units = ACPI_BIX_UNITS_MA; } if (acpi_smbus_read_2(sc, addr, SMBATT_CMD_DESIGN_CAPACITY, &val)) goto out; - sc->bif.dcap = val * factor; + sc->bix.dcap = val * factor; if (acpi_smbus_read_2(sc, addr, SMBATT_CMD_FULL_CHARGE_CAPACITY, &val)) goto out; - sc->bif.lfcap = val * factor; - sc->bif.btech = 1; /* secondary (rechargeable) */ + sc->bix.lfcap = val * factor; + sc->bix.btech = 1; /* secondary (rechargeable) */ if (acpi_smbus_read_2(sc, addr, SMBATT_CMD_DESIGN_VOLTAGE, &val)) goto out; - sc->bif.dvol = val; + sc->bix.dvol = val; - sc->bif.wcap = sc->bif.dcap / 10; - sc->bif.lcap = sc->bif.dcap / 10; + sc->bix.wcap = sc->bix.dcap / 10; + sc->bix.lcap = sc->bix.dcap / 10; - sc->bif.gra1 = factor; /* not supported */ - sc->bif.gra2 = factor; /* not supported */ + sc->bix.gra1 = factor; /* not supported */ + sc->bix.gra2 = factor; /* not supported */ if (acpi_smbus_read_multi_1(sc, addr, SMBATT_CMD_DEVICE_NAME, - sc->bif.model, sizeof(sc->bif.model))) + sc->bix.model, sizeof(sc->bix.model))) goto out; if (acpi_smbus_read_2(sc, addr, SMBATT_CMD_SERIAL_NUMBER, &val)) goto out; - snprintf(sc->bif.serial, sizeof(sc->bif.serial), "0x%04x", val); + snprintf(sc->bix.serial, sizeof(sc->bix.serial), "0x%04x", val); if (acpi_smbus_read_multi_1(sc, addr, SMBATT_CMD_DEVICE_CHEMISTRY, - sc->bif.type, sizeof(sc->bif.type))) + sc->bix.type, sizeof(sc->bix.type))) goto out; if (acpi_smbus_read_multi_1(sc, addr, SMBATT_CMD_MANUFACTURER_DATA, - sc->bif.oeminfo, sizeof(sc->bif.oeminfo))) + sc->bix.oeminfo, sizeof(sc->bix.oeminfo))) goto out; /* XXX check if device was replugged during read? */ - acpi_smbat_info_updated(&sc->bif_lastupdated); + acpi_smbat_info_updated(&sc->bix_lastupdated); error = 0; out: if (error == 0) - memcpy(bif, &sc->bif, sizeof(sc->bif)); + memcpy(bix, &sc->bix, len); ACPI_SERIAL_END(smbat); return (error); } Index: stable/11/sys/dev/acpica/acpiio.h =================================================================== --- stable/11/sys/dev/acpica/acpiio.h (revision 359075) +++ stable/11/sys/dev/acpica/acpiio.h (revision 359076) @@ -1,125 +1,212 @@ /*- * Copyright (c) 1999 Takanori Watanabe * Copyright (c) 1999 Mitsuru IWASAKI * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #ifndef _ACPIIO_H_ #define _ACPIIO_H_ /* * Core ACPI subsystem ioctls */ #define ACPIIO_SETSLPSTATE _IOW('P', 3, int) /* DEPRECATED */ /* Request S1-5 sleep state. User is notified and then sleep proceeds. */ #define ACPIIO_REQSLPSTATE _IOW('P', 4, int) /* Allow suspend to continue (0) or abort it (errno). */ #define ACPIIO_ACKSLPSTATE _IOW('P', 5, int) struct acpi_battinfo { int cap; /* percent */ int min; /* remaining time (in minutes) */ int state; /* battery state */ int rate; /* emptying rate */ }; +/* + * Battery Information object. Note that this object is deprecated in + * ACPI 4.0 + */ #define ACPI_CMBAT_MAXSTRLEN 32 struct acpi_bif { - uint32_t units; /* Units (mW or mA). */ + uint32_t units; /* Power Unit (mW or mA). */ #define ACPI_BIF_UNITS_MW 0 /* Capacity in mWh, rate in mW. */ #define ACPI_BIF_UNITS_MA 1 /* Capacity in mAh, rate in mA. */ uint32_t dcap; /* Design Capacity */ uint32_t lfcap; /* Last Full capacity */ uint32_t btech; /* Battery Technology */ uint32_t dvol; /* Design voltage (mV) */ uint32_t wcap; /* WARN capacity */ uint32_t lcap; /* Low capacity */ uint32_t gra1; /* Granularity 1 (Warn to Low) */ uint32_t gra2; /* Granularity 2 (Full to Warn) */ char model[ACPI_CMBAT_MAXSTRLEN]; /* model identifier */ char serial[ACPI_CMBAT_MAXSTRLEN]; /* Serial number */ char type[ACPI_CMBAT_MAXSTRLEN]; /* Type */ char oeminfo[ACPI_CMBAT_MAXSTRLEN]; /* OEM information */ }; +/* + * Members in acpi_bix are reordered so that the first part is compatible + * with acpi_bif. + */ +struct acpi_bix { +/* _BIF-compatible */ + uint32_t units; /* Power Unit (mW or mA). */ +#define ACPI_BIX_UNITS_MW 0 /* Capacity in mWh, rate in mW. */ +#define ACPI_BIX_UNITS_MA 1 /* Capacity in mAh, rate in mA. */ + uint32_t dcap; /* Design Capacity */ + uint32_t lfcap; /* Last Full capacity */ + uint32_t btech; /* Battery Technology */ + uint32_t dvol; /* Design voltage (mV) */ + uint32_t wcap; /* WARN capacity */ + uint32_t lcap; /* Low capacity */ + uint32_t gra1; /* Granularity 1 (Warn to Low) */ + uint32_t gra2; /* Granularity 2 (Full to Warn) */ + char model[ACPI_CMBAT_MAXSTRLEN]; /* model identifier */ + char serial[ACPI_CMBAT_MAXSTRLEN]; /* Serial number */ + char type[ACPI_CMBAT_MAXSTRLEN]; /* Type */ + char oeminfo[ACPI_CMBAT_MAXSTRLEN]; /* OEM information */ + /* ACPI 4.0 or later */ + uint16_t rev; /* Revision */ +#define ACPI_BIX_REV_0 0 /* ACPI 4.0 _BIX */ +#define ACPI_BIX_REV_1 1 /* ACPI 6.0 _BIX */ +#define ACPI_BIX_REV_BIF 0xffff /* _BIF */ +#define ACPI_BIX_REV_MIN_CHECK(x, min) \ + (((min) == ACPI_BIX_REV_BIF) ? ((x) == ACPI_BIX_REV_BIF) : \ + (((x) == ACPI_BIX_REV_BIF) ? 0 : ((x) >= (min)))) + uint32_t cycles; /* Cycle Count */ + uint32_t accuracy; /* Measurement Accuracy */ + uint32_t stmax; /* Max Sampling Time */ + uint32_t stmin; /* Min Sampling Time */ + uint32_t aimax; /* Max Average Interval */ + uint32_t aimin; /* Min Average Interval */ + /* ACPI 6.0 or later */ + uint32_t scap; /* Battery Swapping Capability */ +#define ACPI_BIX_SCAP_NO 0x00000000 +#define ACPI_BIX_SCAP_COLD 0x00000001 +#define ACPI_BIX_SCAP_HOT 0x00000010 + uint8_t bix_reserved[58]; /* padding */ +}; + +#if 0 +/* acpi_bix in the original order just for reference */ +struct acpi_bix { + uint16_t rev; /* Revision */ + uint32_t units; /* Power Unit (mW or mA). */ + uint32_t dcap; /* Design Capacity */ + uint32_t lfcap; /* Last Full capacity */ + uint32_t btech; /* Battery Technology */ + uint32_t dvol; /* Design voltage (mV) */ + uint32_t wcap; /* Design Capacity of Warning */ + uint32_t lcap; /* Design Capacity of Low */ + uint32_t cycles; /* Cycle Count */ + uint32_t accuracy; /* Measurement Accuracy */ + uint32_t stmax; /* Max Sampling Time */ + uint32_t stmin; /* Min Sampling Time */ + uint32_t aimax; /* Max Average Interval */ + uint32_t aimin; /* Min Average Interval */ + uint32_t gra1; /* Granularity 1 (Warn to Low) */ + uint32_t gra2; /* Granularity 2 (Full to Warn) */ + char model[ACPI_CMBAT_MAXSTRLEN]; /* model identifier */ + char serial[ACPI_CMBAT_MAXSTRLEN]; /* Serial number */ + char type[ACPI_CMBAT_MAXSTRLEN]; /* Type */ + char oeminfo[ACPI_CMBAT_MAXSTRLEN]; /* OEM information */ + uint32_t scap; /* Battery Swapping Capability */ +}; +#endif + struct acpi_bst { uint32_t state; /* Battery State */ uint32_t rate; /* Present Rate */ uint32_t cap; /* Remaining Capacity */ uint32_t volt; /* Present Voltage */ }; /* * Note that the following definitions represent status bits for internal * driver state. The first three of them (charging, discharging and critical) * conveninetly conform to ACPI specification of status returned by _BST * method. Other definitions (not present, etc) are synthetic. * Also note that according to the specification the charging and discharging * status bits must not be set at the same time. */ #define ACPI_BATT_STAT_DISCHARG 0x0001 #define ACPI_BATT_STAT_CHARGING 0x0002 #define ACPI_BATT_STAT_CRITICAL 0x0004 #define ACPI_BATT_STAT_INVALID \ (ACPI_BATT_STAT_DISCHARG | ACPI_BATT_STAT_CHARGING) #define ACPI_BATT_STAT_BST_MASK \ (ACPI_BATT_STAT_INVALID | ACPI_BATT_STAT_CRITICAL) #define ACPI_BATT_STAT_NOT_PRESENT ACPI_BATT_STAT_BST_MASK +/* For backward compatibility */ +union acpi_battery_ioctl_arg_v1 { + int unit; /* Device unit or ACPI_BATTERY_ALL_UNITS. */ + + struct acpi_battinfo battinfo; + + struct acpi_bif bif; + struct acpi_bst bst; +}; union acpi_battery_ioctl_arg { int unit; /* Device unit or ACPI_BATTERY_ALL_UNITS. */ struct acpi_battinfo battinfo; + struct acpi_bix bix; struct acpi_bif bif; struct acpi_bst bst; }; #define ACPI_BATTERY_ALL_UNITS (-1) -#define ACPI_BATT_UNKNOWN 0xffffffff /* _BST or _BIF value unknown. */ +#define ACPI_BATT_UNKNOWN 0xffffffff /* _BST or _BI[FX] value unknown. */ /* Common battery ioctls */ #define ACPIIO_BATT_GET_UNITS _IOR('B', 0x01, int) #define ACPIIO_BATT_GET_BATTINFO _IOWR('B', 0x03, union acpi_battery_ioctl_arg) -#define ACPIIO_BATT_GET_BIF _IOWR('B', 0x10, union acpi_battery_ioctl_arg) +#define ACPIIO_BATT_GET_BATTINFO_V1 _IOWR('B', 0x03, union acpi_battery_ioctl_arg_v1) +#define ACPIIO_BATT_GET_BIF _IOWR('B', 0x10, union acpi_battery_ioctl_arg_v1) +#define ACPIIO_BATT_GET_BIX _IOWR('B', 0x10, union acpi_battery_ioctl_arg) #define ACPIIO_BATT_GET_BST _IOWR('B', 0x11, union acpi_battery_ioctl_arg) +#define ACPIIO_BATT_GET_BST_V1 _IOWR('B', 0x11, union acpi_battery_ioctl_arg_v1) /* Control Method battery ioctls (deprecated) */ #define ACPIIO_CMBAT_GET_BIF ACPIIO_BATT_GET_BIF #define ACPIIO_CMBAT_GET_BST ACPIIO_BATT_GET_BST /* Get AC adapter status. */ #define ACPIIO_ACAD_GET_STATUS _IOR('A', 1, int) #ifdef _KERNEL typedef int (*acpi_ioctl_fn)(u_long cmd, caddr_t addr, void *arg); extern int acpi_register_ioctl(u_long cmd, acpi_ioctl_fn fn, void *arg); extern void acpi_deregister_ioctl(u_long cmd, acpi_ioctl_fn fn); #endif #endif /* !_ACPIIO_H_ */ Index: stable/11/sys/dev/acpica/acpivar.h =================================================================== --- stable/11/sys/dev/acpica/acpivar.h (revision 359075) +++ stable/11/sys/dev/acpica/acpivar.h (revision 359076) @@ -1,514 +1,518 @@ /*- * Copyright (c) 2000 Mitsuru IWASAKI * Copyright (c) 2000 Michael Smith * Copyright (c) 2000 BSDi * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #ifndef _ACPIVAR_H_ #define _ACPIVAR_H_ #ifdef _KERNEL #include "acpi_if.h" #include "bus_if.h" #include #include #include #include #include #include #include #include #include struct apm_clone_data; struct acpi_softc { device_t acpi_dev; struct cdev *acpi_dev_t; int acpi_enabled; int acpi_sstate; int acpi_sleep_disabled; int acpi_resources_reserved; struct sysctl_ctx_list acpi_sysctl_ctx; struct sysctl_oid *acpi_sysctl_tree; int acpi_power_button_sx; int acpi_sleep_button_sx; int acpi_lid_switch_sx; int acpi_standby_sx; int acpi_suspend_sx; int acpi_sleep_delay; int acpi_s4bios; int acpi_do_disable; int acpi_verbose; int acpi_handle_reboot; vm_offset_t acpi_wakeaddr; vm_paddr_t acpi_wakephys; int acpi_next_sstate; /* Next suspend Sx state. */ struct apm_clone_data *acpi_clone; /* Pseudo-dev for devd(8). */ STAILQ_HEAD(,apm_clone_data) apm_cdevs; /* All apm/apmctl/acpi cdevs. */ struct callout susp_force_to; /* Force suspend if no acks. */ }; struct acpi_device { /* ACPI ivars */ ACPI_HANDLE ad_handle; void *ad_private; int ad_flags; /* Resources */ struct resource_list ad_rl; }; /* Track device (/dev/{apm,apmctl} and /dev/acpi) notification status. */ struct apm_clone_data { STAILQ_ENTRY(apm_clone_data) entries; struct cdev *cdev; int flags; #define ACPI_EVF_NONE 0 /* /dev/apm semantics */ #define ACPI_EVF_DEVD 1 /* /dev/acpi is handled via devd(8) */ #define ACPI_EVF_WRITE 2 /* Device instance is opened writable. */ int notify_status; #define APM_EV_NONE 0 /* Device not yet aware of pending sleep. */ #define APM_EV_NOTIFIED 1 /* Device saw next sleep state. */ #define APM_EV_ACKED 2 /* Device agreed sleep can occur. */ struct acpi_softc *acpi_sc; struct selinfo sel_read; }; #define ACPI_PRW_MAX_POWERRES 8 struct acpi_prw_data { ACPI_HANDLE gpe_handle; int gpe_bit; int lowest_wake; ACPI_OBJECT power_res[ACPI_PRW_MAX_POWERRES]; int power_res_count; }; /* Flags for each device defined in the AML namespace. */ #define ACPI_FLAG_WAKE_ENABLED 0x1 /* Macros for extracting parts of a PCI address from an _ADR value. */ #define ACPI_ADR_PCI_SLOT(adr) (((adr) & 0xffff0000) >> 16) #define ACPI_ADR_PCI_FUNC(adr) ((adr) & 0xffff) /* * Entry points to ACPI from above are global functions defined in this * file, sysctls, and I/O on the control device. Entry points from below * are interrupts (the SCI), notifies, task queue threads, and the thermal * zone polling thread. * * ACPI tables and global shared data are protected by a global lock * (acpi_mutex). * * Each ACPI device can have its own driver-specific mutex for protecting * shared access to local data. The ACPI_LOCK macros handle mutexes. * * Drivers that need to serialize access to functions (e.g., to route * interrupts, get/set control paths, etc.) should use the sx lock macros * (ACPI_SERIAL). * * ACPI-CA handles its own locking and should not be called with locks held. * * The most complicated path is: * GPE -> EC runs _Qxx -> _Qxx reads EC space -> GPE */ extern struct mtx acpi_mutex; #define ACPI_LOCK(sys) mtx_lock(&sys##_mutex) #define ACPI_UNLOCK(sys) mtx_unlock(&sys##_mutex) #define ACPI_LOCK_ASSERT(sys) mtx_assert(&sys##_mutex, MA_OWNED); #define ACPI_LOCK_DECL(sys, name) \ static struct mtx sys##_mutex; \ MTX_SYSINIT(sys##_mutex, &sys##_mutex, name, MTX_DEF) #define ACPI_SERIAL_BEGIN(sys) sx_xlock(&sys##_sxlock) #define ACPI_SERIAL_END(sys) sx_xunlock(&sys##_sxlock) #define ACPI_SERIAL_ASSERT(sys) sx_assert(&sys##_sxlock, SX_XLOCKED); #define ACPI_SERIAL_DECL(sys, name) \ static struct sx sys##_sxlock; \ SX_SYSINIT(sys##_sxlock, &sys##_sxlock, name) /* * ACPI CA does not define layers for non-ACPI CA drivers. * We define some here within the range provided. */ #define ACPI_AC_ADAPTER 0x00010000 #define ACPI_BATTERY 0x00020000 #define ACPI_BUS 0x00040000 #define ACPI_BUTTON 0x00080000 #define ACPI_EC 0x00100000 #define ACPI_FAN 0x00200000 #define ACPI_POWERRES 0x00400000 #define ACPI_PROCESSOR 0x00800000 #define ACPI_THERMAL 0x01000000 #define ACPI_TIMER 0x02000000 #define ACPI_OEM 0x04000000 /* * Constants for different interrupt models used with acpi_SetIntrModel(). */ #define ACPI_INTR_PIC 0 #define ACPI_INTR_APIC 1 #define ACPI_INTR_SAPIC 2 /* * Various features and capabilities for the acpi_get_features() method. * In particular, these are used for the ACPI 3.0 _PDC and _OSC methods. * See the Intel document titled "Intel Processor Vendor-Specific ACPI", * number 302223-007. */ #define ACPI_CAP_PERF_MSRS (1 << 0) /* Intel SpeedStep PERF_CTL MSRs */ #define ACPI_CAP_C1_IO_HALT (1 << 1) /* Intel C1 "IO then halt" sequence */ #define ACPI_CAP_THR_MSRS (1 << 2) /* Intel OnDemand throttling MSRs */ #define ACPI_CAP_SMP_SAME (1 << 3) /* MP C1, Px, and Tx (all the same) */ #define ACPI_CAP_SMP_SAME_C3 (1 << 4) /* MP C2 and C3 (all the same) */ #define ACPI_CAP_SMP_DIFF_PX (1 << 5) /* MP Px (different, using _PSD) */ #define ACPI_CAP_SMP_DIFF_CX (1 << 6) /* MP Cx (different, using _CSD) */ #define ACPI_CAP_SMP_DIFF_TX (1 << 7) /* MP Tx (different, using _TSD) */ #define ACPI_CAP_SMP_C1_NATIVE (1 << 8) /* MP C1 support other than halt */ #define ACPI_CAP_SMP_C3_NATIVE (1 << 9) /* MP C2 and C3 support */ #define ACPI_CAP_PX_HW_COORD (1 << 11) /* Intel P-state HW coordination */ #define ACPI_CAP_INTR_CPPC (1 << 12) /* Native Interrupt Handling for Collaborative Processor Performance Control notifications */ #define ACPI_CAP_HW_DUTY_C (1 << 13) /* Hardware Duty Cycling */ /* * Quirk flags. * * ACPI_Q_BROKEN: Disables all ACPI support. * ACPI_Q_TIMER: Disables support for the ACPI timer. * ACPI_Q_MADT_IRQ0: Specifies that ISA IRQ 0 is wired up to pin 0 of the * first APIC and that the MADT should force that by ignoring the PC-AT * compatible flag and ignoring overrides that redirect IRQ 0 to pin 2. */ extern int acpi_quirks; #define ACPI_Q_OK 0 #define ACPI_Q_BROKEN (1 << 0) #define ACPI_Q_TIMER (1 << 1) #define ACPI_Q_MADT_IRQ0 (1 << 2) /* * Note that the low ivar values are reserved to provide * interface compatibility with ISA drivers which can also * attach to ACPI. */ #define ACPI_IVAR_HANDLE 0x100 #define ACPI_IVAR_UNUSED 0x101 /* Unused/reserved. */ #define ACPI_IVAR_PRIVATE 0x102 #define ACPI_IVAR_FLAGS 0x103 /* * Accessor functions for our ivars. Default value for BUS_READ_IVAR is * (type) 0. The accessor functions don't check return values. */ #define __ACPI_BUS_ACCESSOR(varp, var, ivarp, ivar, type) \ \ static __inline type varp ## _get_ ## var(device_t dev) \ { \ uintptr_t v = 0; \ BUS_READ_IVAR(device_get_parent(dev), dev, \ ivarp ## _IVAR_ ## ivar, &v); \ return ((type) v); \ } \ \ static __inline void varp ## _set_ ## var(device_t dev, type t) \ { \ uintptr_t v = (uintptr_t) t; \ BUS_WRITE_IVAR(device_get_parent(dev), dev, \ ivarp ## _IVAR_ ## ivar, v); \ } __ACPI_BUS_ACCESSOR(acpi, handle, ACPI, HANDLE, ACPI_HANDLE) __ACPI_BUS_ACCESSOR(acpi, private, ACPI, PRIVATE, void *) __ACPI_BUS_ACCESSOR(acpi, flags, ACPI, FLAGS, int) void acpi_fake_objhandler(ACPI_HANDLE h, void *data); static __inline device_t acpi_get_device(ACPI_HANDLE handle) { void *dev = NULL; AcpiGetData(handle, acpi_fake_objhandler, &dev); return ((device_t)dev); } static __inline ACPI_OBJECT_TYPE acpi_get_type(device_t dev) { ACPI_HANDLE h; ACPI_OBJECT_TYPE t; if ((h = acpi_get_handle(dev)) == NULL) return (ACPI_TYPE_NOT_FOUND); if (ACPI_FAILURE(AcpiGetType(h, &t))) return (ACPI_TYPE_NOT_FOUND); return (t); } /* Find the difference between two PM tick counts. */ static __inline uint32_t acpi_TimerDelta(uint32_t end, uint32_t start) { if (end < start && (AcpiGbl_FADT.Flags & ACPI_FADT_32BIT_TIMER) == 0) end |= 0x01000000; return (end - start); } #ifdef ACPI_DEBUGGER void acpi_EnterDebugger(void); #endif #ifdef ACPI_DEBUG #include #define STEP(x) do {printf x, printf("\n"); cngetc();} while (0) #else #define STEP(x) #endif #define ACPI_VPRINT(dev, acpi_sc, x...) do { \ if (acpi_get_verbose(acpi_sc)) \ device_printf(dev, x); \ } while (0) /* Values for the device _STA (status) method. */ #define ACPI_STA_PRESENT (1 << 0) #define ACPI_STA_ENABLED (1 << 1) #define ACPI_STA_SHOW_IN_UI (1 << 2) #define ACPI_STA_FUNCTIONAL (1 << 3) #define ACPI_STA_BATT_PRESENT (1 << 4) #define ACPI_DEVINFO_PRESENT(x, flags) \ (((x) & (flags)) == (flags)) #define ACPI_DEVICE_PRESENT(x) \ ACPI_DEVINFO_PRESENT(x, ACPI_STA_PRESENT | ACPI_STA_FUNCTIONAL) #define ACPI_BATTERY_PRESENT(x) \ ACPI_DEVINFO_PRESENT(x, ACPI_STA_PRESENT | ACPI_STA_FUNCTIONAL | \ ACPI_STA_BATT_PRESENT) /* Callback function type for walking subtables within a table. */ typedef void acpi_subtable_handler(ACPI_SUBTABLE_HEADER *, void *); BOOLEAN acpi_DeviceIsPresent(device_t dev); BOOLEAN acpi_BatteryIsPresent(device_t dev); ACPI_STATUS acpi_GetHandleInScope(ACPI_HANDLE parent, char *path, ACPI_HANDLE *result); ACPI_BUFFER *acpi_AllocBuffer(int size); ACPI_STATUS acpi_ConvertBufferToInteger(ACPI_BUFFER *bufp, UINT32 *number); ACPI_STATUS acpi_GetInteger(ACPI_HANDLE handle, char *path, UINT32 *number); ACPI_STATUS acpi_SetInteger(ACPI_HANDLE handle, char *path, UINT32 number); ACPI_STATUS acpi_ForeachPackageObject(ACPI_OBJECT *obj, void (*func)(ACPI_OBJECT *comp, void *arg), void *arg); ACPI_STATUS acpi_FindIndexedResource(ACPI_BUFFER *buf, int index, ACPI_RESOURCE **resp); ACPI_STATUS acpi_AppendBufferResource(ACPI_BUFFER *buf, ACPI_RESOURCE *res); ACPI_STATUS acpi_EvaluateOSC(ACPI_HANDLE handle, uint8_t *uuid, int revision, int count, uint32_t *caps_in, uint32_t *caps_out, bool query); ACPI_STATUS acpi_OverrideInterruptLevel(UINT32 InterruptNumber); ACPI_STATUS acpi_SetIntrModel(int model); int acpi_ReqSleepState(struct acpi_softc *sc, int state); int acpi_AckSleepState(struct apm_clone_data *clone, int error); ACPI_STATUS acpi_SetSleepState(struct acpi_softc *sc, int state); int acpi_wake_set_enable(device_t dev, int enable); int acpi_parse_prw(ACPI_HANDLE h, struct acpi_prw_data *prw); ACPI_STATUS acpi_Startup(void); void acpi_UserNotify(const char *subsystem, ACPI_HANDLE h, uint8_t notify); int acpi_bus_alloc_gas(device_t dev, int *type, int *rid, ACPI_GENERIC_ADDRESS *gas, struct resource **res, u_int flags); void acpi_walk_subtables(void *first, void *end, acpi_subtable_handler *handler, void *arg); BOOLEAN acpi_MatchHid(ACPI_HANDLE h, const char *hid); struct acpi_parse_resource_set { void (*set_init)(device_t dev, void *arg, void **context); void (*set_done)(device_t dev, void *context); void (*set_ioport)(device_t dev, void *context, uint64_t base, uint64_t length); void (*set_iorange)(device_t dev, void *context, uint64_t low, uint64_t high, uint64_t length, uint64_t align); void (*set_memory)(device_t dev, void *context, uint64_t base, uint64_t length); void (*set_memoryrange)(device_t dev, void *context, uint64_t low, uint64_t high, uint64_t length, uint64_t align); void (*set_irq)(device_t dev, void *context, uint8_t *irq, int count, int trig, int pol); void (*set_ext_irq)(device_t dev, void *context, uint32_t *irq, int count, int trig, int pol); void (*set_drq)(device_t dev, void *context, uint8_t *drq, int count); void (*set_start_dependent)(device_t dev, void *context, int preference); void (*set_end_dependent)(device_t dev, void *context); }; extern struct acpi_parse_resource_set acpi_res_parse_set; int acpi_identify(void); void acpi_config_intr(device_t dev, ACPI_RESOURCE *res); ACPI_STATUS acpi_lookup_irq_resource(device_t dev, int rid, struct resource *res, ACPI_RESOURCE *acpi_res); ACPI_STATUS acpi_parse_resources(device_t dev, ACPI_HANDLE handle, struct acpi_parse_resource_set *set, void *arg); struct resource *acpi_alloc_sysres(device_t child, int type, int *rid, rman_res_t start, rman_res_t end, rman_res_t count, u_int flags); /* ACPI event handling */ UINT32 acpi_event_power_button_sleep(void *context); UINT32 acpi_event_power_button_wake(void *context); UINT32 acpi_event_sleep_button_sleep(void *context); UINT32 acpi_event_sleep_button_wake(void *context); #define ACPI_EVENT_PRI_FIRST 0 #define ACPI_EVENT_PRI_DEFAULT 10000 #define ACPI_EVENT_PRI_LAST 20000 typedef void (*acpi_event_handler_t)(void *, int); EVENTHANDLER_DECLARE(acpi_sleep_event, acpi_event_handler_t); EVENTHANDLER_DECLARE(acpi_wakeup_event, acpi_event_handler_t); /* Device power control. */ ACPI_STATUS acpi_pwr_wake_enable(ACPI_HANDLE consumer, int enable); ACPI_STATUS acpi_pwr_switch_consumer(ACPI_HANDLE consumer, int state); int acpi_device_pwr_for_sleep(device_t bus, device_t dev, int *dstate); /* APM emulation */ void acpi_apm_init(struct acpi_softc *); /* Misc. */ static __inline struct acpi_softc * acpi_device_get_parent_softc(device_t child) { device_t parent; parent = device_get_parent(child); if (parent == NULL) return (NULL); return (device_get_softc(parent)); } static __inline int acpi_get_verbose(struct acpi_softc *sc) { if (sc) return (sc->acpi_verbose); return (0); } char *acpi_name(ACPI_HANDLE handle); int acpi_avoid(ACPI_HANDLE handle); int acpi_disabled(char *subsys); int acpi_machdep_init(device_t dev); void acpi_install_wakeup_handler(struct acpi_softc *sc); int acpi_sleep_machdep(struct acpi_softc *sc, int state); int acpi_wakeup_machdep(struct acpi_softc *sc, int state, int sleep_result, int intr_enabled); int acpi_table_quirks(int *quirks); int acpi_machdep_quirks(int *quirks); uint32_t hpet_get_uid(device_t dev); /* Battery Abstraction. */ struct acpi_battinfo; int acpi_battery_register(device_t dev); int acpi_battery_remove(device_t dev); int acpi_battery_get_units(void); int acpi_battery_get_info_expire(void); int acpi_battery_bst_valid(struct acpi_bst *bst); -int acpi_battery_bif_valid(struct acpi_bif *bif); +int acpi_battery_bix_valid(struct acpi_bix *bix); int acpi_battery_get_battinfo(device_t dev, struct acpi_battinfo *info); /* Embedded controller. */ void acpi_ec_ecdt_probe(device_t); /* AC adapter interface. */ int acpi_acad_get_acline(int *); /* Package manipulation convenience functions. */ #define ACPI_PKG_VALID(pkg, size) \ ((pkg) != NULL && (pkg)->Type == ACPI_TYPE_PACKAGE && \ (pkg)->Package.Count >= (size)) +#define ACPI_PKG_VALID_EQ(pkg, size) \ + ((pkg) != NULL && (pkg)->Type == ACPI_TYPE_PACKAGE && \ + (pkg)->Package.Count == (size)) int acpi_PkgInt(ACPI_OBJECT *res, int idx, UINT64 *dst); int acpi_PkgInt32(ACPI_OBJECT *res, int idx, uint32_t *dst); +int acpi_PkgInt16(ACPI_OBJECT *res, int idx, uint16_t *dst); int acpi_PkgStr(ACPI_OBJECT *res, int idx, void *dst, size_t size); int acpi_PkgGas(device_t dev, ACPI_OBJECT *res, int idx, int *type, int *rid, struct resource **dst, u_int flags); int acpi_PkgFFH_IntelCpu(ACPI_OBJECT *res, int idx, int *vendor, int *class, uint64_t *address, int *accsize); ACPI_HANDLE acpi_GetReference(ACPI_HANDLE scope, ACPI_OBJECT *obj); /* * Base level for BUS_ADD_CHILD. Special devices are added at orders less * than this, and normal devices at or above this level. This keeps the * probe order sorted so that things like sysresource are available before * their children need them. */ #define ACPI_DEV_BASE_ORDER 100 /* Default maximum number of tasks to enqueue. */ #ifndef ACPI_MAX_TASKS #define ACPI_MAX_TASKS MAX(32, MAXCPU * 4) #endif /* Default number of task queue threads to start. */ #ifndef ACPI_MAX_THREADS #define ACPI_MAX_THREADS 3 #endif /* Use the device logging level for ktr(4). */ #define KTR_ACPI KTR_DEV SYSCTL_DECL(_debug_acpi); /* * Map a PXM to a VM domain. * * Returns the VM domain ID if found, or -1 if not found / invalid. */ int acpi_map_pxm_to_vm_domainid(int pxm); int acpi_get_cpus(device_t dev, device_t child, enum cpu_sets op, size_t setsize, cpuset_t *cpuset); int acpi_get_domain(device_t dev, device_t child, int *domain); #endif /* _KERNEL */ #endif /* !_ACPIVAR_H_ */ Index: stable/11/usr.sbin/acpi/acpiconf/acpiconf.c =================================================================== --- stable/11/usr.sbin/acpi/acpiconf/acpiconf.c (revision 359075) +++ stable/11/usr.sbin/acpi/acpiconf/acpiconf.c (revision 359076) @@ -1,249 +1,276 @@ /*- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD * * Copyright (c) 1999 Mitsuru IWASAKI * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $Id: acpiconf.c,v 1.5 2000/08/08 14:12:19 iwasaki Exp $ * $FreeBSD$ */ #include #include #include #include #include #include #include #include #include #define ACPIDEV "/dev/acpi" static int acpifd; static void acpi_init(void) { acpifd = open(ACPIDEV, O_RDWR); if (acpifd == -1) acpifd = open(ACPIDEV, O_RDONLY); if (acpifd == -1) err(EX_OSFILE, ACPIDEV); } /* Prepare to sleep and then wait for the signal that sleeping can occur. */ static void acpi_sleep(int sleep_type) { int ret; /* Notify OS that we want to sleep. devd(8) gets this notify. */ ret = ioctl(acpifd, ACPIIO_REQSLPSTATE, &sleep_type); if (ret != 0) err(EX_IOERR, "request sleep type (%d) failed", sleep_type); } /* Ack or abort a pending suspend request. */ static void acpi_sleep_ack(int err_val) { int ret; ret = ioctl(acpifd, ACPIIO_ACKSLPSTATE, &err_val); if (ret != 0) err(EX_IOERR, "ack sleep type failed"); } /* should be a acpi define, but doesn't appear to be */ #define UNKNOWN_CAP 0xffffffff #define UNKNOWN_VOLTAGE 0xffffffff static int acpi_battinfo(int num) { union acpi_battery_ioctl_arg battio; const char *pwr_units; int hours, min, amp; uint32_t volt; if (num < 0 || num > 64) err(EX_USAGE, "invalid battery %d", num); /* Print battery design information. */ battio.unit = num; - if (ioctl(acpifd, ACPIIO_BATT_GET_BIF, &battio) == -1) + if (ioctl(acpifd, ACPIIO_BATT_GET_BIX, &battio) == -1) err(EX_IOERR, "get battery info (%d) failed", num); - amp = battio.bif.units; + amp = battio.bix.units; pwr_units = amp ? "mA" : "mW"; - if (battio.bif.dcap == UNKNOWN_CAP) + if (battio.bix.dcap == UNKNOWN_CAP) printf("Design capacity:\tunknown\n"); else - printf("Design capacity:\t%d %sh\n", battio.bif.dcap, + printf("Design capacity:\t%d %sh\n", battio.bix.dcap, pwr_units); - if (battio.bif.lfcap == UNKNOWN_CAP) + if (battio.bix.lfcap == UNKNOWN_CAP) printf("Last full capacity:\tunknown\n"); else - printf("Last full capacity:\t%d %sh\n", battio.bif.lfcap, + printf("Last full capacity:\t%d %sh\n", battio.bix.lfcap, pwr_units); - printf("Technology:\t\t%s\n", battio.bif.btech == 0 ? + printf("Technology:\t\t%s\n", battio.bix.btech == 0 ? "primary (non-rechargeable)" : "secondary (rechargeable)"); - if (battio.bif.dvol == UNKNOWN_CAP) + if (ACPI_BIX_REV_MIN_CHECK(battio.bix.rev, ACPI_BIX_REV_1)) { + printf("Battery Swappable Capability:\t"); + if (battio.bix.scap == ACPI_BIX_SCAP_NO) + printf("Non-swappable\n"); + else if (battio.bix.scap == ACPI_BIX_SCAP_COLD) + printf("cold swap\n"); + else if (battio.bix.scap == ACPI_BIX_SCAP_HOT) + printf("hot swap\n"); + else + printf("unknown\n"); + } + if (battio.bix.dvol == UNKNOWN_CAP) printf("Design voltage:\t\tunknown\n"); else - printf("Design voltage:\t\t%d mV\n", battio.bif.dvol); - printf("Capacity (warn):\t%d %sh\n", battio.bif.wcap, pwr_units); - printf("Capacity (low):\t\t%d %sh\n", battio.bif.lcap, pwr_units); - printf("Low/warn granularity:\t%d %sh\n", battio.bif.gra1, pwr_units); - printf("Warn/full granularity:\t%d %sh\n", battio.bif.gra2, pwr_units); - printf("Model number:\t\t%s\n", battio.bif.model); - printf("Serial number:\t\t%s\n", battio.bif.serial); - printf("Type:\t\t\t%s\n", battio.bif.type); - printf("OEM info:\t\t%s\n", battio.bif.oeminfo); + printf("Design voltage:\t\t%d mV\n", battio.bix.dvol); + printf("Capacity (warn):\t%d %sh\n", battio.bix.wcap, pwr_units); + printf("Capacity (low):\t\t%d %sh\n", battio.bix.lcap, pwr_units); + if (ACPI_BIX_REV_MIN_CHECK(battio.bix.rev, ACPI_BIX_REV_0)) { + if (battio.bix.cycles != ACPI_BATT_UNKNOWN) + printf("Cycle Count:\t\t%d\n", battio.bix.cycles); + printf("Mesurement Accuracy:\t%d %%\n", + battio.bix.accuracy / 1000); + if (battio.bix.stmax != ACPI_BATT_UNKNOWN) + printf("Max Sampling Time:\t%d ms\n", + battio.bix.stmax); + if (battio.bix.stmin != ACPI_BATT_UNKNOWN) + printf("Min Sampling Time:\t%d ms\n", + battio.bix.stmin); + printf("Max Average Interval:\t%d ms\n", + battio.bix.aimax); + printf("Min Average Interval:\t%d ms\n", + battio.bix.aimin); + } + printf("Low/warn granularity:\t%d %sh\n", battio.bix.gra1, pwr_units); + printf("Warn/full granularity:\t%d %sh\n", battio.bix.gra2, pwr_units); + printf("Model number:\t\t%s\n", battio.bix.model); + printf("Serial number:\t\t%s\n", battio.bix.serial); + printf("Type:\t\t\t%s\n", battio.bix.type); + printf("OEM info:\t\t%s\n", battio.bix.oeminfo); /* Fetch battery voltage information. */ volt = UNKNOWN_VOLTAGE; battio.unit = num; if (ioctl(acpifd, ACPIIO_BATT_GET_BST, &battio) == -1) err(EX_IOERR, "get battery status (%d) failed", num); if (battio.bst.state != ACPI_BATT_STAT_NOT_PRESENT) volt = battio.bst.volt; /* Print current battery state information. */ battio.unit = num; if (ioctl(acpifd, ACPIIO_BATT_GET_BATTINFO, &battio) == -1) err(EX_IOERR, "get battery user info (%d) failed", num); if (battio.battinfo.state != ACPI_BATT_STAT_NOT_PRESENT) { const char *state; switch (battio.battinfo.state & ACPI_BATT_STAT_BST_MASK) { case 0: state = "high"; break; case ACPI_BATT_STAT_DISCHARG: state = "discharging"; break; case ACPI_BATT_STAT_CHARGING: state = "charging"; break; case ACPI_BATT_STAT_CRITICAL: state = "critical"; break; case ACPI_BATT_STAT_DISCHARG | ACPI_BATT_STAT_CRITICAL: state = "critical discharging"; break; case ACPI_BATT_STAT_CHARGING | ACPI_BATT_STAT_CRITICAL: state = "critical charging"; break; default: state = "invalid"; } printf("State:\t\t\t%s\n", state); if (battio.battinfo.cap == -1) printf("Remaining capacity:\tunknown\n"); else printf("Remaining capacity:\t%d%%\n", battio.battinfo.cap); if (battio.battinfo.min == -1) printf("Remaining time:\t\tunknown\n"); else { hours = battio.battinfo.min / 60; min = battio.battinfo.min % 60; printf("Remaining time:\t\t%d:%02d\n", hours, min); } if (battio.battinfo.rate == -1) printf("Present rate:\t\tunknown\n"); else if (amp && volt != UNKNOWN_VOLTAGE) { printf("Present rate:\t\t%d mA (%d mW)\n", battio.battinfo.rate, battio.battinfo.rate * volt / 1000); } else printf("Present rate:\t\t%d %s\n", battio.battinfo.rate, pwr_units); } else printf("State:\t\t\tnot present\n"); /* Print battery voltage information. */ if (volt == UNKNOWN_VOLTAGE) printf("Present voltage:\tunknown\n"); else printf("Present voltage:\t%d mV\n", volt); return (0); } static void usage(const char* prog) { printf("usage: %s [-h] [-i batt] [-k ack] [-s 1-4]\n", prog); exit(0); } int main(int argc, char *argv[]) { char *prog; int c, sleep_type; prog = argv[0]; if (argc < 2) usage(prog); /* NOTREACHED */ sleep_type = -1; acpi_init(); while ((c = getopt(argc, argv, "hi:k:s:")) != -1) { switch (c) { case 'i': acpi_battinfo(atoi(optarg)); break; case 'k': acpi_sleep_ack(atoi(optarg)); break; case 's': if (optarg[0] == 'S') sleep_type = optarg[1] - '0'; else sleep_type = optarg[0] - '0'; if (sleep_type < 1 || sleep_type > 4) errx(EX_USAGE, "invalid sleep type (%d)", sleep_type); break; case 'h': default: usage(prog); /* NOTREACHED */ } } argc -= optind; argv += optind; if (sleep_type != -1) acpi_sleep(sleep_type); close(acpifd); exit (0); } Index: stable/11 =================================================================== --- stable/11 (revision 359075) +++ stable/11 (revision 359076) Property changes on: stable/11 ___________________________________________________________________ Modified: svn:mergeinfo ## -0,0 +0,1 ## Merged /head:r355574,358095,358395 Index: stable/12/share/man/man4/Makefile =================================================================== --- stable/12/share/man/man4/Makefile (revision 359075) +++ stable/12/share/man/man4/Makefile (revision 359076) @@ -1,1045 +1,1046 @@ # @(#)Makefile 8.1 (Berkeley) 6/18/93 # $FreeBSD$ .include PACKAGE=runtime-manuals MAN= aac.4 \ aacraid.4 \ acpi.4 \ ${_acpi_asus.4} \ ${_acpi_asus_wmi.4} \ ${_acpi_dock.4} \ ${_acpi_fujitsu.4} \ ${_acpi_hp.4} \ ${_acpi_ibm.4} \ ${_acpi_panasonic.4} \ ${_acpi_rapidstart.4} \ ${_acpi_sony.4} \ acpi_thermal.4 \ + acpi_battery.4 \ ${_acpi_toshiba.4} \ acpi_video.4 \ ${_acpi_wmi.4} \ ada.4 \ adm6996fc.4 \ adv.4 \ adw.4 \ ads111x.4 \ ae.4 \ ${_aesni.4} \ age.4 \ agp.4 \ aha.4 \ ahc.4 \ ahci.4 \ ahd.4 \ ${_aibs.4} \ aio.4 \ alc.4 \ ale.4 \ alpm.4 \ altera_atse.4 \ altera_avgen.4 \ altera_jtag_uart.4 \ altera_sdcard.4 \ altq.4 \ amdpm.4 \ ${_amdsbwd.4} \ ${_amdsmb.4} \ ${_amdsmn.4} \ ${_amdtemp.4} \ ${_bxe.4} \ amr.4 \ an.4 \ ${_aout.4} \ ${_apic.4} \ arcmsr.4 \ ${_asmc.4} \ at45d.4 \ ata.4 \ ath.4 \ ath_ahb.4 \ ath_hal.4 \ ath_pci.4 \ atkbd.4 \ atkbdc.4 \ atp.4 \ ${_atf_test_case.4} \ ${_atrtc.4} \ ${_attimer.4} \ audit.4 \ auditpipe.4 \ aue.4 \ axe.4 \ axge.4 \ bce.4 \ bcma.4 \ bfe.4 \ bge.4 \ ${_bhyve.4} \ bhnd.4 \ bhnd_chipc.4 \ bhnd_pmu.4 \ bhndb.4 \ bhndb_pci.4 \ bktr.4 \ blackhole.4 \ bnxt.4 \ bpf.4 \ bridge.4 \ bt.4 \ bwi.4 \ bwn.4 \ ${_bytgpio.4} \ ${_chvgpio.4} \ capsicum.4 \ cardbus.4 \ carp.4 \ cas.4 \ cc_cdg.4 \ cc_chd.4 \ cc_cubic.4 \ cc_dctcp.4 \ cc_hd.4 \ cc_htcp.4 \ cc_newreno.4 \ cc_vegas.4 \ ${_ccd.4} \ ccr.4 \ cd.4 \ cdce.4 \ cdceem.4 \ cfi.4 \ cfumass.4 \ ch.4 \ chromebook_platform.4 \ ciss.4 \ cloudabi.4 \ cmx.4 \ ${_coretemp.4} \ ${_cpuctl.4} \ cpufreq.4 \ crypto.4 \ ctl.4 \ cue.4 \ cxgb.4 \ cxgbe.4 \ cxgbev.4 \ cy.4 \ cyapa.4 \ da.4 \ dc.4 \ dcons.4 \ dcons_crom.4 \ ddb.4 \ de.4 \ devctl.4 \ disc.4 \ divert.4 \ ${_dpms.4} \ dpt.4 \ ds1307.4 \ ds3231.4 \ ${_dtrace_provs} \ dummynet.4 \ ed.4 \ edsc.4 \ ehci.4 \ em.4 \ ena.4 \ enc.4 \ epair.4 \ esp.4 \ est.4 \ et.4 \ etherswitch.4 \ eventtimers.4 \ exca.4 \ e6060sw.4 \ fd.4 \ fdc.4 \ fdt.4 \ fdt_pinctrl.4 \ fdtbus.4 \ ffclock.4 \ filemon.4 \ firewire.4 \ full.4 \ fwe.4 \ fwip.4 \ fwohci.4 \ fxp.4 \ gbde.4 \ gdb.4 \ gem.4 \ geom.4 \ geom_fox.4 \ geom_linux_lvm.4 \ geom_map.4 \ geom_uzip.4 \ gif.4 \ gpio.4 \ gpioiic.4 \ gpioled.4 \ gpioths.4 \ gre.4 \ h_ertt.4 \ hifn.4 \ hme.4 \ hpet.4 \ ${_hpt27xx.4} \ ${_hptiop.4} \ ${_hptmv.4} \ ${_hptnr.4} \ ${_hptrr.4} \ ${_hv_kvp.4} \ ${_hv_netvsc.4} \ ${_hv_storvsc.4} \ ${_hv_utils.4} \ ${_hv_vmbus.4} \ ${_hv_vss.4} \ hwpmc.4 \ iavf.4 \ ichsmb.4 \ ${_ichwd.4} \ icmp.4 \ icmp6.4 \ ida.4 \ if_ipsec.4 \ iflib.4 \ ifmib.4 \ ig4.4 \ igmp.4 \ iic.4 \ iic_gpiomux.4 \ iicbb.4 \ iicbus.4 \ iicmux.4 \ iicsmb.4 \ iir.4 \ ${_imcsmb.4} \ inet.4 \ inet6.4 \ intpm.4 \ intro.4 \ ${_io.4} \ ${_ioat.4} \ ip.4 \ ip6.4 \ ipfirewall.4 \ ipheth.4 \ ${_ipmi.4} \ ips.4 \ ipsec.4 \ ipw.4 \ ipwfw.4 \ isci.4 \ isl.4 \ ismt.4 \ isp.4 \ ispfw.4 \ ${_itwd.4} \ iwi.4 \ iwifw.4 \ iwm.4 \ iwmfw.4 \ iwn.4 \ iwnfw.4 \ ixgbe.4 \ ixl.4 \ jedec_dimm.4 \ jme.4 \ joy.4 \ kbdmux.4 \ keyboard.4 \ kld.4 \ ksyms.4 \ ksz8995ma.4 \ ktr.4 \ kue.4 \ lagg.4 \ le.4 \ led.4 \ lge.4 \ ${_linux.4} \ liquidio.4 \ lm75.4 \ lo.4 \ lp.4 \ lpbb.4 \ lpt.4 \ ltc430x.4 \ mac.4 \ mac_biba.4 \ mac_bsdextended.4 \ mac_ifoff.4 \ mac_lomac.4 \ mac_mls.4 \ mac_none.4 \ mac_ntpd.4 \ mac_partition.4 \ mac_portacl.4 \ mac_seeotheruids.4 \ mac_stub.4 \ mac_test.4 \ malo.4 \ md.4 \ mdio.4 \ me.4 \ mem.4 \ meteor.4 \ mfi.4 \ miibus.4 \ mk48txx.4 \ mld.4 \ mlx.4 \ mlx4en.4 \ mlx5en.4 \ mly.4 \ mmc.4 \ mmcsd.4 \ mn.4 \ mod_cc.4 \ mos.4 \ mouse.4 \ mpr.4 \ mps.4 \ mpt.4 \ mrsas.4 \ msk.4 \ mtio.4 \ multicast.4 \ muge.4 \ mvs.4 \ mwl.4 \ mwlfw.4 \ mx25l.4 \ mxge.4 \ my.4 \ nand.4 \ nandsim.4 \ ncr.4 \ ncv.4 \ ${_ndis.4} \ net80211.4 \ netdump.4 \ netfpga10g_nf10bmac.4 \ netgraph.4 \ netintro.4 \ netmap.4 \ ${_nfe.4} \ ${_nfsmb.4} \ ng_async.4 \ ngatmbase.4 \ ng_atmllc.4 \ ng_bpf.4 \ ng_bridge.4 \ ng_bt3c.4 \ ng_btsocket.4 \ ng_car.4 \ ng_ccatm.4 \ ng_cisco.4 \ ng_deflate.4 \ ng_device.4 \ nge.4 \ ng_echo.4 \ ng_eiface.4 \ ng_etf.4 \ ng_ether.4 \ ng_ether_echo.4 \ ng_frame_relay.4 \ ng_gif.4 \ ng_gif_demux.4 \ ng_h4.4 \ ng_hci.4 \ ng_hole.4 \ ng_hub.4 \ ng_iface.4 \ ng_ipfw.4 \ ng_ip_input.4 \ ng_ksocket.4 \ ng_l2cap.4 \ ng_l2tp.4 \ ng_lmi.4 \ ng_mppc.4 \ ng_nat.4 \ ng_netflow.4 \ ng_one2many.4 \ ng_patch.4 \ ng_ppp.4 \ ng_pppoe.4 \ ng_pptpgre.4 \ ng_pred1.4 \ ng_rfc1490.4 \ ng_socket.4 \ ng_source.4 \ ng_split.4 \ ng_sppp.4 \ ng_sscfu.4 \ ng_sscop.4 \ ng_tag.4 \ ng_tcpmss.4 \ ng_tee.4 \ ng_tty.4 \ ng_ubt.4 \ ng_UI.4 \ ng_uni.4 \ ng_vjc.4 \ ng_vlan.4 \ nmdm.4 \ nsp.4 \ ${_ntb.4} \ ${_ntb_hw_amd.4} \ ${_ntb_hw_intel.4} \ ${_ntb_hw_plx.4} \ ${_ntb_transport.4} \ ${_nda.4} \ ${_if_ntb.4} \ null.4 \ numa.4 \ ${_nvd.4} \ ${_nvdimm.4} \ ${_nvme.4} \ ${_nvram.4} \ ${_nvram2env.4} \ oce.4 \ ocs_fc.4\ ohci.4 \ orm.4 \ ow.4 \ ow_temp.4 \ owc.4 \ ${_padlock.4} \ pass.4 \ pccard.4 \ pccbb.4 \ pcf.4 \ pci.4 \ pcib.4 \ pcic.4 \ pcm.4 \ pcn.4 \ ${_pf.4} \ ${_pflog.4} \ ${_pfsync.4} \ pim.4 \ pms.4 \ polling.4 \ ppbus.4 \ ppc.4 \ ppi.4 \ procdesc.4 \ proto.4 \ psm.4 \ pst.4 \ pt.4 \ ptnet.4 \ pts.4 \ pty.4 \ puc.4 \ pwmc.4 \ ${_qlxge.4} \ ${_qlxgb.4} \ ${_qlxgbe.4} \ ${_qlnxe.4} \ ral.4 \ random.4 \ rc.4 \ rctl.4 \ re.4 \ rgephy.4 \ rights.4 \ rl.4 \ rndtest.4 \ route.4 \ rp.4 \ rtwn.4 \ rtwnfw.4 \ rtwn_pci.4 \ rue.4 \ sa.4 \ safe.4 \ sbp.4 \ sbp_targ.4 \ scc.4 \ sched_4bsd.4 \ sched_ule.4 \ screen.4 \ scsi.4 \ sctp.4 \ sdhci.4 \ sem.4 \ send.4 \ ses.4 \ sf.4 \ ${_sfxge.4} \ sge.4 \ siba.4 \ siftr.4 \ siis.4 \ simplebus.4 \ sio.4 \ sis.4 \ sk.4 \ ${_smartpqi.4} \ smb.4 \ smbus.4 \ smp.4 \ smsc.4 \ sn.4 \ snd_ad1816.4 \ snd_als4000.4 \ snd_atiixp.4 \ snd_cmi.4 \ snd_cs4281.4 \ snd_csa.4 \ snd_ds1.4 \ snd_emu10k1.4 \ snd_emu10kx.4 \ snd_envy24.4 \ snd_envy24ht.4 \ snd_es137x.4 \ snd_ess.4 \ snd_fm801.4 \ snd_gusc.4 \ snd_hda.4 \ snd_hdspe.4 \ snd_ich.4 \ snd_maestro3.4 \ snd_maestro.4 \ snd_mss.4 \ snd_neomagic.4 \ snd_sbc.4 \ snd_solo.4 \ snd_spicds.4 \ snd_t4dwave.4 \ snd_uaudio.4 \ snd_via8233.4 \ snd_via82c686.4 \ snd_vibes.4 \ snp.4 \ spigen.4 \ ${_spkr.4} \ splash.4 \ sppp.4 \ ste.4 \ stf.4 \ stg.4 \ stge.4 \ ${_superio.4} \ sym.4 \ syncache.4 \ syncer.4 \ syscons.4 \ sysmouse.4 \ tap.4 \ targ.4 \ tcp.4 \ tdfx.4 \ terasic_mtl.4 \ termios.4 \ textdump.4 \ ti.4 \ timecounters.4 \ tl.4 \ ${_tpm.4} \ trm.4 \ tty.4 \ tun.4 \ twa.4 \ twe.4 \ tws.4 \ tx.4 \ txp.4 \ udp.4 \ udplite.4 \ ure.4 \ vale.4 \ vga.4 \ vge.4 \ viapm.4 \ ${_viawd.4} \ ${_virtio.4} \ ${_virtio_balloon.4} \ ${_virtio_blk.4} \ ${_virtio_console.4} \ ${_virtio_random.4} \ ${_virtio_scsi.4} \ vkbd.4 \ vlan.4 \ vxlan.4 \ ${_vmm.4} \ ${_vmx.4} \ vpo.4 \ vr.4 \ vt.4 \ vte.4 \ ${_vtnet.4} \ watchdog.4 \ wb.4 \ ${_wbwd.4} \ wi.4 \ witness.4 \ wlan.4 \ wlan_acl.4 \ wlan_amrr.4 \ wlan_ccmp.4 \ wlan_tkip.4 \ wlan_wep.4 \ wlan_xauth.4 \ wmt.4 \ ${_wpi.4} \ wsp.4 \ xe.4 \ ${_xen.4} \ xhci.4 \ xl.4 \ ${_xnb.4} \ xpt.4 \ zero.4 MLINKS= ads111x.4 ads1013.4 \ ads111x.4 ads1014.4 \ ads111x.4 ads1015.4 \ ads111x.4 ads1113.4 \ ads111x.4 ads1114.4 \ ads111x.4 ads1115.4 MLINKS+=ae.4 if_ae.4 MLINKS+=age.4 if_age.4 MLINKS+=agp.4 agpgart.4 MLINKS+=alc.4 if_alc.4 MLINKS+=ale.4 if_ale.4 MLINKS+=altera_atse.4 atse.4 MLINKS+=altera_sdcard.4 altera_sdcardc.4 MLINKS+=altq.4 ALTQ.4 MLINKS+=ath.4 if_ath.4 MLINKS+=ath_pci.4 if_ath_pci.4 MLINKS+=an.4 if_an.4 MLINKS+=aue.4 if_aue.4 MLINKS+=axe.4 if_axe.4 MLINKS+=bce.4 if_bce.4 MLINKS+=bfe.4 if_bfe.4 MLINKS+=bge.4 if_bge.4 MLINKS+=bktr.4 brooktree.4 MLINKS+=bnxt.4 if_bnxt.4 MLINKS+=bridge.4 if_bridge.4 MLINKS+=bwi.4 if_bwi.4 MLINKS+=bwn.4 if_bwn.4 MLINKS+=${_bxe.4} ${_if_bxe.4} MLINKS+=cas.4 if_cas.4 MLINKS+=cdce.4 if_cdce.4 MLINKS+=cfi.4 cfid.4 MLINKS+=cloudabi.4 cloudabi32.4 \ cloudabi.4 cloudabi64.4 MLINKS+=crypto.4 cryptodev.4 MLINKS+=cue.4 if_cue.4 MLINKS+=cxgb.4 if_cxgb.4 MLINKS+=cxgbe.4 if_cxgbe.4 \ cxgbe.4 vcxgbe.4 \ cxgbe.4 if_vcxgbe.4 \ cxgbe.4 cxl.4 \ cxgbe.4 if_cxl.4 \ cxgbe.4 vcxl.4 \ cxgbe.4 if_vcxl.4 \ cxgbe.4 cc.4 \ cxgbe.4 if_cc.4 \ cxgbe.4 vcc.4 \ cxgbe.4 if_vcc.4 MLINKS+=cxgbev.4 if_cxgbev.4 \ cxgbev.4 cxlv.4 \ cxgbev.4 if_cxlv.4 \ cxgbev.4 ccv.4 \ cxgbev.4 if_ccv.4 MLINKS+=dc.4 if_dc.4 MLINKS+=de.4 if_de.4 MLINKS+=disc.4 if_disc.4 MLINKS+=ed.4 if_ed.4 MLINKS+=edsc.4 if_edsc.4 MLINKS+=em.4 if_em.4 MLINKS+=enc.4 if_enc.4 MLINKS+=epair.4 if_epair.4 MLINKS+=et.4 if_et.4 MLINKS+=fd.4 stderr.4 \ fd.4 stdin.4 \ fd.4 stdout.4 MLINKS+=fdt.4 FDT.4 MLINKS+=firewire.4 ieee1394.4 MLINKS+=fwe.4 if_fwe.4 MLINKS+=fwip.4 if_fwip.4 MLINKS+=fxp.4 if_fxp.4 MLINKS+=gem.4 if_gem.4 MLINKS+=geom.4 GEOM.4 MLINKS+=gif.4 if_gif.4 MLINKS+=gpio.4 gpiobus.4 MLINKS+=gpioths.4 dht11.4 MLINKS+=gpioths.4 dht22.4 MLINKS+=gre.4 if_gre.4 MLINKS+=hme.4 if_hme.4 MLINKS+=hpet.4 acpi_hpet.4 MLINKS+=${_hptrr.4} ${_rr232x.4} MLINKS+=${_attimer.4} ${_i8254.4} MLINKS+=ip.4 rawip.4 MLINKS+=ipfirewall.4 ipaccounting.4 \ ipfirewall.4 ipacct.4 \ ipfirewall.4 ipfw.4 MLINKS+=ipheth.4 if_ipheth.4 MLINKS+=ipw.4 if_ipw.4 MLINKS+=iwi.4 if_iwi.4 MLINKS+=iwm.4 if_iwm.4 MLINKS+=iwn.4 if_iwn.4 MLINKS+=ixgbe.4 ix.4 MLINKS+=ixgbe.4 if_ix.4 MLINKS+=ixgbe.4 if_ixgbe.4 MLINKS+=ixl.4 if_ixl.4 MLINKS+=iavf.4 if_iavf.4 MLINKS+=jme.4 if_jme.4 MLINKS+=kue.4 if_kue.4 MLINKS+=lagg.4 trunk.4 MLINKS+=lagg.4 if_lagg.4 MLINKS+=le.4 if_le.4 MLINKS+=lge.4 if_lge.4 MLINKS+=lo.4 loop.4 MLINKS+=lp.4 plip.4 MLINKS+=malo.4 if_malo.4 MLINKS+=md.4 vn.4 MLINKS+=mem.4 kmem.4 MLINKS+=mfi.4 mfi_linux.4 \ mfi.4 mfip.4 MLINKS+=mlx5en.4 mce.4 MLINKS+=mn.4 if_mn.4 MLINKS+=mos.4 if_mos.4 MLINKS+=msk.4 if_msk.4 MLINKS+=mwl.4 if_mwl.4 MLINKS+=mxge.4 if_mxge.4 MLINKS+=my.4 if_my.4 MLINKS+=${_ndis.4} ${_if_ndis.4} MLINKS+=netfpga10g_nf10bmac.4 if_nf10bmac.4 MLINKS+=netintro.4 net.4 \ netintro.4 networking.4 MLINKS+=${_nfe.4} ${_if_nfe.4} MLINKS+=nge.4 if_nge.4 MLINKS+=ow.4 onewire.4 MLINKS+=pccbb.4 cbb.4 MLINKS+=pcm.4 snd.4 \ pcm.4 sound.4 MLINKS+=pcn.4 if_pcn.4 MLINKS+=pms.4 pmspcv.4 MLINKS+=ptnet.4 if_ptnet.4 MLINKS+=ral.4 if_ral.4 MLINKS+=re.4 if_re.4 MLINKS+=rl.4 if_rl.4 MLINKS+=rtwn_pci.4 if_rtwn_pci.4 MLINKS+=rue.4 if_rue.4 MLINKS+=scsi.4 CAM.4 \ scsi.4 cam.4 \ scsi.4 scbus.4 \ scsi.4 SCSI.4 MLINKS+=sf.4 if_sf.4 MLINKS+=sge.4 if_sge.4 MLINKS+=sis.4 if_sis.4 MLINKS+=sk.4 if_sk.4 MLINKS+=smp.4 SMP.4 MLINKS+=smsc.4 if_smsc.4 MLINKS+=sn.4 if_sn.4 MLINKS+=snd_envy24.4 snd_ak452x.4 MLINKS+=snd_sbc.4 snd_sb16.4 \ snd_sbc.4 snd_sb8.4 MLINKS+=${_spkr.4} ${_speaker.4} MLINKS+=splash.4 screensaver.4 MLINKS+=ste.4 if_ste.4 MLINKS+=stf.4 if_stf.4 MLINKS+=stge.4 if_stge.4 MLINKS+=syncache.4 syncookies.4 MLINKS+=syscons.4 sc.4 MLINKS+=tap.4 if_tap.4 \ tap.4 vmnet.4 \ tap.4 if_vmnet.4 MLINKS+=tdfx.4 tdfx_linux.4 MLINKS+=ti.4 if_ti.4 MLINKS+=tl.4 if_tl.4 MLINKS+=tun.4 if_tun.4 MLINKS+=tx.4 if_tx.4 MLINKS+=txp.4 if_txp.4 MLINKS+=ure.4 if_ure.4 MLINKS+=vge.4 if_vge.4 MLINKS+=vlan.4 if_vlan.4 MLINKS+=vxlan.4 if_vxlan.4 MLINKS+=${_vmx.4} ${_if_vmx.4} MLINKS+=vpo.4 imm.4 MLINKS+=vr.4 if_vr.4 MLINKS+=vte.4 if_vte.4 MLINKS+=${_vtnet.4} ${_if_vtnet.4} MLINKS+=watchdog.4 SW_WATCHDOG.4 MLINKS+=wb.4 if_wb.4 MLINKS+=wi.4 if_wi.4 MLINKS+=${_wpi.4} ${_if_wpi.4} MLINKS+=xe.4 if_xe.4 MLINKS+=xl.4 if_xl.4 .if ${MACHINE_CPUARCH} == "amd64" || ${MACHINE_CPUARCH} == "i386" _acpi_asus.4= acpi_asus.4 _acpi_asus_wmi.4= acpi_asus_wmi.4 _acpi_dock.4= acpi_dock.4 _acpi_fujitsu.4=acpi_fujitsu.4 _acpi_hp.4= acpi_hp.4 _acpi_ibm.4= acpi_ibm.4 _acpi_panasonic.4=acpi_panasonic.4 _acpi_rapidstart.4=acpi_rapidstart.4 _acpi_sony.4= acpi_sony.4 _acpi_toshiba.4=acpi_toshiba.4 _acpi_wmi.4= acpi_wmi.4 _aesni.4= aesni.4 _aout.4= aout.4 _apic.4= apic.4 _atrtc.4= atrtc.4 _attimer.4= attimer.4 _aibs.4= aibs.4 _amdsbwd.4= amdsbwd.4 _amdsmb.4= amdsmb.4 _amdsmn.4= amdsmn.4 _amdtemp.4= amdtemp.4 _asmc.4= asmc.4 _bxe.4= bxe.4 _bytgpio.4= bytgpio.4 _chvgpio.4= chvgpio.4 _coretemp.4= coretemp.4 _cpuctl.4= cpuctl.4 _dpms.4= dpms.4 _hpt27xx.4= hpt27xx.4 _hptiop.4= hptiop.4 _hptmv.4= hptmv.4 _hptnr.4= hptnr.4 _hptrr.4= hptrr.4 _hv_kvp.4= hv_kvp.4 _hv_netvsc.4= hv_netvsc.4 _hv_storvsc.4= hv_storvsc.4 _hv_utils.4= hv_utils.4 _hv_vmbus.4= hv_vmbus.4 _hv_vss.4= hv_vss.4 _i8254.4= i8254.4 _ichwd.4= ichwd.4 _if_bxe.4= if_bxe.4 _if_ndis.4= if_ndis.4 _if_nfe.4= if_nfe.4 _if_urtw.4= if_urtw.4 _if_vmx.4= if_vmx.4 _if_vtnet.4= if_vtnet.4 _if_wpi.4= if_wpi.4 _imcsmb.4= imcsmb.4 _ipmi.4= ipmi.4 _io.4= io.4 _itwd.4= itwd.4 _linux.4= linux.4 _nda.4= nda.4 _ndis.4= ndis.4 _nfe.4= nfe.4 _nfsmb.4= nfsmb.4 _nvd.4= nvd.4 _nvme.4= nvme.4 _nvram.4= nvram.4 _padlock.4= padlock.4 _rr232x.4= rr232x.4 _speaker.4= speaker.4 _spkr.4= spkr.4 _superio.4= superio.4 _tpm.4= tpm.4 _urtw.4= urtw.4 _viawd.4= viawd.4 _virtio.4= virtio.4 _virtio_balloon.4=virtio_balloon.4 _virtio_blk.4= virtio_blk.4 _virtio_console.4=virtio_console.4 _virtio_random.4= virtio_random.4 _virtio_scsi.4= virtio_scsi.4 _vmx.4= vmx.4 _vtnet.4= vtnet.4 _wbwd.4= wbwd.4 _wpi.4= wpi.4 _xen.4= xen.4 _xnb.4= xnb.4 .endif .if ${MACHINE_CPUARCH} == "amd64" _if_ntb.4= if_ntb.4 _ioat.4= ioat.4 _ntb.4= ntb.4 _ntb_hw_amd.4= ntb_hw_amd.4 _ntb_hw_intel.4= ntb_hw_intel.4 _ntb_hw_plx.4= ntb_hw_plx.4 _ntb_transport.4=ntb_transport.4 _nvdimm.4= nvdimm.4 _qlxge.4= qlxge.4 _qlxgb.4= qlxgb.4 _qlxgbe.4= qlxgbe.4 _qlnxe.4= qlnxe.4 _sfxge.4= sfxge.4 _smartpqi.4= smartpqi.4 MLINKS+=qlxge.4 if_qlxge.4 MLINKS+=qlxgb.4 if_qlxgb.4 MLINKS+=qlxgbe.4 if_qlxgbe.4 MLINKS+=qlnxe.4 if_qlnxe.4 MLINKS+=sfxge.4 if_sfxge.4 .if ${MK_BHYVE} != "no" _bhyve.4= bhyve.4 _vmm.4= vmm.4 .endif .endif .if ${MACHINE_CPUARCH} == "mips" _nvram2env.4= nvram2env.4 .endif .if ${MACHINE_CPUARCH} == "powerpc" _nvd.4= nvd.4 _nvme.4= nvme.4 .endif .if empty(MAN_ARCH) __arches= ${MACHINE} ${MACHINE_ARCH} ${MACHINE_CPUARCH} .elif ${MAN_ARCH} == "all" __arches= ${:!/bin/sh -c "/bin/ls -d ${.CURDIR}/man4.*"!:E} .else __arches= ${MAN_ARCH} .endif .for __arch in ${__arches:O:u} .if exists(${.CURDIR}/man4.${__arch}) SUBDIR+= man4.${__arch} .endif .endfor .if ${MK_BLUETOOTH} != "no" MAN+= ng_bluetooth.4 .endif .if ${MK_CCD} != "no" _ccd.4= ccd.4 .endif .if ${MK_CDDL} != "no" _dtrace_provs= dtrace_audit.4 \ dtrace_io.4 \ dtrace_ip.4 \ dtrace_lockstat.4 \ dtrace_proc.4 \ dtrace_sched.4 \ dtrace_sctp.4 \ dtrace_tcp.4 \ dtrace_udp.4 \ dtrace_udplite.4 MLINKS+= dtrace_audit.4 dtaudit.4 .endif .if ${MK_EFI} != "no" MAN+= efidev.4 MLINKS+= efidev.4 efirtc.4 .endif .if ${MK_ISCSI} != "no" MAN+= cfiscsi.4 MAN+= iscsi.4 MAN+= iscsi_initiator.4 MAN+= iser.4 .endif .if ${MK_OFED} != "no" MAN+= mlx4ib.4 MAN+= mlx5ib.4 .endif .if ${MK_MLX5TOOL} != "no" MAN+= mlx5io.4 .endif .if ${MK_TESTS} != "no" ATF= ${SRCTOP}/contrib/atf .PATH: ${ATF}/doc _atf_test_case.4= atf-test-case.4 .endif .if ${MK_PF} != "no" _pf.4= pf.4 _pflog.4= pflog.4 _pfsync.4= pfsync.4 .endif .if ${MK_USB} != "no" MAN+= \ otus.4 \ otusfw.4 \ rsu.4 \ rsufw.4 \ rtwn_usb.4 \ rum.4 \ run.4 \ runfw.4 \ u3g.4 \ uark.4 \ uart.4 \ uath.4 \ ubsa.4 \ ubsec.4 \ ubser.4 \ ubtbcmfw.4 \ uchcom.4 \ ucom.4 \ ucycom.4 \ udav.4 \ udbp.4 \ udl.4 \ uep.4 \ ufm.4 \ ufoma.4 \ uftdi.4 \ ugen.4 \ ugold.4 \ uhci.4 \ uhid.4 \ uhso.4 \ uipaq.4 \ ukbd.4 \ uled.4 \ ulpt.4 \ umass.4 \ umcs.4 \ umct.4 \ umodem.4 \ umoscom.4 \ ums.4 \ unix.4 \ upgt.4 \ uplcom.4 \ ural.4 \ urio.4 \ urndis.4 \ ${_urtw.4} \ usb.4 \ usb_quirk.4 \ usb_template.4 \ usfs.4 \ uslcom.4 \ uvisor.4 \ uvscom.4 \ zyd.4 MLINKS+=otus.4 if_otus.4 MLINKS+=rsu.4 if_rsu.4 MLINKS+=rtwn_usb.4 if_rtwn_usb.4 MLINKS+=rum.4 if_rum.4 MLINKS+=run.4 if_run.4 MLINKS+=u3g.4 u3gstub.4 MLINKS+=uath.4 if_uath.4 MLINKS+=udav.4 if_udav.4 MLINKS+=upgt.4 if_upgt.4 MLINKS+=ural.4 if_ural.4 MLINKS+=urndis.4 if_urndis.4 MLINKS+=${_urtw.4} ${_if_urtw.4} MLINKS+=zyd.4 if_zyd.4 .endif .include Index: stable/12/share/man/man4/acpi_battery.4 =================================================================== --- stable/12/share/man/man4/acpi_battery.4 (nonexistent) +++ stable/12/share/man/man4/acpi_battery.4 (revision 359076) @@ -0,0 +1,380 @@ +.\" +.\" Copyright (c) 2019 Takanori Watanabe +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $FreeBSD$ +.\" +.Dd February 16, 2020 +.Dt ACPI_BATTERY 4 +.Os +.Sh NAME +.Nm acpi_battery +.Nd ACPI battery management subsystem +.Sh SYNOPSIS +.Cd "device acpi" +.Sh DESCRIPTION +The +.Nm +is a driver for battery management features of the ACPI module. +.Pp +An ACPI-compatible battery device supports either a Control +Method Battery interface or a Smart Battery subsystem interface. +The former is accessed by the AML +.Pq ACPI Machine Language +code control methods, +and the latter is controlled directly through the ACPI EC +.Pq Embedded Controller +typically via an SMBus interface. +.Pp +This driver supports the +.Xr sysctl 8 +and +.Xr ioctl 2 +interfaces as well as the +.Xr devd 8 +event notification interface. +.Sh IOCTLS +Every ioctl for the +.Nm +driver takes a single integer value for the battery unit +number as an argument, +and returns a specific structure for each request. +A special unit number +.Dv ACPI_BATTERY_ALL_UNITS +specifies all of the attached units +and reports accumulated information. +.Bl -tag -width indent +.It Dv ACPIIO_BATT_GET_UNITS Vt int +Returns the number of battery units in the system. +The unit number argument will be ignored. +.It Dv ACPIIO_BATT_GET_BATTINFO Vt struct acpi_battinfo +Returns the following: +.Bl -tag -width indent +.It Va cap +Battery capacity in percent, +.It Va min +Remaining battery life in minutes, +.It Va state +Current status of the battery encoded in the following: +.Bl -tag -width indent +.It Dv ACPI_BATT_STAT_DISCHARG Pq 0x0001 +Battery is discharging, +.It Dv ACPI_BATT_STAT_CHARGING Pq 0x0002 +Battery is being charged, or +.It Dv ACPI_BATT_STAT_CRITICAL Pq 0x0004 +Remaining battery life is critically low. +.El +.Pp +Note that the status bits of each battery will be +consolidated when +.Dv ACPI_BATTERY_ALL_UNITS +is specified. +.It Va rate +Current battery discharging rate in mW. +.Li -1 +means not discharging right now. +.El +.It Dv ACPIIO_BATT_GET_BIX Vt struct acpi_bix +Returns battery information given by the ACPI +.Li _BIX Pq Battery Information +object, +which is the static portion of the Control Method +Battery information. +In the case of a Smart Battery attached to +SMBus or a Control Method Battery with a +.Li _BIF +object, +this ioctl will build a +.Vt struct acpi_bix +structure based on the obtained information +and return it. +.Bl -tag -width indent +.It Va rev +Revision number of the object. +There are the following well-known values: +.Bl -tag -width indent +.It Dv ACPI_BIX_REV_0 Pq 0x0000 +A +.Li _BIX +object in ACPI 4.0. +.It Dv ACPI_BIX_REV_1 Pq 0x0001 +A +.Li _BIX +object in ACPI 6.0. +.It Dv ACPI_BIX_REV_BIF Pq 0xffff +A +.Li _BIX +object built from the +.Li _BIF +object found on the system. +.El +.Pp +Note that this field should be checked by using +.Fn ACPI_BIX_REV_MIN_CHECK var rev +macro when checking the minimum revision number. +.It Va units +Indicates the units used by the battery to report its +capacity and charge rate encoded in the following: +.Bl -tag -width indent +.It ACPI_BIX_UNITS_MW Pq 0x00000000 +in mW +.Pq power +.It ACPI_BIX_UNITS_MA Pq 0x00000001 +in mA +.Pq current +.El +.Pp +Note that capacity is expressed in mWh or mAh, +and rate is expressed in mW or mA, +respectively. +.It Va dcap +The Battery's design capacity, +which is the nominal capacity of a new battery. +This is expressed as power or current depending on +the value of +.Va units . +.It Va lfcap +Predicted battery capacity when fully charged. +Typically this will decrease every charging cycle. +.It btech +Battery technology: +.Bl -tag -width indent +.It 0x00000000 Primary cell Pq non-rechargable +.It 0x00000001 Secondary cell Pq rechargable +.El +.It Va dvol +Design voltage in mV, +which is the nominal voltage of a new battery. +.It Va wcap +Design capacity of warning. +When a discharging battery device reaches this capacity, +notification is sent to the system. +.It Va lcap +Design capacity of low. +.It Va cycles +.Pq rev 0 or newer +The number of cycles the battery has experienced. +A cycle means an amount of discharge occurred which was +approximately equal to the value of Design Capacity. +.It Va accuracy +.Pq rev 0 or newer +The accuracy of the battery capacity measurement, +in thousandth of a percent. +.It Va stmax +.Pq rev 0 or newer +The Maximum Sampling Time of the battery in +milliseconds. +This is the maximum duration between two consecutive +measurements of the battery's capacities specified in +.Li _BST . +If two succeeding readings of +.Li _BST +beyond this duration occur, +two different results can be returned. +.It Va stmin +.Pq rev 0 or newer +The Minimum Sampling Time of the battery in +milliseconds. +.It Va aimax +.Pq rev 0 or newer +The Maximum Average Interval of the battery in +milliseconds. +This is the length of time within which the battery +averages the capacity measurements specified in +.Li _BST . +The Sampling Time specifies the frequency of measurements, +and the Average Interval specifies the width of the time +window of every measurement. +.It Va aimin +.Pq rev 0 or newer +The Minimum Average Interval of the battery in +milliseconds. +.It Va gra1 +Battery capacity granularity between +.Va low +and +.Va warning . +This is expressed as power or current depending on +the value of +.Va units . +.It Va gra2 +Battery capacity granularity between +.Va warning +and +.Va full . +This is expressed as power or current depending on +the value of +.Va units . +.It Va model +Model number of the battery as a string. +.It Va serial +Serial number of the battery as a string. +.It Va type +Type identifier of the battery as a string. +.It Va oeminfo +OEM-specific information of the battery as a string. +.It Va scap +.Pq rev 1 or newer +Battery swapping capability encoded in the following: +.Bl -tag -width indent +.It ACPI_BIX_SCAP_NO Pq 0x00000000 +Non-swappable +.It ACPI_BIX_SCAP_COLD Pq 0x00000001 +Cold-swappable +.It ACPI_BIX_SCAP_HOT Pq 0x00000010 +Hot-swappable +.El +.El +.It Dv ACPIIO_BATT_GET_BIF Vt struct acpi_bif +.Pq deprecated +Returns battery information given by the ACPI +.Li _BIF Pq Battery Information +object, +which was deprecated in ACPI 4.0 specification. +The data structure is a subset of +.Vt struct acpi_bix . +.Pp +Note that this ioctl will built a +.Vt struct acpi_bif +structure based on the obtained information +even if this object is not available and a +.Li _BIX +object is found. +.It ACPIIO_BATT_GET_BST Vt struct acpi_bst +Returns battery information given by the ACPI +.Li _BST Pq Battery Status +object, +which is the present battery status. +In the case of a Smart Battery attached to SMBus, +this ioctl will build a +.Vt struct acpi_bst +structure based on the obtained information +and return it. +.Bl -tag -width indent +.It Va state +Battery state. +The value is encoded in the same way as +.Va state +of +.Vt struct acpi_battinfo . +.It Va rate +Battery present rate of charging or discharging. +The unit of the value depends on +.Va unit +of +.Vt struct acpi_bif . +.It Va cap +Battery remaining capacity. +The unit of this value depends on +.Va unit +of +.Vt struct acpi_bif . +.It Va volt +Battery present voltage. +.El +.El +.Sh SYSCTL VARIABLES +The following +.Xr sysctl 8 +variables export battery status. +Note that they are accumulated status of all of the +connected batteries: +.Bl -tag -width indent +.It Va hw.acpi.battery.info_expire +Information cache expiration time in seconds. +The battery information obtained by +.Li _BIX +or +.Li _BIF +object will be stored and reused for successive +read access to this MIB within the specified period. +.It Va hw.acpi.battery.units +Number of battery units in the system. +.It Va hw.acpi.battery.state +Current battery charging status. +This is same as +.Va state +of +.Vt struct acpi_battinfo . +.It Va hw.acpi.battery.rate +Current battery discharging rate in mW. +.It Va hw.acpi.battery.time +Remaining battery life in minutes. +If the battery is not discharging, +the value shows +.Li -1 . +.It Va hw.acpi.battery.life +Battery capacity in percent. +.El +.Sh EVENT NOTIFICATIONS +Battery-related event notifications are sent +to the userland via the +.Xr devd 8 +interface. +See +.Pa /etc/devd.conf +and +.Xr devd.conf 5 +for more details. +Note that notifications are supported only by +the Control Method Battery. +.Pp +The +.Nm +driver sends events with the following attributes: +.Pp +.Bl -tag -width "subsystem" -compact +.It system +.Li ACPI +.It subsystem +.Li CMBAT +.It type +The fully qualified battery object path as in the ASL. +.It notify +An integer designating the event: +.Pp +.Bl -tag -width indent -compact +.It Li 0x80 +Battery status was changed. +.It Li 0x81 +Battery information was changed. +.El +.El +.Sh SEE ALSO +.Xr acpi 4 , +.Xr acpiconf 8 +.Sh AUTHORS +.An -nosplit +.An Nate Lawson Aq Mt njl@FreeBSD.org , +.An Munehiro Matsuda , +.An Takanori Watanabe Aq Mt takawata@FreeBSD.org , +.An Mitsuru IWASAKI Aq Mt iwasaki@FreeBSD.org , +.An Hans Petter Selasky Aq Mt hselasky@FreeBSD.org , +and +.An Hiroki Sato Aq Mt hrs@FreeBSD.org . +.Pp +This manual page was written by +.An Takanori Watanabe Aq Mt takawata@FreeBSD.org +and +.An Hiroki Sato Aq Mt hrs@FreeBSD.org . Property changes on: stable/12/share/man/man4/acpi_battery.4 ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: stable/12/sys/dev/acpica/acpi_battery.c =================================================================== --- stable/12/sys/dev/acpica/acpi_battery.c (revision 359075) +++ stable/12/sys/dev/acpica/acpi_battery.c (revision 359076) @@ -1,521 +1,541 @@ /*- * Copyright (c) 2005 Nate Lawson * Copyright (c) 2000 Mitsuru IWASAKI * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include "opt_acpi.h" #include #include #include #include #include #include #include #include #include /* Default seconds before re-sampling the battery state. */ #define ACPI_BATTERY_INFO_EXPIRE 5 -static int acpi_batteries_initted; +static int acpi_batteries_initialized; static int acpi_battery_info_expire = ACPI_BATTERY_INFO_EXPIRE; static struct acpi_battinfo acpi_battery_battinfo; static struct sysctl_ctx_list acpi_battery_sysctl_ctx; static struct sysctl_oid *acpi_battery_sysctl_tree; ACPI_SERIAL_DECL(battery, "ACPI generic battery"); static void acpi_reset_battinfo(struct acpi_battinfo *info); static void acpi_battery_clean_str(char *str, int len); static device_t acpi_battery_find_dev(u_int logical_unit); static int acpi_battery_ioctl(u_long cmd, caddr_t addr, void *arg); static int acpi_battery_sysctl(SYSCTL_HANDLER_ARGS); static int acpi_battery_units_sysctl(SYSCTL_HANDLER_ARGS); static int acpi_battery_init(void); int acpi_battery_register(device_t dev) { int error; - error = 0; ACPI_SERIAL_BEGIN(battery); - if (!acpi_batteries_initted) - error = acpi_battery_init(); + error = acpi_battery_init(); ACPI_SERIAL_END(battery); + return (error); } int acpi_battery_remove(device_t dev) { return (0); } int acpi_battery_get_units(void) { devclass_t batt_dc; batt_dc = devclass_find("battery"); if (batt_dc == NULL) return (0); return (devclass_get_count(batt_dc)); } int acpi_battery_get_info_expire(void) { return (acpi_battery_info_expire); } /* Check _BST results for validity. */ int acpi_battery_bst_valid(struct acpi_bst *bst) { return (bst->state != ACPI_BATT_STAT_NOT_PRESENT && bst->cap != ACPI_BATT_UNKNOWN && bst->volt != ACPI_BATT_UNKNOWN); } -/* Check _BIF results for validity. */ +/* Check _BI[FX] results for validity. */ int -acpi_battery_bif_valid(struct acpi_bif *bif) +acpi_battery_bix_valid(struct acpi_bix *bix) { - return (bif->lfcap != 0); + + return (bix->lfcap != 0); } /* Get info about one or all batteries. */ int acpi_battery_get_battinfo(device_t dev, struct acpi_battinfo *battinfo) { int batt_stat, devcount, dev_idx, error, i; int total_cap, total_lfcap, total_min, valid_rate, valid_units; devclass_t batt_dc; device_t batt_dev; struct acpi_bst *bst; - struct acpi_bif *bif; + struct acpi_bix *bix; struct acpi_battinfo *bi; /* * Get the battery devclass and max unit for battery devices. If there * are none or error, return immediately. */ batt_dc = devclass_find("battery"); if (batt_dc == NULL) return (ENXIO); devcount = devclass_get_maxunit(batt_dc); if (devcount == 0) return (ENXIO); /* * Allocate storage for all _BST data, their derived battinfo data, - * and the current battery's _BIF data. + * and the current battery's _BIX (or _BIF) data. */ bst = malloc(devcount * sizeof(*bst), M_TEMP, M_WAITOK | M_ZERO); bi = malloc(devcount * sizeof(*bi), M_TEMP, M_WAITOK | M_ZERO); - bif = malloc(sizeof(*bif), M_TEMP, M_WAITOK | M_ZERO); + bix = malloc(sizeof(*bix), M_TEMP, M_WAITOK | M_ZERO); /* * Pass 1: for each battery that is present and valid, get its status, * calculate percent capacity remaining, and sum all the current * discharge rates. */ dev_idx = -1; batt_stat = valid_rate = valid_units = 0; total_cap = total_lfcap = 0; for (i = 0; i < devcount; i++) { /* Default info for every battery is "not present". */ acpi_reset_battinfo(&bi[i]); /* * Find the device. Since devcount is in terms of max units, this * may be a sparse array so skip devices that aren't present. */ batt_dev = devclass_get_device(batt_dc, i); if (batt_dev == NULL) continue; /* If examining a specific battery and this is it, record its index. */ if (dev != NULL && dev == batt_dev) dev_idx = i; /* * Be sure we can get various info from the battery. Note that * acpi_BatteryIsPresent() is not enough because smart batteries only * return that the device is present. */ if (!acpi_BatteryIsPresent(batt_dev) || ACPI_BATT_GET_STATUS(batt_dev, &bst[i]) != 0 || - ACPI_BATT_GET_INFO(batt_dev, bif) != 0) + ACPI_BATT_GET_INFO(batt_dev, bix, sizeof(*bix)) != 0) continue; /* If a battery is not installed, we sometimes get strange values. */ if (!acpi_battery_bst_valid(&bst[i]) || - !acpi_battery_bif_valid(bif)) + !acpi_battery_bix_valid(bix)) continue; /* * Record current state. If both charging and discharging are set, * ignore the charging flag. */ valid_units++; if ((bst[i].state & ACPI_BATT_STAT_DISCHARG) != 0) bst[i].state &= ~ACPI_BATT_STAT_CHARGING; batt_stat |= bst[i].state; bi[i].state = bst[i].state; /* * If the battery info is in terms of mA, convert to mW by * multiplying by the design voltage. If the design voltage * is 0 (due to some error reading the battery), skip this * conversion. */ - if (bif->units == ACPI_BIF_UNITS_MA && bif->dvol != 0 && dev == NULL) { - bst[i].rate = (bst[i].rate * bif->dvol) / 1000; - bst[i].cap = (bst[i].cap * bif->dvol) / 1000; - bif->lfcap = (bif->lfcap * bif->dvol) / 1000; + if (bix->units == ACPI_BIX_UNITS_MA && bix->dvol != 0 && dev == NULL) { + bst[i].rate = (bst[i].rate * bix->dvol) / 1000; + bst[i].cap = (bst[i].cap * bix->dvol) / 1000; + bix->lfcap = (bix->lfcap * bix->dvol) / 1000; } /* - * The calculation above may set bif->lfcap to zero. This was + * The calculation above may set bix->lfcap to zero. This was * seen on a laptop with a broken battery. The result of the * division was rounded to zero. */ - if (!acpi_battery_bif_valid(bif)) + if (!acpi_battery_bix_valid(bix)) continue; /* * Some laptops report the "design-capacity" instead of the * "real-capacity" when the battery is fully charged. That breaks * the above arithmetic as it needs to be 100% maximum. */ - if (bst[i].cap > bif->lfcap) - bst[i].cap = bif->lfcap; + if (bst[i].cap > bix->lfcap) + bst[i].cap = bix->lfcap; /* Calculate percent capacity remaining. */ - bi[i].cap = (100 * bst[i].cap) / bif->lfcap; + bi[i].cap = (100 * bst[i].cap) / bix->lfcap; /* If this battery is not present, don't use its capacity. */ if (bi[i].cap != -1) { total_cap += bst[i].cap; - total_lfcap += bif->lfcap; + total_lfcap += bix->lfcap; } /* * On systems with more than one battery, they may get used * sequentially, thus bst.rate may only signify the one currently * in use. For the remaining batteries, bst.rate will be zero, * which makes it impossible to calculate the total remaining time. * Therefore, we sum the bst.rate for batteries in the discharging * state and use the sum to calculate the total remaining time. */ if (bst[i].rate != ACPI_BATT_UNKNOWN && (bst[i].state & ACPI_BATT_STAT_DISCHARG) != 0) valid_rate += bst[i].rate; } /* If the caller asked for a device but we didn't find it, error. */ if (dev != NULL && dev_idx == -1) { error = ENXIO; goto out; } /* Pass 2: calculate capacity and remaining time for all batteries. */ total_min = 0; for (i = 0; i < devcount; i++) { /* * If any batteries are discharging, use the sum of the bst.rate * values. Otherwise, we are on AC power, and there is infinite * time remaining for this battery until we go offline. */ if (valid_rate > 0) bi[i].min = (60 * bst[i].cap) / valid_rate; else bi[i].min = 0; total_min += bi[i].min; } /* * Return total battery percent and time remaining. If there are * no valid batteries, report values as unknown. */ if (valid_units > 0) { if (dev == NULL) { battinfo->cap = (total_cap * 100) / total_lfcap; battinfo->min = total_min; battinfo->state = batt_stat; battinfo->rate = valid_rate; } else { battinfo->cap = bi[dev_idx].cap; battinfo->min = bi[dev_idx].min; battinfo->state = bi[dev_idx].state; battinfo->rate = bst[dev_idx].rate; } /* * If the queried battery has no discharge rate or is charging, * report that we don't know the remaining time. */ if (valid_rate == 0 || (battinfo->state & ACPI_BATT_STAT_CHARGING)) battinfo->min = -1; } else acpi_reset_battinfo(battinfo); error = 0; out: - if (bi) - free(bi, M_TEMP); - if (bif) - free(bif, M_TEMP); - if (bst) - free(bst, M_TEMP); + free(bi, M_TEMP); + free(bix, M_TEMP); + free(bst, M_TEMP); return (error); } static void acpi_reset_battinfo(struct acpi_battinfo *info) { info->cap = -1; info->min = -1; info->state = ACPI_BATT_STAT_NOT_PRESENT; info->rate = -1; } /* Make string printable, removing invalid chars. */ static void acpi_battery_clean_str(char *str, int len) { int i; for (i = 0; i < len && *str != '\0'; i++, str++) { if (!isprint(*str)) *str = '?'; } /* NUL-terminate the string if we reached the end. */ if (i == len) *str = '\0'; } /* * The battery interface deals with devices and methods but userland * expects a logical unit number. Convert a logical unit to a device_t. */ static device_t acpi_battery_find_dev(u_int logical_unit) { int found_unit, i, maxunit; device_t dev; devclass_t batt_dc; dev = NULL; found_unit = 0; batt_dc = devclass_find("battery"); maxunit = devclass_get_maxunit(batt_dc); for (i = 0; i < maxunit; i++) { dev = devclass_get_device(batt_dc, i); if (dev == NULL) continue; if (logical_unit == found_unit) break; found_unit++; dev = NULL; } return (dev); } static int acpi_battery_ioctl(u_long cmd, caddr_t addr, void *arg) { union acpi_battery_ioctl_arg *ioctl_arg; int error, unit; device_t dev; /* For commands that use the ioctl_arg struct, validate it first. */ error = ENXIO; unit = 0; dev = NULL; ioctl_arg = NULL; - if (IOCPARM_LEN(cmd) == sizeof(*ioctl_arg)) { + if (IOCPARM_LEN(cmd) == sizeof(union acpi_battery_ioctl_arg) || + IOCPARM_LEN(cmd) == sizeof(union acpi_battery_ioctl_arg_v1)) { ioctl_arg = (union acpi_battery_ioctl_arg *)addr; unit = ioctl_arg->unit; if (unit != ACPI_BATTERY_ALL_UNITS) dev = acpi_battery_find_dev(unit); } /* * No security check required: information retrieval only. If * new functions are added here, a check might be required. */ + /* Unit check */ switch (cmd) { case ACPIIO_BATT_GET_UNITS: *(int *)addr = acpi_battery_get_units(); error = 0; break; case ACPIIO_BATT_GET_BATTINFO: + case ACPIIO_BATT_GET_BATTINFO_V1: if (dev != NULL || unit == ACPI_BATTERY_ALL_UNITS) { bzero(&ioctl_arg->battinfo, sizeof(ioctl_arg->battinfo)); error = acpi_battery_get_battinfo(dev, &ioctl_arg->battinfo); } break; case ACPIIO_BATT_GET_BIF: if (dev != NULL) { bzero(&ioctl_arg->bif, sizeof(ioctl_arg->bif)); - error = ACPI_BATT_GET_INFO(dev, &ioctl_arg->bif); - - /* - * Remove invalid characters. Perhaps this should be done - * within a convenience function so all callers get the - * benefit. - */ - acpi_battery_clean_str(ioctl_arg->bif.model, - sizeof(ioctl_arg->bif.model)); - acpi_battery_clean_str(ioctl_arg->bif.serial, - sizeof(ioctl_arg->bif.serial)); - acpi_battery_clean_str(ioctl_arg->bif.type, - sizeof(ioctl_arg->bif.type)); - acpi_battery_clean_str(ioctl_arg->bif.oeminfo, - sizeof(ioctl_arg->bif.oeminfo)); + error = ACPI_BATT_GET_INFO(dev, &ioctl_arg->bif, + sizeof(ioctl_arg->bif)); } break; + case ACPIIO_BATT_GET_BIX: + if (dev != NULL) { + bzero(&ioctl_arg->bix, sizeof(ioctl_arg->bix)); + error = ACPI_BATT_GET_INFO(dev, &ioctl_arg->bix, + sizeof(ioctl_arg->bix)); + } + break; case ACPIIO_BATT_GET_BST: + case ACPIIO_BATT_GET_BST_V1: if (dev != NULL) { bzero(&ioctl_arg->bst, sizeof(ioctl_arg->bst)); error = ACPI_BATT_GET_STATUS(dev, &ioctl_arg->bst); } break; default: error = EINVAL; } + /* Sanitize the string members. */ + switch (cmd) { + case ACPIIO_BATT_GET_BIX: + case ACPIIO_BATT_GET_BIF: + /* + * Remove invalid characters. Perhaps this should be done + * within a convenience function so all callers get the + * benefit. + */ + acpi_battery_clean_str(ioctl_arg->bix.model, + sizeof(ioctl_arg->bix.model)); + acpi_battery_clean_str(ioctl_arg->bix.serial, + sizeof(ioctl_arg->bix.serial)); + acpi_battery_clean_str(ioctl_arg->bix.type, + sizeof(ioctl_arg->bix.type)); + acpi_battery_clean_str(ioctl_arg->bix.oeminfo, + sizeof(ioctl_arg->bix.oeminfo)); + }; + return (error); } static int acpi_battery_sysctl(SYSCTL_HANDLER_ARGS) { int val, error; acpi_battery_get_battinfo(NULL, &acpi_battery_battinfo); val = *(u_int *)oidp->oid_arg1; error = sysctl_handle_int(oidp, &val, 0, req); return (error); } static int acpi_battery_units_sysctl(SYSCTL_HANDLER_ARGS) { int count, error; count = acpi_battery_get_units(); error = sysctl_handle_int(oidp, &count, 0, req); return (error); } static int acpi_battery_init(void) { struct acpi_softc *sc; device_t dev; int error; ACPI_SERIAL_ASSERT(battery); + if (acpi_batteries_initialized) + return(0); + error = ENXIO; dev = devclass_get_device(devclass_find("acpi"), 0); if (dev == NULL) goto out; sc = device_get_softc(dev); - error = acpi_register_ioctl(ACPIIO_BATT_GET_UNITS, acpi_battery_ioctl, - NULL); - if (error != 0) - goto out; - error = acpi_register_ioctl(ACPIIO_BATT_GET_BATTINFO, acpi_battery_ioctl, - NULL); - if (error != 0) - goto out; - error = acpi_register_ioctl(ACPIIO_BATT_GET_BIF, acpi_battery_ioctl, NULL); - if (error != 0) - goto out; - error = acpi_register_ioctl(ACPIIO_BATT_GET_BST, acpi_battery_ioctl, NULL); - if (error != 0) - goto out; +#define ACPI_REGISTER_IOCTL(a, b, c) do { \ + error = acpi_register_ioctl(a, b, c); \ + if (error) \ + goto out; \ + } while (0) + ACPI_REGISTER_IOCTL(ACPIIO_BATT_GET_UNITS, acpi_battery_ioctl, NULL); + ACPI_REGISTER_IOCTL(ACPIIO_BATT_GET_BATTINFO, acpi_battery_ioctl, NULL); + ACPI_REGISTER_IOCTL(ACPIIO_BATT_GET_BATTINFO_V1, acpi_battery_ioctl, NULL); + ACPI_REGISTER_IOCTL(ACPIIO_BATT_GET_BIF, acpi_battery_ioctl, NULL); + ACPI_REGISTER_IOCTL(ACPIIO_BATT_GET_BIX, acpi_battery_ioctl, NULL); + ACPI_REGISTER_IOCTL(ACPIIO_BATT_GET_BST, acpi_battery_ioctl, NULL); + ACPI_REGISTER_IOCTL(ACPIIO_BATT_GET_BST_V1, acpi_battery_ioctl, NULL); +#undef ACPI_REGISTER_IOCTL + sysctl_ctx_init(&acpi_battery_sysctl_ctx); acpi_battery_sysctl_tree = SYSCTL_ADD_NODE(&acpi_battery_sysctl_ctx, SYSCTL_CHILDREN(sc->acpi_sysctl_tree), OID_AUTO, "battery", CTLFLAG_RD, 0, "battery status and info"); SYSCTL_ADD_PROC(&acpi_battery_sysctl_ctx, SYSCTL_CHILDREN(acpi_battery_sysctl_tree), OID_AUTO, "life", CTLTYPE_INT | CTLFLAG_RD, &acpi_battery_battinfo.cap, 0, acpi_battery_sysctl, "I", "percent capacity remaining"); SYSCTL_ADD_PROC(&acpi_battery_sysctl_ctx, SYSCTL_CHILDREN(acpi_battery_sysctl_tree), OID_AUTO, "time", CTLTYPE_INT | CTLFLAG_RD, &acpi_battery_battinfo.min, 0, acpi_battery_sysctl, "I", "remaining time in minutes"); SYSCTL_ADD_PROC(&acpi_battery_sysctl_ctx, SYSCTL_CHILDREN(acpi_battery_sysctl_tree), OID_AUTO, "rate", CTLTYPE_INT | CTLFLAG_RD, &acpi_battery_battinfo.rate, 0, acpi_battery_sysctl, "I", "present rate in mW"); SYSCTL_ADD_PROC(&acpi_battery_sysctl_ctx, SYSCTL_CHILDREN(acpi_battery_sysctl_tree), OID_AUTO, "state", CTLTYPE_INT | CTLFLAG_RD, &acpi_battery_battinfo.state, 0, acpi_battery_sysctl, "I", "current status flags"); SYSCTL_ADD_PROC(&acpi_battery_sysctl_ctx, SYSCTL_CHILDREN(acpi_battery_sysctl_tree), OID_AUTO, "units", CTLTYPE_INT | CTLFLAG_RD, NULL, 0, acpi_battery_units_sysctl, "I", "number of batteries"); SYSCTL_ADD_INT(&acpi_battery_sysctl_ctx, SYSCTL_CHILDREN(acpi_battery_sysctl_tree), OID_AUTO, "info_expire", CTLFLAG_RW, &acpi_battery_info_expire, 0, "time in seconds until info is refreshed"); - acpi_batteries_initted = TRUE; + acpi_batteries_initialized = TRUE; out: - if (error != 0) { + if (error) { acpi_deregister_ioctl(ACPIIO_BATT_GET_UNITS, acpi_battery_ioctl); acpi_deregister_ioctl(ACPIIO_BATT_GET_BATTINFO, acpi_battery_ioctl); + acpi_deregister_ioctl(ACPIIO_BATT_GET_BATTINFO_V1, acpi_battery_ioctl); acpi_deregister_ioctl(ACPIIO_BATT_GET_BIF, acpi_battery_ioctl); + acpi_deregister_ioctl(ACPIIO_BATT_GET_BIX, acpi_battery_ioctl); acpi_deregister_ioctl(ACPIIO_BATT_GET_BST, acpi_battery_ioctl); + acpi_deregister_ioctl(ACPIIO_BATT_GET_BST_V1, acpi_battery_ioctl); } return (error); } Index: stable/12/sys/dev/acpica/acpi_cmbat.c =================================================================== --- stable/12/sys/dev/acpica/acpi_cmbat.c (revision 359075) +++ stable/12/sys/dev/acpica/acpi_cmbat.c (revision 359076) @@ -1,507 +1,593 @@ /*- * Copyright (c) 2005 Nate Lawson * Copyright (c) 2000 Munehiro Matsuda * Copyright (c) 2000 Takanori Watanabe * Copyright (c) 2000 Mitsuru IWASAKI * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include "opt_acpi.h" #include #include #include #include #include #include #include #include #include #include #include static MALLOC_DEFINE(M_ACPICMBAT, "acpicmbat", "ACPI control method battery data"); /* Number of times to retry initialization before giving up. */ #define ACPI_CMBAT_RETRY_MAX 6 /* Check the battery once a minute. */ #define CMBAT_POLLRATE (60 * hz) /* Hooks for the ACPI CA debugging infrastructure */ #define _COMPONENT ACPI_BATTERY ACPI_MODULE_NAME("BATTERY") #define ACPI_BATTERY_BST_CHANGE 0x80 #define ACPI_BATTERY_BIF_CHANGE 0x81 +#define ACPI_BATTERY_BIX_CHANGE ACPI_BATTERY_BIF_CHANGE struct acpi_cmbat_softc { device_t dev; int flags; - struct acpi_bif bif; + struct acpi_bix bix; struct acpi_bst bst; struct timespec bst_lastupdated; }; ACPI_SERIAL_DECL(cmbat, "ACPI cmbat"); static int acpi_cmbat_probe(device_t dev); static int acpi_cmbat_attach(device_t dev); static int acpi_cmbat_detach(device_t dev); static int acpi_cmbat_resume(device_t dev); static void acpi_cmbat_notify_handler(ACPI_HANDLE h, UINT32 notify, void *context); static int acpi_cmbat_info_expired(struct timespec *lastupdated); static void acpi_cmbat_info_updated(struct timespec *lastupdated); static void acpi_cmbat_get_bst(void *arg); -static void acpi_cmbat_get_bif_task(void *arg); -static void acpi_cmbat_get_bif(void *arg); -static int acpi_cmbat_bst(device_t dev, struct acpi_bst *bstp); -static int acpi_cmbat_bif(device_t dev, struct acpi_bif *bifp); +static void acpi_cmbat_get_bix_task(void *arg); +static void acpi_cmbat_get_bix(void *arg); +static int acpi_cmbat_bst(device_t, struct acpi_bst *); +static int acpi_cmbat_bix(device_t, void *, size_t); static void acpi_cmbat_init_battery(void *arg); static device_method_t acpi_cmbat_methods[] = { /* Device interface */ DEVMETHOD(device_probe, acpi_cmbat_probe), DEVMETHOD(device_attach, acpi_cmbat_attach), DEVMETHOD(device_detach, acpi_cmbat_detach), DEVMETHOD(device_resume, acpi_cmbat_resume), /* ACPI battery interface */ - DEVMETHOD(acpi_batt_get_info, acpi_cmbat_bif), + DEVMETHOD(acpi_batt_get_info, acpi_cmbat_bix), DEVMETHOD(acpi_batt_get_status, acpi_cmbat_bst), DEVMETHOD_END }; static driver_t acpi_cmbat_driver = { "battery", acpi_cmbat_methods, sizeof(struct acpi_cmbat_softc), }; static devclass_t acpi_cmbat_devclass; DRIVER_MODULE(acpi_cmbat, acpi, acpi_cmbat_driver, acpi_cmbat_devclass, 0, 0); MODULE_DEPEND(acpi_cmbat, acpi, 1, 1, 1); static int acpi_cmbat_probe(device_t dev) { static char *cmbat_ids[] = { "PNP0C0A", NULL }; if (acpi_disabled("cmbat") || ACPI_ID_PROBE(device_get_parent(dev), dev, cmbat_ids) == NULL) return (ENXIO); device_set_desc(dev, "ACPI Control Method Battery"); return (0); } static int acpi_cmbat_attach(device_t dev) { int error; ACPI_HANDLE handle; struct acpi_cmbat_softc *sc; sc = device_get_softc(dev); handle = acpi_get_handle(dev); sc->dev = dev; timespecclear(&sc->bst_lastupdated); error = acpi_battery_register(dev); if (error != 0) { device_printf(dev, "registering battery failed\n"); return (error); } /* * Install a system notify handler in addition to the device notify. * Toshiba notebook uses this alternate notify for its battery. */ AcpiInstallNotifyHandler(handle, ACPI_ALL_NOTIFY, acpi_cmbat_notify_handler, dev); AcpiOsExecute(OSL_NOTIFY_HANDLER, acpi_cmbat_init_battery, dev); return (0); } static int acpi_cmbat_detach(device_t dev) { ACPI_HANDLE handle; handle = acpi_get_handle(dev); AcpiRemoveNotifyHandler(handle, ACPI_ALL_NOTIFY, acpi_cmbat_notify_handler); acpi_battery_remove(dev); /* * Force any pending notification handler calls to complete by * requesting cmbat serialisation while freeing and clearing the * softc pointer: */ ACPI_SERIAL_BEGIN(cmbat); device_set_softc(dev, NULL); ACPI_SERIAL_END(cmbat); return (0); } static int acpi_cmbat_resume(device_t dev) { AcpiOsExecute(OSL_NOTIFY_HANDLER, acpi_cmbat_init_battery, dev); return (0); } static void acpi_cmbat_notify_handler(ACPI_HANDLE h, UINT32 notify, void *context) { struct acpi_cmbat_softc *sc; device_t dev; dev = (device_t)context; sc = device_get_softc(dev); switch (notify) { case ACPI_NOTIFY_DEVICE_CHECK: case ACPI_BATTERY_BST_CHANGE: /* * Clear the last updated time. The next call to retrieve the * battery status will get the new value for us. */ timespecclear(&sc->bst_lastupdated); break; case ACPI_NOTIFY_BUS_CHECK: - case ACPI_BATTERY_BIF_CHANGE: + case ACPI_BATTERY_BIX_CHANGE: /* * Queue a callback to get the current battery info from thread * context. It's not safe to block in a notify handler. */ - AcpiOsExecute(OSL_NOTIFY_HANDLER, acpi_cmbat_get_bif_task, dev); + AcpiOsExecute(OSL_NOTIFY_HANDLER, acpi_cmbat_get_bix_task, dev); break; } acpi_UserNotify("CMBAT", h, notify); } static int acpi_cmbat_info_expired(struct timespec *lastupdated) { struct timespec curtime; ACPI_SERIAL_ASSERT(cmbat); if (lastupdated == NULL) return (TRUE); if (!timespecisset(lastupdated)) return (TRUE); getnanotime(&curtime); timespecsub(&curtime, lastupdated, &curtime); return (curtime.tv_sec < 0 || curtime.tv_sec > acpi_battery_get_info_expire()); } static void acpi_cmbat_info_updated(struct timespec *lastupdated) { ACPI_SERIAL_ASSERT(cmbat); if (lastupdated != NULL) getnanotime(lastupdated); } static void acpi_cmbat_get_bst(void *arg) { struct acpi_cmbat_softc *sc; ACPI_STATUS as; ACPI_OBJECT *res; ACPI_HANDLE h; ACPI_BUFFER bst_buffer; device_t dev; ACPI_SERIAL_ASSERT(cmbat); dev = arg; sc = device_get_softc(dev); h = acpi_get_handle(dev); bst_buffer.Pointer = NULL; bst_buffer.Length = ACPI_ALLOCATE_BUFFER; if (!acpi_cmbat_info_expired(&sc->bst_lastupdated)) goto end; as = AcpiEvaluateObject(h, "_BST", NULL, &bst_buffer); if (ACPI_FAILURE(as)) { ACPI_VPRINT(dev, acpi_device_get_parent_softc(dev), - "error fetching current battery status -- %s\n", - AcpiFormatException(as)); + "error fetching current battery status -- %s\n", + AcpiFormatException(as)); goto end; } res = (ACPI_OBJECT *)bst_buffer.Pointer; if (!ACPI_PKG_VALID(res, 4)) { ACPI_VPRINT(dev, acpi_device_get_parent_softc(dev), - "battery status corrupted\n"); + "battery status corrupted\n"); goto end; } if (acpi_PkgInt32(res, 0, &sc->bst.state) != 0) goto end; if (acpi_PkgInt32(res, 1, &sc->bst.rate) != 0) goto end; if (acpi_PkgInt32(res, 2, &sc->bst.cap) != 0) goto end; if (acpi_PkgInt32(res, 3, &sc->bst.volt) != 0) goto end; acpi_cmbat_info_updated(&sc->bst_lastupdated); /* Clear out undefined/extended bits that might be set by hardware. */ sc->bst.state &= ACPI_BATT_STAT_BST_MASK; if ((sc->bst.state & ACPI_BATT_STAT_INVALID) == ACPI_BATT_STAT_INVALID) ACPI_VPRINT(dev, acpi_device_get_parent_softc(dev), "battery reports simultaneous charging and discharging\n"); /* XXX If all batteries are critical, perhaps we should suspend. */ if (sc->bst.state & ACPI_BATT_STAT_CRITICAL) { if ((sc->flags & ACPI_BATT_STAT_CRITICAL) == 0) { sc->flags |= ACPI_BATT_STAT_CRITICAL; device_printf(dev, "critically low charge!\n"); } } else sc->flags &= ~ACPI_BATT_STAT_CRITICAL; end: - if (bst_buffer.Pointer != NULL) - AcpiOsFree(bst_buffer.Pointer); + AcpiOsFree(bst_buffer.Pointer); } /* XXX There should be a cleaner way to do this locking. */ static void -acpi_cmbat_get_bif_task(void *arg) +acpi_cmbat_get_bix_task(void *arg) { ACPI_SERIAL_BEGIN(cmbat); - acpi_cmbat_get_bif(arg); + acpi_cmbat_get_bix(arg); ACPI_SERIAL_END(cmbat); } static void -acpi_cmbat_get_bif(void *arg) +acpi_cmbat_get_bix(void *arg) { struct acpi_cmbat_softc *sc; ACPI_STATUS as; ACPI_OBJECT *res; ACPI_HANDLE h; - ACPI_BUFFER bif_buffer; + ACPI_BUFFER bix_buffer; device_t dev; + int i, n; + const struct { + enum { _BIX, _BIF } type; + char *name; + } bobjs[] = { + { _BIX, "_BIX"}, + { _BIF, "_BIF"}, + }; ACPI_SERIAL_ASSERT(cmbat); dev = arg; sc = device_get_softc(dev); h = acpi_get_handle(dev); - bif_buffer.Pointer = NULL; - bif_buffer.Length = ACPI_ALLOCATE_BUFFER; + bix_buffer.Pointer = NULL; + bix_buffer.Length = ACPI_ALLOCATE_BUFFER; - as = AcpiEvaluateObject(h, "_BIF", NULL, &bif_buffer); - if (ACPI_FAILURE(as)) { + for (n = 0; n < sizeof(bobjs); n++) { + as = AcpiEvaluateObject(h, bobjs[n].name, NULL, &bix_buffer); + if (!ACPI_FAILURE(as)) { + res = (ACPI_OBJECT *)bix_buffer.Pointer; + break; + } + AcpiOsFree(bix_buffer.Pointer); + bix_buffer.Pointer = NULL; + bix_buffer.Length = ACPI_ALLOCATE_BUFFER; + } + /* Both _BIF and _BIX were not found. */ + if (n == sizeof(bobjs)) { ACPI_VPRINT(dev, acpi_device_get_parent_softc(dev), - "error fetching current battery info -- %s\n", - AcpiFormatException(as)); + "error fetching current battery info -- %s\n", + AcpiFormatException(as)); goto end; } - res = (ACPI_OBJECT *)bif_buffer.Pointer; - if (!ACPI_PKG_VALID(res, 13)) { - ACPI_VPRINT(dev, acpi_device_get_parent_softc(dev), - "battery info corrupted\n"); - goto end; + /* + * ACPI _BIX and _BIF revision mismatch check: + * + * 1. _BIF has no revision field. The number of fields must be 13. + * + * 2. _BIX has a revision field. As of ACPI 6.3 it must be "0" or + * "1". The number of fields will be checked---20 and 21, + * respectively. + * + * If the revision number is grater than "1" and the number of + * fields is grater than 21, it will be treated as compatible with + * ACPI 6.0 _BIX. If not, it will be ignored. + */ + i = 0; + switch (bobjs[n].type) { + case _BIX: + if (acpi_PkgInt16(res, i++, &sc->bix.rev) != 0) { + ACPI_VPRINT(dev, acpi_device_get_parent_softc(dev), + "_BIX revision error\n"); + goto end; + } +#define ACPI_BIX_REV_MISMATCH_ERR(x, r) do { \ + ACPI_VPRINT(dev, acpi_device_get_parent_softc(dev), \ + "_BIX revision mismatch (%u != %u)\n", x, r); \ + goto end; \ + } while (0) + + if (ACPI_PKG_VALID_EQ(res, 21)) { /* ACPI 6.0 _BIX */ + /* + * Some models have rev.0 _BIX with 21 members. + * In that case, treat the first 20 members as rev.0 _BIX. + */ + if (sc->bix.rev != ACPI_BIX_REV_0 && + sc->bix.rev != ACPI_BIX_REV_1) + ACPI_BIX_REV_MISMATCH_ERR(sc->bix.rev, ACPI_BIX_REV_1); + } else if (ACPI_PKG_VALID_EQ(res, 20)) {/* ACPI 4.0 _BIX */ + if (sc->bix.rev != ACPI_BIX_REV_0) + ACPI_BIX_REV_MISMATCH_ERR(sc->bix.rev, ACPI_BIX_REV_0); + } else if (ACPI_PKG_VALID(res, 22)) { + /* _BIX with 22 or more members. */ + if (ACPI_BIX_REV_MIN_CHECK(sc->bix.rev, ACPI_BIX_REV_1 + 1)) { + /* + * Unknown revision number. + * Assume 21 members are compatible with 6.0 _BIX. + */ + ACPI_VPRINT(dev, acpi_device_get_parent_softc(dev), + "Unknown _BIX revision(%u). " + "Assuming compatible with revision %u.\n", + sc->bix.rev, ACPI_BIX_REV_1); + } else { + /* + * Known revision number. Ignore the extra members. + */ + ACPI_VPRINT(dev, acpi_device_get_parent_softc(dev), + "Extra objects found in _BIX were ignored.\n"); + } + } else { + /* Invalid _BIX. Ignore it. */ + ACPI_VPRINT(dev, acpi_device_get_parent_softc(dev), + "Invalid _BIX found (rev=%u, count=%u). Ignored.\n", + sc->bix.rev, res->Package.Count); + goto end; + } + break; +#undef ACPI_BIX_REV_MISMATCH_ERR + case _BIF: + if (ACPI_PKG_VALID_EQ(res, 13)) /* _BIF */ + sc->bix.rev = ACPI_BIX_REV_BIF; + else { + ACPI_VPRINT(dev, acpi_device_get_parent_softc(dev), + "Invalid _BIF found (count=%u). Ignored.\n", + res->Package.Count); + goto end; + } + break; } - if (acpi_PkgInt32(res, 0, &sc->bif.units) != 0) - goto end; - if (acpi_PkgInt32(res, 1, &sc->bif.dcap) != 0) - goto end; - if (acpi_PkgInt32(res, 2, &sc->bif.lfcap) != 0) - goto end; - if (acpi_PkgInt32(res, 3, &sc->bif.btech) != 0) - goto end; - if (acpi_PkgInt32(res, 4, &sc->bif.dvol) != 0) - goto end; - if (acpi_PkgInt32(res, 5, &sc->bif.wcap) != 0) - goto end; - if (acpi_PkgInt32(res, 6, &sc->bif.lcap) != 0) - goto end; - if (acpi_PkgInt32(res, 7, &sc->bif.gra1) != 0) - goto end; - if (acpi_PkgInt32(res, 8, &sc->bif.gra2) != 0) - goto end; - if (acpi_PkgStr(res, 9, sc->bif.model, ACPI_CMBAT_MAXSTRLEN) != 0) - goto end; - if (acpi_PkgStr(res, 10, sc->bif.serial, ACPI_CMBAT_MAXSTRLEN) != 0) - goto end; - if (acpi_PkgStr(res, 11, sc->bif.type, ACPI_CMBAT_MAXSTRLEN) != 0) - goto end; - if (acpi_PkgStr(res, 12, sc->bif.oeminfo, ACPI_CMBAT_MAXSTRLEN) != 0) - goto end; + ACPI_VPRINT(dev, acpi_device_get_parent_softc(dev), + "rev = %04x\n", sc->bix.rev); +#define BIX_GETU32(NAME) do { \ + ACPI_VPRINT(dev, acpi_device_get_parent_softc(dev), \ + #NAME " = %u\n", sc->bix.NAME); \ + if (acpi_PkgInt32(res, i++, &sc->bix.NAME) != 0) \ + goto end; \ + } while (0) + BIX_GETU32(units); + BIX_GETU32(dcap); + BIX_GETU32(lfcap); + BIX_GETU32(btech); + BIX_GETU32(dvol); + BIX_GETU32(wcap); + BIX_GETU32(lcap); + if (ACPI_BIX_REV_MIN_CHECK(sc->bix.rev, ACPI_BIX_REV_0)) { + BIX_GETU32(cycles); + BIX_GETU32(accuracy); + BIX_GETU32(stmax); + BIX_GETU32(stmin); + BIX_GETU32(aimax); + BIX_GETU32(aimin); + } + BIX_GETU32(gra1); + BIX_GETU32(gra2); + if (acpi_PkgStr(res, i++, sc->bix.model, ACPI_CMBAT_MAXSTRLEN) != 0) + goto end; + if (acpi_PkgStr(res, i++, sc->bix.serial, ACPI_CMBAT_MAXSTRLEN) != 0) + goto end; + if (acpi_PkgStr(res, i++, sc->bix.type, ACPI_CMBAT_MAXSTRLEN) != 0) + goto end; + if (acpi_PkgStr(res, i++, sc->bix.oeminfo, ACPI_CMBAT_MAXSTRLEN) != 0) + goto end; + if (ACPI_BIX_REV_MIN_CHECK(sc->bix.rev, ACPI_BIX_REV_1)) + BIX_GETU32(scap); +#undef BIX_GETU32 end: - if (bif_buffer.Pointer != NULL) - AcpiOsFree(bif_buffer.Pointer); + AcpiOsFree(bix_buffer.Pointer); } static int -acpi_cmbat_bif(device_t dev, struct acpi_bif *bifp) +acpi_cmbat_bix(device_t dev, void *bix, size_t len) { struct acpi_cmbat_softc *sc; + if (len != sizeof(struct acpi_bix) && + len != sizeof(struct acpi_bif)) + return (-1); + sc = device_get_softc(dev); /* * Just copy the data. The only value that should change is the * last-full capacity, so we only update when we get a notify that says * the info has changed. Many systems apparently take a long time to - * process a _BIF call so we avoid it if possible. + * process a _BI[FX] call so we avoid it if possible. */ ACPI_SERIAL_BEGIN(cmbat); - bifp->units = sc->bif.units; - bifp->dcap = sc->bif.dcap; - bifp->lfcap = sc->bif.lfcap; - bifp->btech = sc->bif.btech; - bifp->dvol = sc->bif.dvol; - bifp->wcap = sc->bif.wcap; - bifp->lcap = sc->bif.lcap; - bifp->gra1 = sc->bif.gra1; - bifp->gra2 = sc->bif.gra2; - strncpy(bifp->model, sc->bif.model, sizeof(sc->bif.model)); - strncpy(bifp->serial, sc->bif.serial, sizeof(sc->bif.serial)); - strncpy(bifp->type, sc->bif.type, sizeof(sc->bif.type)); - strncpy(bifp->oeminfo, sc->bif.oeminfo, sizeof(sc->bif.oeminfo)); + memcpy(bix, &sc->bix, len); ACPI_SERIAL_END(cmbat); return (0); } static int -acpi_cmbat_bst(device_t dev, struct acpi_bst *bstp) +acpi_cmbat_bst(device_t dev, struct acpi_bst *bst) { struct acpi_cmbat_softc *sc; sc = device_get_softc(dev); ACPI_SERIAL_BEGIN(cmbat); if (acpi_BatteryIsPresent(dev)) { acpi_cmbat_get_bst(dev); - bstp->state = sc->bst.state; - bstp->rate = sc->bst.rate; - bstp->cap = sc->bst.cap; - bstp->volt = sc->bst.volt; + memcpy(bst, &sc->bst, sizeof(*bst)); } else - bstp->state = ACPI_BATT_STAT_NOT_PRESENT; + bst->state = ACPI_BATT_STAT_NOT_PRESENT; ACPI_SERIAL_END(cmbat); return (0); } static void acpi_cmbat_init_battery(void *arg) { struct acpi_cmbat_softc *sc; int retry, valid; device_t dev; dev = (device_t)arg; ACPI_VPRINT(dev, acpi_device_get_parent_softc(dev), - "battery initialization start\n"); + "battery enitialization start\n"); /* * Try repeatedly to get valid data from the battery. Since the * embedded controller isn't always ready just after boot, we may have * to wait a while. */ for (retry = 0; retry < ACPI_CMBAT_RETRY_MAX; retry++, AcpiOsSleep(10000)) { /* * Batteries on DOCK can be ejected w/ DOCK during retrying. * * If there is a valid softc pointer the device may be in * attaching, attached or detaching state. If the state is * different from attached retry getting the device state * until it becomes stable. This solves a race if the ACPI * notification handler is called during attach, because * device_is_attached() doesn't return non-zero until after * the attach code has been executed. */ ACPI_SERIAL_BEGIN(cmbat); sc = device_get_softc(dev); if (sc == NULL) { ACPI_SERIAL_END(cmbat); return; } if (!acpi_BatteryIsPresent(dev) || !device_is_attached(dev)) { ACPI_SERIAL_END(cmbat); continue; } /* * Only query the battery if this is the first try or the specific * type of info is still invalid. */ if (retry == 0 || !acpi_battery_bst_valid(&sc->bst)) { timespecclear(&sc->bst_lastupdated); acpi_cmbat_get_bst(dev); } - if (retry == 0 || !acpi_battery_bif_valid(&sc->bif)) - acpi_cmbat_get_bif(dev); + if (retry == 0 || !acpi_battery_bix_valid(&sc->bix)) + acpi_cmbat_get_bix(dev); valid = acpi_battery_bst_valid(&sc->bst) && - acpi_battery_bif_valid(&sc->bif); + acpi_battery_bix_valid(&sc->bix); ACPI_SERIAL_END(cmbat); if (valid) break; } if (retry == ACPI_CMBAT_RETRY_MAX) { ACPI_VPRINT(dev, acpi_device_get_parent_softc(dev), - "battery initialization failed, giving up\n"); + "battery initialization failed, giving up\n"); } else { ACPI_VPRINT(dev, acpi_device_get_parent_softc(dev), - "battery initialization done, tried %d times\n", retry + 1); + "battery initialization done, tried %d times\n", retry + 1); } } Index: stable/12/sys/dev/acpica/acpi_if.m =================================================================== --- stable/12/sys/dev/acpica/acpi_if.m (revision 359075) +++ stable/12/sys/dev/acpica/acpi_if.m (revision 359076) @@ -1,224 +1,227 @@ #- # Copyright (c) 2004 Nate Lawson # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF # SUCH DAMAGE. # # $FreeBSD$ # #include #include #include INTERFACE acpi; # # Callback function for each child handle traversed in acpi_scan_children(). # # ACPI_HANDLE h: current child device being considered # # device_t *dev: pointer to the child's original device_t or NULL if there # was none. The callback should store a new device in *dev if it has # created one. The method implementation will automatically clean up the # previous device and properly associate the current ACPI_HANDLE with it. # # level: current level being scanned # # void *arg: argument passed in original call to acpi_scan_children() # # Returns: AE_OK if the scan should continue, otherwise an error # HEADER { typedef ACPI_STATUS (*acpi_scan_cb_t)(ACPI_HANDLE h, device_t *dev, int level, void *arg); + struct acpi_bix; struct acpi_bif; struct acpi_bst; }; # # Default implementation for acpi_id_probe(). # CODE { static char * acpi_generic_id_probe(device_t bus, device_t dev, char **ids) { return (NULL); } }; # # Check a device for a match in a list of ID strings. The strings can be # EISA PNP IDs or ACPI _HID/_CID values. # # device_t bus: parent bus for the device # # device_t dev: device being considered # # char **ids: array of ID strings to consider # # Returns: ID string matched or NULL if no match # METHOD char * id_probe { device_t bus; device_t dev; char **ids; } DEFAULT acpi_generic_id_probe; # # Evaluate an ACPI method or object, given its path. # # device_t bus: parent bus for the device # # device_t dev: evaluate the object relative to this device's handle. # Specify NULL to begin the search at the ACPI root. # # ACPI_STRING pathname: absolute or relative path to this object # # ACPI_OBJECT_LIST *parameters: array of arguments to pass to the object. # Specify NULL if there are none. # # ACPI_BUFFER *ret: the result (if any) of the evaluation # Specify NULL if there is none. # # Returns: AE_OK or an error value # METHOD ACPI_STATUS evaluate_object { device_t bus; device_t dev; ACPI_STRING pathname; ACPI_OBJECT_LIST *parameters; ACPI_BUFFER *ret; }; # # Get the highest power state (D0-D3) that is usable for a device when # suspending/resuming. If a bus calls this when suspending a device, it # must also call it when resuming. # # device_t bus: parent bus for the device # # device_t dev: check this device's appropriate power state # # int *dstate: if successful, contains the highest valid sleep state # # Returns: 0 on success or some other error value. # METHOD int pwr_for_sleep { device_t bus; device_t dev; int *dstate; }; # # Rescan a subtree and optionally reattach devices to handles. Users # specify a callback that is called for each ACPI_HANDLE of type Device # that is a child of "dev". # # device_t bus: parent bus for the device # # device_t dev: begin the scan starting with this device's handle. # Specify NULL to begin the scan at the ACPI root. # # int max_depth: number of levels to traverse (i.e., 1 means just the # immediate children. # # acpi_scan_cb_t user_fn: called for each child handle # # void *arg: argument to pass to the callback function # # Returns: AE_OK or an error value, based on the callback return value # METHOD ACPI_STATUS scan_children { device_t bus; device_t dev; int max_depth; acpi_scan_cb_t user_fn; void *arg; }; # # Query a given driver for its supported feature(s). This should be # called by the parent bus before the driver is probed. # # driver_t *driver: child driver # # u_int *features: returned bitmask of all supported features # STATICMETHOD int get_features { driver_t *driver; u_int *features; }; # # Read embedded controller (EC) address space # # device_t dev: EC device # u_int addr: Address to read from in EC space # UINT64 *val: Location to store read value # int width: Size of area to read in bytes # METHOD int ec_read { device_t dev; u_int addr; UINT64 *val; int width; }; # # Write embedded controller (EC) address space # # device_t dev: EC device # u_int addr: Address to write to in EC space # UINT64 val: Value to write # int width: Size of value to write in bytes # METHOD int ec_write { device_t dev; u_int addr; UINT64 val; int width; }; # -# Get battery information (_BIF format) +# Get battery information (_BIF or _BIX format) # # device_t dev: Battery device -# struct acpi_bif *bif: Pointer to storage for _BIF results +# void *bix: Pointer to storage for _BIF or _BIX results +# size_t len: length of acpi_bif or acpi_bix. # METHOD int batt_get_info { device_t dev; - struct acpi_bif *bif; + void *bix; + size_t len; }; # # Get battery status (_BST format) # # device_t dev: Battery device # struct acpi_bst *bst: Pointer to storage for _BST results # METHOD int batt_get_status { device_t dev; struct acpi_bst *bst; }; Index: stable/12/sys/dev/acpica/acpi_package.c =================================================================== --- stable/12/sys/dev/acpica/acpi_package.c (revision 359075) +++ stable/12/sys/dev/acpica/acpi_package.c (revision 359076) @@ -1,173 +1,186 @@ /*- * Copyright (c) 2003 Nate Lawson * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include /* * Package manipulation convenience functions */ int acpi_PkgInt(ACPI_OBJECT *res, int idx, UINT64 *dst) { ACPI_OBJECT *obj; obj = &res->Package.Elements[idx]; if (obj->Type != ACPI_TYPE_INTEGER) return (EINVAL); *dst = obj->Integer.Value; return (0); } int acpi_PkgInt32(ACPI_OBJECT *res, int idx, uint32_t *dst) { UINT64 tmp; int error; error = acpi_PkgInt(res, idx, &tmp); if (error == 0) *dst = (uint32_t)tmp; return (error); } int +acpi_PkgInt16(ACPI_OBJECT *res, int idx, uint16_t *dst) +{ + UINT64 tmp; + int error; + + error = acpi_PkgInt(res, idx, &tmp); + if (error == 0) + *dst = (uint16_t)tmp; + + return (error); +} + +int acpi_PkgStr(ACPI_OBJECT *res, int idx, void *dst, size_t size) { ACPI_OBJECT *obj; void *ptr; size_t length; obj = &res->Package.Elements[idx]; if (obj == NULL) return (EINVAL); switch (obj->Type) { case ACPI_TYPE_STRING: ptr = obj->String.Pointer; length = obj->String.Length; break; case ACPI_TYPE_BUFFER: ptr = obj->Buffer.Pointer; length = obj->Buffer.Length; break; default: return (EINVAL); } /* Make sure string will fit, including terminating NUL */ if (++length > size) return (E2BIG); strlcpy(dst, ptr, length); return (0); } int acpi_PkgGas(device_t dev, ACPI_OBJECT *res, int idx, int *type, int *rid, struct resource **dst, u_int flags) { ACPI_GENERIC_ADDRESS gas; ACPI_OBJECT *obj; obj = &res->Package.Elements[idx]; if (obj == NULL || obj->Type != ACPI_TYPE_BUFFER || obj->Buffer.Length < sizeof(ACPI_GENERIC_ADDRESS) + 3) return (EINVAL); memcpy(&gas, obj->Buffer.Pointer + 3, sizeof(gas)); return (acpi_bus_alloc_gas(dev, type, rid, &gas, dst, flags)); } int acpi_PkgFFH_IntelCpu(ACPI_OBJECT *res, int idx, int *vendor, int *class, uint64_t *address, int *accsize) { ACPI_GENERIC_ADDRESS gas; ACPI_OBJECT *obj; obj = &res->Package.Elements[idx]; if (obj == NULL || obj->Type != ACPI_TYPE_BUFFER || obj->Buffer.Length < sizeof(ACPI_GENERIC_ADDRESS) + 3) return (EINVAL); memcpy(&gas, obj->Buffer.Pointer + 3, sizeof(gas)); if (gas.SpaceId != ACPI_ADR_SPACE_FIXED_HARDWARE) return (ERESTART); *vendor = gas.BitWidth; *class = gas.BitOffset; *address = gas.Address; *accsize = gas.AccessWidth; return (0); } ACPI_HANDLE acpi_GetReference(ACPI_HANDLE scope, ACPI_OBJECT *obj) { ACPI_HANDLE h; if (obj == NULL) return (NULL); switch (obj->Type) { case ACPI_TYPE_LOCAL_REFERENCE: case ACPI_TYPE_ANY: h = obj->Reference.Handle; break; case ACPI_TYPE_STRING: /* * The String object usually contains a fully-qualified path, so * scope can be NULL. * * XXX This may not always be the case. */ if (ACPI_FAILURE(AcpiGetHandle(scope, obj->String.Pointer, &h))) h = NULL; break; default: h = NULL; break; } return (h); } Index: stable/12/sys/dev/acpica/acpi_smbat.c =================================================================== --- stable/12/sys/dev/acpica/acpi_smbat.c (revision 359075) +++ stable/12/sys/dev/acpica/acpi_smbat.c (revision 359076) @@ -1,490 +1,496 @@ /*- * Copyright (c) 2005 Hans Petter Selasky * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include "opt_acpi.h" #include #include #include #include #include #include #include #include /* Transactions have failed after 500 ms. */ #define SMBUS_TIMEOUT 50 struct acpi_smbat_softc { uint8_t sb_base_addr; device_t ec_dev; - struct acpi_bif bif; + struct acpi_bix bix; struct acpi_bst bst; - struct timespec bif_lastupdated; + struct timespec bix_lastupdated; struct timespec bst_lastupdated; }; static int acpi_smbat_probe(device_t dev); static int acpi_smbat_attach(device_t dev); static int acpi_smbat_shutdown(device_t dev); static int acpi_smbat_info_expired(struct timespec *lastupdated); static void acpi_smbat_info_updated(struct timespec *lastupdated); -static int acpi_smbat_get_bif(device_t dev, struct acpi_bif *bif); +static int acpi_smbat_get_bix(device_t dev, void *, size_t); static int acpi_smbat_get_bst(device_t dev, struct acpi_bst *bst); ACPI_SERIAL_DECL(smbat, "ACPI Smart Battery"); static SYSCTL_NODE(_debug_acpi, OID_AUTO, batt, CTLFLAG_RD, NULL, "Battery debugging"); /* On some laptops with smart batteries, enabling battery monitoring * software causes keystrokes from atkbd to be lost. This has also been * reported on Linux, and is apparently due to the keyboard and I2C line * for the battery being routed through the same chip. Whether that's * accurate or not, adding extra sleeps to the status checking code * causes the problem to go away. * * If you experience that problem, try a value of 10ms and move up * from there. */ static int batt_sleep_ms; SYSCTL_INT(_debug_acpi_batt, OID_AUTO, batt_sleep_ms, CTLFLAG_RW, &batt_sleep_ms, 0, "Sleep during battery status updates to prevent keystroke loss."); static device_method_t acpi_smbat_methods[] = { /* device interface */ DEVMETHOD(device_probe, acpi_smbat_probe), DEVMETHOD(device_attach, acpi_smbat_attach), DEVMETHOD(device_shutdown, acpi_smbat_shutdown), /* ACPI battery interface */ DEVMETHOD(acpi_batt_get_status, acpi_smbat_get_bst), - DEVMETHOD(acpi_batt_get_info, acpi_smbat_get_bif), + DEVMETHOD(acpi_batt_get_info, acpi_smbat_get_bix), DEVMETHOD_END }; static driver_t acpi_smbat_driver = { "battery", acpi_smbat_methods, sizeof(struct acpi_smbat_softc), }; static devclass_t acpi_smbat_devclass; DRIVER_MODULE(acpi_smbat, acpi, acpi_smbat_driver, acpi_smbat_devclass, 0, 0); MODULE_DEPEND(acpi_smbat, acpi, 1, 1, 1); static int acpi_smbat_probe(device_t dev) { static char *smbat_ids[] = {"ACPI0001", "ACPI0005", NULL}; ACPI_STATUS status; if (acpi_disabled("smbat") || ACPI_ID_PROBE(device_get_parent(dev), dev, smbat_ids) == NULL) return (ENXIO); status = AcpiEvaluateObject(acpi_get_handle(dev), "_EC", NULL, NULL); if (ACPI_FAILURE(status)) return (ENXIO); device_set_desc(dev, "ACPI Smart Battery"); return (0); } static int acpi_smbat_attach(device_t dev) { struct acpi_smbat_softc *sc; uint32_t base; sc = device_get_softc(dev); if (ACPI_FAILURE(acpi_GetInteger(acpi_get_handle(dev), "_EC", &base))) { device_printf(dev, "cannot get EC base address\n"); return (ENXIO); } sc->sb_base_addr = (base >> 8) & 0xff; /* XXX Only works with one EC, but nearly all systems only have one. */ sc->ec_dev = devclass_get_device(devclass_find("acpi_ec"), 0); if (sc->ec_dev == NULL) { device_printf(dev, "cannot find EC device\n"); return (ENXIO); } - timespecclear(&sc->bif_lastupdated); + timespecclear(&sc->bix_lastupdated); timespecclear(&sc->bst_lastupdated); if (acpi_battery_register(dev) != 0) { device_printf(dev, "cannot register battery\n"); return (ENXIO); } return (0); } static int acpi_smbat_shutdown(device_t dev) { acpi_battery_remove(dev); return (0); } static int acpi_smbat_info_expired(struct timespec *lastupdated) { struct timespec curtime; ACPI_SERIAL_ASSERT(smbat); if (lastupdated == NULL) return (TRUE); if (!timespecisset(lastupdated)) return (TRUE); getnanotime(&curtime); timespecsub(&curtime, lastupdated, &curtime); return (curtime.tv_sec < 0 || curtime.tv_sec > acpi_battery_get_info_expire()); } static void acpi_smbat_info_updated(struct timespec *lastupdated) { ACPI_SERIAL_ASSERT(smbat); if (lastupdated != NULL) getnanotime(lastupdated); } static int acpi_smbus_read_2(struct acpi_smbat_softc *sc, uint8_t addr, uint8_t cmd, uint16_t *ptr) { int error, to; UINT64 val; ACPI_SERIAL_ASSERT(smbat); if (batt_sleep_ms) AcpiOsSleep(batt_sleep_ms); val = addr; error = ACPI_EC_WRITE(sc->ec_dev, sc->sb_base_addr + SMBUS_ADDR, val, 1); if (error) goto out; val = cmd; error = ACPI_EC_WRITE(sc->ec_dev, sc->sb_base_addr + SMBUS_CMD, val, 1); if (error) goto out; val = 0x09; /* | 0x80 if PEC */ error = ACPI_EC_WRITE(sc->ec_dev, sc->sb_base_addr + SMBUS_PRTCL, val, 1); if (error) goto out; if (batt_sleep_ms) AcpiOsSleep(batt_sleep_ms); for (to = SMBUS_TIMEOUT; to != 0; to--) { error = ACPI_EC_READ(sc->ec_dev, sc->sb_base_addr + SMBUS_PRTCL, &val, 1); if (error) goto out; if (val == 0) break; AcpiOsSleep(10); } if (to == 0) { error = ETIMEDOUT; goto out; } error = ACPI_EC_READ(sc->ec_dev, sc->sb_base_addr + SMBUS_STS, &val, 1); if (error) goto out; if (val & SMBUS_STS_MASK) { printf("%s: AE_ERROR 0x%x\n", __FUNCTION__, (int)(val & SMBUS_STS_MASK)); error = EIO; goto out; } error = ACPI_EC_READ(sc->ec_dev, sc->sb_base_addr + SMBUS_DATA, &val, 2); if (error) goto out; *ptr = val; out: return (error); } static int acpi_smbus_read_multi_1(struct acpi_smbat_softc *sc, uint8_t addr, uint8_t cmd, uint8_t *ptr, uint16_t len) { UINT64 val; uint8_t to; int error; ACPI_SERIAL_ASSERT(smbat); if (batt_sleep_ms) AcpiOsSleep(batt_sleep_ms); val = addr; error = ACPI_EC_WRITE(sc->ec_dev, sc->sb_base_addr + SMBUS_ADDR, val, 1); if (error) goto out; val = cmd; error = ACPI_EC_WRITE(sc->ec_dev, sc->sb_base_addr + SMBUS_CMD, val, 1); if (error) goto out; val = 0x0B /* | 0x80 if PEC */ ; error = ACPI_EC_WRITE(sc->ec_dev, sc->sb_base_addr + SMBUS_PRTCL, val, 1); if (error) goto out; if (batt_sleep_ms) AcpiOsSleep(batt_sleep_ms); for (to = SMBUS_TIMEOUT; to != 0; to--) { error = ACPI_EC_READ(sc->ec_dev, sc->sb_base_addr + SMBUS_PRTCL, &val, 1); if (error) goto out; if (val == 0) break; AcpiOsSleep(10); } if (to == 0) { error = ETIMEDOUT; goto out; } error = ACPI_EC_READ(sc->ec_dev, sc->sb_base_addr + SMBUS_STS, &val, 1); if (error) goto out; if (val & SMBUS_STS_MASK) { printf("%s: AE_ERROR 0x%x\n", __FUNCTION__, (int)(val & SMBUS_STS_MASK)); error = EIO; goto out; } /* get length */ error = ACPI_EC_READ(sc->ec_dev, sc->sb_base_addr + SMBUS_BCNT, &val, 1); if (error) goto out; val = (val & 0x1f) + 1; bzero(ptr, len); if (len > val) len = val; if (batt_sleep_ms) AcpiOsSleep(batt_sleep_ms); while (len--) { error = ACPI_EC_READ(sc->ec_dev, sc->sb_base_addr + SMBUS_DATA + len, &val, 1); if (error) goto out; ptr[len] = val; if (batt_sleep_ms) AcpiOsSleep(batt_sleep_ms); } out: return (error); } static int acpi_smbat_get_bst(device_t dev, struct acpi_bst *bst) { struct acpi_smbat_softc *sc; int error; uint32_t factor; int16_t val; uint8_t addr; ACPI_SERIAL_BEGIN(smbat); addr = SMBATT_ADDRESS; error = ENXIO; sc = device_get_softc(dev); if (!acpi_smbat_info_expired(&sc->bst_lastupdated)) { error = 0; goto out; } if (acpi_smbus_read_2(sc, addr, SMBATT_CMD_BATTERY_MODE, &val)) goto out; if (val & SMBATT_BM_CAPACITY_MODE) factor = 10; else factor = 1; /* get battery status */ if (acpi_smbus_read_2(sc, addr, SMBATT_CMD_BATTERY_STATUS, &val)) goto out; sc->bst.state = 0; if (val & SMBATT_BS_DISCHARGING) sc->bst.state |= ACPI_BATT_STAT_DISCHARG; if (val & SMBATT_BS_REMAINING_CAPACITY_ALARM) sc->bst.state |= ACPI_BATT_STAT_CRITICAL; /* * If the rate is negative, it is discharging. Otherwise, * it is charging. */ if (acpi_smbus_read_2(sc, addr, SMBATT_CMD_CURRENT, &val)) goto out; if (val > 0) { sc->bst.rate = val * factor; sc->bst.state &= ~SMBATT_BS_DISCHARGING; sc->bst.state |= ACPI_BATT_STAT_CHARGING; } else if (val < 0) sc->bst.rate = (-val) * factor; else sc->bst.rate = 0; if (acpi_smbus_read_2(sc, addr, SMBATT_CMD_REMAINING_CAPACITY, &val)) goto out; sc->bst.cap = val * factor; if (acpi_smbus_read_2(sc, addr, SMBATT_CMD_VOLTAGE, &val)) goto out; sc->bst.volt = val; acpi_smbat_info_updated(&sc->bst_lastupdated); error = 0; out: if (error == 0) memcpy(bst, &sc->bst, sizeof(sc->bst)); ACPI_SERIAL_END(smbat); return (error); } static int -acpi_smbat_get_bif(device_t dev, struct acpi_bif *bif) +acpi_smbat_get_bix(device_t dev, void *bix, size_t len) { struct acpi_smbat_softc *sc; int error; uint32_t factor; uint16_t val; uint8_t addr; + if (len != sizeof(struct acpi_bix) && + len != sizeof(struct acpi_bif)) + return (-1); + ACPI_SERIAL_BEGIN(smbat); addr = SMBATT_ADDRESS; error = ENXIO; sc = device_get_softc(dev); - if (!acpi_smbat_info_expired(&sc->bif_lastupdated)) { + if (!acpi_smbat_info_expired(&sc->bix_lastupdated)) { error = 0; goto out; } + sc->bix.rev = ACPI_BIX_REV_BIF; + if (acpi_smbus_read_2(sc, addr, SMBATT_CMD_BATTERY_MODE, &val)) goto out; if (val & SMBATT_BM_CAPACITY_MODE) { factor = 10; - sc->bif.units = ACPI_BIF_UNITS_MW; + sc->bix.units = ACPI_BIX_UNITS_MW; } else { factor = 1; - sc->bif.units = ACPI_BIF_UNITS_MA; + sc->bix.units = ACPI_BIX_UNITS_MA; } if (acpi_smbus_read_2(sc, addr, SMBATT_CMD_DESIGN_CAPACITY, &val)) goto out; - sc->bif.dcap = val * factor; + sc->bix.dcap = val * factor; if (acpi_smbus_read_2(sc, addr, SMBATT_CMD_FULL_CHARGE_CAPACITY, &val)) goto out; - sc->bif.lfcap = val * factor; - sc->bif.btech = 1; /* secondary (rechargeable) */ + sc->bix.lfcap = val * factor; + sc->bix.btech = 1; /* secondary (rechargeable) */ if (acpi_smbus_read_2(sc, addr, SMBATT_CMD_DESIGN_VOLTAGE, &val)) goto out; - sc->bif.dvol = val; + sc->bix.dvol = val; - sc->bif.wcap = sc->bif.dcap / 10; - sc->bif.lcap = sc->bif.dcap / 10; + sc->bix.wcap = sc->bix.dcap / 10; + sc->bix.lcap = sc->bix.dcap / 10; - sc->bif.gra1 = factor; /* not supported */ - sc->bif.gra2 = factor; /* not supported */ + sc->bix.gra1 = factor; /* not supported */ + sc->bix.gra2 = factor; /* not supported */ if (acpi_smbus_read_multi_1(sc, addr, SMBATT_CMD_DEVICE_NAME, - sc->bif.model, sizeof(sc->bif.model))) + sc->bix.model, sizeof(sc->bix.model))) goto out; if (acpi_smbus_read_2(sc, addr, SMBATT_CMD_SERIAL_NUMBER, &val)) goto out; - snprintf(sc->bif.serial, sizeof(sc->bif.serial), "0x%04x", val); + snprintf(sc->bix.serial, sizeof(sc->bix.serial), "0x%04x", val); if (acpi_smbus_read_multi_1(sc, addr, SMBATT_CMD_DEVICE_CHEMISTRY, - sc->bif.type, sizeof(sc->bif.type))) + sc->bix.type, sizeof(sc->bix.type))) goto out; if (acpi_smbus_read_multi_1(sc, addr, SMBATT_CMD_MANUFACTURER_DATA, - sc->bif.oeminfo, sizeof(sc->bif.oeminfo))) + sc->bix.oeminfo, sizeof(sc->bix.oeminfo))) goto out; /* XXX check if device was replugged during read? */ - acpi_smbat_info_updated(&sc->bif_lastupdated); + acpi_smbat_info_updated(&sc->bix_lastupdated); error = 0; out: if (error == 0) - memcpy(bif, &sc->bif, sizeof(sc->bif)); + memcpy(bix, &sc->bix, len); ACPI_SERIAL_END(smbat); return (error); } Index: stable/12/sys/dev/acpica/acpiio.h =================================================================== --- stable/12/sys/dev/acpica/acpiio.h (revision 359075) +++ stable/12/sys/dev/acpica/acpiio.h (revision 359076) @@ -1,125 +1,212 @@ /*- * Copyright (c) 1999 Takanori Watanabe * Copyright (c) 1999 Mitsuru IWASAKI * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #ifndef _ACPIIO_H_ #define _ACPIIO_H_ /* * Core ACPI subsystem ioctls */ #define ACPIIO_SETSLPSTATE _IOW('P', 3, int) /* DEPRECATED */ /* Request S1-5 sleep state. User is notified and then sleep proceeds. */ #define ACPIIO_REQSLPSTATE _IOW('P', 4, int) /* Allow suspend to continue (0) or abort it (errno). */ #define ACPIIO_ACKSLPSTATE _IOW('P', 5, int) struct acpi_battinfo { int cap; /* percent */ int min; /* remaining time (in minutes) */ int state; /* battery state */ int rate; /* emptying rate */ }; +/* + * Battery Information object. Note that this object is deprecated in + * ACPI 4.0 + */ #define ACPI_CMBAT_MAXSTRLEN 32 struct acpi_bif { - uint32_t units; /* Units (mW or mA). */ + uint32_t units; /* Power Unit (mW or mA). */ #define ACPI_BIF_UNITS_MW 0 /* Capacity in mWh, rate in mW. */ #define ACPI_BIF_UNITS_MA 1 /* Capacity in mAh, rate in mA. */ uint32_t dcap; /* Design Capacity */ uint32_t lfcap; /* Last Full capacity */ uint32_t btech; /* Battery Technology */ uint32_t dvol; /* Design voltage (mV) */ uint32_t wcap; /* WARN capacity */ uint32_t lcap; /* Low capacity */ uint32_t gra1; /* Granularity 1 (Warn to Low) */ uint32_t gra2; /* Granularity 2 (Full to Warn) */ char model[ACPI_CMBAT_MAXSTRLEN]; /* model identifier */ char serial[ACPI_CMBAT_MAXSTRLEN]; /* Serial number */ char type[ACPI_CMBAT_MAXSTRLEN]; /* Type */ char oeminfo[ACPI_CMBAT_MAXSTRLEN]; /* OEM information */ }; +/* + * Members in acpi_bix are reordered so that the first part is compatible + * with acpi_bif. + */ +struct acpi_bix { +/* _BIF-compatible */ + uint32_t units; /* Power Unit (mW or mA). */ +#define ACPI_BIX_UNITS_MW 0 /* Capacity in mWh, rate in mW. */ +#define ACPI_BIX_UNITS_MA 1 /* Capacity in mAh, rate in mA. */ + uint32_t dcap; /* Design Capacity */ + uint32_t lfcap; /* Last Full capacity */ + uint32_t btech; /* Battery Technology */ + uint32_t dvol; /* Design voltage (mV) */ + uint32_t wcap; /* WARN capacity */ + uint32_t lcap; /* Low capacity */ + uint32_t gra1; /* Granularity 1 (Warn to Low) */ + uint32_t gra2; /* Granularity 2 (Full to Warn) */ + char model[ACPI_CMBAT_MAXSTRLEN]; /* model identifier */ + char serial[ACPI_CMBAT_MAXSTRLEN]; /* Serial number */ + char type[ACPI_CMBAT_MAXSTRLEN]; /* Type */ + char oeminfo[ACPI_CMBAT_MAXSTRLEN]; /* OEM information */ + /* ACPI 4.0 or later */ + uint16_t rev; /* Revision */ +#define ACPI_BIX_REV_0 0 /* ACPI 4.0 _BIX */ +#define ACPI_BIX_REV_1 1 /* ACPI 6.0 _BIX */ +#define ACPI_BIX_REV_BIF 0xffff /* _BIF */ +#define ACPI_BIX_REV_MIN_CHECK(x, min) \ + (((min) == ACPI_BIX_REV_BIF) ? ((x) == ACPI_BIX_REV_BIF) : \ + (((x) == ACPI_BIX_REV_BIF) ? 0 : ((x) >= (min)))) + uint32_t cycles; /* Cycle Count */ + uint32_t accuracy; /* Measurement Accuracy */ + uint32_t stmax; /* Max Sampling Time */ + uint32_t stmin; /* Min Sampling Time */ + uint32_t aimax; /* Max Average Interval */ + uint32_t aimin; /* Min Average Interval */ + /* ACPI 6.0 or later */ + uint32_t scap; /* Battery Swapping Capability */ +#define ACPI_BIX_SCAP_NO 0x00000000 +#define ACPI_BIX_SCAP_COLD 0x00000001 +#define ACPI_BIX_SCAP_HOT 0x00000010 + uint8_t bix_reserved[58]; /* padding */ +}; + +#if 0 +/* acpi_bix in the original order just for reference */ +struct acpi_bix { + uint16_t rev; /* Revision */ + uint32_t units; /* Power Unit (mW or mA). */ + uint32_t dcap; /* Design Capacity */ + uint32_t lfcap; /* Last Full capacity */ + uint32_t btech; /* Battery Technology */ + uint32_t dvol; /* Design voltage (mV) */ + uint32_t wcap; /* Design Capacity of Warning */ + uint32_t lcap; /* Design Capacity of Low */ + uint32_t cycles; /* Cycle Count */ + uint32_t accuracy; /* Measurement Accuracy */ + uint32_t stmax; /* Max Sampling Time */ + uint32_t stmin; /* Min Sampling Time */ + uint32_t aimax; /* Max Average Interval */ + uint32_t aimin; /* Min Average Interval */ + uint32_t gra1; /* Granularity 1 (Warn to Low) */ + uint32_t gra2; /* Granularity 2 (Full to Warn) */ + char model[ACPI_CMBAT_MAXSTRLEN]; /* model identifier */ + char serial[ACPI_CMBAT_MAXSTRLEN]; /* Serial number */ + char type[ACPI_CMBAT_MAXSTRLEN]; /* Type */ + char oeminfo[ACPI_CMBAT_MAXSTRLEN]; /* OEM information */ + uint32_t scap; /* Battery Swapping Capability */ +}; +#endif + struct acpi_bst { uint32_t state; /* Battery State */ uint32_t rate; /* Present Rate */ uint32_t cap; /* Remaining Capacity */ uint32_t volt; /* Present Voltage */ }; /* * Note that the following definitions represent status bits for internal * driver state. The first three of them (charging, discharging and critical) * conveninetly conform to ACPI specification of status returned by _BST * method. Other definitions (not present, etc) are synthetic. * Also note that according to the specification the charging and discharging * status bits must not be set at the same time. */ #define ACPI_BATT_STAT_DISCHARG 0x0001 #define ACPI_BATT_STAT_CHARGING 0x0002 #define ACPI_BATT_STAT_CRITICAL 0x0004 #define ACPI_BATT_STAT_INVALID \ (ACPI_BATT_STAT_DISCHARG | ACPI_BATT_STAT_CHARGING) #define ACPI_BATT_STAT_BST_MASK \ (ACPI_BATT_STAT_INVALID | ACPI_BATT_STAT_CRITICAL) #define ACPI_BATT_STAT_NOT_PRESENT ACPI_BATT_STAT_BST_MASK +/* For backward compatibility */ +union acpi_battery_ioctl_arg_v1 { + int unit; /* Device unit or ACPI_BATTERY_ALL_UNITS. */ + + struct acpi_battinfo battinfo; + + struct acpi_bif bif; + struct acpi_bst bst; +}; union acpi_battery_ioctl_arg { int unit; /* Device unit or ACPI_BATTERY_ALL_UNITS. */ struct acpi_battinfo battinfo; + struct acpi_bix bix; struct acpi_bif bif; struct acpi_bst bst; }; #define ACPI_BATTERY_ALL_UNITS (-1) -#define ACPI_BATT_UNKNOWN 0xffffffff /* _BST or _BIF value unknown. */ +#define ACPI_BATT_UNKNOWN 0xffffffff /* _BST or _BI[FX] value unknown. */ /* Common battery ioctls */ #define ACPIIO_BATT_GET_UNITS _IOR('B', 0x01, int) #define ACPIIO_BATT_GET_BATTINFO _IOWR('B', 0x03, union acpi_battery_ioctl_arg) -#define ACPIIO_BATT_GET_BIF _IOWR('B', 0x10, union acpi_battery_ioctl_arg) +#define ACPIIO_BATT_GET_BATTINFO_V1 _IOWR('B', 0x03, union acpi_battery_ioctl_arg_v1) +#define ACPIIO_BATT_GET_BIF _IOWR('B', 0x10, union acpi_battery_ioctl_arg_v1) +#define ACPIIO_BATT_GET_BIX _IOWR('B', 0x10, union acpi_battery_ioctl_arg) #define ACPIIO_BATT_GET_BST _IOWR('B', 0x11, union acpi_battery_ioctl_arg) +#define ACPIIO_BATT_GET_BST_V1 _IOWR('B', 0x11, union acpi_battery_ioctl_arg_v1) /* Control Method battery ioctls (deprecated) */ #define ACPIIO_CMBAT_GET_BIF ACPIIO_BATT_GET_BIF #define ACPIIO_CMBAT_GET_BST ACPIIO_BATT_GET_BST /* Get AC adapter status. */ #define ACPIIO_ACAD_GET_STATUS _IOR('A', 1, int) #ifdef _KERNEL typedef int (*acpi_ioctl_fn)(u_long cmd, caddr_t addr, void *arg); extern int acpi_register_ioctl(u_long cmd, acpi_ioctl_fn fn, void *arg); extern void acpi_deregister_ioctl(u_long cmd, acpi_ioctl_fn fn); #endif #endif /* !_ACPIIO_H_ */ Index: stable/12/sys/dev/acpica/acpivar.h =================================================================== --- stable/12/sys/dev/acpica/acpivar.h (revision 359075) +++ stable/12/sys/dev/acpica/acpivar.h (revision 359076) @@ -1,552 +1,556 @@ /*- * Copyright (c) 2000 Mitsuru IWASAKI * Copyright (c) 2000 Michael Smith * Copyright (c) 2000 BSDi * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #ifndef _ACPIVAR_H_ #define _ACPIVAR_H_ #ifdef _KERNEL #include "acpi_if.h" #include "bus_if.h" #include #ifdef INTRNG #include #endif #include #include #include #include #include #include #include #include struct apm_clone_data; struct acpi_softc { device_t acpi_dev; struct cdev *acpi_dev_t; int acpi_enabled; int acpi_sstate; int acpi_sleep_disabled; int acpi_resources_reserved; struct sysctl_ctx_list acpi_sysctl_ctx; struct sysctl_oid *acpi_sysctl_tree; int acpi_power_button_sx; int acpi_sleep_button_sx; int acpi_lid_switch_sx; int acpi_standby_sx; int acpi_suspend_sx; int acpi_sleep_delay; int acpi_s4bios; int acpi_do_disable; int acpi_verbose; int acpi_handle_reboot; vm_offset_t acpi_wakeaddr; vm_paddr_t acpi_wakephys; int acpi_next_sstate; /* Next suspend Sx state. */ struct apm_clone_data *acpi_clone; /* Pseudo-dev for devd(8). */ STAILQ_HEAD(,apm_clone_data) apm_cdevs; /* All apm/apmctl/acpi cdevs. */ struct callout susp_force_to; /* Force suspend if no acks. */ }; struct acpi_device { /* ACPI ivars */ ACPI_HANDLE ad_handle; void *ad_private; int ad_flags; int ad_cls_class; /* Resources */ struct resource_list ad_rl; }; #ifdef INTRNG struct intr_map_data_acpi { struct intr_map_data hdr; u_int irq; u_int pol; u_int trig; }; #endif /* Track device (/dev/{apm,apmctl} and /dev/acpi) notification status. */ struct apm_clone_data { STAILQ_ENTRY(apm_clone_data) entries; struct cdev *cdev; int flags; #define ACPI_EVF_NONE 0 /* /dev/apm semantics */ #define ACPI_EVF_DEVD 1 /* /dev/acpi is handled via devd(8) */ #define ACPI_EVF_WRITE 2 /* Device instance is opened writable. */ int notify_status; #define APM_EV_NONE 0 /* Device not yet aware of pending sleep. */ #define APM_EV_NOTIFIED 1 /* Device saw next sleep state. */ #define APM_EV_ACKED 2 /* Device agreed sleep can occur. */ struct acpi_softc *acpi_sc; struct selinfo sel_read; }; #define ACPI_PRW_MAX_POWERRES 8 struct acpi_prw_data { ACPI_HANDLE gpe_handle; int gpe_bit; int lowest_wake; ACPI_OBJECT power_res[ACPI_PRW_MAX_POWERRES]; int power_res_count; }; /* Flags for each device defined in the AML namespace. */ #define ACPI_FLAG_WAKE_ENABLED 0x1 /* Macros for extracting parts of a PCI address from an _ADR value. */ #define ACPI_ADR_PCI_SLOT(adr) (((adr) & 0xffff0000) >> 16) #define ACPI_ADR_PCI_FUNC(adr) ((adr) & 0xffff) /* * Entry points to ACPI from above are global functions defined in this * file, sysctls, and I/O on the control device. Entry points from below * are interrupts (the SCI), notifies, task queue threads, and the thermal * zone polling thread. * * ACPI tables and global shared data are protected by a global lock * (acpi_mutex). * * Each ACPI device can have its own driver-specific mutex for protecting * shared access to local data. The ACPI_LOCK macros handle mutexes. * * Drivers that need to serialize access to functions (e.g., to route * interrupts, get/set control paths, etc.) should use the sx lock macros * (ACPI_SERIAL). * * ACPI-CA handles its own locking and should not be called with locks held. * * The most complicated path is: * GPE -> EC runs _Qxx -> _Qxx reads EC space -> GPE */ extern struct mtx acpi_mutex; #define ACPI_LOCK(sys) mtx_lock(&sys##_mutex) #define ACPI_UNLOCK(sys) mtx_unlock(&sys##_mutex) #define ACPI_LOCK_ASSERT(sys) mtx_assert(&sys##_mutex, MA_OWNED); #define ACPI_LOCK_DECL(sys, name) \ static struct mtx sys##_mutex; \ MTX_SYSINIT(sys##_mutex, &sys##_mutex, name, MTX_DEF) #define ACPI_SERIAL_BEGIN(sys) sx_xlock(&sys##_sxlock) #define ACPI_SERIAL_END(sys) sx_xunlock(&sys##_sxlock) #define ACPI_SERIAL_ASSERT(sys) sx_assert(&sys##_sxlock, SX_XLOCKED); #define ACPI_SERIAL_DECL(sys, name) \ static struct sx sys##_sxlock; \ SX_SYSINIT(sys##_sxlock, &sys##_sxlock, name) /* * ACPI CA does not define layers for non-ACPI CA drivers. * We define some here within the range provided. */ #define ACPI_AC_ADAPTER 0x00010000 #define ACPI_BATTERY 0x00020000 #define ACPI_BUS 0x00040000 #define ACPI_BUTTON 0x00080000 #define ACPI_EC 0x00100000 #define ACPI_FAN 0x00200000 #define ACPI_POWERRES 0x00400000 #define ACPI_PROCESSOR 0x00800000 #define ACPI_THERMAL 0x01000000 #define ACPI_TIMER 0x02000000 #define ACPI_OEM 0x04000000 /* * Constants for different interrupt models used with acpi_SetIntrModel(). */ #define ACPI_INTR_PIC 0 #define ACPI_INTR_APIC 1 #define ACPI_INTR_SAPIC 2 /* * Various features and capabilities for the acpi_get_features() method. * In particular, these are used for the ACPI 3.0 _PDC and _OSC methods. * See the Intel document titled "Intel Processor Vendor-Specific ACPI", * number 302223-007. */ #define ACPI_CAP_PERF_MSRS (1 << 0) /* Intel SpeedStep PERF_CTL MSRs */ #define ACPI_CAP_C1_IO_HALT (1 << 1) /* Intel C1 "IO then halt" sequence */ #define ACPI_CAP_THR_MSRS (1 << 2) /* Intel OnDemand throttling MSRs */ #define ACPI_CAP_SMP_SAME (1 << 3) /* MP C1, Px, and Tx (all the same) */ #define ACPI_CAP_SMP_SAME_C3 (1 << 4) /* MP C2 and C3 (all the same) */ #define ACPI_CAP_SMP_DIFF_PX (1 << 5) /* MP Px (different, using _PSD) */ #define ACPI_CAP_SMP_DIFF_CX (1 << 6) /* MP Cx (different, using _CSD) */ #define ACPI_CAP_SMP_DIFF_TX (1 << 7) /* MP Tx (different, using _TSD) */ #define ACPI_CAP_SMP_C1_NATIVE (1 << 8) /* MP C1 support other than halt */ #define ACPI_CAP_SMP_C3_NATIVE (1 << 9) /* MP C2 and C3 support */ #define ACPI_CAP_PX_HW_COORD (1 << 11) /* Intel P-state HW coordination */ #define ACPI_CAP_INTR_CPPC (1 << 12) /* Native Interrupt Handling for Collaborative Processor Performance Control notifications */ #define ACPI_CAP_HW_DUTY_C (1 << 13) /* Hardware Duty Cycling */ /* * Quirk flags. * * ACPI_Q_BROKEN: Disables all ACPI support. * ACPI_Q_TIMER: Disables support for the ACPI timer. * ACPI_Q_MADT_IRQ0: Specifies that ISA IRQ 0 is wired up to pin 0 of the * first APIC and that the MADT should force that by ignoring the PC-AT * compatible flag and ignoring overrides that redirect IRQ 0 to pin 2. */ extern int acpi_quirks; #define ACPI_Q_OK 0 #define ACPI_Q_BROKEN (1 << 0) #define ACPI_Q_TIMER (1 << 1) #define ACPI_Q_MADT_IRQ0 (1 << 2) /* * Note that the low ivar values are reserved to provide * interface compatibility with ISA drivers which can also * attach to ACPI. */ #define ACPI_IVAR_HANDLE 0x100 #define ACPI_IVAR_UNUSED 0x101 /* Unused/reserved. */ #define ACPI_IVAR_PRIVATE 0x102 #define ACPI_IVAR_FLAGS 0x103 /* * Accessor functions for our ivars. Default value for BUS_READ_IVAR is * (type) 0. The accessor functions don't check return values. */ #define __ACPI_BUS_ACCESSOR(varp, var, ivarp, ivar, type) \ \ static __inline type varp ## _get_ ## var(device_t dev) \ { \ uintptr_t v = 0; \ BUS_READ_IVAR(device_get_parent(dev), dev, \ ivarp ## _IVAR_ ## ivar, &v); \ return ((type) v); \ } \ \ static __inline void varp ## _set_ ## var(device_t dev, type t) \ { \ uintptr_t v = (uintptr_t) t; \ BUS_WRITE_IVAR(device_get_parent(dev), dev, \ ivarp ## _IVAR_ ## ivar, v); \ } __ACPI_BUS_ACCESSOR(acpi, handle, ACPI, HANDLE, ACPI_HANDLE) __ACPI_BUS_ACCESSOR(acpi, private, ACPI, PRIVATE, void *) __ACPI_BUS_ACCESSOR(acpi, flags, ACPI, FLAGS, int) void acpi_fake_objhandler(ACPI_HANDLE h, void *data); static __inline device_t acpi_get_device(ACPI_HANDLE handle) { void *dev = NULL; AcpiGetData(handle, acpi_fake_objhandler, &dev); return ((device_t)dev); } static __inline ACPI_OBJECT_TYPE acpi_get_type(device_t dev) { ACPI_HANDLE h; ACPI_OBJECT_TYPE t; if ((h = acpi_get_handle(dev)) == NULL) return (ACPI_TYPE_NOT_FOUND); if (ACPI_FAILURE(AcpiGetType(h, &t))) return (ACPI_TYPE_NOT_FOUND); return (t); } /* Find the difference between two PM tick counts. */ static __inline uint32_t acpi_TimerDelta(uint32_t end, uint32_t start) { if (end < start && (AcpiGbl_FADT.Flags & ACPI_FADT_32BIT_TIMER) == 0) end |= 0x01000000; return (end - start); } #ifdef ACPI_DEBUGGER void acpi_EnterDebugger(void); #endif #ifdef ACPI_DEBUG #include #define STEP(x) do {printf x, printf("\n"); cngetc();} while (0) #else #define STEP(x) #endif #define ACPI_VPRINT(dev, acpi_sc, x...) do { \ if (acpi_get_verbose(acpi_sc)) \ device_printf(dev, x); \ } while (0) /* Values for the first status word returned by _OSC. */ #define ACPI_OSC_FAILURE (1 << 1) #define ACPI_OSC_BAD_UUID (1 << 2) #define ACPI_OSC_BAD_REVISION (1 << 3) #define ACPI_OSC_CAPS_MASKED (1 << 4) #define ACPI_DEVINFO_PRESENT(x, flags) \ (((x) & (flags)) == (flags)) #define ACPI_DEVICE_PRESENT(x) \ ACPI_DEVINFO_PRESENT(x, ACPI_STA_DEVICE_PRESENT | \ ACPI_STA_DEVICE_FUNCTIONING) #define ACPI_BATTERY_PRESENT(x) \ ACPI_DEVINFO_PRESENT(x, ACPI_STA_DEVICE_PRESENT | \ ACPI_STA_DEVICE_FUNCTIONING | ACPI_STA_BATTERY_PRESENT) /* Callback function type for walking subtables within a table. */ typedef void acpi_subtable_handler(ACPI_SUBTABLE_HEADER *, void *); BOOLEAN acpi_DeviceIsPresent(device_t dev); BOOLEAN acpi_BatteryIsPresent(device_t dev); ACPI_STATUS acpi_GetHandleInScope(ACPI_HANDLE parent, char *path, ACPI_HANDLE *result); ACPI_BUFFER *acpi_AllocBuffer(int size); ACPI_STATUS acpi_ConvertBufferToInteger(ACPI_BUFFER *bufp, UINT32 *number); ACPI_STATUS acpi_GetInteger(ACPI_HANDLE handle, char *path, UINT32 *number); ACPI_STATUS acpi_SetInteger(ACPI_HANDLE handle, char *path, UINT32 number); ACPI_STATUS acpi_ForeachPackageObject(ACPI_OBJECT *obj, void (*func)(ACPI_OBJECT *comp, void *arg), void *arg); ACPI_STATUS acpi_FindIndexedResource(ACPI_BUFFER *buf, int index, ACPI_RESOURCE **resp); ACPI_STATUS acpi_AppendBufferResource(ACPI_BUFFER *buf, ACPI_RESOURCE *res); UINT8 acpi_DSMQuery(ACPI_HANDLE h, uint8_t *uuid, int revision); ACPI_STATUS acpi_EvaluateDSM(ACPI_HANDLE handle, uint8_t *uuid, int revision, uint64_t function, union acpi_object *package, ACPI_BUFFER *out_buf); ACPI_STATUS acpi_EvaluateOSC(ACPI_HANDLE handle, uint8_t *uuid, int revision, int count, uint32_t *caps_in, uint32_t *caps_out, bool query); ACPI_STATUS acpi_OverrideInterruptLevel(UINT32 InterruptNumber); ACPI_STATUS acpi_SetIntrModel(int model); int acpi_ReqSleepState(struct acpi_softc *sc, int state); int acpi_AckSleepState(struct apm_clone_data *clone, int error); ACPI_STATUS acpi_SetSleepState(struct acpi_softc *sc, int state); int acpi_wake_set_enable(device_t dev, int enable); int acpi_parse_prw(ACPI_HANDLE h, struct acpi_prw_data *prw); ACPI_STATUS acpi_Startup(void); void acpi_UserNotify(const char *subsystem, ACPI_HANDLE h, uint8_t notify); int acpi_bus_alloc_gas(device_t dev, int *type, int *rid, ACPI_GENERIC_ADDRESS *gas, struct resource **res, u_int flags); void acpi_walk_subtables(void *first, void *end, acpi_subtable_handler *handler, void *arg); BOOLEAN acpi_MatchHid(ACPI_HANDLE h, const char *hid); struct acpi_parse_resource_set { void (*set_init)(device_t dev, void *arg, void **context); void (*set_done)(device_t dev, void *context); void (*set_ioport)(device_t dev, void *context, uint64_t base, uint64_t length); void (*set_iorange)(device_t dev, void *context, uint64_t low, uint64_t high, uint64_t length, uint64_t align); void (*set_memory)(device_t dev, void *context, uint64_t base, uint64_t length); void (*set_memoryrange)(device_t dev, void *context, uint64_t low, uint64_t high, uint64_t length, uint64_t align); void (*set_irq)(device_t dev, void *context, uint8_t *irq, int count, int trig, int pol); void (*set_ext_irq)(device_t dev, void *context, uint32_t *irq, int count, int trig, int pol); void (*set_drq)(device_t dev, void *context, uint8_t *drq, int count); void (*set_start_dependent)(device_t dev, void *context, int preference); void (*set_end_dependent)(device_t dev, void *context); }; extern struct acpi_parse_resource_set acpi_res_parse_set; int acpi_identify(void); void acpi_config_intr(device_t dev, ACPI_RESOURCE *res); #ifdef INTRNG int acpi_map_intr(device_t dev, u_int irq, ACPI_HANDLE handle); #endif ACPI_STATUS acpi_lookup_irq_resource(device_t dev, int rid, struct resource *res, ACPI_RESOURCE *acpi_res); ACPI_STATUS acpi_parse_resources(device_t dev, ACPI_HANDLE handle, struct acpi_parse_resource_set *set, void *arg); struct resource *acpi_alloc_sysres(device_t child, int type, int *rid, rman_res_t start, rman_res_t end, rman_res_t count, u_int flags); /* ACPI event handling */ UINT32 acpi_event_power_button_sleep(void *context); UINT32 acpi_event_power_button_wake(void *context); UINT32 acpi_event_sleep_button_sleep(void *context); UINT32 acpi_event_sleep_button_wake(void *context); #define ACPI_EVENT_PRI_FIRST 0 #define ACPI_EVENT_PRI_DEFAULT 10000 #define ACPI_EVENT_PRI_LAST 20000 typedef void (*acpi_event_handler_t)(void *, int); EVENTHANDLER_DECLARE(acpi_sleep_event, acpi_event_handler_t); EVENTHANDLER_DECLARE(acpi_wakeup_event, acpi_event_handler_t); /* Device power control. */ ACPI_STATUS acpi_pwr_wake_enable(ACPI_HANDLE consumer, int enable); ACPI_STATUS acpi_pwr_switch_consumer(ACPI_HANDLE consumer, int state); int acpi_device_pwr_for_sleep(device_t bus, device_t dev, int *dstate); /* APM emulation */ void acpi_apm_init(struct acpi_softc *); /* Misc. */ static __inline struct acpi_softc * acpi_device_get_parent_softc(device_t child) { device_t parent; parent = device_get_parent(child); if (parent == NULL) return (NULL); return (device_get_softc(parent)); } static __inline int acpi_get_verbose(struct acpi_softc *sc) { if (sc) return (sc->acpi_verbose); return (0); } char *acpi_name(ACPI_HANDLE handle); int acpi_avoid(ACPI_HANDLE handle); int acpi_disabled(char *subsys); int acpi_machdep_init(device_t dev); void acpi_install_wakeup_handler(struct acpi_softc *sc); int acpi_sleep_machdep(struct acpi_softc *sc, int state); int acpi_wakeup_machdep(struct acpi_softc *sc, int state, int sleep_result, int intr_enabled); int acpi_table_quirks(int *quirks); int acpi_machdep_quirks(int *quirks); uint32_t hpet_get_uid(device_t dev); /* Battery Abstraction. */ struct acpi_battinfo; int acpi_battery_register(device_t dev); int acpi_battery_remove(device_t dev); int acpi_battery_get_units(void); int acpi_battery_get_info_expire(void); int acpi_battery_bst_valid(struct acpi_bst *bst); -int acpi_battery_bif_valid(struct acpi_bif *bif); +int acpi_battery_bix_valid(struct acpi_bix *bix); int acpi_battery_get_battinfo(device_t dev, struct acpi_battinfo *info); /* Embedded controller. */ void acpi_ec_ecdt_probe(device_t); /* AC adapter interface. */ int acpi_acad_get_acline(int *); /* Package manipulation convenience functions. */ #define ACPI_PKG_VALID(pkg, size) \ ((pkg) != NULL && (pkg)->Type == ACPI_TYPE_PACKAGE && \ (pkg)->Package.Count >= (size)) +#define ACPI_PKG_VALID_EQ(pkg, size) \ + ((pkg) != NULL && (pkg)->Type == ACPI_TYPE_PACKAGE && \ + (pkg)->Package.Count == (size)) int acpi_PkgInt(ACPI_OBJECT *res, int idx, UINT64 *dst); int acpi_PkgInt32(ACPI_OBJECT *res, int idx, uint32_t *dst); +int acpi_PkgInt16(ACPI_OBJECT *res, int idx, uint16_t *dst); int acpi_PkgStr(ACPI_OBJECT *res, int idx, void *dst, size_t size); int acpi_PkgGas(device_t dev, ACPI_OBJECT *res, int idx, int *type, int *rid, struct resource **dst, u_int flags); int acpi_PkgFFH_IntelCpu(ACPI_OBJECT *res, int idx, int *vendor, int *class, uint64_t *address, int *accsize); ACPI_HANDLE acpi_GetReference(ACPI_HANDLE scope, ACPI_OBJECT *obj); /* * Base level for BUS_ADD_CHILD. Special devices are added at orders less * than this, and normal devices at or above this level. This keeps the * probe order sorted so that things like sysresource are available before * their children need them. */ #define ACPI_DEV_BASE_ORDER 100 /* Default maximum number of tasks to enqueue. */ #ifndef ACPI_MAX_TASKS #define ACPI_MAX_TASKS MAX(32, MAXCPU * 4) #endif /* Default number of task queue threads to start. */ #ifndef ACPI_MAX_THREADS #define ACPI_MAX_THREADS 3 #endif /* Use the device logging level for ktr(4). */ #define KTR_ACPI KTR_DEV SYSCTL_DECL(_debug_acpi); /* * Parse and use proximity information in SRAT and SLIT. */ int acpi_pxm_init(int ncpus, vm_paddr_t maxphys); void acpi_pxm_parse_tables(void); void acpi_pxm_set_mem_locality(void); void acpi_pxm_set_cpu_locality(void); int acpi_pxm_get_cpu_locality(int apic_id); void acpi_pxm_free(void); /* * Map a PXM to a VM domain. * * Returns the VM domain ID if found, or -1 if not found / invalid. */ int acpi_map_pxm_to_vm_domainid(int pxm); int acpi_get_cpus(device_t dev, device_t child, enum cpu_sets op, size_t setsize, cpuset_t *cpuset); int acpi_get_domain(device_t dev, device_t child, int *domain); #ifdef __aarch64__ /* * ARM specific ACPI interfaces, relating to IORT table. */ int acpi_iort_map_pci_msi(u_int seg, u_int rid, u_int *xref, u_int *devid); int acpi_iort_its_lookup(u_int its_id, u_int *xref, int *pxm); #endif #endif /* _KERNEL */ #endif /* !_ACPIVAR_H_ */ Index: stable/12/usr.sbin/acpi/acpiconf/acpiconf.c =================================================================== --- stable/12/usr.sbin/acpi/acpiconf/acpiconf.c (revision 359075) +++ stable/12/usr.sbin/acpi/acpiconf/acpiconf.c (revision 359076) @@ -1,276 +1,303 @@ /*- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD * * Copyright (c) 1999 Mitsuru IWASAKI * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $Id: acpiconf.c,v 1.5 2000/08/08 14:12:19 iwasaki Exp $ * $FreeBSD$ */ #include #include #include #include #include #include #include #include #include #define ACPIDEV "/dev/acpi" static int acpifd; static void acpi_init(void) { acpifd = open(ACPIDEV, O_RDWR); if (acpifd == -1) acpifd = open(ACPIDEV, O_RDONLY); if (acpifd == -1) err(EX_OSFILE, ACPIDEV); } /* Prepare to sleep and then wait for the signal that sleeping can occur. */ static void acpi_sleep(int sleep_type) { int ret; /* Notify OS that we want to sleep. devd(8) gets this notify. */ ret = ioctl(acpifd, ACPIIO_REQSLPSTATE, &sleep_type); if (ret != 0) err(EX_IOERR, "request sleep type (%d) failed", sleep_type); } /* Ack or abort a pending suspend request. */ static void acpi_sleep_ack(int err_val) { int ret; ret = ioctl(acpifd, ACPIIO_ACKSLPSTATE, &err_val); if (ret != 0) err(EX_IOERR, "ack sleep type failed"); } /* should be a acpi define, but doesn't appear to be */ #define UNKNOWN_CAP 0xffffffff #define UNKNOWN_VOLTAGE 0xffffffff static int acpi_battinfo(int num) { union acpi_battery_ioctl_arg battio; const char *pwr_units; int hours, min, amp; uint32_t volt; if (num < 0 || num > 64) errx(EX_USAGE, "invalid battery %d", num); /* Print battery design information. */ battio.unit = num; - if (ioctl(acpifd, ACPIIO_BATT_GET_BIF, &battio) == -1) + if (ioctl(acpifd, ACPIIO_BATT_GET_BIX, &battio) == -1) err(EX_IOERR, "get battery info (%d) failed", num); - amp = battio.bif.units; + amp = battio.bix.units; pwr_units = amp ? "mA" : "mW"; - if (battio.bif.dcap == UNKNOWN_CAP) + if (battio.bix.dcap == UNKNOWN_CAP) printf("Design capacity:\tunknown\n"); else - printf("Design capacity:\t%d %sh\n", battio.bif.dcap, + printf("Design capacity:\t%d %sh\n", battio.bix.dcap, pwr_units); - if (battio.bif.lfcap == UNKNOWN_CAP) + if (battio.bix.lfcap == UNKNOWN_CAP) printf("Last full capacity:\tunknown\n"); else - printf("Last full capacity:\t%d %sh\n", battio.bif.lfcap, + printf("Last full capacity:\t%d %sh\n", battio.bix.lfcap, pwr_units); - printf("Technology:\t\t%s\n", battio.bif.btech == 0 ? + printf("Technology:\t\t%s\n", battio.bix.btech == 0 ? "primary (non-rechargeable)" : "secondary (rechargeable)"); - if (battio.bif.dvol == UNKNOWN_CAP) + if (ACPI_BIX_REV_MIN_CHECK(battio.bix.rev, ACPI_BIX_REV_1)) { + printf("Battery Swappable Capability:\t"); + if (battio.bix.scap == ACPI_BIX_SCAP_NO) + printf("Non-swappable\n"); + else if (battio.bix.scap == ACPI_BIX_SCAP_COLD) + printf("cold swap\n"); + else if (battio.bix.scap == ACPI_BIX_SCAP_HOT) + printf("hot swap\n"); + else + printf("unknown\n"); + } + if (battio.bix.dvol == UNKNOWN_CAP) printf("Design voltage:\t\tunknown\n"); else - printf("Design voltage:\t\t%d mV\n", battio.bif.dvol); - printf("Capacity (warn):\t%d %sh\n", battio.bif.wcap, pwr_units); - printf("Capacity (low):\t\t%d %sh\n", battio.bif.lcap, pwr_units); - printf("Low/warn granularity:\t%d %sh\n", battio.bif.gra1, pwr_units); - printf("Warn/full granularity:\t%d %sh\n", battio.bif.gra2, pwr_units); - printf("Model number:\t\t%s\n", battio.bif.model); - printf("Serial number:\t\t%s\n", battio.bif.serial); - printf("Type:\t\t\t%s\n", battio.bif.type); - printf("OEM info:\t\t%s\n", battio.bif.oeminfo); + printf("Design voltage:\t\t%d mV\n", battio.bix.dvol); + printf("Capacity (warn):\t%d %sh\n", battio.bix.wcap, pwr_units); + printf("Capacity (low):\t\t%d %sh\n", battio.bix.lcap, pwr_units); + if (ACPI_BIX_REV_MIN_CHECK(battio.bix.rev, ACPI_BIX_REV_0)) { + if (battio.bix.cycles != ACPI_BATT_UNKNOWN) + printf("Cycle Count:\t\t%d\n", battio.bix.cycles); + printf("Mesurement Accuracy:\t%d %%\n", + battio.bix.accuracy / 1000); + if (battio.bix.stmax != ACPI_BATT_UNKNOWN) + printf("Max Sampling Time:\t%d ms\n", + battio.bix.stmax); + if (battio.bix.stmin != ACPI_BATT_UNKNOWN) + printf("Min Sampling Time:\t%d ms\n", + battio.bix.stmin); + printf("Max Average Interval:\t%d ms\n", + battio.bix.aimax); + printf("Min Average Interval:\t%d ms\n", + battio.bix.aimin); + } + printf("Low/warn granularity:\t%d %sh\n", battio.bix.gra1, pwr_units); + printf("Warn/full granularity:\t%d %sh\n", battio.bix.gra2, pwr_units); + printf("Model number:\t\t%s\n", battio.bix.model); + printf("Serial number:\t\t%s\n", battio.bix.serial); + printf("Type:\t\t\t%s\n", battio.bix.type); + printf("OEM info:\t\t%s\n", battio.bix.oeminfo); /* Fetch battery voltage information. */ volt = UNKNOWN_VOLTAGE; battio.unit = num; if (ioctl(acpifd, ACPIIO_BATT_GET_BST, &battio) == -1) err(EX_IOERR, "get battery status (%d) failed", num); if (battio.bst.state != ACPI_BATT_STAT_NOT_PRESENT) volt = battio.bst.volt; /* Print current battery state information. */ battio.unit = num; if (ioctl(acpifd, ACPIIO_BATT_GET_BATTINFO, &battio) == -1) err(EX_IOERR, "get battery user info (%d) failed", num); if (battio.battinfo.state != ACPI_BATT_STAT_NOT_PRESENT) { const char *state; switch (battio.battinfo.state & ACPI_BATT_STAT_BST_MASK) { case 0: state = "high"; break; case ACPI_BATT_STAT_DISCHARG: state = "discharging"; break; case ACPI_BATT_STAT_CHARGING: state = "charging"; break; case ACPI_BATT_STAT_CRITICAL: state = "critical"; break; case ACPI_BATT_STAT_DISCHARG | ACPI_BATT_STAT_CRITICAL: state = "critical discharging"; break; case ACPI_BATT_STAT_CHARGING | ACPI_BATT_STAT_CRITICAL: state = "critical charging"; break; default: state = "invalid"; } printf("State:\t\t\t%s\n", state); if (battio.battinfo.cap == -1) printf("Remaining capacity:\tunknown\n"); else printf("Remaining capacity:\t%d%%\n", battio.battinfo.cap); if (battio.battinfo.min == -1) printf("Remaining time:\t\tunknown\n"); else { hours = battio.battinfo.min / 60; min = battio.battinfo.min % 60; printf("Remaining time:\t\t%d:%02d\n", hours, min); } if (battio.battinfo.rate == -1) printf("Present rate:\t\tunknown\n"); else if (amp && volt != UNKNOWN_VOLTAGE) { printf("Present rate:\t\t%d mA (%d mW)\n", battio.battinfo.rate, battio.battinfo.rate * volt / 1000); } else printf("Present rate:\t\t%d %s\n", battio.battinfo.rate, pwr_units); } else printf("State:\t\t\tnot present\n"); /* Print battery voltage information. */ if (volt == UNKNOWN_VOLTAGE) printf("Present voltage:\tunknown\n"); else printf("Present voltage:\t%d mV\n", volt); return (0); } static void usage(const char* prog) { printf("usage: %s [-h] [-i batt] [-k ack] [-s 1-4]\n", prog); exit(0); } int main(int argc, char *argv[]) { char *prog, *end; int c, sleep_type, battery, ack; int iflag = 0, kflag = 0, sflag = 0; prog = argv[0]; if (argc < 2) usage(prog); /* NOTREACHED */ sleep_type = -1; acpi_init(); while ((c = getopt(argc, argv, "hi:k:s:")) != -1) { switch (c) { case 'i': iflag = 1; battery = strtol(optarg, &end, 10); if ((size_t)(end - optarg) != strlen(optarg)) errx(EX_USAGE, "invalid battery"); break; case 'k': kflag = 1; ack = strtol(optarg, &end, 10); if ((size_t)(end - optarg) != strlen(optarg)) errx(EX_USAGE, "invalid ack argument"); break; case 's': sflag = 1; if (optarg[0] == 'S') optarg++; sleep_type = strtol(optarg, &end, 10); if ((size_t)(end - optarg) != strlen(optarg)) errx(EX_USAGE, "invalid sleep type"); if (sleep_type < 1 || sleep_type > 4) errx(EX_USAGE, "invalid sleep type (%d)", sleep_type); break; case 'h': default: usage(prog); /* NOTREACHED */ } } argc -= optind; argv += optind; if (iflag != 0 && kflag != 0 && sflag != 0) errx(EX_USAGE, "-i, -k and -s are mutually exclusive"); if (iflag != 0) { if (kflag != 0) errx(EX_USAGE, "-i and -k are mutually exclusive"); if (sflag != 0) errx(EX_USAGE, "-i and -s are mutually exclusive"); acpi_battinfo(battery); } if (kflag != 0) { if (sflag != 0) errx(EX_USAGE, "-k and -s are mutually exclusive"); acpi_sleep_ack(ack); } if (sflag != 0) acpi_sleep(sleep_type); close(acpifd); exit (0); } Index: stable/12 =================================================================== --- stable/12 (revision 359075) +++ stable/12 (revision 359076) Property changes on: stable/12 ___________________________________________________________________ Modified: svn:mergeinfo ## -0,0 +0,1 ## Merged /head:r355574,358095,358395