From 2a6179996e5a503bd61c641cef1e49ba5fb1576f Mon Sep 17 00:00:00 2001 From: Sascha Wildner Date: Mon, 10 Nov 2014 11:49:03 +0100 Subject: [PATCH] Remove the old USB stack and related userland, etc. As detailed in UPDATING, users with a custom configuration file which was derived from a *GENERIC file before we made usb4bsd default (this happened in 3.6) might need to remove or comment out a couple of devices which are now unknown. --- Makefile_upgrade.inc | 591 +-- UPDATING | 25 +- etc/Makefile | 2 +- etc/defaults/rc.conf | 2 - etc/mtree/BSD.include.dist | 2 - etc/rc.d/Makefile | 2 +- etc/rc.d/syscons | 2 +- etc/rc.d/usbd | 21 - etc/usbd.conf | 54 - include/Makefile | 8 +- lib/Makefile | 11 +- lib/libusbhid/Makefile | 25 - lib/libusbhid/data.c | 94 - lib/libusbhid/descr.c | 79 - lib/libusbhid/parse.c | 440 -- lib/libusbhid/usage.c | 237 -- lib/libusbhid/usbhid.3 | 225 - lib/libusbhid/usbhid.h | 109 - lib/libusbhid/usbvar.h | 37 - share/examples/etc/README.examples | 1 - share/man/man4/Makefile | 66 +- share/man/man4/lgue.4 | 62 - share/man/man4/rue.4 | 155 - share/man/man4/snd_uaudio.4 | 4 +- share/man/man4/ural.4 | 175 - share/man/man5/make.conf.5 | 5 - share/man/man5/rc.conf.5 | 17 - sys/bus/Makefile | 8 +- sys/bus/pci/pci.c | 11 - sys/bus/usb/FILES | 58 - sys/bus/usb/Makefile | 7 - sys/bus/usb/dsbr100io.h | 42 - sys/bus/usb/ehci.c | 3201 --------------- sys/bus/usb/ehci/Makefile | 11 - sys/bus/usb/ehci_pci.c | 569 --- sys/bus/usb/ehcireg.h | 301 -- sys/bus/usb/ehcivar.h | 173 - sys/bus/usb/hid.c | 461 --- sys/bus/usb/hid.h | 94 - sys/bus/usb/kue_fw.h | 686 ---- sys/bus/usb/ohci.c | 3616 ---------------- sys/bus/usb/ohci_pci.c | 399 -- sys/bus/usb/ohcireg.h | 250 -- sys/bus/usb/ohcivar.h | 166 - sys/bus/usb/rio500_usb.h | 44 - sys/bus/usb/ugraphire_rdesc.h | 95 - sys/bus/usb/uhci.c | 3497 ---------------- sys/bus/usb/uhci_pci.c | 496 --- sys/bus/usb/uhcireg.h | 194 - sys/bus/usb/uhcivar.h | 201 - sys/bus/usb/uhub.c | 739 ---- sys/bus/usb/usb.c | 996 ----- sys/bus/usb/usb.h | 702 ---- sys/bus/usb/usb/Makefile | 25 - sys/bus/usb/usb_ethersubr.c | 110 - sys/bus/usb/usb_ethersubr.h | 47 - sys/bus/usb/usb_if.m | 43 - sys/bus/usb/usb_mem.c | 297 -- sys/bus/usb/usb_mem.h | 61 - sys/bus/usb/usb_port.h | 191 - sys/bus/usb/usb_quirks.c | 197 - sys/bus/usb/usb_quirks.h | 64 - sys/bus/usb/usb_subr.c | 1275 ------ sys/bus/usb/usbcdc.h | 184 - sys/bus/usb/usbdi.c | 1245 ------ sys/bus/usb/usbdi.h | 280 -- sys/bus/usb/usbdi_util.c | 564 --- sys/bus/usb/usbdi_util.h | 99 - sys/bus/usb/usbdivar.h | 293 -- sys/bus/usb/usbhid.h | 190 - sys/conf/files | 50 - sys/conf/kmod.mk | 8 +- sys/config/GENERIC | 18 +- sys/config/LINT | 35 - sys/config/LINT64 | 35 - sys/config/SOEKRIS | 13 +- sys/config/X86_64_GENERIC | 18 +- sys/dev/Makefile | 4 - sys/dev/disk/nata/Makefile | 4 - sys/dev/disk/nata/ata-usb.c | 989 ----- sys/dev/disk/nata/natausb/Makefile | 9 - sys/dev/netif/Makefile | 4 - sys/dev/netif/aue/Makefile | 8 - sys/dev/netif/aue/if_aue.c | 1482 ------- sys/dev/netif/aue/if_auereg.h | 250 -- sys/dev/netif/axe/Makefile | 7 - sys/dev/netif/axe/if_axe.c | 1069 ----- sys/dev/netif/axe/if_axereg.h | 158 - sys/dev/netif/cue/Makefile | 7 - sys/dev/netif/cue/if_cue.c | 1150 ------ sys/dev/netif/cue/if_cuereg.h | 180 - sys/dev/netif/kue/Makefile | 8 - sys/dev/netif/kue/if_kue.c | 1105 ----- sys/dev/netif/kue/if_kuereg.h | 181 - sys/dev/netif/lgue/Makefile | 10 - sys/dev/netif/lgue/if_lgue.c | 864 ---- sys/dev/netif/lgue/if_lgue.h | 57 - sys/dev/netif/ndis/Makefile | 10 +- sys/dev/netif/ndis/if_ndis.c | 28 - sys/dev/netif/ndis/if_ndis_pccard.c | 7 - sys/dev/netif/ndis/if_ndis_pci.c | 7 - sys/dev/netif/ndis/if_ndis_usb.c | 263 -- sys/dev/netif/ndis/if_ndisvar.h | 46 - sys/dev/netif/rue/Makefile | 8 - sys/dev/netif/rue/if_rue.c | 1380 ------- sys/dev/netif/rue/if_ruereg.h | 228 -- sys/dev/sound/driver/Makefile | 4 - sys/dev/sound/driver/uaudio/Makefile | 10 - sys/dev/sound/usb/uaudio.c | 3146 -------------- sys/dev/sound/usb/uaudio.h | 54 - sys/dev/sound/usb/uaudio_pcm.c | 417 -- sys/dev/sound/usb/uaudioreg.h | 405 -- sys/dev/usbmisc/Makefile | 8 - sys/dev/usbmisc/moscom/Makefile | 9 - sys/dev/usbmisc/moscom/moscom.c | 449 -- sys/dev/usbmisc/uark/Makefile | 8 - sys/dev/usbmisc/uark/uark.c | 371 -- sys/dev/usbmisc/ubsa/Makefile | 9 - sys/dev/usbmisc/ubsa/ubsa.c | 713 ---- sys/dev/usbmisc/ubt/Makefile | 6 - sys/dev/usbmisc/ubt/ubt.c | 1669 -------- sys/dev/usbmisc/uchcom/Makefile | 9 - sys/dev/usbmisc/uchcom/uchcom.c | 1028 ----- sys/dev/usbmisc/ucom/Makefile | 10 - sys/dev/usbmisc/ucom/ucom.c | 1299 ------ sys/dev/usbmisc/ucom/ucomvar.h | 186 - sys/dev/usbmisc/ufm/Makefile | 8 - sys/dev/usbmisc/ufm/ufm.c | 380 -- sys/dev/usbmisc/uftdi/Makefile | 10 - sys/dev/usbmisc/uftdi/uftdi.c | 999 ----- sys/dev/usbmisc/uftdi/uftdireg.h | 341 -- sys/dev/usbmisc/ugen/Makefile | 8 - sys/dev/usbmisc/ugen/ugen.c | 1564 ------- sys/dev/usbmisc/ugen/ugenbuf.c | 96 - sys/dev/usbmisc/ugen/ugenbuf.h | 40 - sys/dev/usbmisc/ugensa/Makefile | 8 - sys/dev/usbmisc/ugensa/ugensa.c | 477 --- sys/dev/usbmisc/uhid/Makefile | 8 - sys/dev/usbmisc/uhid/uhid.c | 747 ---- sys/dev/usbmisc/ukbd/Makefile | 14 - sys/dev/usbmisc/ukbd/ukbd.c | 1540 ------- sys/dev/usbmisc/ulpt/Makefile | 8 - sys/dev/usbmisc/ulpt/ulpt.c | 758 ---- sys/dev/usbmisc/umass/Makefile | 11 - sys/dev/usbmisc/umass/umass.c | 3636 ----------------- sys/dev/usbmisc/umct/Makefile | 9 - sys/dev/usbmisc/umct/umct.c | 501 --- sys/dev/usbmisc/umodem/Makefile | 8 - sys/dev/usbmisc/umodem/umodem.c | 774 ---- sys/dev/usbmisc/ums/Makefile | 8 - sys/dev/usbmisc/ums/ums.c | 839 ---- sys/dev/usbmisc/uplcom/Makefile | 9 - sys/dev/usbmisc/uplcom/uplcom.c | 984 ----- sys/dev/usbmisc/urio/urio.c | 560 --- sys/dev/usbmisc/uscanner/Makefile | 8 - sys/dev/usbmisc/uscanner/uscanner.c | 678 --- sys/dev/usbmisc/uslcom/Makefile | 8 - sys/dev/usbmisc/uslcom/uslcom.c | 480 --- sys/dev/usbmisc/uticom/Makefile | 10 - sys/dev/usbmisc/uticom/uticom.c | 971 ----- sys/dev/usbmisc/uticom/uticom_fw3410.h | 303 -- sys/dev/usbmisc/uvisor/Makefile | 9 - sys/dev/usbmisc/uvisor/uvisor.c | 532 --- sys/dev/usbmisc/uvscom/Makefile | 9 - sys/dev/usbmisc/uvscom/uvscom.c | 865 ---- sys/emulation/ndis/Makefile | 10 +- sys/emulation/ndis/kern_ndis.c | 11 - sys/emulation/ndis/kern_windrv.c | 11 - sys/emulation/ndis/ntoskrnl_var.h | 10 - sys/emulation/ndis/subr_ndis.c | 7 - sys/emulation/ndis/subr_usbd.c | 1207 ------ sys/platform/pc32/conf/files | 2 - sys/platform/pc64/conf/files | 2 - .../tools/convert_usb_ids/convert_usb_ids.sh | 155 - usr.bin/Makefile | 11 +- usr.bin/usbhidctl/Makefile | 12 - usr.bin/usbhidctl/usbhid.c | 343 -- usr.bin/usbhidctl/usbhidctl.1 | 98 - usr.sbin/Makefile | 14 +- usr.sbin/usbd/Makefile | 7 - usr.sbin/usbd/usbd.8 | 144 - usr.sbin/usbd/usbd.c | 1128 ----- usr.sbin/usbd/usbd.conf.5 | 163 - usr.sbin/usbdevs/Makefile | 9 - usr.sbin/usbdevs/usbdevs.8 | 74 - usr.sbin/usbdevs/usbdevs.c | 227 - 186 files changed, 111 insertions(+), 65895 deletions(-) delete mode 100644 etc/rc.d/usbd delete mode 100644 etc/usbd.conf delete mode 100644 lib/libusbhid/Makefile delete mode 100644 lib/libusbhid/data.c delete mode 100644 lib/libusbhid/descr.c delete mode 100644 lib/libusbhid/parse.c delete mode 100644 lib/libusbhid/usage.c delete mode 100644 lib/libusbhid/usbhid.3 delete mode 100644 lib/libusbhid/usbhid.h delete mode 100644 lib/libusbhid/usbvar.h delete mode 100644 share/man/man4/lgue.4 delete mode 100644 share/man/man4/rue.4 delete mode 100644 share/man/man4/ural.4 delete mode 100644 sys/bus/usb/FILES delete mode 100644 sys/bus/usb/Makefile delete mode 100644 sys/bus/usb/dsbr100io.h delete mode 100644 sys/bus/usb/ehci.c delete mode 100644 sys/bus/usb/ehci/Makefile delete mode 100644 sys/bus/usb/ehci_pci.c delete mode 100644 sys/bus/usb/ehcireg.h delete mode 100644 sys/bus/usb/ehcivar.h delete mode 100644 sys/bus/usb/hid.c delete mode 100644 sys/bus/usb/hid.h delete mode 100644 sys/bus/usb/kue_fw.h delete mode 100644 sys/bus/usb/ohci.c delete mode 100644 sys/bus/usb/ohci_pci.c delete mode 100644 sys/bus/usb/ohcireg.h delete mode 100644 sys/bus/usb/ohcivar.h delete mode 100644 sys/bus/usb/rio500_usb.h delete mode 100644 sys/bus/usb/ugraphire_rdesc.h delete mode 100644 sys/bus/usb/uhci.c delete mode 100644 sys/bus/usb/uhci_pci.c delete mode 100644 sys/bus/usb/uhcireg.h delete mode 100644 sys/bus/usb/uhcivar.h delete mode 100644 sys/bus/usb/uhub.c delete mode 100644 sys/bus/usb/usb.c delete mode 100644 sys/bus/usb/usb.h delete mode 100644 sys/bus/usb/usb/Makefile delete mode 100644 sys/bus/usb/usb_ethersubr.c delete mode 100644 sys/bus/usb/usb_ethersubr.h delete mode 100644 sys/bus/usb/usb_if.m delete mode 100644 sys/bus/usb/usb_mem.c delete mode 100644 sys/bus/usb/usb_mem.h delete mode 100644 sys/bus/usb/usb_port.h delete mode 100644 sys/bus/usb/usb_quirks.c delete mode 100644 sys/bus/usb/usb_quirks.h delete mode 100644 sys/bus/usb/usb_subr.c delete mode 100644 sys/bus/usb/usbcdc.h delete mode 100644 sys/bus/usb/usbdi.c delete mode 100644 sys/bus/usb/usbdi.h delete mode 100644 sys/bus/usb/usbdi_util.c delete mode 100644 sys/bus/usb/usbdi_util.h delete mode 100644 sys/bus/usb/usbdivar.h delete mode 100644 sys/bus/usb/usbhid.h delete mode 100644 sys/dev/disk/nata/ata-usb.c delete mode 100644 sys/dev/disk/nata/natausb/Makefile delete mode 100644 sys/dev/netif/aue/Makefile delete mode 100644 sys/dev/netif/aue/if_aue.c delete mode 100644 sys/dev/netif/aue/if_auereg.h delete mode 100644 sys/dev/netif/axe/Makefile delete mode 100644 sys/dev/netif/axe/if_axe.c delete mode 100644 sys/dev/netif/axe/if_axereg.h delete mode 100644 sys/dev/netif/cue/Makefile delete mode 100644 sys/dev/netif/cue/if_cue.c delete mode 100644 sys/dev/netif/cue/if_cuereg.h delete mode 100644 sys/dev/netif/kue/Makefile delete mode 100644 sys/dev/netif/kue/if_kue.c delete mode 100644 sys/dev/netif/kue/if_kuereg.h delete mode 100644 sys/dev/netif/lgue/Makefile delete mode 100644 sys/dev/netif/lgue/if_lgue.c delete mode 100644 sys/dev/netif/lgue/if_lgue.h delete mode 100644 sys/dev/netif/ndis/if_ndis_usb.c delete mode 100644 sys/dev/netif/rue/Makefile delete mode 100644 sys/dev/netif/rue/if_rue.c delete mode 100644 sys/dev/netif/rue/if_ruereg.h delete mode 100644 sys/dev/sound/driver/uaudio/Makefile delete mode 100644 sys/dev/sound/usb/uaudio.c delete mode 100644 sys/dev/sound/usb/uaudio.h delete mode 100644 sys/dev/sound/usb/uaudio_pcm.c delete mode 100644 sys/dev/sound/usb/uaudioreg.h delete mode 100644 sys/dev/usbmisc/Makefile delete mode 100644 sys/dev/usbmisc/moscom/Makefile delete mode 100644 sys/dev/usbmisc/moscom/moscom.c delete mode 100644 sys/dev/usbmisc/uark/Makefile delete mode 100644 sys/dev/usbmisc/uark/uark.c delete mode 100644 sys/dev/usbmisc/ubsa/Makefile delete mode 100644 sys/dev/usbmisc/ubsa/ubsa.c delete mode 100644 sys/dev/usbmisc/ubt/Makefile delete mode 100644 sys/dev/usbmisc/ubt/ubt.c delete mode 100644 sys/dev/usbmisc/uchcom/Makefile delete mode 100644 sys/dev/usbmisc/uchcom/uchcom.c delete mode 100644 sys/dev/usbmisc/ucom/Makefile delete mode 100644 sys/dev/usbmisc/ucom/ucom.c delete mode 100644 sys/dev/usbmisc/ucom/ucomvar.h delete mode 100644 sys/dev/usbmisc/ufm/Makefile delete mode 100644 sys/dev/usbmisc/ufm/ufm.c delete mode 100644 sys/dev/usbmisc/uftdi/Makefile delete mode 100644 sys/dev/usbmisc/uftdi/uftdi.c delete mode 100644 sys/dev/usbmisc/uftdi/uftdireg.h delete mode 100644 sys/dev/usbmisc/ugen/Makefile delete mode 100644 sys/dev/usbmisc/ugen/ugen.c delete mode 100644 sys/dev/usbmisc/ugen/ugenbuf.c delete mode 100644 sys/dev/usbmisc/ugen/ugenbuf.h delete mode 100644 sys/dev/usbmisc/ugensa/Makefile delete mode 100644 sys/dev/usbmisc/ugensa/ugensa.c delete mode 100644 sys/dev/usbmisc/uhid/Makefile delete mode 100644 sys/dev/usbmisc/uhid/uhid.c delete mode 100644 sys/dev/usbmisc/ukbd/Makefile delete mode 100644 sys/dev/usbmisc/ukbd/ukbd.c delete mode 100644 sys/dev/usbmisc/ulpt/Makefile delete mode 100644 sys/dev/usbmisc/ulpt/ulpt.c delete mode 100644 sys/dev/usbmisc/umass/Makefile delete mode 100644 sys/dev/usbmisc/umass/umass.c delete mode 100644 sys/dev/usbmisc/umct/Makefile delete mode 100644 sys/dev/usbmisc/umct/umct.c delete mode 100644 sys/dev/usbmisc/umodem/Makefile delete mode 100644 sys/dev/usbmisc/umodem/umodem.c delete mode 100644 sys/dev/usbmisc/ums/Makefile delete mode 100644 sys/dev/usbmisc/ums/ums.c delete mode 100644 sys/dev/usbmisc/uplcom/Makefile delete mode 100644 sys/dev/usbmisc/uplcom/uplcom.c delete mode 100644 sys/dev/usbmisc/urio/urio.c delete mode 100644 sys/dev/usbmisc/uscanner/Makefile delete mode 100644 sys/dev/usbmisc/uscanner/uscanner.c delete mode 100644 sys/dev/usbmisc/uslcom/Makefile delete mode 100644 sys/dev/usbmisc/uslcom/uslcom.c delete mode 100644 sys/dev/usbmisc/uticom/Makefile delete mode 100644 sys/dev/usbmisc/uticom/uticom.c delete mode 100644 sys/dev/usbmisc/uticom/uticom_fw3410.h delete mode 100644 sys/dev/usbmisc/uvisor/Makefile delete mode 100644 sys/dev/usbmisc/uvisor/uvisor.c delete mode 100644 sys/dev/usbmisc/uvscom/Makefile delete mode 100644 sys/dev/usbmisc/uvscom/uvscom.c delete mode 100644 sys/emulation/ndis/subr_usbd.c delete mode 100644 tools/tools/convert_usb_ids/convert_usb_ids.sh delete mode 100644 usr.bin/usbhidctl/Makefile delete mode 100644 usr.bin/usbhidctl/usbhid.c delete mode 100644 usr.bin/usbhidctl/usbhidctl.1 delete mode 100644 usr.sbin/usbd/Makefile delete mode 100644 usr.sbin/usbd/usbd.8 delete mode 100644 usr.sbin/usbd/usbd.c delete mode 100644 usr.sbin/usbd/usbd.conf.5 delete mode 100644 usr.sbin/usbdevs/Makefile delete mode 100644 usr.sbin/usbdevs/usbdevs.8 delete mode 100644 usr.sbin/usbdevs/usbdevs.c diff --git a/Makefile_upgrade.inc b/Makefile_upgrade.inc index eec67ee79c..54d3c05acb 100644 --- a/Makefile_upgrade.inc +++ b/Makefile_upgrade.inc @@ -2680,6 +2680,39 @@ TO_REMOVE+=/usr/share/man/cat1/pkg_search.1.gz TO_REMOVE+=/usr/share/man/man1/pkg_search.1.gz TO_REMOVE+=/usr/share/man/cat7/pkgsrc.7.gz TO_REMOVE+=/usr/share/man/man7/pkgsrc.7.gz +TO_REMOVE+=/boot/kernel/if_lgue.ko +TO_REMOVE+=/boot/kernel/if_rue.ko +TO_REMOVE+=/boot/kernel/if_ural.ko +TO_REMOVE+=/boot/kernel/moscom.ko +TO_REMOVE+=/boot/kernel/natausb.ko +TO_REMOVE+=/boot/kernel/snd_uaudio.ko +TO_REMOVE+=/boot/kernel/ubt.ko +TO_REMOVE+=/boot/kernel/ugen.ko +TO_REMOVE+=/boot/kernel/uscanner.ko +TO_REMOVE+=/boot/kernel/uticom.ko +TO_REMOVE+=/etc/rc.d/usbd +TO_REMOVE+=/usr/include/bus/usb +TO_REMOVE+=/usr/sbin/usbd +TO_REMOVE+=/usr/sbin/usbdevs +TO_REMOVE+=/usr/share/examples/etc/usbd.conf +TO_REMOVE+=/usr/share/man/cat4/if_lgue.4.gz +TO_REMOVE+=/usr/share/man/man4/if_lgue.4.gz +TO_REMOVE+=/usr/share/man/cat4/if_rue.4.gz +TO_REMOVE+=/usr/share/man/man4/if_rue.4.gz +TO_REMOVE+=/usr/share/man/cat4/if_ural.4.gz +TO_REMOVE+=/usr/share/man/man4/if_ural.4.gz +TO_REMOVE+=/usr/share/man/cat4/lgue.4.gz +TO_REMOVE+=/usr/share/man/man4/lgue.4.gz +TO_REMOVE+=/usr/share/man/cat4/rue.4.gz +TO_REMOVE+=/usr/share/man/man4/rue.4.gz +TO_REMOVE+=/usr/share/man/cat4/ural.4.gz +TO_REMOVE+=/usr/share/man/man4/ural.4.gz +TO_REMOVE+=/usr/share/man/cat5/usbd.conf.5.gz +TO_REMOVE+=/usr/share/man/cat8/usbd.8.gz +TO_REMOVE+=/usr/share/man/cat8/usbdevs.8.gz +TO_REMOVE+=/usr/share/man/man5/usbd.conf.5.gz +TO_REMOVE+=/usr/share/man/man8/usbd.8.gz +TO_REMOVE+=/usr/share/man/man8/usbdevs.8.gz .if ${MACHINE_ARCH} == "x86_64" TO_REMOVE+=/usr/sbin/stlstats @@ -2720,561 +2753,3 @@ TO_REMOVE+=/usr/share/man/man4/iwl.4.gz TO_REMOVE+=/boot/kernel/if_rtw.ko TO_REMOVE+=/usr/share/man/cat4/rtw.4.gz TO_REMOVE+=/usr/share/man/man4/rtw.4.gz -TO_REMOVE+=/boot/kernel/if_ural.ko -TO_REMOVE+=/usr/share/man/cat4/ural.4.gz -TO_REMOVE+=/usr/share/man/man4/ural.4.gz - -# Clean up old USB stuff when the new stack is requested -# and vice versa -.if !defined(WANT_OLDUSB) -TO_REMOVE+=/boot/kernel/if_lgue.ko -TO_REMOVE+=/boot/kernel/if_rue.ko -TO_REMOVE+=/boot/kernel/moscom.ko -TO_REMOVE+=/boot/kernel/natausb.ko -TO_REMOVE+=/boot/kernel/snd_uaudio.ko -TO_REMOVE+=/boot/kernel/ubt.ko -TO_REMOVE+=/boot/kernel/ugen.ko -TO_REMOVE+=/boot/kernel/uscanner.ko -TO_REMOVE+=/boot/kernel/uticom.ko -TO_REMOVE+=/usr/include/bus/usb/dsbr100io.h -TO_REMOVE+=/usr/include/bus/usb/ehcireg.h -TO_REMOVE+=/usr/include/bus/usb/ehcivar.h -TO_REMOVE+=/usr/include/bus/usb/hid.h -TO_REMOVE+=/usr/include/bus/usb/kue_fw.h -TO_REMOVE+=/usr/include/bus/usb/ohcireg.h -TO_REMOVE+=/usr/include/bus/usb/ohcivar.h -TO_REMOVE+=/usr/include/bus/usb/rio500_usb.h -TO_REMOVE+=/usr/include/bus/usb/ugraphire_rdesc.h -TO_REMOVE+=/usr/include/bus/usb/uhcireg.h -TO_REMOVE+=/usr/include/bus/usb/uhcivar.h -TO_REMOVE+=/usr/include/bus/usb/usb.h -TO_REMOVE+=/usr/include/bus/usb/usb_ethersubr.h -TO_REMOVE+=/usr/include/bus/usb/usb_mem.h -TO_REMOVE+=/usr/include/bus/usb/usb_port.h -TO_REMOVE+=/usr/include/bus/usb/usb_quirks.h -TO_REMOVE+=/usr/include/bus/usb/usbcdc.h -TO_REMOVE+=/usr/include/bus/usb/usbdi.h -TO_REMOVE+=/usr/include/bus/usb/usbdi_util.h -TO_REMOVE+=/usr/include/bus/usb/usbdivar.h -TO_REMOVE+=/usr/include/bus/usb/usbhid.h -TO_REMOVE+=/usr/sbin/usbd -TO_REMOVE+=/usr/sbin/usbdevs -TO_REMOVE+=/usr/share/man/cat5/usbd.conf.5.gz -TO_REMOVE+=/usr/share/man/cat8/usbd.8.gz -TO_REMOVE+=/usr/share/man/cat8/usbdevs.8.gz -TO_REMOVE+=/usr/share/man/man5/usbd.conf.5.gz -TO_REMOVE+=/usr/share/man/man8/usbd.8.gz -TO_REMOVE+=/usr/share/man/man8/usbdevs.8.gz -.else -TO_REMOVE+=/boot/kernel/if_ipheth.ko -TO_REMOVE+=/boot/kernel/if_mos.ko -TO_REMOVE+=/boot/kernel/if_rum.ko -TO_REMOVE+=/boot/kernel/if_run.ko -TO_REMOVE+=/boot/kernel/if_udav.ko -TO_REMOVE+=/boot/kernel/if_urndis.ko -TO_REMOVE+=/boot/kernel/if_urtwn.ko -TO_REMOVE+=/boot/kernel/ohci.ko -TO_REMOVE+=/boot/kernel/runfw.ko -TO_REMOVE+=/boot/kernel/u3g.ko -TO_REMOVE+=/boot/kernel/uaudio.ko -TO_REMOVE+=/boot/kernel/ubser.ko -TO_REMOVE+=/boot/kernel/ucycom.ko -TO_REMOVE+=/boot/kernel/uep.ko -TO_REMOVE+=/boot/kernel/uether.ko -TO_REMOVE+=/boot/kernel/ufoma.ko -TO_REMOVE+=/boot/kernel/uhci.ko -TO_REMOVE+=/boot/kernel/uipaq.ko -TO_REMOVE+=/boot/kernel/umcs.ko -TO_REMOVE+=/boot/kernel/umoscom.ko -TO_REMOVE+=/boot/kernel/urtwn-rtl8192cfwT.ko -TO_REMOVE+=/boot/kernel/urtwn-rtl8192cfwU.ko -TO_REMOVE+=/boot/kernel/usb_quirk.ko -TO_REMOVE+=/boot/kernel/usb_template.ko -TO_REMOVE+=/boot/kernel/usfs.ko -TO_REMOVE+=/boot/kernel/xhci.ko -TO_REMOVE+=/usr/bin/usbhidaction -TO_REMOVE+=/usr/include/bus/u4b/ufm_ioctl.h -TO_REMOVE+=/usr/include/bus/u4b/usb.h -TO_REMOVE+=/usr/include/bus/u4b/usb_bus.h -TO_REMOVE+=/usr/include/bus/u4b/usb_busdma.h -TO_REMOVE+=/usr/include/bus/u4b/usb_cdc.h -TO_REMOVE+=/usr/include/bus/u4b/usb_compat_linux.h -TO_REMOVE+=/usr/include/bus/u4b/usb_controller.h -TO_REMOVE+=/usr/include/bus/u4b/usb_core.h -TO_REMOVE+=/usr/include/bus/u4b/usb_debug.h -TO_REMOVE+=/usr/include/bus/u4b/usb_dev.h -TO_REMOVE+=/usr/include/bus/u4b/usb_device.h -TO_REMOVE+=/usr/include/bus/u4b/usb_dragonfly.h -TO_REMOVE+=/usr/include/bus/u4b/usb_dynamic.h -TO_REMOVE+=/usr/include/bus/u4b/usb_endian.h -TO_REMOVE+=/usr/include/bus/u4b/usb_freebsd.h -TO_REMOVE+=/usr/include/bus/u4b/usb_generic.h -TO_REMOVE+=/usr/include/bus/u4b/usb_hub.h -TO_REMOVE+=/usr/include/bus/u4b/usb_ioctl.h -TO_REMOVE+=/usr/include/bus/u4b/usb_mbuf.h -TO_REMOVE+=/usr/include/bus/u4b/usb_msctest.h -TO_REMOVE+=/usr/include/bus/u4b/usb_pci.h -TO_REMOVE+=/usr/include/bus/u4b/usb_pf.h -TO_REMOVE+=/usr/include/bus/u4b/usb_process.h -TO_REMOVE+=/usr/include/bus/u4b/usb_request.h -TO_REMOVE+=/usr/include/bus/u4b/usb_transfer.h -TO_REMOVE+=/usr/include/bus/u4b/usb_util.h -TO_REMOVE+=/usr/include/bus/u4b/usbdevs_data.h -TO_REMOVE+=/usr/include/bus/u4b/usbdi.h -TO_REMOVE+=/usr/include/bus/u4b/usbdi_util.h -TO_REMOVE+=/usr/include/bus/u4b/usbhid.h -TO_REMOVE+=/usr/include/libusb.h -TO_REMOVE+=/usr/include/libusb20.h -TO_REMOVE+=/usr/include/libusb20_desc.h -TO_REMOVE+=/usr/include/usb.h -TO_REMOVE+=/usr/lib/libusb.a -TO_REMOVE+=/usr/lib/libusb.so -TO_REMOVE+=/usr/lib/libusb.so.2 -TO_REMOVE+=/usr/lib/profile/libusb.a -TO_REMOVE+=/usr/libdata/pkgconfig/libusb-0.1.pc -TO_REMOVE+=/usr/libdata/pkgconfig/libusb-1.0.pc -TO_REMOVE+=/usr/libdata/pkgconfig/libusb-2.0.pc -TO_REMOVE+=/usr/sbin/usbconfig -TO_REMOVE+=/usr/sbin/usbcontrol -TO_REMOVE+=/usr/sbin/usbdump -TO_REMOVE+=/usr/share/examples/libusb20/Makefile -TO_REMOVE+=/usr/share/examples/libusb20/README -TO_REMOVE+=/usr/share/examples/libusb20/bulk.c -TO_REMOVE+=/usr/share/examples/libusb20/control.c -TO_REMOVE+=/usr/share/examples/libusb20/util.c -TO_REMOVE+=/usr/share/examples/libusb20/util.h -TO_REMOVE+=/usr/share/man/cat1/usbhidaction.1.gz -TO_REMOVE+=/usr/share/man/cat3/libusb.3.gz -TO_REMOVE+=/usr/share/man/cat3/libusb20.3.gz -TO_REMOVE+=/usr/share/man/cat3/libusb20_be_add_dev_quirk.3.gz -TO_REMOVE+=/usr/share/man/cat3/libusb20_be_alloc_default.3.gz -TO_REMOVE+=/usr/share/man/cat3/libusb20_be_dequeue_device.3.gz -TO_REMOVE+=/usr/share/man/cat3/libusb20_be_device_foreach.3.gz -TO_REMOVE+=/usr/share/man/cat3/libusb20_be_enqueue_device.3.gz -TO_REMOVE+=/usr/share/man/cat3/libusb20_be_free.3.gz -TO_REMOVE+=/usr/share/man/cat3/libusb20_be_get_dev_quirk.3.gz -TO_REMOVE+=/usr/share/man/cat3/libusb20_be_get_quirk_name.3.gz -TO_REMOVE+=/usr/share/man/cat3/libusb20_be_get_template.3.gz -TO_REMOVE+=/usr/share/man/cat3/libusb20_be_remove_dev_quirk.3.gz -TO_REMOVE+=/usr/share/man/cat3/libusb20_be_set_template.3.gz -TO_REMOVE+=/usr/share/man/cat3/libusb20_desc_foreach.3.gz -TO_REMOVE+=/usr/share/man/cat3/libusb20_dev_alloc.3.gz -TO_REMOVE+=/usr/share/man/cat3/libusb20_dev_alloc_config.3.gz -TO_REMOVE+=/usr/share/man/cat3/libusb20_dev_check_connected.3.gz -TO_REMOVE+=/usr/share/man/cat3/libusb20_dev_close.3.gz -TO_REMOVE+=/usr/share/man/cat3/libusb20_dev_detach_kernel_driver.3.gz -TO_REMOVE+=/usr/share/man/cat3/libusb20_dev_free.3.gz -TO_REMOVE+=/usr/share/man/cat3/libusb20_dev_get_address.3.gz -TO_REMOVE+=/usr/share/man/cat3/libusb20_dev_get_backend_name.3.gz -TO_REMOVE+=/usr/share/man/cat3/libusb20_dev_get_bus_number.3.gz -TO_REMOVE+=/usr/share/man/cat3/libusb20_dev_get_config_index.3.gz -TO_REMOVE+=/usr/share/man/cat3/libusb20_dev_get_debug.3.gz -TO_REMOVE+=/usr/share/man/cat3/libusb20_dev_get_desc.3.gz -TO_REMOVE+=/usr/share/man/cat3/libusb20_dev_get_device_desc.3.gz -TO_REMOVE+=/usr/share/man/cat3/libusb20_dev_get_fd.3.gz -TO_REMOVE+=/usr/share/man/cat3/libusb20_dev_get_iface_desc.3.gz -TO_REMOVE+=/usr/share/man/cat3/libusb20_dev_get_info.3.gz -TO_REMOVE+=/usr/share/man/cat3/libusb20_dev_get_mode.3.gz -TO_REMOVE+=/usr/share/man/cat3/libusb20_dev_get_parent_address.3.gz -TO_REMOVE+=/usr/share/man/cat3/libusb20_dev_get_parent_port.3.gz -TO_REMOVE+=/usr/share/man/cat3/libusb20_dev_get_port_path.3.gz -TO_REMOVE+=/usr/share/man/cat3/libusb20_dev_get_power_mode.3.gz -TO_REMOVE+=/usr/share/man/cat3/libusb20_dev_get_power_usage.3.gz -TO_REMOVE+=/usr/share/man/cat3/libusb20_dev_get_speed.3.gz -TO_REMOVE+=/usr/share/man/cat3/libusb20_dev_kernel_driver_active.3.gz -TO_REMOVE+=/usr/share/man/cat3/libusb20_dev_open.3.gz -TO_REMOVE+=/usr/share/man/cat3/libusb20_dev_process.3.gz -TO_REMOVE+=/usr/share/man/cat3/libusb20_dev_req_string_simple_sync.3.gz -TO_REMOVE+=/usr/share/man/cat3/libusb20_dev_req_string_sync.3.gz -TO_REMOVE+=/usr/share/man/cat3/libusb20_dev_request_sync.3.gz -TO_REMOVE+=/usr/share/man/cat3/libusb20_dev_reset.3.gz -TO_REMOVE+=/usr/share/man/cat3/libusb20_dev_set_alt_index.3.gz -TO_REMOVE+=/usr/share/man/cat3/libusb20_dev_set_config_index.3.gz -TO_REMOVE+=/usr/share/man/cat3/libusb20_dev_set_debug.3.gz -TO_REMOVE+=/usr/share/man/cat3/libusb20_dev_set_power_mode.3.gz -TO_REMOVE+=/usr/share/man/cat3/libusb20_dev_wait_process.3.gz -TO_REMOVE+=/usr/share/man/cat3/libusb20_error_name.3.gz -TO_REMOVE+=/usr/share/man/cat3/libusb20_me_decode.3.gz -TO_REMOVE+=/usr/share/man/cat3/libusb20_me_encode.3.gz -TO_REMOVE+=/usr/share/man/cat3/libusb20_me_get_1.3.gz -TO_REMOVE+=/usr/share/man/cat3/libusb20_me_get_2.3.gz -TO_REMOVE+=/usr/share/man/cat3/libusb20_strerror.3.gz -TO_REMOVE+=/usr/share/man/cat3/libusb20_tr_bulk_intr_sync.3.gz -TO_REMOVE+=/usr/share/man/cat3/libusb20_tr_callback_wrapper.3.gz -TO_REMOVE+=/usr/share/man/cat3/libusb20_tr_clear_stall_sync.3.gz -TO_REMOVE+=/usr/share/man/cat3/libusb20_tr_close.3.gz -TO_REMOVE+=/usr/share/man/cat3/libusb20_tr_drain.3.gz -TO_REMOVE+=/usr/share/man/cat3/libusb20_tr_get_actual_frames.3.gz -TO_REMOVE+=/usr/share/man/cat3/libusb20_tr_get_actual_length.3.gz -TO_REMOVE+=/usr/share/man/cat3/libusb20_tr_get_length.3.gz -TO_REMOVE+=/usr/share/man/cat3/libusb20_tr_get_max_frames.3.gz -TO_REMOVE+=/usr/share/man/cat3/libusb20_tr_get_max_packet_length.3.gz -TO_REMOVE+=/usr/share/man/cat3/libusb20_tr_get_max_total_length.3.gz -TO_REMOVE+=/usr/share/man/cat3/libusb20_tr_get_pointer.3.gz -TO_REMOVE+=/usr/share/man/cat3/libusb20_tr_get_priv_sc0.3.gz -TO_REMOVE+=/usr/share/man/cat3/libusb20_tr_get_priv_sc1.3.gz -TO_REMOVE+=/usr/share/man/cat3/libusb20_tr_get_status.3.gz -TO_REMOVE+=/usr/share/man/cat3/libusb20_tr_get_time_complete.3.gz -TO_REMOVE+=/usr/share/man/cat3/libusb20_tr_open.3.gz -TO_REMOVE+=/usr/share/man/cat3/libusb20_tr_pending.3.gz -TO_REMOVE+=/usr/share/man/cat3/libusb20_tr_set_buffer.3.gz -TO_REMOVE+=/usr/share/man/cat3/libusb20_tr_set_callback.3.gz -TO_REMOVE+=/usr/share/man/cat3/libusb20_tr_set_flags.3.gz -TO_REMOVE+=/usr/share/man/cat3/libusb20_tr_set_length.3.gz -TO_REMOVE+=/usr/share/man/cat3/libusb20_tr_set_priv_sc0.3.gz -TO_REMOVE+=/usr/share/man/cat3/libusb20_tr_set_priv_sc1.3.gz -TO_REMOVE+=/usr/share/man/cat3/libusb20_tr_set_timeout.3.gz -TO_REMOVE+=/usr/share/man/cat3/libusb20_tr_set_total_frames.3.gz -TO_REMOVE+=/usr/share/man/cat3/libusb20_tr_setup_bulk.3.gz -TO_REMOVE+=/usr/share/man/cat3/libusb20_tr_setup_control.3.gz -TO_REMOVE+=/usr/share/man/cat3/libusb20_tr_setup_intr.3.gz -TO_REMOVE+=/usr/share/man/cat3/libusb20_tr_setup_isoc.3.gz -TO_REMOVE+=/usr/share/man/cat3/libusb20_tr_start.3.gz -TO_REMOVE+=/usr/share/man/cat3/libusb20_tr_stop.3.gz -TO_REMOVE+=/usr/share/man/cat3/libusb20_tr_submit.3.gz -TO_REMOVE+=/usr/share/man/cat3/libusb_alloc_transfer.3.gz -TO_REMOVE+=/usr/share/man/cat3/libusb_attach_kernel_driver.3.gz -TO_REMOVE+=/usr/share/man/cat3/libusb_bulk_transfer.3.gz -TO_REMOVE+=/usr/share/man/cat3/libusb_cancel_transfer.3.gz -TO_REMOVE+=/usr/share/man/cat3/libusb_check_connected.3.gz -TO_REMOVE+=/usr/share/man/cat3/libusb_claim_interface.3.gz -TO_REMOVE+=/usr/share/man/cat3/libusb_clear_halt.3.gz -TO_REMOVE+=/usr/share/man/cat3/libusb_close.3.gz -TO_REMOVE+=/usr/share/man/cat3/libusb_control_transfer.3.gz -TO_REMOVE+=/usr/share/man/cat3/libusb_detach_kernel_driver.3.gz -TO_REMOVE+=/usr/share/man/cat3/libusb_detach_kernel_driver_np.3.gz -TO_REMOVE+=/usr/share/man/cat3/libusb_error_name.3.gz -TO_REMOVE+=/usr/share/man/cat3/libusb_event_handler_active.3.gz -TO_REMOVE+=/usr/share/man/cat3/libusb_event_handling_ok.3.gz -TO_REMOVE+=/usr/share/man/cat3/libusb_exit.3.gz -TO_REMOVE+=/usr/share/man/cat3/libusb_free_bos_descriptor.3.gz -TO_REMOVE+=/usr/share/man/cat3/libusb_free_config_descriptor.3.gz -TO_REMOVE+=/usr/share/man/cat3/libusb_free_device_list.3.gz -TO_REMOVE+=/usr/share/man/cat3/libusb_free_ss_endpoint_comp.3.gz -TO_REMOVE+=/usr/share/man/cat3/libusb_free_transfer.3.gz -TO_REMOVE+=/usr/share/man/cat3/libusb_get_active_config_descriptor.3.gz -TO_REMOVE+=/usr/share/man/cat3/libusb_get_bus_number.3.gz -TO_REMOVE+=/usr/share/man/cat3/libusb_get_config_descriptor.3.gz -TO_REMOVE+=/usr/share/man/cat3/libusb_get_config_descriptor_by_value.3.gz -TO_REMOVE+=/usr/share/man/cat3/libusb_get_configuration.3.gz -TO_REMOVE+=/usr/share/man/cat3/libusb_get_device.3.gz -TO_REMOVE+=/usr/share/man/cat3/libusb_get_device_address.3.gz -TO_REMOVE+=/usr/share/man/cat3/libusb_get_device_descriptor.3.gz -TO_REMOVE+=/usr/share/man/cat3/libusb_get_device_list.3.gz -TO_REMOVE+=/usr/share/man/cat3/libusb_get_device_speed.3.gz -TO_REMOVE+=/usr/share/man/cat3/libusb_get_driver.3.gz -TO_REMOVE+=/usr/share/man/cat3/libusb_get_driver_np.3.gz -TO_REMOVE+=/usr/share/man/cat3/libusb_get_max_iso_packet_size.3.gz -TO_REMOVE+=/usr/share/man/cat3/libusb_get_max_packet_size.3.gz -TO_REMOVE+=/usr/share/man/cat3/libusb_get_next_timeout.3.gz -TO_REMOVE+=/usr/share/man/cat3/libusb_get_pollfds.3.gz -TO_REMOVE+=/usr/share/man/cat3/libusb_get_string_descriptor.3.gz -TO_REMOVE+=/usr/share/man/cat3/libusb_get_string_descriptor_ascii.3.gz -TO_REMOVE+=/usr/share/man/cat3/libusb_handle_events.3.gz -TO_REMOVE+=/usr/share/man/cat3/libusb_handle_events_completed.3.gz -TO_REMOVE+=/usr/share/man/cat3/libusb_handle_events_locked.3.gz -TO_REMOVE+=/usr/share/man/cat3/libusb_handle_events_timeout.3.gz -TO_REMOVE+=/usr/share/man/cat3/libusb_handle_events_timeout_completed.3.gz -TO_REMOVE+=/usr/share/man/cat3/libusb_init.3.gz -TO_REMOVE+=/usr/share/man/cat3/libusb_interrupt_transfer.3.gz -TO_REMOVE+=/usr/share/man/cat3/libusb_kernel_driver_active.3.gz -TO_REMOVE+=/usr/share/man/cat3/libusb_lock_event_waiters.3.gz -TO_REMOVE+=/usr/share/man/cat3/libusb_lock_events.3.gz -TO_REMOVE+=/usr/share/man/cat3/libusb_open.3.gz -TO_REMOVE+=/usr/share/man/cat3/libusb_open_device_with_vid_pid.3.gz -TO_REMOVE+=/usr/share/man/cat3/libusb_parse_bos_descriptor.3.gz -TO_REMOVE+=/usr/share/man/cat3/libusb_parse_ss_endpoint_comp.3.gz -TO_REMOVE+=/usr/share/man/cat3/libusb_ref_device.3.gz -TO_REMOVE+=/usr/share/man/cat3/libusb_release_interface.3.gz -TO_REMOVE+=/usr/share/man/cat3/libusb_reset_device.3.gz -TO_REMOVE+=/usr/share/man/cat3/libusb_set_configuration.3.gz -TO_REMOVE+=/usr/share/man/cat3/libusb_set_debug.3.gz -TO_REMOVE+=/usr/share/man/cat3/libusb_set_interface_alt_setting.3.gz -TO_REMOVE+=/usr/share/man/cat3/libusb_set_pollfd_notifiers.3.gz -TO_REMOVE+=/usr/share/man/cat3/libusb_strerror.3.gz -TO_REMOVE+=/usr/share/man/cat3/libusb_submit_transfer.3.gz -TO_REMOVE+=/usr/share/man/cat3/libusb_try_lock_events.3.gz -TO_REMOVE+=/usr/share/man/cat3/libusb_unlock_event_waiters.3.gz -TO_REMOVE+=/usr/share/man/cat3/libusb_unlock_events.3.gz -TO_REMOVE+=/usr/share/man/cat3/libusb_unref_device.3.gz -TO_REMOVE+=/usr/share/man/cat3/libusb_wait_for_event.3.gz -TO_REMOVE+=/usr/share/man/cat3/usb.3.gz -TO_REMOVE+=/usr/share/man/cat3/usb_bulk_read.3.gz -TO_REMOVE+=/usr/share/man/cat3/usb_bulk_write.3.gz -TO_REMOVE+=/usr/share/man/cat3/usb_check_connected.3.gz -TO_REMOVE+=/usr/share/man/cat3/usb_claim_interface.3.gz -TO_REMOVE+=/usr/share/man/cat3/usb_clear_halt.3.gz -TO_REMOVE+=/usr/share/man/cat3/usb_close.3.gz -TO_REMOVE+=/usr/share/man/cat3/usb_control_msg.3.gz -TO_REMOVE+=/usr/share/man/cat3/usb_destroy_configuration.3.gz -TO_REMOVE+=/usr/share/man/cat3/usb_device.3.gz -TO_REMOVE+=/usr/share/man/cat3/usb_fetch_and_parse_descriptors.3.gz -TO_REMOVE+=/usr/share/man/cat3/usb_find_busses.3.gz -TO_REMOVE+=/usr/share/man/cat3/usb_find_devices.3.gz -TO_REMOVE+=/usr/share/man/cat3/usb_get_busses.3.gz -TO_REMOVE+=/usr/share/man/cat3/usb_get_descriptor.3.gz -TO_REMOVE+=/usr/share/man/cat3/usb_get_descriptor_by_endpoint.3.gz -TO_REMOVE+=/usr/share/man/cat3/usb_get_string.3.gz -TO_REMOVE+=/usr/share/man/cat3/usb_get_string_simple.3.gz -TO_REMOVE+=/usr/share/man/cat3/usb_init.3.gz -TO_REMOVE+=/usr/share/man/cat3/usb_interrupt_read.3.gz -TO_REMOVE+=/usr/share/man/cat3/usb_interrupt_write.3.gz -TO_REMOVE+=/usr/share/man/cat3/usb_open.3.gz -TO_REMOVE+=/usr/share/man/cat3/usb_parse_configuration.3.gz -TO_REMOVE+=/usr/share/man/cat3/usb_parse_descriptor.3.gz -TO_REMOVE+=/usr/share/man/cat3/usb_release_interface.3.gz -TO_REMOVE+=/usr/share/man/cat3/usb_reset.3.gz -TO_REMOVE+=/usr/share/man/cat3/usb_resetep.3.gz -TO_REMOVE+=/usr/share/man/cat3/usb_set_altinterface.3.gz -TO_REMOVE+=/usr/share/man/cat3/usb_set_configuration.3.gz -TO_REMOVE+=/usr/share/man/cat3/usb_set_debug.3.gz -TO_REMOVE+=/usr/share/man/cat3/usb_strerror.3.gz -TO_REMOVE+=/usr/share/man/cat4/if_ipheth.4.gz -TO_REMOVE+=/usr/share/man/cat4/if_mos.4.gz -TO_REMOVE+=/usr/share/man/cat4/if_rum.4.gz -TO_REMOVE+=/usr/share/man/cat4/if_run.4.gz -TO_REMOVE+=/usr/share/man/cat4/if_udav.4.gz -TO_REMOVE+=/usr/share/man/cat4/if_urndis.4.gz -TO_REMOVE+=/usr/share/man/cat4/if_urtwn.4.gz -TO_REMOVE+=/usr/share/man/cat4/ipheth.4.gz -TO_REMOVE+=/usr/share/man/cat4/mos.4.gz -TO_REMOVE+=/usr/share/man/cat4/rum.4.gz -TO_REMOVE+=/usr/share/man/cat4/run.4.gz -TO_REMOVE+=/usr/share/man/cat4/runfw.4.gz -TO_REMOVE+=/usr/share/man/cat4/u3g.4.gz -TO_REMOVE+=/usr/share/man/cat4/ubser.4.gz -TO_REMOVE+=/usr/share/man/cat4/ucycom.4.gz -TO_REMOVE+=/usr/share/man/cat4/udav.4.gz -TO_REMOVE+=/usr/share/man/cat4/uep.4.gz -TO_REMOVE+=/usr/share/man/cat4/ufoma.4.gz -TO_REMOVE+=/usr/share/man/cat4/uipaq.4.gz -TO_REMOVE+=/usr/share/man/cat4/umcs.4.gz -TO_REMOVE+=/usr/share/man/cat4/umoscom.4.gz -TO_REMOVE+=/usr/share/man/cat4/urndis.4.gz -TO_REMOVE+=/usr/share/man/cat4/urtwn.4.gz -TO_REMOVE+=/usr/share/man/cat4/urtwnfw.4.gz -TO_REMOVE+=/usr/share/man/cat4/usb_quirk.4.gz -TO_REMOVE+=/usr/share/man/cat4/usb_template.4.gz -TO_REMOVE+=/usr/share/man/cat4/usfs.4.gz -TO_REMOVE+=/usr/share/man/cat4/xhci.4.gz -TO_REMOVE+=/usr/share/man/cat8/usbconfig.8.gz -TO_REMOVE+=/usr/share/man/cat8/usbcontrol.8.gz -TO_REMOVE+=/usr/share/man/cat8/usbdump.8.gz -TO_REMOVE+=/usr/share/man/man1/usbhidaction.1.gz -TO_REMOVE+=/usr/share/man/man3/libusb.3.gz -TO_REMOVE+=/usr/share/man/man3/libusb20.3.gz -TO_REMOVE+=/usr/share/man/man3/libusb20_be_add_dev_quirk.3.gz -TO_REMOVE+=/usr/share/man/man3/libusb20_be_alloc_default.3.gz -TO_REMOVE+=/usr/share/man/man3/libusb20_be_dequeue_device.3.gz -TO_REMOVE+=/usr/share/man/man3/libusb20_be_device_foreach.3.gz -TO_REMOVE+=/usr/share/man/man3/libusb20_be_enqueue_device.3.gz -TO_REMOVE+=/usr/share/man/man3/libusb20_be_free.3.gz -TO_REMOVE+=/usr/share/man/man3/libusb20_be_get_dev_quirk.3.gz -TO_REMOVE+=/usr/share/man/man3/libusb20_be_get_quirk_name.3.gz -TO_REMOVE+=/usr/share/man/man3/libusb20_be_get_template.3.gz -TO_REMOVE+=/usr/share/man/man3/libusb20_be_remove_dev_quirk.3.gz -TO_REMOVE+=/usr/share/man/man3/libusb20_be_set_template.3.gz -TO_REMOVE+=/usr/share/man/man3/libusb20_desc_foreach.3.gz -TO_REMOVE+=/usr/share/man/man3/libusb20_dev_alloc.3.gz -TO_REMOVE+=/usr/share/man/man3/libusb20_dev_alloc_config.3.gz -TO_REMOVE+=/usr/share/man/man3/libusb20_dev_check_connected.3.gz -TO_REMOVE+=/usr/share/man/man3/libusb20_dev_close.3.gz -TO_REMOVE+=/usr/share/man/man3/libusb20_dev_detach_kernel_driver.3.gz -TO_REMOVE+=/usr/share/man/man3/libusb20_dev_free.3.gz -TO_REMOVE+=/usr/share/man/man3/libusb20_dev_get_address.3.gz -TO_REMOVE+=/usr/share/man/man3/libusb20_dev_get_backend_name.3.gz -TO_REMOVE+=/usr/share/man/man3/libusb20_dev_get_bus_number.3.gz -TO_REMOVE+=/usr/share/man/man3/libusb20_dev_get_config_index.3.gz -TO_REMOVE+=/usr/share/man/man3/libusb20_dev_get_debug.3.gz -TO_REMOVE+=/usr/share/man/man3/libusb20_dev_get_desc.3.gz -TO_REMOVE+=/usr/share/man/man3/libusb20_dev_get_device_desc.3.gz -TO_REMOVE+=/usr/share/man/man3/libusb20_dev_get_fd.3.gz -TO_REMOVE+=/usr/share/man/man3/libusb20_dev_get_iface_desc.3.gz -TO_REMOVE+=/usr/share/man/man3/libusb20_dev_get_info.3.gz -TO_REMOVE+=/usr/share/man/man3/libusb20_dev_get_mode.3.gz -TO_REMOVE+=/usr/share/man/man3/libusb20_dev_get_parent_address.3.gz -TO_REMOVE+=/usr/share/man/man3/libusb20_dev_get_parent_port.3.gz -TO_REMOVE+=/usr/share/man/man3/libusb20_dev_get_port_path.3.gz -TO_REMOVE+=/usr/share/man/man3/libusb20_dev_get_power_mode.3.gz -TO_REMOVE+=/usr/share/man/man3/libusb20_dev_get_power_usage.3.gz -TO_REMOVE+=/usr/share/man/man3/libusb20_dev_get_speed.3.gz -TO_REMOVE+=/usr/share/man/man3/libusb20_dev_kernel_driver_active.3.gz -TO_REMOVE+=/usr/share/man/man3/libusb20_dev_open.3.gz -TO_REMOVE+=/usr/share/man/man3/libusb20_dev_process.3.gz -TO_REMOVE+=/usr/share/man/man3/libusb20_dev_req_string_simple_sync.3.gz -TO_REMOVE+=/usr/share/man/man3/libusb20_dev_req_string_sync.3.gz -TO_REMOVE+=/usr/share/man/man3/libusb20_dev_request_sync.3.gz -TO_REMOVE+=/usr/share/man/man3/libusb20_dev_reset.3.gz -TO_REMOVE+=/usr/share/man/man3/libusb20_dev_set_alt_index.3.gz -TO_REMOVE+=/usr/share/man/man3/libusb20_dev_set_config_index.3.gz -TO_REMOVE+=/usr/share/man/man3/libusb20_dev_set_debug.3.gz -TO_REMOVE+=/usr/share/man/man3/libusb20_dev_set_power_mode.3.gz -TO_REMOVE+=/usr/share/man/man3/libusb20_dev_wait_process.3.gz -TO_REMOVE+=/usr/share/man/man3/libusb20_error_name.3.gz -TO_REMOVE+=/usr/share/man/man3/libusb20_me_decode.3.gz -TO_REMOVE+=/usr/share/man/man3/libusb20_me_encode.3.gz -TO_REMOVE+=/usr/share/man/man3/libusb20_me_get_1.3.gz -TO_REMOVE+=/usr/share/man/man3/libusb20_me_get_2.3.gz -TO_REMOVE+=/usr/share/man/man3/libusb20_strerror.3.gz -TO_REMOVE+=/usr/share/man/man3/libusb20_tr_bulk_intr_sync.3.gz -TO_REMOVE+=/usr/share/man/man3/libusb20_tr_callback_wrapper.3.gz -TO_REMOVE+=/usr/share/man/man3/libusb20_tr_clear_stall_sync.3.gz -TO_REMOVE+=/usr/share/man/man3/libusb20_tr_close.3.gz -TO_REMOVE+=/usr/share/man/man3/libusb20_tr_drain.3.gz -TO_REMOVE+=/usr/share/man/man3/libusb20_tr_get_actual_frames.3.gz -TO_REMOVE+=/usr/share/man/man3/libusb20_tr_get_actual_length.3.gz -TO_REMOVE+=/usr/share/man/man3/libusb20_tr_get_length.3.gz -TO_REMOVE+=/usr/share/man/man3/libusb20_tr_get_max_frames.3.gz -TO_REMOVE+=/usr/share/man/man3/libusb20_tr_get_max_packet_length.3.gz -TO_REMOVE+=/usr/share/man/man3/libusb20_tr_get_max_total_length.3.gz -TO_REMOVE+=/usr/share/man/man3/libusb20_tr_get_pointer.3.gz -TO_REMOVE+=/usr/share/man/man3/libusb20_tr_get_priv_sc0.3.gz -TO_REMOVE+=/usr/share/man/man3/libusb20_tr_get_priv_sc1.3.gz -TO_REMOVE+=/usr/share/man/man3/libusb20_tr_get_status.3.gz -TO_REMOVE+=/usr/share/man/man3/libusb20_tr_get_time_complete.3.gz -TO_REMOVE+=/usr/share/man/man3/libusb20_tr_open.3.gz -TO_REMOVE+=/usr/share/man/man3/libusb20_tr_pending.3.gz -TO_REMOVE+=/usr/share/man/man3/libusb20_tr_set_buffer.3.gz -TO_REMOVE+=/usr/share/man/man3/libusb20_tr_set_callback.3.gz -TO_REMOVE+=/usr/share/man/man3/libusb20_tr_set_flags.3.gz -TO_REMOVE+=/usr/share/man/man3/libusb20_tr_set_length.3.gz -TO_REMOVE+=/usr/share/man/man3/libusb20_tr_set_priv_sc0.3.gz -TO_REMOVE+=/usr/share/man/man3/libusb20_tr_set_priv_sc1.3.gz -TO_REMOVE+=/usr/share/man/man3/libusb20_tr_set_timeout.3.gz -TO_REMOVE+=/usr/share/man/man3/libusb20_tr_set_total_frames.3.gz -TO_REMOVE+=/usr/share/man/man3/libusb20_tr_setup_bulk.3.gz -TO_REMOVE+=/usr/share/man/man3/libusb20_tr_setup_control.3.gz -TO_REMOVE+=/usr/share/man/man3/libusb20_tr_setup_intr.3.gz -TO_REMOVE+=/usr/share/man/man3/libusb20_tr_setup_isoc.3.gz -TO_REMOVE+=/usr/share/man/man3/libusb20_tr_start.3.gz -TO_REMOVE+=/usr/share/man/man3/libusb20_tr_stop.3.gz -TO_REMOVE+=/usr/share/man/man3/libusb20_tr_submit.3.gz -TO_REMOVE+=/usr/share/man/man3/libusb_alloc_transfer.3.gz -TO_REMOVE+=/usr/share/man/man3/libusb_attach_kernel_driver.3.gz -TO_REMOVE+=/usr/share/man/man3/libusb_bulk_transfer.3.gz -TO_REMOVE+=/usr/share/man/man3/libusb_cancel_transfer.3.gz -TO_REMOVE+=/usr/share/man/man3/libusb_check_connected.3.gz -TO_REMOVE+=/usr/share/man/man3/libusb_claim_interface.3.gz -TO_REMOVE+=/usr/share/man/man3/libusb_clear_halt.3.gz -TO_REMOVE+=/usr/share/man/man3/libusb_close.3.gz -TO_REMOVE+=/usr/share/man/man3/libusb_control_transfer.3.gz -TO_REMOVE+=/usr/share/man/man3/libusb_detach_kernel_driver.3.gz -TO_REMOVE+=/usr/share/man/man3/libusb_detach_kernel_driver_np.3.gz -TO_REMOVE+=/usr/share/man/man3/libusb_error_name.3.gz -TO_REMOVE+=/usr/share/man/man3/libusb_event_handler_active.3.gz -TO_REMOVE+=/usr/share/man/man3/libusb_event_handling_ok.3.gz -TO_REMOVE+=/usr/share/man/man3/libusb_exit.3.gz -TO_REMOVE+=/usr/share/man/man3/libusb_free_bos_descriptor.3.gz -TO_REMOVE+=/usr/share/man/man3/libusb_free_config_descriptor.3.gz -TO_REMOVE+=/usr/share/man/man3/libusb_free_device_list.3.gz -TO_REMOVE+=/usr/share/man/man3/libusb_free_ss_endpoint_comp.3.gz -TO_REMOVE+=/usr/share/man/man3/libusb_free_transfer.3.gz -TO_REMOVE+=/usr/share/man/man3/libusb_get_active_config_descriptor.3.gz -TO_REMOVE+=/usr/share/man/man3/libusb_get_bus_number.3.gz -TO_REMOVE+=/usr/share/man/man3/libusb_get_config_descriptor.3.gz -TO_REMOVE+=/usr/share/man/man3/libusb_get_config_descriptor_by_value.3.gz -TO_REMOVE+=/usr/share/man/man3/libusb_get_configuration.3.gz -TO_REMOVE+=/usr/share/man/man3/libusb_get_device.3.gz -TO_REMOVE+=/usr/share/man/man3/libusb_get_device_address.3.gz -TO_REMOVE+=/usr/share/man/man3/libusb_get_device_descriptor.3.gz -TO_REMOVE+=/usr/share/man/man3/libusb_get_device_list.3.gz -TO_REMOVE+=/usr/share/man/man3/libusb_get_device_speed.3.gz -TO_REMOVE+=/usr/share/man/man3/libusb_get_driver.3.gz -TO_REMOVE+=/usr/share/man/man3/libusb_get_driver_np.3.gz -TO_REMOVE+=/usr/share/man/man3/libusb_get_max_iso_packet_size.3.gz -TO_REMOVE+=/usr/share/man/man3/libusb_get_max_packet_size.3.gz -TO_REMOVE+=/usr/share/man/man3/libusb_get_next_timeout.3.gz -TO_REMOVE+=/usr/share/man/man3/libusb_get_pollfds.3.gz -TO_REMOVE+=/usr/share/man/man3/libusb_get_string_descriptor.3.gz -TO_REMOVE+=/usr/share/man/man3/libusb_get_string_descriptor_ascii.3.gz -TO_REMOVE+=/usr/share/man/man3/libusb_handle_events.3.gz -TO_REMOVE+=/usr/share/man/man3/libusb_handle_events_completed.3.gz -TO_REMOVE+=/usr/share/man/man3/libusb_handle_events_locked.3.gz -TO_REMOVE+=/usr/share/man/man3/libusb_handle_events_timeout.3.gz -TO_REMOVE+=/usr/share/man/man3/libusb_handle_events_timeout_completed.3.gz -TO_REMOVE+=/usr/share/man/man3/libusb_init.3.gz -TO_REMOVE+=/usr/share/man/man3/libusb_interrupt_transfer.3.gz -TO_REMOVE+=/usr/share/man/man3/libusb_kernel_driver_active.3.gz -TO_REMOVE+=/usr/share/man/man3/libusb_lock_event_waiters.3.gz -TO_REMOVE+=/usr/share/man/man3/libusb_lock_events.3.gz -TO_REMOVE+=/usr/share/man/man3/libusb_open.3.gz -TO_REMOVE+=/usr/share/man/man3/libusb_open_device_with_vid_pid.3.gz -TO_REMOVE+=/usr/share/man/man3/libusb_parse_bos_descriptor.3.gz -TO_REMOVE+=/usr/share/man/man3/libusb_parse_ss_endpoint_comp.3.gz -TO_REMOVE+=/usr/share/man/man3/libusb_ref_device.3.gz -TO_REMOVE+=/usr/share/man/man3/libusb_release_interface.3.gz -TO_REMOVE+=/usr/share/man/man3/libusb_reset_device.3.gz -TO_REMOVE+=/usr/share/man/man3/libusb_set_configuration.3.gz -TO_REMOVE+=/usr/share/man/man3/libusb_set_debug.3.gz -TO_REMOVE+=/usr/share/man/man3/libusb_set_interface_alt_setting.3.gz -TO_REMOVE+=/usr/share/man/man3/libusb_set_pollfd_notifiers.3.gz -TO_REMOVE+=/usr/share/man/man3/libusb_strerror.3.gz -TO_REMOVE+=/usr/share/man/man3/libusb_submit_transfer.3.gz -TO_REMOVE+=/usr/share/man/man3/libusb_try_lock_events.3.gz -TO_REMOVE+=/usr/share/man/man3/libusb_unlock_event_waiters.3.gz -TO_REMOVE+=/usr/share/man/man3/libusb_unlock_events.3.gz -TO_REMOVE+=/usr/share/man/man3/libusb_unref_device.3.gz -TO_REMOVE+=/usr/share/man/man3/libusb_wait_for_event.3.gz -TO_REMOVE+=/usr/share/man/man3/usb.3.gz -TO_REMOVE+=/usr/share/man/man3/usb_bulk_read.3.gz -TO_REMOVE+=/usr/share/man/man3/usb_bulk_write.3.gz -TO_REMOVE+=/usr/share/man/man3/usb_check_connected.3.gz -TO_REMOVE+=/usr/share/man/man3/usb_claim_interface.3.gz -TO_REMOVE+=/usr/share/man/man3/usb_clear_halt.3.gz -TO_REMOVE+=/usr/share/man/man3/usb_close.3.gz -TO_REMOVE+=/usr/share/man/man3/usb_control_msg.3.gz -TO_REMOVE+=/usr/share/man/man3/usb_destroy_configuration.3.gz -TO_REMOVE+=/usr/share/man/man3/usb_device.3.gz -TO_REMOVE+=/usr/share/man/man3/usb_fetch_and_parse_descriptors.3.gz -TO_REMOVE+=/usr/share/man/man3/usb_find_busses.3.gz -TO_REMOVE+=/usr/share/man/man3/usb_find_devices.3.gz -TO_REMOVE+=/usr/share/man/man3/usb_get_busses.3.gz -TO_REMOVE+=/usr/share/man/man3/usb_get_descriptor.3.gz -TO_REMOVE+=/usr/share/man/man3/usb_get_descriptor_by_endpoint.3.gz -TO_REMOVE+=/usr/share/man/man3/usb_get_string.3.gz -TO_REMOVE+=/usr/share/man/man3/usb_get_string_simple.3.gz -TO_REMOVE+=/usr/share/man/man3/usb_init.3.gz -TO_REMOVE+=/usr/share/man/man3/usb_interrupt_read.3.gz -TO_REMOVE+=/usr/share/man/man3/usb_interrupt_write.3.gz -TO_REMOVE+=/usr/share/man/man3/usb_open.3.gz -TO_REMOVE+=/usr/share/man/man3/usb_parse_configuration.3.gz -TO_REMOVE+=/usr/share/man/man3/usb_parse_descriptor.3.gz -TO_REMOVE+=/usr/share/man/man3/usb_release_interface.3.gz -TO_REMOVE+=/usr/share/man/man3/usb_reset.3.gz -TO_REMOVE+=/usr/share/man/man3/usb_resetep.3.gz -TO_REMOVE+=/usr/share/man/man3/usb_set_altinterface.3.gz -TO_REMOVE+=/usr/share/man/man3/usb_set_configuration.3.gz -TO_REMOVE+=/usr/share/man/man3/usb_set_debug.3.gz -TO_REMOVE+=/usr/share/man/man3/usb_strerror.3.gz -TO_REMOVE+=/usr/share/man/man4/if_ipheth.4.gz -TO_REMOVE+=/usr/share/man/man4/if_mos.4.gz -TO_REMOVE+=/usr/share/man/man4/if_rum.4.gz -TO_REMOVE+=/usr/share/man/man4/if_run.4.gz -TO_REMOVE+=/usr/share/man/man4/if_udav.4.gz -TO_REMOVE+=/usr/share/man/man4/if_urndis.4.gz -TO_REMOVE+=/usr/share/man/man4/if_urtwn.4.gz -TO_REMOVE+=/usr/share/man/man4/ipheth.4.gz -TO_REMOVE+=/usr/share/man/man4/mos.4.gz -TO_REMOVE+=/usr/share/man/man4/rum.4.gz -TO_REMOVE+=/usr/share/man/man4/run.4.gz -TO_REMOVE+=/usr/share/man/man4/runfw.4.gz -TO_REMOVE+=/usr/share/man/man4/u3g.4.gz -TO_REMOVE+=/usr/share/man/man4/ubser.4.gz -TO_REMOVE+=/usr/share/man/man4/ucycom.4.gz -TO_REMOVE+=/usr/share/man/man4/udav.4.gz -TO_REMOVE+=/usr/share/man/man4/uep.4.gz -TO_REMOVE+=/usr/share/man/man4/ufoma.4.gz -TO_REMOVE+=/usr/share/man/man4/uipaq.4.gz -TO_REMOVE+=/usr/share/man/man4/umcs.4.gz -TO_REMOVE+=/usr/share/man/man4/umoscom.4.gz -TO_REMOVE+=/usr/share/man/man4/urndis.4.gz -TO_REMOVE+=/usr/share/man/man4/urtwn.4.gz -TO_REMOVE+=/usr/share/man/man4/urtwnfw.4.gz -TO_REMOVE+=/usr/share/man/man4/usb_quirk.4.gz -TO_REMOVE+=/usr/share/man/man4/usb_template.4.gz -TO_REMOVE+=/usr/share/man/man4/usfs.4.gz -TO_REMOVE+=/usr/share/man/man4/xhci.4.gz -TO_REMOVE+=/usr/share/man/man8/usbconfig.8.gz -TO_REMOVE+=/usr/share/man/man8/usbcontrol.8.gz -TO_REMOVE+=/usr/share/man/man8/usbdump.8.gz -.endif diff --git a/UPDATING b/UPDATING index cb797efc01..afc6e53b7d 100644 --- a/UPDATING +++ b/UPDATING @@ -8,11 +8,34 @@ # If you discover any problem, please contact the bugs@lists.dragonflybsd.org # mailing list with the details. ++-----------------------------------------------------------------------+ ++ UPGRADING DRAGONFLY FROM 4.0 TO LATER VERSIONS + ++-----------------------------------------------------------------------+ + +OLD USB DRIVERS REMOVED +----------------------- + +The old USB stack, along with the kernel config option "device oldusb" +and the make.conf variable "WANT_OLDUSB" have been removed. This means +that for custom kernel configuration files which were derived from a +GENERIC or X86_64_GENERIC file prior to making the usb4bsd stack default, +various (old USB stack specific) devices will now complain about being +unknown: + + * oldusb (obviously) + * natausb (not yet ported to usb4bsd) + * rue (not yet ported to usb4bsd) + * ugen (no longer needed in usb4bsd) + * urio (not yet ported to usb4bsd) + * uscanner (no longer needed in usb4bsd) + +They should be removed or commented out in such custom kernel configs. + +-----------------------------------------------------------------------+ + UPGRADING DRAGONFLY FROM 3.8 TO LATER VERSIONS + +-----------------------------------------------------------------------+ -SMP and DEVICE_POLLING OPTIONS MADE UNKNOWN +SMP AND DEVICE_POLLING OPTIONS MADE UNKNOWN ------------------------------------------- DEVICE_POLLING was replaced by IFPOLL_ENABLE and the former SMP code is diff --git a/etc/Makefile b/etc/Makefile index 73d5f96134..a86b12194d 100644 --- a/etc/Makefile +++ b/etc/Makefile @@ -32,7 +32,7 @@ BIN1= amd.map auth.conf \ motd modems netconfig networks newsyslog.conf \ nscd.conf pf.conf phones printcap profile \ regdomain.xml remote sensorsd.conf services \ - shells sysctl.conf syslog.conf usbd.conf \ + shells sysctl.conf syslog.conf \ hostapd.conf wpa_supplicant.conf \ etc.${MACHINE_ARCH}/ttys .if defined(BINARY_UPGRADE) # location of these depends on upgrade method diff --git a/etc/defaults/rc.conf b/etc/defaults/rc.conf index 07be09bad0..bdb4831303 100644 --- a/etc/defaults/rc.conf +++ b/etc/defaults/rc.conf @@ -351,8 +351,6 @@ lpd_enable="NO" # Run the line printer daemon. lpd_program="/usr/sbin/lpd" # path to lpd, if you want a different one. lpd_flags="" # Flags to lpd (if enabled). nscd_enable="NO" # Run the nsswitch caching daemon. -usbd_enable="NO" # Run the usbd daemon. -usbd_flags="" # Flags to usbd (if enabled). devd_enable="YES" # Run devd, to trigger programs on device tree changes. devd_flags="" # Additional flags for devd(8). dumpdev="NO" # Device name to crashdump to (or NO). diff --git a/etc/mtree/BSD.include.dist b/etc/mtree/BSD.include.dist index 46778ce197..b0ed47abda 100644 --- a/etc/mtree/BSD.include.dist +++ b/etc/mtree/BSD.include.dist @@ -22,8 +22,6 @@ .. smbus .. - usb - .. u4b .. .. diff --git a/etc/rc.d/Makefile b/etc/rc.d/Makefile index 1949d878b2..8d4d6e1b80 100644 --- a/etc/rc.d/Makefile +++ b/etc/rc.d/Makefile @@ -21,7 +21,7 @@ FILES= DAEMON LOGIN NETWORKING SERVERS abi accounting addswap adjkerntz \ quota random rarpd rcconf resident rndcontrol root route6d routed \ routing rpcbind rtadvd rtsold rwho sysdb savecore sdpd securelevel \ sendmail sensorsd serial sppp sshd statd swap1 syscons sysctl syslogd sysvipcd \ - timed ttys udevd udevd_early usbd \ + timed ttys udevd udevd_early \ varsym vfs_quota vinum virecover vkernel vknetd \ watchdogd wpa_supplicant \ ypbind yppasswdd ypserv ypset ypupdated ypxfrd diff --git a/etc/rc.d/syscons b/etc/rc.d/syscons index 7eaac66b61..64cdf65e84 100644 --- a/etc/rc.d/syscons +++ b/etc/rc.d/syscons @@ -28,7 +28,7 @@ # # PROVIDE: syscons -# REQUIRE: LOGIN usbd +# REQUIRE: LOGIN . /etc/rc.subr diff --git a/etc/rc.d/usbd b/etc/rc.d/usbd deleted file mode 100644 index 81d2619f93..0000000000 --- a/etc/rc.d/usbd +++ /dev/null @@ -1,21 +0,0 @@ -#!/bin/sh -# -# $FreeBSD: src/etc/rc.d/usbd,v 1.1 2002/06/13 22:14:36 gordon Exp $ -# - -# PROVIDE: usbd -# REQUIRE: DAEMON -# BEFORE: LOGIN - -. /etc/rc.subr - -name="usbd" -rcvar=`set_rcvar` -command="/usr/sbin/${name}" - -load_rc_config $name -if [ -x $command -a -c /dev/usb ]; then - run_rc_command "$1" -else - dummy_rc_command "$1" -fi diff --git a/etc/usbd.conf b/etc/usbd.conf deleted file mode 100644 index 064d95006d..0000000000 --- a/etc/usbd.conf +++ /dev/null @@ -1,54 +0,0 @@ -# Configuration file the USB daemon. -# -# See usbd.conf(5) for the description of the format of the file. -# -# $FreeBSD: src/etc/usbd.conf,v 1.5.2.3 2002/11/04 08:05:44 dougb Exp $ -# $DragonFly: src/etc/usbd.conf,v 1.3 2005/06/17 23:10:11 swildner Exp $ - -# Firmware download into the ActiveWire board. After the firmware download is -# done the device detaches and reappears as something new and shiny automatically. -# -device "ActiveWire board, firmware download" - vendor 0x0854 - product 0x0100 - release 0x0000 - attach "/usr/local/bin/ezdownload -f /usr/local/share/usb/firmware/0854.0100.0_01.hex ${DEVNAME}" - -# Firmware download for Entrega Serial DB25 adapter. -# -device "Entrega Serial with UART" - product 0x8001 - vendor 0x1645 - release 0x0101 - attach "if ! kldstat -n usio > /dev/null 2>&1 ; then kldload usio; fi" - attach "/usr/sbin/ezdownload -v -f /usr/share/usb/firmware/1645.8001.0101 /dev/${DEVNAME}" - -# The entry below starts and stops dhclient when an ethernet device is inserted -# Caveat: It does not support multiple interfaces. -# -device "USB ethernet" - devname "[ack]ue[0-9]+" - attach "/etc/pccard_ether ${DEVNAME} start" - detach "/etc/pccard_ether ${DEVNAME} stop" - -# This entry starts the ColdSync tool in daemon mode. Make sure you have an up -# to date /usr/local/etc/palms. We override the 'listen' settings for port and -# type in /usr/local/etc/coldsync.conf. -device "Handspring Visor" - devname "ugen[0-9]+" - vendor 0x082d - product 0x0100 - release 0x0100 - attach "/usr/local/bin/coldsync -md -p /dev/${DEVNAME} -t usb" - -# The entry below starts moused when a mouse is plugged in. Moused -# stops automatically (actually it bombs :) when the device disappears. -# -device "Mouse" - devname "ums[0-9]+" - attach "/usr/sbin/moused -p /dev/${DEVNAME} -I /var/run/moused.${DEVNAME}.pid ; /usr/sbin/vidcontrol -m on" - -# The fallthrough entry: Nothing is specified, nothing is done. And it isn't -# necessary at all :-). Just for pretty printing in debugging mode. -# -device "USB device" diff --git a/include/Makefile b/include/Makefile index 7f067c0a9d..7a8b6f4c9e 100644 --- a/include/Makefile +++ b/include/Makefile @@ -56,7 +56,7 @@ LDIRS= net netbt netgraph netgraph7 netinet netinet6 sys vm # LSUBDIRS= \ bus/cam bus/cam/scsi \ - bus/cam bus/pccard bus/pci bus/isa bus/ppbus bus/smbus \ + bus/cam bus/pccard bus/pci bus/isa bus/ppbus bus/smbus bus/u4b \ dev/disk/dm \ dev/disk/mpt/mpilib \ dev/misc/lpt dev/misc/ppi dev/misc/putter \ @@ -92,12 +92,6 @@ LSUBDIRS= \ vfs/msdosfs vfs/nfs vfs/ntfs \ vfs/smbfs vfs/udf vfs/ufs vfs/hammer vfs/hammer2 -.if !defined(WANT_OLDUSB) -LSUBDIRS+= bus/u4b -.else -LSUBDIRS+= bus/usb -.endif - # For SHARED=symlinks, bus/cam is a symlink, so cam/scsi is taken care of LSYMSUBDIRS= ${LSUBDIRS:Nbus/cam/scsi:Nnet/*:Nnetgraph/*:Nnetgraph7/*} diff --git a/lib/Makefile b/lib/Makefile index a3f9d043a6..c1eb6499d8 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -84,8 +84,8 @@ SUBDIR= ${SUBDIR_ORDERED} \ libstand \ libtcplay \ libtelnet \ - ${_libusb} \ - ${_libusbhid} \ + libusb \ + libu4bhid \ libvgl \ libwrap \ liby \ @@ -114,11 +114,4 @@ _libnetgraph= libnetgraph7 _libnetgraph= libnetgraph .endif -.if !defined(WANT_OLDUSB) -_libusb= libusb -_libusbhid= libu4bhid -.else -_libusbhid= libusbhid -.endif - .include diff --git a/lib/libusbhid/Makefile b/lib/libusbhid/Makefile deleted file mode 100644 index 7438c64aa4..0000000000 --- a/lib/libusbhid/Makefile +++ /dev/null @@ -1,25 +0,0 @@ -# $NetBSD: Makefile,v 1.5 1999/07/23 09:44:38 mrg Exp $ -# $FreeBSD: src/lib/libusbhid/Makefile,v 1.6 2002/03/28 18:44:24 joe Exp $ - -LIB= usbhid -MAN= usbhid.3 - -SHLIB_MAJOR= 2 - -MLINKS= usbhid.3 libusbhid.3 usbhid.3 hid_get_report_desc.3 \ - usbhid.3 hid_dispose_report_desc.3 \ - usbhid.3 hid_start_parse.3 usbhid.3 hid_end_parse.3 \ - usbhid.3 hid_get_item.3 usbhid.3 hid_report_size.3 \ - usbhid.3 hid_locate.3 \ - usbhid.3 hid_usage_page.3 usbhid.3 hid_usage_in_page.3 \ - usbhid.3 hid_parse_usage_page.3 usbhid.3 hid_parse_usage_in_page.3 \ - usbhid.3 hid_init.3 \ - usbhid.3 hid_get_data.3 usbhid.3 hid_set_data.3 \ - usbhid.3 hid_use_report_desc.3 - -SRCS= descr.c parse.c usage.c data.c - -INCS= usbhid.h - -.include - diff --git a/lib/libusbhid/data.c b/lib/libusbhid/data.c deleted file mode 100644 index b685673d72..0000000000 --- a/lib/libusbhid/data.c +++ /dev/null @@ -1,94 +0,0 @@ -/* $NetBSD: data.c,v 1.8 2000/04/02 11:10:53 augustss Exp $ */ - -/* - * Copyright (c) 1999 Lennart Augustsson - * 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: src/lib/libusbhid/data.c,v 1.6 2003/04/09 01:52:48 mdodd Exp $ - * $DragonFly: src/lib/libusbhid/data.c,v 1.3 2008/11/24 17:15:17 hasso Exp $ - */ - -#include -#include -#include "usbhid.h" - -int -hid_get_data(const void *p, const hid_item_t *h) -{ - const unsigned char *buf; - unsigned int hpos; - unsigned int hsize; - int data; - int i, end, offs; - - buf = p; - hpos = h->pos; /* bit position of data */ - hsize = h->report_size; /* bit length of data */ - - if (hsize == 0) - return (0); - offs = hpos / 8; - end = (hpos + hsize) / 8 - offs; - data = 0; - for (i = 0; i <= end; i++) - data |= buf[offs + i] << (i*8); - data >>= hpos % 8; - data &= (1 << hsize) - 1; - if (h->logical_minimum < 0) { - /* Need to sign extend */ - hsize = sizeof data * 8 - hsize; - data = (data << hsize) >> hsize; - } - return (data); -} - -void -hid_set_data(void *p, const hid_item_t *h, int data) -{ - unsigned char *buf; - unsigned int hpos; - unsigned int hsize; - int i, end, offs, mask; - - buf = p; - hpos = h->pos; /* bit position of data */ - hsize = h->report_size; /* bit length of data */ - - if (hsize != 32) { - mask = (1 << hsize) - 1; - data &= mask; - } else - mask = ~0; - - data <<= (hpos % 8); - mask <<= (hpos % 8); - mask = ~mask; - - offs = hpos / 8; - end = (hpos + hsize) / 8 - offs; - - for (i = 0; i <= end; i++) - buf[offs + i] = (buf[offs + i] & (mask >> (i*8))) | - ((data >> (i*8)) & 0xff); -} diff --git a/lib/libusbhid/descr.c b/lib/libusbhid/descr.c deleted file mode 100644 index b1968c2ddb..0000000000 --- a/lib/libusbhid/descr.c +++ /dev/null @@ -1,79 +0,0 @@ -/* $NetBSD: descr.c,v 1.9 2000/09/24 02:13:24 augustss Exp $ */ - -/* - * Copyright (c) 1999 Lennart Augustsson - * 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: src/lib/libusbhid/descr.c,v 1.8 2003/04/09 01:52:48 mdodd Exp $ - * $DragonFly: src/lib/libusbhid/descr.c,v 1.5 2008/11/24 17:15:17 hasso Exp $ - */ - -#include - -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "usbhid.h" -#include "usbvar.h" - -report_desc_t -hid_get_report_desc(int fd) -{ - struct usb_ctl_report_desc rep; - - rep.ucrd_size = 0; - if (ioctl(fd, USB_GET_REPORT_DESC, &rep) < 0) - return (NULL); - - return hid_use_report_desc(rep.ucrd_data, (unsigned int)rep.ucrd_size); -} - -report_desc_t -hid_use_report_desc(unsigned char *data, unsigned int size) -{ - report_desc_t r; - - r = malloc(sizeof(*r) + size); - if (r == 0) { - errno = ENOMEM; - return (NULL); - } - r->size = size; - memcpy(r->data, data, size); - return (r); -} - -void -hid_dispose_report_desc(report_desc_t r) -{ - - free(r); -} diff --git a/lib/libusbhid/parse.c b/lib/libusbhid/parse.c deleted file mode 100644 index 5f4564cb41..0000000000 --- a/lib/libusbhid/parse.c +++ /dev/null @@ -1,440 +0,0 @@ -/* $NetBSD: parse.c,v 1.11 2000/09/24 02:19:54 augustss Exp $ */ - -/* - * Copyright (c) 1999, 2001 Lennart Augustsson - * 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: src/lib/libusbhid/parse.c,v 1.10 2004/02/11 21:09:13 emax Exp $ - * $DragonFly: src/lib/libusbhid/parse.c,v 1.4 2008/11/24 17:15:17 hasso Exp $ - */ - -#include -#include -#include -#include - -#include -#include - -#include "usbhid.h" -#include "usbvar.h" - -#define MAXUSAGE 100 -struct hid_data { - u_char *start; - u_char *end; - u_char *p; - hid_item_t cur; - unsigned int usages[MAXUSAGE]; - int nusage; - int minset; - int logminsize; - int multi; - int multimax; - int kindset; - int reportid; - - /* - * The start of collection item has no report ID set, so save - * it until we know the ID. - */ - hid_item_t savedcoll; - u_char hassavedcoll; - /* - * Absolute data position (bits) for input/output/feature. - * Assumes that hid_input, hid_output and hid_feature have - * values 0, 1 and 2. - */ - unsigned int kindpos[3]; -}; - -static int min(int x, int y) { return x < y ? x : y; } - -static int hid_get_item_raw(hid_data_t s, hid_item_t *h); - -static void -hid_clear_local(hid_item_t *c) -{ - c->usage = 0; - c->usage_minimum = 0; - c->usage_maximum = 0; - c->designator_index = 0; - c->designator_minimum = 0; - c->designator_maximum = 0; - c->string_index = 0; - c->string_minimum = 0; - c->string_maximum = 0; - c->set_delimiter = 0; -} - -hid_data_t -hid_start_parse(report_desc_t d, int kindset, int id) -{ - struct hid_data *s; - - s = malloc(sizeof *s); - memset(s, 0, sizeof *s); - s->start = s->p = d->data; - s->end = d->data + d->size; - s->kindset = kindset; - s->reportid = id; - s->hassavedcoll = 0; - return (s); -} - -void -hid_end_parse(hid_data_t s) -{ - while (s->cur.next) { - hid_item_t *hi = s->cur.next->next; - free(s->cur.next); - s->cur.next = hi; - } - free(s); -} - -int -hid_get_item(hid_data_t s, hid_item_t *h) -{ - int r; - - for (;;) { - r = hid_get_item_raw(s, h); - if (r <= 0) - break; - if (h->report_ID == s->reportid || s->reportid == -1) - break; - } - return (r); -} - -#define REPORT_SAVED_COLL \ - do { \ - if (s->hassavedcoll) { \ - *h = s->savedcoll; \ - h->report_ID = c->report_ID; \ - s->hassavedcoll = 0; \ - return (1); \ - } \ - } while(/*LINTED*/ 0) - -static int -hid_get_item_raw(hid_data_t s, hid_item_t *h) -{ - hid_item_t *c; - unsigned int bTag = 0, bType = 0, bSize; - unsigned char *data; - int dval; - unsigned char *p; - hid_item_t *hi; - hid_item_t nc; - int i; - hid_kind_t retkind; - - c = &s->cur; - - top: - if (s->multimax) { - REPORT_SAVED_COLL; - if (c->logical_minimum >= c->logical_maximum) { - if (s->logminsize == 1) - c->logical_minimum =(int8_t)c->logical_minimum; - else if (s->logminsize == 2) - c->logical_minimum =(int16_t)c->logical_minimum; - } - if (s->multi < s->multimax) { - c->usage = s->usages[min(s->multi, s->nusage-1)]; - s->multi++; - *h = *c; - /* - * 'multimax' is only non-zero if the current - * item kind is input/output/feature - */ - h->pos = s->kindpos[c->kind]; - s->kindpos[c->kind] += c->report_size; - h->next = 0; - return (1); - } else { - c->report_count = s->multimax; - s->multimax = 0; - s->nusage = 0; - hid_clear_local(c); - } - } - for (;;) { - p = s->p; - if (p >= s->end) - return (0); - - bSize = *p++; - if (bSize == 0xfe) { - /* long item */ - bSize = *p++; - bSize |= *p++ << 8; - bTag = *p++; - data = p; - p += bSize; - } else { - /* short item */ - bTag = bSize >> 4; - bType = (bSize >> 2) & 3; - bSize &= 3; - if (bSize == 3) bSize = 4; - data = p; - p += bSize; - } - s->p = p; - /* - * The spec is unclear if the data is signed or unsigned. - */ - switch(bSize) { - case 0: - dval = 0; - break; - case 1: - dval = *data++; - break; - case 2: - dval = *data++; - dval |= *data++ << 8; - break; - case 4: - dval = *data++; - dval |= *data++ << 8; - dval |= *data++ << 16; - dval |= *data++ << 24; - break; - default: - return (-1); - } - - switch (bType) { - case 0: /* Main */ - switch (bTag) { - case 8: /* Input */ - retkind = hid_input; - ret: - if (!(s->kindset & (1 << retkind))) { - /* Drop the items of this kind */ - s->nusage = 0; - continue; - } - c->kind = retkind; - c->flags = dval; - if (c->flags & HIO_VARIABLE) { - s->multimax = c->report_count; - s->multi = 0; - c->report_count = 1; - if (s->minset) { - for (i = c->usage_minimum; - i <= c->usage_maximum; - i++) { - s->usages[s->nusage] = i; - if (s->nusage < MAXUSAGE-1) - s->nusage++; - } - c->usage_minimum = 0; - c->usage_maximum = 0; - s->minset = 0; - } - goto top; - } else { - if (s->minset) - c->usage = c->usage_minimum; - *h = *c; - h->next = 0; - h->pos = s->kindpos[c->kind]; - s->kindpos[c->kind] += - c->report_size * c->report_count; - hid_clear_local(c); - s->minset = 0; - return (1); - } - case 9: /* Output */ - retkind = hid_output; - goto ret; - case 10: /* Collection */ - c->kind = hid_collection; - c->collection = dval; - c->collevel++; - nc = *c; - hid_clear_local(c); - /*c->report_ID = NO_REPORT_ID;*/ - s->nusage = 0; - if (s->hassavedcoll) { - *h = s->savedcoll; - h->report_ID = nc.report_ID; - s->savedcoll = nc; - return (1); - } else { - s->hassavedcoll = 1; - s->savedcoll = nc; - } - break; - case 11: /* Feature */ - retkind = hid_feature; - goto ret; - case 12: /* End collection */ - REPORT_SAVED_COLL; - c->kind = hid_endcollection; - c->collevel--; - *h = *c; - /*hid_clear_local(c);*/ - s->nusage = 0; - return (1); - default: - return (-2); - } - break; - - case 1: /* Global */ - switch (bTag) { - case 0: - c->_usage_page = dval << 16; - break; - case 1: - c->logical_minimum = dval; - s->logminsize = bSize; - break; - case 2: - c->logical_maximum = dval; - break; - case 3: - c->physical_maximum = dval; - break; - case 4: - c->physical_maximum = dval; - break; - case 5: - c->unit_exponent = dval; - break; - case 6: - c->unit = dval; - break; - case 7: - c->report_size = dval; - break; - case 8: - c->report_ID = dval; - s->kindpos[hid_input] = - s->kindpos[hid_output] = - s->kindpos[hid_feature] = 0; - break; - case 9: - c->report_count = dval; - break; - case 10: /* Push */ - hi = malloc(sizeof *hi); - *hi = s->cur; - c->next = hi; - break; - case 11: /* Pop */ - hi = c->next; - s->cur = *hi; - free(hi); - break; - default: - return (-3); - } - break; - case 2: /* Local */ - switch (bTag) { - case 0: - c->usage = c->_usage_page | dval; - if (s->nusage < MAXUSAGE) - s->usages[s->nusage++] = c->usage; - /* else XXX */ - break; - case 1: - s->minset = 1; - c->usage_minimum = c->_usage_page | dval; - break; - case 2: - c->usage_maximum = c->_usage_page | dval; - break; - case 3: - c->designator_index = dval; - break; - case 4: - c->designator_minimum = dval; - break; - case 5: - c->designator_maximum = dval; - break; - case 7: - c->string_index = dval; - break; - case 8: - c->string_minimum = dval; - break; - case 9: - c->string_maximum = dval; - break; - case 10: - c->set_delimiter = dval; - break; - default: - return (-4); - } - break; - default: - return (-5); - } - } -} - -int -hid_report_size(report_desc_t r, enum hid_kind k, int id) -{ - struct hid_data *d; - hid_item_t h; - int size; - - memset(&h, 0, sizeof h); - size = 0; - for (d = hid_start_parse(r, 1<kindpos[k]; - } - } - hid_end_parse(d); - return ((size + 7) / 8); -} - -int -hid_locate(report_desc_t desc, unsigned int u, enum hid_kind k, - hid_item_t *h, int id) -{ - hid_data_t d; - - for (d = hid_start_parse(desc, 1<kind == k && !(h->flags & HIO_CONST) && h->usage == u) { - hid_end_parse(d); - return (1); - } - } - hid_end_parse(d); - h->report_size = 0; - return (0); -} diff --git a/lib/libusbhid/usage.c b/lib/libusbhid/usage.c deleted file mode 100644 index de25076ce9..0000000000 --- a/lib/libusbhid/usage.c +++ /dev/null @@ -1,237 +0,0 @@ -/* $NetBSD: usage.c,v 1.8 2000/10/10 19:23:58 is Exp $ */ - -/* - * Copyright (c) 1999 Lennart Augustsson - * 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: src/lib/libusbhid/usage.c,v 1.8 2003/04/09 01:52:48 mdodd Exp $ - */ - -#include -#include -#include -#include -#include -#include - -#include "usbhid.h" - -#define _PATH_HIDTABLE "/usr/share/misc/usb_hid_usages" - -struct usage_in_page { - const char *name; - int usage; -}; - -static struct usage_page { - const char *name; - int usage; - struct usage_in_page *page_contents; - int pagesize, pagesizemax; -} *pages; -static int npages, npagesmax; - -#ifdef DEBUG -void -dump_hid_table(void) -{ - int i, j; - - for (i = 0; i < npages; i++) { - printf("%d\t%s\n", pages[i].usage, pages[i].name); - for (j = 0; j < pages[i].pagesize; j++) { - printf("\t%d\t%s\n", pages[i].page_contents[j].usage, - pages[i].page_contents[j].name); - } - } -} -#endif - -void -hid_init(const char *hidname) -{ - FILE *f; - char line[100], name[100], *p, *n; - int no; - int lineno; - struct usage_page *curpage = NULL; - - if (hidname == NULL) - hidname = _PATH_HIDTABLE; - - f = fopen(hidname, "r"); - if (f == NULL) - err(1, "%s", hidname); - for (lineno = 1; ; lineno++) { - if (fgets(line, sizeof line, f) == NULL) - break; - if (line[0] == '#') - continue; - for (p = line; *p && isspace(*p); p++) - ; - if (!*p) - continue; - if (sscanf(line, " * %[^\n]", name) == 1) - no = -1; - else if (sscanf(line, " 0x%x %[^\n]", &no, name) != 2 && - sscanf(line, " %d %[^\n]", &no, name) != 2) - errx(1, "file %s, line %d, syntax error", - hidname, lineno); - for (p = name; *p; p++) - if (isspace(*p) || *p == '.') - *p = '_'; - n = strdup(name); - if (!n) - err(1, "strdup"); - if (isspace(line[0])) { - if (!curpage) - errx(1, "file %s, line %d, syntax error", - hidname, lineno); - if (curpage->pagesize >= curpage->pagesizemax) { - curpage->pagesizemax += 10; - curpage->page_contents = - realloc(curpage->page_contents, - curpage->pagesizemax * - sizeof (struct usage_in_page)); - if (!curpage->page_contents) - err(1, "realloc"); - } - curpage->page_contents[curpage->pagesize].name = n; - curpage->page_contents[curpage->pagesize].usage = no; - curpage->pagesize++; - } else { - if (npages >= npagesmax) { - if (pages == NULL) { - npagesmax = 5; - pages = malloc(npagesmax * - sizeof (struct usage_page)); - } else { - npagesmax += 5; - pages = realloc(pages, - npagesmax * - sizeof (struct usage_page)); - } - if (!pages) - err(1, "alloc"); - } - curpage = &pages[npages++]; - curpage->name = n; - curpage->usage = no; - curpage->pagesize = 0; - curpage->pagesizemax = 10; - curpage->page_contents = - malloc(curpage->pagesizemax * - sizeof (struct usage_in_page)); - if (!curpage->page_contents) - err(1, "malloc"); - } - } - fclose(f); -#ifdef DEBUG - dump_hid_table(); -#endif -} - -const char * -hid_usage_page(int i) -{ - static char b[10]; - int k; - - if (!pages) - errx(1, "no hid table"); - - for (k = 0; k < npages; k++) - if (pages[k].usage == i) - return pages[k].name; - sprintf(b, "0x%04x", i); - return b; -} - -const char * -hid_usage_in_page(unsigned int u) -{ - int page = HID_PAGE(u); - int i = HID_USAGE(u); - static char b[100]; - int j, k, us; - - for (k = 0; k < npages; k++) - if (pages[k].usage == page) - break; - if (k >= npages) - goto bad; - for (j = 0; j < pages[k].pagesize; j++) { - us = pages[k].page_contents[j].usage; - if (us == -1) { - sprintf(b, - fmtcheck(pages[k].page_contents[j].name, "%d"), - i); - return b; - } - if (us == i) - return pages[k].page_contents[j].name; - } - bad: - sprintf(b, "0x%04x", i); - return b; -} - -int -hid_parse_usage_page(const char *name) -{ - int k; - - if (!pages) - errx(1, "no hid table"); - - for (k = 0; k < npages; k++) - if (strcmp(pages[k].name, name) == 0) - return pages[k].usage; - return -1; -} - -/* XXX handle hex */ -int -hid_parse_usage_in_page(const char *name) -{ - const char *sep; - int k, j; - unsigned int l; - - sep = strchr(name, ':'); - if (sep == NULL) - return -1; - l = sep - name; - for (k = 0; k < npages; k++) - if (strncmp(pages[k].name, name, l) == 0) - goto found; - return -1; - found: - sep++; - for (j = 0; j < pages[k].pagesize; j++) - if (strcmp(pages[k].page_contents[j].name, sep) == 0) - return (pages[k].usage << 16) | pages[k].page_contents[j].usage; - return (-1); -} diff --git a/lib/libusbhid/usbhid.3 b/lib/libusbhid/usbhid.3 deleted file mode 100644 index 05ab06ec15..0000000000 --- a/lib/libusbhid/usbhid.3 +++ /dev/null @@ -1,225 +0,0 @@ -.\" $NetBSD: usb.3,v 1.13 2000/09/24 02:17:52 augustss Exp $ -.\" -.\" Copyright (c) 1999, 2001 Lennart Augustsson -.\" 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: src/lib/libusbhid/usbhid.3,v 1.18 2005/11/24 11:26:36 ru Exp $ -.\" $DragonFly: src/lib/libusbhid/usbhid.3,v 1.10 2008/11/26 17:17:16 swildner Exp $ -.\" -.Dd November 24, 2008 -.Dt USBHID 3 -.Os -.Sh NAME -.Nm usbhid , -.Nm hid_get_report_desc , -.Nm hid_use_report_desc , -.Nm hid_dispose_report_desc , -.Nm hid_start_parse , -.Nm hid_end_parse , -.Nm hid_get_item , -.Nm hid_report_size , -.Nm hid_locate , -.Nm hid_usage_page , -.Nm hid_usage_in_page , -.Nm hid_parse_usage_page , -.Nm hid_parse_usage_in_page , -.Nm hid_init , -.Nm hid_get_data , -.Nm hid_set_data -.Nd USB HID access routines -.Sh LIBRARY -.Lb libusbhid -.Sh SYNOPSIS -.In usbhid.h -.Ft report_desc_t -.Fn hid_get_report_desc "int file" -.Ft report_desc_t -.Fn hid_use_report_desc "unsigned char *data" "unsigned int size" -.Ft void -.Fn hid_dispose_report_desc "report_desc_t d" -.Ft hid_data_t -.Fn hid_start_parse "report_desc_t d" "int kindset" "int id" -.Ft void -.Fn hid_end_parse "hid_data_t s" -.Ft int -.Fn hid_get_item "hid_data_t s" "hid_item_t *h" -.Ft int -.Fn hid_report_size "report_desc_t d" "hid_kind_t k" "int id" -.Ft int -.Fn hid_locate "report_desc_t d" "unsigned int usage" "hid_kind_t k" "hid_item_t *h" "int id" -.Ft "const char *" -.Fn hid_usage_page "int i" -.Ft "const char *" -.Fn hid_usage_in_page "unsigned int u" -.Ft int -.Fn hid_parse_usage_page "const char *" -.Ft int -.Fn hid_parse_usage_in_page "const char *" -.Ft void -.Fn hid_init "const char *file" -.Ft int -.Fn hid_get_data "const void *data" "const hid_item_t *h" -.Ft void -.Fn hid_set_data "void *buf" "const hid_item_t *h" "int data" -.Sh DESCRIPTION -The -.Nm -library provides routines to extract data from USB Human Interface Devices. -.Ss Introduction -USB HID devices send and receive data laid out in a device dependent way. -The -.Nm -library contains routines to extract the -.Em "report descriptor" -which contains the data layout information and then use this information. -.Pp -The routines can be divided into four parts: extraction of the descriptor, -parsing of the descriptor, translating to/from symbolic names, and -data manipulation. -.Ss Descriptor Functions -A report descriptor can be obtained by calling -.Fn hid_get_report_desc -with a file descriptor obtained by opening a -.Xr uhid 4 -device. -Alternatively a data buffer containing the report descriptor can be -passed into -.Fn hid_use_report_desc . -The data is copied into an internal structure. -When the report descriptor -is no longer needed it should be freed by calling -.Fn hid_dispose_report_desc . -The type -.Vt report_desc_t -is opaque and should be used when calling the parsing functions. -If -.Fn hid_dispose_report_desc -fails it will return -.Dv NULL . -.Ss Descriptor Parsing Functions -To parse the report descriptor the -.Fn hid_start_parse -function should be called with a report descriptor and a set that -describes which items that are interesting. -The set is obtained by OR-ing together values -.Fa "(1 << k)" -where -.Fa k -is an item of type -.Vt hid_kind_t . -The report ID (if present) is given by -.Fa id . -The function returns -.Dv NULL -if the initialization fails, otherwise an opaque value to be used -in subsequent calls. -After parsing the -.Fn hid_end_parse -function should be called to free internal data structures. -.Pp -To iterate through all the items in the report descriptor -.Fn hid_get_item -should be called while it returns a value greater than 0. -When the report descriptor ends it will returns 0; a syntax -error within the report descriptor will cause a return value less -than 0. -The struct pointed to by -.Fa h -will be filled with the relevant data for the item. -The definition of -.Vt hid_item_t -can be found in -.In usbhid.h -and the meaning of the components in the USB HID documentation. -.Pp -Data should be read/written to the device in the size of -the report. -The size of a report (of a certain kind) can be computed by the -.Fn hid_report_size -function. -If the report is prefixed by an ID byte it is given by -.Fa id . -.Pp -To locate a single item the -.Fn hid_locate -function can be used. -It should be given the usage code of -the item and its kind and it will fill the item and return -non-zero if the item was found. -.Ss Name Translation Functions -The function -.Fn hid_usage_page -will return the symbolic name of a usage page, and the function -.Fn hid_usage_in_page -will return the symbolic name of the usage within the page. -Both these functions may return a pointer to static data. -.Pp -The functions -.Fn hid_parse_usage_page -and -.Fn hid_parse_usage_in_page -are the inverses of -.Fn hid_usage_page -and -.Fn hid_usage_in_page . -They take a usage string and return the number of the usage, or \-1 -if it cannot be found. -.Pp -Before any of these functions can be called the usage table -must be parsed, this is done by calling -.Fn hid_init -with the name of the table. -Passing -.Dv NULL -to this function will cause it to use the default table. -.Ss Data Extraction Functions -Given the data obtained from a HID device and an item in the -report descriptor the -.Fn hid_get_data -function extracts the value of the item. -Conversely -.Fn hid_set_data -can be used to put data into a report (which must be zeroed first). -.Sh FILES -.Bl -tag -width ".Pa /usr/share/misc/usb_hid_usages" -.It Pa /usr/share/misc/usb_hid_usages -The default HID usage table. -.El -.Sh EXAMPLES -Not yet. -.Sh SEE ALSO -The -.Tn USB -specifications can be found at -.Pa http://www.usb.org/developers/docs/ . -.Pp -.Xr uhid 4 , -.Xr usb 4 -.Sh HISTORY -The -.Nm -library first appeared in -.Nx 1.5 . -.Sh BUGS -This man page is woefully incomplete. diff --git a/lib/libusbhid/usbhid.h b/lib/libusbhid/usbhid.h deleted file mode 100644 index f87af45b09..0000000000 --- a/lib/libusbhid/usbhid.h +++ /dev/null @@ -1,109 +0,0 @@ -/* $NetBSD: usb.h,v 1.8 2000/08/13 22:22:02 augustss Exp $ */ - -/* - * Copyright (c) 1999 Lennart Augustsson - * 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: src/lib/libusbhid/usbhid.h,v 1.11 2004/06/03 15:04:24 des Exp $ - * $DragonFly: src/lib/libusbhid/usbhid.h,v 1.1 2008/11/24 17:15:17 hasso Exp $ - */ - -#include - -typedef struct report_desc *report_desc_t; - -typedef struct hid_data *hid_data_t; - -typedef enum hid_kind { - hid_input = 0, - hid_output = 1, - hid_feature = 2, - hid_collection, - hid_endcollection -} hid_kind_t; - -typedef struct hid_item { - /* Global */ - unsigned int _usage_page; - int logical_minimum; - int logical_maximum; - int physical_minimum; - int physical_maximum; - int unit_exponent; - int unit; - int report_size; - int report_ID; -#define NO_REPORT_ID 0 - int report_count; - /* Local */ - unsigned int usage; - int usage_minimum; - int usage_maximum; - int designator_index; - int designator_minimum; - int designator_maximum; - int string_index; - int string_minimum; - int string_maximum; - int set_delimiter; - /* Misc */ - int collection; - int collevel; - enum hid_kind kind; - unsigned int flags; - /* Absolute data position (bits) */ - unsigned int pos; - /* */ - struct hid_item *next; -} hid_item_t; - -#define HID_PAGE(u) (((u) >> 16) & 0xffff) -#define HID_USAGE(u) ((u) & 0xffff) - -__BEGIN_DECLS - -/* Obtaining a report descriptor, descr.c: */ -report_desc_t hid_get_report_desc(int file); -report_desc_t hid_use_report_desc(unsigned char *data, unsigned int size); -void hid_dispose_report_desc(report_desc_t); - -/* Parsing of a HID report descriptor, parse.c: */ -hid_data_t hid_start_parse(report_desc_t d, int kindset, int id); -void hid_end_parse(hid_data_t s); -int hid_get_item(hid_data_t s, hid_item_t *h); -int hid_report_size(report_desc_t d, enum hid_kind k, int id); -int hid_locate(report_desc_t d, unsigned int usage, enum hid_kind k, hid_item_t *h, int id); - -/* Conversion to/from usage names, usage.c: */ -const char *hid_usage_page(int i); -const char *hid_usage_in_page(unsigned int u); -void hid_init(const char *file); -int hid_parse_usage_in_page(const char *name); -int hid_parse_usage_page(const char *name); - -/* Extracting/insertion of data, data.c: */ -int hid_get_data(const void *p, const hid_item_t *h); -void hid_set_data(void *p, const hid_item_t *h, int data); - -__END_DECLS diff --git a/lib/libusbhid/usbvar.h b/lib/libusbhid/usbvar.h deleted file mode 100644 index 2b40b2a521..0000000000 --- a/lib/libusbhid/usbvar.h +++ /dev/null @@ -1,37 +0,0 @@ -/* $NetBSD: usbvar.h,v 1.2 1999/05/11 21:15:46 augustss Exp $ */ - -/* - * Copyright (c) 1999 Lennart Augustsson - * 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: src/lib/libusbhid/usbvar.h,v 1.2.2.1 2002/04/03 15:54:00 joe Exp $ - * $DragonFly: src/lib/libusbhid/usbvar.h,v 1.2 2003/06/17 04:26:51 dillon Exp $ - * - */ - -struct report_desc { - unsigned int size; - unsigned char data[1]; -}; - diff --git a/share/examples/etc/README.examples b/share/examples/etc/README.examples index 8d3efcaf96..74a892e20a 100644 --- a/share/examples/etc/README.examples +++ b/share/examples/etc/README.examples @@ -72,7 +72,6 @@ shells - list of configurable shells sysctl.conf - kernel state defaults syslog.conf - configuration file for syslogd(8) ttys - defines port configuration for init(8) -usbd.conf - configuration file for usbd(8) defaults/ - directory containing default configuration files defaults/compilers.conf - default configuration for non-base compilers defaults/devfs.conf - default rule file for devfs(5) diff --git a/share/man/man4/Makefile b/share/man/man4/Makefile index 621aecb239..a3a56f47e3 100644 --- a/share/man/man4/Makefile +++ b/share/man/man4/Makefile @@ -130,6 +130,7 @@ MAN= aac.4 \ ip.4 \ ip6.4 \ ipfirewall.4 \ + ipheth.4 \ ips.4 \ ipsec.4 \ isa.4 \ @@ -154,7 +155,6 @@ MAN= aac.4 \ lagg.4 \ led.4 \ lge.4 \ - lgue.4 \ lm.4 \ lo.4 \ lp.4 \ @@ -169,6 +169,7 @@ MAN= aac.4 \ mmc.4 \ mmcsd.4 \ mn.4 \ + mos.4 \ moscom.4 \ mouse.4 \ mps.4 \ @@ -252,7 +253,9 @@ MAN= aac.4 \ rndtest.4 \ route.4 \ rp.4 \ - rue.4 \ + rum.4 \ + run.4 \ + runfw.4 \ sa.4 \ safe.4 \ sbp.4 \ @@ -326,12 +329,18 @@ MAN= aac.4 \ uark.4 \ ubsa.4 \ ubsec.4 \ + ubser.4 \ ubt.4 \ uchcom.4 \ + ucycom.4 \ ucom.4 \ + udav.4 \ udp.4 \ + uep.4 \ ufm.4 \ + ufoma.4 \ uftdi.4 \ + uipaq.4 \ ugen.4 \ ugensa.4 \ uguru.4 \ @@ -340,16 +349,25 @@ MAN= aac.4 \ ukbd.4 \ ulpt.4 \ umass.4 \ + umcs.4 \ umct.4 \ umodem.4 \ + umoscom.4 \ ums.4 \ unix.4 \ uplcom.4 \ upmap.4 \ urio.4 \ + urndis.4 \ + urtwn.4 \ + urtwnfw.4 \ usb.4 \ + usb_quirk.4 \ + usb_template.4 \ uscanner.4 \ + usfs.4 \ uslcom.4 \ + u3g.4 \ uticom.4 \ uvisor.4 \ uvscom.4 \ @@ -376,6 +394,7 @@ MAN= aac.4 \ wlan_xauth.4 \ wpi.4 \ xe.4 \ + xhci.4 \ xl.4 \ xpt.4 \ zero.4 @@ -388,7 +407,6 @@ MAN= aac.4 \ # bwi.4 \ # iwl.4 \ # rtw.4 \ -# ural.4 \ MLINKS= acpi_thermal.4 acpi_tz.4 #MLINKS+=acx.4 if_acx.4 @@ -437,6 +455,7 @@ MLINKS+=iicbus.4 ic.4 \ MLINKS+=ipfirewall.4 ipaccounting.4 \ ipfirewall.4 ipacct.4 \ ipfirewall.4 ipfw.4 +MLINKS+=ipheth.4 if_ipheth.4 MLINKS+=iwi.4 if_iwi.4 #MLINKS+=iwl.4 if_iwl.4 MLINKS+=iwn.4 if_iwn.4 @@ -447,10 +466,10 @@ MLINKS+=jme.4 if_jme.4 MLINKS+=kue.4 if_kue.4 MLINKS+=lagg.4 if_lagg.4 MLINKS+=lge.4 if_lge.4 -MLINKS+=lgue.4 if_lgue.4 MLINKS+=lo.4 loop.4 MLINKS+=lp.4 plip.4 MLINKS+=mem.4 kmem.4 +MLINKS+=mos.4 if_mos.4 MLINKS+=msk.4 if_msk.4 MLINKS+=mxge.4 if_mxge.4 MLINKS+=my.4 if_my.4 @@ -472,7 +491,9 @@ MLINKS+=random.4 urandom.4 MLINKS+=re.4 if_re.4 MLINKS+=rl.4 if_rl.4 #MLINKS+=rtw.4 if_rtw.4 -MLINKS+=rue.4 if_rue.4 +#MLINKS+=rue.4 if_rue.4 +MLINKS+=rum.4 if_rum.4 +MLINKS+=run.4 if_run.4 MLINKS+=sbsh.4 if_sbsh.4 MLINKS+=scsi.4 CAM.4 \ scsi.4 cam.4 \ @@ -517,8 +538,11 @@ MLINKS+=ti.4 if_ti.4 MLINKS+=tl.4 if_tl.4 MLINKS+=tun.4 if_tun.4 MLINKS+=txp.4 if_txp.4 +MLINKS+=udav.4 if_udav.4 MLINKS+=upmap.4 kpmap.4 #MLINKS+=ural.4 if_ural.4 +MLINKS+=urndis.4 if_urndis.4 +MLINKS+=urtwn.4 if_urtwn.4 MLINKS+=vga.4 vesa.4 MLINKS+=vge.4 if_vge.4 MLINKS+=vlan.4 if_vlan.4 @@ -531,38 +555,6 @@ MLINKS+=wpi.4 if_wpi.4 MLINKS+=xe.4 if_xe.4 MLINKS+=xl.4 if_xl.4 -.if !defined(WANT_OLDUSB) -MAN+= \ - ipheth.4 \ - mos.4 \ - rum.4 \ - run.4 \ - runfw.4 \ - ubser.4 \ - ucycom.4 \ - udav.4 \ - uep.4 \ - ufoma.4 \ - uipaq.4 \ - umcs.4 \ - umoscom.4 \ - urndis.4 \ - urtwn.4 \ - urtwnfw.4 \ - usb_quirk.4 \ - usb_template.4 \ - usfs.4 \ - u3g.4 \ - xhci.4 -MLINKS+=ipheth.4 if_ipheth.4 -MLINKS+=mos.4 if_mos.4 -MLINKS+=rum.4 if_rum.4 -MLINKS+=run.4 if_run.4 -MLINKS+=udav.4 if_udav.4 -MLINKS+=urndis.4 if_urndis.4 -MLINKS+=urtwn.4 if_urtwn.4 -.endif - .if ${MACHINE_ARCH} == "i386" SUBDIR= man4.${MACHINE_ARCH} .endif diff --git a/share/man/man4/lgue.4 b/share/man/man4/lgue.4 deleted file mode 100644 index 5329324156..0000000000 --- a/share/man/man4/lgue.4 +++ /dev/null @@ -1,62 +0,0 @@ -.\" -.\" Copyright (c) 2011 -.\" The DragonFly Project. 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. -.\" 3. Neither the name of The DragonFly Project nor the names of its -.\" contributors may be used to endorse or promote products derived -.\" from this software without specific, prior written permission. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 -.\" COPYRIGHT HOLDERS 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. -.\" -.Dd July 25, 2011 -.Dt LGUE 4 -.Os -.Sh NAME -.Nm lgue -.Nd USB CDC ethernet -.Sh SYNOPSIS -.Cd "device uhci" -.Cd "device ohci" -.Cd "device oldusb" -.Cd "device lgue" -.Sh DESCRIPTION -The -.Nm -driver provides support for USB CDC (communication device class) ethernet. -It currently supports the -.Tn LG P-500 -smartphone. -.Pp -For more information on configuring this device, see -.Xr ifconfig 8 . -.Sh SEE ALSO -.Xr arp 4 , -.Xr netintro 4 , -.Xr ng_ether 4 , -.Xr ifconfig 8 -.Sh HISTORY -The -.Nm -device driver first appeared in -.Dx 2.11 . diff --git a/share/man/man4/rue.4 b/share/man/man4/rue.4 deleted file mode 100644 index cc5984f924..0000000000 --- a/share/man/man4/rue.4 +++ /dev/null @@ -1,155 +0,0 @@ -.\" -.\" Copyright (c) 2001-2003, Shunsuke Akiyama . -.\" 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: src/share/man/man4/rue.4,v 1.11 2005/10/07 02:32:15 trhodes Exp $ -.\" -.Dd July 16, 2005 -.Dt RUE 4 -.Os -.Sh NAME -.Nm rue -.Nd "RealTek RTL8150 USB to Fast Ethernet controller driver" -.Sh SYNOPSIS -To compile this driver into the kernel, -place the following lines in your -kernel configuration file: -.Bd -ragged -offset indent -.Cd "device uhci" -.Cd "device ohci" -.Cd "device oldusb" -.Cd "device miibus" -.Cd "device rue" -.Ed -.Pp -Alternatively, to load the driver as a -module at boot time, place the following line in -.Xr loader.conf 5 : -.Bd -literal -offset indent -if_rue_load="YES" -.Ed -.Sh DESCRIPTION -The -.Nm -driver provides support for USB Ethernet adapters based on the RealTek -RTL8150 USB to Fast Ethernet controller chip. -.Pp -The RTL8150 contains an integrated Fast Ethernet MAC, which supports -both 10 and 100Mbps speeds in either full or half duplex. -Although designed to interface with -100Mbps peripheral, the existing USB standard specifies a maximum -transfer speed of 12Mbps. -Users should therefore not expect to actually -achieve 100Mbps speeds with this device. -.Pp -The -.Nm -driver supports the following media types: -.Bl -tag -width ".Cm 10baseT/UTP" -.It Cm autoselect -Enable auto selection of the media type and options. -The user can manually override -the auto selected mode by adding media options to the -.Pa /etc/rc.conf -file. -.It Cm 10baseT/UTP -Set 10Mbps operation. -The -.Cm mediaopt -option can also be used to select either -.Cm full-duplex -or -.Cm half-duplex -modes. -.It Cm 100baseTX -Set 100Mbps (Fast Ethernet) operation. -The -.Cm mediaopt -option can also be used to select either -.Cm full-duplex -or -.Cm half-duplex -modes. -.El -.Pp -The -.Nm -driver supports the following media options: -.Bl -tag -width ".Cm 10baseT/UTP" -.It Cm full-duplex -Force full duplex operation. -.It Cm half-duplex -Force half duplex operation. -.El -.Pp -For more information on configuring this device, see -.Xr ifconfig 8 . -.Sh HARDWARE -The -.Nm -driver supports RealTek RTL8150 based USB Ethernet -adapters including: -.Pp -.Bl -bullet -compact -.It -Buffalo (Melco Inc.) LUA-KTX -.It -Green House GH-USB100B -.It -LinkSys USB100M -.It -Billionton 10/100 FastEthernet USBKR2 -.El -.Sh DIAGNOSTICS -.Bl -diag -.It "rue%d: watchdog timeout" -A packet was queued for transmission and a transmit command was -issued, however the device failed to acknowledge the transmission -before a timeout expired. -.It "rue%d: rx list init failed" -The driver failed to allocate an mbuf for the transmitter ring. -.It "rue%d: no memory for rx list" -The driver failed to allocate an mbuf for the receiver ring. -.El -.Sh SEE ALSO -.Xr arp 4 , -.Xr ifmedia 4 , -.Xr miibus 4 , -.Xr netintro 4 , -.Xr ng_ether 4 , -.Xr ifconfig 8 -.Rs -.%T "ReakTek RTL8150 data sheet" -.%O ftp://ftp.realtek.com.tw/lancard/data_sheet/8150/ -.Re -.Sh HISTORY -The -.Nm -device driver first appeared in -.Fx 5.1 . -.Sh AUTHORS -The -.Nm -driver was written by -.An Shunsuke Akiyama Aq Mt akiyama@FreeBSD.org . diff --git a/share/man/man4/snd_uaudio.4 b/share/man/man4/snd_uaudio.4 index 68d0c5a611..51eb764ad9 100644 --- a/share/man/man4/snd_uaudio.4 +++ b/share/man/man4/snd_uaudio.4 @@ -29,7 +29,7 @@ .\" .\" $FreeBSD: head/share/man/man4/snd_uaudio.4 267938 2014-06-26 21:46:14Z bapt $ .\" -.Dd September 2, 2014 +.Dd November 10, 2014 .Dt SND_UAUDIO 4 .Os .Sh NAME @@ -48,7 +48,7 @@ Alternatively, to load the driver as a module at boot time, place the following line in .Xr loader.conf 5 : .Bd -literal -offset indent -snd_uaudio_load="YES" +uaudio_load="YES" .Ed .Sh DESCRIPTION The diff --git a/share/man/man4/ural.4 b/share/man/man4/ural.4 deleted file mode 100644 index 085eaddacd..0000000000 --- a/share/man/man4/ural.4 +++ /dev/null @@ -1,175 +0,0 @@ -.\" Copyright (c) 2005, 2006 -.\" Damien Bergamini -.\" -.\" Permission to use, copy, modify, and distribute this software for any -.\" purpose with or without fee is hereby granted, provided that the above -.\" copyright notice and this permission notice appear in all copies. -.\" -.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -.\" -.\" $FreeBSD: src/share/man/man4/ural.4,v 1.11 2006/10/07 18:18:40 flz Exp $ -.\" -.Dd July 26, 2008 -.Os -.Dt URAL 4 -.Sh NAME -.Nm ural -.Nd "Ralink Technology RT2500USB IEEE 802.11 driver" -.Sh SYNOPSIS -To compile this driver into the kernel, -place the following lines in your -kernel configuration file: -.Bd -ragged -offset indent -.Cd "device ehci" -.Cd "device uhci" -.Cd "device ohci" -.Cd "device oldusb" -.Cd "device ural" -.Cd "device wlan" -.Cd "device wlan_ratectl_onoe" -.Ed -.Pp -Alternatively, to load the driver as a -module at boot time, place the following line in -.Xr loader.conf 5 : -.Bd -literal -offset indent -if_ural_load="YES" -.Ed -.Sh DESCRIPTION -The -.Nm -driver supports USB 2.0 wireless adapters based on the RT2500USB chipset. -.Pp -The RT2500USB chipset consists of two integrated chips, a RT2570 MAC/BBP -and a radio transceiver (the model of which depends on the card revision). -.Pp -The RT2522, RT2523, RT2524, RT2525, RT2525e and RT2526 radio transceivers -operate in the 2.4GHz band (802.11b/g) whereas the RT5222 is a dual-band radio -transceiver that can operate in the 2.4GHz and 5.2GHz bands (802.11a). -.Sh HARDWARE -The -.Nm -driver supports the following adapters: -.Pp -.Bl -bullet -compact -.It -AMIT WL532U -.It -ASUS WL-167g -.It -Belkin F5D7050 v2000 -.It -Buffalo WLI-U2-KG54 -.It -Buffalo WLI-U2-KG54-AI -.It -Buffalo WLI-U2-KG54-YB -.It -CNet CWD-854 -.It -Compex WLU54G 2A1100 -.It -Conceptronic C54RU -.It -D-Link DWL-G122 b1 -.It -Dynalink WLG25USB -.It -E-Tech WGUS02 -.It -Eminent 3035 -.It -Gigabyte GN-WBKG -.It -Hercules HWGUSB2-54 -.It -KCORP LifeStyle KLS-685 -.It -Linksys HU200-TS -.It -Linksys WUSB54G v4 -.It -Linksys WUSB54GP v4 -.It -MSI MS-6861 -.It -MSI MS-6865 -.It -MSI MS-6869 -.It -Nintendo Wi-Fi USB Connector -.It -NovaTech NV-902 -.It -OvisLink Evo-W54USB -.It -SerComm UB801R -.It -SparkLAN WL-685R -.It -Sphairon UB801R -.It -Surecom EP-9001-g -.It -Sweex LC100060 -.It -Tonze UW-6200C -.It -Zaapa ZNWUSB-54 -.It -Zinwell ZPlus-G250 -.It -Zinwell ZWX-G261 -.It -Zonet ZEW2500P -.El -.Pp -An up to date list can be found at -.Pa http://ralink.rapla.net/ . -.Sh EXAMPLES -Refer to the -.Sx EXAMPLES -section of -.Xr wlan 4 . -.Sh DIAGNOSTICS -.Bl -diag -.It "ural%d: device timeout" -The driver will reset the hardware. -This should not happen. -.El -.Sh SEE ALSO -.Xr arp 4 , -.Xr ifmedia 4 , -.Xr netintro 4 , -.Xr usb 4 , -.Xr wlan 4 , -.Xr wlan_ratectl 4 , -.Xr hostapd 8 , -.Xr ifconfig 8 , -.Xr wpa_supplicant 8 -.Rs -.%T "Ralink Technology" -.%O http://www.ralinktech.com/ -.Re -.Sh HISTORY -The -.Nm -driver first appeared in -.Ox 3.7 . -.Sh CAVEATS -The -.Nm -driver supports automatic adaptation of the transmit speed in IBSS -and HostAP operating modes, -but it does not work well if there are more than one peer node. -.Sh AUTHORS -The -.Nm -driver was written by -.An Damien Bergamini Aq Mt damien@FreeBSD.org . diff --git a/share/man/man5/make.conf.5 b/share/man/man5/make.conf.5 index 38ca52d352..e49ea51326 100644 --- a/share/man/man5/make.conf.5 +++ b/share/man/man5/make.conf.5 @@ -596,11 +596,6 @@ userland. It has to be accompanied by .Dv NETGRAPH7* options in the kernel. -.It Va WANT_OLDUSB -.Pq Vt bool -Set to build the old, deprecated -.Xr usb 4 -userland. .El .Pp The following list provides a name and short description for variables diff --git a/share/man/man5/rc.conf.5 b/share/man/man5/rc.conf.5 index 13ec4947ba..50fb9d3947 100644 --- a/share/man/man5/rc.conf.5 +++ b/share/man/man5/rc.conf.5 @@ -2264,22 +2264,6 @@ is set to these are the flags to pass to the .Xr ftpd 8 daemon. -.It Va usbd_enable -.Pq Vt bool -If set to -.Dq Li YES , -run the -.Xr usbd 8 -daemon at boot time. -.It Va usbd_flags -.Pq Vt str -If -.Va usbd_enable -is set to -.Dq Li YES , -these are the flags passed to -.Xr usbd 8 -daemon. .It Va watchdogd_enable .Pq Vt bool If set to @@ -2749,7 +2733,6 @@ if it is not set. .Xr syslogd 8 , .Xr sysvipcd 8 , .Xr timed 8 , -.Xr usbd 8 , .Xr vinum 8 , .Xr yp 8 , .Xr ypbind 8 , diff --git a/sys/bus/Makefile b/sys/bus/Makefile index fdb37e4b5f..3b44fc4319 100644 --- a/sys/bus/Makefile +++ b/sys/bus/Makefile @@ -1,9 +1,3 @@ -SUBDIR= cam firewire iicbus mmc pccard ppbus smbus - -.if !defined(WANT_OLDUSB) -SUBDIR+=u4b -.else -SUBDIR+=usb -.endif +SUBDIR= cam firewire iicbus mmc pccard ppbus smbus u4b .include diff --git a/sys/bus/pci/pci.c b/sys/bus/pci/pci.c index d6e388ffbe..9219e5023f 100644 --- a/sys/bus/pci/pci.c +++ b/sys/bus/pci/pci.c @@ -30,7 +30,6 @@ #include "opt_acpi.h" #include "opt_compat_oldpci.h" -#include "use_oldusb.h" #include #include @@ -60,12 +59,10 @@ #include #include -#if NOLDUSB == 0 #include #include #include #include -#endif #include "pcib_if.h" #include "pci_if.h" @@ -311,12 +308,8 @@ TUNABLE_INT("hw.pci.honor_msi_blacklist", &pci_honor_msi_blacklist); SYSCTL_INT(_hw_pci, OID_AUTO, honor_msi_blacklist, CTLFLAG_RD, &pci_honor_msi_blacklist, 1, "Honor chipset blacklist for MSI"); -#if NOLDUSB == 0 #if defined(__i386__) || defined(__x86_64__) static int pci_usb_takeover = 1; -#else -static int pci_usb_takeover = 0; -#endif TUNABLE_INT("hw.pci.usb_early_takeover", &pci_usb_takeover); SYSCTL_INT(_hw_pci, OID_AUTO, usb_early_takeover, CTLFLAG_RD, &pci_usb_takeover, 1, "Enable early takeover of USB controllers.\n\ @@ -2777,7 +2770,6 @@ pci_assign_interrupt(device_t bus, device_t dev, int force_route) machintr_legacy_intr_cpuid(irq)); } -#if NOLDUSB == 0 /* Perform early OHCI takeover from SMM. */ static void ohci_early_takeover(device_t self) @@ -2970,7 +2962,6 @@ xhci_early_takeover(device_t self) } bus_release_resource(self, SYS_RES_MEMORY, rid, res); } -#endif /* NOLDUSB == 0 */ void pci_add_resources(device_t pcib, device_t bus, device_t dev, int force, uint32_t prefetchmask) @@ -3017,7 +3008,6 @@ pci_add_resources(device_t pcib, device_t bus, device_t dev, int force, uint32_t pci_assign_interrupt(bus, dev, 1); } -#if NOLDUSB == 0 if (pci_usb_takeover && pci_get_class(dev) == PCIC_SERIALBUS && pci_get_subclass(dev) == PCIS_SERIALBUS_USB) { if (pci_get_progif(dev) == PCIP_SERIALBUS_USB_XHCI) @@ -3029,7 +3019,6 @@ pci_add_resources(device_t pcib, device_t bus, device_t dev, int force, uint32_t else if (pci_get_progif(dev) == PCIP_SERIALBUS_USB_UHCI) uhci_early_takeover(dev); } -#endif } void diff --git a/sys/bus/usb/FILES b/sys/bus/usb/FILES deleted file mode 100644 index 6c87d6cb4f..0000000000 --- a/sys/bus/usb/FILES +++ /dev/null @@ -1,58 +0,0 @@ -$FreeBSD: src/sys/dev/usb/FILES,v 1.6 2003/04/14 14:04:07 ticso Exp $ -$DragonFly: src/sys/bus/usb/FILES,v 1.4 2007/11/05 19:09:42 hasso Exp $ - -A small roadmap of the USB files: - -FILES this file -Makefile to install .h files -TODO just a list of things to do -dsbr100io.h API for ufm.c -ehci.c Host controller driver for EHCI -ehcireg.h Hardware definitions for EHCI -ehcivar.h API for ehci.c -files.usb config include file -hid.c subroutines to parse and access HID data -hid.h API for hid.c -if_aue.c USB Pegasus Ethernet driver -if_auereg.h and definitions for it -if_cue.c USB CATC Ethernet driver -if_cuereg.h and definitions for it -if_kue.c USB Kawasaki Ethernet driver -if_kuereg.h and definitions for it -if_upl.c USB Prolofic host-to-host driver -ohci.c Host controller driver for OHCI -ohcireg.h Hardware definitions for OHCI -ohcivar.h API for ohci.c -uaudio.c USB audio class driver -uaudioreg.h and definitions for it -ufm.c USB fm radio driver -[Merged] ugen.c generic driver that can handle access to any USB device -uhci.c Host controller driver for UHCI -uhcireg.h Hardware definitions for UHCI -uhcivar.h API for uhci.c -uhid.c USB HID class driver -uhub.c USB hub driver -ukbd.c USB keyboard driver -ukbdmap.c wscons key mapping for ukbd -ukbdvar.h API for ukbd.c -ulpt.c USB printer class driver -umass.c USB mass storage driver -umodem.c USB modem (CDC ACM) driver -ums.c USB mouse driver -urio.c USB Diamond Rio500 driver -usb.c usb (bus) device driver -usb.h general USB defines -usb_mem.c memory allocation for DMAable memory -usb_mem.h API for usb_mem.c -usb_port.h compatibility defines for different OSs -usb_quirks.c table of non-conforming USB devices and their problems -usb_quirks.h API for usb_quirks.c -usb_subr.c various subroutines used by USB code -usbcdc.h USB CDC class definitions -usbdi.c implementation of the USBDI API, which all drivers use -usbdi.h API for usbdi.c -usbdi_util.c utilities built on top of usbdi.h -usbdi_util.h API for usbdi_util.c -usbdivar.h internal defines and structures for usbdi.c -uscanner.c minimal USB scanner driver -usbhid.h USB HID class definitions diff --git a/sys/bus/usb/Makefile b/sys/bus/usb/Makefile deleted file mode 100644 index 46bead2035..0000000000 --- a/sys/bus/usb/Makefile +++ /dev/null @@ -1,7 +0,0 @@ -# Makefile - module build for usb bus elements -# -# $DragonFly: src/sys/bus/usb/Makefile,v 1.6 2004/03/17 18:12:55 dillon Exp $ - -SUBDIR=usb ehci - -.include diff --git a/sys/bus/usb/dsbr100io.h b/sys/bus/usb/dsbr100io.h deleted file mode 100644 index 39e29d241f..0000000000 --- a/sys/bus/usb/dsbr100io.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (c) 2001 M. Warner Losh - * 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. - * - * This code is based on ugen.c and ulpt.c developed by Lennart Augustsson. - * This code includes software developed by the NetBSD Foundation, Inc. and - * its contributors. - */ - -/* - * $FreeBSD: src/sys/dev/usb/dsbr100io.h,v 1.1 2002/03/04 03:51:19 alfred Exp $ - * $DragonFly: src/sys/bus/usb/dsbr100io.h,v 1.5 2007/06/27 12:27:59 hasso Exp $ - */ - -#include - -#define FM_SET_FREQ _IOWR('U', 200, int) -#define FM_GET_FREQ _IOWR('U', 201, int) -#define FM_START _IOWR('U', 202, int) -#define FM_STOP _IOWR('U', 203, int) -#define FM_GET_STAT _IOWR('U', 204, int) diff --git a/sys/bus/usb/ehci.c b/sys/bus/usb/ehci.c deleted file mode 100644 index 670e0d3916..0000000000 --- a/sys/bus/usb/ehci.c +++ /dev/null @@ -1,3201 +0,0 @@ -/* $NetBSD: ehci.c,v 1.91 2005/02/27 00:27:51 perry Exp $ */ -/* $FreeBSD: src/sys/dev/usb/ehci.c,v 1.36.2.3 2006/09/24 13:39:04 iedowse Exp $ */ - -/* - * Copyright (c) 2004 The NetBSD Foundation, Inc. - * All rights reserved. - * - * This code is derived from software contributed to The NetBSD Foundation - * by Lennart Augustsson (lennart@augustsson.net) and by Charles M. Hannum. - * - * 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. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the NetBSD - * Foundation, Inc. and its contributors. - * 4. Neither the name of The NetBSD Foundation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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. - */ - -/* - * USB Enhanced Host Controller Driver, a.k.a. USB 2.0 controller. - * - * The EHCI 1.0 spec can be found at - * http://developer.intel.com/technology/usb/download/ehci-r10.pdf - * and the USB 2.0 spec at - * http://www.usb.org/developers/docs/usb_20.zip - * - */ - -/* - * TODO: - * 1) The EHCI driver lacks support for isochronous transfers, so - * devices using them don't work. - * - * 2) Interrupt transfer scheduling does not manage the time available - * in each frame, so it is possible for the transfers to overrun - * the end of the frame. - * - * 3) Command failures are not recovered correctly. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include -#include -#include -#include - -#include -#include - -#ifdef USB_DEBUG -#define EHCI_DEBUG USB_DEBUG -#define DPRINTF(x) do { if (ehcidebug) kprintf x; } while (0) -#define DPRINTFN(n,x) do { if (ehcidebug>(n)) kprintf x; } while (0) -int ehcidebug = 0; -SYSCTL_NODE(_hw_usb, OID_AUTO, ehci, CTLFLAG_RW, 0, "USB ehci"); -SYSCTL_INT(_hw_usb_ehci, OID_AUTO, debug, CTLFLAG_RW, - &ehcidebug, 0, "ehci debug level"); -#define bitmask_snprintf(q,f,b,l) ksnprintf((b), (l), "%b", (q), (f)) -#else -#define DPRINTF(x) -#define DPRINTFN(n,x) -#endif - -struct ehci_pipe { - struct usbd_pipe pipe; - - ehci_soft_qh_t *sqh; - union { - ehci_soft_qtd_t *qtd; - /* ehci_soft_itd_t *itd; */ - } tail; - union { - /* Control pipe */ - struct { - usb_dma_t reqdma; - u_int length; - /*ehci_soft_qtd_t *setup, *data, *stat;*/ - } ctl; - /* Interrupt pipe */ - struct { - u_int length; - } intr; - /* Bulk pipe */ - struct { - u_int length; - } bulk; - /* Iso pipe */ - /* XXX */ - } u; -}; - -static usbd_status ehci_open(usbd_pipe_handle); -static void ehci_poll(struct usbd_bus *); -static void ehci_softintr(void *); -static int ehci_intr1(ehci_softc_t *); -static void ehci_waitintr(ehci_softc_t *, usbd_xfer_handle); -static void ehci_check_intr(ehci_softc_t *, struct ehci_xfer *); -static void ehci_idone(struct ehci_xfer *); -static void ehci_timeout(void *); -static void ehci_timeout_task(void *); -static void ehci_intrlist_timeout(void *); - -static usbd_status ehci_allocm(struct usbd_bus *, usb_dma_t *, u_int32_t); -static void ehci_freem(struct usbd_bus *, usb_dma_t *); - -static usbd_xfer_handle ehci_allocx(struct usbd_bus *); -static void ehci_freex(struct usbd_bus *, usbd_xfer_handle); - -static usbd_status ehci_root_ctrl_transfer(usbd_xfer_handle); -static usbd_status ehci_root_ctrl_start(usbd_xfer_handle); -static void ehci_root_ctrl_abort(usbd_xfer_handle); -static void ehci_root_ctrl_close(usbd_pipe_handle); -static void ehci_root_ctrl_done(usbd_xfer_handle); - -static usbd_status ehci_root_intr_transfer(usbd_xfer_handle); -static usbd_status ehci_root_intr_start(usbd_xfer_handle); -static void ehci_root_intr_abort(usbd_xfer_handle); -static void ehci_root_intr_close(usbd_pipe_handle); -static void ehci_root_intr_done(usbd_xfer_handle); - -static usbd_status ehci_device_ctrl_transfer(usbd_xfer_handle); -static usbd_status ehci_device_ctrl_start(usbd_xfer_handle); -static void ehci_device_ctrl_abort(usbd_xfer_handle); -static void ehci_device_ctrl_close(usbd_pipe_handle); -static void ehci_device_ctrl_done(usbd_xfer_handle); - -static usbd_status ehci_device_bulk_transfer(usbd_xfer_handle); -static usbd_status ehci_device_bulk_start(usbd_xfer_handle); -static void ehci_device_bulk_abort(usbd_xfer_handle); -static void ehci_device_bulk_close(usbd_pipe_handle); -static void ehci_device_bulk_done(usbd_xfer_handle); - -static usbd_status ehci_device_intr_transfer(usbd_xfer_handle); -static usbd_status ehci_device_intr_start(usbd_xfer_handle); -static void ehci_device_intr_abort(usbd_xfer_handle); -static void ehci_device_intr_close(usbd_pipe_handle); -static void ehci_device_intr_done(usbd_xfer_handle); - -static usbd_status ehci_device_isoc_transfer(usbd_xfer_handle); -static usbd_status ehci_device_isoc_start(usbd_xfer_handle); -static void ehci_device_isoc_abort(usbd_xfer_handle); -static void ehci_device_isoc_close(usbd_pipe_handle); -static void ehci_device_isoc_done(usbd_xfer_handle); - -static void ehci_device_clear_toggle(usbd_pipe_handle pipe); -static void ehci_noop(usbd_pipe_handle pipe); - -static int ehci_str(usb_string_descriptor_t *, int, char *); -static void ehci_pcd(ehci_softc_t *, usbd_xfer_handle); -static void ehci_disown(ehci_softc_t *, int, int); - -static ehci_soft_qh_t *ehci_alloc_sqh(ehci_softc_t *); -static void ehci_free_sqh(ehci_softc_t *, ehci_soft_qh_t *); - -static ehci_soft_qtd_t *ehci_alloc_sqtd(ehci_softc_t *); -static void ehci_free_sqtd(ehci_softc_t *, ehci_soft_qtd_t *); -static usbd_status ehci_alloc_sqtd_chain(struct ehci_pipe *, - ehci_softc_t *, int, int, usbd_xfer_handle, - ehci_soft_qtd_t **, ehci_soft_qtd_t **); -static void ehci_free_sqtd_chain(ehci_softc_t *, ehci_soft_qtd_t *, - ehci_soft_qtd_t *); - -static usbd_status ehci_device_request(usbd_xfer_handle xfer); - -static usbd_status ehci_device_setintr(ehci_softc_t *, ehci_soft_qh_t *, - int ival); - -static void ehci_add_qh(ehci_soft_qh_t *, ehci_soft_qh_t *); -static void ehci_rem_qh(ehci_softc_t *, ehci_soft_qh_t *, - ehci_soft_qh_t *); -static void ehci_set_qh_qtd(ehci_soft_qh_t *, ehci_soft_qtd_t *); -static void ehci_sync_hc(ehci_softc_t *); - -static void ehci_close_pipe(usbd_pipe_handle, ehci_soft_qh_t *); -static void ehci_abort_xfer(usbd_xfer_handle, usbd_status); - -#ifdef EHCI_DEBUG -static void ehci_dump_regs(ehci_softc_t *); -void ehci_dump(void); -static ehci_softc_t *theehci; -static void ehci_dump_link(ehci_link_t, int); -static void ehci_dump_sqtds(ehci_soft_qtd_t *); -static void ehci_dump_sqtd(ehci_soft_qtd_t *); -static void ehci_dump_qtd(ehci_qtd_t *); -static void ehci_dump_sqh(ehci_soft_qh_t *); -#ifdef DIAGNOSTIC -static void ehci_dump_exfer(struct ehci_xfer *); -#endif -#endif - -#define EHCI_NULL htole32(EHCI_LINK_TERMINATE) - -#define EHCI_INTR_ENDPT 1 - -#define ehci_add_intr_list(sc, ex) \ - LIST_INSERT_HEAD(&(sc)->sc_intrhead, (ex), inext); -#define ehci_del_intr_list(ex) \ - do { \ - LIST_REMOVE((ex), inext); \ - (ex)->inext.le_prev = NULL; \ - } while (0) -#define ehci_active_intr_list(ex) ((ex)->inext.le_prev != NULL) - -static struct usbd_bus_methods ehci_bus_methods = { - ehci_open, - ehci_softintr, - ehci_poll, - ehci_allocm, - ehci_freem, - ehci_allocx, - ehci_freex, -}; - -static struct usbd_pipe_methods ehci_root_ctrl_methods = { - ehci_root_ctrl_transfer, - ehci_root_ctrl_start, - ehci_root_ctrl_abort, - ehci_root_ctrl_close, - ehci_noop, - ehci_root_ctrl_done, -}; - -static struct usbd_pipe_methods ehci_root_intr_methods = { - ehci_root_intr_transfer, - ehci_root_intr_start, - ehci_root_intr_abort, - ehci_root_intr_close, - ehci_noop, - ehci_root_intr_done, -}; - -static struct usbd_pipe_methods ehci_device_ctrl_methods = { - ehci_device_ctrl_transfer, - ehci_device_ctrl_start, - ehci_device_ctrl_abort, - ehci_device_ctrl_close, - ehci_noop, - ehci_device_ctrl_done, -}; - -static struct usbd_pipe_methods ehci_device_intr_methods = { - ehci_device_intr_transfer, - ehci_device_intr_start, - ehci_device_intr_abort, - ehci_device_intr_close, - ehci_device_clear_toggle, - ehci_device_intr_done, -}; - -static struct usbd_pipe_methods ehci_device_bulk_methods = { - ehci_device_bulk_transfer, - ehci_device_bulk_start, - ehci_device_bulk_abort, - ehci_device_bulk_close, - ehci_device_clear_toggle, - ehci_device_bulk_done, -}; - -static struct usbd_pipe_methods ehci_device_isoc_methods = { - ehci_device_isoc_transfer, - ehci_device_isoc_start, - ehci_device_isoc_abort, - ehci_device_isoc_close, - ehci_noop, - ehci_device_isoc_done, -}; - -usbd_status -ehci_init(ehci_softc_t *sc) -{ - u_int32_t vers, sparams, cparams, hcr; - u_int i; - usbd_status err; - ehci_soft_qh_t *sqh; - u_int ncomp; - int lev; - - DPRINTF(("ehci_init: start\n")); -#ifdef EHCI_DEBUG - theehci = sc; -#endif - - sc->sc_offs = EREAD1(sc, EHCI_CAPLENGTH); - - vers = EREAD2(sc, EHCI_HCIVERSION); - device_printf(sc->sc_bus.bdev, - "EHCI version %x.%x\n", vers >> 8, vers & 0xff); - /* Disable all interrupts */ - EOWRITE4(sc, EHCI_USBINTR, 0); - - sparams = EREAD4(sc, EHCI_HCSPARAMS); - DPRINTF(("ehci_init: sparams=0x%x\n", sparams)); - sc->sc_npcomp = EHCI_HCS_N_PCC(sparams); - ncomp = EHCI_HCS_N_CC(sparams); - if (ncomp != sc->sc_ncomp) { - device_printf(sc->sc_bus.bdev, - "wrong number of companions (%d != %d)\n", - ncomp, sc->sc_ncomp); - if (ncomp < sc->sc_ncomp) - sc->sc_ncomp = ncomp; - } - if (sc->sc_ncomp > 0) { - device_printf(sc->sc_bus.bdev, - "companion controller%s, %d port%s each:", - sc->sc_ncomp!=1 ? "s" : "", - EHCI_HCS_N_PCC(sparams), - EHCI_HCS_N_PCC(sparams)!=1 ? "s" : ""); - for (i = 0; i < sc->sc_ncomp; i++) - kprintf(" %s", device_get_nameunit(sc->sc_comps[i]->bdev)); - kprintf("\n"); - } - sc->sc_noport = EHCI_HCS_N_PORTS(sparams); - cparams = EREAD4(sc, EHCI_HCCPARAMS); - DPRINTF(("ehci_init: cparams=0x%x\n", cparams)); - - if (EHCI_HCC_64BIT(cparams)) { - /* MUST clear segment register if 64 bit capable. */ - EWRITE4(sc, EHCI_CTRLDSSEGMENT, 0); - } - - sc->sc_bus.usbrev = USBREV_2_0; - - /* Reset the controller */ - DPRINTF(("%s: resetting\n", device_get_nameunit(sc->sc_bus.bdev))); - EOWRITE4(sc, EHCI_USBCMD, 0); /* Halt controller */ - usb_delay_ms(&sc->sc_bus, 1); - EOWRITE4(sc, EHCI_USBCMD, EHCI_CMD_HCRESET); - for (i = 0; i < 100; i++) { - usb_delay_ms(&sc->sc_bus, 1); - hcr = EOREAD4(sc, EHCI_USBCMD) & EHCI_CMD_HCRESET; - if (!hcr) - break; - } - if (hcr) { - device_printf(sc->sc_bus.bdev, "reset timeout\n"); - return (USBD_IOERROR); - } - - /* frame list size at default, read back what we got and use that */ - switch (EHCI_CMD_FLS(EOREAD4(sc, EHCI_USBCMD))) { - case 0: sc->sc_flsize = 1024; break; - case 1: sc->sc_flsize = 512; break; - case 2: sc->sc_flsize = 256; break; - case 3: return (USBD_IOERROR); - } - err = usb_allocmem(&sc->sc_bus, sc->sc_flsize * sizeof(ehci_link_t), - EHCI_FLALIGN_ALIGN, &sc->sc_fldma); - if (err) - return (err); - DPRINTF(("%s: flsize=%d\n", device_get_nameunit(sc->sc_bus.bdev),sc->sc_flsize)); - sc->sc_flist = KERNADDR(&sc->sc_fldma, 0); - EOWRITE4(sc, EHCI_PERIODICLISTBASE, DMAADDR(&sc->sc_fldma, 0)); - - /* Set up the bus struct. */ - sc->sc_bus.methods = &ehci_bus_methods; - sc->sc_bus.pipe_size = sizeof(struct ehci_pipe); - - sc->sc_eintrs = EHCI_NORMAL_INTRS; - - /* - * Allocate the interrupt dummy QHs. These are arranged to give - * poll intervals that are powers of 2 times 1ms. - */ - for (i = 0; i < EHCI_INTRQHS; i++) { - sqh = ehci_alloc_sqh(sc); - if (sqh == NULL) { - err = USBD_NOMEM; - goto bad1; - } - sc->sc_islots[i].sqh = sqh; - } - lev = 0; - for (i = 0; i < EHCI_INTRQHS; i++) { - if (i == EHCI_IQHIDX(lev + 1, 0)) - lev++; - sqh = sc->sc_islots[i].sqh; - if (i == 0) { - /* The last (1ms) QH terminates. */ - sqh->qh.qh_link = EHCI_NULL; - sqh->next = NULL; - } else { - /* Otherwise the next QH has half the poll interval */ - sqh->next = - sc->sc_islots[EHCI_IQHIDX(lev - 1, i + 1)].sqh; - sqh->qh.qh_link = htole32(sqh->next->physaddr | - EHCI_LINK_QH); - } - sqh->qh.qh_endp = htole32(EHCI_QH_SET_EPS(EHCI_QH_SPEED_HIGH)); - sqh->qh.qh_endphub = htole32(EHCI_QH_SET_MULT(1)); - sqh->qh.qh_curqtd = EHCI_NULL; - sqh->qh.qh_qtd.qtd_next = EHCI_NULL; - sqh->qh.qh_qtd.qtd_altnext = EHCI_NULL; - sqh->qh.qh_qtd.qtd_status = htole32(EHCI_QTD_HALTED); - sqh->sqtd = NULL; - } - /* Point the frame list at the last level (128ms). */ - for (i = 0; i < sc->sc_flsize; i++) { - sc->sc_flist[i] = htole32(EHCI_LINK_QH | - sc->sc_islots[EHCI_IQHIDX(EHCI_IPOLLRATES - 1, - i)].sqh->physaddr); - } - - /* Allocate dummy QH that starts the async list. */ - sqh = ehci_alloc_sqh(sc); - if (sqh == NULL) { - err = USBD_NOMEM; - goto bad1; - } - /* Fill the QH */ - sqh->qh.qh_endp = - htole32(EHCI_QH_SET_EPS(EHCI_QH_SPEED_HIGH) | EHCI_QH_HRECL); - sqh->qh.qh_link = - htole32(sqh->physaddr | EHCI_LINK_QH); - sqh->qh.qh_curqtd = EHCI_NULL; - sqh->prev = sqh; /*It's a circular list.. */ - sqh->next = sqh; - /* Fill the overlay qTD */ - sqh->qh.qh_qtd.qtd_next = EHCI_NULL; - sqh->qh.qh_qtd.qtd_altnext = EHCI_NULL; - sqh->qh.qh_qtd.qtd_status = htole32(EHCI_QTD_HALTED); - sqh->sqtd = NULL; -#ifdef EHCI_DEBUG - if (ehcidebug) { - ehci_dump_sqh(sqh); - } -#endif - - /* Point to async list */ - sc->sc_async_head = sqh; - EOWRITE4(sc, EHCI_ASYNCLISTADDR, sqh->physaddr | EHCI_LINK_QH); - - callout_init(&sc->sc_tmo_intrlist); - - lockinit(&sc->sc_doorbell_lock, "ehcidb", 0, 0); - - /* Turn on controller */ - EOWRITE4(sc, EHCI_USBCMD, - EHCI_CMD_ITC_2 | /* 2 microframes interrupt delay */ - (EOREAD4(sc, EHCI_USBCMD) & EHCI_CMD_FLS_M) | - EHCI_CMD_ASE | - EHCI_CMD_PSE | - EHCI_CMD_RS); - - /* Take over port ownership */ - EOWRITE4(sc, EHCI_CONFIGFLAG, EHCI_CONF_CF); - - for (i = 0; i < 100; i++) { - usb_delay_ms(&sc->sc_bus, 1); - hcr = EOREAD4(sc, EHCI_USBSTS) & EHCI_STS_HCH; - if (!hcr) - break; - } - if (hcr) { - device_printf(sc->sc_bus.bdev, "run timeout\n"); - return (USBD_IOERROR); - } - - crit_enter(); - sc->sc_flags |= EHCI_SCFLG_DONEINIT; - EOWRITE4(sc, EHCI_USBINTR, sc->sc_eintrs); - ehci_intr(sc); - crit_exit(); - - return (USBD_NORMAL_COMPLETION); - -#if 0 - bad2: - ehci_free_sqh(sc, sc->sc_async_head); - sc->sc_async_head = NULL; -#endif - bad1: - usb_freemem(&sc->sc_bus, &sc->sc_fldma); - return (err); -} - -int -ehci_intr(void *v) -{ - ehci_softc_t *sc = v; - - if (sc->sc_dying || (sc->sc_flags & EHCI_SCFLG_DONEINIT) == 0) - return (0); - - /* If we get an interrupt while polling, then just ignore it. */ - if (sc->sc_bus.use_polling) { - u_int32_t intrs = EHCI_STS_INTRS(EOREAD4(sc, EHCI_USBSTS)); - - if (intrs) - EOWRITE4(sc, EHCI_USBSTS, intrs); /* Acknowledge */ - sc->sc_dintrs |= intrs; -#ifdef DIAGNOSTIC - DPRINTFN(16, ("ehci_intr: ignored interrupt while polling\n")); -#endif - return (0); - } - - return (ehci_intr1(sc)); -} - -static int -ehci_intr1(ehci_softc_t *sc) -{ - u_int32_t intrs, eintrs; - - DPRINTFN(20,("ehci_intr1: enter\n")); - - intrs = EHCI_STS_INTRS(EOREAD4(sc, EHCI_USBSTS)) | sc->sc_dintrs; - if (intrs == 0) - return (0); - - sc->sc_dintrs = 0; - eintrs = intrs & sc->sc_eintrs; - DPRINTFN(7, ("ehci_intr1: sc=%p intrs=0x%x(0x%x) eintrs=0x%x\n", - sc, (u_int)intrs, EOREAD4(sc, EHCI_USBSTS), - (u_int)eintrs)); - if (!eintrs) - return (0); - - EOWRITE4(sc, EHCI_USBSTS, intrs); /* Acknowledge */ - sc->sc_bus.intr_context++; - sc->sc_bus.no_intrs++; - if (eintrs & EHCI_STS_IAA) { - DPRINTF(("ehci_intr1: door bell\n")); - wakeup(&sc->sc_async_head); - eintrs &= ~EHCI_STS_IAA; - } - if (eintrs & (EHCI_STS_INT | EHCI_STS_ERRINT)) { - DPRINTFN(5,("ehci_intr1: %s %s\n", - eintrs & EHCI_STS_INT ? "INT" : "", - eintrs & EHCI_STS_ERRINT ? "ERRINT" : "")); - usb_schedsoftintr(&sc->sc_bus); - eintrs &= ~(EHCI_STS_INT | EHCI_STS_ERRINT); - } - if (eintrs & EHCI_STS_HSE) { - device_printf(sc->sc_bus.bdev, - "unrecoverable error, controller halted\n"); - /* XXX what else */ - } - if (eintrs & EHCI_STS_PCD) { - ehci_pcd(sc, sc->sc_intrxfer); - eintrs &= ~EHCI_STS_PCD; - } - - sc->sc_bus.intr_context--; - - if (eintrs != 0) { - /* Block unprocessed interrupts. */ - sc->sc_eintrs &= ~eintrs; - EOWRITE4(sc, EHCI_USBINTR, sc->sc_eintrs); - device_printf(sc->sc_bus.bdev, - "blocking intrs 0x%x\n", eintrs); - } - - return (1); -} - -void -ehci_pcd(ehci_softc_t *sc, usbd_xfer_handle xfer) -{ - u_char *p; - int i, m; - - if (xfer == NULL) { - /* Just ignore the change. */ - return; - } - - p = KERNADDR(&xfer->dmabuf, 0); - m = min(sc->sc_noport, xfer->length * 8 - 1); - memset(p, 0, xfer->length); - for (i = 1; i <= m; i++) { - /* Pick out CHANGE bits from the status reg. */ - if (EOREAD4(sc, EHCI_PORTSC(i)) & EHCI_PS_CLEAR) - p[i/8] |= 1 << (i%8); - } - DPRINTF(("ehci_pcd: change=0x%02x\n", *p)); - xfer->actlen = xfer->length; - xfer->status = USBD_NORMAL_COMPLETION; - - usb_transfer_complete(xfer); -} - -void -ehci_softintr(void *v) -{ - ehci_softc_t *sc = v; - struct ehci_xfer *ex, *nextex; - - DPRINTFN(10,("%s: ehci_softintr (%d)\n", device_get_nameunit(sc->sc_bus.bdev), - sc->sc_bus.intr_context)); - - sc->sc_bus.intr_context++; - - /* - * The only explanation I can think of for why EHCI is as brain dead - * as UHCI interrupt-wise is that Intel was involved in both. - * An interrupt just tells us that something is done, we have no - * clue what, so we need to scan through all active transfers. :-( - */ - for (ex = LIST_FIRST(&sc->sc_intrhead); ex; ex = nextex) { - nextex = LIST_NEXT(ex, inext); - ehci_check_intr(sc, ex); - } - - /* Schedule a callout to catch any dropped transactions. */ - if ((sc->sc_flags & EHCI_SCFLG_LOSTINTRBUG) && - !LIST_EMPTY(&sc->sc_intrhead)) - callout_reset(&sc->sc_tmo_intrlist, hz / 5, ehci_intrlist_timeout, - sc); - -#ifdef USB_USE_SOFTINTR - if (sc->sc_softwake) { - sc->sc_softwake = 0; - wakeup(&sc->sc_softwake); - } -#endif /* USB_USE_SOFTINTR */ - - sc->sc_bus.intr_context--; -} - -/* Check for an interrupt. */ -void -ehci_check_intr(ehci_softc_t *sc, struct ehci_xfer *ex) -{ - ehci_soft_qtd_t *sqtd, *lsqtd; - u_int32_t status; - - DPRINTFN(/*15*/2, ("ehci_check_intr: ex=%p\n", ex)); - - if (ex->sqtdstart == NULL) { - kprintf("ehci_check_intr: sqtdstart=NULL\n"); - return; - } - lsqtd = ex->sqtdend; -#ifdef DIAGNOSTIC - if (lsqtd == NULL) { - kprintf("ehci_check_intr: lsqtd==0\n"); - return; - } -#endif - /* - * If the last TD is still active we need to check whether there - * is a an error somewhere in the middle, or whether there was a - * short packet (SPD and not ACTIVE). - */ - if (le32toh(lsqtd->qtd.qtd_status) & EHCI_QTD_ACTIVE) { - DPRINTFN(12, ("ehci_check_intr: active ex=%p\n", ex)); - for (sqtd = ex->sqtdstart; sqtd != lsqtd; sqtd=sqtd->nextqtd) { - status = le32toh(sqtd->qtd.qtd_status); - /* If there's an active QTD the xfer isn't done. */ - if (status & EHCI_QTD_ACTIVE) - break; - /* Any kind of error makes the xfer done. */ - if (status & EHCI_QTD_HALTED) - goto done; - /* We want short packets, and it is short: it's done */ - if (EHCI_QTD_GET_BYTES(status) != 0) - goto done; - } - DPRINTFN(12, ("ehci_check_intr: ex=%p std=%p still active\n", - ex, ex->sqtdstart)); - return; - } - done: - DPRINTFN(12, ("ehci_check_intr: ex=%p done\n", ex)); - callout_stop(&ex->xfer.timeout_handle); - usb_rem_task(ex->xfer.pipe->device, &ex->abort_task); - ehci_idone(ex); -} - -void -ehci_idone(struct ehci_xfer *ex) -{ - usbd_xfer_handle xfer = &ex->xfer; -#ifdef USB_DEBUG - struct ehci_pipe *epipe = (struct ehci_pipe *)xfer->pipe; -#endif - ehci_soft_qtd_t *sqtd, *lsqtd; - u_int32_t status = 0, nstatus = 0; - int actlen, cerr; - - DPRINTFN(/*12*/2, ("ehci_idone: ex=%p\n", ex)); -#ifdef DIAGNOSTIC - { - crit_enter(); - if (ex->isdone) { - crit_exit(); -#ifdef EHCI_DEBUG - kprintf("ehci_idone: ex is done!\n "); - ehci_dump_exfer(ex); -#else - kprintf("ehci_idone: ex=%p is done!\n", ex); -#endif - return; - } - ex->isdone = 1; - crit_exit(); - } -#endif - - if (xfer->status == USBD_CANCELLED || - xfer->status == USBD_TIMEOUT) { - DPRINTF(("ehci_idone: aborted xfer=%p\n", xfer)); - return; - } - -#ifdef EHCI_DEBUG - DPRINTFN(/*10*/2, ("ehci_idone: xfer=%p, pipe=%p ready\n", xfer, epipe)); - if (ehcidebug > 10) - ehci_dump_sqtds(ex->sqtdstart); -#endif - - /* The transfer is done, compute actual length and status. */ - lsqtd = ex->sqtdend; - actlen = 0; - for (sqtd = ex->sqtdstart; sqtd != lsqtd->nextqtd; sqtd=sqtd->nextqtd) { - nstatus = le32toh(sqtd->qtd.qtd_status); - if (nstatus & EHCI_QTD_ACTIVE) - break; - - status = nstatus; - /* halt is ok if descriptor is last, and complete */ - if (sqtd->qtd.qtd_next == EHCI_NULL && - EHCI_QTD_GET_BYTES(status) == 0) - status &= ~EHCI_QTD_HALTED; - if (EHCI_QTD_GET_PID(status) != EHCI_QTD_PID_SETUP) - actlen += sqtd->len - EHCI_QTD_GET_BYTES(status); - } - - cerr = EHCI_QTD_GET_CERR(status); - DPRINTFN(/*10*/2, ("ehci_idone: len=%d, actlen=%d, cerr=%d, " - "status=0x%x\n", xfer->length, actlen, cerr, status)); - xfer->actlen = actlen; - if ((status & EHCI_QTD_HALTED) != 0) { -#ifdef EHCI_DEBUG - char sbuf[128]; - - bitmask_snprintf(status, - "\20\7HALTED\6BUFERR\5BABBLE\4XACTERR" - "\3MISSED\2SPLIT\1PING", sbuf, sizeof(sbuf)); - - DPRINTFN(2, - ("ehci_idone: error, addr=%d, endpt=0x%02x, " - "status 0x%s\n", - xfer->pipe->device->address, - xfer->pipe->endpoint->edesc->bEndpointAddress, - sbuf)); - if (ehcidebug > 2) { - ehci_dump_sqh(epipe->sqh); - ehci_dump_sqtds(ex->sqtdstart); - } -#endif - if ((status & EHCI_QTD_BABBLE) == 0 && cerr > 0) - xfer->status = USBD_STALLED; - else - xfer->status = USBD_IOERROR; /* more info XXX */ - } else { - xfer->status = USBD_NORMAL_COMPLETION; - } - - usb_transfer_complete(xfer); - DPRINTFN(/*12*/2, ("ehci_idone: ex=%p done\n", ex)); -} - -/* - * Wait here until controller claims to have an interrupt. - * Then call ehci_intr and return. Use timeout to avoid waiting - * too long. - */ -void -ehci_waitintr(ehci_softc_t *sc, usbd_xfer_handle xfer) -{ - int timo = xfer->timeout; - int usecs; - - xfer->status = USBD_IN_PROGRESS; - for (usecs = timo * 1000000 / hz; usecs > 0; usecs -= 1000) { - usb_delay_ms(&sc->sc_bus, 1); - if (sc->sc_dying) - break; - ehci_intr1(sc); - if (xfer->status != USBD_IN_PROGRESS) - return; - } - - /* Timeout */ - DPRINTF(("ehci_waitintr: timeout\n")); - xfer->status = USBD_TIMEOUT; - usb_transfer_complete(xfer); - /* XXX should free TD */ -} - -void -ehci_poll(struct usbd_bus *bus) -{ - ehci_softc_t *sc = (ehci_softc_t *)bus; -#ifdef EHCI_DEBUG - static int last; - int new; - new = EHCI_STS_INTRS(EOREAD4(sc, EHCI_USBSTS)); - if (new != last) { - DPRINTFN(10,("ehci_poll: intrs=0x%04x\n", new)); - last = new; - } -#endif - crit_enter(); - ehci_intr1(sc); - ehci_softintr(sc); - crit_exit(); -} - -int -ehci_detach(struct ehci_softc *sc, int flags) -{ - int rv = 0; - - crit_enter(); - sc->sc_dying = 1; - callout_stop(&sc->sc_tmo_intrlist); - EOWRITE4(sc, EHCI_USBINTR, 0); - EOWRITE4(sc, EHCI_USBCMD, 0); - EOWRITE4(sc, EHCI_USBCMD, EHCI_CMD_HCRESET); - crit_exit(); - - usb_delay_ms(&sc->sc_bus, 300); /* XXX let stray task complete */ - - usb_freemem(&sc->sc_bus, &sc->sc_fldma); - /* XXX free other data structures XXX */ - - return (rv); -} - -/* - * Handle suspend/resume. - * - * We need to switch to polling mode here, because this routine is - * called from an interrupt context. This is all right since we - * are almost suspended anyway. - */ -void -ehci_power(int why, void *v) -{ - ehci_softc_t *sc = v; - u_int32_t cmd, hcr; - int i; - -#ifdef EHCI_DEBUG - DPRINTF(("ehci_power: sc=%p, why=%d\n", sc, why)); - if (ehcidebug > 0) - ehci_dump_regs(sc); -#endif - - crit_enter(); - - switch (why) { - case PWR_SUSPEND: - sc->sc_bus.use_polling++; - - for (i = 1; i <= sc->sc_noport; i++) { - cmd = EOREAD4(sc, EHCI_PORTSC(i)); - if ((cmd & EHCI_PS_PO) == 0 && - (cmd & EHCI_PS_PE) == EHCI_PS_PE) - EOWRITE4(sc, EHCI_PORTSC(i), - cmd | EHCI_PS_SUSP); - } - - sc->sc_cmd = EOREAD4(sc, EHCI_USBCMD); - - cmd = sc->sc_cmd & ~(EHCI_CMD_ASE | EHCI_CMD_PSE); - EOWRITE4(sc, EHCI_USBCMD, cmd); - - for (i = 0; i < 100; i++) { - hcr = EOREAD4(sc, EHCI_USBSTS) & - (EHCI_STS_ASS | EHCI_STS_PSS); - if (hcr == 0) - break; - - usb_delay_ms(&sc->sc_bus, 1); - } - if (hcr != 0) { - device_printf(sc->sc_bus.bdev, "reset timeout\n"); - } - - cmd &= ~EHCI_CMD_RS; - EOWRITE4(sc, EHCI_USBCMD, cmd); - - for (i = 0; i < 100; i++) { - hcr = EOREAD4(sc, EHCI_USBSTS) & EHCI_STS_HCH; - if (hcr == EHCI_STS_HCH) - break; - - usb_delay_ms(&sc->sc_bus, 1); - } - if (hcr != EHCI_STS_HCH) { - device_printf(sc->sc_bus.bdev, "config timeout\n"); - } - - sc->sc_bus.use_polling--; - break; - - case PWR_RESUME: - sc->sc_bus.use_polling++; - - /* restore things in case the bios sucks */ - EOWRITE4(sc, EHCI_CTRLDSSEGMENT, 0); - EOWRITE4(sc, EHCI_PERIODICLISTBASE, DMAADDR(&sc->sc_fldma, 0)); - EOWRITE4(sc, EHCI_ASYNCLISTADDR, - sc->sc_async_head->physaddr | EHCI_LINK_QH); - EOWRITE4(sc, EHCI_USBINTR, sc->sc_eintrs); - - hcr = 0; - for (i = 1; i <= sc->sc_noport; i++) { - cmd = EOREAD4(sc, EHCI_PORTSC(i)); - if ((cmd & EHCI_PS_PO) == 0 && - (cmd & EHCI_PS_SUSP) == EHCI_PS_SUSP) { - EOWRITE4(sc, EHCI_PORTSC(i), - cmd | EHCI_PS_FPR); - hcr = 1; - } - } - - if (hcr) { - usb_delay_ms(&sc->sc_bus, USB_RESUME_WAIT); - - for (i = 1; i <= sc->sc_noport; i++) { - cmd = EOREAD4(sc, EHCI_PORTSC(i)); - if ((cmd & EHCI_PS_PO) == 0 && - (cmd & EHCI_PS_SUSP) == EHCI_PS_SUSP) - EOWRITE4(sc, EHCI_PORTSC(i), - cmd & ~EHCI_PS_FPR); - } - } - - EOWRITE4(sc, EHCI_USBCMD, sc->sc_cmd); - - for (i = 0; i < 100; i++) { - hcr = EOREAD4(sc, EHCI_USBSTS) & EHCI_STS_HCH; - if (hcr != EHCI_STS_HCH) - break; - - usb_delay_ms(&sc->sc_bus, 1); - } - if (hcr == EHCI_STS_HCH) { - device_printf(sc->sc_bus.bdev, "config timeout\n"); - } - - usb_delay_ms(&sc->sc_bus, USB_RESUME_WAIT); - - sc->sc_bus.use_polling--; - break; - } - crit_exit(); - -#ifdef EHCI_DEBUG - DPRINTF(("ehci_power: sc=%p\n", sc)); - if (ehcidebug > 0) - ehci_dump_regs(sc); -#endif -} - -/* - * Shut down the controller when the system is going down. - */ -void -ehci_shutdown(void *v) -{ - ehci_softc_t *sc = v; - - DPRINTF(("ehci_shutdown: stopping the HC\n")); - crit_enter(); - sc->sc_dying = 1; - callout_stop(&sc->sc_tmo_intrlist); - EOWRITE4(sc, EHCI_USBINTR, 0); - EOWRITE4(sc, EHCI_USBCMD, 0); - EOWRITE4(sc, EHCI_USBCMD, EHCI_CMD_HCRESET); - crit_exit(); -} - -usbd_status -ehci_allocm(struct usbd_bus *bus, usb_dma_t *dma, u_int32_t size) -{ - usbd_status err; - - err = usb_allocmem(bus, size, 0, dma); -#ifdef EHCI_DEBUG - if (err) - kprintf("ehci_allocm: usb_allocmem()=%d\n", err); -#endif - return (err); -} - -void -ehci_freem(struct usbd_bus *bus, usb_dma_t *dma) -{ - usb_freemem(bus, dma); -} - -usbd_xfer_handle -ehci_allocx(struct usbd_bus *bus) -{ - struct ehci_softc *sc = (struct ehci_softc *)bus; - usbd_xfer_handle xfer; - - xfer = STAILQ_FIRST(&sc->sc_free_xfers); - if (xfer != NULL) { - STAILQ_REMOVE_HEAD(&sc->sc_free_xfers, next); -#ifdef DIAGNOSTIC - if (xfer->busy_free != XFER_FREE) { - kprintf("ehci_allocx: xfer=%p not free, 0x%08x\n", xfer, - xfer->busy_free); - } -#endif - } else { - xfer = kmalloc(sizeof(struct ehci_xfer), M_USB, M_INTWAIT); - } - if (xfer != NULL) { - memset(xfer, 0, sizeof(struct ehci_xfer)); - usb_init_task(&EXFER(xfer)->abort_task, ehci_timeout_task, - xfer); - EXFER(xfer)->ehci_xfer_flags = 0; -#ifdef DIAGNOSTIC - EXFER(xfer)->isdone = 1; - xfer->busy_free = XFER_BUSY; -#endif - } - return (xfer); -} - -void -ehci_freex(struct usbd_bus *bus, usbd_xfer_handle xfer) -{ - struct ehci_softc *sc = (struct ehci_softc *)bus; - -#ifdef DIAGNOSTIC - if (xfer->busy_free != XFER_BUSY) { - kprintf("ehci_freex: xfer=%p not busy, 0x%08x\n", xfer, - xfer->busy_free); - return; - } - xfer->busy_free = XFER_FREE; - if (!EXFER(xfer)->isdone) { - kprintf("ehci_freex: !isdone\n"); - return; - } -#endif - STAILQ_INSERT_HEAD(&sc->sc_free_xfers, xfer, next); -} - -static void -ehci_device_clear_toggle(usbd_pipe_handle pipe) -{ - struct ehci_pipe *epipe = (struct ehci_pipe *)pipe; - - DPRINTF(("ehci_device_clear_toggle: epipe=%p status=0x%x\n", - epipe, epipe->sqh->qh.qh_qtd.qtd_status)); -#ifdef USB_DEBUG - if (ehcidebug) - usbd_dump_pipe(pipe); -#endif - KASSERT((epipe->sqh->qh.qh_qtd.qtd_status & - htole32(EHCI_QTD_ACTIVE)) == 0, - ("ehci_device_clear_toggle: queue active")); - epipe->sqh->qh.qh_qtd.qtd_status &= htole32(~EHCI_QTD_TOGGLE_MASK); -} - -static void -ehci_noop(usbd_pipe_handle pipe) -{ -} - -#ifdef EHCI_DEBUG -void -ehci_dump_regs(ehci_softc_t *sc) -{ - int i; - kprintf("cmd=0x%08x, sts=0x%08x, ien=0x%08x\n", - EOREAD4(sc, EHCI_USBCMD), - EOREAD4(sc, EHCI_USBSTS), - EOREAD4(sc, EHCI_USBINTR)); - kprintf("frindex=0x%08x ctrdsegm=0x%08x periodic=0x%08x async=0x%08x\n", - EOREAD4(sc, EHCI_FRINDEX), - EOREAD4(sc, EHCI_CTRLDSSEGMENT), - EOREAD4(sc, EHCI_PERIODICLISTBASE), - EOREAD4(sc, EHCI_ASYNCLISTADDR)); - for (i = 1; i <= sc->sc_noport; i++) - kprintf("port %d status=0x%08x\n", i, - EOREAD4(sc, EHCI_PORTSC(i))); -} - -/* - * Unused function - this is meant to be called from a kernel - * debugger. - */ -void -ehci_dump(void) -{ - ehci_dump_regs(theehci); -} - -void -ehci_dump_link(ehci_link_t link, int type) -{ - link = le32toh(link); - kprintf("0x%08x", link); - if (link & EHCI_LINK_TERMINATE) - kprintf(""); - else { - kprintf("<"); - if (type) { - switch (EHCI_LINK_TYPE(link)) { - case EHCI_LINK_ITD: kprintf("ITD"); break; - case EHCI_LINK_QH: kprintf("QH"); break; - case EHCI_LINK_SITD: kprintf("SITD"); break; - case EHCI_LINK_FSTN: kprintf("FSTN"); break; - } - } - kprintf(">"); - } -} - -void -ehci_dump_sqtds(ehci_soft_qtd_t *sqtd) -{ - int i; - u_int32_t stop; - - stop = 0; - for (i = 0; sqtd && i < 20 && !stop; sqtd = sqtd->nextqtd, i++) { - ehci_dump_sqtd(sqtd); - stop = sqtd->qtd.qtd_next & htole32(EHCI_LINK_TERMINATE); - } - if (sqtd) - kprintf("dump aborted, too many TDs\n"); -} - -void -ehci_dump_sqtd(ehci_soft_qtd_t *sqtd) -{ - kprintf("QTD(%p) at 0x%08x:\n", sqtd, sqtd->physaddr); - ehci_dump_qtd(&sqtd->qtd); -} - -void -ehci_dump_qtd(ehci_qtd_t *qtd) -{ - u_int32_t s; - char sbuf[128]; - - kprintf(" next="); ehci_dump_link(qtd->qtd_next, 0); - kprintf(" altnext="); ehci_dump_link(qtd->qtd_altnext, 0); - kprintf("\n"); - s = le32toh(qtd->qtd_status); - bitmask_snprintf(EHCI_QTD_GET_STATUS(s), - "\20\10ACTIVE\7HALTED\6BUFERR\5BABBLE\4XACTERR" - "\3MISSED\2SPLIT\1PING", sbuf, sizeof(sbuf)); - kprintf(" status=0x%08x: toggle=%d bytes=0x%x ioc=%d c_page=0x%x\n", - s, EHCI_QTD_GET_TOGGLE(s), EHCI_QTD_GET_BYTES(s), - EHCI_QTD_GET_IOC(s), EHCI_QTD_GET_C_PAGE(s)); - kprintf(" cerr=%d pid=%d stat=0x%s\n", EHCI_QTD_GET_CERR(s), - EHCI_QTD_GET_PID(s), sbuf); - for (s = 0; s < 5; s++) - kprintf(" buffer[%d]=0x%08x\n", s, le32toh(qtd->qtd_buffer[s])); -} - -void -ehci_dump_sqh(ehci_soft_qh_t *sqh) -{ - ehci_qh_t *qh = &sqh->qh; - u_int32_t endp, endphub; - - kprintf("QH(%p) at 0x%08x:\n", sqh, sqh->physaddr); - kprintf(" link="); ehci_dump_link(qh->qh_link, 1); kprintf("\n"); - endp = le32toh(qh->qh_endp); - kprintf(" endp=0x%08x\n", endp); - kprintf(" addr=0x%02x inact=%d endpt=%d eps=%d dtc=%d hrecl=%d\n", - EHCI_QH_GET_ADDR(endp), EHCI_QH_GET_INACT(endp), - EHCI_QH_GET_ENDPT(endp), EHCI_QH_GET_EPS(endp), - EHCI_QH_GET_DTC(endp), EHCI_QH_GET_HRECL(endp)); - kprintf(" mpl=0x%x ctl=%d nrl=%d\n", - EHCI_QH_GET_MPL(endp), EHCI_QH_GET_CTL(endp), - EHCI_QH_GET_NRL(endp)); - endphub = le32toh(qh->qh_endphub); - kprintf(" endphub=0x%08x\n", endphub); - kprintf(" smask=0x%02x cmask=0x%02x huba=0x%02x port=%d mult=%d\n", - EHCI_QH_GET_SMASK(endphub), EHCI_QH_GET_CMASK(endphub), - EHCI_QH_GET_HUBA(endphub), EHCI_QH_GET_PORT(endphub), - EHCI_QH_GET_MULT(endphub)); - kprintf(" curqtd="); ehci_dump_link(qh->qh_curqtd, 0); kprintf("\n"); - kprintf("Overlay qTD:\n"); - ehci_dump_qtd(&qh->qh_qtd); -} - -#ifdef DIAGNOSTIC -static void -ehci_dump_exfer(struct ehci_xfer *ex) -{ - kprintf("ehci_dump_exfer: ex=%p\n", ex); -} -#endif -#endif - -usbd_status -ehci_open(usbd_pipe_handle pipe) -{ - usbd_device_handle dev = pipe->device; - ehci_softc_t *sc = (ehci_softc_t *)dev->bus; - usb_endpoint_descriptor_t *ed = pipe->endpoint->edesc; - u_int8_t addr = dev->address; - u_int8_t xfertype = ed->bmAttributes & UE_XFERTYPE; - struct ehci_pipe *epipe = (struct ehci_pipe *)pipe; - ehci_soft_qh_t *sqh; - usbd_status err; - int ival, speed, naks; - int hshubaddr, hshubport; - - DPRINTFN(1, ("ehci_open: pipe=%p, addr=%d, endpt=%d (%d)\n", - pipe, addr, ed->bEndpointAddress, sc->sc_addr)); - - if (dev->myhsport) { - hshubaddr = dev->myhsport->parent->address; - hshubport = dev->myhsport->portno; - } else { - hshubaddr = 0; - hshubport = 0; - } - - if (sc->sc_dying) - return (USBD_IOERROR); - - if (addr == sc->sc_addr) { - switch (ed->bEndpointAddress) { - case USB_CONTROL_ENDPOINT: - pipe->methods = &ehci_root_ctrl_methods; - break; - case UE_DIR_IN | EHCI_INTR_ENDPT: - pipe->methods = &ehci_root_intr_methods; - break; - default: - return (USBD_INVAL); - } - return (USBD_NORMAL_COMPLETION); - } - - /* XXX All this stuff is only valid for async. */ - switch (dev->speed) { - case USB_SPEED_LOW: speed = EHCI_QH_SPEED_LOW; break; - case USB_SPEED_FULL: speed = EHCI_QH_SPEED_FULL; break; - case USB_SPEED_HIGH: speed = EHCI_QH_SPEED_HIGH; break; - default: panic("ehci_open: bad device speed %d", dev->speed); - } - if (speed != EHCI_QH_SPEED_HIGH && xfertype == UE_ISOCHRONOUS) { - device_printf(sc->sc_bus.bdev, - "*** WARNING: opening low/full speed device, this " - "does not work yet.\n"); - DPRINTFN(1,("ehci_open: hshubaddr=%d hshubport=%d\n", - hshubaddr, hshubport)); - return USBD_INVAL; - } - - naks = 8; /* XXX */ - sqh = ehci_alloc_sqh(sc); - if (sqh == NULL) - goto bad0; - /* qh_link filled when the QH is added */ - sqh->qh.qh_endp = htole32( - EHCI_QH_SET_ADDR(addr) | - EHCI_QH_SET_ENDPT(UE_GET_ADDR(ed->bEndpointAddress)) | - EHCI_QH_SET_EPS(speed) | - (xfertype == UE_CONTROL ? EHCI_QH_DTC : 0) | - EHCI_QH_SET_MPL(UGETW(ed->wMaxPacketSize)) | - (speed != EHCI_QH_SPEED_HIGH && xfertype == UE_CONTROL ? - EHCI_QH_CTL : 0) | - EHCI_QH_SET_NRL(naks) - ); - sqh->qh.qh_endphub = htole32( - EHCI_QH_SET_MULT(1) | - EHCI_QH_SET_HUBA(hshubaddr) | - EHCI_QH_SET_PORT(hshubport) | - EHCI_QH_SET_CMASK(0x1c) | - EHCI_QH_SET_SMASK(xfertype == UE_INTERRUPT ? 0x01 : 0) - ); - sqh->qh.qh_curqtd = EHCI_NULL; - /* Fill the overlay qTD */ - sqh->qh.qh_qtd.qtd_next = EHCI_NULL; - sqh->qh.qh_qtd.qtd_altnext = EHCI_NULL; - sqh->qh.qh_qtd.qtd_status = - htole32(EHCI_QTD_SET_TOGGLE(pipe->endpoint->savedtoggle)); - - epipe->sqh = sqh; - - switch (xfertype) { - case UE_CONTROL: - err = usb_allocmem(&sc->sc_bus, sizeof(usb_device_request_t), - 0, &epipe->u.ctl.reqdma); -#ifdef EHCI_DEBUG - if (err) - kprintf("ehci_open: usb_allocmem()=%d\n", err); -#endif - if (err) - goto bad1; - pipe->methods = &ehci_device_ctrl_methods; - crit_enter(); - ehci_add_qh(sqh, sc->sc_async_head); - crit_exit(); - break; - case UE_BULK: - pipe->methods = &ehci_device_bulk_methods; - crit_enter(); - ehci_add_qh(sqh, sc->sc_async_head); - crit_exit(); - break; - case UE_INTERRUPT: - pipe->methods = &ehci_device_intr_methods; - ival = pipe->interval; - if (ival == USBD_DEFAULT_INTERVAL) - ival = ed->bInterval; - return (ehci_device_setintr(sc, sqh, ival)); - case UE_ISOCHRONOUS: - pipe->methods = &ehci_device_isoc_methods; - return (USBD_INVAL); - default: - return (USBD_INVAL); - } - return (USBD_NORMAL_COMPLETION); - - bad1: - ehci_free_sqh(sc, sqh); - epipe->sqh = NULL; - bad0: - return (USBD_NOMEM); -} - -/* - * Add an ED to the schedule. Called while in a critical section. - * If in the async schedule, it will always have a next. - * If in the intr schedule it may not. - */ -void -ehci_add_qh(ehci_soft_qh_t *sqh, ehci_soft_qh_t *head) -{ - sqh->next = head->next; - sqh->prev = head; - sqh->qh.qh_link = head->qh.qh_link; - head->next = sqh; - if (sqh->next) - sqh->next->prev = sqh; - head->qh.qh_link = htole32(sqh->physaddr | EHCI_LINK_QH); - -#ifdef EHCI_DEBUG - if (ehcidebug > 5) { - kprintf("ehci_add_qh:\n"); - ehci_dump_sqh(sqh); - } -#endif -} - -/* - * Remove an ED from the schedule. Called while in a critical section. - * Will always have a 'next' if it's in the async list as it's circular. - */ -void -ehci_rem_qh(ehci_softc_t *sc, ehci_soft_qh_t *sqh, ehci_soft_qh_t *head) -{ - /* XXX */ - sqh->prev->qh.qh_link = sqh->qh.qh_link; - sqh->prev->next = sqh->next; - if (sqh->next) - sqh->next->prev = sqh->prev; - ehci_sync_hc(sc); -} - -void -ehci_set_qh_qtd(ehci_soft_qh_t *sqh, ehci_soft_qtd_t *sqtd) -{ - int i; - u_int32_t status; - - /* Save toggle bit and ping status. */ - status = sqh->qh.qh_qtd.qtd_status & - htole32(EHCI_QTD_TOGGLE_MASK | - EHCI_QTD_SET_STATUS(EHCI_QTD_PINGSTATE)); - /* Set HALTED to make hw leave it alone. */ - sqh->qh.qh_qtd.qtd_status = - htole32(EHCI_QTD_SET_STATUS(EHCI_QTD_HALTED)); - sqh->qh.qh_curqtd = 0; - sqh->qh.qh_qtd.qtd_next = htole32(sqtd->physaddr); - sqh->qh.qh_qtd.qtd_altnext = 0; - for (i = 0; i < EHCI_QTD_NBUFFERS; i++) - sqh->qh.qh_qtd.qtd_buffer[i] = 0; - sqh->sqtd = sqtd; - /* Set !HALTED && !ACTIVE to start execution, preserve some fields */ - sqh->qh.qh_qtd.qtd_status = status; -} - -/* - * Ensure that the HC has released all references to the QH. We do this - * by asking for a Async Advance Doorbell interrupt and then we wait for - * the interrupt. - * To make this easier we first obtain exclusive use of the doorbell. - */ -void -ehci_sync_hc(ehci_softc_t *sc) -{ - int error; - - if (sc->sc_dying) { - DPRINTFN(2,("ehci_sync_hc: dying\n")); - return; - } - DPRINTFN(2,("ehci_sync_hc: enter\n")); - /* get doorbell */ - lockmgr(&sc->sc_doorbell_lock, LK_EXCLUSIVE); - crit_enter(); - /* ask for doorbell */ - EOWRITE4(sc, EHCI_USBCMD, EOREAD4(sc, EHCI_USBCMD) | EHCI_CMD_IAAD); - DPRINTFN(1,("ehci_sync_hc: cmd=0x%08x sts=0x%08x\n", - EOREAD4(sc, EHCI_USBCMD), EOREAD4(sc, EHCI_USBSTS))); - error = tsleep(&sc->sc_async_head, 0, "ehcidi", hz); /* bell wait */ - DPRINTFN(1,("ehci_sync_hc: cmd=0x%08x sts=0x%08x\n", - EOREAD4(sc, EHCI_USBCMD), EOREAD4(sc, EHCI_USBSTS))); - crit_exit(); - /* release doorbell */ - lockmgr(&sc->sc_doorbell_lock, LK_RELEASE); -#ifdef DIAGNOSTIC - if (error) - kprintf("ehci_sync_hc: tsleep() = %d\n", error); -#endif - DPRINTFN(2,("ehci_sync_hc: exit\n")); -} - -/***********/ - -/* - * Data structures and routines to emulate the root hub. - */ -static usb_device_descriptor_t ehci_devd = { - USB_DEVICE_DESCRIPTOR_SIZE, - UDESC_DEVICE, /* type */ - {0x00, 0x02}, /* USB version */ - UDCLASS_HUB, /* class */ - UDSUBCLASS_HUB, /* subclass */ - UDPROTO_HSHUBSTT, /* protocol */ - 64, /* max packet */ - {0},{0},{0x00,0x01}, /* device id */ - 1,2,0, /* string indicies */ - 1 /* # of configurations */ -}; - -static usb_device_qualifier_t ehci_odevd = { - USB_DEVICE_DESCRIPTOR_SIZE, - UDESC_DEVICE_QUALIFIER, /* type */ - {0x00, 0x02}, /* USB version */ - UDCLASS_HUB, /* class */ - UDSUBCLASS_HUB, /* subclass */ - UDPROTO_FSHUB, /* protocol */ - 64, /* max packet */ - 1, /* # of configurations */ - 0 -}; - -static usb_config_descriptor_t ehci_confd = { - USB_CONFIG_DESCRIPTOR_SIZE, - UDESC_CONFIG, - {USB_CONFIG_DESCRIPTOR_SIZE + - USB_INTERFACE_DESCRIPTOR_SIZE + - USB_ENDPOINT_DESCRIPTOR_SIZE}, - 1, - 1, - 0, - UC_SELF_POWERED, - 0 /* max power */ -}; - -static usb_interface_descriptor_t ehci_ifcd = { - USB_INTERFACE_DESCRIPTOR_SIZE, - UDESC_INTERFACE, - 0, - 0, - 1, - UICLASS_HUB, - UISUBCLASS_HUB, - UIPROTO_HSHUBSTT, - 0 -}; - -static usb_endpoint_descriptor_t ehci_endpd = { - USB_ENDPOINT_DESCRIPTOR_SIZE, - UDESC_ENDPOINT, - UE_DIR_IN | EHCI_INTR_ENDPT, - UE_INTERRUPT, - {8, 0}, /* max packet */ - 255 -}; - -static usb_hub_descriptor_t ehci_hubd = { - USB_HUB_DESCRIPTOR_SIZE, - UDESC_HUB, - 0, - {0,0}, - 0, - 0, - {0}, -}; - -static int -ehci_str(usb_string_descriptor_t *p, int l, char *s) -{ - int i; - - if (l == 0) - return (0); - p->bLength = 2 * strlen(s) + 2; - if (l == 1) - return (1); - p->bDescriptorType = UDESC_STRING; - l -= 2; - for (i = 0; s[i] && l > 1; i++, l -= 2) - USETW2(p->bString[i], 0, s[i]); - return (2*i+2); -} - -/* - * Simulate a hardware hub by handling all the necessary requests. - */ -static usbd_status -ehci_root_ctrl_transfer(usbd_xfer_handle xfer) -{ - usbd_status err; - - /* Insert last in queue. */ - err = usb_insert_transfer(xfer); - if (err) - return (err); - - /* Pipe isn't running, start first */ - return (ehci_root_ctrl_start(STAILQ_FIRST(&xfer->pipe->queue))); -} - -static usbd_status -ehci_root_ctrl_start(usbd_xfer_handle xfer) -{ - ehci_softc_t *sc = (ehci_softc_t *)xfer->pipe->device->bus; - usb_device_request_t *req; - void *buf = NULL; - int port, i; - int retries; - int len, value, index, l, totlen = 0; - usb_port_status_t ps; - usb_hub_descriptor_t hubd; - usbd_status err; - u_int32_t v; - - if (sc->sc_dying) - return (USBD_IOERROR); - -#ifdef DIAGNOSTIC - if (!(xfer->rqflags & URQ_REQUEST)) - /* XXX panic */ - return (USBD_INVAL); -#endif - req = &xfer->request; - - DPRINTFN(4,("ehci_root_ctrl_start: type=0x%02x request=%02x\n", - req->bmRequestType, req->bRequest)); - - len = UGETW(req->wLength); - value = UGETW(req->wValue); - index = UGETW(req->wIndex); - - if (len != 0) - buf = KERNADDR(&xfer->dmabuf, 0); - -#define C(x,y) ((x) | ((y) << 8)) - switch(C(req->bRequest, req->bmRequestType)) { - case C(UR_CLEAR_FEATURE, UT_WRITE_DEVICE): - case C(UR_CLEAR_FEATURE, UT_WRITE_INTERFACE): - case C(UR_CLEAR_FEATURE, UT_WRITE_ENDPOINT): - /* - * DEVICE_REMOTE_WAKEUP and ENDPOINT_HALT are no-ops - * for the integrated root hub. - */ - break; - case C(UR_GET_CONFIG, UT_READ_DEVICE): - if (len > 0) { - *(u_int8_t *)buf = sc->sc_conf; - totlen = 1; - } - break; - case C(UR_GET_DESCRIPTOR, UT_READ_DEVICE): - DPRINTFN(8,("ehci_root_ctrl_start: wValue=0x%04x\n", value)); - switch(value >> 8) { - case UDESC_DEVICE: - if ((value & 0xff) != 0) { - err = USBD_IOERROR; - goto ret; - } - totlen = l = min(len, USB_DEVICE_DESCRIPTOR_SIZE); - USETW(ehci_devd.idVendor, sc->sc_id_vendor); - memcpy(buf, &ehci_devd, l); - break; - /* - * We can't really operate at another speed, but the spec says - * we need this descriptor. - */ - case UDESC_DEVICE_QUALIFIER: - if ((value & 0xff) != 0) { - err = USBD_IOERROR; - goto ret; - } - totlen = l = min(len, USB_DEVICE_DESCRIPTOR_SIZE); - memcpy(buf, &ehci_odevd, l); - break; - /* - * We can't really operate at another speed, but the spec says - * we need this descriptor. - */ - case UDESC_OTHER_SPEED_CONFIGURATION: - case UDESC_CONFIG: - if ((value & 0xff) != 0) { - err = USBD_IOERROR; - goto ret; - } - totlen = l = min(len, USB_CONFIG_DESCRIPTOR_SIZE); - memcpy(buf, &ehci_confd, l); - ((usb_config_descriptor_t *)buf)->bDescriptorType = - value >> 8; - buf = (char *)buf + l; - len -= l; - l = min(len, USB_INTERFACE_DESCRIPTOR_SIZE); - totlen += l; - memcpy(buf, &ehci_ifcd, l); - buf = (char *)buf + l; - len -= l; - l = min(len, USB_ENDPOINT_DESCRIPTOR_SIZE); - totlen += l; - memcpy(buf, &ehci_endpd, l); - break; - case UDESC_STRING: - if (len == 0) - break; - *(u_int8_t *)buf = 0; - totlen = 1; - switch (value & 0xff) { - case 0: /* Language table */ - totlen = ehci_str(buf, len, "\001"); - break; - case 1: /* Vendor */ - totlen = ehci_str(buf, len, sc->sc_vendor); - break; - case 2: /* Product */ - totlen = ehci_str(buf, len, "EHCI root hub"); - break; - } - break; - default: - err = USBD_IOERROR; - goto ret; - } - break; - case C(UR_GET_INTERFACE, UT_READ_INTERFACE): - if (len > 0) { - *(u_int8_t *)buf = 0; - totlen = 1; - } - break; - case C(UR_GET_STATUS, UT_READ_DEVICE): - if (len > 1) { - USETW(((usb_status_t *)buf)->wStatus,UDS_SELF_POWERED); - totlen = 2; - } - break; - case C(UR_GET_STATUS, UT_READ_INTERFACE): - case C(UR_GET_STATUS, UT_READ_ENDPOINT): - if (len > 1) { - USETW(((usb_status_t *)buf)->wStatus, 0); - totlen = 2; - } - break; - case C(UR_SET_ADDRESS, UT_WRITE_DEVICE): - if (value >= USB_MAX_DEVICES) { - err = USBD_IOERROR; - goto ret; - } - sc->sc_addr = value; - break; - case C(UR_SET_CONFIG, UT_WRITE_DEVICE): - if (value != 0 && value != 1) { - err = USBD_IOERROR; - goto ret; - } - sc->sc_conf = value; - break; - case C(UR_SET_DESCRIPTOR, UT_WRITE_DEVICE): - break; - case C(UR_SET_FEATURE, UT_WRITE_DEVICE): - case C(UR_SET_FEATURE, UT_WRITE_INTERFACE): - case C(UR_SET_FEATURE, UT_WRITE_ENDPOINT): - err = USBD_IOERROR; - goto ret; - case C(UR_SET_INTERFACE, UT_WRITE_INTERFACE): - break; - case C(UR_SYNCH_FRAME, UT_WRITE_ENDPOINT): - break; - /* Hub requests */ - case C(UR_CLEAR_FEATURE, UT_WRITE_CLASS_DEVICE): - break; - case C(UR_CLEAR_FEATURE, UT_WRITE_CLASS_OTHER): - DPRINTFN(8, ("ehci_root_ctrl_start: UR_CLEAR_PORT_FEATURE " - "port=%d feature=%d\n", - index, value)); - if (index < 1 || index > sc->sc_noport) { - err = USBD_IOERROR; - goto ret; - } - port = EHCI_PORTSC(index); - v = EOREAD4(sc, port) &~ EHCI_PS_CLEAR; - switch(value) { - case UHF_PORT_ENABLE: - EOWRITE4(sc, port, v &~ EHCI_PS_PE); - break; - case UHF_PORT_SUSPEND: - EOWRITE4(sc, port, v &~ EHCI_PS_SUSP); - break; - case UHF_PORT_POWER: - EOWRITE4(sc, port, v &~ EHCI_PS_PP); - break; - case UHF_PORT_TEST: - DPRINTFN(2,("ehci_root_ctrl_start: clear port test " - "%d\n", index)); - break; - case UHF_PORT_INDICATOR: - DPRINTFN(2,("ehci_root_ctrl_start: clear port ind " - "%d\n", index)); - EOWRITE4(sc, port, v &~ EHCI_PS_PIC); - break; - case UHF_C_PORT_CONNECTION: - EOWRITE4(sc, port, v | EHCI_PS_CSC); - break; - case UHF_C_PORT_ENABLE: - EOWRITE4(sc, port, v | EHCI_PS_PEC); - break; - case UHF_C_PORT_SUSPEND: - /* how? */ - break; - case UHF_C_PORT_OVER_CURRENT: - EOWRITE4(sc, port, v | EHCI_PS_OCC); - break; - case UHF_C_PORT_RESET: - sc->sc_isreset = 0; - break; - default: - err = USBD_IOERROR; - goto ret; - } - break; - case C(UR_GET_DESCRIPTOR, UT_READ_CLASS_DEVICE): - if ((value & 0xff) != 0) { - err = USBD_IOERROR; - goto ret; - } - hubd = ehci_hubd; - hubd.bNbrPorts = sc->sc_noport; - v = EOREAD4(sc, EHCI_HCSPARAMS); - USETW(hubd.wHubCharacteristics, - EHCI_HCS_PPC(v) ? UHD_PWR_INDIVIDUAL : UHD_PWR_NO_SWITCH | - EHCI_HCS_P_INDICATOR(EREAD4(sc, EHCI_HCSPARAMS)) - ? UHD_PORT_IND : 0); - hubd.bPwrOn2PwrGood = 200; /* XXX can't find out? */ - for (i = 0, l = sc->sc_noport; l > 0; i++, l -= 8, v >>= 8) - hubd.DeviceRemovable[i++] = 0; /* XXX can't find out? */ - hubd.bDescLength = USB_HUB_DESCRIPTOR_SIZE + i; - l = min(len, hubd.bDescLength); - totlen = l; - memcpy(buf, &hubd, l); - break; - case C(UR_GET_STATUS, UT_READ_CLASS_DEVICE): - if (len != 4) { - err = USBD_IOERROR; - goto ret; - } - memset(buf, 0, len); /* ? XXX */ - totlen = len; - break; - case C(UR_GET_STATUS, UT_READ_CLASS_OTHER): - DPRINTFN(8,("ehci_root_ctrl_start: get port status i=%d\n", - index)); - if (index < 1 || index > sc->sc_noport) { - err = USBD_IOERROR; - goto ret; - } - if (len != 4) { - err = USBD_IOERROR; - goto ret; - } - v = EOREAD4(sc, EHCI_PORTSC(index)); - DPRINTFN(8,("ehci_root_ctrl_start: port status=0x%04x\n", v)); - i = UPS_HIGH_SPEED; - if (v & EHCI_PS_CS) i |= UPS_CURRENT_CONNECT_STATUS; - if (v & EHCI_PS_PE) i |= UPS_PORT_ENABLED; - if (v & EHCI_PS_SUSP) i |= UPS_SUSPEND; - if (v & EHCI_PS_OCA) i |= UPS_OVERCURRENT_INDICATOR; - if (v & EHCI_PS_PR) i |= UPS_RESET; - if (v & EHCI_PS_PP) i |= UPS_PORT_POWER; - USETW(ps.wPortStatus, i); - i = 0; - if (v & EHCI_PS_CSC) i |= UPS_C_CONNECT_STATUS; - if (v & EHCI_PS_PEC) i |= UPS_C_PORT_ENABLED; - if (v & EHCI_PS_OCC) i |= UPS_C_OVERCURRENT_INDICATOR; - if (sc->sc_isreset) i |= UPS_C_PORT_RESET; - USETW(ps.wPortChange, i); - l = min(len, sizeof ps); - memcpy(buf, &ps, l); - totlen = l; - break; - case C(UR_SET_DESCRIPTOR, UT_WRITE_CLASS_DEVICE): - err = USBD_IOERROR; - goto ret; - case C(UR_SET_FEATURE, UT_WRITE_CLASS_DEVICE): - break; - case C(UR_SET_FEATURE, UT_WRITE_CLASS_OTHER): - if (index < 1 || index > sc->sc_noport) { - err = USBD_IOERROR; - goto ret; - } - port = EHCI_PORTSC(index); - v = EOREAD4(sc, port) &~ EHCI_PS_CLEAR; - switch(value) { - case UHF_PORT_ENABLE: - EOWRITE4(sc, port, v | EHCI_PS_PE); - break; - case UHF_PORT_SUSPEND: - EOWRITE4(sc, port, v | EHCI_PS_SUSP); - break; - case UHF_PORT_RESET: - /* - * Give up ownership if this is a low-speed port. - */ - DPRINTFN(5,("ehci_root_ctrl_start: reset port %d\n", - index)); - if (EHCI_PS_IS_LOWSPEED(v)) { - ehci_disown(sc, index, 1); - break; - } - - /* - * Issue a RESET sequence on the port. Set PS_PR for - * 2ms then clear it, then wait for it to read clear. - * - * Some devices, particularly smartphones, will not - * properly reset on the first try. - */ - retries = 2; - - while (retries) { - v &= ~(EHCI_PS_PE | EHCI_PS_PR); - EOWRITE4(sc, port, v | EHCI_PS_PR); - usb_delay_ms(&sc->sc_bus, - USB_PORT_ROOT_RESET_DELAY); - if (sc->sc_dying) { - err = USBD_IOERROR; - goto ret; - } - EOWRITE4(sc, port, v); - usb_delay_ms(&sc->sc_bus, - EHCI_PORT_RESET_COMPLETE); - if (sc->sc_dying) { - err = USBD_IOERROR; - goto ret; - } - v = EOREAD4(sc, port); - DPRINTF(("ehci after reset, status=0x%08x\n", - v)); - if ((v & EHCI_PS_PR) == 0 || --retries == 0) - break; - } - - /* - * Wait up to 1 second for PR to clear. - */ - retries = 10; - while ((v & EHCI_PS_PR) && --retries > 0) { - usb_delay_ms(&sc->sc_bus, 100); - v = EOREAD4(sc, port); - } - if (v & EHCI_PS_PR) { - device_printf(sc->sc_bus.bdev, - "port reset timeout\n"); - err = USBD_TIMEOUT; - goto ret; - } - - /* - * Give up ownership if this is not a high-speed - * device after completing the reset sequence. - */ - if ((v & EHCI_PS_PE) == 0) { - ehci_disown(sc, index, 0); - break; - } - sc->sc_isreset = 1; - DPRINTF(("ehci port %d reset, status = 0x%08x\n", - index, v)); - break; - case UHF_PORT_POWER: - DPRINTFN(2,("ehci_root_ctrl_start: set port power " - "%d\n", index)); - EOWRITE4(sc, port, v | EHCI_PS_PP); - break; - case UHF_PORT_TEST: - DPRINTFN(2,("ehci_root_ctrl_start: set port test " - "%d\n", index)); - break; - case UHF_PORT_INDICATOR: - DPRINTFN(2,("ehci_root_ctrl_start: set port ind " - "%d\n", index)); - EOWRITE4(sc, port, v | EHCI_PS_PIC); - break; - default: - err = USBD_IOERROR; - goto ret; - } - break; - case C(UR_CLEAR_TT_BUFFER, UT_WRITE_CLASS_OTHER): - case C(UR_RESET_TT, UT_WRITE_CLASS_OTHER): - case C(UR_GET_TT_STATE, UT_READ_CLASS_OTHER): - case C(UR_STOP_TT, UT_WRITE_CLASS_OTHER): - break; - default: - err = USBD_IOERROR; - goto ret; - } - xfer->actlen = totlen; - err = USBD_NORMAL_COMPLETION; - ret: - xfer->status = err; - crit_enter(); - usb_transfer_complete(xfer); - crit_exit(); - return (USBD_IN_PROGRESS); -} - -void -ehci_disown(ehci_softc_t *sc, int index, int lowspeed) -{ - int port; - u_int32_t v; - - DPRINTF(("ehci_disown: index=%d lowspeed=%d\n", index, lowspeed)); -#ifdef DIAGNOSTIC - if (sc->sc_npcomp != 0) { - int i = (index-1) / sc->sc_npcomp; - if (i >= sc->sc_ncomp) - device_printf(sc->sc_bus.bdev, "strange port\n"); - else - device_printf(sc->sc_bus.bdev, - "handing over %s speed device on port %d to %s\n", - (lowspeed ? "low" : "full"), - index, device_get_nameunit(sc->sc_comps[i]->bdev)); - } else { - device_printf(sc->sc_bus.bdev, "npcomp == 0\n"); - } -#endif - port = EHCI_PORTSC(index); - v = EOREAD4(sc, port) &~ EHCI_PS_CLEAR; - EOWRITE4(sc, port, v | EHCI_PS_PO); -} - -/* Abort a root control request. */ -static void -ehci_root_ctrl_abort(usbd_xfer_handle xfer) -{ - /* Nothing to do, all transfers are synchronous. */ -} - -/* Close the root pipe. */ -static void -ehci_root_ctrl_close(usbd_pipe_handle pipe) -{ - DPRINTF(("ehci_root_ctrl_close\n")); - /* Nothing to do. */ -} - -void -ehci_root_intr_done(usbd_xfer_handle xfer) -{ -} - -static usbd_status -ehci_root_intr_transfer(usbd_xfer_handle xfer) -{ - usbd_status err; - - /* Insert last in queue. */ - err = usb_insert_transfer(xfer); - if (err) - return (err); - - /* Pipe isn't running, start first */ - return (ehci_root_intr_start(STAILQ_FIRST(&xfer->pipe->queue))); -} - -static usbd_status -ehci_root_intr_start(usbd_xfer_handle xfer) -{ - usbd_pipe_handle pipe = xfer->pipe; - ehci_softc_t *sc = (ehci_softc_t *)pipe->device->bus; - - if (sc->sc_dying) - return (USBD_IOERROR); - - sc->sc_intrxfer = xfer; - - return (USBD_IN_PROGRESS); -} - -/* Abort a root interrupt request. */ -static void -ehci_root_intr_abort(usbd_xfer_handle xfer) -{ - if (xfer->pipe->intrxfer == xfer) { - DPRINTF(("ehci_root_intr_abort: remove\n")); - xfer->pipe->intrxfer = NULL; - } - xfer->status = USBD_CANCELLED; - crit_enter(); - usb_transfer_complete(xfer); - crit_exit(); -} - -/* Close the root pipe. */ -static void -ehci_root_intr_close(usbd_pipe_handle pipe) -{ - ehci_softc_t *sc = (ehci_softc_t *)pipe->device->bus; - - DPRINTF(("ehci_root_intr_close\n")); - - sc->sc_intrxfer = NULL; -} - -void -ehci_root_ctrl_done(usbd_xfer_handle xfer) -{ -} - -/************************/ - -ehci_soft_qh_t * -ehci_alloc_sqh(ehci_softc_t *sc) -{ - ehci_soft_qh_t *sqh; - usbd_status err; - int i, offs; - usb_dma_t dma; - - if (sc->sc_freeqhs == NULL) { - DPRINTFN(2, ("ehci_alloc_sqh: allocating chunk\n")); - err = usb_allocmem(&sc->sc_bus, EHCI_SQH_SIZE * EHCI_SQH_CHUNK, - EHCI_PAGE_SIZE, &dma); -#ifdef EHCI_DEBUG - if (err) - kprintf("ehci_alloc_sqh: usb_allocmem()=%d\n", err); -#endif - if (err) - return (NULL); - for(i = 0; i < EHCI_SQH_CHUNK; i++) { - offs = i * EHCI_SQH_SIZE; - sqh = KERNADDR(&dma, offs); - sqh->physaddr = DMAADDR(&dma, offs); - sqh->next = sc->sc_freeqhs; - sc->sc_freeqhs = sqh; - } - } - sqh = sc->sc_freeqhs; - sc->sc_freeqhs = sqh->next; - memset(&sqh->qh, 0, sizeof(ehci_qh_t)); - sqh->next = NULL; - sqh->prev = NULL; - return (sqh); -} - -void -ehci_free_sqh(ehci_softc_t *sc, ehci_soft_qh_t *sqh) -{ - sqh->next = sc->sc_freeqhs; - sc->sc_freeqhs = sqh; -} - -ehci_soft_qtd_t * -ehci_alloc_sqtd(ehci_softc_t *sc) -{ - ehci_soft_qtd_t *sqtd; - usbd_status err; - int i, offs; - usb_dma_t dma; - - if (sc->sc_freeqtds == NULL) { - DPRINTFN(2, ("ehci_alloc_sqtd: allocating chunk\n")); - err = usb_allocmem(&sc->sc_bus, EHCI_SQTD_SIZE*EHCI_SQTD_CHUNK, - EHCI_PAGE_SIZE, &dma); -#ifdef EHCI_DEBUG - if (err) - kprintf("ehci_alloc_sqtd: usb_allocmem()=%d\n", err); -#endif - if (err) - return (NULL); - crit_enter(); - for(i = 0; i < EHCI_SQTD_CHUNK; i++) { - offs = i * EHCI_SQTD_SIZE; - sqtd = KERNADDR(&dma, offs); - sqtd->physaddr = DMAADDR(&dma, offs); - sqtd->nextqtd = sc->sc_freeqtds; - sc->sc_freeqtds = sqtd; - } - crit_exit(); - } - - crit_enter(); - sqtd = sc->sc_freeqtds; - sc->sc_freeqtds = sqtd->nextqtd; - memset(&sqtd->qtd, 0, sizeof(ehci_qtd_t)); - sqtd->nextqtd = NULL; - sqtd->xfer = NULL; - crit_exit(); - - return (sqtd); -} - -void -ehci_free_sqtd(ehci_softc_t *sc, ehci_soft_qtd_t *sqtd) -{ - crit_enter(); - sqtd->nextqtd = sc->sc_freeqtds; - sc->sc_freeqtds = sqtd; - crit_exit(); -} - -usbd_status -ehci_alloc_sqtd_chain(struct ehci_pipe *epipe, ehci_softc_t *sc, - int alen, int rd, usbd_xfer_handle xfer, - ehci_soft_qtd_t **sp, ehci_soft_qtd_t **ep) -{ - ehci_soft_qtd_t *next, *cur; - ehci_physaddr_t dataphys, dataphyspage, dataphyslastpage, nextphys; - u_int32_t qtdstatus; - int len, curlen, mps, offset; - int i, iscontrol; - usb_dma_t *dma = &xfer->dmabuf; - - DPRINTFN(alen<4*4096,("ehci_alloc_sqtd_chain: start len=%d\n", alen)); - - offset = 0; - len = alen; - iscontrol = (epipe->pipe.endpoint->edesc->bmAttributes & UE_XFERTYPE) == - UE_CONTROL; - dataphys = DMAADDR(dma, 0); - dataphyslastpage = EHCI_PAGE(DMAADDR(dma, len - 1)); - qtdstatus = EHCI_QTD_ACTIVE | - EHCI_QTD_SET_PID(rd ? EHCI_QTD_PID_IN : EHCI_QTD_PID_OUT) | - EHCI_QTD_SET_CERR(3) - /* IOC set below */ - /* BYTES set below */ - ; - mps = UGETW(epipe->pipe.endpoint->edesc->wMaxPacketSize); - /* - * The control transfer data stage always starts with a toggle of 1. - * For other transfers we let the hardware track the toggle state. - */ - if (iscontrol) - qtdstatus |= EHCI_QTD_SET_TOGGLE(1); - - cur = ehci_alloc_sqtd(sc); - *sp = cur; - if (cur == NULL) - goto nomem; - for (;;) { - dataphyspage = EHCI_PAGE(dataphys); - /* XXX This is pretty broken: Because we do not allocate - * a contiguous buffer (contiguous in physical pages) we - * can only transfer one page in one go. - * So check whether the start and end of the buffer are on - * the same page. - */ - if (dataphyspage == dataphyslastpage) { - curlen = len; - } - else { - /* See comment above (XXX) */ - curlen = EHCI_PAGE_SIZE - - EHCI_PAGE_MASK(dataphys); - /* the length must be a multiple of the max size */ - curlen -= curlen % mps; - DPRINTFN(1,("ehci_alloc_sqtd_chain: multiple QTDs, " - "curlen=%d\n", curlen)); - KASSERT(curlen != 0, ("ehci_alloc_std: curlen == 0")); - } - DPRINTFN(4,("ehci_alloc_sqtd_chain: dataphys=0x%08x " - "dataphyslastpage=0x%08x len=%d curlen=%d\n", - dataphys, dataphyslastpage, - len, curlen)); - len -= curlen; - - if (len != 0) { - next = ehci_alloc_sqtd(sc); - if (next == NULL) - goto nomem; - nextphys = htole32(next->physaddr); - } else { - next = NULL; - nextphys = EHCI_NULL; - } - - for (i = 0; i * EHCI_PAGE_SIZE < curlen; i++) { - ehci_physaddr_t a = dataphys + i * EHCI_PAGE_SIZE; - if (i != 0) /* use offset only in first buffer */ - a = EHCI_PAGE(a); - cur->qtd.qtd_buffer[i] = htole32(a); - cur->qtd.qtd_buffer_hi[i] = 0; -#ifdef DIAGNOSTIC - if (i >= EHCI_QTD_NBUFFERS) { - kprintf("ehci_alloc_sqtd_chain: i=%d\n", i); - goto nomem; - } -#endif - } - cur->nextqtd = next; - cur->qtd.qtd_next = cur->qtd.qtd_altnext = nextphys; - cur->qtd.qtd_status = - htole32(qtdstatus | EHCI_QTD_SET_BYTES(curlen)); - cur->xfer = xfer; - cur->len = curlen; - DPRINTFN(10,("ehci_alloc_sqtd_chain: cbp=0x%08x end=0x%08x\n", - dataphys, dataphys + curlen)); - if (iscontrol) { - /* - * adjust the toggle based on the number of packets - * in this qtd - */ - if (((curlen + mps - 1) / mps) & 1) - qtdstatus ^= EHCI_QTD_TOGGLE_MASK; - } - if (len == 0) - break; - DPRINTFN(10,("ehci_alloc_sqtd_chain: extend chain\n")); - offset += curlen; - dataphys = DMAADDR(dma, offset); - cur = next; - } - cur->qtd.qtd_status |= htole32(EHCI_QTD_IOC); - *ep = cur; - - DPRINTFN(10,("ehci_alloc_sqtd_chain: return sqtd=%p sqtdend=%p\n", - *sp, *ep)); - - return (USBD_NORMAL_COMPLETION); - - nomem: - /* XXX free chain */ - DPRINTFN(-1,("ehci_alloc_sqtd_chain: no memory\n")); - return (USBD_NOMEM); -} - -static void -ehci_free_sqtd_chain(ehci_softc_t *sc, ehci_soft_qtd_t *sqtd, - ehci_soft_qtd_t *sqtdend) -{ - ehci_soft_qtd_t *p; - int i; - - DPRINTFN(10,("ehci_free_sqtd_chain: sqtd=%p sqtdend=%p\n", - sqtd, sqtdend)); - - for (i = 0; sqtd != sqtdend; sqtd = p, i++) { - p = sqtd->nextqtd; - ehci_free_sqtd(sc, sqtd); - } -} - -/****************/ - -/* - * Close a reqular pipe. - * Assumes that there are no pending transactions. - */ -void -ehci_close_pipe(usbd_pipe_handle pipe, ehci_soft_qh_t *head) -{ - struct ehci_pipe *epipe = (struct ehci_pipe *)pipe; - ehci_softc_t *sc = (ehci_softc_t *)pipe->device->bus; - ehci_soft_qh_t *sqh = epipe->sqh; - - crit_enter(); - ehci_rem_qh(sc, sqh, head); - crit_exit(); - pipe->endpoint->savedtoggle = - EHCI_QTD_GET_TOGGLE(le32toh(sqh->qh.qh_qtd.qtd_status)); - ehci_free_sqh(sc, epipe->sqh); - epipe->sqh = NULL; -} - -/* - * Abort a device request. - * If this routine is called from a critical section it guarantees that the - * request will be removed from the hardware scheduling and that the callback - * for it will be called with USBD_CANCELLED status. - * It's impossible to guarantee that the requested transfer will not - * have happened since the hardware runs concurrently. - * If the transaction has already happened we rely on the ordinary - * interrupt processing to process it. - * XXX This is most probably wrong. - */ -void -ehci_abort_xfer(usbd_xfer_handle xfer, usbd_status status) -{ -#define exfer EXFER(xfer) - struct ehci_pipe *epipe = (struct ehci_pipe *)xfer->pipe; - ehci_softc_t *sc = (ehci_softc_t *)epipe->pipe.device->bus; - ehci_soft_qh_t *sqh = epipe->sqh; - ehci_soft_qtd_t *sqtd, *snext, **psqtd; - ehci_physaddr_t cur, us, next; - int hit; - /* int count = 0; */ - ehci_soft_qh_t *psqh; - - DPRINTF(("ehci_abort_xfer: xfer=%p pipe=%p\n", xfer, epipe)); - - if (sc->sc_dying) { - /* If we're dying, just do the software part. */ - crit_enter(); - xfer->status = status; /* make software ignore it */ - callout_stop(&xfer->timeout_handle); - usb_rem_task(epipe->pipe.device, &exfer->abort_task); - usb_transfer_complete(xfer); - crit_exit(); - return; - } - -#if 0 - if (xfer->device->bus->intr_context /* || !curproc REMOVED DFly */) - panic("ehci_abort_xfer: not in process context"); -#endif - - /* - * If an abort is already in progress then just wait for it to - * complete and return. - */ - if (exfer->ehci_xfer_flags & EHCI_XFER_ABORTING) { - DPRINTFN(2, ("ehci_abort_xfer: already aborting\n")); - /* No need to wait if we're aborting from a timeout. */ - if (status == USBD_TIMEOUT) - return; - /* Override the status which might be USBD_TIMEOUT. */ - xfer->status = status; - DPRINTFN(2, ("ehci_abort_xfer: waiting for abort to finish\n")); - exfer->ehci_xfer_flags |= EHCI_XFER_ABORTWAIT; - while (exfer->ehci_xfer_flags & EHCI_XFER_ABORTING) - tsleep(&exfer->ehci_xfer_flags, 0, "ehciaw", 0); - return; - } - - /* - * Step 1: Make interrupt routine and timeouts ignore xfer. - */ - crit_enter(); - exfer->ehci_xfer_flags |= EHCI_XFER_ABORTING; - xfer->status = status; /* make software ignore it */ - callout_stop(&xfer->timeout_handle); - usb_rem_task(epipe->pipe.device, &exfer->abort_task); - crit_exit(); - - /* - * Step 2: Wait until we know hardware has finished any possible - * use of the xfer. We do this by removing the entire - * queue from the async schedule and waiting for the doorbell. - * Nothing else should be touching the queue now. - */ - psqh = sqh->prev; - ehci_rem_qh(sc, sqh, psqh); - - /* - * Step 3: make sure the soft interrupt routine - * has run. This should remove any completed items off the queue. - * The hardware has no reference to completed items (TDs). - * It's safe to remove them at any time. - */ - crit_enter(); -#ifdef USB_USE_SOFTINTR - sc->sc_softwake = 1; -#endif /* USB_USE_SOFTINTR */ - usb_schedsoftintr(&sc->sc_bus); -#ifdef USB_USE_SOFTINTR - tsleep(&sc->sc_softwake, 0, "ehciab", 0); -#endif /* USB_USE_SOFTINTR */ - - /* - * Step 4: Remove any vestiges of the xfer from the hardware. - * The complication here is that the hardware may have executed - * into or even beyond the xfer we're trying to abort. - * So as we're scanning the TDs of this xfer we check if - * the hardware points to any of them. - * - * first we need to see if there are any transfers - * on this queue before the xfer we are aborting.. we need - * to update any pointers that point to us to point past - * the aborting xfer. (If there is something past us). - * Hardware and software. - */ - cur = EHCI_LINK_ADDR(le32toh(sqh->qh.qh_curqtd)); - hit = 0; - - /* If they initially point here. */ - us = exfer->sqtdstart->physaddr; - - /* We will change them to point here */ - snext = exfer->sqtdend->nextqtd; - next = snext ? htole32(snext->physaddr) : EHCI_NULL; - - /* - * Now loop through any qTDs before us and keep track of the pointer - * that points to us for the end. - */ - psqtd = &sqh->sqtd; - sqtd = sqh->sqtd; - while (sqtd && sqtd != exfer->sqtdstart) { - hit |= (cur == sqtd->physaddr); - if (EHCI_LINK_ADDR(le32toh(sqtd->qtd.qtd_next)) == us) - sqtd->qtd.qtd_next = next; - if (EHCI_LINK_ADDR(le32toh(sqtd->qtd.qtd_altnext)) == us) - sqtd->qtd.qtd_altnext = next; - psqtd = &sqtd->nextqtd; - sqtd = sqtd->nextqtd; - } - /* make the software pointer bypass us too */ - *psqtd = exfer->sqtdend->nextqtd; - - /* - * If we already saw the active one then we are pretty much done. - * We've done all the relinking we need to do. - */ - if (!hit) { - - /* - * Now reinitialise the QH to point to the next qTD - * (if there is one). We only need to do this if - * it was previously pointing to us. - */ - for (sqtd = exfer->sqtdstart; ; sqtd = sqtd->nextqtd) { - if (cur == sqtd->physaddr) { - hit++; - } - if (sqtd == exfer->sqtdend) - break; - } - sqtd = sqtd->nextqtd; - /* - * Only need to alter the QH if it was pointing at a qTD - * that we are removing. - */ - if (hit) { - if (snext) { - ehci_set_qh_qtd(sqh, snext); - } else { - - sqh->qh.qh_curqtd = 0; /* unlink qTDs */ - sqh->qh.qh_qtd.qtd_status &= - htole32(EHCI_QTD_TOGGLE_MASK); - sqh->qh.qh_qtd.qtd_next = - sqh->qh.qh_qtd.qtd_altnext - = EHCI_NULL; - DPRINTFN(1,("ehci_abort_xfer: no hit\n")); - } - } - } - ehci_add_qh(sqh, psqh); - /* - * Step 5: Execute callback. - */ -#ifdef DIAGNOSTIC - exfer->isdone = 1; -#endif - /* Do the wakeup first to avoid touching the xfer after the callback. */ - exfer->ehci_xfer_flags &= ~EHCI_XFER_ABORTING; - if (exfer->ehci_xfer_flags & EHCI_XFER_ABORTWAIT) { - exfer->ehci_xfer_flags &= ~EHCI_XFER_ABORTWAIT; - wakeup(&exfer->ehci_xfer_flags); - } - usb_transfer_complete(xfer); - - /* kprintf("%s: %d TDs aborted\n", __func__, count); */ - crit_exit(); -#undef exfer -} - -void -ehci_timeout(void *addr) -{ - struct ehci_xfer *exfer = addr; - struct ehci_pipe *epipe = (struct ehci_pipe *)exfer->xfer.pipe; - ehci_softc_t *sc = (ehci_softc_t *)epipe->pipe.device->bus; - - DPRINTF(("ehci_timeout: exfer=%p\n", exfer)); -#ifdef USB_DEBUG - if (ehcidebug > 1) - usbd_dump_pipe(exfer->xfer.pipe); -#endif - - if (sc->sc_dying) { - ehci_abort_xfer(&exfer->xfer, USBD_TIMEOUT); - return; - } - - /* Execute the abort in a process context. */ - usb_add_task(exfer->xfer.pipe->device, &exfer->abort_task, - USB_TASKQ_HC); -} - -void -ehci_timeout_task(void *addr) -{ - usbd_xfer_handle xfer = addr; - - DPRINTF(("ehci_timeout_task: xfer=%p\n", xfer)); - crit_enter(); - ehci_abort_xfer(xfer, USBD_TIMEOUT); - crit_exit(); -} - -/* - * Some EHCI chips from VIA / ATI seem to trigger interrupts before writing - * back the qTD status, or miss signalling occasionally under heavy load. - * If the host machine is too fast, we can miss transaction completion - when - * we scan the active list the transaction still seems to be active. This - * generally exhibits itself as a umass stall that never recovers. - * - * We work around this behaviour by setting up this callback after any softintr - * that completes with transactions still pending, giving us another chance to - * check for completion after the writeback has taken place. - */ -void -ehci_intrlist_timeout(void *arg) -{ - ehci_softc_t *sc = arg; - - DPRINTFN(3, ("ehci_intrlist_timeout\n")); - usb_schedsoftintr(&sc->sc_bus); -} - -/************************/ - -static usbd_status -ehci_device_ctrl_transfer(usbd_xfer_handle xfer) -{ - usbd_status err; - - /* Insert last in queue. */ - err = usb_insert_transfer(xfer); - if (err) - return (err); - - /* Pipe isn't running, start first */ - return (ehci_device_ctrl_start(STAILQ_FIRST(&xfer->pipe->queue))); -} - -static usbd_status -ehci_device_ctrl_start(usbd_xfer_handle xfer) -{ - ehci_softc_t *sc = (ehci_softc_t *)xfer->pipe->device->bus; - usbd_status err; - - if (sc->sc_dying) - return (USBD_IOERROR); - -#ifdef DIAGNOSTIC - if (!(xfer->rqflags & URQ_REQUEST)) { - /* XXX panic */ - kprintf("ehci_device_ctrl_transfer: not a request\n"); - return (USBD_INVAL); - } -#endif - - err = ehci_device_request(xfer); - if (err) - return (err); - - if (sc->sc_bus.use_polling) - ehci_waitintr(sc, xfer); - return (USBD_IN_PROGRESS); -} - -void -ehci_device_ctrl_done(usbd_xfer_handle xfer) -{ - struct ehci_xfer *ex = EXFER(xfer); - ehci_softc_t *sc = (ehci_softc_t *)xfer->pipe->device->bus; - /*struct ehci_pipe *epipe = (struct ehci_pipe *)xfer->pipe;*/ - - DPRINTFN(10,("ehci_ctrl_done: xfer=%p\n", xfer)); - -#ifdef DIAGNOSTIC - if (!(xfer->rqflags & URQ_REQUEST)) { - panic("ehci_ctrl_done: not a request"); - } -#endif - - if (xfer->status != USBD_NOMEM && ehci_active_intr_list(ex)) { - ehci_del_intr_list(ex); /* remove from active list */ - ehci_free_sqtd_chain(sc, ex->sqtdstart, NULL); - } - - DPRINTFN(5, ("ehci_ctrl_done: length=%d\n", xfer->actlen)); -} - -/* Abort a device control request. */ -static void -ehci_device_ctrl_abort(usbd_xfer_handle xfer) -{ - DPRINTF(("ehci_device_ctrl_abort: xfer=%p\n", xfer)); - ehci_abort_xfer(xfer, USBD_CANCELLED); -} - -/* Close a device control pipe. */ -static void -ehci_device_ctrl_close(usbd_pipe_handle pipe) -{ - ehci_softc_t *sc = (ehci_softc_t *)pipe->device->bus; - /*struct ehci_pipe *epipe = (struct ehci_pipe *)pipe;*/ - - DPRINTF(("ehci_device_ctrl_close: pipe=%p\n", pipe)); - ehci_close_pipe(pipe, sc->sc_async_head); -} - -usbd_status -ehci_device_request(usbd_xfer_handle xfer) -{ -#define exfer EXFER(xfer) - struct ehci_pipe *epipe = (struct ehci_pipe *)xfer->pipe; - usb_device_request_t *req = &xfer->request; - usbd_device_handle dev = epipe->pipe.device; - ehci_softc_t *sc = (ehci_softc_t *)dev->bus; - ehci_soft_qtd_t *setup, *stat, *next; - ehci_soft_qh_t *sqh; - int isread; - int len; - int addr = dev->address; - usbd_status err; - - isread = req->bmRequestType & UT_READ; - len = UGETW(req->wLength); - - DPRINTFN(3,("ehci_device_request: type=0x%02x, request=0x%02x, " - "wValue=0x%04x, wIndex=0x%04x len=%d, addr=%d, endpt=%d\n", - req->bmRequestType, req->bRequest, UGETW(req->wValue), - UGETW(req->wIndex), len, dev->address, - epipe->pipe.endpoint->edesc->bEndpointAddress)); - - setup = ehci_alloc_sqtd(sc); - if (setup == NULL) { - err = USBD_NOMEM; - goto bad1; - } - stat = ehci_alloc_sqtd(sc); - if (stat == NULL) { - err = USBD_NOMEM; - goto bad2; - } - - sqh = epipe->sqh; - epipe->u.ctl.length = len; - -#if 1 - /* Update device address and length since they may have changed - during the setup of the control pipe in usbd_new_device(). */ - /* XXX This only needs to be done once, but it's too early in open. */ - /* XXXX Should not touch ED here! */ - sqh->qh.qh_endp = - (sqh->qh.qh_endp & htole32(~(EHCI_QH_ADDRMASK | EHCI_QH_MPLMASK))) | - htole32( - EHCI_QH_SET_ADDR(addr) | - EHCI_QH_SET_MPL(UGETW(epipe->pipe.endpoint->edesc->wMaxPacketSize)) - ); -#endif - - /* Set up data transaction */ - if (len != 0) { - ehci_soft_qtd_t *end; - - err = ehci_alloc_sqtd_chain(epipe, sc, len, isread, xfer, - &next, &end); - if (err) - goto bad3; - end->qtd.qtd_status &= htole32(~EHCI_QTD_IOC); - end->nextqtd = stat; - end->qtd.qtd_next = - end->qtd.qtd_altnext = htole32(stat->physaddr); - } else { - next = stat; - } - - memcpy(KERNADDR(&epipe->u.ctl.reqdma, 0), req, sizeof *req); - - /* Clear toggle */ - setup->qtd.qtd_status = htole32( - EHCI_QTD_ACTIVE | - EHCI_QTD_SET_PID(EHCI_QTD_PID_SETUP) | - EHCI_QTD_SET_CERR(3) | - EHCI_QTD_SET_TOGGLE(0) | - EHCI_QTD_SET_BYTES(sizeof *req) - ); - setup->qtd.qtd_buffer[0] = htole32(DMAADDR(&epipe->u.ctl.reqdma, 0)); - setup->qtd.qtd_buffer_hi[0] = 0; - setup->nextqtd = next; - setup->qtd.qtd_next = setup->qtd.qtd_altnext = htole32(next->physaddr); - setup->xfer = xfer; - setup->len = sizeof *req; - - stat->qtd.qtd_status = htole32( - EHCI_QTD_ACTIVE | - EHCI_QTD_SET_PID(isread ? EHCI_QTD_PID_OUT : EHCI_QTD_PID_IN) | - EHCI_QTD_SET_CERR(3) | - EHCI_QTD_SET_TOGGLE(1) | - EHCI_QTD_IOC - ); - stat->qtd.qtd_buffer[0] = 0; /* XXX not needed? */ - stat->qtd.qtd_buffer_hi[0] = 0; /* XXX not needed? */ - stat->nextqtd = NULL; - stat->qtd.qtd_next = stat->qtd.qtd_altnext = EHCI_NULL; - stat->xfer = xfer; - stat->len = 0; - -#ifdef EHCI_DEBUG - if (ehcidebug > 5) { - DPRINTF(("ehci_device_request:\n")); - ehci_dump_sqh(sqh); - ehci_dump_sqtds(setup); - } -#endif - - exfer->sqtdstart = setup; - exfer->sqtdend = stat; -#ifdef DIAGNOSTIC - if (!exfer->isdone) { - kprintf("ehci_device_request: not done, exfer=%p\n", exfer); - } - exfer->isdone = 0; -#endif - - /* Insert qTD in QH list. */ - crit_enter(); - ehci_set_qh_qtd(sqh, setup); - if (xfer->timeout && !sc->sc_bus.use_polling) { - callout_reset(&xfer->timeout_handle, MS_TO_TICKS(xfer->timeout), - ehci_timeout, xfer); - } - ehci_add_intr_list(sc, exfer); - xfer->status = USBD_IN_PROGRESS; - crit_exit(); - -#ifdef EHCI_DEBUG - if (ehcidebug > 10) { - DPRINTF(("ehci_device_request: status=%x\n", - EOREAD4(sc, EHCI_USBSTS))); - DELAY(10000); - ehci_dump_regs(sc); - ehci_dump_sqh(sc->sc_async_head); - ehci_dump_sqh(sqh); - ehci_dump_sqtds(setup); - } -#endif - - return (USBD_NORMAL_COMPLETION); - - bad3: - ehci_free_sqtd(sc, stat); - bad2: - ehci_free_sqtd(sc, setup); - bad1: - DPRINTFN(-1,("ehci_device_request: no memory\n")); - xfer->status = err; - usb_transfer_complete(xfer); - return (err); -#undef exfer -} - -/************************/ - -static usbd_status -ehci_device_bulk_transfer(usbd_xfer_handle xfer) -{ - usbd_status err; - - /* Insert last in queue. */ - err = usb_insert_transfer(xfer); - if (err) - return (err); - - /* Pipe isn't running, start first */ - return (ehci_device_bulk_start(STAILQ_FIRST(&xfer->pipe->queue))); -} - -usbd_status -ehci_device_bulk_start(usbd_xfer_handle xfer) -{ -#define exfer EXFER(xfer) - struct ehci_pipe *epipe = (struct ehci_pipe *)xfer->pipe; - usbd_device_handle dev = epipe->pipe.device; - ehci_softc_t *sc = (ehci_softc_t *)dev->bus; - ehci_soft_qtd_t *data, *dataend; - ehci_soft_qh_t *sqh; - usbd_status err; - int len, isread, endpt; - - DPRINTFN(2, ("ehci_device_bulk_start: xfer=%p len=%d flags=%d\n", - xfer, xfer->length, xfer->flags)); - - if (sc->sc_dying) - return (USBD_IOERROR); - -#ifdef DIAGNOSTIC - if (xfer->rqflags & URQ_REQUEST) - panic("ehci_device_bulk_start: a request"); -#endif - - len = xfer->length; - endpt = epipe->pipe.endpoint->edesc->bEndpointAddress; - isread = UE_GET_DIR(endpt) == UE_DIR_IN; - sqh = epipe->sqh; - - epipe->u.bulk.length = len; - - err = ehci_alloc_sqtd_chain(epipe, sc, len, isread, xfer, &data, - &dataend); - if (err) { - DPRINTFN(-1,("ehci_device_bulk_start: no memory\n")); - xfer->status = err; - usb_transfer_complete(xfer); - return (err); - } - -#ifdef EHCI_DEBUG - if (ehcidebug > 5) { - DPRINTF(("ehci_device_bulk_start: data(1)\n")); - ehci_dump_sqh(sqh); - ehci_dump_sqtds(data); - } -#endif - - /* Set up interrupt info. */ - exfer->sqtdstart = data; - exfer->sqtdend = dataend; -#ifdef DIAGNOSTIC - if (!exfer->isdone) { - kprintf("ehci_device_bulk_start: not done, ex=%p\n", exfer); - } - exfer->isdone = 0; -#endif - - crit_enter(); - ehci_set_qh_qtd(sqh, data); - if (xfer->timeout && !sc->sc_bus.use_polling) { - callout_reset(&xfer->timeout_handle, MS_TO_TICKS(xfer->timeout), - ehci_timeout, xfer); - } - ehci_add_intr_list(sc, exfer); - xfer->status = USBD_IN_PROGRESS; - crit_exit(); - -#ifdef EHCI_DEBUG - if (ehcidebug > 10) { - DPRINTF(("ehci_device_bulk_start: data(2)\n")); - DELAY(10000); - DPRINTF(("ehci_device_bulk_start: data(3)\n")); - ehci_dump_regs(sc); -#if 0 - kprintf("async_head:\n"); - ehci_dump_sqh(sc->sc_async_head); -#endif - kprintf("sqh:\n"); - ehci_dump_sqh(sqh); - ehci_dump_sqtds(data); - } -#endif - - if (sc->sc_bus.use_polling) - ehci_waitintr(sc, xfer); - - return (USBD_IN_PROGRESS); -#undef exfer -} - -static void -ehci_device_bulk_abort(usbd_xfer_handle xfer) -{ - DPRINTF(("ehci_device_bulk_abort: xfer=%p\n", xfer)); - ehci_abort_xfer(xfer, USBD_CANCELLED); -} - -/* - * Close a device bulk pipe. - */ -static void -ehci_device_bulk_close(usbd_pipe_handle pipe) -{ - ehci_softc_t *sc = (ehci_softc_t *)pipe->device->bus; - - DPRINTF(("ehci_device_bulk_close: pipe=%p\n", pipe)); - ehci_close_pipe(pipe, sc->sc_async_head); -} - -void -ehci_device_bulk_done(usbd_xfer_handle xfer) -{ - struct ehci_xfer *ex = EXFER(xfer); - ehci_softc_t *sc = (ehci_softc_t *)xfer->pipe->device->bus; - /*struct ehci_pipe *epipe = (struct ehci_pipe *)xfer->pipe;*/ - - DPRINTFN(10,("ehci_bulk_done: xfer=%p, actlen=%d\n", - xfer, xfer->actlen)); - - if (xfer->status != USBD_NOMEM && ehci_active_intr_list(ex)) { - ehci_del_intr_list(ex); /* remove from active list */ - ehci_free_sqtd_chain(sc, ex->sqtdstart, NULL); - } - - DPRINTFN(5, ("ehci_bulk_done: length=%d\n", xfer->actlen)); -} - -/************************/ - -static usbd_status -ehci_device_setintr(ehci_softc_t *sc, ehci_soft_qh_t *sqh, int ival) -{ - struct ehci_soft_islot *isp; - int islot, lev; - - /* Find a poll rate that is large enough. */ - for (lev = EHCI_IPOLLRATES - 1; lev > 0; lev--) - if (EHCI_ILEV_IVAL(lev) <= ival) - break; - - /* Pick an interrupt slot at the right level. */ - /* XXX could do better than picking at random. */ - islot = EHCI_IQHIDX(lev, karc4random()); - - sqh->islot = islot; - isp = &sc->sc_islots[islot]; - ehci_add_qh(sqh, isp->sqh); - - return (USBD_NORMAL_COMPLETION); -} - -static usbd_status -ehci_device_intr_transfer(usbd_xfer_handle xfer) -{ - usbd_status err; - - /* Insert last in queue. */ - err = usb_insert_transfer(xfer); - if (err) - return (err); - - /* - * Pipe isn't running (otherwise err would be USBD_INPROG), - * so start it first. - */ - return (ehci_device_intr_start(STAILQ_FIRST(&xfer->pipe->queue))); -} - -static usbd_status -ehci_device_intr_start(usbd_xfer_handle xfer) -{ -#define exfer EXFER(xfer) - struct ehci_pipe *epipe = (struct ehci_pipe *)xfer->pipe; - usbd_device_handle dev = xfer->pipe->device; - ehci_softc_t *sc = (ehci_softc_t *)dev->bus; - ehci_soft_qtd_t *data, *dataend; - ehci_soft_qh_t *sqh; - usbd_status err; - int len, isread, endpt; - - DPRINTFN(2, ("ehci_device_intr_start: xfer=%p len=%d flags=%d\n", - xfer, xfer->length, xfer->flags)); - - if (sc->sc_dying) - return (USBD_IOERROR); - -#ifdef DIAGNOSTIC - if (xfer->rqflags & URQ_REQUEST) - panic("ehci_device_intr_start: a request"); -#endif - - len = xfer->length; - endpt = epipe->pipe.endpoint->edesc->bEndpointAddress; - isread = UE_GET_DIR(endpt) == UE_DIR_IN; - sqh = epipe->sqh; - - epipe->u.intr.length = len; - - err = ehci_alloc_sqtd_chain(epipe, sc, len, isread, xfer, &data, - &dataend); - if (err) { - DPRINTFN(-1, ("ehci_device_intr_start: no memory\n")); - xfer->status = err; - usb_transfer_complete(xfer); - return (err); - } - -#ifdef EHCI_DEBUG - if (ehcidebug > 5) { - DPRINTF(("ehci_device_intr_start: data(1)\n")); - ehci_dump_sqh(sqh); - ehci_dump_sqtds(data); - } -#endif - - /* Set up interrupt info. */ - exfer->sqtdstart = data; - exfer->sqtdend = dataend; -#ifdef DIAGNOSTIC - if (!exfer->isdone) { - kprintf("ehci_device_intr_start: not done, ex=%p\n", exfer); - } - exfer->isdone = 0; -#endif - - crit_enter(); - ehci_set_qh_qtd(sqh, data); - if (xfer->timeout && !sc->sc_bus.use_polling) { - callout_reset(&xfer->timeout_handle, MS_TO_TICKS(xfer->timeout), - ehci_timeout, xfer); - } - ehci_add_intr_list(sc, exfer); - xfer->status = USBD_IN_PROGRESS; - crit_exit(); - -#ifdef EHCI_DEBUG - if (ehcidebug > 10) { - DPRINTF(("ehci_device_intr_start: data(2)\n")); - DELAY(10000); - DPRINTF(("ehci_device_intr_start: data(3)\n")); - ehci_dump_regs(sc); - kprintf("sqh:\n"); - ehci_dump_sqh(sqh); - ehci_dump_sqtds(data); - } -#endif - - if (sc->sc_bus.use_polling) - ehci_waitintr(sc, xfer); - - return (USBD_IN_PROGRESS); -#undef exfer -} - -static void -ehci_device_intr_abort(usbd_xfer_handle xfer) -{ - DPRINTFN(1, ("ehci_device_intr_abort: xfer=%p\n", xfer)); - if (xfer->pipe->intrxfer == xfer) { - DPRINTFN(1, ("ehci_device_intr_abort: remove\n")); - xfer->pipe->intrxfer = NULL; - } - ehci_abort_xfer(xfer, USBD_CANCELLED); -} - -static void -ehci_device_intr_close(usbd_pipe_handle pipe) -{ - ehci_softc_t *sc = (ehci_softc_t *)pipe->device->bus; - struct ehci_pipe *epipe = (struct ehci_pipe *)pipe; - struct ehci_soft_islot *isp; - - isp = &sc->sc_islots[epipe->sqh->islot]; - ehci_close_pipe(pipe, isp->sqh); -} - -static void -ehci_device_intr_done(usbd_xfer_handle xfer) -{ -#define exfer EXFER(xfer) - struct ehci_xfer *ex = EXFER(xfer); - ehci_softc_t *sc = (ehci_softc_t *)xfer->pipe->device->bus; - struct ehci_pipe *epipe = (struct ehci_pipe *)xfer->pipe; - ehci_soft_qtd_t *data, *dataend; - ehci_soft_qh_t *sqh; - usbd_status err; - int len, isread, endpt; - - DPRINTFN(10, ("ehci_device_intr_done: xfer=%p, actlen=%d\n", - xfer, xfer->actlen)); - - if (xfer->pipe->repeat) { - ehci_free_sqtd_chain(sc, ex->sqtdstart, NULL); - - len = epipe->u.intr.length; - xfer->length = len; - endpt = epipe->pipe.endpoint->edesc->bEndpointAddress; - isread = UE_GET_DIR(endpt) == UE_DIR_IN; - sqh = epipe->sqh; - - err = ehci_alloc_sqtd_chain(epipe, sc, len, isread, xfer, - &data, &dataend); - if (err) { - DPRINTFN(-1, ("ehci_device_intr_done: no memory\n")); - xfer->status = err; - return; - } - - /* Set up interrupt info. */ - exfer->sqtdstart = data; - exfer->sqtdend = dataend; -#ifdef DIAGNOSTIC - if (!exfer->isdone) { - kprintf("ehci_device_intr_done: not done, ex=%p\n", - exfer); - } - exfer->isdone = 0; -#endif - - crit_enter(); - ehci_set_qh_qtd(sqh, data); - if (xfer->timeout && !sc->sc_bus.use_polling) { - callout_reset(&xfer->timeout_handle, - MS_TO_TICKS(xfer->timeout), ehci_timeout, xfer); - } - crit_exit(); - - xfer->status = USBD_IN_PROGRESS; - } else if (xfer->status != USBD_NOMEM && ehci_active_intr_list(ex)) { - ehci_del_intr_list(ex); /* remove from active list */ - ehci_free_sqtd_chain(sc, ex->sqtdstart, NULL); - } -#undef exfer -} - -/************************/ - -static usbd_status -ehci_device_isoc_transfer(usbd_xfer_handle xfer) -{ - return USBD_IOERROR; -} - -static usbd_status -ehci_device_isoc_start(usbd_xfer_handle xfer) -{ - return USBD_IOERROR; -} - -static void -ehci_device_isoc_abort(usbd_xfer_handle xfer) -{ -} - -static void -ehci_device_isoc_close(usbd_pipe_handle pipe) -{ -} - -static void -ehci_device_isoc_done(usbd_xfer_handle xfer) -{ -} - -MODULE_DEPEND(ehci, usb, 1, 1, 1); diff --git a/sys/bus/usb/ehci/Makefile b/sys/bus/usb/ehci/Makefile deleted file mode 100644 index 1d3b059a16..0000000000 --- a/sys/bus/usb/ehci/Makefile +++ /dev/null @@ -1,11 +0,0 @@ -# Makefile for EHCI module - -.PATH: ${.CURDIR}/.. -KMOD= ehci -SRCS= ehci.c ehci_pci.c \ - opt_usb.h \ - bus_if.h device_if.h pci_if.h - -CFLAGS+= -I${.OBJDIR}/.. - -.include diff --git a/sys/bus/usb/ehci_pci.c b/sys/bus/usb/ehci_pci.c deleted file mode 100644 index 0214909354..0000000000 --- a/sys/bus/usb/ehci_pci.c +++ /dev/null @@ -1,569 +0,0 @@ -/* - * Copyright (c) 1998 The NetBSD Foundation, Inc. - * All rights reserved. - * - * This code is derived from software contributed to The NetBSD Foundation - * by Lennart Augustsson (augustss@carlstedt.se) at - * Carlstedt Research & Technology. - * - * 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. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the NetBSD - * Foundation, Inc. and its contributors. - * 4. Neither the name of The NetBSD Foundation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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: src/sys/dev/usb/ehci_pci.c,v 1.18.2.1 2006/01/26 01:43:13 iedowse Exp $ - */ - -/* - * USB Enhanced Host Controller Driver, a.k.a. USB 2.0 controller. - * - * The EHCI 1.0 spec can be found at - * http://developer.intel.com/technology/usb/download/ehci-r10.pdf - * and the USB 2.0 spec at - * http://www.usb.org/developers/docs/usb_20.zip - */ - -/* The low level controller code for EHCI has been split into - * PCI probes and EHCI specific code. This was done to facilitate the - * sharing of code between *BSD's - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include -#include -#include - -#include -#include - -#define PCI_EHCI_VENDORID_ACERLABS 0x10b9 -#define PCI_EHCI_VENDORID_AMD 0x1022 -#define PCI_EHCI_VENDORID_APPLE 0x106b -#define PCI_EHCI_VENDORID_ATI 0x1002 -#define PCI_EHCI_VENDORID_CMDTECH 0x1095 -#define PCI_EHCI_VENDORID_INTEL 0x8086 -#define PCI_EHCI_VENDORID_NEC 0x1033 -#define PCI_EHCI_VENDORID_OPTI 0x1045 -#define PCI_EHCI_VENDORID_PHILIPS 0x1131 -#define PCI_EHCI_VENDORID_SIS 0x1039 -#define PCI_EHCI_VENDORID_NVIDIA 0x12D2 -#define PCI_EHCI_VENDORID_NVIDIA2 0x10DE -#define PCI_EHCI_VENDORID_VIA 0x1106 - -/* AcerLabs/ALi */ -#define PCI_EHCI_DEVICEID_M5239 0x523910b9 -static const char *ehci_device_m5239 = "ALi M5239 USB 2.0 controller"; - -/* AMD */ -#define PCI_EHCI_DEVICEID_8111 0x74631022 -#define PCI_EHCI_DEVICEID_CS5536 0x20951022 -static const char *ehci_device_8111 = "AMD 8111 USB 2.0 controller"; -static const char *ehci_device_CS5536 = "AMD CS5536 USB 2.0 controller"; - -/* ATI */ -#define PCI_EHCI_DEVICEID_SB200 0x43451002 -static const char *ehci_device_sb200 = "ATI SB200 USB 2.0 controller"; -#define PCI_EHCI_DEVICEID_SB400 0x43731002 -static const char *ehci_device_sb400 = "ATI SB400 USB 2.0 controller"; - -/* Intel */ -#define PCI_EHCI_DEVICEID_6300 0x25ad8086 -static const char *ehci_device_6300 = "Intel 6300ESB USB 2.0 controller"; -#define PCI_EHCI_DEVICEID_ICH4 0x24cd8086 -static const char *ehci_device_ich4 = "Intel 82801DB/L/M USB 2.0 controller"; -#define PCI_EHCI_DEVICEID_ICH5 0x24dd8086 -static const char *ehci_device_ich5 = "Intel 82801EB/R USB 2.0 controller"; -#define PCI_EHCI_DEVICEID_ICH6 0x265c8086 -static const char *ehci_device_ich6 = "Intel 82801FB USB 2.0 controller"; -#define PCI_EHCI_DEVICEID_ICH7 0x27cc8086 -static const char *ehci_device_ich7 = "Intel 82801GB/R USB 2.0 controller"; - -/* NEC */ -#define PCI_EHCI_DEVICEID_NEC 0x00e01033 -static const char *ehci_device_nec = "NEC uPD 720100 USB 2.0 controller"; - -/* NVIDIA */ -#define PCI_EHCI_DEVICEID_NF2 0x006810de -static const char *ehci_device_nf2 = "NVIDIA nForce2 USB 2.0 controller"; -#define PCI_EHCI_DEVICEID_NF2_400 0x008810de -static const char *ehci_device_nf2_400 = "NVIDIA nForce2 Ultra 400 USB 2.0 controller"; -#define PCI_EHCI_DEVICEID_NF3 0x00d810de -static const char *ehci_device_nf3 = "NVIDIA nForce3 USB 2.0 controller"; -#define PCI_EHCI_DEVICEID_NF3_250 0x00e810de -static const char *ehci_device_nf3_250 = "NVIDIA nForce3 250 USB 2.0 controller"; -#define PCI_EHCI_DEVICEID_NF4 0x005b10de -static const char *ehci_device_nf4 = "NVIDIA nForce4 USB 2.0 controller"; - -/* Philips */ -#define PCI_EHCI_DEVICEID_ISP156X 0x15621131 -static const char *ehci_device_isp156x = "Philips ISP156x USB 2.0 controller"; - -/* VIA */ -#define PCI_EHCI_DEVICEID_VIA 0x31041106 -static const char *ehci_device_via = "VIA VT6202 USB 2.0 controller"; - -/* Generic */ -static const char *ehci_device_generic = "EHCI (generic) USB 2.0 controller"; - -#define PCI_EHCI_BASE_REG 0x10 - -#ifdef USB_DEBUG -#define EHCI_DEBUG USB_DEBUG -#define DPRINTF(x) do { if (ehcidebug) kprintf x; } while (0) -extern int ehcidebug; -#else -#define DPRINTF(x) -#endif - -static int ehci_pci_attach(device_t self); -static int ehci_pci_detach(device_t self); -static int ehci_pci_shutdown(device_t self); -static int ehci_pci_suspend(device_t self); -static int ehci_pci_resume(device_t self); -static void ehci_pci_givecontroller(device_t self); -static void ehci_pci_takecontroller(device_t self); - -static int -ehci_pci_suspend(device_t self) -{ - ehci_softc_t *sc = device_get_softc(self); - int err; - - err = bus_generic_suspend(self); - if (err) - return (err); - ehci_power(PWR_SUSPEND, sc); - - return 0; -} - -static int -ehci_pci_resume(device_t self) -{ - ehci_softc_t *sc = device_get_softc(self); - - ehci_pci_takecontroller(self); - ehci_power(PWR_RESUME, sc); - bus_generic_resume(self); - - return 0; -} - -static int -ehci_pci_shutdown(device_t self) -{ - ehci_softc_t *sc = device_get_softc(self); - int err; - - err = bus_generic_shutdown(self); - if (sc->sc_flags & EHCI_SCFLG_DONEINIT) { - ehci_shutdown(sc); - ehci_pci_givecontroller(self); - } - - return err; -} - -static const char * -ehci_pci_match(device_t self) -{ - u_int32_t device_id = pci_get_devid(self); - - switch (device_id) { - case PCI_EHCI_DEVICEID_M5239: - return (ehci_device_m5239); - case PCI_EHCI_DEVICEID_8111: - return (ehci_device_8111); - case PCI_EHCI_DEVICEID_CS5536: - return (ehci_device_CS5536); - case PCI_EHCI_DEVICEID_SB200: - return (ehci_device_sb200); - case PCI_EHCI_DEVICEID_SB400: - return (ehci_device_sb400); - case PCI_EHCI_DEVICEID_6300: - return (ehci_device_6300); - case PCI_EHCI_DEVICEID_ICH4: - return (ehci_device_ich4); - case PCI_EHCI_DEVICEID_ICH5: - return (ehci_device_ich5); - case PCI_EHCI_DEVICEID_ICH6: - return (ehci_device_ich6); - case PCI_EHCI_DEVICEID_ICH7: - return (ehci_device_ich7); - case PCI_EHCI_DEVICEID_NEC: - return (ehci_device_nec); - case PCI_EHCI_DEVICEID_NF2: - return (ehci_device_nf2); - case PCI_EHCI_DEVICEID_NF2_400: - return (ehci_device_nf2_400); - case PCI_EHCI_DEVICEID_NF3: - return (ehci_device_nf3); - case PCI_EHCI_DEVICEID_NF3_250: - return (ehci_device_nf3_250); - case PCI_EHCI_DEVICEID_NF4: - return (ehci_device_nf4); - case PCI_EHCI_DEVICEID_ISP156X: - return (ehci_device_isp156x); - case PCI_EHCI_DEVICEID_VIA: - return (ehci_device_via); - default: - if (pci_get_class(self) == PCIC_SERIALBUS - && pci_get_subclass(self) == PCIS_SERIALBUS_USB - && pci_get_progif(self) == PCI_INTERFACE_EHCI) { - return (ehci_device_generic); - } - } - - return NULL; /* dunno */ -} - -static int -ehci_pci_probe(device_t self) -{ - const char *desc = ehci_pci_match(self); - - if (desc) { - device_set_desc(self, desc); - device_set_async_attach(self, TRUE); - return 0; - } else { - return ENXIO; - } -} - -static int -ehci_pci_attach(device_t self) -{ - ehci_softc_t *sc = device_get_softc(self); - device_t parent; - device_t *neighbors; - device_t *nbus; - struct usb_softc *usb_sc; - struct usbd_bus *bsc; - int err; - int rid; - int ncomp; - int count, buscount; - int slot, function; - int res; - int i; - - switch(pci_read_config(self, PCI_USBREV, 1) & PCI_USBREV_MASK) { - case PCI_USBREV_PRE_1_0: - case PCI_USBREV_1_0: - case PCI_USBREV_1_1: - sc->sc_bus.usbrev = USBREV_UNKNOWN; - kprintf("pre-2.0 USB rev\n"); - return ENXIO; - case PCI_USBREV_2_0: - sc->sc_bus.usbrev = USBREV_2_0; - break; - default: - sc->sc_bus.usbrev = USBREV_UNKNOWN; - break; - } - - pci_enable_busmaster(self); - - rid = PCI_CBMEM; - sc->io_res = bus_alloc_resource_any(self, SYS_RES_MEMORY, &rid, - RF_ACTIVE); - if (!sc->io_res) { - device_printf(self, "Could not map memory\n"); - return ENXIO; - } - sc->iot = rman_get_bustag(sc->io_res); - sc->ioh = rman_get_bushandle(sc->io_res); - - rid = 0; - sc->irq_res = bus_alloc_resource_any(self, SYS_RES_IRQ, &rid, - RF_SHAREABLE | RF_ACTIVE); - if (sc->irq_res == NULL) { - device_printf(self, "Could not allocate irq\n"); - ehci_pci_detach(self); - return ENXIO; - } - sc->sc_bus.bdev = device_add_child(self, "usb", -1); - if (!sc->sc_bus.bdev) { - device_printf(self, "Could not add USB device\n"); - ehci_pci_detach(self); - return ENOMEM; - } - device_set_ivars(sc->sc_bus.bdev, &sc->sc_bus); - - /* ehci_pci_match will never return NULL if ehci_pci_probe succeeded */ - device_set_desc(sc->sc_bus.bdev, ehci_pci_match(self)); - switch (pci_get_vendor(self)) { - case PCI_EHCI_VENDORID_ACERLABS: - ksprintf(sc->sc_vendor, "AcerLabs"); - break; - case PCI_EHCI_VENDORID_AMD: - ksprintf(sc->sc_vendor, "AMD"); - break; - case PCI_EHCI_VENDORID_APPLE: - ksprintf(sc->sc_vendor, "Apple"); - break; - case PCI_EHCI_VENDORID_ATI: - ksprintf(sc->sc_vendor, "ATI"); - break; - case PCI_EHCI_VENDORID_CMDTECH: - ksprintf(sc->sc_vendor, "CMDTECH"); - break; - case PCI_EHCI_VENDORID_INTEL: - ksprintf(sc->sc_vendor, "Intel"); - break; - case PCI_EHCI_VENDORID_NEC: - ksprintf(sc->sc_vendor, "NEC"); - break; - case PCI_EHCI_VENDORID_OPTI: - ksprintf(sc->sc_vendor, "OPTi"); - break; - case PCI_EHCI_VENDORID_SIS: - ksprintf(sc->sc_vendor, "SiS"); - break; - case PCI_EHCI_VENDORID_NVIDIA: - case PCI_EHCI_VENDORID_NVIDIA2: - ksprintf(sc->sc_vendor, "nVidia"); - break; - case PCI_EHCI_VENDORID_VIA: - ksprintf(sc->sc_vendor, "VIA"); - break; - default: - if (bootverbose) - device_printf(self, "(New EHCI DeviceId=0x%08x)\n", - pci_get_devid(self)); - ksprintf(sc->sc_vendor, "(0x%04x)", pci_get_vendor(self)); - } - - err = bus_setup_intr(self, sc->irq_res, 0, - (driver_intr_t *) ehci_intr, sc, &sc->ih, NULL); - if (err) { - device_printf(self, "Could not setup irq, %d\n", err); - sc->ih = NULL; - ehci_pci_detach(self); - return ENXIO; - } - - /* Enable workaround for dropped interrupts as required */ - switch (pci_get_vendor(self)) { - case PCI_EHCI_VENDORID_ATI: - case PCI_EHCI_VENDORID_VIA: - sc->sc_flags |= EHCI_SCFLG_LOSTINTRBUG; - if (bootverbose) - device_printf(self, - "Dropped interrupts workaround enabled\n"); - break; - default: - break; - } - - /* - * Find companion controllers. According to the spec they always - * have lower function numbers so they should be enumerated already. - */ - parent = device_get_parent(self); - res = device_get_children(parent, &neighbors, &count); - if (res != 0) { - device_printf(self, "Error finding companion busses\n"); - ehci_pci_detach(self); - return ENXIO; - } - ncomp = 0; - slot = pci_get_slot(self); - function = pci_get_function(self); - for (i = 0; i < count; i++) { - if (pci_get_slot(neighbors[i]) == slot && \ - pci_get_function(neighbors[i]) < function) { - res = device_get_children(neighbors[i], - &nbus, &buscount); - if (res != 0 || buscount != 1) - continue; - usb_sc = device_get_softc(nbus[0]); - if (usb_sc == NULL) - continue; - bsc = usb_getbushandle(usb_sc); - if (bsc == NULL) - continue; - DPRINTF(("ehci_pci_attach: companion %s\n", - device_get_nameunit(bsc->bdev))); - sc->sc_comps[ncomp++] = bsc; - if (ncomp >= EHCI_COMPANION_MAX) - break; - } - } - sc->sc_ncomp = ncomp; - - ehci_pci_takecontroller(self); - err = ehci_init(sc); - if (err == 0) - err = device_probe_and_attach(sc->sc_bus.bdev); - - if (err) { - device_printf(self, "USB init failed err=%d\n", err); - ehci_pci_detach(self); - return EIO; - } - return 0; -} - -static int -ehci_pci_detach(device_t self) -{ - ehci_softc_t *sc = device_get_softc(self); - - if (sc->sc_flags & EHCI_SCFLG_DONEINIT) { - ehci_detach(sc, 0); - sc->sc_flags &= ~EHCI_SCFLG_DONEINIT; - } - - /* - * disable interrupts that might have been switched on in ehci_init - */ - if (sc->iot && sc->ioh) - bus_space_write_4(sc->iot, sc->ioh, EHCI_USBINTR, 0); - - if (sc->irq_res && sc->ih) { - int err = bus_teardown_intr(self, sc->irq_res, sc->ih); - - if (err) - /* XXX or should we panic? */ - device_printf(self, "Could not tear down irq, %d\n", - err); - sc->ih = NULL; - } - if (sc->sc_bus.bdev) { - device_delete_child(self, sc->sc_bus.bdev); - sc->sc_bus.bdev = NULL; - } - if (sc->irq_res) { - bus_release_resource(self, SYS_RES_IRQ, 0, sc->irq_res); - sc->irq_res = NULL; - } - if (sc->io_res) { - bus_release_resource(self, SYS_RES_MEMORY, PCI_CBMEM, sc->io_res); - sc->io_res = NULL; - sc->iot = 0; - sc->ioh = 0; - } - return 0; -} - -static void -ehci_pci_takecontroller(device_t self) -{ - ehci_softc_t *sc = device_get_softc(self); - u_int32_t cparams, eec, legsup; - int eecp, i; - - cparams = EREAD4(sc, EHCI_HCCPARAMS); - - /* Synchronise with the BIOS if it owns the controller. */ - for (eecp = EHCI_HCC_EECP(cparams); eecp != 0; - eecp = EHCI_EECP_NEXT(eec)) { - eec = pci_read_config(self, eecp, 4); - if (EHCI_EECP_ID(eec) != EHCI_EC_LEGSUP) - continue; - legsup = eec; - pci_write_config(self, eecp, legsup | EHCI_LEGSUP_OSOWNED, 4); - if (legsup & EHCI_LEGSUP_BIOSOWNED) { - device_printf(sc->sc_bus.bdev, - "waiting for BIOS to give up control\n"); - for (i = 0; i < 5000; i++) { - legsup = pci_read_config(self, eecp, 4); - if ((legsup & EHCI_LEGSUP_BIOSOWNED) == 0) - break; - DELAY(1000); - } - if (legsup & EHCI_LEGSUP_BIOSOWNED) - device_printf(sc->sc_bus.bdev, - "timed out waiting for BIOS\n"); - } - } -} - -/* - * Return the controller to the BIOS. Do we really need to do this? - * - * One thing we do need to do is give the chip reset (from the shutdown) - * time to finish before handing anything back. This fixes a machine - * lockup. - */ -static void -ehci_pci_givecontroller(device_t self) -{ - ehci_softc_t *sc = device_get_softc(self); - u_int32_t cparams, eec, legsup; - int eecp; - - DELAY(1000); - cparams = EREAD4(sc, EHCI_HCCPARAMS); - for (eecp = EHCI_HCC_EECP(cparams); eecp != 0; - eecp = EHCI_EECP_NEXT(eec)) { - eec = pci_read_config(self, eecp, 4); - if (EHCI_EECP_ID(eec) != EHCI_EC_LEGSUP) - continue; - legsup = eec; - pci_write_config(self, eecp, legsup & ~EHCI_LEGSUP_OSOWNED, 4); - } -} - -static device_method_t ehci_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, ehci_pci_probe), - DEVMETHOD(device_attach, ehci_pci_attach), - DEVMETHOD(device_detach, ehci_pci_detach), - DEVMETHOD(device_suspend, ehci_pci_suspend), - DEVMETHOD(device_resume, ehci_pci_resume), - DEVMETHOD(device_shutdown, ehci_pci_shutdown), - - /* Bus interface */ - DEVMETHOD(bus_print_child, bus_generic_print_child), - - DEVMETHOD_END -}; - -static driver_t ehci_driver = { - "ehci", - ehci_methods, - sizeof(ehci_softc_t), -}; - -static devclass_t ehci_devclass; - -DRIVER_MODULE(ehci, pci, ehci_driver, ehci_devclass, NULL, NULL); -DRIVER_MODULE(ehci, cardbus, ehci_driver, ehci_devclass, NULL, NULL); diff --git a/sys/bus/usb/ehcireg.h b/sys/bus/usb/ehcireg.h deleted file mode 100644 index 03ab92f59d..0000000000 --- a/sys/bus/usb/ehcireg.h +++ /dev/null @@ -1,301 +0,0 @@ -/* $NetBSD: ehcireg.h,v 1.18 2004/10/22 10:38:17 augustss Exp $ */ -/* $FreeBSD: src/sys/dev/usb/ehcireg.h,v 1.7.2.1 2006/01/26 01:43:13 iedowse Exp $ */ -/* $DragonFly: src/sys/bus/usb/ehcireg.h,v 1.7 2007/06/27 12:27:59 hasso Exp $ */ - -/* - * Copyright (c) 2001 The NetBSD Foundation, Inc. - * All rights reserved. - * - * This code is derived from software contributed to The NetBSD Foundation - * by Lennart Augustsson (lennart@augustsson.net). - * - * 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. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the NetBSD - * Foundation, Inc. and its contributors. - * 4. Neither the name of The NetBSD Foundation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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. - */ - -/* - * The EHCI 0.96 spec can be found at - * http://developer.intel.com/technology/usb/download/ehci-r096.pdf - * and the USB 2.0 spec at - * http://www.usb.org/developers/data/usb_20.zip - */ - -#ifndef _DEV_PCI_EHCIREG_H_ -#define _DEV_PCI_EHCIREG_H_ - -/*** PCI config registers ***/ - -#define PCI_CBMEM 0x10 /* configuration base MEM */ - -#define PCI_INTERFACE_EHCI 0x20 - -#define PCI_USBREV 0x60 /* RO USB protocol revision */ -#define PCI_USBREV_MASK 0xff -#define PCI_USBREV_PRE_1_0 0x00 -#define PCI_USBREV_1_0 0x10 -#define PCI_USBREV_1_1 0x11 -#define PCI_USBREV_2_0 0x20 - -#define PCI_EHCI_FLADJ 0x61 /*RW Frame len adj, SOF=59488+6*fladj */ - -#define PCI_EHCI_PORTWAKECAP 0x62 /* RW Port wake caps (opt) */ - -/* EHCI Extended Capabilities */ -#define EHCI_EC_LEGSUP 0x01 - -#define EHCI_EECP_NEXT(x) (((x) >> 8) & 0xff) -#define EHCI_EECP_ID(x) ((x) & 0xff) - -/* Legacy support extended capability */ -#define EHCI_LEGSUP_LEGSUP 0x01 -#define EHCI_LEGSUP_OSOWNED 0x01000000 /* OS owned semaphore */ -#define EHCI_LEGSUP_BIOSOWNED 0x00010000 /* BIOS owned semaphore */ -#define EHCI_LEGSUP_USBLEGCTLSTS 0x04 - -/*** EHCI capability registers ***/ - -#define EHCI_CAPLENGTH 0x00 /*RO Capability register length field */ -/* reserved 0x01 */ -#define EHCI_HCIVERSION 0x02 /* RO Interface version number */ - -#define EHCI_HCSPARAMS 0x04 /* RO Structural parameters */ -#define EHCI_HCS_DEBUGPORT(x) (((x) >> 20) & 0xf) -#define EHCI_HCS_P_INDICATOR(x) ((x) & 0x10000) -#define EHCI_HCS_N_CC(x) (((x) >> 12) & 0xf) /* # of companion ctlrs */ -#define EHCI_HCS_N_PCC(x) (((x) >> 8) & 0xf) /* # of ports per comp. */ -#define EHCI_HCS_PPC(x) ((x) & 0x10) /* port power control */ -#define EHCI_HCS_N_PORTS(x) ((x) & 0xf) /* # of ports */ - -#define EHCI_HCCPARAMS 0x08 /* RO Capability parameters */ -#define EHCI_HCC_EECP(x) (((x) >> 8) & 0xff) /* extended ports caps */ -#define EHCI_HCC_IST(x) (((x) >> 4) & 0xf) /* isoc sched threshold */ -#define EHCI_HCC_ASPC(x) ((x) & 0x4) /* async sched park cap */ -#define EHCI_HCC_PFLF(x) ((x) & 0x2) /* prog frame list flag */ -#define EHCI_HCC_64BIT(x) ((x) & 0x1) /* 64 bit address cap */ - -#define EHCI_HCSP_PORTROUTE 0x0c /*RO Companion port route description */ - -/* EHCI operational registers. Offset given by EHCI_CAPLENGTH register */ -#define EHCI_USBCMD 0x00 /* RO, RW, WO Command register */ -#define EHCI_CMD_ITC_M 0x00ff0000 /* RW interrupt threshold ctrl */ -#define EHCI_CMD_ITC_1 0x00010000 -#define EHCI_CMD_ITC_2 0x00020000 -#define EHCI_CMD_ITC_4 0x00040000 -#define EHCI_CMD_ITC_8 0x00080000 -#define EHCI_CMD_ITC_16 0x00100000 -#define EHCI_CMD_ITC_32 0x00200000 -#define EHCI_CMD_ITC_64 0x00400000 -#define EHCI_CMD_ASPME 0x00000800 /* RW/RO async park enable */ -#define EHCI_CMD_ASPMC 0x00000300 /* RW/RO async park count */ -#define EHCI_CMD_LHCR 0x00000080 /* RW light host ctrl reset */ -#define EHCI_CMD_IAAD 0x00000040 /* RW intr on async adv door bell */ -#define EHCI_CMD_ASE 0x00000020 /* RW async sched enable */ -#define EHCI_CMD_PSE 0x00000010 /* RW periodic sched enable */ -#define EHCI_CMD_FLS_M 0x0000000c /* RW/RO frame list size */ -#define EHCI_CMD_FLS(x) (((x) >> 2) & 3) /* RW/RO frame list size */ -#define EHCI_CMD_HCRESET 0x00000002 /* RW reset */ -#define EHCI_CMD_RS 0x00000001 /* RW run/stop */ - -#define EHCI_USBSTS 0x04 /* RO, RW, RWC Status register */ -#define EHCI_STS_ASS 0x00008000 /* RO async sched status */ -#define EHCI_STS_PSS 0x00004000 /* RO periodic sched status */ -#define EHCI_STS_REC 0x00002000 /* RO reclamation */ -#define EHCI_STS_HCH 0x00001000 /* RO host controller halted */ -#define EHCI_STS_IAA 0x00000020 /* RWC interrupt on async adv */ -#define EHCI_STS_HSE 0x00000010 /* RWC host system error */ -#define EHCI_STS_FLR 0x00000008 /* RWC frame list rollover */ -#define EHCI_STS_PCD 0x00000004 /* RWC port change detect */ -#define EHCI_STS_ERRINT 0x00000002 /* RWC error interrupt */ -#define EHCI_STS_INT 0x00000001 /* RWC interrupt */ -#define EHCI_STS_INTRS(x) ((x) & 0x3f) - -#define EHCI_NORMAL_INTRS (EHCI_STS_IAA | EHCI_STS_HSE | EHCI_STS_PCD | EHCI_STS_ERRINT | EHCI_STS_INT) - -#define EHCI_USBINTR 0x08 /* RW Interrupt register */ -#define EHCI_INTR_IAAE 0x00000020 /* interrupt on async advance ena */ -#define EHCI_INTR_HSEE 0x00000010 /* host system error ena */ -#define EHCI_INTR_FLRE 0x00000008 /* frame list rollover ena */ -#define EHCI_INTR_PCIE 0x00000004 /* port change ena */ -#define EHCI_INTR_UEIE 0x00000002 /* USB error intr ena */ -#define EHCI_INTR_UIE 0x00000001 /* USB intr ena */ - -#define EHCI_FRINDEX 0x0c /* RW Frame Index register */ - -#define EHCI_CTRLDSSEGMENT 0x10 /* RW Control Data Structure Segment */ - -#define EHCI_PERIODICLISTBASE 0x14 /* RW Periodic List Base */ -#define EHCI_ASYNCLISTADDR 0x18 /* RW Async List Base */ - -#define EHCI_CONFIGFLAG 0x40 /* RW Configure Flag register */ -#define EHCI_CONF_CF 0x00000001 /* RW configure flag */ - -#define EHCI_PORTSC(n) (0x40+4*(n)) /* RO, RW, RWC Port Status reg */ -#define EHCI_PS_WKOC_E 0x00400000 /* RW wake on over current ena */ -#define EHCI_PS_WKDSCNNT_E 0x00200000 /* RW wake on disconnect ena */ -#define EHCI_PS_WKCNNT_E 0x00100000 /* RW wake on connect ena */ -#define EHCI_PS_PTC 0x000f0000 /* RW port test control */ -#define EHCI_PS_PIC 0x0000c000 /* RW port indicator control */ -#define EHCI_PS_PO 0x00002000 /* RW port owner */ -#define EHCI_PS_PP 0x00001000 /* RW,RO port power */ -#define EHCI_PS_LS 0x00000c00 /* RO line status */ -#define EHCI_PS_IS_LOWSPEED(x) (((x) & EHCI_PS_LS) == 0x00000400) -#define EHCI_PS_PR 0x00000100 /* RW port reset */ -#define EHCI_PS_SUSP 0x00000080 /* RW suspend */ -#define EHCI_PS_FPR 0x00000040 /* RW force port resume */ -#define EHCI_PS_OCC 0x00000020 /* RWC over current change */ -#define EHCI_PS_OCA 0x00000010 /* RO over current active */ -#define EHCI_PS_PEC 0x00000008 /* RWC port enable change */ -#define EHCI_PS_PE 0x00000004 /* RW port enable */ -#define EHCI_PS_CSC 0x00000002 /* RWC connect status change */ -#define EHCI_PS_CS 0x00000001 /* RO connect status */ -#define EHCI_PS_CLEAR (EHCI_PS_OCC|EHCI_PS_PEC|EHCI_PS_CSC) - -#define EHCI_PORT_RESET_COMPLETE 2 /* in ms */ - -#define EHCI_FLALIGN_ALIGN 0x1000 - -/* No data structure may cross a page boundary. */ -#define EHCI_PAGE_SIZE 0x1000 -#define EHCI_PAGE(x) ((x) &~ 0xfff) -#define EHCI_PAGE_OFFSET(x) ((x) & 0xfff) -#define EHCI_PAGE_MASK(x) ((x) & 0xfff) - -typedef u_int32_t ehci_link_t; -#define EHCI_LINK_TERMINATE 0x00000001 -#define EHCI_LINK_TYPE(x) ((x) & 0x00000006) -#define EHCI_LINK_ITD 0x0 -#define EHCI_LINK_QH 0x2 -#define EHCI_LINK_SITD 0x4 -#define EHCI_LINK_FSTN 0x6 -#define EHCI_LINK_ADDR(x) ((x) &~ 0x1f) - -typedef u_int32_t ehci_physaddr_t; - -/* Isochronous Transfer Descriptor */ -typedef struct { - ehci_link_t itd_next; - /* XXX many more */ -} ehci_itd_t; -#define EHCI_ITD_ALIGN 32 - -/* Split Transaction Isochronous Transfer Descriptor */ -typedef struct { - ehci_link_t sitd_next; - /* XXX many more */ -} ehci_sitd_t; -#define EHCI_SITD_ALIGN 32 - -/* Queue Element Transfer Descriptor */ -#define EHCI_QTD_NBUFFERS 5 -typedef struct { - ehci_link_t qtd_next; - ehci_link_t qtd_altnext; - u_int32_t qtd_status; -#define EHCI_QTD_GET_STATUS(x) (((x) >> 0) & 0xff) -#define EHCI_QTD_SET_STATUS(x) ((x) << 0) -#define EHCI_QTD_ACTIVE 0x80 -#define EHCI_QTD_HALTED 0x40 -#define EHCI_QTD_BUFERR 0x20 -#define EHCI_QTD_BABBLE 0x10 -#define EHCI_QTD_XACTERR 0x08 -#define EHCI_QTD_MISSEDMICRO 0x04 -#define EHCI_QTD_SPLITXSTATE 0x02 -#define EHCI_QTD_PINGSTATE 0x01 -#define EHCI_QTD_STATERRS 0x7c -#define EHCI_QTD_GET_PID(x) (((x) >> 8) & 0x3) -#define EHCI_QTD_SET_PID(x) ((x) << 8) -#define EHCI_QTD_PID_OUT 0x0 -#define EHCI_QTD_PID_IN 0x1 -#define EHCI_QTD_PID_SETUP 0x2 -#define EHCI_QTD_GET_CERR(x) (((x) >> 10) & 0x3) -#define EHCI_QTD_SET_CERR(x) ((x) << 10) -#define EHCI_QTD_GET_C_PAGE(x) (((x) >> 12) & 0x7) -#define EHCI_QTD_SET_C_PAGE(x) ((x) << 12) -#define EHCI_QTD_GET_IOC(x) (((x) >> 15) & 0x1) -#define EHCI_QTD_IOC 0x00008000 -#define EHCI_QTD_GET_BYTES(x) (((x) >> 16) & 0x7fff) -#define EHCI_QTD_SET_BYTES(x) ((x) << 16) -#define EHCI_QTD_GET_TOGGLE(x) (((x) >> 31) & 0x1) -#define EHCI_QTD_SET_TOGGLE(x) ((x) << 31) -#define EHCI_QTD_TOGGLE_MASK 0x80000000 - ehci_physaddr_t qtd_buffer[EHCI_QTD_NBUFFERS]; - ehci_physaddr_t qtd_buffer_hi[EHCI_QTD_NBUFFERS]; -} ehci_qtd_t; -#define EHCI_QTD_ALIGN 32 - -/* Queue Head */ -typedef struct { - ehci_link_t qh_link; - u_int32_t qh_endp; -#define EHCI_QH_GET_ADDR(x) (((x) >> 0) & 0x7f) /* endpoint addr */ -#define EHCI_QH_SET_ADDR(x) (x) -#define EHCI_QH_ADDRMASK 0x0000007f -#define EHCI_QH_GET_INACT(x) (((x) >> 7) & 0x01) /* inactivate on next */ -#define EHCI_QH_INACT 0x00000080 -#define EHCI_QH_GET_ENDPT(x) (((x) >> 8) & 0x0f) /* endpoint no */ -#define EHCI_QH_SET_ENDPT(x) ((x) << 8) -#define EHCI_QH_GET_EPS(x) (((x) >> 12) & 0x03) /* endpoint speed */ -#define EHCI_QH_SET_EPS(x) ((x) << 12) -#define EHCI_QH_SPEED_FULL 0x0 -#define EHCI_QH_SPEED_LOW 0x1 -#define EHCI_QH_SPEED_HIGH 0x2 -#define EHCI_QH_GET_DTC(x) (((x) >> 14) & 0x01) /* data toggle control */ -#define EHCI_QH_DTC 0x00004000 -#define EHCI_QH_GET_HRECL(x) (((x) >> 15) & 0x01) /* head of reclamation */ -#define EHCI_QH_HRECL 0x00008000 -#define EHCI_QH_GET_MPL(x) (((x) >> 16) & 0x7ff) /* max packet len */ -#define EHCI_QH_SET_MPL(x) ((x) << 16) -#define EHCI_QH_MPLMASK 0x07ff0000 -#define EHCI_QH_GET_CTL(x) (((x) >> 27) & 0x01) /* control endpoint */ -#define EHCI_QH_CTL 0x08000000 -#define EHCI_QH_GET_NRL(x) (((x) >> 28) & 0x0f) /* NAK reload */ -#define EHCI_QH_SET_NRL(x) ((x) << 28) - u_int32_t qh_endphub; -#define EHCI_QH_GET_SMASK(x) (((x) >> 0) & 0xff) /* intr sched mask */ -#define EHCI_QH_SET_SMASK(x) ((x) << 0) -#define EHCI_QH_GET_CMASK(x) (((x) >> 8) & 0xff) /* split completion mask */ -#define EHCI_QH_SET_CMASK(x) ((x) << 8) -#define EHCI_QH_GET_HUBA(x) (((x) >> 16) & 0x7f) /* hub address */ -#define EHCI_QH_SET_HUBA(x) ((x) << 16) -#define EHCI_QH_GET_PORT(x) (((x) >> 23) & 0x7f) /* hub port */ -#define EHCI_QH_SET_PORT(x) ((x) << 23) -#define EHCI_QH_GET_MULT(x) (((x) >> 30) & 0x03) /* pipe multiplier */ -#define EHCI_QH_SET_MULT(x) ((x) << 30) - ehci_link_t qh_curqtd; - ehci_qtd_t qh_qtd; -} ehci_qh_t; -#define EHCI_QH_ALIGN 32 - -/* Periodic Frame Span Traversal Node */ -typedef struct { - ehci_link_t fstn_link; - ehci_link_t fstn_back; -} ehci_fstn_t; -#define EHCI_FSTN_ALIGN 32 - -#endif /* _DEV_PCI_EHCIREG_H_ */ diff --git a/sys/bus/usb/ehcivar.h b/sys/bus/usb/ehcivar.h deleted file mode 100644 index 0576c2b035..0000000000 --- a/sys/bus/usb/ehcivar.h +++ /dev/null @@ -1,173 +0,0 @@ -/* $NetBSD: ehcivar.h,v 1.19 2005/04/29 15:04:29 augustss Exp $ */ -/* $FreeBSD: src/sys/dev/usb/ehcivar.h,v 1.9.2.1 2006/01/26 01:43:13 iedowse Exp $ */ -/* $DragonFly: src/sys/bus/usb/ehcivar.h,v 1.12 2008/06/10 10:04:06 hasso Exp $ */ - -/* - * Copyright (c) 2001 The NetBSD Foundation, Inc. - * All rights reserved. - * - * This code is derived from software contributed to The NetBSD Foundation - * by Lennart Augustsson (lennart@augustsson.net). - * - * 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. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the NetBSD - * Foundation, Inc. and its contributors. - * 4. Neither the name of The NetBSD Foundation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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. - */ - -typedef struct ehci_soft_qtd { - ehci_qtd_t qtd; - struct ehci_soft_qtd *nextqtd; /* mirrors nextqtd in TD */ - ehci_physaddr_t physaddr; - usbd_xfer_handle xfer; - LIST_ENTRY(ehci_soft_qtd) hnext; - u_int16_t len; -} ehci_soft_qtd_t; -#define EHCI_SQTD_SIZE ((sizeof (struct ehci_soft_qtd) + EHCI_QTD_ALIGN - 1) / EHCI_QTD_ALIGN * EHCI_QTD_ALIGN) -#define EHCI_SQTD_CHUNK (EHCI_PAGE_SIZE / EHCI_SQTD_SIZE) - -typedef struct ehci_soft_qh { - ehci_qh_t qh; - struct ehci_soft_qh *next; - struct ehci_soft_qh *prev; - struct ehci_soft_qtd *sqtd; - ehci_physaddr_t physaddr; - int islot; /* Interrupt list slot. */ -} ehci_soft_qh_t; -#define EHCI_SQH_SIZE ((sizeof (struct ehci_soft_qh) + EHCI_QH_ALIGN - 1) / EHCI_QH_ALIGN * EHCI_QH_ALIGN) -#define EHCI_SQH_CHUNK (EHCI_PAGE_SIZE / EHCI_SQH_SIZE) - -struct ehci_xfer { - struct usbd_xfer xfer; - struct usb_task abort_task; - LIST_ENTRY(ehci_xfer) inext; /* list of active xfers */ - ehci_soft_qtd_t *sqtdstart; - ehci_soft_qtd_t *sqtdend; - u_int32_t ehci_xfer_flags; -#ifdef DIAGNOSTIC - int isdone; -#endif -}; -#define EHCI_XFER_ABORTING 0x0001 /* xfer is aborting. */ -#define EHCI_XFER_ABORTWAIT 0x0002 /* abort completion is being awaited. */ - -#define EXFER(xfer) ((struct ehci_xfer *)(xfer)) - -/* Information about an entry in the interrupt list. */ -struct ehci_soft_islot { - ehci_soft_qh_t *sqh; /* Queue Head. */ -}; - -#define EHCI_FRAMELIST_MAXCOUNT 1024 -#define EHCI_IPOLLRATES 8 /* Poll rates (1ms, 2, 4, 8 .. 128) */ -#define EHCI_INTRQHS ((1 << EHCI_IPOLLRATES) - 1) -#define EHCI_MAX_POLLRATE (1 << (EHCI_IPOLLRATES - 1)) -#define EHCI_IQHIDX(lev, pos) \ - ((((pos) & ((1 << (lev)) - 1)) | (1 << (lev))) - 1) -#define EHCI_ILEV_IVAL(lev) (1 << (lev)) - - -#define EHCI_HASH_SIZE 128 -#define EHCI_COMPANION_MAX 8 - -#define EHCI_SCFLG_DONEINIT 0x0001 /* ehci_init() has been called. */ -#define EHCI_SCFLG_LOSTINTRBUG 0x0002 /* workaround for VIA / ATI chipsets */ - -typedef struct ehci_softc { - struct usbd_bus sc_bus; /* base device */ - bus_space_tag_t iot; - bus_space_handle_t ioh; - bus_size_t sc_size; - void *ih; - - struct resource *io_res; - struct resource *irq_res; - u_int sc_offs; /* offset to operational regs */ - int sc_flags; /* misc flags */ - - char sc_vendor[32]; /* vendor string for root hub */ - int sc_id_vendor; /* vendor ID for root hub */ - - u_int32_t sc_cmd; /* shadow of cmd reg during suspend */ - - u_int sc_ncomp; - u_int sc_npcomp; - struct usbd_bus *sc_comps[EHCI_COMPANION_MAX]; - - usb_dma_t sc_fldma; - ehci_link_t *sc_flist; - u_int sc_flsize; - - struct ehci_soft_islot sc_islots[EHCI_INTRQHS]; - - LIST_HEAD(, ehci_xfer) sc_intrhead; - - ehci_soft_qh_t *sc_freeqhs; - ehci_soft_qtd_t *sc_freeqtds; - - int sc_noport; - u_int8_t sc_addr; /* device address */ - u_int8_t sc_conf; /* device configuration */ - usbd_xfer_handle sc_intrxfer; - char sc_isreset; -#ifdef USB_USE_SOFTINTR - char sc_softwake; -#endif /* USB_USE_SOFTINTR */ - - u_int32_t sc_eintrs; /* enabled interrupts */ - u_int32_t sc_dintrs; /* deferred interrupts */ - ehci_soft_qh_t *sc_async_head; - - STAILQ_HEAD(, usbd_xfer) sc_free_xfers; /* free xfers */ - - struct lock sc_doorbell_lock; - - struct callout sc_tmo_intrlist; - - char sc_dying; -} ehci_softc_t; - -#define EREAD1(sc, a) bus_space_read_1((sc)->iot, (sc)->ioh, (a)) -#define EREAD2(sc, a) bus_space_read_2((sc)->iot, (sc)->ioh, (a)) -#define EREAD4(sc, a) bus_space_read_4((sc)->iot, (sc)->ioh, (a)) -#define EWRITE1(sc, a, x) bus_space_write_1((sc)->iot, (sc)->ioh, (a), (x)) -#define EWRITE2(sc, a, x) bus_space_write_2((sc)->iot, (sc)->ioh, (a), (x)) -#define EWRITE4(sc, a, x) bus_space_write_4((sc)->iot, (sc)->ioh, (a), (x)) -#define EOREAD1(sc, a) bus_space_read_1((sc)->iot, (sc)->ioh, (sc)->sc_offs+(a)) -#define EOREAD2(sc, a) bus_space_read_2((sc)->iot, (sc)->ioh, (sc)->sc_offs+(a)) -#define EOREAD4(sc, a) bus_space_read_4((sc)->iot, (sc)->ioh, (sc)->sc_offs+(a)) -#define EOWRITE1(sc, a, x) bus_space_write_1((sc)->iot, (sc)->ioh, (sc)->sc_offs+(a), (x)) -#define EOWRITE2(sc, a, x) bus_space_write_2((sc)->iot, (sc)->ioh, (sc)->sc_offs+(a), (x)) -#define EOWRITE4(sc, a, x) bus_space_write_4((sc)->iot, (sc)->ioh, (sc)->sc_offs+(a), (x)) - -usbd_status ehci_init(ehci_softc_t *); -int ehci_intr(void *); -int ehci_detach(ehci_softc_t *, int); -void ehci_power(int state, void *priv); -void ehci_shutdown(void *v); - -#define MS_TO_TICKS(ms) ((ms) * hz / 1000) - diff --git a/sys/bus/usb/hid.c b/sys/bus/usb/hid.c deleted file mode 100644 index a58a428e25..0000000000 --- a/sys/bus/usb/hid.c +++ /dev/null @@ -1,461 +0,0 @@ -/* - * $NetBSD: hid.c,v 1.17 2001/11/13 06:24:53 lukem Exp $ - * $FreeBSD: src/sys/dev/usb/hid.c,v 1.23 2003/08/24 17:55:54 obrien Exp $ - * $DragonFly: src/sys/bus/usb/hid.c,v 1.13 2007/06/28 13:55:12 hasso Exp $ - */ -/* - * Copyright (c) 1998 The NetBSD Foundation, Inc. - * All rights reserved. - * - * This code is derived from software contributed to The NetBSD Foundation - * by Lennart Augustsson (lennart@augustsson.net) at - * Carlstedt Research & Technology. - * - * 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. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the NetBSD - * Foundation, Inc. and its contributors. - * 4. Neither the name of The NetBSD Foundation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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 -#include -#include - -#include -#include - -#include - -#ifdef USB_DEBUG -#define DPRINTF(x) if (usbdebug) kprintf x -#define DPRINTFN(n,x) if (usbdebug>(n)) kprintf x -extern int usbdebug; -#else -#define DPRINTF(x) -#define DPRINTFN(n,x) -#endif - -static void hid_clear_local(struct hid_item *); - -#define MAXUSAGE 100 -struct hid_data { - u_char *start; - u_char *end; - u_char *p; - struct hid_item cur; - int32_t usages[MAXUSAGE]; - int nu; - int minset; - int multi; - int multimax; - int kindset; -}; - -static void -hid_clear_local(struct hid_item *c) -{ - - c->usage = 0; - c->usage_minimum = 0; - c->usage_maximum = 0; - c->designator_index = 0; - c->designator_minimum = 0; - c->designator_maximum = 0; - c->string_index = 0; - c->string_minimum = 0; - c->string_maximum = 0; - c->set_delimiter = 0; -} - -struct hid_data * -hid_start_parse(void *d, int len, int kindset) -{ - struct hid_data *s; - - s = kmalloc(sizeof *s, M_TEMP, M_INTWAIT|M_ZERO); - s->start = s->p = d; - s->end = (char *)d + len; - s->kindset = kindset; - return (s); -} - -void -hid_end_parse(struct hid_data *s) -{ - - while (s->cur.next != NULL) { - struct hid_item *hi = s->cur.next->next; - kfree(s->cur.next, M_TEMP); - s->cur.next = hi; - } - kfree(s, M_TEMP); -} - -int -hid_get_item(struct hid_data *s, struct hid_item *h) -{ - struct hid_item *c = &s->cur; - unsigned int bTag, bType, bSize; - u_int32_t oldpos; - u_char *data; - int32_t dval; - u_char *p; - struct hid_item *hi; - int i; - - top: - if (s->multimax != 0) { - if (s->multi < s->multimax) { - c->usage = s->usages[min(s->multi, s->nu-1)]; - s->multi++; - *h = *c; - c->loc.pos += c->loc.size; - h->next = 0; - return (1); - } else { - c->loc.count = s->multimax; - s->multimax = 0; - s->nu = 0; - hid_clear_local(c); - } - } - for (;;) { - p = s->p; - if (p >= s->end) - return (0); - - bSize = *p++; - if (bSize == 0xfe) { - /* long item */ - bSize = *p++; - bSize |= *p++ << 8; - bTag = *p++; - data = p; - p += bSize; - bType = 0xff; /* XXX what should it be */ - } else { - /* short item */ - bTag = bSize >> 4; - bType = (bSize >> 2) & 3; - bSize &= 3; - if (bSize == 3) bSize = 4; - data = p; - p += bSize; - } - s->p = p; - switch(bSize) { - case 0: - dval = 0; - break; - case 1: - dval = (int8_t)*data++; - break; - case 2: - dval = *data++; - dval |= *data++ << 8; - dval = (int16_t)dval; - break; - case 4: - dval = *data++; - dval |= *data++ << 8; - dval |= *data++ << 16; - dval |= *data++ << 24; - break; - default: - kprintf("BAD LENGTH %d\n", bSize); - continue; - } - - switch (bType) { - case 0: /* Main */ - switch (bTag) { - case 8: /* Input */ - if (!(s->kindset & (1 << hid_input))) - continue; - c->kind = hid_input; - c->flags = dval; - ret: - if (c->flags & HIO_VARIABLE) { - s->multimax = c->loc.count; - s->multi = 0; - c->loc.count = 1; - if (s->minset) { - for (i = c->usage_minimum; - i <= c->usage_maximum; - i++) { - s->usages[s->nu] = i; - if (s->nu < MAXUSAGE-1) - s->nu++; - } - s->minset = 0; - } - goto top; - } else { - *h = *c; - h->next = 0; - c->loc.pos += - c->loc.size * c->loc.count; - hid_clear_local(c); - s->minset = 0; - return (1); - } - case 9: /* Output */ - if (!(s->kindset & (1 << hid_output))) - continue; - c->kind = hid_output; - c->flags = dval; - goto ret; - case 10: /* Collection */ - c->kind = hid_collection; - c->collection = dval; - c->collevel++; - *h = *c; - hid_clear_local(c); - s->nu = 0; - return (1); - case 11: /* Feature */ - if (!(s->kindset & (1 << hid_feature))) - continue; - c->kind = hid_feature; - c->flags = dval; - goto ret; - case 12: /* End collection */ - c->kind = hid_endcollection; - c->collevel--; - *h = *c; - hid_clear_local(c); - s->nu = 0; - return (1); - default: - kprintf("Main bTag=%d\n", bTag); - break; - } - break; - case 1: /* Global */ - switch (bTag) { - case 0: - c->_usage_page = dval << 16; - break; - case 1: - c->logical_minimum = dval; - break; - case 2: - c->logical_maximum = dval; - break; - case 3: - c->physical_maximum = dval; - break; - case 4: - c->physical_maximum = dval; - break; - case 5: - c->unit_exponent = dval; - break; - case 6: - c->unit = dval; - break; - case 7: - c->loc.size = dval; - break; - case 8: - c->report_ID = dval; - break; - case 9: - c->loc.count = dval; - break; - case 10: /* Push */ - hi = kmalloc(sizeof *hi, M_TEMP, M_INTWAIT); - *hi = s->cur; - c->next = hi; - break; - case 11: /* Pop */ - hi = c->next; - oldpos = c->loc.pos; - s->cur = *hi; - c->loc.pos = oldpos; - kfree(hi, M_TEMP); - break; - default: - kprintf("Global bTag=%d\n", bTag); - break; - } - break; - case 2: /* Local */ - switch (bTag) { - case 0: - if (bSize == 1) - dval = c->_usage_page | (dval&0xff); - else if (bSize == 2) - dval = c->_usage_page | (dval&0xffff); - c->usage = dval; - if (s->nu < MAXUSAGE) - s->usages[s->nu++] = dval; - /* else XXX */ - break; - case 1: - s->minset = 1; - if (bSize == 1) - dval = c->_usage_page | (dval&0xff); - else if (bSize == 2) - dval = c->_usage_page | (dval&0xffff); - c->usage_minimum = dval; - break; - case 2: - if (bSize == 1) - dval = c->_usage_page | (dval&0xff); - else if (bSize == 2) - dval = c->_usage_page | (dval&0xffff); - c->usage_maximum = dval; - break; - case 3: - c->designator_index = dval; - break; - case 4: - c->designator_minimum = dval; - break; - case 5: - c->designator_maximum = dval; - break; - case 7: - c->string_index = dval; - break; - case 8: - c->string_minimum = dval; - break; - case 9: - c->string_maximum = dval; - break; - case 10: - c->set_delimiter = dval; - break; - default: - kprintf("Local bTag=%d\n", bTag); - break; - } - break; - default: - kprintf("default bType=%d\n", bType); - break; - } - } -} - -int -hid_report_size(void *buf, int len, enum hid_kind k, u_int8_t *idp) -{ - struct hid_data *d; - struct hid_item h; - int hi, lo, size, id; - - id = 0; - hi = lo = -1; - for (d = hid_start_parse(buf, len, 1<size = 0; - return (0); -} - -u_long -hid_get_data(u_char *buf, struct hid_location *loc) -{ - u_int hpos = loc->pos; - u_int hsize = loc->size; - u_int32_t data; - int i, s; - - DPRINTFN(10, ("hid_get_data: loc %d/%d\n", hpos, hsize)); - - if (hsize == 0) - return (0); - - data = 0; - s = hpos / 8; - for (i = hpos; i < hpos+hsize; i += 8) - data |= buf[i / 8] << ((i / 8 - s) * 8); - data >>= hpos % 8; - data &= (1 << hsize) - 1; - hsize = 32 - hsize; - /* Sign extend */ - data = ((int32_t)data << hsize) >> hsize; - DPRINTFN(10,("hid_get_data: loc %d/%d = %lu\n", - loc->pos, loc->size, (long)data)); - return (data); -} - -int -hid_is_collection(void *desc, int size, u_int32_t usage) -{ - struct hid_data *hd; - struct hid_item hi; - int err; - - hd = hid_start_parse(desc, size, hid_input); - if (hd == NULL) - return (0); - - err = hid_get_item(hd, &hi) && - hi.kind == hid_collection && - hi.usage == usage; - hid_end_parse(hd); - return (err); -} diff --git a/sys/bus/usb/hid.h b/sys/bus/usb/hid.h deleted file mode 100644 index 687ba1deef..0000000000 --- a/sys/bus/usb/hid.h +++ /dev/null @@ -1,94 +0,0 @@ -/* - * $NetBSD: hid.h,v 1.6 2000/06/01 14:28:57 augustss Exp $ - * $FreeBSD: src/sys/dev/usb/hid.h,v 1.12 2003/07/04 01:50:38 jmg Exp $ - * $DragonFly: src/sys/bus/usb/hid.h,v 1.3 2003/12/30 01:01:44 dillon Exp $ - */ - -/* - * Copyright (c) 1998 The NetBSD Foundation, Inc. - * All rights reserved. - * - * This code is derived from software contributed to The NetBSD Foundation - * by Lennart Augustsson (lennart@augustsson.net) at - * Carlstedt Research & Technology. - * - * 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. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the NetBSD - * Foundation, Inc. and its contributors. - * 4. Neither the name of The NetBSD Foundation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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. - */ - -enum hid_kind { - hid_input, hid_output, hid_feature, hid_collection, hid_endcollection -}; - -struct hid_location { - u_int32_t size; - u_int32_t count; - u_int32_t pos; -}; - -struct hid_item { - /* Global */ - int32_t _usage_page; - int32_t logical_minimum; - int32_t logical_maximum; - int32_t physical_minimum; - int32_t physical_maximum; - int32_t unit_exponent; - int32_t unit; - int32_t report_ID; - /* Local */ - int32_t usage; - int32_t usage_minimum; - int32_t usage_maximum; - int32_t designator_index; - int32_t designator_minimum; - int32_t designator_maximum; - int32_t string_index; - int32_t string_minimum; - int32_t string_maximum; - int32_t set_delimiter; - /* Misc */ - int32_t collection; - int collevel; - enum hid_kind kind; - u_int32_t flags; - /* Location */ - struct hid_location loc; - /* */ - struct hid_item *next; -}; - -struct hid_data *hid_start_parse(void *d, int len, int kindset); -void hid_end_parse(struct hid_data *s); -int hid_get_item(struct hid_data *s, struct hid_item *h); -int hid_report_size(void *buf, int len, enum hid_kind k, u_int8_t *id); -int hid_locate(void *desc, int size, u_int32_t usage, - enum hid_kind kind, struct hid_location *loc, - u_int32_t *flags); -u_long hid_get_data(u_char *buf, struct hid_location *loc); -int hid_is_collection(void *desc, int size, u_int32_t usage); diff --git a/sys/bus/usb/kue_fw.h b/sys/bus/usb/kue_fw.h deleted file mode 100644 index afd1f8ada2..0000000000 --- a/sys/bus/usb/kue_fw.h +++ /dev/null @@ -1,686 +0,0 @@ -/* - * Copyright (c) 1997, 1998, 1999, 2000 - * Bill Paul . 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. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Bill Paul. - * 4. Neither the name of the author nor the names of any co-contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY Bill Paul 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 Bill Paul OR THE VOICES IN HIS HEAD - * 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: src/sys/dev/usb/kue_fw.h,v 1.2 2000/04/03 20:58:23 n_hibma Exp $ - * $DragonFly: src/sys/bus/usb/kue_fw.h,v 1.4 2007/06/28 06:32:31 hasso Exp $ - */ - -/* - * This file contains the firmware needed to make the KLSI chip work, - * along with a few constants related to the QT Engine microcontroller - * embedded in the KLSI part. - * - * Firmware is loaded using the vendor-specific 'send scan data' - * command (0xFF). The basic operation is that we must load the - * firmware, then issue some trigger commands to fix it up and start - * it running. There are three transfers: load the binary code, - * load the 'fixup' (data segment?), then issue a command to - * start the code firmware running. The data itself is prefixed by - * a 16-bit signature word, a 16-bit length value, a type byte - * and an interrupt (command) byte. The code segment is of type - * 0x02 (replacement interrupt vector data) and the fixup segment - * is of type 0x03 (replacement interrupt fixup data). The interrupt - * code is 0x64 (load new code). The length word is the total length - * of the segment minus 7. I precomputed the values and stuck them - * into the appropriate locations within the segments to save some - * work in the driver. - */ - -/* QT controller data block types. */ -/* Write data into specific memory location. */ -#define KUE_QTBTYPE_WRITE_DATA 0x00 -/* Write data into interrupt vector location */ -#define KUE_QTBTYPE_WRITE_INTVEC 0x01 -/* Replace interrupt vector with this data */ -#define KUE_QTBTYPE_REPL_INTVEC 0x02 -/* Fixup interrupt vector code with this data */ -#define KUE_QTBTYPE_FIXUP_INTVEC 0x03 -/* Force jump to location */ -#define KUE_QTBTYPE_JUMP 0x04 -/* Force call to location */ -#define KUE_QTBTYPE_CALL 0x05 -/* Force interrupt call */ -#define KUE_QTBTYPE_CALLINTR 0x06 -/* - * Cause data to be written using the specified QT engine - * interrupt, from starting location in memory for a specified - * number of bytes. - */ -#define KUE_QTBTYPE_WRITE_WITH_INTR 0x07 -/* Cause data from stream to be written using specified QT interrupt. */ -#define KUE_QTBTYPE_WRITE_STR_WITH_INTR 0x08 -/* Cause data to be written to config locations. */ -/* Addresses assume 0xc000 offset. */ -#define KUE_QTBTYPE_WRITE_CONFIG 0x09 - -#define KUE_QTINTR_LOAD_CODE 0x64 -#define KUE_QTINTR_TRIGGER_CODE 0x3B -#define KUE_QTINTR_LOAD_CODE_HIGH 0x9C - -/* Firmware code segment */ -static unsigned char kue_code_seg[] = -{ - /******************************************/ - /* NOTE: B6/C3 is data header signature */ - /* 0xAA/0xBB is data length = total */ - /* bytes - 7, 0xCC is type, 0xDD is */ - /* interrupt to use. */ - /******************************************/ - 0xB6, 0xC3, 0xf7, 0x0e, 0x02, 0x64, - 0x9f, 0xcf, 0xbc, 0x08, 0xe7, 0x57, 0x00, 0x00, - 0x9a, 0x08, 0x97, 0xc1, 0xe7, 0x67, 0xff, 0x1f, - 0x28, 0xc0, 0xe7, 0x87, 0x00, 0x04, 0x24, 0xc0, - 0xe7, 0x67, 0xff, 0xf9, 0x22, 0xc0, 0x97, 0xcf, - 0xe7, 0x09, 0xa2, 0xc0, 0x94, 0x08, 0xd7, 0x09, - 0x00, 0xc0, 0xe7, 0x59, 0xba, 0x08, 0x94, 0x08, - 0x03, 0xc1, 0xe7, 0x67, 0xff, 0xf7, 0x24, 0xc0, - 0xe7, 0x05, 0x00, 0xc0, 0xa7, 0xcf, 0x92, 0x08, - 0xe7, 0x57, 0x00, 0x00, 0x8e, 0x08, 0xa7, 0xa1, - 0x8e, 0x08, 0x97, 0xcf, 0xe7, 0x57, 0x00, 0x00, - 0xf2, 0x09, 0x0a, 0xc0, 0xe7, 0x57, 0x00, 0x00, - 0xa4, 0xc0, 0xa7, 0xc0, 0x56, 0x08, 0x9f, 0xaf, - 0x70, 0x09, 0xe7, 0x07, 0x00, 0x00, 0xf2, 0x09, - 0xe7, 0x57, 0xff, 0xff, 0x90, 0x08, 0x9f, 0xa0, - 0x40, 0x00, 0xe7, 0x59, 0x90, 0x08, 0x94, 0x08, - 0x9f, 0xa0, 0x40, 0x00, 0xc8, 0x09, 0xa2, 0x08, - 0x08, 0x62, 0x9f, 0xa1, 0x14, 0x0a, 0xe7, 0x57, - 0x00, 0x00, 0x52, 0x08, 0xa7, 0xc0, 0x56, 0x08, - 0x9f, 0xaf, 0x04, 0x00, 0xe7, 0x57, 0x00, 0x00, - 0x8e, 0x08, 0xa7, 0xc1, 0x56, 0x08, 0xc0, 0x09, - 0xa8, 0x08, 0x00, 0x60, 0x05, 0xc4, 0xc0, 0x59, - 0x94, 0x08, 0x02, 0xc0, 0x9f, 0xaf, 0xee, 0x00, - 0xe7, 0x59, 0xae, 0x08, 0x94, 0x08, 0x02, 0xc1, - 0x9f, 0xaf, 0xf6, 0x00, 0x9f, 0xaf, 0x9e, 0x03, - 0xef, 0x57, 0x00, 0x00, 0xf0, 0x09, 0x9f, 0xa1, - 0xde, 0x01, 0xe7, 0x57, 0x00, 0x00, 0x78, 0x08, - 0x9f, 0xa0, 0xe4, 0x03, 0x9f, 0xaf, 0x2c, 0x04, - 0xa7, 0xcf, 0x56, 0x08, 0x48, 0x02, 0xe7, 0x09, - 0x94, 0x08, 0xa8, 0x08, 0xc8, 0x37, 0x04, 0x00, - 0x9f, 0xaf, 0x68, 0x04, 0x97, 0xcf, 0xe7, 0x57, - 0x00, 0x00, 0xa6, 0x08, 0x97, 0xc0, 0xd7, 0x09, - 0x00, 0xc0, 0xc1, 0xdf, 0xc8, 0x09, 0x9c, 0x08, - 0x08, 0x62, 0x1d, 0xc0, 0x27, 0x04, 0x9c, 0x08, - 0x10, 0x94, 0xf0, 0x07, 0xee, 0x09, 0x02, 0x00, - 0xc1, 0x07, 0x01, 0x00, 0x70, 0x00, 0x04, 0x00, - 0xf0, 0x07, 0x44, 0x01, 0x06, 0x00, 0x50, 0xaf, - 0xe7, 0x09, 0x94, 0x08, 0xae, 0x08, 0xe7, 0x17, - 0x14, 0x00, 0xae, 0x08, 0xe7, 0x67, 0xff, 0x07, - 0xae, 0x08, 0xe7, 0x07, 0xff, 0xff, 0xa8, 0x08, - 0xe7, 0x07, 0x00, 0x00, 0xa6, 0x08, 0xe7, 0x05, - 0x00, 0xc0, 0x97, 0xcf, 0xd7, 0x09, 0x00, 0xc0, - 0xc1, 0xdf, 0x48, 0x02, 0xd0, 0x09, 0x9c, 0x08, - 0x27, 0x02, 0x9c, 0x08, 0xe7, 0x09, 0x20, 0xc0, - 0xee, 0x09, 0xe7, 0xd0, 0xee, 0x09, 0xe7, 0x05, - 0x00, 0xc0, 0x97, 0xcf, 0x48, 0x02, 0xc8, 0x37, - 0x04, 0x00, 0x00, 0x0c, 0x0c, 0x00, 0x00, 0x60, - 0x21, 0xc0, 0xc0, 0x37, 0x3e, 0x00, 0x23, 0xc9, - 0xc0, 0x57, 0xb4, 0x05, 0x1b, 0xc8, 0xc0, 0x17, - 0x3f, 0x00, 0xc0, 0x67, 0xc0, 0xff, 0x30, 0x00, - 0x08, 0x00, 0xf0, 0x07, 0x00, 0x00, 0x04, 0x00, - 0x00, 0x02, 0xc0, 0x17, 0x4c, 0x00, 0x30, 0x00, - 0x06, 0x00, 0xf0, 0x07, 0xbe, 0x01, 0x0a, 0x00, - 0x48, 0x02, 0xc1, 0x07, 0x02, 0x00, 0xd7, 0x09, - 0x00, 0xc0, 0xc1, 0xdf, 0x51, 0xaf, 0xe7, 0x05, - 0x00, 0xc0, 0x97, 0xcf, 0x9f, 0xaf, 0x68, 0x04, - 0x9f, 0xaf, 0xe4, 0x03, 0x97, 0xcf, 0x9f, 0xaf, - 0xe4, 0x03, 0xc9, 0x37, 0x04, 0x00, 0xc1, 0xdf, - 0xc8, 0x09, 0x70, 0x08, 0x50, 0x02, 0x67, 0x02, - 0x70, 0x08, 0xd1, 0x07, 0x00, 0x00, 0xc0, 0xdf, - 0x9f, 0xaf, 0xde, 0x01, 0x97, 0xcf, 0xe7, 0x57, - 0x00, 0x00, 0xaa, 0x08, 0x97, 0xc1, 0xe7, 0x57, - 0x01, 0x00, 0x7a, 0x08, 0x97, 0xc0, 0xc8, 0x09, - 0x6e, 0x08, 0x08, 0x62, 0x97, 0xc0, 0x00, 0x02, - 0xc0, 0x17, 0x0e, 0x00, 0x27, 0x00, 0x34, 0x01, - 0x27, 0x0c, 0x0c, 0x00, 0x36, 0x01, 0xef, 0x57, - 0x00, 0x00, 0xf0, 0x09, 0x9f, 0xc0, 0xbe, 0x02, - 0xe7, 0x57, 0x00, 0x00, 0xb0, 0x08, 0x97, 0xc1, - 0xe7, 0x07, 0x09, 0x00, 0x12, 0xc0, 0xe7, 0x77, - 0x00, 0x08, 0x20, 0xc0, 0x9f, 0xc1, 0xb6, 0x02, - 0xe7, 0x57, 0x09, 0x00, 0x12, 0xc0, 0x77, 0xc9, - 0xd7, 0x09, 0x00, 0xc0, 0xc1, 0xdf, 0xe7, 0x77, - 0x00, 0x08, 0x20, 0xc0, 0x2f, 0xc1, 0xe7, 0x07, - 0x00, 0x00, 0x42, 0xc0, 0xe7, 0x07, 0x05, 0x00, - 0x90, 0xc0, 0xc8, 0x07, 0x0a, 0x00, 0xe7, 0x77, - 0x04, 0x00, 0x20, 0xc0, 0x09, 0xc1, 0x08, 0xda, - 0x7a, 0xc1, 0xe7, 0x07, 0x00, 0x01, 0x42, 0xc0, - 0xe7, 0x07, 0x04, 0x00, 0x90, 0xc0, 0x1a, 0xcf, - 0xe7, 0x07, 0x01, 0x00, 0x7a, 0x08, 0x00, 0xd8, - 0x27, 0x50, 0x34, 0x01, 0x17, 0xc1, 0xe7, 0x77, - 0x02, 0x00, 0x20, 0xc0, 0x79, 0xc1, 0x27, 0x50, - 0x34, 0x01, 0x10, 0xc1, 0xe7, 0x77, 0x02, 0x00, - 0x20, 0xc0, 0x79, 0xc0, 0x9f, 0xaf, 0xd8, 0x02, - 0xe7, 0x05, 0x00, 0xc0, 0x00, 0x60, 0x9f, 0xc0, - 0xde, 0x01, 0x97, 0xcf, 0xe7, 0x07, 0x01, 0x00, - 0xb8, 0x08, 0x06, 0xcf, 0xe7, 0x07, 0x30, 0x0e, - 0x02, 0x00, 0xe7, 0x07, 0x50, 0xc3, 0x12, 0xc0, - 0xe7, 0x05, 0x00, 0xc0, 0x97, 0xcf, 0xe7, 0x07, - 0x01, 0x00, 0xb8, 0x08, 0x97, 0xcf, 0xe7, 0x07, - 0x50, 0xc3, 0x12, 0xc0, 0xe7, 0x07, 0x30, 0x0e, - 0x02, 0x00, 0xe7, 0x07, 0x01, 0x00, 0x7a, 0x08, - 0xe7, 0x07, 0x05, 0x00, 0x90, 0xc0, 0x97, 0xcf, - 0xe7, 0x07, 0x00, 0x01, 0x42, 0xc0, 0xe7, 0x07, - 0x04, 0x00, 0x90, 0xc0, 0xe7, 0x07, 0x00, 0x00, - 0x7a, 0x08, 0xe7, 0x57, 0x0f, 0x00, 0xb2, 0x08, - 0x13, 0xc1, 0x9f, 0xaf, 0x2e, 0x08, 0xca, 0x09, - 0xac, 0x08, 0xf2, 0x17, 0x01, 0x00, 0x5c, 0x00, - 0xf2, 0x27, 0x00, 0x00, 0x5e, 0x00, 0xe7, 0x07, - 0x00, 0x00, 0xb2, 0x08, 0xe7, 0x07, 0x01, 0x00, - 0xb4, 0x08, 0xc0, 0x07, 0xff, 0xff, 0x97, 0xcf, - 0x9f, 0xaf, 0x4c, 0x03, 0xc0, 0x69, 0xb4, 0x08, - 0x57, 0x00, 0x9f, 0xde, 0x33, 0x00, 0xc1, 0x05, - 0x27, 0xd8, 0xb2, 0x08, 0x27, 0xd2, 0xb4, 0x08, - 0xe7, 0x87, 0x01, 0x00, 0xb4, 0x08, 0xe7, 0x67, - 0xff, 0x03, 0xb4, 0x08, 0x00, 0x60, 0x97, 0xc0, - 0xe7, 0x07, 0x01, 0x00, 0xb0, 0x08, 0x27, 0x00, - 0x12, 0xc0, 0x97, 0xcf, 0xc0, 0x09, 0xb6, 0x08, - 0x00, 0xd2, 0x02, 0xc3, 0xc0, 0x97, 0x05, 0x80, - 0x27, 0x00, 0xb6, 0x08, 0xc0, 0x99, 0x82, 0x08, - 0xc0, 0x99, 0xa2, 0xc0, 0x97, 0xcf, 0xe7, 0x07, - 0x00, 0x00, 0xb0, 0x08, 0xc0, 0xdf, 0x97, 0xcf, - 0xc8, 0x09, 0x72, 0x08, 0x08, 0x62, 0x02, 0xc0, - 0x10, 0x64, 0x07, 0xc1, 0xe7, 0x07, 0x00, 0x00, - 0x64, 0x08, 0xe7, 0x07, 0xc8, 0x05, 0x24, 0x00, - 0x97, 0xcf, 0x27, 0x04, 0x72, 0x08, 0xc8, 0x17, - 0x0e, 0x00, 0x27, 0x02, 0x64, 0x08, 0xe7, 0x07, - 0xd6, 0x05, 0x24, 0x00, 0x97, 0xcf, 0xd7, 0x09, - 0x00, 0xc0, 0xc1, 0xdf, 0xe7, 0x57, 0x00, 0x00, - 0x62, 0x08, 0x13, 0xc1, 0x9f, 0xaf, 0x70, 0x03, - 0xe7, 0x57, 0x00, 0x00, 0x64, 0x08, 0x13, 0xc0, - 0xe7, 0x09, 0x64, 0x08, 0x30, 0x01, 0xe7, 0x07, - 0xf2, 0x05, 0x32, 0x01, 0xe7, 0x07, 0x10, 0x00, - 0x96, 0xc0, 0xe7, 0x09, 0x64, 0x08, 0x62, 0x08, - 0x04, 0xcf, 0xe7, 0x57, 0x00, 0x00, 0x64, 0x08, - 0x02, 0xc1, 0x9f, 0xaf, 0x70, 0x03, 0xe7, 0x05, - 0x00, 0xc0, 0x97, 0xcf, 0xd7, 0x09, 0x00, 0xc0, - 0xc1, 0xdf, 0xc8, 0x09, 0x72, 0x08, 0x27, 0x02, - 0x78, 0x08, 0x08, 0x62, 0x03, 0xc1, 0xe7, 0x05, - 0x00, 0xc0, 0x97, 0xcf, 0x27, 0x04, 0x72, 0x08, - 0xe7, 0x05, 0x00, 0xc0, 0xf0, 0x07, 0x40, 0x00, - 0x08, 0x00, 0xf0, 0x07, 0x00, 0x00, 0x04, 0x00, - 0x00, 0x02, 0xc0, 0x17, 0x0c, 0x00, 0x30, 0x00, - 0x06, 0x00, 0xf0, 0x07, 0x64, 0x01, 0x0a, 0x00, - 0xc8, 0x17, 0x04, 0x00, 0xc1, 0x07, 0x02, 0x00, - 0x51, 0xaf, 0x97, 0xcf, 0xe7, 0x57, 0x00, 0x00, - 0x6a, 0x08, 0x97, 0xc0, 0xc1, 0xdf, 0xc8, 0x09, - 0x6a, 0x08, 0x27, 0x04, 0x6a, 0x08, 0x27, 0x52, - 0x6c, 0x08, 0x03, 0xc1, 0xe7, 0x07, 0x6a, 0x08, - 0x6c, 0x08, 0xc0, 0xdf, 0x17, 0x02, 0xc8, 0x17, - 0x0e, 0x00, 0x9f, 0xaf, 0x16, 0x05, 0xc8, 0x05, - 0x00, 0x60, 0x03, 0xc0, 0x9f, 0xaf, 0x80, 0x04, - 0x97, 0xcf, 0x9f, 0xaf, 0x68, 0x04, 0x97, 0xcf, - 0xd7, 0x09, 0x00, 0xc0, 0xc1, 0xdf, 0x08, 0x62, - 0x1c, 0xc0, 0xd0, 0x09, 0x72, 0x08, 0x27, 0x02, - 0x72, 0x08, 0xe7, 0x05, 0x00, 0xc0, 0x97, 0xcf, - 0x97, 0x02, 0xca, 0x09, 0xac, 0x08, 0xf2, 0x17, - 0x01, 0x00, 0x04, 0x00, 0xf2, 0x27, 0x00, 0x00, - 0x06, 0x00, 0xca, 0x17, 0x2c, 0x00, 0xf8, 0x77, - 0x01, 0x00, 0x0e, 0x00, 0x06, 0xc0, 0xca, 0xd9, - 0xf8, 0x57, 0xff, 0x00, 0x0e, 0x00, 0x01, 0xc1, - 0xca, 0xd9, 0x22, 0x1c, 0x0c, 0x00, 0xe2, 0x27, - 0x00, 0x00, 0xe2, 0x17, 0x01, 0x00, 0xe2, 0x27, - 0x00, 0x00, 0xca, 0x05, 0x00, 0x0c, 0x0c, 0x00, - 0xc0, 0x17, 0x41, 0x00, 0xc0, 0x67, 0xc0, 0xff, - 0x30, 0x00, 0x08, 0x00, 0x00, 0x02, 0xc0, 0x17, - 0x0c, 0x00, 0x30, 0x00, 0x06, 0x00, 0xf0, 0x07, - 0xdc, 0x00, 0x0a, 0x00, 0xf0, 0x07, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x0c, 0x08, 0x00, 0x40, 0xd1, - 0x01, 0x00, 0xc0, 0x19, 0xa6, 0x08, 0xc0, 0x59, - 0x98, 0x08, 0x04, 0xc9, 0x49, 0xaf, 0x9f, 0xaf, - 0xee, 0x00, 0x4a, 0xaf, 0x67, 0x10, 0xa6, 0x08, - 0xc8, 0x17, 0x04, 0x00, 0xc1, 0x07, 0x01, 0x00, - 0xd7, 0x09, 0x00, 0xc0, 0xc1, 0xdf, 0x50, 0xaf, - 0xe7, 0x05, 0x00, 0xc0, 0x97, 0xcf, 0xc0, 0x07, - 0x01, 0x00, 0xc1, 0x09, 0x7c, 0x08, 0xc1, 0x77, - 0x01, 0x00, 0x97, 0xc1, 0xd8, 0x77, 0x01, 0x00, - 0x12, 0xc0, 0xc9, 0x07, 0x4c, 0x08, 0x9f, 0xaf, - 0x64, 0x05, 0x04, 0xc1, 0xc1, 0x77, 0x08, 0x00, - 0x13, 0xc0, 0x97, 0xcf, 0xc1, 0x77, 0x02, 0x00, - 0x97, 0xc1, 0xc1, 0x77, 0x10, 0x00, 0x0c, 0xc0, - 0x9f, 0xaf, 0x86, 0x05, 0x97, 0xcf, 0xc1, 0x77, - 0x04, 0x00, 0x06, 0xc0, 0xc9, 0x07, 0x7e, 0x08, - 0x9f, 0xaf, 0x64, 0x05, 0x97, 0xc0, 0x00, 0xcf, - 0x00, 0x90, 0x97, 0xcf, 0x50, 0x54, 0x97, 0xc1, - 0x70, 0x5c, 0x02, 0x00, 0x02, 0x00, 0x97, 0xc1, - 0x70, 0x5c, 0x04, 0x00, 0x04, 0x00, 0x97, 0xcf, - 0xc0, 0x00, 0x60, 0x00, 0x30, 0x00, 0x18, 0x00, - 0x0c, 0x00, 0x06, 0x00, 0x00, 0x00, 0xcb, 0x09, - 0x88, 0x08, 0xcc, 0x09, 0x8a, 0x08, 0x0b, 0x53, - 0x11, 0xc0, 0xc9, 0x02, 0xca, 0x07, 0x78, 0x05, - 0x9f, 0xaf, 0x64, 0x05, 0x97, 0xc0, 0x0a, 0xc8, - 0x82, 0x08, 0x0a, 0xcf, 0x82, 0x08, 0x9f, 0xaf, - 0x64, 0x05, 0x97, 0xc0, 0x05, 0xc2, 0x89, 0x30, - 0x82, 0x60, 0x78, 0xc1, 0x00, 0x90, 0x97, 0xcf, - 0x89, 0x10, 0x09, 0x53, 0x79, 0xc2, 0x89, 0x30, - 0x82, 0x08, 0x7a, 0xcf, 0xc0, 0xdf, 0x97, 0xcf, - 0xe7, 0x09, 0x96, 0xc0, 0x66, 0x08, 0xe7, 0x09, - 0x98, 0xc0, 0x68, 0x08, 0x0f, 0xcf, 0xe7, 0x09, - 0x96, 0xc0, 0x66, 0x08, 0xe7, 0x09, 0x98, 0xc0, - 0x68, 0x08, 0xe7, 0x09, 0x64, 0x08, 0x30, 0x01, - 0xe7, 0x07, 0xf2, 0x05, 0x32, 0x01, 0xe7, 0x07, - 0x10, 0x00, 0x96, 0xc0, 0xd7, 0x09, 0x00, 0xc0, - 0x17, 0x02, 0xc8, 0x09, 0x62, 0x08, 0xc8, 0x37, - 0x0e, 0x00, 0xe7, 0x57, 0x04, 0x00, 0x68, 0x08, - 0x3d, 0xc0, 0xe7, 0x87, 0x00, 0x08, 0x24, 0xc0, - 0xe7, 0x09, 0x94, 0x08, 0xba, 0x08, 0xe7, 0x17, - 0x64, 0x00, 0xba, 0x08, 0xe7, 0x67, 0xff, 0x07, - 0xba, 0x08, 0xe7, 0x77, 0x2a, 0x00, 0x66, 0x08, - 0x30, 0xc0, 0x97, 0x02, 0xca, 0x09, 0xac, 0x08, - 0xe7, 0x77, 0x20, 0x00, 0x66, 0x08, 0x0e, 0xc0, - 0xf2, 0x17, 0x01, 0x00, 0x10, 0x00, 0xf2, 0x27, - 0x00, 0x00, 0x12, 0x00, 0xe7, 0x77, 0x0a, 0x00, - 0x66, 0x08, 0xca, 0x05, 0x1e, 0xc0, 0x97, 0x02, - 0xca, 0x09, 0xac, 0x08, 0xf2, 0x17, 0x01, 0x00, - 0x0c, 0x00, 0xf2, 0x27, 0x00, 0x00, 0x0e, 0x00, - 0xe7, 0x77, 0x02, 0x00, 0x66, 0x08, 0x07, 0xc0, - 0xf2, 0x17, 0x01, 0x00, 0x44, 0x00, 0xf2, 0x27, - 0x00, 0x00, 0x46, 0x00, 0x06, 0xcf, 0xf2, 0x17, - 0x01, 0x00, 0x60, 0x00, 0xf2, 0x27, 0x00, 0x00, - 0x62, 0x00, 0xca, 0x05, 0x9f, 0xaf, 0x68, 0x04, - 0x0f, 0xcf, 0x57, 0x02, 0x09, 0x02, 0xf1, 0x09, - 0x68, 0x08, 0x0c, 0x00, 0xf1, 0xda, 0x0c, 0x00, - 0xc8, 0x09, 0x6c, 0x08, 0x50, 0x02, 0x67, 0x02, - 0x6c, 0x08, 0xd1, 0x07, 0x00, 0x00, 0xc9, 0x05, - 0xe7, 0x09, 0x64, 0x08, 0x62, 0x08, 0xe7, 0x57, - 0x00, 0x00, 0x62, 0x08, 0x02, 0xc0, 0x9f, 0xaf, - 0x70, 0x03, 0xc8, 0x05, 0xe7, 0x05, 0x00, 0xc0, - 0xc0, 0xdf, 0x97, 0xcf, 0xd7, 0x09, 0x00, 0xc0, - 0x17, 0x00, 0x17, 0x02, 0x97, 0x02, 0xc0, 0x09, - 0x92, 0xc0, 0xe7, 0x87, 0x00, 0x08, 0x24, 0xc0, - 0xe7, 0x09, 0x94, 0x08, 0xba, 0x08, 0xe7, 0x17, - 0x64, 0x00, 0xba, 0x08, 0xe7, 0x67, 0xff, 0x07, - 0xba, 0x08, 0xe7, 0x07, 0x04, 0x00, 0x90, 0xc0, - 0xca, 0x09, 0xac, 0x08, 0xe7, 0x07, 0x00, 0x00, - 0x7a, 0x08, 0xe7, 0x07, 0x66, 0x03, 0x02, 0x00, - 0xc0, 0x77, 0x02, 0x00, 0x10, 0xc0, 0xef, 0x57, - 0x00, 0x00, 0xf0, 0x09, 0x04, 0xc0, 0x9f, 0xaf, - 0xd8, 0x02, 0x9f, 0xcf, 0x12, 0x08, 0xf2, 0x17, - 0x01, 0x00, 0x50, 0x00, 0xf2, 0x27, 0x00, 0x00, - 0x52, 0x00, 0x9f, 0xcf, 0x12, 0x08, 0xef, 0x57, - 0x00, 0x00, 0xf0, 0x09, 0x08, 0xc0, 0xe7, 0x57, - 0x00, 0x00, 0xb8, 0x08, 0xe7, 0x07, 0x00, 0x00, - 0xb8, 0x08, 0x0a, 0xc0, 0x03, 0xcf, 0xc0, 0x77, - 0x10, 0x00, 0x06, 0xc0, 0xf2, 0x17, 0x01, 0x00, - 0x58, 0x00, 0xf2, 0x27, 0x00, 0x00, 0x5a, 0x00, - 0xc0, 0x77, 0x80, 0x00, 0x06, 0xc0, 0xf2, 0x17, - 0x01, 0x00, 0x70, 0x00, 0xf2, 0x27, 0x00, 0x00, - 0x72, 0x00, 0xc0, 0x77, 0x08, 0x00, 0x1d, 0xc1, - 0xf2, 0x17, 0x01, 0x00, 0x08, 0x00, 0xf2, 0x27, - 0x00, 0x00, 0x0a, 0x00, 0xc0, 0x77, 0x00, 0x02, - 0x06, 0xc0, 0xf2, 0x17, 0x01, 0x00, 0x64, 0x00, - 0xf2, 0x27, 0x00, 0x00, 0x66, 0x00, 0xc0, 0x77, - 0x40, 0x00, 0x06, 0xc0, 0xf2, 0x17, 0x01, 0x00, - 0x5c, 0x00, 0xf2, 0x27, 0x00, 0x00, 0x5e, 0x00, - 0xc0, 0x77, 0x01, 0x00, 0x01, 0xc0, 0x37, 0xcf, - 0x36, 0xcf, 0xf2, 0x17, 0x01, 0x00, 0x00, 0x00, - 0xf2, 0x27, 0x00, 0x00, 0x02, 0x00, 0xef, 0x57, - 0x00, 0x00, 0xf0, 0x09, 0x18, 0xc0, 0xe7, 0x57, - 0x01, 0x00, 0xb2, 0x08, 0x0e, 0xc2, 0x07, 0xc8, - 0xf2, 0x17, 0x01, 0x00, 0x50, 0x00, 0xf2, 0x27, - 0x00, 0x00, 0x52, 0x00, 0x06, 0xcf, 0xf2, 0x17, - 0x01, 0x00, 0x54, 0x00, 0xf2, 0x27, 0x00, 0x00, - 0x56, 0x00, 0xe7, 0x07, 0x00, 0x00, 0xb2, 0x08, - 0xe7, 0x07, 0x01, 0x00, 0xb4, 0x08, 0xc8, 0x09, - 0x34, 0x01, 0xca, 0x17, 0x14, 0x00, 0xd8, 0x77, - 0x01, 0x00, 0x05, 0xc0, 0xca, 0xd9, 0xd8, 0x57, - 0xff, 0x00, 0x01, 0xc0, 0xca, 0xd9, 0xe2, 0x19, - 0x94, 0xc0, 0xe2, 0x27, 0x00, 0x00, 0xe2, 0x17, - 0x01, 0x00, 0xe2, 0x27, 0x00, 0x00, 0x9f, 0xaf, - 0x2e, 0x08, 0x9f, 0xaf, 0xde, 0x01, 0xe7, 0x57, - 0x00, 0x00, 0xaa, 0x08, 0x9f, 0xa1, 0xf0, 0x0b, - 0xca, 0x05, 0xc8, 0x05, 0xc0, 0x05, 0xe7, 0x05, - 0x00, 0xc0, 0xc0, 0xdf, 0x97, 0xcf, 0xc8, 0x09, - 0x6e, 0x08, 0x08, 0x62, 0x97, 0xc0, 0x27, 0x04, - 0x6e, 0x08, 0x27, 0x52, 0x70, 0x08, 0x03, 0xc1, - 0xe7, 0x07, 0x6e, 0x08, 0x70, 0x08, 0x9f, 0xaf, - 0x68, 0x04, 0x97, 0xcf, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x33, 0xcc, - 0x00, 0x00, 0x00, 0x00, 0xe7, 0x57, 0x00, 0x80, - 0xb2, 0x00, 0x06, 0xc2, 0xe7, 0x07, 0x52, 0x0e, - 0x12, 0x00, 0xe7, 0x07, 0x98, 0x0e, 0xb2, 0x00, - 0xe7, 0x07, 0xa4, 0x09, 0xf2, 0x02, 0xc8, 0x09, - 0xb4, 0x00, 0xf8, 0x07, 0x02, 0x00, 0x0d, 0x00, - 0xd7, 0x09, 0x0e, 0xc0, 0xe7, 0x07, 0x00, 0x00, - 0x0e, 0xc0, 0xc8, 0x09, 0xdc, 0x00, 0xf0, 0x07, - 0xff, 0xff, 0x09, 0x00, 0xf0, 0x07, 0xfb, 0x13, - 0x0b, 0x00, 0xe7, 0x09, 0xc0, 0x00, 0x58, 0x08, - 0xe7, 0x09, 0xbe, 0x00, 0x54, 0x08, 0xe7, 0x09, - 0x10, 0x00, 0x92, 0x08, 0xc8, 0x07, 0xb4, 0x09, - 0x9f, 0xaf, 0x8c, 0x09, 0x9f, 0xaf, 0xe2, 0x0b, - 0xc0, 0x07, 0x80, 0x01, 0x44, 0xaf, 0x27, 0x00, - 0x88, 0x08, 0x27, 0x00, 0x8a, 0x08, 0x27, 0x00, - 0x8c, 0x08, 0xc0, 0x07, 0x74, 0x00, 0x44, 0xaf, - 0x27, 0x00, 0xac, 0x08, 0x08, 0x00, 0x00, 0x90, - 0xc1, 0x07, 0x1d, 0x00, 0x20, 0x00, 0x20, 0x00, - 0x01, 0xda, 0x7c, 0xc1, 0x9f, 0xaf, 0x8a, 0x0b, - 0xc0, 0x07, 0x4c, 0x00, 0x48, 0xaf, 0x27, 0x00, - 0x56, 0x08, 0x9f, 0xaf, 0x72, 0x0c, 0xe7, 0x07, - 0x00, 0x80, 0x96, 0x08, 0xef, 0x57, 0x00, 0x00, - 0xf0, 0x09, 0x03, 0xc0, 0xe7, 0x07, 0x01, 0x00, - 0x1c, 0xc0, 0xe7, 0x05, 0x0e, 0xc0, 0x97, 0xcf, - 0x49, 0xaf, 0xe7, 0x87, 0x43, 0x00, 0x0e, 0xc0, - 0xe7, 0x07, 0xff, 0xff, 0x94, 0x08, 0x9f, 0xaf, - 0x8a, 0x0c, 0xc0, 0x07, 0x01, 0x00, 0x60, 0xaf, - 0x4a, 0xaf, 0x97, 0xcf, 0x00, 0x08, 0x09, 0x08, - 0x11, 0x08, 0x00, 0xda, 0x7c, 0xc1, 0x97, 0xcf, - 0x67, 0x04, 0xcc, 0x02, 0xc0, 0xdf, 0x51, 0x94, - 0xb1, 0xaf, 0x06, 0x00, 0xc1, 0xdf, 0xc9, 0x09, - 0xcc, 0x02, 0x49, 0x62, 0x75, 0xc1, 0xc0, 0xdf, - 0xa7, 0xcf, 0xd6, 0x02, 0x0e, 0x00, 0x24, 0x00, - 0xd6, 0x05, 0x22, 0x00, 0xc4, 0x06, 0xd0, 0x00, - 0xf0, 0x0b, 0xaa, 0x00, 0x0e, 0x0a, 0xbe, 0x00, - 0x2c, 0x0c, 0x10, 0x00, 0x20, 0x00, 0x04, 0x00, - 0xc4, 0x05, 0x02, 0x00, 0x66, 0x03, 0x06, 0x00, - 0x00, 0x00, 0x24, 0xc0, 0x04, 0x04, 0x28, 0xc0, - 0xfe, 0xfb, 0x1e, 0xc0, 0x00, 0x04, 0x22, 0xc0, - 0xff, 0xf0, 0xc0, 0x00, 0x60, 0x0b, 0x00, 0x00, - 0x00, 0x00, 0xff, 0xff, 0x34, 0x0a, 0x3e, 0x0a, - 0x9e, 0x0a, 0xa8, 0x0a, 0xce, 0x0a, 0xd2, 0x0a, - 0xd6, 0x0a, 0x00, 0x0b, 0x10, 0x0b, 0x1e, 0x0b, - 0x20, 0x0b, 0x28, 0x0b, 0x28, 0x0b, 0x27, 0x02, - 0xa2, 0x08, 0x97, 0xcf, 0xe7, 0x07, 0x00, 0x00, - 0xa2, 0x08, 0x0a, 0x0e, 0x01, 0x00, 0xca, 0x57, - 0x0e, 0x00, 0x9f, 0xc3, 0x2a, 0x0b, 0xca, 0x37, - 0x00, 0x00, 0x9f, 0xc2, 0x2a, 0x0b, 0x0a, 0xd2, - 0xb2, 0xcf, 0xf4, 0x09, 0xc8, 0x09, 0xde, 0x00, - 0x07, 0x06, 0x9f, 0xcf, 0x3c, 0x0b, 0xf0, 0x57, - 0x80, 0x01, 0x06, 0x00, 0x9f, 0xc8, 0x2a, 0x0b, - 0x27, 0x0c, 0x02, 0x00, 0x86, 0x08, 0xc0, 0x09, - 0x88, 0x08, 0x27, 0x00, 0x8a, 0x08, 0xe7, 0x07, - 0x00, 0x00, 0x84, 0x08, 0x27, 0x00, 0x5c, 0x08, - 0x00, 0x1c, 0x06, 0x00, 0x27, 0x00, 0x8c, 0x08, - 0x41, 0x90, 0x67, 0x50, 0x86, 0x08, 0x0d, 0xc0, - 0x67, 0x00, 0x5a, 0x08, 0x27, 0x0c, 0x06, 0x00, - 0x5e, 0x08, 0xe7, 0x07, 0x8a, 0x0a, 0x60, 0x08, - 0xc8, 0x07, 0x5a, 0x08, 0x41, 0x90, 0x51, 0xaf, - 0x97, 0xcf, 0x9f, 0xaf, 0xac, 0x0e, 0xe7, 0x09, - 0x8c, 0x08, 0x8a, 0x08, 0xe7, 0x09, 0x86, 0x08, - 0x84, 0x08, 0x59, 0xaf, 0x97, 0xcf, 0x27, 0x0c, - 0x02, 0x00, 0x7c, 0x08, 0x59, 0xaf, 0x97, 0xcf, - 0x09, 0x0c, 0x02, 0x00, 0x09, 0xda, 0x49, 0xd2, - 0xc9, 0x19, 0xac, 0x08, 0xc8, 0x07, 0x5a, 0x08, - 0xe0, 0x07, 0x00, 0x00, 0x60, 0x02, 0xe0, 0x07, - 0x04, 0x00, 0xd0, 0x07, 0x9a, 0x0a, 0x48, 0xdb, - 0x41, 0x90, 0x50, 0xaf, 0x97, 0xcf, 0x59, 0xaf, - 0x97, 0xcf, 0x59, 0xaf, 0x97, 0xcf, 0xf0, 0x57, - 0x06, 0x00, 0x06, 0x00, 0x26, 0xc1, 0xe7, 0x07, - 0x7e, 0x08, 0x5c, 0x08, 0x41, 0x90, 0x67, 0x00, - 0x5a, 0x08, 0x27, 0x0c, 0x06, 0x00, 0x5e, 0x08, - 0xe7, 0x07, 0x5c, 0x0b, 0x60, 0x08, 0xc8, 0x07, - 0x5a, 0x08, 0x41, 0x90, 0x51, 0xaf, 0x97, 0xcf, - 0x07, 0x0c, 0x06, 0x00, 0xc7, 0x57, 0x06, 0x00, - 0x10, 0xc1, 0xc8, 0x07, 0x7e, 0x08, 0x16, 0xcf, - 0x00, 0x0c, 0x02, 0x00, 0x00, 0xda, 0x40, 0xd1, - 0x27, 0x00, 0x98, 0x08, 0x1f, 0xcf, 0x1e, 0xcf, - 0x27, 0x0c, 0x02, 0x00, 0xa4, 0x08, 0x1a, 0xcf, - 0x00, 0xcf, 0x27, 0x02, 0x20, 0x01, 0xe7, 0x07, - 0x08, 0x00, 0x22, 0x01, 0xe7, 0x07, 0x13, 0x00, - 0xb0, 0xc0, 0x97, 0xcf, 0x41, 0x90, 0x67, 0x00, - 0x5a, 0x08, 0xe7, 0x01, 0x5e, 0x08, 0x27, 0x02, - 0x5c, 0x08, 0xe7, 0x07, 0x5c, 0x0b, 0x60, 0x08, - 0xc8, 0x07, 0x5a, 0x08, 0xc1, 0x07, 0x00, 0x80, - 0x50, 0xaf, 0x97, 0xcf, 0x59, 0xaf, 0x97, 0xcf, - 0x00, 0x60, 0x05, 0xc0, 0xe7, 0x07, 0x00, 0x00, - 0x9a, 0x08, 0xa7, 0xcf, 0x58, 0x08, 0x9f, 0xaf, - 0xe2, 0x0b, 0xe7, 0x07, 0x01, 0x00, 0x9a, 0x08, - 0x49, 0xaf, 0xd7, 0x09, 0x00, 0xc0, 0x07, 0xaf, - 0xe7, 0x05, 0x00, 0xc0, 0x4a, 0xaf, 0xa7, 0xcf, - 0x58, 0x08, 0xc0, 0x07, 0x40, 0x00, 0x44, 0xaf, - 0x27, 0x00, 0xa0, 0x08, 0x08, 0x00, 0xc0, 0x07, - 0x20, 0x00, 0x20, 0x94, 0x00, 0xda, 0x7d, 0xc1, - 0xc0, 0x07, 0xfe, 0x7f, 0x44, 0xaf, 0x40, 0x00, - 0x41, 0x90, 0xc0, 0x37, 0x08, 0x00, 0xdf, 0xde, - 0x50, 0x06, 0xc0, 0x57, 0x10, 0x00, 0x02, 0xc2, - 0xc0, 0x07, 0x10, 0x00, 0x27, 0x00, 0x76, 0x08, - 0x41, 0x90, 0x9f, 0xde, 0x40, 0x06, 0x44, 0xaf, - 0x27, 0x00, 0x74, 0x08, 0xc0, 0x09, 0x76, 0x08, - 0x41, 0x90, 0x00, 0xd2, 0x00, 0xd8, 0x9f, 0xde, - 0x08, 0x00, 0x44, 0xaf, 0x27, 0x00, 0x9e, 0x08, - 0x97, 0xcf, 0xe7, 0x87, 0x00, 0x84, 0x28, 0xc0, - 0xe7, 0x67, 0xff, 0xf3, 0x24, 0xc0, 0x97, 0xcf, - 0xe7, 0x87, 0x01, 0x00, 0xaa, 0x08, 0xe7, 0x57, - 0x00, 0x00, 0x7a, 0x08, 0x97, 0xc1, 0x9f, 0xaf, - 0xe2, 0x0b, 0xe7, 0x87, 0x00, 0x06, 0x22, 0xc0, - 0xe7, 0x07, 0x00, 0x00, 0x90, 0xc0, 0xe7, 0x67, - 0xfe, 0xff, 0x3e, 0xc0, 0xe7, 0x07, 0x2e, 0x00, - 0x0a, 0xc0, 0xe7, 0x87, 0x01, 0x00, 0x3e, 0xc0, - 0xe7, 0x07, 0xff, 0xff, 0x94, 0x08, 0x9f, 0xaf, - 0xf0, 0x0c, 0x97, 0xcf, 0x17, 0x00, 0xa7, 0xaf, - 0x54, 0x08, 0xc0, 0x05, 0x27, 0x00, 0x52, 0x08, - 0xe7, 0x87, 0x01, 0x00, 0xaa, 0x08, 0x9f, 0xaf, - 0xe2, 0x0b, 0xe7, 0x07, 0x0c, 0x00, 0x40, 0xc0, - 0x9f, 0xaf, 0xf0, 0x0c, 0xe7, 0x07, 0x00, 0x00, - 0x78, 0x08, 0x00, 0x90, 0xe7, 0x09, 0x88, 0x08, - 0x8a, 0x08, 0x27, 0x00, 0x84, 0x08, 0x27, 0x00, - 0x7c, 0x08, 0x9f, 0xaf, 0x8a, 0x0c, 0xe7, 0x07, - 0x00, 0x00, 0xb2, 0x02, 0xe7, 0x07, 0x00, 0x00, - 0xb4, 0x02, 0xc0, 0x07, 0x06, 0x00, 0xc8, 0x09, - 0xde, 0x00, 0xc8, 0x17, 0x03, 0x00, 0xc9, 0x07, - 0x7e, 0x08, 0x29, 0x0a, 0x00, 0xda, 0x7d, 0xc1, - 0x97, 0xcf, 0xd7, 0x09, 0x00, 0xc0, 0xc1, 0xdf, - 0x00, 0x90, 0x27, 0x00, 0x6a, 0x08, 0xe7, 0x07, - 0x6a, 0x08, 0x6c, 0x08, 0x27, 0x00, 0x6e, 0x08, - 0xe7, 0x07, 0x6e, 0x08, 0x70, 0x08, 0x27, 0x00, - 0x78, 0x08, 0x27, 0x00, 0x62, 0x08, 0x27, 0x00, - 0x64, 0x08, 0xc8, 0x09, 0x74, 0x08, 0xc1, 0x09, - 0x76, 0x08, 0xc9, 0x07, 0x72, 0x08, 0x11, 0x02, - 0x09, 0x02, 0xc8, 0x17, 0x40, 0x06, 0x01, 0xda, - 0x7a, 0xc1, 0x51, 0x94, 0xc8, 0x09, 0x9e, 0x08, - 0xc9, 0x07, 0x9c, 0x08, 0xc1, 0x09, 0x76, 0x08, - 0x01, 0xd2, 0x01, 0xd8, 0x11, 0x02, 0x09, 0x02, - 0xc8, 0x17, 0x08, 0x00, 0x01, 0xda, 0x7a, 0xc1, - 0x51, 0x94, 0xe7, 0x05, 0x00, 0xc0, 0x97, 0xcf, - 0xe7, 0x57, 0x00, 0x00, 0x52, 0x08, 0x97, 0xc0, - 0x9f, 0xaf, 0x04, 0x00, 0xe7, 0x09, 0x94, 0x08, - 0x90, 0x08, 0xe7, 0x57, 0xff, 0xff, 0x90, 0x08, - 0x04, 0xc1, 0xe7, 0x07, 0xf0, 0x0c, 0x8e, 0x08, - 0x97, 0xcf, 0xe7, 0x17, 0x32, 0x00, 0x90, 0x08, - 0xe7, 0x67, 0xff, 0x07, 0x90, 0x08, 0xe7, 0x07, - 0x26, 0x0d, 0x8e, 0x08, 0x97, 0xcf, 0xd7, 0x09, - 0x00, 0xc0, 0xc1, 0xdf, 0xe7, 0x57, 0x00, 0x00, - 0x96, 0x08, 0x23, 0xc0, 0xe7, 0x07, 0x00, 0x80, - 0x80, 0xc0, 0xe7, 0x07, 0x04, 0x00, 0x90, 0xc0, - 0xe7, 0x07, 0x00, 0x00, 0x80, 0xc0, 0xe7, 0x07, - 0x00, 0x80, 0x80, 0xc0, 0xc0, 0x07, 0x00, 0x00, - 0xc0, 0x07, 0x00, 0x00, 0xc0, 0x07, 0x00, 0x00, - 0xe7, 0x07, 0x00, 0x00, 0x80, 0xc0, 0xe7, 0x07, - 0x00, 0x80, 0x80, 0xc0, 0xe7, 0x07, 0x00, 0x80, - 0x40, 0xc0, 0xc0, 0x07, 0x00, 0x00, 0xe7, 0x07, - 0x00, 0x00, 0x40, 0xc0, 0xe7, 0x07, 0x00, 0x00, - 0x80, 0xc0, 0xef, 0x57, 0x00, 0x00, 0xf1, 0x09, - 0x9f, 0xa0, 0xc0, 0x0d, 0xe7, 0x07, 0x04, 0x00, - 0x90, 0xc0, 0xe7, 0x07, 0x00, 0x02, 0x40, 0xc0, - 0xe7, 0x07, 0x0c, 0x02, 0x40, 0xc0, 0xe7, 0x07, - 0x00, 0x00, 0x96, 0x08, 0xe7, 0x07, 0x00, 0x00, - 0x8e, 0x08, 0xe7, 0x07, 0x00, 0x00, 0xaa, 0x08, - 0xd7, 0x09, 0x00, 0xc0, 0xc1, 0xdf, 0x9f, 0xaf, - 0x9e, 0x03, 0xe7, 0x05, 0x00, 0xc0, 0x9f, 0xaf, - 0xde, 0x01, 0xe7, 0x05, 0x00, 0xc0, 0x97, 0xcf, - 0x9f, 0xaf, 0xde, 0x0d, 0xef, 0x77, 0x00, 0x00, - 0xf1, 0x09, 0x97, 0xc1, 0x9f, 0xaf, 0xde, 0x0d, - 0xef, 0x77, 0x00, 0x00, 0xf1, 0x09, 0x97, 0xc1, - 0xef, 0x07, 0x01, 0x00, 0xf1, 0x09, 0xe7, 0x87, - 0x00, 0x08, 0x1e, 0xc0, 0xe7, 0x87, 0x00, 0x08, - 0x22, 0xc0, 0xe7, 0x67, 0xff, 0xf7, 0x22, 0xc0, - 0xe7, 0x77, 0x00, 0x08, 0x20, 0xc0, 0x11, 0xc0, - 0xe7, 0x67, 0xff, 0xf7, 0x1e, 0xc0, 0xe7, 0x87, - 0x00, 0x08, 0x22, 0xc0, 0xe7, 0x67, 0xff, 0xf7, - 0x22, 0xc0, 0xe7, 0x77, 0x00, 0x08, 0x20, 0xc0, - 0x04, 0xc1, 0xe7, 0x87, 0x00, 0x08, 0x22, 0xc0, - 0x97, 0xcf, 0xe7, 0x07, 0x01, 0x01, 0xf0, 0x09, - 0xef, 0x57, 0x18, 0x00, 0xfe, 0xff, 0x97, 0xc2, - 0xef, 0x07, 0x00, 0x00, 0xf0, 0x09, 0x97, 0xcf, - 0xd7, 0x09, 0x00, 0xc0, 0x17, 0x00, 0x17, 0x02, - 0x97, 0x02, 0xe7, 0x57, 0x00, 0x00, 0x7a, 0x08, - 0x06, 0xc0, 0xc0, 0x09, 0x92, 0xc0, 0xc0, 0x77, - 0x09, 0x02, 0x9f, 0xc1, 0xea, 0x06, 0x9f, 0xcf, - 0x20, 0x08, 0xd7, 0x09, 0x0e, 0xc0, 0xe7, 0x07, - 0x00, 0x00, 0x0e, 0xc0, 0x9f, 0xaf, 0x66, 0x0e, - 0xe7, 0x05, 0x0e, 0xc0, 0x97, 0xcf, 0xd7, 0x09, - 0x00, 0xc0, 0x17, 0x02, 0xc8, 0x09, 0xb0, 0xc0, - 0xe7, 0x67, 0xfe, 0x7f, 0xb0, 0xc0, 0xc8, 0x77, - 0x00, 0x20, 0x9f, 0xc1, 0x64, 0xeb, 0xe7, 0x57, - 0x00, 0x00, 0xc8, 0x02, 0x9f, 0xc1, 0x80, 0xeb, - 0xc8, 0x99, 0xca, 0x02, 0xc8, 0x67, 0x04, 0x00, - 0x9f, 0xc1, 0x96, 0xeb, 0x9f, 0xcf, 0x4c, 0xeb, - 0xe7, 0x07, 0x00, 0x00, 0xa6, 0xc0, 0xe7, 0x09, - 0xb0, 0xc0, 0xc8, 0x02, 0xe7, 0x07, 0x03, 0x00, - 0xb0, 0xc0, 0x97, 0xcf, 0xc0, 0x09, 0x86, 0x08, - 0xc0, 0x37, 0x01, 0x00, 0x97, 0xc9, 0xc9, 0x09, - 0x88, 0x08, 0x02, 0x00, 0x41, 0x90, 0x48, 0x02, - 0xc9, 0x17, 0x06, 0x00, 0x9f, 0xaf, 0x64, 0x05, - 0x9f, 0xa2, 0xd6, 0x0e, 0x02, 0xda, 0x77, 0xc1, - 0x41, 0x60, 0x71, 0xc1, 0x97, 0xcf, 0x17, 0x02, - 0x57, 0x02, 0x43, 0x04, 0x21, 0x04, 0xe0, 0x00, - 0x43, 0x04, 0x21, 0x04, 0xe0, 0x00, 0x43, 0x04, - 0x21, 0x04, 0xe0, 0x00, 0xc1, 0x07, 0x01, 0x00, - 0xc9, 0x05, 0xc8, 0x05, 0x97, 0xcf, - 0, 0 -}; - -/* Firmware fixup (data?) segment */ -static unsigned char kue_fix_seg[] = -{ - /******************************************/ - /* NOTE: B6/C3 is data header signature */ - /* 0xAA/0xBB is data length = total */ - /* bytes - 7, 0xCC is type, 0xDD is */ - /* interrupt to use. */ - /******************************************/ - 0xB6, 0xC3, 0xc9, 0x02, 0x03, 0x64, - 0x02, 0x00, 0x08, 0x00, 0x24, 0x00, 0x2e, 0x00, - 0x2c, 0x00, 0x3e, 0x00, 0x44, 0x00, 0x48, 0x00, - 0x50, 0x00, 0x5c, 0x00, 0x60, 0x00, 0x66, 0x00, - 0x6c, 0x00, 0x70, 0x00, 0x76, 0x00, 0x74, 0x00, - 0x7a, 0x00, 0x7e, 0x00, 0x84, 0x00, 0x8a, 0x00, - 0x8e, 0x00, 0x92, 0x00, 0x98, 0x00, 0x9c, 0x00, - 0xa0, 0x00, 0xa8, 0x00, 0xae, 0x00, 0xb4, 0x00, - 0xb2, 0x00, 0xba, 0x00, 0xbe, 0x00, 0xc4, 0x00, - 0xc8, 0x00, 0xce, 0x00, 0xd2, 0x00, 0xd6, 0x00, - 0xda, 0x00, 0xe2, 0x00, 0xe0, 0x00, 0xea, 0x00, - 0xf2, 0x00, 0xfe, 0x00, 0x06, 0x01, 0x0c, 0x01, - 0x1a, 0x01, 0x24, 0x01, 0x22, 0x01, 0x2a, 0x01, - 0x30, 0x01, 0x36, 0x01, 0x3c, 0x01, 0x4e, 0x01, - 0x52, 0x01, 0x58, 0x01, 0x5c, 0x01, 0x9c, 0x01, - 0xb6, 0x01, 0xba, 0x01, 0xc0, 0x01, 0xca, 0x01, - 0xd0, 0x01, 0xda, 0x01, 0xe2, 0x01, 0xea, 0x01, - 0xf0, 0x01, 0x0a, 0x02, 0x0e, 0x02, 0x14, 0x02, - 0x26, 0x02, 0x6c, 0x02, 0x8e, 0x02, 0x98, 0x02, - 0xa0, 0x02, 0xa6, 0x02, 0xba, 0x02, 0xc6, 0x02, - 0xce, 0x02, 0xe8, 0x02, 0xee, 0x02, 0xf4, 0x02, - 0xf8, 0x02, 0x0a, 0x03, 0x10, 0x03, 0x1a, 0x03, - 0x1e, 0x03, 0x2a, 0x03, 0x2e, 0x03, 0x34, 0x03, - 0x3a, 0x03, 0x44, 0x03, 0x4e, 0x03, 0x5a, 0x03, - 0x5e, 0x03, 0x6a, 0x03, 0x72, 0x03, 0x80, 0x03, - 0x84, 0x03, 0x8c, 0x03, 0x94, 0x03, 0x98, 0x03, - 0xa8, 0x03, 0xae, 0x03, 0xb4, 0x03, 0xba, 0x03, - 0xce, 0x03, 0xcc, 0x03, 0xd6, 0x03, 0xdc, 0x03, - 0xec, 0x03, 0xf0, 0x03, 0xfe, 0x03, 0x1c, 0x04, - 0x30, 0x04, 0x38, 0x04, 0x3c, 0x04, 0x40, 0x04, - 0x48, 0x04, 0x46, 0x04, 0x54, 0x04, 0x5e, 0x04, - 0x64, 0x04, 0x74, 0x04, 0x78, 0x04, 0x84, 0x04, - 0xd8, 0x04, 0xec, 0x04, 0xf0, 0x04, 0xf8, 0x04, - 0xfe, 0x04, 0x1c, 0x05, 0x2c, 0x05, 0x30, 0x05, - 0x4a, 0x05, 0x56, 0x05, 0x5a, 0x05, 0x88, 0x05, - 0x8c, 0x05, 0x96, 0x05, 0x9a, 0x05, 0xa8, 0x05, - 0xcc, 0x05, 0xd2, 0x05, 0xda, 0x05, 0xe0, 0x05, - 0xe4, 0x05, 0xfc, 0x05, 0x06, 0x06, 0x14, 0x06, - 0x12, 0x06, 0x1a, 0x06, 0x20, 0x06, 0x26, 0x06, - 0x2e, 0x06, 0x34, 0x06, 0x48, 0x06, 0x52, 0x06, - 0x64, 0x06, 0x86, 0x06, 0x90, 0x06, 0x9a, 0x06, - 0xa0, 0x06, 0xac, 0x06, 0xaa, 0x06, 0xb2, 0x06, - 0xb8, 0x06, 0xdc, 0x06, 0xda, 0x06, 0xe2, 0x06, - 0xe8, 0x06, 0xf2, 0x06, 0xf8, 0x06, 0xfc, 0x06, - 0x0a, 0x07, 0x10, 0x07, 0x14, 0x07, 0x24, 0x07, - 0x2a, 0x07, 0x32, 0x07, 0x38, 0x07, 0xb2, 0x07, - 0xba, 0x07, 0xde, 0x07, 0xe4, 0x07, 0x10, 0x08, - 0x14, 0x08, 0x1a, 0x08, 0x1e, 0x08, 0x30, 0x08, - 0x38, 0x08, 0x3c, 0x08, 0x44, 0x08, 0x42, 0x08, - 0x48, 0x08, 0xc6, 0x08, 0xcc, 0x08, 0xd2, 0x08, - 0xfe, 0x08, 0x04, 0x09, 0x0a, 0x09, 0x0e, 0x09, - 0x12, 0x09, 0x16, 0x09, 0x20, 0x09, 0x24, 0x09, - 0x28, 0x09, 0x32, 0x09, 0x46, 0x09, 0x4a, 0x09, - 0x50, 0x09, 0x54, 0x09, 0x5a, 0x09, 0x60, 0x09, - 0x7c, 0x09, 0x80, 0x09, 0xb8, 0x09, 0xbc, 0x09, - 0xc0, 0x09, 0xc4, 0x09, 0xc8, 0x09, 0xcc, 0x09, - 0xd0, 0x09, 0xd4, 0x09, 0xec, 0x09, 0xf4, 0x09, - 0xf6, 0x09, 0xf8, 0x09, 0xfa, 0x09, 0xfc, 0x09, - 0xfe, 0x09, 0x00, 0x0a, 0x02, 0x0a, 0x04, 0x0a, - 0x06, 0x0a, 0x08, 0x0a, 0x0a, 0x0a, 0x0c, 0x0a, - 0x10, 0x0a, 0x18, 0x0a, 0x24, 0x0a, 0x2c, 0x0a, - 0x32, 0x0a, 0x3c, 0x0a, 0x46, 0x0a, 0x4c, 0x0a, - 0x50, 0x0a, 0x54, 0x0a, 0x5a, 0x0a, 0x5e, 0x0a, - 0x66, 0x0a, 0x6c, 0x0a, 0x72, 0x0a, 0x78, 0x0a, - 0x7e, 0x0a, 0x7c, 0x0a, 0x82, 0x0a, 0x8c, 0x0a, - 0x92, 0x0a, 0x90, 0x0a, 0x98, 0x0a, 0x96, 0x0a, - 0xa2, 0x0a, 0xb2, 0x0a, 0xb6, 0x0a, 0xc4, 0x0a, - 0xe2, 0x0a, 0xe0, 0x0a, 0xe8, 0x0a, 0xee, 0x0a, - 0xf4, 0x0a, 0xf2, 0x0a, 0xf8, 0x0a, 0x0c, 0x0b, - 0x1a, 0x0b, 0x24, 0x0b, 0x40, 0x0b, 0x44, 0x0b, - 0x48, 0x0b, 0x4e, 0x0b, 0x4c, 0x0b, 0x52, 0x0b, - 0x68, 0x0b, 0x6c, 0x0b, 0x70, 0x0b, 0x76, 0x0b, - 0x88, 0x0b, 0x92, 0x0b, 0xbe, 0x0b, 0xca, 0x0b, - 0xce, 0x0b, 0xde, 0x0b, 0xf4, 0x0b, 0xfa, 0x0b, - 0x00, 0x0c, 0x24, 0x0c, 0x28, 0x0c, 0x30, 0x0c, - 0x36, 0x0c, 0x3c, 0x0c, 0x40, 0x0c, 0x4a, 0x0c, - 0x50, 0x0c, 0x58, 0x0c, 0x56, 0x0c, 0x5c, 0x0c, - 0x60, 0x0c, 0x64, 0x0c, 0x80, 0x0c, 0x94, 0x0c, - 0x9a, 0x0c, 0x98, 0x0c, 0x9e, 0x0c, 0xa4, 0x0c, - 0xa2, 0x0c, 0xa8, 0x0c, 0xac, 0x0c, 0xb0, 0x0c, - 0xb4, 0x0c, 0xb8, 0x0c, 0xbc, 0x0c, 0xce, 0x0c, - 0xd2, 0x0c, 0xd6, 0x0c, 0xf4, 0x0c, 0xfa, 0x0c, - 0x00, 0x0d, 0xfe, 0x0c, 0x06, 0x0d, 0x0e, 0x0d, - 0x0c, 0x0d, 0x16, 0x0d, 0x1c, 0x0d, 0x22, 0x0d, - 0x20, 0x0d, 0x30, 0x0d, 0x7e, 0x0d, 0x82, 0x0d, - 0x9a, 0x0d, 0xa0, 0x0d, 0xa6, 0x0d, 0xb0, 0x0d, - 0xb8, 0x0d, 0xc2, 0x0d, 0xc8, 0x0d, 0xce, 0x0d, - 0xd4, 0x0d, 0xdc, 0x0d, 0x1e, 0x0e, 0x2c, 0x0e, - 0x3e, 0x0e, 0x4c, 0x0e, 0x50, 0x0e, 0x5e, 0x0e, - 0xae, 0x0e, 0xb8, 0x0e, 0xc6, 0x0e, 0xca, 0x0e, - 0, 0 -}; - -/* Fixup command. */ -#define KUE_TRIGCMD_OFFSET 5 -static unsigned char kue_trig_seg[] = { -0xb6, 0xc3, 0x01, 0x00, 0x06, 0x64, 0x00, 0x00 -}; diff --git a/sys/bus/usb/ohci.c b/sys/bus/usb/ohci.c deleted file mode 100644 index 928f6dc3e2..0000000000 --- a/sys/bus/usb/ohci.c +++ /dev/null @@ -1,3616 +0,0 @@ -/* $NetBSD: ohci.c,v 1.138 2003/02/08 03:32:50 ichiro Exp $ */ -/* $FreeBSD: src/sys/dev/usb/ohci.c,v 1.154.2.4 2006/06/26 00:31:25 iedowse Exp $ */ - -/* Also, already ported: - * $NetBSD: ohci.c,v 1.140 2003/05/13 04:42:00 gson Exp $ - * $NetBSD: ohci.c,v 1.141 2003/09/10 20:08:29 mycroft Exp $ - * $NetBSD: ohci.c,v 1.142 2003/10/11 03:04:26 toshii Exp $ - * $NetBSD: ohci.c,v 1.143 2003/10/18 04:50:35 simonb Exp $ - * $NetBSD: ohci.c,v 1.144 2003/11/23 19:18:06 augustss Exp $ - * $NetBSD: ohci.c,v 1.145 2003/11/23 19:20:25 augustss Exp $ - * $NetBSD: ohci.c,v 1.146 2003/12/29 08:17:10 toshii Exp $ - * $NetBSD: ohci.c,v 1.147 2004/06/22 07:20:35 mycroft Exp $ - * $NetBSD: ohci.c,v 1.148 2004/06/22 18:27:46 mycroft Exp $ - */ - -/* - * Copyright (c) 1998 The NetBSD Foundation, Inc. - * All rights reserved. - * - * This code is derived from software contributed to The NetBSD Foundation - * by Lennart Augustsson (lennart@augustsson.net) at - * Carlstedt Research & Technology. - * - * 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. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the NetBSD - * Foundation, Inc. and its contributors. - * 4. Neither the name of The NetBSD Foundation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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. - */ - -/* - * USB Open Host Controller driver. - * - * OHCI spec: http://www.compaq.com/productinfo/development/openhci.html - * USB spec: http://www.usb.org/developers/docs/usbspec.zip - */ - -#include -#include -#include -#include -#include -#include -#include -#if defined(DIAGNOSTIC) && defined(__i386__) -#include -#endif -#include -#include -#include -#include - -#include - -#include -#include -#include -#include -#include - -#include -#include - -#define delay(d) DELAY(d) - -#ifdef USB_DEBUG -#define DPRINTF(x) if (ohcidebug) kprintf x -#define DPRINTFN(n,x) if (ohcidebug>(n)) kprintf x -int ohcidebug = 0; -SYSCTL_NODE(_hw_usb, OID_AUTO, ohci, CTLFLAG_RW, 0, "USB ohci"); -SYSCTL_INT(_hw_usb_ohci, OID_AUTO, debug, CTLFLAG_RW, - &ohcidebug, 0, "ohci debug level"); -#define bitmask_snprintf(q,f,b,l) ksnprintf((b), (l), "%b", (q), (f)) -#else -#define DPRINTF(x) -#define DPRINTFN(n,x) -#endif - -struct ohci_pipe; - -static ohci_soft_ed_t *ohci_alloc_sed(ohci_softc_t *); -static void ohci_free_sed(ohci_softc_t *, ohci_soft_ed_t *); - -static ohci_soft_td_t *ohci_alloc_std(ohci_softc_t *); -static void ohci_free_std(ohci_softc_t *, ohci_soft_td_t *); - -static ohci_soft_itd_t *ohci_alloc_sitd(ohci_softc_t *); -static void ohci_free_sitd(ohci_softc_t *,ohci_soft_itd_t *); - -#if 0 -static void ohci_free_std_chain(ohci_softc_t *, ohci_soft_td_t *, - ohci_soft_td_t *); -#endif -static usbd_status ohci_alloc_std_chain(struct ohci_pipe *, - ohci_softc_t *, int, int, usbd_xfer_handle, - ohci_soft_td_t *, ohci_soft_td_t **); - -static usbd_status ohci_open(usbd_pipe_handle); -static void ohci_poll(struct usbd_bus *); -static void ohci_softintr(void *); -static void ohci_waitintr(ohci_softc_t *, usbd_xfer_handle); -static void ohci_add_done(ohci_softc_t *, ohci_physaddr_t); -static void ohci_rhsc(ohci_softc_t *, usbd_xfer_handle); - -static usbd_status ohci_device_request(usbd_xfer_handle xfer); -static void ohci_add_ed(ohci_soft_ed_t *, ohci_soft_ed_t *); -static void ohci_rem_ed(ohci_soft_ed_t *, ohci_soft_ed_t *); -static void ohci_hash_add_td(ohci_softc_t *, ohci_soft_td_t *); -static void ohci_hash_rem_td(ohci_softc_t *, ohci_soft_td_t *); -static ohci_soft_td_t *ohci_hash_find_td(ohci_softc_t *, ohci_physaddr_t); -static void ohci_hash_add_itd(ohci_softc_t *, ohci_soft_itd_t *); -static void ohci_hash_rem_itd(ohci_softc_t *, ohci_soft_itd_t *); -static ohci_soft_itd_t *ohci_hash_find_itd(ohci_softc_t *, ohci_physaddr_t); - -static usbd_status ohci_setup_isoc(usbd_pipe_handle pipe); -static void ohci_device_isoc_enter(usbd_xfer_handle); - -static usbd_status ohci_allocm(struct usbd_bus *, usb_dma_t *, u_int32_t); -static void ohci_freem(struct usbd_bus *, usb_dma_t *); - -static usbd_xfer_handle ohci_allocx(struct usbd_bus *); -static void ohci_freex(struct usbd_bus *, usbd_xfer_handle); - -static usbd_status ohci_root_ctrl_transfer(usbd_xfer_handle); -static usbd_status ohci_root_ctrl_start(usbd_xfer_handle); -static void ohci_root_ctrl_abort(usbd_xfer_handle); -static void ohci_root_ctrl_close(usbd_pipe_handle); -static void ohci_root_ctrl_done(usbd_xfer_handle); - -static usbd_status ohci_root_intr_transfer(usbd_xfer_handle); -static usbd_status ohci_root_intr_start(usbd_xfer_handle); -static void ohci_root_intr_abort(usbd_xfer_handle); -static void ohci_root_intr_close(usbd_pipe_handle); -static void ohci_root_intr_done(usbd_xfer_handle); - -static usbd_status ohci_device_ctrl_transfer(usbd_xfer_handle); -static usbd_status ohci_device_ctrl_start(usbd_xfer_handle); -static void ohci_device_ctrl_abort(usbd_xfer_handle); -static void ohci_device_ctrl_close(usbd_pipe_handle); -static void ohci_device_ctrl_done(usbd_xfer_handle); - -static usbd_status ohci_device_bulk_transfer(usbd_xfer_handle); -static usbd_status ohci_device_bulk_start(usbd_xfer_handle); -static void ohci_device_bulk_abort(usbd_xfer_handle); -static void ohci_device_bulk_close(usbd_pipe_handle); -static void ohci_device_bulk_done(usbd_xfer_handle); - -static usbd_status ohci_device_intr_transfer(usbd_xfer_handle); -static usbd_status ohci_device_intr_start(usbd_xfer_handle); -static void ohci_device_intr_abort(usbd_xfer_handle); -static void ohci_device_intr_close(usbd_pipe_handle); -static void ohci_device_intr_done(usbd_xfer_handle); - -static usbd_status ohci_device_isoc_transfer(usbd_xfer_handle); -static usbd_status ohci_device_isoc_start(usbd_xfer_handle); -static void ohci_device_isoc_abort(usbd_xfer_handle); -static void ohci_device_isoc_close(usbd_pipe_handle); -static void ohci_device_isoc_done(usbd_xfer_handle); - -static usbd_status ohci_device_setintr(ohci_softc_t *sc, - struct ohci_pipe *pipe, int ival); - -static int ohci_str(usb_string_descriptor_t *, int, const char *); - -static void ohci_timeout(void *); -static void ohci_timeout_task(void *); -static void ohci_rhsc_able(ohci_softc_t *, int); -static void ohci_rhsc_enable(void *); - -static void ohci_close_pipe(usbd_pipe_handle, ohci_soft_ed_t *); -static void ohci_abort_xfer(usbd_xfer_handle, usbd_status); - -static void ohci_device_clear_toggle(usbd_pipe_handle pipe); -static void ohci_noop(usbd_pipe_handle pipe); - -static usbd_status ohci_controller_init(ohci_softc_t *sc); - -#ifdef USB_DEBUG -static void ohci_dumpregs(ohci_softc_t *); -static void ohci_dump_tds(ohci_soft_td_t *); -static void ohci_dump_td(ohci_soft_td_t *); -static void ohci_dump_ed(ohci_soft_ed_t *); -static void ohci_dump_itd(ohci_soft_itd_t *); -static void ohci_dump_itds(ohci_soft_itd_t *); -#endif - -#define OBARR(sc) bus_space_barrier((sc)->iot, (sc)->ioh, 0, (sc)->sc_size, \ - BUS_SPACE_BARRIER_READ|BUS_SPACE_BARRIER_WRITE) -#define OWRITE1(sc, r, x) \ - do { OBARR(sc); bus_space_write_1((sc)->iot, (sc)->ioh, (r), (x)); } while (0) -#define OWRITE2(sc, r, x) \ - do { OBARR(sc); bus_space_write_2((sc)->iot, (sc)->ioh, (r), (x)); } while (0) -#define OWRITE4(sc, r, x) \ - do { OBARR(sc); bus_space_write_4((sc)->iot, (sc)->ioh, (r), (x)); } while (0) -#define OREAD1(sc, r) (OBARR(sc), bus_space_read_1((sc)->iot, (sc)->ioh, (r))) -#define OREAD2(sc, r) (OBARR(sc), bus_space_read_2((sc)->iot, (sc)->ioh, (r))) -#define OREAD4(sc, r) (OBARR(sc), bus_space_read_4((sc)->iot, (sc)->ioh, (r))) - -/* Reverse the bits in a value 0 .. 31 */ -static u_int8_t revbits[OHCI_NO_INTRS] = - { 0x00, 0x10, 0x08, 0x18, 0x04, 0x14, 0x0c, 0x1c, - 0x02, 0x12, 0x0a, 0x1a, 0x06, 0x16, 0x0e, 0x1e, - 0x01, 0x11, 0x09, 0x19, 0x05, 0x15, 0x0d, 0x1d, - 0x03, 0x13, 0x0b, 0x1b, 0x07, 0x17, 0x0f, 0x1f }; - -struct ohci_pipe { - struct usbd_pipe pipe; - ohci_soft_ed_t *sed; - u_int32_t aborting; - union { - ohci_soft_td_t *td; - ohci_soft_itd_t *itd; - } tail; - /* Info needed for different pipe kinds. */ - union { - /* Control pipe */ - struct { - usb_dma_t reqdma; - u_int length; - ohci_soft_td_t *setup, *data, *stat; - } ctl; - /* Interrupt pipe */ - struct { - int nslots; - int pos; - } intr; - /* Bulk pipe */ - struct { - u_int length; - int isread; - } bulk; - /* Iso pipe */ - struct iso { - int next, inuse; - } iso; - } u; -}; - -#define OHCI_INTR_ENDPT 1 - -static struct usbd_bus_methods ohci_bus_methods = { - ohci_open, - ohci_softintr, - ohci_poll, - ohci_allocm, - ohci_freem, - ohci_allocx, - ohci_freex, -}; - -static struct usbd_pipe_methods ohci_root_ctrl_methods = { - ohci_root_ctrl_transfer, - ohci_root_ctrl_start, - ohci_root_ctrl_abort, - ohci_root_ctrl_close, - ohci_noop, - ohci_root_ctrl_done, -}; - -static struct usbd_pipe_methods ohci_root_intr_methods = { - ohci_root_intr_transfer, - ohci_root_intr_start, - ohci_root_intr_abort, - ohci_root_intr_close, - ohci_noop, - ohci_root_intr_done, -}; - -static struct usbd_pipe_methods ohci_device_ctrl_methods = { - ohci_device_ctrl_transfer, - ohci_device_ctrl_start, - ohci_device_ctrl_abort, - ohci_device_ctrl_close, - ohci_noop, - ohci_device_ctrl_done, -}; - -static struct usbd_pipe_methods ohci_device_intr_methods = { - ohci_device_intr_transfer, - ohci_device_intr_start, - ohci_device_intr_abort, - ohci_device_intr_close, - ohci_device_clear_toggle, - ohci_device_intr_done, -}; - -static struct usbd_pipe_methods ohci_device_bulk_methods = { - ohci_device_bulk_transfer, - ohci_device_bulk_start, - ohci_device_bulk_abort, - ohci_device_bulk_close, - ohci_device_clear_toggle, - ohci_device_bulk_done, -}; - -static struct usbd_pipe_methods ohci_device_isoc_methods = { - ohci_device_isoc_transfer, - ohci_device_isoc_start, - ohci_device_isoc_abort, - ohci_device_isoc_close, - ohci_noop, - ohci_device_isoc_done, -}; - -int -ohci_detach(struct ohci_softc *sc, int flags) -{ - int i, rv = 0; - - crit_enter(); - sc->sc_dying = 1; - - callout_stop(&sc->sc_tmo_rhsc); - - OWRITE4(sc, OHCI_INTERRUPT_DISABLE, OHCI_ALL_INTRS); - OWRITE4(sc, OHCI_CONTROL, OHCI_HCFS_RESET); - crit_exit(); - - usb_delay_ms(&sc->sc_bus, 300); /* XXX let stray task complete */ - - for (i = 0; i < OHCI_NO_EDS; i++) { - ohci_free_sed(sc, sc->sc_eds[i]); - sc->sc_eds[i] = NULL; - } - ohci_free_sed(sc, sc->sc_isoc_head); - sc->sc_isoc_head = NULL; - ohci_free_sed(sc, sc->sc_bulk_head); - sc->sc_bulk_head = NULL; - ohci_free_sed(sc, sc->sc_ctrl_head); - sc->sc_ctrl_head = NULL; - usb_freemem(&sc->sc_bus, &sc->sc_hccadma); - - return (rv); -} - -ohci_soft_ed_t * -ohci_alloc_sed(ohci_softc_t *sc) -{ - ohci_soft_ed_t *sed; - usbd_status err; - int i, offs; - usb_dma_t dma; - - if (sc->sc_freeeds == NULL) { - DPRINTFN(2, ("ohci_alloc_sed: allocating chunk\n")); - err = usb_allocmem(&sc->sc_bus, OHCI_SED_SIZE * OHCI_SED_CHUNK, - OHCI_ED_ALIGN, &dma); - if (err) - return (NULL); - for(i = 0; i < OHCI_SED_CHUNK; i++) { - offs = i * OHCI_SED_SIZE; - sed = KERNADDR(&dma, offs); - sed->physaddr = DMAADDR(&dma, offs); - sed->next = sc->sc_freeeds; - sc->sc_freeeds = sed; - } - } - sed = sc->sc_freeeds; - sc->sc_freeeds = sed->next; - memset(&sed->ed, 0, sizeof(ohci_ed_t)); - sed->next = 0; - return (sed); -} - -void -ohci_free_sed(ohci_softc_t *sc, ohci_soft_ed_t *sed) -{ - sed->next = sc->sc_freeeds; - sc->sc_freeeds = sed; -} - -ohci_soft_td_t * -ohci_alloc_std(ohci_softc_t *sc) -{ - ohci_soft_td_t *std; - usbd_status err; - int i, offs; - usb_dma_t dma; - - if (sc->sc_freetds == NULL) { - DPRINTFN(2, ("ohci_alloc_std: allocating chunk\n")); - err = usb_allocmem(&sc->sc_bus, OHCI_STD_SIZE * OHCI_STD_CHUNK, - OHCI_TD_ALIGN, &dma); - if (err) - return (NULL); - crit_enter(); - for(i = 0; i < OHCI_STD_CHUNK; i++) { - offs = i * OHCI_STD_SIZE; - std = KERNADDR(&dma, offs); - std->physaddr = DMAADDR(&dma, offs); - std->nexttd = sc->sc_freetds; - sc->sc_freetds = std; - } - crit_exit(); - } - - crit_enter(); - std = sc->sc_freetds; - sc->sc_freetds = std->nexttd; - memset(&std->td, 0, sizeof(ohci_td_t)); - std->nexttd = NULL; - std->xfer = NULL; - ohci_hash_add_td(sc, std); - crit_exit(); - - return (std); -} - -void -ohci_free_std(ohci_softc_t *sc, ohci_soft_td_t *std) -{ - crit_enter(); - ohci_hash_rem_td(sc, std); - std->nexttd = sc->sc_freetds; - sc->sc_freetds = std; - crit_exit(); -} - -usbd_status -ohci_alloc_std_chain(struct ohci_pipe *opipe, ohci_softc_t *sc, - int alen, int rd, usbd_xfer_handle xfer, - ohci_soft_td_t *sp, ohci_soft_td_t **ep) -{ - ohci_soft_td_t *next, *cur; - ohci_physaddr_t dataphys; - u_int32_t tdflags; - int offset = 0; - int len, curlen; - usb_dma_t *dma = &xfer->dmabuf; - u_int16_t flags = xfer->flags; - - DPRINTFN(alen < 4096,("ohci_alloc_std_chain: start len=%d\n", alen)); - - len = alen; - cur = sp; - - tdflags = htole32( - (rd ? OHCI_TD_IN : OHCI_TD_OUT) | - (flags & USBD_SHORT_XFER_OK ? OHCI_TD_R : 0) | - OHCI_TD_NOCC | OHCI_TD_TOGGLE_CARRY | OHCI_TD_SET_DI(6)); - - for (;;) { - next = ohci_alloc_std(sc); - if (next == NULL) - goto nomem; - - dataphys = DMAADDR(dma, offset); - - /* - * The OHCI hardware can handle at most one 4k crossing. - * XXX - currently we only allocate contigous buffers, but - * the OHCI spec says: If during the data transfer the buffer - * address contained in the HC's working copy of - * CurrentBufferPointer crosses a 4K boundary, the upper 20 - * bits of Buffer End are copied to the working value of - * CurrentBufferPointer causing the next buffer address to - * be the 0th byte in the same 4K page that contains the - * last byte of the buffer (the 4K boundary crossing may - * occur within a data packet transfer.) - * - * If/when dma has multiple segments, this will need to - * properly handle fragmenting TD's. - * - * Note that if we are gathering data from multiple SMALL - * segments, e.g. mbufs, we need to do special gymnastics, - * e.g. bounce buffering or data aggregation, - * BEFORE WE GET HERE because a bulk USB transfer must - * consist of maximally sized packets right up to the end. - * A shorter than maximal packet means that it is the end - * of the transfer. If the data transfer length is a - * multiple of the packet size, then a 0 byte - * packet will be the signal of the end of transfer. - * Since packets can't cross TDs this means that - * each TD except the last one must cover an exact multiple - * of the maximal packet length. - */ - if (OHCI_PAGE_OFFSET(dataphys) + len <= (2 * OHCI_PAGE_SIZE)) { - /* We can handle all that remains in this TD */ - curlen = len; - } else { - /* must use multiple TDs, fill as much as possible. */ - curlen = 2 * OHCI_PAGE_SIZE - - OHCI_PAGE_OFFSET(dataphys); - /* the length must be a multiple of the max size */ - curlen -= curlen % - UGETW(opipe->pipe.endpoint->edesc->wMaxPacketSize); - KASSERT((curlen != 0), ("ohci_alloc_std: curlen == 0")); - } - DPRINTFN(4,("ohci_alloc_std_chain: dataphys=0x%08x " - "len=%d curlen=%d\n", - dataphys, len, curlen)); - len -= curlen; - - cur->td.td_flags = tdflags; - cur->td.td_cbp = htole32(dataphys); - cur->nexttd = next; - cur->td.td_nexttd = htole32(next->physaddr); - cur->td.td_be = htole32(DMAADDR(dma, offset + curlen - 1)); - cur->len = curlen; - cur->flags = OHCI_ADD_LEN; - cur->xfer = xfer; - DPRINTFN(10,("ohci_alloc_std_chain: cbp=0x%08x be=0x%08x\n", - dataphys, dataphys + curlen - 1)); - if (len == 0) - break; - if (len < 0) - panic("Length went negative: %d curlen %d dma %p offset %08x", len, curlen, dma, (int)0); - - DPRINTFN(10,("ohci_alloc_std_chain: extend chain\n")); - offset += curlen; - cur = next; - } - if ((flags & USBD_FORCE_SHORT_XFER) && - alen % UGETW(opipe->pipe.endpoint->edesc->wMaxPacketSize) == 0) { - /* Force a 0 length transfer at the end. */ - - cur = next; - - next = ohci_alloc_std(sc); - if (next == NULL) - goto nomem; - - cur->td.td_flags = tdflags; - cur->td.td_cbp = 0; /* indicate 0 length packet */ - cur->nexttd = next; - cur->td.td_nexttd = htole32(next->physaddr); - cur->td.td_be = ~0; - cur->len = 0; - cur->flags = 0; - cur->xfer = xfer; - DPRINTFN(2,("ohci_alloc_std_chain: add 0 xfer\n")); - } - *ep = cur; - - return (USBD_NORMAL_COMPLETION); - - nomem: - /* XXX free chain */ - return (USBD_NOMEM); -} - -#if 0 -static void -ohci_free_std_chain(ohci_softc_t *sc, ohci_soft_td_t *std, - ohci_soft_td_t *stdend) -{ - ohci_soft_td_t *p; - - for (; std != stdend; std = p) { - p = std->nexttd; - ohci_free_std(sc, std); - } -} -#endif - -ohci_soft_itd_t * -ohci_alloc_sitd(ohci_softc_t *sc) -{ - ohci_soft_itd_t *sitd; - usbd_status err; - int i, offs; - usb_dma_t dma; - - crit_enter(); - if (sc->sc_freeitds == NULL) { - DPRINTFN(2, ("ohci_alloc_sitd: allocating chunk\n")); - crit_exit(); - err = usb_allocmem(&sc->sc_bus, - OHCI_SITD_SIZE * OHCI_SITD_CHUNK, - OHCI_ITD_ALIGN, &dma); - if (err) - return (NULL); - crit_enter(); - for (i = 0; i < OHCI_SITD_CHUNK; i++) { - offs = i * OHCI_SITD_SIZE; - sitd = KERNADDR(&dma, offs); - sitd->physaddr = DMAADDR(&dma, offs); - sitd->nextitd = sc->sc_freeitds; - sc->sc_freeitds = sitd; - } - } - sitd = sc->sc_freeitds; - sc->sc_freeitds = sitd->nextitd; - memset(&sitd->itd, 0, sizeof(ohci_itd_t)); - sitd->nextitd = NULL; - sitd->xfer = NULL; - ohci_hash_add_itd(sc, sitd); - crit_exit(); - -#ifdef DIAGNOSTIC - sitd->isdone = 0; -#endif - - return (sitd); -} - -void -ohci_free_sitd(ohci_softc_t *sc, ohci_soft_itd_t *sitd) -{ - DPRINTFN(10,("ohci_free_sitd: sitd=%p\n", sitd)); - -#ifdef DIAGNOSTIC - if (!sitd->isdone) { - panic("ohci_free_sitd: sitd=%p not done", sitd); - return; - } - /* Warn double free */ - sitd->isdone = 0; -#endif - - crit_enter(); - ohci_hash_rem_itd(sc, sitd); - sitd->nextitd = sc->sc_freeitds; - sc->sc_freeitds = sitd; - crit_exit(); -} - -usbd_status -ohci_init(ohci_softc_t *sc) -{ - ohci_soft_ed_t *sed, *psed; - usbd_status err; - int i; - u_int32_t rev; - - DPRINTF(("ohci_init: start\n")); - rev = OREAD4(sc, OHCI_REVISION); - device_printf(sc->sc_bus.bdev, "OHCI version %d.%d%s\n", - OHCI_REV_HI(rev), OHCI_REV_LO(rev), - OHCI_REV_LEGACY(rev) ? ", legacy support" : ""); - - /* - * Make sure all interrupts are disabled before we start messing - * with things. - */ - OWRITE4(sc, OHCI_INTERRUPT_DISABLE, -1); - - if (OHCI_REV_HI(rev) != 1 || OHCI_REV_LO(rev) != 0) { - device_printf(sc->sc_bus.bdev, "unsupported OHCI revision\n"); - sc->sc_bus.usbrev = USBREV_UNKNOWN; - return (USBD_INVAL); - } - sc->sc_bus.usbrev = USBREV_1_0; - - for (i = 0; i < OHCI_HASH_SIZE; i++) - LIST_INIT(&sc->sc_hash_tds[i]); - for (i = 0; i < OHCI_HASH_SIZE; i++) - LIST_INIT(&sc->sc_hash_itds[i]); - - STAILQ_INIT(&sc->sc_free_xfers); - - /* XXX determine alignment by R/W */ - /* Allocate the HCCA area. */ - err = usb_allocmem(&sc->sc_bus, OHCI_HCCA_SIZE, - OHCI_HCCA_ALIGN, &sc->sc_hccadma); - if (err) - return (err); - sc->sc_hcca = KERNADDR(&sc->sc_hccadma, 0); - memset(sc->sc_hcca, 0, OHCI_HCCA_SIZE); - - sc->sc_eintrs = OHCI_NORMAL_INTRS; - - /* Allocate dummy ED that starts the control list. */ - sc->sc_ctrl_head = ohci_alloc_sed(sc); - if (sc->sc_ctrl_head == NULL) { - err = USBD_NOMEM; - goto bad1; - } - sc->sc_ctrl_head->ed.ed_flags |= htole32(OHCI_ED_SKIP); - - /* Allocate dummy ED that starts the bulk list. */ - sc->sc_bulk_head = ohci_alloc_sed(sc); - if (sc->sc_bulk_head == NULL) { - err = USBD_NOMEM; - goto bad2; - } - sc->sc_bulk_head->ed.ed_flags |= htole32(OHCI_ED_SKIP); - - /* Allocate dummy ED that starts the isochronous list. */ - sc->sc_isoc_head = ohci_alloc_sed(sc); - if (sc->sc_isoc_head == NULL) { - err = USBD_NOMEM; - goto bad3; - } - sc->sc_isoc_head->ed.ed_flags |= htole32(OHCI_ED_SKIP); - - /* Allocate all the dummy EDs that make up the interrupt tree. */ - for (i = 0; i < OHCI_NO_EDS; i++) { - sed = ohci_alloc_sed(sc); - if (sed == NULL) { - while (--i >= 0) { - ohci_free_sed(sc, sc->sc_eds[i]); - sc->sc_eds[i] = NULL; - } - err = USBD_NOMEM; - goto bad4; - } - /* All ED fields are set to 0. */ - sc->sc_eds[i] = sed; - sed->ed.ed_flags |= htole32(OHCI_ED_SKIP); - if (i != 0) - psed = sc->sc_eds[(i-1) / 2]; - else - psed= sc->sc_isoc_head; - sed->next = psed; - sed->ed.ed_nexted = htole32(psed->physaddr); - } - /* - * Fill HCCA interrupt table. The bit reversal is to get - * the tree set up properly to spread the interrupts. - */ - for (i = 0; i < OHCI_NO_INTRS; i++) - sc->sc_hcca->hcca_interrupt_table[revbits[i]] = - htole32(sc->sc_eds[OHCI_NO_EDS-OHCI_NO_INTRS+i]->physaddr); - -#ifdef USB_DEBUG - if (ohcidebug > 15) { - for (i = 0; i < OHCI_NO_EDS; i++) { - kprintf("ed#%d ", i); - ohci_dump_ed(sc->sc_eds[i]); - } - kprintf("iso "); - ohci_dump_ed(sc->sc_isoc_head); - } -#endif - - err = ohci_controller_init(sc); - if (err != USBD_NORMAL_COMPLETION) - goto bad5; - - /* Set up the bus struct. */ - sc->sc_bus.methods = &ohci_bus_methods; - sc->sc_bus.pipe_size = sizeof(struct ohci_pipe); - - callout_init(&sc->sc_tmo_rhsc); - - /* - * Finish up w/ interlocked done flag (the interrupt handler could - * be called due to other shared interrupts), enable interrupts, - * and run the handler in case a pending interrupt got cleared - * before we finished. - */ - crit_enter(); - sc->sc_flags |= OHCI_SCFLG_DONEINIT; - OWRITE4(sc, OHCI_INTERRUPT_ENABLE, sc->sc_eintrs); - ohci_intr(sc); - crit_exit(); - - return (USBD_NORMAL_COMPLETION); - - bad5: - for (i = 0; i < OHCI_NO_EDS; i++) { - ohci_free_sed(sc, sc->sc_eds[i]); - sc->sc_eds[i] = NULL; - } - bad4: - ohci_free_sed(sc, sc->sc_isoc_head); - sc->sc_isoc_head = NULL; - bad3: - ohci_free_sed(sc, sc->sc_bulk_head); - sc->sc_bulk_head = NULL; - bad2: - ohci_free_sed(sc, sc->sc_ctrl_head); - sc->sc_ctrl_head = NULL; - bad1: - usb_freemem(&sc->sc_bus, &sc->sc_hccadma); - return (err); -} - -static usbd_status -ohci_controller_init(ohci_softc_t *sc) -{ - int i; - u_int32_t s, ctl, ival, hcr, fm, per, desca; - - /* Determine in what context we are running. */ - ctl = OREAD4(sc, OHCI_CONTROL); - if (ctl & OHCI_IR) { - /* SMM active, request change */ - DPRINTF(("ohci_init: SMM active, request owner change\n")); - s = OREAD4(sc, OHCI_COMMAND_STATUS); - OWRITE4(sc, OHCI_COMMAND_STATUS, s | OHCI_OCR); - for (i = 0; i < 100 && (ctl & OHCI_IR); i++) { - usb_delay_ms(&sc->sc_bus, 1); - ctl = OREAD4(sc, OHCI_CONTROL); - } - if ((ctl & OHCI_IR) == 0) { - device_printf(sc->sc_bus.bdev, - "SMM does not respond, resetting\n"); - OWRITE4(sc, OHCI_CONTROL, OHCI_HCFS_RESET); - goto reset; - } -#if 0 -/* Don't bother trying to reuse the BIOS init, we'll reset it anyway. */ - } else if ((ctl & OHCI_HCFS_MASK) != OHCI_HCFS_RESET) { - /* BIOS started controller. */ - DPRINTF(("ohci_init: BIOS active\n")); - if ((ctl & OHCI_HCFS_MASK) != OHCI_HCFS_OPERATIONAL) { - OWRITE4(sc, OHCI_CONTROL, OHCI_HCFS_OPERATIONAL); - usb_delay_ms(&sc->sc_bus, USB_RESUME_DELAY); - } -#endif - } else { - DPRINTF(("ohci_init: cold started\n")); - reset: - /* Controller was cold started. */ - usb_delay_ms(&sc->sc_bus, USB_BUS_RESET_DELAY); - } - - /* - * This reset should not be necessary according to the OHCI spec, but - * without it some controllers do not start. - */ - DPRINTF(("%s: resetting\n", device_get_nameunit(sc->sc_bus.bdev))); - OWRITE4(sc, OHCI_CONTROL, OHCI_HCFS_RESET); - usb_delay_ms(&sc->sc_bus, USB_BUS_RESET_DELAY); - - /* We now own the host controller and the bus has been reset. */ - ival = OHCI_GET_IVAL(OREAD4(sc, OHCI_FM_INTERVAL)); - - OWRITE4(sc, OHCI_COMMAND_STATUS, OHCI_HCR); /* Reset HC */ - /* Nominal time for a reset is 10 us. */ - for (i = 0; i < 10; i++) { - delay(10); - hcr = OREAD4(sc, OHCI_COMMAND_STATUS) & OHCI_HCR; - if (!hcr) - break; - } - if (hcr) { - device_printf(sc->sc_bus.bdev, "reset timeout\n"); - return (USBD_IOERROR); - } -#ifdef USB_DEBUG - if (ohcidebug > 15) - ohci_dumpregs(sc); -#endif - - /* The controller is now in SUSPEND state, we have 2ms to finish. */ - - /* Set up HC registers. */ - OWRITE4(sc, OHCI_HCCA, DMAADDR(&sc->sc_hccadma, 0)); - OWRITE4(sc, OHCI_CONTROL_HEAD_ED, sc->sc_ctrl_head->physaddr); - OWRITE4(sc, OHCI_BULK_HEAD_ED, sc->sc_bulk_head->physaddr); - /* disable all interrupts */ - OWRITE4(sc, OHCI_INTERRUPT_DISABLE, OHCI_ALL_INTRS); - /* switch on desired functional features */ - ctl = OREAD4(sc, OHCI_CONTROL); - ctl &= ~(OHCI_CBSR_MASK | OHCI_LES | OHCI_HCFS_MASK | OHCI_IR); - ctl |= OHCI_PLE | OHCI_IE | OHCI_CLE | OHCI_BLE | - OHCI_RATIO_1_4 | OHCI_HCFS_OPERATIONAL; - /* And finally start it! */ - OWRITE4(sc, OHCI_CONTROL, ctl); - - /* - * The controller is now OPERATIONAL. Set a some final - * registers that should be set earlier, but that the - * controller ignores when in the SUSPEND state. - */ - fm = (OREAD4(sc, OHCI_FM_INTERVAL) & OHCI_FIT) ^ OHCI_FIT; - fm |= OHCI_FSMPS(ival) | ival; - OWRITE4(sc, OHCI_FM_INTERVAL, fm); - per = OHCI_PERIODIC(ival); /* 90% periodic */ - OWRITE4(sc, OHCI_PERIODIC_START, per); - - /* Fiddle the No OverCurrent Protection bit to avoid chip bug. */ - desca = OREAD4(sc, OHCI_RH_DESCRIPTOR_A); - OWRITE4(sc, OHCI_RH_DESCRIPTOR_A, desca | OHCI_NOCP); - OWRITE4(sc, OHCI_RH_STATUS, OHCI_LPSC); /* Enable port power */ - usb_delay_ms(&sc->sc_bus, OHCI_ENABLE_POWER_DELAY); - OWRITE4(sc, OHCI_RH_DESCRIPTOR_A, desca); - - /* - * The AMD756 requires a delay before re-reading the register, - * otherwise it will occasionally report 0 ports. - */ - sc->sc_noport = 0; - for (i = 0; i < 10 && sc->sc_noport == 0; i++) { - usb_delay_ms(&sc->sc_bus, OHCI_READ_DESC_DELAY); - sc->sc_noport = OHCI_GET_NDP(OREAD4(sc, OHCI_RH_DESCRIPTOR_A)); - } - - /* - * Enable desired interrupts - */ - sc->sc_eintrs |= OHCI_MIE; - if (sc->sc_flags & OHCI_SCFLG_DONEINIT) - OWRITE4(sc, OHCI_INTERRUPT_ENABLE, sc->sc_eintrs); - -#ifdef USB_DEBUG - if (ohcidebug > 5) - ohci_dumpregs(sc); -#endif - return (USBD_NORMAL_COMPLETION); -} - -usbd_status -ohci_allocm(struct usbd_bus *bus, usb_dma_t *dma, u_int32_t size) -{ - return (usb_allocmem(bus, size, 0, dma)); -} - -void -ohci_freem(struct usbd_bus *bus, usb_dma_t *dma) -{ - usb_freemem(bus, dma); -} - -usbd_xfer_handle -ohci_allocx(struct usbd_bus *bus) -{ - struct ohci_softc *sc = (struct ohci_softc *)bus; - usbd_xfer_handle xfer; - - xfer = STAILQ_FIRST(&sc->sc_free_xfers); - if (xfer != NULL) { - STAILQ_REMOVE_HEAD(&sc->sc_free_xfers, next); -#ifdef DIAGNOSTIC - if (xfer->busy_free != XFER_FREE) { - kprintf("ohci_allocx: xfer=%p not free, 0x%08x\n", xfer, - xfer->busy_free); - } -#endif - } else { - xfer = kmalloc(sizeof(struct ohci_xfer), M_USB, M_INTWAIT); - } - if (xfer != NULL) { - memset(xfer, 0, sizeof (struct ohci_xfer)); - usb_init_task(&OXFER(xfer)->abort_task, ohci_timeout_task, - xfer); - OXFER(xfer)->ohci_xfer_flags = 0; -#ifdef DIAGNOSTIC - xfer->busy_free = XFER_BUSY; -#endif - } - return (xfer); -} - -void -ohci_freex(struct usbd_bus *bus, usbd_xfer_handle xfer) -{ - struct ohci_softc *sc = (struct ohci_softc *)bus; - struct ohci_xfer *oxfer = (struct ohci_xfer *)xfer; - ohci_soft_itd_t *sitd; - - if (oxfer->ohci_xfer_flags & OHCI_ISOC_DIRTY) { - crit_enter(); - for (sitd = xfer->hcpriv; sitd != NULL && sitd->xfer == xfer; - sitd = sitd->nextitd) - ohci_free_sitd(sc, sitd); - crit_exit(); - } - -#ifdef DIAGNOSTIC - if (xfer->busy_free != XFER_BUSY) { - kprintf("ohci_freex: xfer=%p not busy, 0x%08x\n", xfer, - xfer->busy_free); - return; - } - xfer->busy_free = XFER_FREE; -#endif - STAILQ_INSERT_HEAD(&sc->sc_free_xfers, xfer, next); -} - -/* - * Shut down the controller when the system is going down. - */ -void -ohci_shutdown(void *v) -{ - ohci_softc_t *sc = v; - - DPRINTF(("ohci_shutdown: stopping the HC\n")); - OWRITE4(sc, OHCI_CONTROL, OHCI_HCFS_RESET); -} - -/* - * Handle suspend/resume. - * - * We need to switch to polling mode here, because this routine is - * called from an intterupt context. This is all right since we - * are almost suspended anyway. - */ -void -ohci_power(int why, void *v) -{ - ohci_softc_t *sc = v; - u_int32_t ctl; - -#ifdef USB_DEBUG - DPRINTF(("ohci_power: sc=%p, why=%d\n", sc, why)); - ohci_dumpregs(sc); -#endif - - crit_enter(); - if (why != PWR_RESUME) { - sc->sc_bus.use_polling++; - ctl = OREAD4(sc, OHCI_CONTROL) & ~OHCI_HCFS_MASK; - if (sc->sc_control == 0) { - /* - * Preserve register values, in case that APM BIOS - * does not recover them. - */ - sc->sc_control = ctl; - sc->sc_intre = OREAD4(sc, OHCI_INTERRUPT_ENABLE); - } - ctl |= OHCI_HCFS_SUSPEND; - OWRITE4(sc, OHCI_CONTROL, ctl); - usb_delay_ms(&sc->sc_bus, USB_RESUME_WAIT); - sc->sc_bus.use_polling--; - } else { - sc->sc_bus.use_polling++; - - /* Some broken BIOSes never initialize Controller chip */ - ohci_controller_init(sc); - - if (sc->sc_intre) - OWRITE4(sc, OHCI_INTERRUPT_ENABLE, - sc->sc_intre & (OHCI_ALL_INTRS | OHCI_MIE)); - if (sc->sc_control) - ctl = sc->sc_control; - else - ctl = OREAD4(sc, OHCI_CONTROL); - ctl |= OHCI_HCFS_RESUME; - OWRITE4(sc, OHCI_CONTROL, ctl); - usb_delay_ms(&sc->sc_bus, USB_RESUME_DELAY); - ctl = (ctl & ~OHCI_HCFS_MASK) | OHCI_HCFS_OPERATIONAL; - OWRITE4(sc, OHCI_CONTROL, ctl); - usb_delay_ms(&sc->sc_bus, USB_RESUME_RECOVERY); - sc->sc_control = sc->sc_intre = 0; - sc->sc_bus.use_polling--; - } - crit_exit(); -} - -#ifdef USB_DEBUG -void -ohci_dumpregs(ohci_softc_t *sc) -{ - DPRINTF(("ohci_dumpregs: rev=0x%08x control=0x%08x command=0x%08x\n", - OREAD4(sc, OHCI_REVISION), - OREAD4(sc, OHCI_CONTROL), - OREAD4(sc, OHCI_COMMAND_STATUS))); - DPRINTF((" intrstat=0x%08x intre=0x%08x intrd=0x%08x\n", - OREAD4(sc, OHCI_INTERRUPT_STATUS), - OREAD4(sc, OHCI_INTERRUPT_ENABLE), - OREAD4(sc, OHCI_INTERRUPT_DISABLE))); - DPRINTF((" hcca=0x%08x percur=0x%08x ctrlhd=0x%08x\n", - OREAD4(sc, OHCI_HCCA), - OREAD4(sc, OHCI_PERIOD_CURRENT_ED), - OREAD4(sc, OHCI_CONTROL_HEAD_ED))); - DPRINTF((" ctrlcur=0x%08x bulkhd=0x%08x bulkcur=0x%08x\n", - OREAD4(sc, OHCI_CONTROL_CURRENT_ED), - OREAD4(sc, OHCI_BULK_HEAD_ED), - OREAD4(sc, OHCI_BULK_CURRENT_ED))); - DPRINTF((" done=0x%08x fmival=0x%08x fmrem=0x%08x\n", - OREAD4(sc, OHCI_DONE_HEAD), - OREAD4(sc, OHCI_FM_INTERVAL), - OREAD4(sc, OHCI_FM_REMAINING))); - DPRINTF((" fmnum=0x%08x perst=0x%08x lsthrs=0x%08x\n", - OREAD4(sc, OHCI_FM_NUMBER), - OREAD4(sc, OHCI_PERIODIC_START), - OREAD4(sc, OHCI_LS_THRESHOLD))); - DPRINTF((" desca=0x%08x descb=0x%08x stat=0x%08x\n", - OREAD4(sc, OHCI_RH_DESCRIPTOR_A), - OREAD4(sc, OHCI_RH_DESCRIPTOR_B), - OREAD4(sc, OHCI_RH_STATUS))); - DPRINTF((" port1=0x%08x port2=0x%08x\n", - OREAD4(sc, OHCI_RH_PORT_STATUS(1)), - OREAD4(sc, OHCI_RH_PORT_STATUS(2)))); - DPRINTF((" HCCA: frame_number=0x%04x done_head=0x%08x\n", - le32toh(sc->sc_hcca->hcca_frame_number), - le32toh(sc->sc_hcca->hcca_done_head))); -} -#endif - -static int ohci_intr1(ohci_softc_t *); - -int -ohci_intr(void *p) -{ - ohci_softc_t *sc = p; - - if (sc->sc_dying || (sc->sc_flags & OHCI_SCFLG_DONEINIT) == 0) - return (0); - - /* - * If we get an interrupt while polling, then remember what it - * was and acknowledge it. - */ - if (sc->sc_bus.use_polling) { - u_int32_t intrs = OREAD4(sc, OHCI_INTERRUPT_STATUS); - - intrs &= ~OHCI_MIE; - if (intrs) - OWRITE4(sc, OHCI_INTERRUPT_STATUS, intrs); - sc->sc_dintrs |= intrs; -#ifdef DIAGNOSTIC - DPRINTFN(16, ("ohci_intr: ignored interrupt while polling\n")); -#endif - return (0); - } - - return (ohci_intr1(sc)); -} - -static int -ohci_intr1(ohci_softc_t *sc) -{ - u_int32_t intrs, eintrs; - ohci_physaddr_t done; - - DPRINTFN(14,("ohci_intr1: enter\n")); - - /* In case the interrupt occurs before initialization has completed. */ - if (sc->sc_hcca == NULL) { -#ifdef DIAGNOSTIC - kprintf("ohci_intr: sc->sc_hcca == NULL\n"); -#endif - return (0); - } - - intrs = 0; - done = le32toh(sc->sc_hcca->hcca_done_head); - - /* The LSb of done is used to inform the HC Driver that an interrupt - * condition exists for both the Done list and for another event - * recorded in HcInterruptStatus. On an interrupt from the HC, the HC - * Driver checks the HccaDoneHead Value. If this value is 0, then the - * interrupt was caused by other than the HccaDoneHead update and the - * HcInterruptStatus register needs to be accessed to determine that - * exact interrupt cause. If HccaDoneHead is nonzero, then a Done list - * update interrupt is indicated and if the LSb of done is nonzero, - * then an additional interrupt event is indicated and - * HcInterruptStatus should be checked to determine its cause. - */ - if (done != 0) { - if (done & ~OHCI_DONE_INTRS) - intrs = OHCI_WDH; - if (done & OHCI_DONE_INTRS) { - intrs |= OREAD4(sc, OHCI_INTERRUPT_STATUS); - intrs |= sc->sc_dintrs; - done &= ~OHCI_DONE_INTRS; - } - sc->sc_hcca->hcca_done_head = 0; - } else { - intrs = OREAD4(sc, OHCI_INTERRUPT_STATUS); - intrs |= sc->sc_dintrs; - intrs &= ~OHCI_WDH; - } - - if (intrs == 0) /* nothing to be done (PCI shared interrupt) */ - return (0); - - intrs &= ~OHCI_MIE; - OWRITE4(sc, OHCI_INTERRUPT_STATUS, intrs); /* Acknowledge */ - sc->sc_dintrs &= ~intrs; - eintrs = intrs & sc->sc_eintrs; - if (!eintrs) - return (0); - - sc->sc_bus.intr_context++; - sc->sc_bus.no_intrs++; - DPRINTFN(7, ("ohci_intr: sc=%p intrs=0x%x(0x%x) eintrs=0x%x\n", - sc, (u_int)intrs, OREAD4(sc, OHCI_INTERRUPT_STATUS), - (u_int)eintrs)); - - if (eintrs & OHCI_SO) { - sc->sc_overrun_cnt++; - if (usbd_ratecheck(&sc->sc_overrun_ntc)) { - device_printf(sc->sc_bus.bdev, - "%u scheduling overruns\n", sc->sc_overrun_cnt); - sc->sc_overrun_cnt = 0; - } - /* XXX do what */ - eintrs &= ~OHCI_SO; - } - if (eintrs & OHCI_WDH) { - ohci_add_done(sc, done &~ OHCI_DONE_INTRS); - usb_schedsoftintr(&sc->sc_bus); - eintrs &= ~OHCI_WDH; - } - if (eintrs & OHCI_RD) { - device_printf(sc->sc_bus.bdev, "resume detect\n"); - /* XXX process resume detect */ - } - if (eintrs & OHCI_UE) { - device_printf(sc->sc_bus.bdev, - "unrecoverable error, controller halted\n"); - OWRITE4(sc, OHCI_CONTROL, OHCI_HCFS_RESET); - /* XXX what else */ - } - if (eintrs & OHCI_RHSC) { - ohci_rhsc(sc, sc->sc_intrxfer); - /* - * Disable RHSC interrupt for now, because it will be - * on until the port has been reset. - */ - ohci_rhsc_able(sc, 0); - /* Do not allow RHSC interrupts > 1 per second */ - callout_reset(&sc->sc_tmo_rhsc, hz, ohci_rhsc_enable, sc); - eintrs &= ~OHCI_RHSC; - } - - sc->sc_bus.intr_context--; - - if (eintrs != 0) { - /* Block unprocessed interrupts. XXX */ - OWRITE4(sc, OHCI_INTERRUPT_DISABLE, eintrs); - sc->sc_eintrs &= ~eintrs; - device_printf(sc->sc_bus.bdev, - "blocking intrs 0x%x\n", eintrs); - } - - return (1); -} - -void -ohci_rhsc_able(ohci_softc_t *sc, int on) -{ - DPRINTFN(4, ("ohci_rhsc_able: on=%d\n", on)); - if (on) { - sc->sc_eintrs |= OHCI_RHSC; - if (sc->sc_flags & OHCI_SCFLG_DONEINIT) - OWRITE4(sc, OHCI_INTERRUPT_ENABLE, OHCI_RHSC); - } else { - sc->sc_eintrs &= ~OHCI_RHSC; - OWRITE4(sc, OHCI_INTERRUPT_DISABLE, OHCI_RHSC); - } -} - -void -ohci_rhsc_enable(void *v_sc) -{ - ohci_softc_t *sc = v_sc; - - crit_enter(); - ohci_rhsc_able(sc, 1); - crit_exit(); -} - -#ifdef USB_DEBUG -char *ohci_cc_strs[] = { - "NO_ERROR", - "CRC", - "BIT_STUFFING", - "DATA_TOGGLE_MISMATCH", - "STALL", - "DEVICE_NOT_RESPONDING", - "PID_CHECK_FAILURE", - "UNEXPECTED_PID", - "DATA_OVERRUN", - "DATA_UNDERRUN", - "BUFFER_OVERRUN", - "BUFFER_UNDERRUN", - "reserved", - "reserved", - "NOT_ACCESSED", - "NOT_ACCESSED" -}; -#endif - -void -ohci_add_done(ohci_softc_t *sc, ohci_physaddr_t done) -{ - ohci_soft_itd_t *sitd, *sidone, **ip; - ohci_soft_td_t *std, *sdone, **p; - - /* Reverse the done list. */ - for (sdone = NULL, sidone = NULL; done != 0; ) { - std = ohci_hash_find_td(sc, done); - if (std != NULL) { - std->dnext = sdone; - done = le32toh(std->td.td_nexttd); - sdone = std; - DPRINTFN(10,("add TD %p\n", std)); - continue; - } - sitd = ohci_hash_find_itd(sc, done); - if (sitd != NULL) { - sitd->dnext = sidone; - done = le32toh(sitd->itd.itd_nextitd); - sidone = sitd; - DPRINTFN(5,("add ITD %p\n", sitd)); - continue; - } - panic("ohci_add_done: addr 0x%08lx not found", (u_long)done); - } - - /* sdone & sidone now hold the done lists. */ - /* Put them on the already processed lists. */ - for (p = &sc->sc_sdone; *p != NULL; p = &(*p)->dnext) - ; - *p = sdone; - for (ip = &sc->sc_sidone; *ip != NULL; ip = &(*ip)->dnext) - ; - *ip = sidone; -} - -void -ohci_softintr(void *v) -{ - ohci_softc_t *sc = v; - ohci_soft_itd_t *sitd, *sidone, *sitdnext; - ohci_soft_td_t *std, *sdone, *stdnext, *p, *n; - usbd_xfer_handle xfer; - struct ohci_pipe *opipe; - int len, cc; - int i, j, iframes; - - DPRINTFN(10,("ohci_softintr: enter\n")); - - sc->sc_bus.intr_context++; - - crit_enter(); - sdone = sc->sc_sdone; - sc->sc_sdone = NULL; - sidone = sc->sc_sidone; - sc->sc_sidone = NULL; - crit_exit(); - - DPRINTFN(10,("ohci_softintr: sdone=%p sidone=%p\n", sdone, sidone)); - -#ifdef USB_DEBUG - if (ohcidebug > 10) { - DPRINTF(("ohci_process_done: TD done:\n")); - ohci_dump_tds(sdone); - } -#endif - - for (std = sdone; std; std = stdnext) { - xfer = std->xfer; - stdnext = std->dnext; - DPRINTFN(10, ("ohci_process_done: std=%p xfer=%p hcpriv=%p\n", - std, xfer, (xfer ? xfer->hcpriv : NULL))); - if (xfer == NULL) { - /* - * xfer == NULL: There seems to be no xfer associated - * with this TD. It is tailp that happened to end up on - * the done queue. - */ - continue; - } - if (xfer->status == USBD_CANCELLED || - xfer->status == USBD_TIMEOUT) { - DPRINTF(("ohci_process_done: cancel/timeout %p\n", - xfer)); - /* Handled by abort routine. */ - continue; - } - - len = std->len; - if (std->td.td_cbp != 0) - len -= le32toh(std->td.td_be) - - le32toh(std->td.td_cbp) + 1; - DPRINTFN(10, ("ohci_process_done: len=%d, flags=0x%x\n", len, - std->flags)); - if (std->flags & OHCI_ADD_LEN) - xfer->actlen += len; - - cc = OHCI_TD_GET_CC(le32toh(std->td.td_flags)); - if (cc != OHCI_CC_NO_ERROR) { - /* - * Endpoint is halted. First unlink all the TDs - * belonging to the failed transfer, and then restart - * the endpoint. - */ - opipe = (struct ohci_pipe *)xfer->pipe; - - DPRINTFN(15,("ohci_process_done: error cc=%d (%s)\n", - OHCI_TD_GET_CC(le32toh(std->td.td_flags)), - ohci_cc_strs[OHCI_TD_GET_CC(le32toh(std->td.td_flags))])); - callout_stop(&xfer->timeout_handle); - usb_rem_task(OXFER(xfer)->xfer.pipe->device, - &OXFER(xfer)->abort_task); - - /* Remove all this xfer's TDs from the done queue. */ - for (p = std; p->dnext != NULL; p = p->dnext) { - if (p->dnext->xfer != xfer) - continue; - p->dnext = p->dnext->dnext; - } - /* The next TD may have been removed. */ - stdnext = std->dnext; - - /* Remove all TDs belonging to this xfer. */ - for (p = xfer->hcpriv; p->xfer == xfer; p = n) { - n = p->nexttd; - ohci_free_std(sc, p); - } - - /* clear halt */ - opipe->sed->ed.ed_headp = htole32(p->physaddr); - OWRITE4(sc, OHCI_COMMAND_STATUS, OHCI_CLF); - - if (cc == OHCI_CC_STALL) - xfer->status = USBD_STALLED; - else - xfer->status = USBD_IOERROR; - crit_enter(); - usb_transfer_complete(xfer); - crit_exit(); - continue; - } - /* - * Skip intermediate TDs. They remain linked from - * xfer->hcpriv and we free them when the transfer completes. - */ - if ((std->flags & OHCI_CALL_DONE) == 0) - continue; - - /* Normal transfer completion */ - callout_stop(&xfer->timeout_handle); - usb_rem_task(OXFER(xfer)->xfer.pipe->device, - &OXFER(xfer)->abort_task); - for (p = xfer->hcpriv; p->xfer == xfer; p = n) { - n = p->nexttd; - ohci_free_std(sc, p); - } - xfer->status = USBD_NORMAL_COMPLETION; - crit_enter(); - usb_transfer_complete(xfer); - crit_exit(); - } - -#ifdef USB_DEBUG - if (ohcidebug > 10) { - DPRINTF(("ohci_softintr: ITD done:\n")); - ohci_dump_itds(sidone); - } -#endif - - for (sitd = sidone; sitd != NULL; sitd = sitdnext) { - xfer = sitd->xfer; - sitdnext = sitd->dnext; - sitd->flags |= OHCI_ITD_INTFIN; - DPRINTFN(1, ("ohci_process_done: sitd=%p xfer=%p hcpriv=%p\n", - sitd, xfer, xfer ? xfer->hcpriv : 0)); - if (xfer == NULL) - continue; - if (xfer->status == USBD_CANCELLED || - xfer->status == USBD_TIMEOUT) { - DPRINTF(("ohci_process_done: cancel/timeout %p\n", - xfer)); - /* Handled by abort routine. */ - continue; - } - if (xfer->pipe) - if (xfer->pipe->aborting) - continue; /*Ignore.*/ -#ifdef DIAGNOSTIC - if (sitd->isdone) - kprintf("ohci_softintr: sitd=%p is done\n", sitd); - sitd->isdone = 1; -#endif - opipe = (struct ohci_pipe *)xfer->pipe; - if (opipe->aborting) - continue; - - if (sitd->flags & OHCI_CALL_DONE) { - ohci_soft_itd_t *next; - - opipe->u.iso.inuse -= xfer->nframes; - xfer->status = USBD_NORMAL_COMPLETION; - for (i = 0, sitd = xfer->hcpriv;;sitd = next) { - next = sitd->nextitd; - if (OHCI_ITD_GET_CC(sitd->itd.itd_flags) != OHCI_CC_NO_ERROR) - xfer->status = USBD_IOERROR; - - if (xfer->status == USBD_NORMAL_COMPLETION) { - iframes = OHCI_ITD_GET_FC(sitd->itd.itd_flags); - for (j = 0; j < iframes; i++, j++) { - len = le16toh(sitd->itd.itd_offset[j]); - len = - (OHCI_ITD_PSW_GET_CC(len) == - OHCI_CC_NOT_ACCESSED) ? 0 : - OHCI_ITD_PSW_LENGTH(len); - xfer->frlengths[i] = len; - } - } - if (sitd->flags & OHCI_CALL_DONE) - break; - } - - crit_enter(); - usb_transfer_complete(xfer); - crit_exit(); - } - } - -#ifdef USB_USE_SOFTINTR - if (sc->sc_softwake) { - sc->sc_softwake = 0; - wakeup(&sc->sc_softwake); - } -#endif /* USB_USE_SOFTINTR */ - - sc->sc_bus.intr_context--; - DPRINTFN(10,("ohci_softintr: done:\n")); -} - -void -ohci_device_ctrl_done(usbd_xfer_handle xfer) -{ - DPRINTFN(10,("ohci_device_ctrl_done: xfer=%p\n", xfer)); - -#ifdef DIAGNOSTIC - if (!(xfer->rqflags & URQ_REQUEST)) { - panic("ohci_device_ctrl_done: not a request"); - } -#endif - xfer->hcpriv = NULL; -} - -void -ohci_device_intr_done(usbd_xfer_handle xfer) -{ - struct ohci_pipe *opipe = (struct ohci_pipe *)xfer->pipe; - ohci_softc_t *sc = (ohci_softc_t *)opipe->pipe.device->bus; - ohci_soft_ed_t *sed = opipe->sed; - ohci_soft_td_t *data, *tail; - - - DPRINTFN(10,("ohci_device_intr_done: xfer=%p, actlen=%d\n", - xfer, xfer->actlen)); - - xfer->hcpriv = NULL; - - if (xfer->pipe->repeat) { - data = opipe->tail.td; - tail = ohci_alloc_std(sc); /* XXX should reuse TD */ - if (tail == NULL) { - xfer->status = USBD_NOMEM; - return; - } - tail->xfer = NULL; - - data->td.td_flags = htole32( - OHCI_TD_IN | OHCI_TD_NOCC | - OHCI_TD_SET_DI(1) | OHCI_TD_TOGGLE_CARRY); - if (xfer->flags & USBD_SHORT_XFER_OK) - data->td.td_flags |= htole32(OHCI_TD_R); - data->td.td_cbp = htole32(DMAADDR(&xfer->dmabuf, 0)); - data->nexttd = tail; - data->td.td_nexttd = htole32(tail->physaddr); - data->td.td_be = htole32(le32toh(data->td.td_cbp) + - xfer->length - 1); - data->len = xfer->length; - data->xfer = xfer; - data->flags = OHCI_CALL_DONE | OHCI_ADD_LEN; - xfer->hcpriv = data; - xfer->actlen = 0; - - sed->ed.ed_tailp = htole32(tail->physaddr); - opipe->tail.td = tail; - } -} - -void -ohci_device_bulk_done(usbd_xfer_handle xfer) -{ - DPRINTFN(10,("ohci_device_bulk_done: xfer=%p, actlen=%d\n", - xfer, xfer->actlen)); - - xfer->hcpriv = NULL; -} - -void -ohci_rhsc(ohci_softc_t *sc, usbd_xfer_handle xfer) -{ - u_char *p; - int i, m; - int hstatus; - - hstatus = OREAD4(sc, OHCI_RH_STATUS); - DPRINTF(("ohci_rhsc: sc=%p xfer=%p hstatus=0x%08x\n", - sc, xfer, hstatus)); - - if (xfer == NULL) { - /* Just ignore the change. */ - return; - } - - p = KERNADDR(&xfer->dmabuf, 0); - m = min(sc->sc_noport, xfer->length * 8 - 1); - memset(p, 0, xfer->length); - for (i = 1; i <= m; i++) { - /* Pick out CHANGE bits from the status reg. */ - if (OREAD4(sc, OHCI_RH_PORT_STATUS(i)) >> 16) - p[i/8] |= 1 << (i%8); - } - DPRINTF(("ohci_rhsc: change=0x%02x\n", *p)); - xfer->actlen = xfer->length; - xfer->status = USBD_NORMAL_COMPLETION; - - usb_transfer_complete(xfer); -} - -void -ohci_root_intr_done(usbd_xfer_handle xfer) -{ - xfer->hcpriv = NULL; -} - -void -ohci_root_ctrl_done(usbd_xfer_handle xfer) -{ - xfer->hcpriv = NULL; -} - -/* - * Wait here until controller claims to have an interrupt. - * Then call ohci_intr and return. Use timeout to avoid waiting - * too long. - */ -void -ohci_waitintr(ohci_softc_t *sc, usbd_xfer_handle xfer) -{ - int timo = xfer->timeout; - int usecs; - u_int32_t intrs; - - xfer->status = USBD_IN_PROGRESS; - for (usecs = timo * 1000000 / hz; usecs > 0; usecs -= 1000) { - usb_delay_ms(&sc->sc_bus, 1); - if (sc->sc_dying) - break; - intrs = OREAD4(sc, OHCI_INTERRUPT_STATUS); - intrs |= sc->sc_dintrs; - intrs &= sc->sc_eintrs; - DPRINTFN(15,("ohci_waitintr: 0x%04x\n", intrs)); -#ifdef USB_DEBUG - if (ohcidebug > 15) - ohci_dumpregs(sc); -#endif - if (intrs) { - ohci_intr1(sc); - if (xfer->status != USBD_IN_PROGRESS) - return; - } - } - - /* Timeout */ - DPRINTF(("ohci_waitintr: timeout\n")); - xfer->status = USBD_TIMEOUT; - usb_transfer_complete(xfer); - /* XXX should free TD */ -} - -void -ohci_poll(struct usbd_bus *bus) -{ - ohci_softc_t *sc = (ohci_softc_t *)bus; -#ifdef USB_DEBUG - static int last; - int new; - - new = OREAD4(sc, OHCI_INTERRUPT_STATUS); - if (new != last) { - DPRINTFN(10,("ohci_poll: intrs=0x%04x\n", new)); - last = new; - } -#endif - crit_enter(); - ohci_intr1(sc); - ohci_softintr(sc); - crit_exit(); -} - -usbd_status -ohci_device_request(usbd_xfer_handle xfer) -{ - struct ohci_pipe *opipe = (struct ohci_pipe *)xfer->pipe; - usb_device_request_t *req = &xfer->request; - usbd_device_handle dev = opipe->pipe.device; - ohci_softc_t *sc = (ohci_softc_t *)dev->bus; - int addr = dev->address; - ohci_soft_td_t *setup, *stat, *next, *tail; - ohci_soft_ed_t *sed; - int isread; - int len; - usbd_status err; - - isread = req->bmRequestType & UT_READ; - len = UGETW(req->wLength); - - DPRINTFN(3,("ohci_device_control type=0x%02x, request=0x%02x, " - "wValue=0x%04x, wIndex=0x%04x len=%d, addr=%d, endpt=%d\n", - req->bmRequestType, req->bRequest, UGETW(req->wValue), - UGETW(req->wIndex), len, addr, - opipe->pipe.endpoint->edesc->bEndpointAddress)); - - setup = opipe->tail.td; - stat = ohci_alloc_std(sc); - if (stat == NULL) { - err = USBD_NOMEM; - goto bad1; - } - tail = ohci_alloc_std(sc); - if (tail == NULL) { - err = USBD_NOMEM; - goto bad2; - } - tail->xfer = NULL; - - sed = opipe->sed; - opipe->u.ctl.length = len; - -#if 1 - /* Update device address and length since they may have changed - during the setup of the control pipe in usbd_new_device(). */ - /* XXX This only needs to be done once, but it's too early in open. */ - /* XXXX Should not touch ED here! */ - sed->ed.ed_flags = htole32( - (le32toh(sed->ed.ed_flags) & ~(OHCI_ED_ADDRMASK | OHCI_ED_MAXPMASK)) | - OHCI_ED_SET_FA(addr) | - OHCI_ED_SET_MAXP(UGETW(opipe->pipe.endpoint->edesc->wMaxPacketSize))); -#endif - - next = stat; - - /* Set up data transaction */ - if (len != 0) { - ohci_soft_td_t *std = stat; - - err = ohci_alloc_std_chain(opipe, sc, len, isread, xfer, - std, &stat); - stat = stat->nexttd; /* point at free TD */ - if (err) - goto bad3; - /* Start toggle at 1 and then use the carried toggle. */ - std->td.td_flags &= htole32(~OHCI_TD_TOGGLE_MASK); - std->td.td_flags |= htole32(OHCI_TD_TOGGLE_1); - } - - memcpy(KERNADDR(&opipe->u.ctl.reqdma, 0), req, sizeof *req); - - setup->td.td_flags = htole32(OHCI_TD_SETUP | OHCI_TD_NOCC | - OHCI_TD_TOGGLE_0 | OHCI_TD_SET_DI(6)); - setup->td.td_cbp = htole32(DMAADDR(&opipe->u.ctl.reqdma, 0)); - setup->nexttd = next; - setup->td.td_nexttd = htole32(next->physaddr); - setup->td.td_be = htole32(le32toh(setup->td.td_cbp) + sizeof *req - 1); - setup->len = 0; - setup->xfer = xfer; - setup->flags = 0; - xfer->hcpriv = setup; - - stat->td.td_flags = htole32( - (isread ? OHCI_TD_OUT : OHCI_TD_IN) | - OHCI_TD_NOCC | OHCI_TD_TOGGLE_1 | OHCI_TD_SET_DI(1)); - stat->td.td_cbp = 0; - stat->nexttd = tail; - stat->td.td_nexttd = htole32(tail->physaddr); - stat->td.td_be = 0; - stat->flags = OHCI_CALL_DONE; - stat->len = 0; - stat->xfer = xfer; - -#ifdef USB_DEBUG - if (ohcidebug > 5) { - DPRINTF(("ohci_device_request:\n")); - ohci_dump_ed(sed); - ohci_dump_tds(setup); - } -#endif - - /* Insert ED in schedule */ - crit_enter(); - sed->ed.ed_tailp = htole32(tail->physaddr); - opipe->tail.td = tail; - OWRITE4(sc, OHCI_COMMAND_STATUS, OHCI_CLF); - if (xfer->timeout && !sc->sc_bus.use_polling) { - callout_reset(&xfer->timeout_handle, MS_TO_TICKS(xfer->timeout), - ohci_timeout, xfer); - } - crit_exit(); - -#ifdef USB_DEBUG - if (ohcidebug > 20) { - delay(10000); - DPRINTF(("ohci_device_request: status=%x\n", - OREAD4(sc, OHCI_COMMAND_STATUS))); - ohci_dumpregs(sc); - kprintf("ctrl head:\n"); - ohci_dump_ed(sc->sc_ctrl_head); - kprintf("sed:\n"); - ohci_dump_ed(sed); - ohci_dump_tds(setup); - } -#endif - - return (USBD_NORMAL_COMPLETION); - - bad3: - ohci_free_std(sc, tail); - bad2: - ohci_free_std(sc, stat); - bad1: - return (err); -} - -/* - * Add an ED to the schedule. Called from a critical section. - */ -void -ohci_add_ed(ohci_soft_ed_t *sed, ohci_soft_ed_t *head) -{ - DPRINTFN(8,("ohci_add_ed: sed=%p head=%p\n", sed, head)); - - sed->next = head->next; - sed->ed.ed_nexted = head->ed.ed_nexted; - head->next = sed; - head->ed.ed_nexted = htole32(sed->physaddr); -} - -/* - * Remove an ED from the schedule. Called from a critical section. - */ -void -ohci_rem_ed(ohci_soft_ed_t *sed, ohci_soft_ed_t *head) -{ - ohci_soft_ed_t *p; - - - /* XXX */ - for (p = head; p != NULL && p->next != sed; p = p->next) - ; -#if 0 - if (p == NULL) - panic("ohci_rem_ed: ED not found"); -#else - /* - * XXX - * p == NULL if ohci is detaching and there are still devices - * using ohci (e.g. usb sticks are still plugged in). But - * the real solution should be correcting ohci_free_sed() or - * correctly use it. - */ - if (p != NULL) { - p->next = sed->next; - p->ed.ed_nexted = sed->ed.ed_nexted; - } -#endif -} - -/* - * When a transfer is completed the TD is added to the done queue by - * the host controller. This queue is the processed by software. - * Unfortunately the queue contains the physical address of the TD - * and we have no simple way to translate this back to a kernel address. - * To make the translation possible (and fast) we use a hash table of - * TDs currently in the schedule. The physical address is used as the - * hash value. - */ - -#define HASH(a) (((a) >> 4) % OHCI_HASH_SIZE) -/* - * Called from a critical section - */ -void -ohci_hash_add_td(ohci_softc_t *sc, ohci_soft_td_t *std) -{ - int h = HASH(std->physaddr); - - LIST_INSERT_HEAD(&sc->sc_hash_tds[h], std, hnext); -} - -/* - * Called from a critical section - */ -void -ohci_hash_rem_td(ohci_softc_t *sc, ohci_soft_td_t *std) -{ - LIST_REMOVE(std, hnext); -} - -ohci_soft_td_t * -ohci_hash_find_td(ohci_softc_t *sc, ohci_physaddr_t a) -{ - int h = HASH(a); - ohci_soft_td_t *std; - - /* if these are present they should be masked out at an earlier - * stage. - */ - KASSERT((a&~OHCI_HEADMASK) == 0, ("%s: 0x%b has lower bits set", - device_get_nameunit(sc->sc_bus.bdev), - (int) a, "\20\1HALT\2TOGGLE")); - - for (std = LIST_FIRST(&sc->sc_hash_tds[h]); - std != NULL; - std = LIST_NEXT(std, hnext)) - if (std->physaddr == a) - return (std); - - DPRINTF(("%s: ohci_hash_find_td: addr 0x%08lx not found\n", - device_get_nameunit(sc->sc_bus.bdev), (u_long) a)); - return (NULL); -} - -/* - * Called from a critical section - */ -void -ohci_hash_add_itd(ohci_softc_t *sc, ohci_soft_itd_t *sitd) -{ - int h = HASH(sitd->physaddr); - - DPRINTFN(10,("ohci_hash_add_itd: sitd=%p physaddr=0x%08lx\n", - sitd, (u_long)sitd->physaddr)); - - LIST_INSERT_HEAD(&sc->sc_hash_itds[h], sitd, hnext); -} - -/* - * Called from a critical section - */ -void -ohci_hash_rem_itd(ohci_softc_t *sc, ohci_soft_itd_t *sitd) -{ - DPRINTFN(10,("ohci_hash_rem_itd: sitd=%p physaddr=0x%08lx\n", - sitd, (u_long)sitd->physaddr)); - - LIST_REMOVE(sitd, hnext); -} - -ohci_soft_itd_t * -ohci_hash_find_itd(ohci_softc_t *sc, ohci_physaddr_t a) -{ - int h = HASH(a); - ohci_soft_itd_t *sitd; - - for (sitd = LIST_FIRST(&sc->sc_hash_itds[h]); - sitd != NULL; - sitd = LIST_NEXT(sitd, hnext)) - if (sitd->physaddr == a) - return (sitd); - return (NULL); -} - -void -ohci_timeout(void *addr) -{ - struct ohci_xfer *oxfer = addr; - struct ohci_pipe *opipe = (struct ohci_pipe *)oxfer->xfer.pipe; - ohci_softc_t *sc = (ohci_softc_t *)opipe->pipe.device->bus; - - DPRINTF(("ohci_timeout: oxfer=%p\n", oxfer)); - - if (sc->sc_dying) { - ohci_abort_xfer(&oxfer->xfer, USBD_TIMEOUT); - return; - } - - /* Execute the abort in a process context. */ - usb_add_task(oxfer->xfer.pipe->device, &oxfer->abort_task, - USB_TASKQ_HC); -} - -void -ohci_timeout_task(void *addr) -{ - usbd_xfer_handle xfer = addr; - - DPRINTF(("ohci_timeout_task: xfer=%p\n", xfer)); - - crit_enter(); - ohci_abort_xfer(xfer, USBD_TIMEOUT); - crit_exit(); -} - -#ifdef USB_DEBUG -void -ohci_dump_tds(ohci_soft_td_t *std) -{ - for (; std; std = std->nexttd) - ohci_dump_td(std); -} - -void -ohci_dump_td(ohci_soft_td_t *std) -{ - char sbuf[128]; - - bitmask_snprintf((u_int32_t)le32toh(std->td.td_flags), - "\20\23R\24OUT\25IN\31TOG1\32SETTOGGLE", - sbuf, sizeof(sbuf)); - - kprintf("TD(%p) at %08lx: %s delay=%d ec=%d cc=%d\ncbp=0x%08lx " - "nexttd=0x%08lx be=0x%08lx\n", - std, (u_long)std->physaddr, sbuf, - OHCI_TD_GET_DI(le32toh(std->td.td_flags)), - OHCI_TD_GET_EC(le32toh(std->td.td_flags)), - OHCI_TD_GET_CC(le32toh(std->td.td_flags)), - (u_long)le32toh(std->td.td_cbp), - (u_long)le32toh(std->td.td_nexttd), - (u_long)le32toh(std->td.td_be)); -} - -void -ohci_dump_itd(ohci_soft_itd_t *sitd) -{ - int i; - - kprintf("ITD(%p) at %08lx: sf=%d di=%d fc=%d cc=%d\n" - "bp0=0x%08lx next=0x%08lx be=0x%08lx\n", - sitd, (u_long)sitd->physaddr, - OHCI_ITD_GET_SF(le32toh(sitd->itd.itd_flags)), - OHCI_ITD_GET_DI(le32toh(sitd->itd.itd_flags)), - OHCI_ITD_GET_FC(le32toh(sitd->itd.itd_flags)), - OHCI_ITD_GET_CC(le32toh(sitd->itd.itd_flags)), - (u_long)le32toh(sitd->itd.itd_bp0), - (u_long)le32toh(sitd->itd.itd_nextitd), - (u_long)le32toh(sitd->itd.itd_be)); - for (i = 0; i < OHCI_ITD_NOFFSET; i++) - kprintf("offs[%d]=0x%04x ", i, - (u_int)le16toh(sitd->itd.itd_offset[i])); - kprintf("\n"); -} - -void -ohci_dump_itds(ohci_soft_itd_t *sitd) -{ - for (; sitd; sitd = sitd->nextitd) - ohci_dump_itd(sitd); -} - -void -ohci_dump_ed(ohci_soft_ed_t *sed) -{ - char sbuf[128], sbuf2[128]; - - bitmask_snprintf((u_int32_t)le32toh(sed->ed.ed_flags), - "\20\14OUT\15IN\16LOWSPEED\17SKIP\20ISO", - sbuf, sizeof(sbuf)); - bitmask_snprintf((u_int32_t)le32toh(sed->ed.ed_headp), - "\20\1HALT\2CARRY", sbuf2, sizeof(sbuf2)); - - kprintf("ED(%p) at 0x%08lx: addr=%d endpt=%d maxp=%d flags=%s\ntailp=0x%08lx " - "headflags=%s headp=0x%08lx nexted=0x%08lx\n", - sed, (u_long)sed->physaddr, - OHCI_ED_GET_FA(le32toh(sed->ed.ed_flags)), - OHCI_ED_GET_EN(le32toh(sed->ed.ed_flags)), - OHCI_ED_GET_MAXP(le32toh(sed->ed.ed_flags)), sbuf, - (u_long)le32toh(sed->ed.ed_tailp), sbuf2, - (u_long)le32toh(sed->ed.ed_headp), - (u_long)le32toh(sed->ed.ed_nexted)); -} -#endif - -usbd_status -ohci_open(usbd_pipe_handle pipe) -{ - usbd_device_handle dev = pipe->device; - ohci_softc_t *sc = (ohci_softc_t *)dev->bus; - usb_endpoint_descriptor_t *ed = pipe->endpoint->edesc; - struct ohci_pipe *opipe = (struct ohci_pipe *)pipe; - u_int8_t addr = dev->address; - u_int8_t xfertype = ed->bmAttributes & UE_XFERTYPE; - ohci_soft_ed_t *sed; - ohci_soft_td_t *std; - ohci_soft_itd_t *sitd; - ohci_physaddr_t tdphys; - u_int32_t fmt; - usbd_status err; - int ival; - - DPRINTFN(1, ("ohci_open: pipe=%p, addr=%d, endpt=%d (%d)\n", - pipe, addr, ed->bEndpointAddress, sc->sc_addr)); - - if (sc->sc_dying) - return (USBD_IOERROR); - - std = NULL; - sed = NULL; - - if (addr == sc->sc_addr) { - switch (ed->bEndpointAddress) { - case USB_CONTROL_ENDPOINT: - pipe->methods = &ohci_root_ctrl_methods; - break; - case UE_DIR_IN | OHCI_INTR_ENDPT: - pipe->methods = &ohci_root_intr_methods; - break; - default: - return (USBD_INVAL); - } - } else { - sed = ohci_alloc_sed(sc); - if (sed == NULL) - goto bad0; - opipe->sed = sed; - if (xfertype == UE_ISOCHRONOUS) { - sitd = ohci_alloc_sitd(sc); - if (sitd == NULL) - goto bad1; - opipe->tail.itd = sitd; - opipe->aborting = 0; - tdphys = sitd->physaddr; - fmt = OHCI_ED_FORMAT_ISO; - if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN) - fmt |= OHCI_ED_DIR_IN; - else - fmt |= OHCI_ED_DIR_OUT; - } else { - std = ohci_alloc_std(sc); - if (std == NULL) - goto bad1; - opipe->tail.td = std; - tdphys = std->physaddr; - fmt = OHCI_ED_FORMAT_GEN | OHCI_ED_DIR_TD; - } - sed->ed.ed_flags = htole32( - OHCI_ED_SET_FA(addr) | - OHCI_ED_SET_EN(UE_GET_ADDR(ed->bEndpointAddress)) | - (dev->speed == USB_SPEED_LOW ? OHCI_ED_SPEED : 0) | - fmt | - OHCI_ED_SET_MAXP(UGETW(ed->wMaxPacketSize))); - sed->ed.ed_headp = htole32(tdphys | - (pipe->endpoint->savedtoggle ? OHCI_TOGGLECARRY : 0)); - sed->ed.ed_tailp = htole32(tdphys); - - switch (xfertype) { - case UE_CONTROL: - pipe->methods = &ohci_device_ctrl_methods; - err = usb_allocmem(&sc->sc_bus, - sizeof(usb_device_request_t), - 0, &opipe->u.ctl.reqdma); - if (err) - goto bad; - crit_enter(); - ohci_add_ed(sed, sc->sc_ctrl_head); - crit_exit(); - break; - case UE_INTERRUPT: - pipe->methods = &ohci_device_intr_methods; - ival = pipe->interval; - if (ival == USBD_DEFAULT_INTERVAL) - ival = ed->bInterval; - return (ohci_device_setintr(sc, opipe, ival)); - case UE_ISOCHRONOUS: - pipe->methods = &ohci_device_isoc_methods; - return (ohci_setup_isoc(pipe)); - case UE_BULK: - pipe->methods = &ohci_device_bulk_methods; - crit_enter(); - ohci_add_ed(sed, sc->sc_bulk_head); - crit_exit(); - break; - } - } - return (USBD_NORMAL_COMPLETION); - - bad: - if (std != NULL) - ohci_free_std(sc, std); - bad1: - if (sed != NULL) { - ohci_free_sed(sc, sed); - opipe->sed = NULL; - } - bad0: - return (USBD_NOMEM); - -} - -/* - * Close a reqular pipe. - * Assumes that there are no pending transactions. - */ -void -ohci_close_pipe(usbd_pipe_handle pipe, ohci_soft_ed_t *head) -{ - struct ohci_pipe *opipe = (struct ohci_pipe *)pipe; - ohci_softc_t *sc = (ohci_softc_t *)pipe->device->bus; - ohci_soft_ed_t *sed = opipe->sed; - - crit_enter(); -#ifdef DIAGNOSTIC - sed->ed.ed_flags |= htole32(OHCI_ED_SKIP); - if ((le32toh(sed->ed.ed_tailp) & OHCI_HEADMASK) != - (le32toh(sed->ed.ed_headp) & OHCI_HEADMASK)) { - ohci_soft_td_t *std; - std = ohci_hash_find_td(sc, le32toh(sed->ed.ed_headp)); - kprintf("ohci_close_pipe: pipe not empty sed=%p hd=0x%x " - "tl=0x%x pipe=%p, std=%p\n", sed, - (int)le32toh(sed->ed.ed_headp), - (int)le32toh(sed->ed.ed_tailp), - pipe, std); -#ifdef USB_DEBUG - usbd_dump_pipe(&opipe->pipe); -#endif -#ifdef USB_DEBUG - ohci_dump_ed(sed); - if (std) - ohci_dump_td(std); -#endif - usb_delay_ms(&sc->sc_bus, 2); - if ((le32toh(sed->ed.ed_tailp) & OHCI_HEADMASK) != - (le32toh(sed->ed.ed_headp) & OHCI_HEADMASK)) - kprintf("ohci_close_pipe: pipe still not empty\n"); - } -#endif - ohci_rem_ed(sed, head); - /* Make sure the host controller is not touching this ED */ - usb_delay_ms(&sc->sc_bus, 1); - crit_exit(); - pipe->endpoint->savedtoggle = - (le32toh(sed->ed.ed_headp) & OHCI_TOGGLECARRY) ? 1 : 0; - ohci_free_sed(sc, opipe->sed); - opipe->sed = NULL; -} - -/* - * Abort a device request. - * If this routine is called from a critical section it guarantees that - * the request will be removed from the hardware scheduling and that - * the callback for it will be called with USBD_CANCELLED status. - * It's impossible to guarantee that the requested transfer will not - * have happened since the hardware runs concurrently. - * If the transaction has already happened we rely on the ordinary - * interrupt processing to process it. - */ -void -ohci_abort_xfer(usbd_xfer_handle xfer, usbd_status status) -{ - struct ohci_xfer *oxfer = OXFER(xfer); - struct ohci_pipe *opipe = (struct ohci_pipe *)xfer->pipe; - ohci_softc_t *sc = (ohci_softc_t *)opipe->pipe.device->bus; - ohci_soft_ed_t *sed = opipe->sed; - ohci_soft_td_t *p, *n; - ohci_physaddr_t headp; - int hit; - - DPRINTF(("ohci_abort_xfer: xfer=%p pipe=%p sed=%p\n", xfer, opipe,sed)); - - if (sc->sc_dying) { - /* If we're dying, just do the software part. */ - crit_enter(); - xfer->status = status; /* make software ignore it */ - callout_stop(&xfer->timeout_handle); - usb_rem_task(xfer->pipe->device, &OXFER(xfer)->abort_task); - usb_transfer_complete(xfer); - crit_exit(); - return; - } - -#if 0 - if (xfer->device->bus->intr_context /* || !curproc REMOVED DFly */) - panic("ohci_abort_xfer: not in process context"); -#endif - - /* - * If an abort is already in progress then just wait for it to - * complete and return. - */ - if (oxfer->ohci_xfer_flags & OHCI_XFER_ABORTING) { - DPRINTFN(2, ("ohci_abort_xfer: already aborting\n")); - /* No need to wait if we're aborting from a timeout. */ - if (status == USBD_TIMEOUT) - return; - /* Override the status which might be USBD_TIMEOUT. */ - xfer->status = status; - DPRINTFN(2, ("ohci_abort_xfer: waiting for abort to finish\n")); - oxfer->ohci_xfer_flags |= OHCI_XFER_ABORTWAIT; - while (oxfer->ohci_xfer_flags & OHCI_XFER_ABORTING) - tsleep(&oxfer->ohci_xfer_flags, 0, "ohciaw", 0); - return; - } - - /* - * Step 1: Make interrupt routine and hardware ignore xfer. - */ - crit_enter(); - oxfer->ohci_xfer_flags |= OHCI_XFER_ABORTING; - xfer->status = status; /* make software ignore it */ - callout_stop(&xfer->timeout_handle); - usb_rem_task(xfer->pipe->device, &OXFER(xfer)->abort_task); - crit_exit(); - DPRINTFN(1,("ohci_abort_xfer: stop ed=%p\n", sed)); - sed->ed.ed_flags |= htole32(OHCI_ED_SKIP); /* force hardware skip */ - - /* - * Step 2: Wait until we know hardware has finished any possible - * use of the xfer. Also make sure the soft interrupt routine - * has run. - */ - usb_delay_ms(opipe->pipe.device->bus, 20); /* Hardware finishes in 1ms */ - crit_enter(); -#ifdef USB_USE_SOFTINTR - sc->sc_softwake = 1; -#endif /* USB_USE_SOFTINTR */ - usb_schedsoftintr(&sc->sc_bus); -#ifdef USB_USE_SOFTINTR - tsleep(&sc->sc_softwake, 0, "ohciab", 0); -#endif /* USB_USE_SOFTINTR */ - - /* - * Step 3: Remove any vestiges of the xfer from the hardware. - * The complication here is that the hardware may have executed - * beyond the xfer we're trying to abort. So as we're scanning - * the TDs of this xfer we check if the hardware points to - * any of them. - */ - p = xfer->hcpriv; -#ifdef DIAGNOSTIC - if (p == NULL) { - oxfer->ohci_xfer_flags &= ~OHCI_XFER_ABORTING; /* XXX */ - crit_exit(); - kprintf("ohci_abort_xfer: hcpriv is NULL\n"); - return; - } -#endif -#ifdef USB_DEBUG - if (ohcidebug > 1) { - DPRINTF(("ohci_abort_xfer: sed=\n")); - ohci_dump_ed(sed); - ohci_dump_tds(p); - } -#endif - headp = le32toh(sed->ed.ed_headp) & OHCI_HEADMASK; - hit = 0; - for (; p->xfer == xfer; p = n) { - hit |= headp == p->physaddr; - n = p->nexttd; - ohci_free_std(sc, p); - } - /* Zap headp register if hardware pointed inside the xfer. */ - if (hit) { - DPRINTFN(1,("ohci_abort_xfer: set hd=0x08%x, tl=0x%08x\n", - (int)p->physaddr, (int)le32toh(sed->ed.ed_tailp))); - sed->ed.ed_headp = htole32(p->physaddr); /* unlink TDs */ - } else { - DPRINTFN(1,("ohci_abort_xfer: no hit\n")); - } - - /* - * Step 4: Turn on hardware again. - */ - sed->ed.ed_flags &= htole32(~OHCI_ED_SKIP); /* remove hardware skip */ - - /* - * Step 5: Execute callback. - */ - /* Do the wakeup first to avoid touching the xfer after the callback. */ - oxfer->ohci_xfer_flags &= ~OHCI_XFER_ABORTING; - if (oxfer->ohci_xfer_flags & OHCI_XFER_ABORTWAIT) { - oxfer->ohci_xfer_flags &= ~OHCI_XFER_ABORTWAIT; - wakeup(&oxfer->ohci_xfer_flags); - } - usb_transfer_complete(xfer); - - crit_exit(); -} - -/* - * Data structures and routines to emulate the root hub. - */ -static usb_device_descriptor_t ohci_devd = { - USB_DEVICE_DESCRIPTOR_SIZE, - UDESC_DEVICE, /* type */ - {0x00, 0x01}, /* USB version */ - UDCLASS_HUB, /* class */ - UDSUBCLASS_HUB, /* subclass */ - UDPROTO_FSHUB, /* protocol */ - 64, /* max packet */ - {0},{0},{0x00,0x01}, /* device id */ - 1,2,0, /* string indicies */ - 1 /* # of configurations */ -}; - -static usb_config_descriptor_t ohci_confd = { - USB_CONFIG_DESCRIPTOR_SIZE, - UDESC_CONFIG, - {USB_CONFIG_DESCRIPTOR_SIZE + - USB_INTERFACE_DESCRIPTOR_SIZE + - USB_ENDPOINT_DESCRIPTOR_SIZE}, - 1, - 1, - 0, - UC_SELF_POWERED, - 0 /* max power */ -}; - -static usb_interface_descriptor_t ohci_ifcd = { - USB_INTERFACE_DESCRIPTOR_SIZE, - UDESC_INTERFACE, - 0, - 0, - 1, - UICLASS_HUB, - UISUBCLASS_HUB, - UIPROTO_FSHUB, - 0 -}; - -static usb_endpoint_descriptor_t ohci_endpd = { - USB_ENDPOINT_DESCRIPTOR_SIZE, - UDESC_ENDPOINT, - UE_DIR_IN | OHCI_INTR_ENDPT, - UE_INTERRUPT, - {8, 0}, /* max packet */ - 255 -}; - -static usb_hub_descriptor_t ohci_hubd = { - USB_HUB_DESCRIPTOR_SIZE, - UDESC_HUB, - 0, - {0,0}, - 0, - 0, - {0}, -}; - -static int -ohci_str(usb_string_descriptor_t *p, int l, const char *s) -{ - int i; - - if (l == 0) - return (0); - p->bLength = 2 * strlen(s) + 2; - if (l == 1) - return (1); - p->bDescriptorType = UDESC_STRING; - l -= 2; - for (i = 0; s[i] && l > 1; i++, l -= 2) - USETW2(p->bString[i], 0, s[i]); - return (2*i+2); -} - -/* - * Simulate a hardware hub by handling all the necessary requests. - */ -static usbd_status -ohci_root_ctrl_transfer(usbd_xfer_handle xfer) -{ - usbd_status err; - - /* Insert last in queue. */ - err = usb_insert_transfer(xfer); - if (err) - return (err); - - /* Pipe isn't running, start first */ - return (ohci_root_ctrl_start(STAILQ_FIRST(&xfer->pipe->queue))); -} - -static usbd_status -ohci_root_ctrl_start(usbd_xfer_handle xfer) -{ - ohci_softc_t *sc = (ohci_softc_t *)xfer->pipe->device->bus; - usb_device_request_t *req; - void *buf = NULL; - int port, i; - int len, value, index, l, totlen = 0; - usb_port_status_t ps; - usb_hub_descriptor_t hubd; - usbd_status err; - u_int32_t v; - - if (sc->sc_dying) - return (USBD_IOERROR); - -#ifdef DIAGNOSTIC - if (!(xfer->rqflags & URQ_REQUEST)) - /* XXX panic */ - return (USBD_INVAL); -#endif - req = &xfer->request; - - DPRINTFN(4,("ohci_root_ctrl_control type=0x%02x request=%02x\n", - req->bmRequestType, req->bRequest)); - - len = UGETW(req->wLength); - value = UGETW(req->wValue); - index = UGETW(req->wIndex); - - if (len != 0) - buf = KERNADDR(&xfer->dmabuf, 0); - -#define C(x,y) ((x) | ((y) << 8)) - switch(C(req->bRequest, req->bmRequestType)) { - case C(UR_CLEAR_FEATURE, UT_WRITE_DEVICE): - case C(UR_CLEAR_FEATURE, UT_WRITE_INTERFACE): - case C(UR_CLEAR_FEATURE, UT_WRITE_ENDPOINT): - /* - * DEVICE_REMOTE_WAKEUP and ENDPOINT_HALT are no-ops - * for the integrated root hub. - */ - break; - case C(UR_GET_CONFIG, UT_READ_DEVICE): - if (len > 0) { - *(u_int8_t *)buf = sc->sc_conf; - totlen = 1; - } - break; - case C(UR_GET_DESCRIPTOR, UT_READ_DEVICE): - DPRINTFN(8,("ohci_root_ctrl_control wValue=0x%04x\n", value)); - switch(value >> 8) { - case UDESC_DEVICE: - if ((value & 0xff) != 0) { - err = USBD_IOERROR; - goto ret; - } - totlen = l = min(len, USB_DEVICE_DESCRIPTOR_SIZE); - USETW(ohci_devd.idVendor, sc->sc_id_vendor); - memcpy(buf, &ohci_devd, l); - break; - case UDESC_CONFIG: - if ((value & 0xff) != 0) { - err = USBD_IOERROR; - goto ret; - } - totlen = l = min(len, USB_CONFIG_DESCRIPTOR_SIZE); - memcpy(buf, &ohci_confd, l); - buf = (char *)buf + l; - len -= l; - l = min(len, USB_INTERFACE_DESCRIPTOR_SIZE); - totlen += l; - memcpy(buf, &ohci_ifcd, l); - buf = (char *)buf + l; - len -= l; - l = min(len, USB_ENDPOINT_DESCRIPTOR_SIZE); - totlen += l; - memcpy(buf, &ohci_endpd, l); - break; - case UDESC_STRING: - if (len == 0) - break; - *(u_int8_t *)buf = 0; - totlen = 1; - switch (value & 0xff) { - case 1: /* Vendor */ - totlen = ohci_str(buf, len, sc->sc_vendor); - break; - case 2: /* Product */ - totlen = ohci_str(buf, len, "OHCI root hub"); - break; - } - break; - default: - err = USBD_IOERROR; - goto ret; - } - break; - case C(UR_GET_INTERFACE, UT_READ_INTERFACE): - if (len > 0) { - *(u_int8_t *)buf = 0; - totlen = 1; - } - break; - case C(UR_GET_STATUS, UT_READ_DEVICE): - if (len > 1) { - USETW(((usb_status_t *)buf)->wStatus,UDS_SELF_POWERED); - totlen = 2; - } - break; - case C(UR_GET_STATUS, UT_READ_INTERFACE): - case C(UR_GET_STATUS, UT_READ_ENDPOINT): - if (len > 1) { - USETW(((usb_status_t *)buf)->wStatus, 0); - totlen = 2; - } - break; - case C(UR_SET_ADDRESS, UT_WRITE_DEVICE): - if (value >= USB_MAX_DEVICES) { - err = USBD_IOERROR; - goto ret; - } - sc->sc_addr = value; - break; - case C(UR_SET_CONFIG, UT_WRITE_DEVICE): - if (value != 0 && value != 1) { - err = USBD_IOERROR; - goto ret; - } - sc->sc_conf = value; - break; - case C(UR_SET_DESCRIPTOR, UT_WRITE_DEVICE): - break; - case C(UR_SET_FEATURE, UT_WRITE_DEVICE): - case C(UR_SET_FEATURE, UT_WRITE_INTERFACE): - case C(UR_SET_FEATURE, UT_WRITE_ENDPOINT): - err = USBD_IOERROR; - goto ret; - case C(UR_SET_INTERFACE, UT_WRITE_INTERFACE): - break; - case C(UR_SYNCH_FRAME, UT_WRITE_ENDPOINT): - break; - /* Hub requests */ - case C(UR_CLEAR_FEATURE, UT_WRITE_CLASS_DEVICE): - break; - case C(UR_CLEAR_FEATURE, UT_WRITE_CLASS_OTHER): - DPRINTFN(8, ("ohci_root_ctrl_control: UR_CLEAR_PORT_FEATURE " - "port=%d feature=%d\n", - index, value)); - if (index < 1 || index > sc->sc_noport) { - err = USBD_IOERROR; - goto ret; - } - port = OHCI_RH_PORT_STATUS(index); - switch(value) { - case UHF_PORT_ENABLE: - OWRITE4(sc, port, UPS_CURRENT_CONNECT_STATUS); - break; - case UHF_PORT_SUSPEND: - OWRITE4(sc, port, UPS_OVERCURRENT_INDICATOR); - break; - case UHF_PORT_POWER: - /* Yes, writing to the LOW_SPEED bit clears power. */ - OWRITE4(sc, port, UPS_LOW_SPEED); - break; - case UHF_C_PORT_CONNECTION: - OWRITE4(sc, port, UPS_C_CONNECT_STATUS << 16); - break; - case UHF_C_PORT_ENABLE: - OWRITE4(sc, port, UPS_C_PORT_ENABLED << 16); - break; - case UHF_C_PORT_SUSPEND: - OWRITE4(sc, port, UPS_C_SUSPEND << 16); - break; - case UHF_C_PORT_OVER_CURRENT: - OWRITE4(sc, port, UPS_C_OVERCURRENT_INDICATOR << 16); - break; - case UHF_C_PORT_RESET: - OWRITE4(sc, port, UPS_C_PORT_RESET << 16); - break; - default: - err = USBD_IOERROR; - goto ret; - } - switch(value) { - case UHF_C_PORT_CONNECTION: - case UHF_C_PORT_ENABLE: - case UHF_C_PORT_SUSPEND: - case UHF_C_PORT_OVER_CURRENT: - case UHF_C_PORT_RESET: - /* Enable RHSC interrupt if condition is cleared. */ - if ((OREAD4(sc, port) >> 16) == 0) - ohci_rhsc_able(sc, 1); - break; - default: - break; - } - break; - case C(UR_GET_DESCRIPTOR, UT_READ_CLASS_DEVICE): - if ((value & 0xff) != 0) { - err = USBD_IOERROR; - goto ret; - } - v = OREAD4(sc, OHCI_RH_DESCRIPTOR_A); - hubd = ohci_hubd; - hubd.bNbrPorts = sc->sc_noport; - USETW(hubd.wHubCharacteristics, - (v & OHCI_NPS ? UHD_PWR_NO_SWITCH : - v & OHCI_PSM ? UHD_PWR_GANGED : UHD_PWR_INDIVIDUAL) - /* XXX overcurrent */ - ); - hubd.bPwrOn2PwrGood = OHCI_GET_POTPGT(v); - v = OREAD4(sc, OHCI_RH_DESCRIPTOR_B); - for (i = 0, l = sc->sc_noport; l > 0; i++, l -= 8, v >>= 8) - hubd.DeviceRemovable[i++] = (u_int8_t)v; - hubd.bDescLength = USB_HUB_DESCRIPTOR_SIZE + i; - l = min(len, hubd.bDescLength); - totlen = l; - memcpy(buf, &hubd, l); - break; - case C(UR_GET_STATUS, UT_READ_CLASS_DEVICE): - if (len != 4) { - err = USBD_IOERROR; - goto ret; - } - memset(buf, 0, len); /* ? XXX */ - totlen = len; - break; - case C(UR_GET_STATUS, UT_READ_CLASS_OTHER): - DPRINTFN(8,("ohci_root_ctrl_transfer: get port status i=%d\n", - index)); - if (index < 1 || index > sc->sc_noport) { - err = USBD_IOERROR; - goto ret; - } - if (len != 4) { - err = USBD_IOERROR; - goto ret; - } - v = OREAD4(sc, OHCI_RH_PORT_STATUS(index)); - DPRINTFN(8,("ohci_root_ctrl_transfer: port status=0x%04x\n", - v)); - USETW(ps.wPortStatus, v); - USETW(ps.wPortChange, v >> 16); - l = min(len, sizeof ps); - memcpy(buf, &ps, l); - totlen = l; - break; - case C(UR_SET_DESCRIPTOR, UT_WRITE_CLASS_DEVICE): - err = USBD_IOERROR; - goto ret; - case C(UR_SET_FEATURE, UT_WRITE_CLASS_DEVICE): - break; - case C(UR_SET_FEATURE, UT_WRITE_CLASS_OTHER): - if (index < 1 || index > sc->sc_noport) { - err = USBD_IOERROR; - goto ret; - } - port = OHCI_RH_PORT_STATUS(index); - switch(value) { - case UHF_PORT_ENABLE: - OWRITE4(sc, port, UPS_PORT_ENABLED); - break; - case UHF_PORT_SUSPEND: - OWRITE4(sc, port, UPS_SUSPEND); - break; - case UHF_PORT_RESET: - DPRINTFN(5,("ohci_root_ctrl_transfer: reset port %d\n", - index)); - OWRITE4(sc, port, UPS_RESET); - for (i = 0; i < 5; i++) { - usb_delay_ms(&sc->sc_bus, - USB_PORT_ROOT_RESET_DELAY); - if (sc->sc_dying) { - err = USBD_IOERROR; - goto ret; - } - if ((OREAD4(sc, port) & UPS_RESET) == 0) - break; - } - DPRINTFN(8,("ohci port %d reset, status = 0x%04x\n", - index, OREAD4(sc, port))); - break; - case UHF_PORT_POWER: - DPRINTFN(2,("ohci_root_ctrl_transfer: set port power " - "%d\n", index)); - OWRITE4(sc, port, UPS_PORT_POWER); - break; - default: - err = USBD_IOERROR; - goto ret; - } - break; - default: - err = USBD_IOERROR; - goto ret; - } - xfer->actlen = totlen; - err = USBD_NORMAL_COMPLETION; - ret: - xfer->status = err; - crit_enter(); - usb_transfer_complete(xfer); - crit_exit(); - return (USBD_IN_PROGRESS); -} - -/* Abort a root control request. */ -static void -ohci_root_ctrl_abort(usbd_xfer_handle xfer) -{ - /* Nothing to do, all transfers are synchronous. */ -} - -/* Close the root pipe. */ -static void -ohci_root_ctrl_close(usbd_pipe_handle pipe) -{ - DPRINTF(("ohci_root_ctrl_close\n")); - /* Nothing to do. */ -} - -static usbd_status -ohci_root_intr_transfer(usbd_xfer_handle xfer) -{ - usbd_status err; - - /* Insert last in queue. */ - err = usb_insert_transfer(xfer); - if (err) - return (err); - - /* Pipe isn't running, start first */ - return (ohci_root_intr_start(STAILQ_FIRST(&xfer->pipe->queue))); -} - -static usbd_status -ohci_root_intr_start(usbd_xfer_handle xfer) -{ - usbd_pipe_handle pipe = xfer->pipe; - ohci_softc_t *sc = (ohci_softc_t *)pipe->device->bus; - - if (sc->sc_dying) - return (USBD_IOERROR); - - sc->sc_intrxfer = xfer; - - return (USBD_IN_PROGRESS); -} - -/* Abort a root interrupt request. */ -static void -ohci_root_intr_abort(usbd_xfer_handle xfer) -{ - if (xfer->pipe->intrxfer == xfer) { - DPRINTF(("ohci_root_intr_abort: remove\n")); - xfer->pipe->intrxfer = NULL; - } - xfer->status = USBD_CANCELLED; - crit_enter(); - usb_transfer_complete(xfer); - crit_exit(); -} - -/* Close the root pipe. */ -static void -ohci_root_intr_close(usbd_pipe_handle pipe) -{ - ohci_softc_t *sc = (ohci_softc_t *)pipe->device->bus; - - DPRINTF(("ohci_root_intr_close\n")); - - sc->sc_intrxfer = NULL; -} - -/************************/ - -static usbd_status -ohci_device_ctrl_transfer(usbd_xfer_handle xfer) -{ - usbd_status err; - - /* Insert last in queue. */ - err = usb_insert_transfer(xfer); - if (err) - return (err); - - /* Pipe isn't running, start first */ - return (ohci_device_ctrl_start(STAILQ_FIRST(&xfer->pipe->queue))); -} - -static usbd_status -ohci_device_ctrl_start(usbd_xfer_handle xfer) -{ - ohci_softc_t *sc = (ohci_softc_t *)xfer->pipe->device->bus; - usbd_status err; - - if (sc->sc_dying) - return (USBD_IOERROR); - -#ifdef DIAGNOSTIC - if (!(xfer->rqflags & URQ_REQUEST)) { - /* XXX panic */ - kprintf("ohci_device_ctrl_transfer: not a request\n"); - return (USBD_INVAL); - } -#endif - - err = ohci_device_request(xfer); - if (err) - return (err); - - if (sc->sc_bus.use_polling) - ohci_waitintr(sc, xfer); - return (USBD_IN_PROGRESS); -} - -/* Abort a device control request. */ -static void -ohci_device_ctrl_abort(usbd_xfer_handle xfer) -{ - DPRINTF(("ohci_device_ctrl_abort: xfer=%p\n", xfer)); - ohci_abort_xfer(xfer, USBD_CANCELLED); -} - -/* Close a device control pipe. */ -static void -ohci_device_ctrl_close(usbd_pipe_handle pipe) -{ - struct ohci_pipe *opipe = (struct ohci_pipe *)pipe; - ohci_softc_t *sc = (ohci_softc_t *)pipe->device->bus; - - DPRINTF(("ohci_device_ctrl_close: pipe=%p\n", pipe)); - ohci_close_pipe(pipe, sc->sc_ctrl_head); - ohci_free_std(sc, opipe->tail.td); -} - -/************************/ - -static void -ohci_device_clear_toggle(usbd_pipe_handle pipe) -{ - struct ohci_pipe *opipe = (struct ohci_pipe *)pipe; - - opipe->sed->ed.ed_headp &= htole32(~OHCI_TOGGLECARRY); -} - -static void -ohci_noop(usbd_pipe_handle pipe) -{ -} - -static usbd_status -ohci_device_bulk_transfer(usbd_xfer_handle xfer) -{ - usbd_status err; - - /* Insert last in queue. */ - err = usb_insert_transfer(xfer); - if (err) - return (err); - - /* Pipe isn't running, start first */ - return (ohci_device_bulk_start(STAILQ_FIRST(&xfer->pipe->queue))); -} - -static usbd_status -ohci_device_bulk_start(usbd_xfer_handle xfer) -{ - struct ohci_pipe *opipe = (struct ohci_pipe *)xfer->pipe; - usbd_device_handle dev = opipe->pipe.device; - ohci_softc_t *sc = (ohci_softc_t *)dev->bus; - int addr = dev->address; - ohci_soft_td_t *data, *tail, *tdp; - ohci_soft_ed_t *sed; - int len, isread, endpt; - usbd_status err; - - if (sc->sc_dying) - return (USBD_IOERROR); - -#ifdef DIAGNOSTIC - if (xfer->rqflags & URQ_REQUEST) { - /* XXX panic */ - kprintf("ohci_device_bulk_start: a request\n"); - return (USBD_INVAL); - } -#endif - - xfer->actlen = 0; - len = xfer->length; - endpt = xfer->pipe->endpoint->edesc->bEndpointAddress; - isread = UE_GET_DIR(endpt) == UE_DIR_IN; - sed = opipe->sed; - - DPRINTFN(4,("ohci_device_bulk_start: xfer=%p len=%d isread=%d " - "flags=%d endpt=%d\n", xfer, len, isread, xfer->flags, - endpt)); - - opipe->u.bulk.isread = isread; - opipe->u.bulk.length = len; - - /* Update device address */ - sed->ed.ed_flags = htole32( - (le32toh(sed->ed.ed_flags) & ~OHCI_ED_ADDRMASK) | - OHCI_ED_SET_FA(addr)); - - /* Allocate a chain of new TDs (including a new tail). */ - data = opipe->tail.td; - err = ohci_alloc_std_chain(opipe, sc, len, isread, xfer, - data, &tail); - /* We want interrupt at the end of the transfer. */ - tail->td.td_flags &= htole32(~OHCI_TD_INTR_MASK); - tail->td.td_flags |= htole32(OHCI_TD_SET_DI(1)); - tail->flags |= OHCI_CALL_DONE; - tail = tail->nexttd; /* point at sentinel */ - if (err) - return (err); - - tail->xfer = NULL; - xfer->hcpriv = data; - - DPRINTFN(4,("ohci_device_bulk_start: ed_flags=0x%08x td_flags=0x%08x " - "td_cbp=0x%08x td_be=0x%08x\n", - (int)le32toh(sed->ed.ed_flags), - (int)le32toh(data->td.td_flags), - (int)le32toh(data->td.td_cbp), - (int)le32toh(data->td.td_be))); - -#ifdef USB_DEBUG - if (ohcidebug > 5) { - ohci_dump_ed(sed); - ohci_dump_tds(data); - } -#endif - - /* Insert ED in schedule */ - crit_enter(); - for (tdp = data; tdp != tail; tdp = tdp->nexttd) { - tdp->xfer = xfer; - } - sed->ed.ed_tailp = htole32(tail->physaddr); - opipe->tail.td = tail; - sed->ed.ed_flags &= htole32(~OHCI_ED_SKIP); - OWRITE4(sc, OHCI_COMMAND_STATUS, OHCI_BLF); - if (xfer->timeout && !sc->sc_bus.use_polling) { - callout_reset(&xfer->timeout_handle, MS_TO_TICKS(xfer->timeout), - ohci_timeout, xfer); - } - -#if 0 -/* This goes wrong if we are too slow. */ - if (ohcidebug > 10) { - delay(10000); - DPRINTF(("ohci_device_intr_transfer: status=%x\n", - OREAD4(sc, OHCI_COMMAND_STATUS))); - ohci_dump_ed(sed); - ohci_dump_tds(data); - } -#endif - - crit_exit(); - - if (sc->sc_bus.use_polling) - ohci_waitintr(sc, xfer); - - return (USBD_IN_PROGRESS); -} - -static void -ohci_device_bulk_abort(usbd_xfer_handle xfer) -{ - DPRINTF(("ohci_device_bulk_abort: xfer=%p\n", xfer)); - ohci_abort_xfer(xfer, USBD_CANCELLED); -} - -/* - * Close a device bulk pipe. - */ -static void -ohci_device_bulk_close(usbd_pipe_handle pipe) -{ - struct ohci_pipe *opipe = (struct ohci_pipe *)pipe; - ohci_softc_t *sc = (ohci_softc_t *)pipe->device->bus; - - DPRINTF(("ohci_device_bulk_close: pipe=%p\n", pipe)); - ohci_close_pipe(pipe, sc->sc_bulk_head); - ohci_free_std(sc, opipe->tail.td); -} - -/************************/ - -static usbd_status -ohci_device_intr_transfer(usbd_xfer_handle xfer) -{ - usbd_status err; - - /* Insert last in queue. */ - err = usb_insert_transfer(xfer); - if (err) - return (err); - - /* Pipe isn't running, start first */ - return (ohci_device_intr_start(STAILQ_FIRST(&xfer->pipe->queue))); -} - -static usbd_status -ohci_device_intr_start(usbd_xfer_handle xfer) -{ - struct ohci_pipe *opipe = (struct ohci_pipe *)xfer->pipe; - usbd_device_handle dev = opipe->pipe.device; - ohci_softc_t *sc = (ohci_softc_t *)dev->bus; - ohci_soft_ed_t *sed = opipe->sed; - ohci_soft_td_t *data, *tail; - int len; - - if (sc->sc_dying) - return (USBD_IOERROR); - - DPRINTFN(3, ("ohci_device_intr_transfer: xfer=%p len=%d " - "flags=%d priv=%p\n", - xfer, xfer->length, xfer->flags, xfer->priv)); - -#ifdef DIAGNOSTIC - if (xfer->rqflags & URQ_REQUEST) - panic("ohci_device_intr_transfer: a request"); -#endif - - len = xfer->length; - - data = opipe->tail.td; - tail = ohci_alloc_std(sc); - if (tail == NULL) - return (USBD_NOMEM); - tail->xfer = NULL; - - data->td.td_flags = htole32( - OHCI_TD_IN | OHCI_TD_NOCC | - OHCI_TD_SET_DI(1) | OHCI_TD_TOGGLE_CARRY); - if (xfer->flags & USBD_SHORT_XFER_OK) - data->td.td_flags |= htole32(OHCI_TD_R); - data->td.td_cbp = htole32(DMAADDR(&xfer->dmabuf, 0)); - data->nexttd = tail; - data->td.td_nexttd = htole32(tail->physaddr); - data->td.td_be = htole32(le32toh(data->td.td_cbp) + len - 1); - data->len = len; - data->xfer = xfer; - data->flags = OHCI_CALL_DONE | OHCI_ADD_LEN; - xfer->hcpriv = data; - -#ifdef USB_DEBUG - if (ohcidebug > 5) { - DPRINTF(("ohci_device_intr_transfer:\n")); - ohci_dump_ed(sed); - ohci_dump_tds(data); - } -#endif - - /* Insert ED in schedule */ - crit_enter(); - sed->ed.ed_tailp = htole32(tail->physaddr); - opipe->tail.td = tail; - sed->ed.ed_flags &= htole32(~OHCI_ED_SKIP); - -#if 0 -/* - * This goes horribly wrong, printing thousands of descriptors, - * because false references are followed due to the fact that the - * TD is gone. - */ - if (ohcidebug > 5) { - usb_delay_ms(&sc->sc_bus, 5); - DPRINTF(("ohci_device_intr_transfer: status=%x\n", - OREAD4(sc, OHCI_COMMAND_STATUS))); - ohci_dump_ed(sed); - ohci_dump_tds(data); - } -#endif - crit_exit(); - - return (USBD_IN_PROGRESS); -} - -/* Abort a device control request. */ -static void -ohci_device_intr_abort(usbd_xfer_handle xfer) -{ - if (xfer->pipe->intrxfer == xfer) { - DPRINTF(("ohci_device_intr_abort: remove\n")); - xfer->pipe->intrxfer = NULL; - } - ohci_abort_xfer(xfer, USBD_CANCELLED); -} - -/* Close a device interrupt pipe. */ -static void -ohci_device_intr_close(usbd_pipe_handle pipe) -{ - struct ohci_pipe *opipe = (struct ohci_pipe *)pipe; - ohci_softc_t *sc = (ohci_softc_t *)pipe->device->bus; - int nslots = opipe->u.intr.nslots; - int pos = opipe->u.intr.pos; - int j; - ohci_soft_ed_t *p, *sed = opipe->sed; - - DPRINTFN(1,("ohci_device_intr_close: pipe=%p nslots=%d pos=%d\n", - pipe, nslots, pos)); - crit_enter(); - sed->ed.ed_flags |= htole32(OHCI_ED_SKIP); - if ((le32toh(sed->ed.ed_tailp) & OHCI_HEADMASK) != - (le32toh(sed->ed.ed_headp) & OHCI_HEADMASK)) - usb_delay_ms(&sc->sc_bus, 2); -#ifdef DIAGNOSTIC - if ((le32toh(sed->ed.ed_tailp) & OHCI_HEADMASK) != - (le32toh(sed->ed.ed_headp) & OHCI_HEADMASK)) - panic("%s: Intr pipe %p still has TDs queued", - device_get_nameunit(sc->sc_bus.bdev), pipe); -#endif - - for (p = sc->sc_eds[pos]; p && p->next != sed; p = p->next) - ; -#ifdef DIAGNOSTIC - if (p == NULL) - panic("ohci_device_intr_close: ED not found"); -#endif - p->next = sed->next; - p->ed.ed_nexted = sed->ed.ed_nexted; - crit_exit(); - - for (j = 0; j < nslots; j++) - --sc->sc_bws[(pos * nslots + j) % OHCI_NO_INTRS]; - - ohci_free_std(sc, opipe->tail.td); - opipe->tail.td = NULL; - ohci_free_sed(sc, opipe->sed); - opipe->sed = NULL; -} - -static usbd_status -ohci_device_setintr(ohci_softc_t *sc, struct ohci_pipe *opipe, int ival) -{ - int i, j, best; - u_int npoll, slow, shigh, nslots; - u_int bestbw, bw; - ohci_soft_ed_t *hsed, *sed = opipe->sed; - - DPRINTFN(2, ("ohci_setintr: pipe=%p\n", opipe)); - if (ival == 0) { - kprintf("ohci_setintr: 0 interval\n"); - return (USBD_INVAL); - } - - npoll = OHCI_NO_INTRS; - while (npoll > ival) - npoll /= 2; - DPRINTFN(2, ("ohci_setintr: ival=%d npoll=%d\n", ival, npoll)); - - /* - * We now know which level in the tree the ED must go into. - * Figure out which slot has most bandwidth left over. - * Slots to examine: - * npoll - * 1 0 - * 2 1 2 - * 4 3 4 5 6 - * 8 7 8 9 10 11 12 13 14 - * N (N-1) .. (N-1+N-1) - */ - slow = npoll-1; - shigh = slow + npoll; - nslots = OHCI_NO_INTRS / npoll; - for (best = i = slow, bestbw = ~0; i < shigh; i++) { - bw = 0; - for (j = 0; j < nslots; j++) - bw += sc->sc_bws[(i * nslots + j) % OHCI_NO_INTRS]; - if (bw < bestbw) { - best = i; - bestbw = bw; - } - } - DPRINTFN(2, ("ohci_setintr: best=%d(%d..%d) bestbw=%d\n", - best, slow, shigh, bestbw)); - - crit_enter(); - hsed = sc->sc_eds[best]; - sed->next = hsed->next; - sed->ed.ed_nexted = hsed->ed.ed_nexted; - hsed->next = sed; - hsed->ed.ed_nexted = htole32(sed->physaddr); - crit_exit(); - - for (j = 0; j < nslots; j++) - ++sc->sc_bws[(best * nslots + j) % OHCI_NO_INTRS]; - opipe->u.intr.nslots = nslots; - opipe->u.intr.pos = best; - - DPRINTFN(5, ("ohci_setintr: returns %p\n", opipe)); - return (USBD_NORMAL_COMPLETION); -} - -/***********************/ - -usbd_status -ohci_device_isoc_transfer(usbd_xfer_handle xfer) -{ - usbd_status err; - - DPRINTFN(5,("ohci_device_isoc_transfer: xfer=%p\n", xfer)); - - /* Put it on our queue, */ - err = usb_insert_transfer(xfer); - - /* bail out on error, */ - if (err && err != USBD_IN_PROGRESS) - return (err); - - /* XXX should check inuse here */ - - /* insert into schedule, */ - ohci_device_isoc_enter(xfer); - - /* and start if the pipe wasn't running */ - if (!err) - ohci_device_isoc_start(STAILQ_FIRST(&xfer->pipe->queue)); - - return (err); -} - -void -ohci_device_isoc_enter(usbd_xfer_handle xfer) -{ - struct ohci_pipe *opipe = (struct ohci_pipe *)xfer->pipe; - usbd_device_handle dev = opipe->pipe.device; - ohci_softc_t *sc = (ohci_softc_t *)dev->bus; - ohci_soft_ed_t *sed = opipe->sed; - struct iso *iso = &opipe->u.iso; - struct ohci_xfer *oxfer = (struct ohci_xfer *)xfer; - ohci_soft_itd_t *sitd, *nsitd; - ohci_physaddr_t buf, offs, noffs, bp0, tdphys; - int i, ncur, nframes; - - DPRINTFN(1,("ohci_device_isoc_enter: used=%d next=%d xfer=%p " - "nframes=%d\n", - iso->inuse, iso->next, xfer, xfer->nframes)); - - if (sc->sc_dying) - return; - - if (iso->next == -1) { - /* Not in use yet, schedule it a few frames ahead. */ - iso->next = le32toh(sc->sc_hcca->hcca_frame_number) + 5; - DPRINTFN(2,("ohci_device_isoc_enter: start next=%d\n", - iso->next)); - } - - if (xfer->hcpriv) { - crit_enter(); - for (sitd = xfer->hcpriv; sitd != NULL && sitd->xfer == xfer; - sitd = sitd->nextitd) - ohci_free_sitd(sc, sitd); /* Free ITDs in prev xfer*/ - crit_exit(); - - if (sitd == NULL) { - sitd = ohci_alloc_sitd(sc); - if (sitd == NULL) - panic("can't alloc isoc"); - opipe->tail.itd = sitd; - tdphys = sitd->physaddr; - sed->ed.ed_flags |= htole32(OHCI_ED_SKIP); /* Stop*/ - sed->ed.ed_headp = - sed->ed.ed_tailp = htole32(tdphys); - sed->ed.ed_flags &= htole32(~OHCI_ED_SKIP); /* Start.*/ - } - } - - sitd = opipe->tail.itd; - buf = DMAADDR(&xfer->dmabuf, 0); - bp0 = OHCI_PAGE(buf); - offs = OHCI_PAGE_OFFSET(buf); - nframes = xfer->nframes; - xfer->hcpriv = sitd; - for (i = ncur = 0; i < nframes; i++, ncur++) { - noffs = offs + xfer->frlengths[i]; - if (ncur == OHCI_ITD_NOFFSET || /* all offsets used */ - OHCI_PAGE(buf + noffs) > bp0 + OHCI_PAGE_SIZE) { /* too many page crossings */ - - /* Allocate next ITD */ - nsitd = ohci_alloc_sitd(sc); - if (nsitd == NULL) { - /* XXX what now? */ - device_printf(sc->sc_bus.bdev, - "isoc TD alloc failed\n"); - return; - } - - /* Fill current ITD */ - sitd->itd.itd_flags = htole32( - OHCI_ITD_NOCC | - OHCI_ITD_SET_SF(iso->next) | - OHCI_ITD_SET_DI(6) | /* delay intr a little */ - OHCI_ITD_SET_FC(ncur)); - sitd->itd.itd_bp0 = htole32(bp0); - sitd->nextitd = nsitd; - sitd->itd.itd_nextitd = htole32(nsitd->physaddr); - sitd->itd.itd_be = htole32(bp0 + offs - 1); - sitd->xfer = xfer; - sitd->flags = OHCI_ITD_ACTIVE; - - sitd = nsitd; - iso->next = iso->next + ncur; - bp0 = OHCI_PAGE(buf + offs); - ncur = 0; - } - sitd->itd.itd_offset[ncur] = htole16(OHCI_ITD_MK_OFFS(offs)); - offs = noffs; - } - nsitd = ohci_alloc_sitd(sc); - if (nsitd == NULL) { - /* XXX what now? */ - device_printf(sc->sc_bus.bdev, "isoc TD alloc failed\n"); - return; - } - /* Fixup last used ITD */ - sitd->itd.itd_flags = htole32( - OHCI_ITD_NOCC | - OHCI_ITD_SET_SF(iso->next) | - OHCI_ITD_SET_DI(0) | - OHCI_ITD_SET_FC(ncur)); - sitd->itd.itd_bp0 = htole32(bp0); - sitd->nextitd = nsitd; - sitd->itd.itd_nextitd = htole32(nsitd->physaddr); - sitd->itd.itd_be = htole32(bp0 + offs - 1); - sitd->xfer = xfer; - sitd->flags = OHCI_CALL_DONE | OHCI_ITD_ACTIVE; - - iso->next = iso->next + ncur; - iso->inuse += nframes; - - xfer->actlen = offs; /* XXX pretend we did it all */ - - xfer->status = USBD_IN_PROGRESS; - - oxfer->ohci_xfer_flags |= OHCI_ISOC_DIRTY; - -#ifdef USB_DEBUG - if (ohcidebug > 5) { - DPRINTF(("ohci_device_isoc_enter: frame=%d\n", - le32toh(sc->sc_hcca->hcca_frame_number))); - ohci_dump_itds(xfer->hcpriv); - ohci_dump_ed(sed); - } -#endif - - crit_enter(); - sed->ed.ed_tailp = htole32(nsitd->physaddr); - opipe->tail.itd = nsitd; - sed->ed.ed_flags &= htole32(~OHCI_ED_SKIP); - crit_exit(); - -#ifdef USB_DEBUG - if (ohcidebug > 5) { - delay(150000); - DPRINTF(("ohci_device_isoc_enter: after frame=%d\n", - le32toh(sc->sc_hcca->hcca_frame_number))); - ohci_dump_itds(xfer->hcpriv); - ohci_dump_ed(sed); - } -#endif -} - -usbd_status -ohci_device_isoc_start(usbd_xfer_handle xfer) -{ - struct ohci_pipe *opipe = (struct ohci_pipe *)xfer->pipe; - ohci_softc_t *sc = (ohci_softc_t *)opipe->pipe.device->bus; - ohci_soft_ed_t *sed; - - DPRINTFN(5,("ohci_device_isoc_start: xfer=%p\n", xfer)); - - if (sc->sc_dying) - return (USBD_IOERROR); - -#ifdef DIAGNOSTIC - if (xfer->status != USBD_IN_PROGRESS) - kprintf("ohci_device_isoc_start: not in progress %p\n", xfer); -#endif - - /* XXX anything to do? */ - - crit_enter(); - sed = opipe->sed; /* Turn off ED skip-bit to start processing */ - sed->ed.ed_flags &= htole32(~OHCI_ED_SKIP); /* ED's ITD list.*/ - crit_exit(); - - return (USBD_IN_PROGRESS); -} - -void -ohci_device_isoc_abort(usbd_xfer_handle xfer) -{ - struct ohci_pipe *opipe = (struct ohci_pipe *)xfer->pipe; - ohci_softc_t *sc = (ohci_softc_t *)opipe->pipe.device->bus; - ohci_soft_ed_t *sed; - ohci_soft_itd_t *sitd, *tmp_sitd; - int undone, num_sitds; - - crit_enter(); - opipe->aborting = 1; - - DPRINTFN(1,("ohci_device_isoc_abort: xfer=%p\n", xfer)); - - /* Transfer is already done. */ - if (xfer->status != USBD_NOT_STARTED && - xfer->status != USBD_IN_PROGRESS) { - crit_exit(); - kprintf("ohci_device_isoc_abort: early return\n"); - return; - } - - /* Give xfer the requested abort code. */ - xfer->status = USBD_CANCELLED; - - sed = opipe->sed; - sed->ed.ed_flags |= htole32(OHCI_ED_SKIP); /* force hardware skip */ - - num_sitds = 0; - sitd = xfer->hcpriv; -#ifdef DIAGNOSTIC - if (sitd == NULL) { - crit_exit(); - kprintf("ohci_device_isoc_abort: hcpriv==0\n"); - return; - } -#endif - for (; sitd != NULL && sitd->xfer == xfer; sitd = sitd->nextitd) { - num_sitds++; -#ifdef DIAGNOSTIC - DPRINTFN(1,("abort sets done sitd=%p\n", sitd)); - sitd->isdone = 1; -#endif - } - - crit_exit(); - - /* - * Each sitd has up to OHCI_ITD_NOFFSET transfers, each can - * take a usb 1ms cycle. Conservatively wait for it to drain. - * Even with DMA done, it can take awhile for the "batch" - * delivery of completion interrupts to occur thru the controller. - */ - - do { - usb_delay_ms(&sc->sc_bus, 2*(num_sitds*OHCI_ITD_NOFFSET)); - - undone = 0; - tmp_sitd = xfer->hcpriv; - for (; tmp_sitd != NULL && tmp_sitd->xfer == xfer; - tmp_sitd = tmp_sitd->nextitd) { - if (OHCI_CC_NO_ERROR == - OHCI_ITD_GET_CC(le32toh(tmp_sitd->itd.itd_flags)) && - tmp_sitd->flags & OHCI_ITD_ACTIVE && - (tmp_sitd->flags & OHCI_ITD_INTFIN) == 0) - undone++; - } - } while( undone != 0 ); - - crit_enter(); - - /* Run callback. */ - usb_transfer_complete(xfer); - - if (sitd != NULL) - /* - * Only if there is a `next' sitd in next xfer... - * unlink this xfer's sitds. - */ - sed->ed.ed_headp = htole32(sitd->physaddr); - else - sed->ed.ed_headp = 0; - - sed->ed.ed_flags &= htole32(~OHCI_ED_SKIP); /* remove hardware skip */ - - crit_exit(); -} - -void -ohci_device_isoc_done(usbd_xfer_handle xfer) -{ - /* This null routine corresponds to non-isoc "done()" routines - * that free the stds associated with an xfer after a completed - * xfer interrupt. However, in the case of isoc transfers, the - * sitds associated with the transfer have already been processed - * and reallocated for the next iteration by - * "ohci_device_isoc_transfer()". - * - * Routine "usb_transfer_complete()" is called at the end of every - * relevant usb interrupt. "usb_transfer_complete()" indirectly - * calls 1) "ohci_device_isoc_transfer()" (which keeps pumping the - * pipeline by setting up the next transfer iteration) and 2) then - * calls "ohci_device_isoc_done()". Isoc transfers have not been - * working for the ohci usb because this routine was trashing the - * xfer set up for the next iteration (thus, only the first - * UGEN_NISOREQS xfers outstanding on an open would work). Perhaps - * this could all be re-factored, but that's another pass... - */ -} - -usbd_status -ohci_setup_isoc(usbd_pipe_handle pipe) -{ - struct ohci_pipe *opipe = (struct ohci_pipe *)pipe; - ohci_softc_t *sc = (ohci_softc_t *)pipe->device->bus; - struct iso *iso = &opipe->u.iso; - - iso->next = -1; - iso->inuse = 0; - - crit_enter(); - ohci_add_ed(opipe->sed, sc->sc_isoc_head); - crit_exit(); - - return (USBD_NORMAL_COMPLETION); -} - -void -ohci_device_isoc_close(usbd_pipe_handle pipe) -{ - struct ohci_pipe *opipe = (struct ohci_pipe *)pipe; - ohci_softc_t *sc = (ohci_softc_t *)pipe->device->bus; - ohci_soft_ed_t *sed; - - DPRINTF(("ohci_device_isoc_close: pipe=%p\n", pipe)); - - sed = opipe->sed; - sed->ed.ed_flags |= htole32(OHCI_ED_SKIP); /* Stop device. */ - - ohci_close_pipe(pipe, sc->sc_isoc_head); /* Stop isoc list, free ED.*/ - - /* up to NISOREQs xfers still outstanding. */ - -#ifdef DIAGNOSTIC - opipe->tail.itd->isdone = 1; -#endif - ohci_free_sitd(sc, opipe->tail.itd); /* Next `avail free' sitd.*/ -} diff --git a/sys/bus/usb/ohci_pci.c b/sys/bus/usb/ohci_pci.c deleted file mode 100644 index b99c09d3d1..0000000000 --- a/sys/bus/usb/ohci_pci.c +++ /dev/null @@ -1,399 +0,0 @@ -/* - * Copyright (c) 1998 The NetBSD Foundation, Inc. - * All rights reserved. - * - * This code is derived from software contributed to The NetBSD Foundation - * by Lennart Augustsson (augustss@carlstedt.se) at - * Carlstedt Research & Technology. - * - * 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. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the NetBSD - * Foundation, Inc. and its contributors. - * 4. Neither the name of The NetBSD Foundation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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: src/sys/dev/usb/ohci_pci.c,v 1.44.2.1 2006/01/29 01:26:46 iedowse Exp $ - */ - -/* - * USB Open Host Controller driver. - * - * OHCI spec: http://www.intel.com/design/usb/ohci11d.pdf - */ - -/* The low level controller code for OHCI has been split into - * PCI probes and OHCI specific code. This was done to facilitate the - * sharing of code between *BSD's - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include -#include -#include - -#include -#include - -#define PCI_OHCI_VENDORID_ACERLABS 0x10b9 -#define PCI_OHCI_VENDORID_AMD 0x1022 -#define PCI_OHCI_VENDORID_APPLE 0x106b -#define PCI_OHCI_VENDORID_ATI 0x1002 -#define PCI_OHCI_VENDORID_CMDTECH 0x1095 -#define PCI_OHCI_VENDORID_NEC 0x1033 -#define PCI_OHCI_VENDORID_NVIDIA 0x12D2 -#define PCI_OHCI_VENDORID_NVIDIA2 0x10DE -#define PCI_OHCI_VENDORID_OPTI 0x1045 -#define PCI_OHCI_VENDORID_SIS 0x1039 -#define PCI_OHCI_VENDORID_SUN 0x108e - -#define PCI_OHCI_DEVICEID_ALADDIN_V 0x523710b9 -static const char *ohci_device_aladdin_v = "AcerLabs M5237 (Aladdin-V) USB controller"; - -#define PCI_OHCI_DEVICEID_AMD756 0x740c1022 -static const char *ohci_device_amd756 = "AMD-756 USB Controller"; - -#define PCI_OHCI_DEVICEID_CS5536 0x20941022 -static const char *ohci_device_cs5536 = "AMD CS5536 [geode companion] USB Controller"; - -#define PCI_OHCI_DEVICEID_AMD766 0x74141022 -static const char *ohci_device_amd766 = "AMD-766 USB Controller"; - -#define PCI_OHCI_DEVICEID_SB400_1 0x43741002 -#define PCI_OHCI_DEVICEID_SB400_2 0x43751002 -static const char *ohci_device_sb400 = "ATI SB400 USB Controller"; - -#define PCI_OHCI_DEVICEID_FIRELINK 0xc8611045 -static const char *ohci_device_firelink = "OPTi 82C861 (FireLink) USB controller"; - -#define PCI_OHCI_DEVICEID_NEC 0x00351033 -static const char *ohci_device_nec = "NEC uPD 9210 USB controller"; - -#define PCI_OHCI_DEVICEID_NFORCE3 0x00d710de -static const char *ohci_device_nforce3 = "nVidia nForce3 USB Controller"; - -#define PCI_OHCI_DEVICEID_USB0670 0x06701095 -static const char *ohci_device_usb0670 = "CMD Tech 670 (USB0670) USB controller"; - -#define PCI_OHCI_DEVICEID_USB0673 0x06731095 -static const char *ohci_device_usb0673 = "CMD Tech 673 (USB0673) USB controller"; - -#define PCI_OHCI_DEVICEID_SIS5571 0x70011039 -static const char *ohci_device_sis5571 = "SiS 5571 USB controller"; - -#define PCI_OHCI_DEVICEID_KEYLARGO 0x0019106b -static const char *ohci_device_keylargo = "Apple KeyLargo USB controller"; - -#define PCI_OHCI_DEVICEID_PCIO2USB 0x1103108e -static const char *ohci_device_pcio2usb = "Sun PCIO-2 USB controller"; - -static const char *ohci_device_generic = "OHCI (generic) USB controller"; - -#define PCI_OHCI_BASE_REG 0x10 - - -static int ohci_pci_attach(device_t self); -static int ohci_pci_detach(device_t self); -static int ohci_pci_suspend(device_t self); -static int ohci_pci_resume(device_t self); - -static int -ohci_pci_suspend(device_t self) -{ - ohci_softc_t *sc = device_get_softc(self); - int err; - - err = bus_generic_suspend(self); - if (err) - return err; - ohci_power(PWR_SUSPEND, sc); - - return 0; -} - -static int -ohci_pci_resume(device_t self) -{ - ohci_softc_t *sc = device_get_softc(self); - -#ifndef BURN_BRIDGES - uint32_t reg, int_line; - - if (pci_get_powerstate(self) != PCI_POWERSTATE_D0) { - device_printf(self, "chip is in D%d mode " - "-- setting to D0\n", pci_get_powerstate(self)); - reg = pci_read_config(self, PCI_CBMEM, 4); - int_line = pci_read_config(self, PCIR_INTLINE, 4); - pci_set_powerstate(self, PCI_POWERSTATE_D0); - pci_write_config(self, PCI_CBMEM, reg, 4); - pci_write_config(self, PCIR_INTLINE, int_line, 4); - } -#endif /* !BURN_BRIDGES */ - - ohci_power(PWR_RESUME, sc); - bus_generic_resume(self); - - return 0; -} - -static const char * -ohci_pci_match(device_t self) -{ - u_int32_t device_id = pci_get_devid(self); - - switch (device_id) { - case PCI_OHCI_DEVICEID_ALADDIN_V: - return (ohci_device_aladdin_v); - case PCI_OHCI_DEVICEID_AMD756: - return (ohci_device_amd756); - case PCI_OHCI_DEVICEID_AMD766: - return (ohci_device_amd766); - case PCI_OHCI_DEVICEID_CS5536: - return (ohci_device_cs5536); - case PCI_OHCI_DEVICEID_SB400_1: - case PCI_OHCI_DEVICEID_SB400_2: - return (ohci_device_sb400); - case PCI_OHCI_DEVICEID_USB0670: - return (ohci_device_usb0670); - case PCI_OHCI_DEVICEID_USB0673: - return (ohci_device_usb0673); - case PCI_OHCI_DEVICEID_FIRELINK: - return (ohci_device_firelink); - case PCI_OHCI_DEVICEID_NEC: - return (ohci_device_nec); - case PCI_OHCI_DEVICEID_NFORCE3: - return (ohci_device_nforce3); - case PCI_OHCI_DEVICEID_SIS5571: - return (ohci_device_sis5571); - case PCI_OHCI_DEVICEID_KEYLARGO: - return (ohci_device_keylargo); - case PCI_OHCI_DEVICEID_PCIO2USB: - return (ohci_device_pcio2usb); - default: - if (pci_get_class(self) == PCIC_SERIALBUS - && pci_get_subclass(self) == PCIS_SERIALBUS_USB - && pci_get_progif(self) == PCI_INTERFACE_OHCI) { - return (ohci_device_generic); - } - } - - return NULL; /* dunno */ -} - -static int -ohci_pci_probe(device_t self) -{ - const char *desc = ohci_pci_match(self); - - if (desc) { - device_set_desc(self, desc); - device_set_async_attach(self, TRUE); - return 0; - } else { - return ENXIO; - } -} - -static int -ohci_pci_attach(device_t self) -{ - ohci_softc_t *sc = device_get_softc(self); - int err; - int rid; - - /* XXX where does it say so in the spec? */ - sc->sc_bus.usbrev = USBREV_1_0; - - pci_enable_busmaster(self); - - /* - * Some Sun PCIO-2 USB controllers have their intpin register - * bogusly set to 0, although it should be 4. Correct that. - */ - if (pci_get_devid(self) == PCI_OHCI_DEVICEID_PCIO2USB && - pci_get_intpin(self) == 0) - pci_set_intpin(self, 4); - - rid = PCI_CBMEM; - sc->io_res = bus_alloc_resource_any(self, SYS_RES_MEMORY, &rid, - RF_ACTIVE); - if (!sc->io_res) { - device_printf(self, "Could not map memory\n"); - return ENXIO; - } - sc->iot = rman_get_bustag(sc->io_res); - sc->ioh = rman_get_bushandle(sc->io_res); - - rid = 0; - sc->irq_res = bus_alloc_resource_any(self, SYS_RES_IRQ, &rid, - RF_SHAREABLE | RF_ACTIVE); - if (sc->irq_res == NULL) { - device_printf(self, "Could not allocate irq\n"); - ohci_pci_detach(self); - return ENXIO; - } - sc->sc_bus.bdev = device_add_child(self, "usb", -1); - if (!sc->sc_bus.bdev) { - device_printf(self, "Could not add USB device\n"); - ohci_pci_detach(self); - return ENOMEM; - } - device_set_ivars(sc->sc_bus.bdev, &sc->sc_bus); - - /* ohci_pci_match will never return NULL if ohci_pci_probe succeeded */ - device_set_desc(sc->sc_bus.bdev, ohci_pci_match(self)); - switch (pci_get_vendor(self)) { - case PCI_OHCI_VENDORID_ACERLABS: - ksprintf(sc->sc_vendor, "AcerLabs"); - break; - case PCI_OHCI_VENDORID_AMD: - ksprintf(sc->sc_vendor, "AMD"); - break; - case PCI_OHCI_VENDORID_APPLE: - ksprintf(sc->sc_vendor, "Apple"); - break; - case PCI_OHCI_VENDORID_ATI: - ksprintf(sc->sc_vendor, "ATI"); - break; - case PCI_OHCI_VENDORID_CMDTECH: - ksprintf(sc->sc_vendor, "CMDTECH"); - break; - case PCI_OHCI_VENDORID_NEC: - ksprintf(sc->sc_vendor, "NEC"); - break; - case PCI_OHCI_VENDORID_NVIDIA: - case PCI_OHCI_VENDORID_NVIDIA2: - ksprintf(sc->sc_vendor, "nVidia"); - break; - case PCI_OHCI_VENDORID_OPTI: - ksprintf(sc->sc_vendor, "OPTi"); - break; - case PCI_OHCI_VENDORID_SIS: - ksprintf(sc->sc_vendor, "SiS"); - break; - default: - if (bootverbose) - device_printf(self, "(New OHCI DeviceId=0x%08x)\n", - pci_get_devid(self)); - ksprintf(sc->sc_vendor, "(0x%04x)", pci_get_vendor(self)); - } - - err = bus_setup_intr(self, sc->irq_res, 0, - (driver_intr_t *) ohci_intr, sc, &sc->ih, NULL); - if (err) { - device_printf(self, "Could not setup irq, %d\n", err); - sc->ih = NULL; - ohci_pci_detach(self); - return ENXIO; - } - - /* - * OHCI interrupts which occur early will leave them disabled, - * so run the interrupt manually once we're done with the init. - */ - err = ohci_init(sc); - if (err == 0) - err = device_probe_and_attach(sc->sc_bus.bdev); - - if (err) { - device_printf(self, "USB init failed\n"); - ohci_pci_detach(self); - return EIO; - } - return 0; -} - -static int -ohci_pci_detach(device_t self) -{ - ohci_softc_t *sc = device_get_softc(self); - - if (sc->sc_flags & OHCI_SCFLG_DONEINIT) { - ohci_detach(sc, 0); - sc->sc_flags &= ~OHCI_SCFLG_DONEINIT; - } - - if (sc->irq_res && sc->ih) { - int err = bus_teardown_intr(self, sc->irq_res, sc->ih); - - if (err) - /* XXX or should we panic? */ - device_printf(self, "Could not tear down irq, %d\n", - err); - sc->ih = NULL; - } - if (sc->sc_bus.bdev) { - device_delete_child(self, sc->sc_bus.bdev); - sc->sc_bus.bdev = NULL; - } - if (sc->irq_res) { - bus_release_resource(self, SYS_RES_IRQ, 0, sc->irq_res); - sc->irq_res = NULL; - } - if (sc->io_res) { - bus_release_resource(self, SYS_RES_MEMORY, PCI_CBMEM, sc->io_res); - sc->io_res = NULL; - sc->iot = 0; - sc->ioh = 0; - } - return 0; -} - -static device_method_t ohci_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, ohci_pci_probe), - DEVMETHOD(device_attach, ohci_pci_attach), - DEVMETHOD(device_detach, ohci_pci_detach), - DEVMETHOD(device_suspend, ohci_pci_suspend), - DEVMETHOD(device_resume, ohci_pci_resume), - DEVMETHOD(device_shutdown, bus_generic_shutdown), - - /* Bus interface */ - DEVMETHOD(bus_print_child, bus_generic_print_child), - - DEVMETHOD_END -}; - -static driver_t ohci_driver = { - "ohci", - ohci_methods, - sizeof(ohci_softc_t), -}; - -static devclass_t ohci_devclass; - -DRIVER_MODULE(ohci, pci, ohci_driver, ohci_devclass, NULL, NULL); -DRIVER_MODULE(ohci, cardbus, ohci_driver, ohci_devclass, NULL, NULL); diff --git a/sys/bus/usb/ohcireg.h b/sys/bus/usb/ohcireg.h deleted file mode 100644 index c51c1eb009..0000000000 --- a/sys/bus/usb/ohcireg.h +++ /dev/null @@ -1,250 +0,0 @@ -/* $NetBSD: ohcireg.h,v 1.17 2000/04/01 09:27:35 augustss Exp $ */ -/* $FreeBSD: src/sys/dev/usb/ohcireg.h,v 1.22 2005/01/06 01:43:28 imp Exp $ */ -/* $DragonFly: src/sys/bus/usb/ohcireg.h,v 1.4 2006/12/10 02:03:56 sephe Exp $ */ - - -/* - * Copyright (c) 1998 The NetBSD Foundation, Inc. - * All rights reserved. - * - * This code is derived from software contributed to The NetBSD Foundation - * by Lennart Augustsson (lennart@augustsson.net) at - * Carlstedt Research & Technology. - * - * 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. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the NetBSD - * Foundation, Inc. and its contributors. - * 4. Neither the name of The NetBSD Foundation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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. - */ - -#ifndef _DEV_PCI_OHCIREG_H_ -#define _DEV_PCI_OHCIREG_H_ - -/*** PCI config registers ***/ - -#define PCI_CBMEM 0x10 /* configuration base memory */ - -#define PCI_INTERFACE_OHCI 0x10 - -/*** OHCI registers */ - -#define OHCI_REVISION 0x00 /* OHCI revision # */ -#define OHCI_REV_LO(rev) ((rev)&0xf) -#define OHCI_REV_HI(rev) (((rev)>>4)&0xf) -#define OHCI_REV_LEGACY(rev) ((rev) & 0x100) - -#define OHCI_CONTROL 0x04 -#define OHCI_CBSR_MASK 0x00000003 /* Control/Bulk Service Ratio */ -#define OHCI_RATIO_1_1 0x00000000 -#define OHCI_RATIO_1_2 0x00000001 -#define OHCI_RATIO_1_3 0x00000002 -#define OHCI_RATIO_1_4 0x00000003 -#define OHCI_PLE 0x00000004 /* Periodic List Enable */ -#define OHCI_IE 0x00000008 /* Isochronous Enable */ -#define OHCI_CLE 0x00000010 /* Control List Enable */ -#define OHCI_BLE 0x00000020 /* Bulk List Enable */ -#define OHCI_HCFS_MASK 0x000000c0 /* HostControllerFunctionalState */ -#define OHCI_HCFS_RESET 0x00000000 -#define OHCI_HCFS_RESUME 0x00000040 -#define OHCI_HCFS_OPERATIONAL 0x00000080 -#define OHCI_HCFS_SUSPEND 0x000000c0 -#define OHCI_IR 0x00000100 /* Interrupt Routing */ -#define OHCI_RWC 0x00000200 /* Remote Wakeup Connected */ -#define OHCI_RWE 0x00000400 /* Remote Wakeup Enabled */ -#define OHCI_COMMAND_STATUS 0x08 -#define OHCI_HCR 0x00000001 /* Host Controller Reset */ -#define OHCI_CLF 0x00000002 /* Control List Filled */ -#define OHCI_BLF 0x00000004 /* Bulk List Filled */ -#define OHCI_OCR 0x00000008 /* Ownership Change Request */ -#define OHCI_SOC_MASK 0x00030000 /* Scheduling Overrun Count */ -#define OHCI_INTERRUPT_STATUS 0x0c -#define OHCI_SO 0x00000001 /* Scheduling Overrun */ -#define OHCI_WDH 0x00000002 /* Writeback Done Head */ -#define OHCI_SF 0x00000004 /* Start of Frame */ -#define OHCI_RD 0x00000008 /* Resume Detected */ -#define OHCI_UE 0x00000010 /* Unrecoverable Error */ -#define OHCI_FNO 0x00000020 /* Frame Number Overflow */ -#define OHCI_RHSC 0x00000040 /* Root Hub Status Change */ -#define OHCI_OC 0x40000000 /* Ownership Change */ -#define OHCI_MIE 0x80000000 /* Master Interrupt Enable */ -#define OHCI_INTERRUPT_ENABLE 0x10 -#define OHCI_INTERRUPT_DISABLE 0x14 -#define OHCI_HCCA 0x18 -#define OHCI_PERIOD_CURRENT_ED 0x1c -#define OHCI_CONTROL_HEAD_ED 0x20 -#define OHCI_CONTROL_CURRENT_ED 0x24 -#define OHCI_BULK_HEAD_ED 0x28 -#define OHCI_BULK_CURRENT_ED 0x2c -#define OHCI_DONE_HEAD 0x30 -#define OHCI_FM_INTERVAL 0x34 -#define OHCI_GET_IVAL(s) ((s) & 0x3fff) -#define OHCI_GET_FSMPS(s) (((s) >> 16) & 0x7fff) -#define OHCI_FIT 0x80000000 -#define OHCI_FM_REMAINING 0x38 -#define OHCI_FM_NUMBER 0x3c -#define OHCI_PERIODIC_START 0x40 -#define OHCI_LS_THRESHOLD 0x44 -#define OHCI_RH_DESCRIPTOR_A 0x48 -#define OHCI_GET_NDP(s) ((s) & 0xff) -#define OHCI_PSM 0x0100 /* Power Switching Mode */ -#define OHCI_NPS 0x0200 /* No Power Switching */ -#define OHCI_DT 0x0400 /* Device Type */ -#define OHCI_OCPM 0x0800 /* Overcurrent Protection Mode */ -#define OHCI_NOCP 0x1000 /* No Overcurrent Protection */ -#define OHCI_GET_POTPGT(s) ((s) >> 24) -#define OHCI_RH_DESCRIPTOR_B 0x4c -#define OHCI_RH_STATUS 0x50 -#define OHCI_LPS 0x00000001 /* Local Power Status */ -#define OHCI_OCI 0x00000002 /* OverCurrent Indicator */ -#define OHCI_DRWE 0x00008000 /* Device Remote Wakeup Enable */ -#define OHCI_LPSC 0x00010000 /* Local Power Status Change */ -#define OHCI_CCIC 0x00020000 /* OverCurrent Indicator Change */ -#define OHCI_CRWE 0x80000000 /* Clear Remote Wakeup Enable */ -#define OHCI_RH_PORT_STATUS(n) (0x50 + (n)*4) /* 1 based indexing */ - -#define OHCI_LES (OHCI_PLE | OHCI_IE | OHCI_CLE | OHCI_BLE) -#define OHCI_ALL_INTRS (OHCI_SO | OHCI_WDH | OHCI_SF | OHCI_RD | OHCI_UE | \ - OHCI_FNO | OHCI_RHSC | OHCI_OC) -#define OHCI_NORMAL_INTRS (OHCI_WDH | OHCI_RD | OHCI_UE | OHCI_RHSC) - -#define OHCI_FSMPS(i) (((i-210)*6/7) << 16) -#define OHCI_PERIODIC(i) ((i)*9/10) - -typedef u_int32_t ohci_physaddr_t; - -#define OHCI_NO_INTRS 32 -struct ohci_hcca { - ohci_physaddr_t hcca_interrupt_table[OHCI_NO_INTRS]; - u_int32_t hcca_frame_number; - ohci_physaddr_t hcca_done_head; -#define OHCI_DONE_INTRS 1 -}; -#define OHCI_HCCA_SIZE 256 -#define OHCI_HCCA_ALIGN 256 - -#define OHCI_PAGE_SIZE 0x1000 -#define OHCI_PAGE(x) ((x) &~ 0xfff) -#define OHCI_PAGE_OFFSET(x) ((x) & 0xfff) -#define OHCI_PAGE_MASK(x) ((x) & 0xfff) - -typedef struct { - u_int32_t ed_flags; -#define OHCI_ED_GET_FA(s) ((s) & 0x7f) -#define OHCI_ED_ADDRMASK 0x0000007f -#define OHCI_ED_SET_FA(s) (s) -#define OHCI_ED_GET_EN(s) (((s) >> 7) & 0xf) -#define OHCI_ED_SET_EN(s) ((s) << 7) -#define OHCI_ED_DIR_MASK 0x00001800 -#define OHCI_ED_DIR_TD 0x00000000 -#define OHCI_ED_DIR_OUT 0x00000800 -#define OHCI_ED_DIR_IN 0x00001000 -#define OHCI_ED_SPEED 0x00002000 -#define OHCI_ED_SKIP 0x00004000 -#define OHCI_ED_FORMAT_GEN 0x00000000 -#define OHCI_ED_FORMAT_ISO 0x00008000 -#define OHCI_ED_GET_MAXP(s) (((s) >> 16) & 0x07ff) -#define OHCI_ED_SET_MAXP(s) ((s) << 16) -#define OHCI_ED_MAXPMASK (0x7ff << 16) - ohci_physaddr_t ed_tailp; - ohci_physaddr_t ed_headp; -#define OHCI_HALTED 0x00000001 -#define OHCI_TOGGLECARRY 0x00000002 -#define OHCI_HEADMASK 0xfffffffc - ohci_physaddr_t ed_nexted; -} ohci_ed_t; -/* #define OHCI_ED_SIZE 16 */ -#define OHCI_ED_ALIGN 16 - -typedef struct { - u_int32_t td_flags; -#define OHCI_TD_R 0x00040000 /* Buffer Rounding */ -#define OHCI_TD_DP_MASK 0x00180000 /* Direction / PID */ -#define OHCI_TD_SETUP 0x00000000 -#define OHCI_TD_OUT 0x00080000 -#define OHCI_TD_IN 0x00100000 -#define OHCI_TD_GET_DI(x) (((x) >> 21) & 7) /* Delay Interrupt */ -#define OHCI_TD_SET_DI(x) ((x) << 21) -#define OHCI_TD_NOINTR 0x00e00000 -#define OHCI_TD_INTR_MASK 0x00e00000 -#define OHCI_TD_TOGGLE_CARRY 0x00000000 -#define OHCI_TD_TOGGLE_0 0x02000000 -#define OHCI_TD_TOGGLE_1 0x03000000 -#define OHCI_TD_TOGGLE_MASK 0x03000000 -#define OHCI_TD_GET_EC(x) (((x) >> 26) & 3) /* Error Count */ -#define OHCI_TD_GET_CC(x) ((x) >> 28) /* Condition Code */ -#define OHCI_TD_NOCC 0xf0000000 - ohci_physaddr_t td_cbp; /* Current Buffer Pointer */ - ohci_physaddr_t td_nexttd; /* Next TD */ - ohci_physaddr_t td_be; /* Buffer End */ -} ohci_td_t; -/* #define OHCI_TD_SIZE 16 */ -#define OHCI_TD_ALIGN 16 - -#define OHCI_ITD_NOFFSET 8 -typedef struct { - u_int32_t itd_flags; -#define OHCI_ITD_GET_SF(x) ((x) & 0x0000ffff) -#define OHCI_ITD_SET_SF(x) ((x) & 0xffff) -#define OHCI_ITD_GET_DI(x) (((x) >> 21) & 7) /* Delay Interrupt */ -#define OHCI_ITD_SET_DI(x) ((x) << 21) -#define OHCI_ITD_NOINTR 0x00e00000 -#define OHCI_ITD_GET_FC(x) ((((x) >> 24) & 7)+1) /* Frame Count */ -#define OHCI_ITD_SET_FC(x) (((x)-1) << 24) -#define OHCI_ITD_GET_CC(x) ((x) >> 28) /* Condition Code */ -#define OHCI_ITD_NOCC 0xf0000000 - ohci_physaddr_t itd_bp0; /* Buffer Page 0 */ - ohci_physaddr_t itd_nextitd; /* Next ITD */ - ohci_physaddr_t itd_be; /* Buffer End */ - u_int16_t itd_offset[OHCI_ITD_NOFFSET]; /* Buffer offsets */ -#define itd_pswn itd_offset /* Packet Status Word*/ -#define OHCI_ITD_PAGE_SELECT 0x00001000 -#define OHCI_ITD_MK_OFFS(len) (0xe000 | ((len) & 0x1fff)) -#define OHCI_ITD_PSW_LENGTH(x) ((x) & 0xfff) /* Transfer length */ -#define OHCI_ITD_PSW_GET_CC(x) ((x) >> 12) /* Condition Code */ -} ohci_itd_t; -/* #define OHCI_ITD_SIZE 32 */ -#define OHCI_ITD_ALIGN 32 - - -#define OHCI_CC_NO_ERROR 0 -#define OHCI_CC_CRC 1 -#define OHCI_CC_BIT_STUFFING 2 -#define OHCI_CC_DATA_TOGGLE_MISMATCH 3 -#define OHCI_CC_STALL 4 -#define OHCI_CC_DEVICE_NOT_RESPONDING 5 -#define OHCI_CC_PID_CHECK_FAILURE 6 -#define OHCI_CC_UNEXPECTED_PID 7 -#define OHCI_CC_DATA_OVERRUN 8 -#define OHCI_CC_DATA_UNDERRUN 9 -#define OHCI_CC_BUFFER_OVERRUN 12 -#define OHCI_CC_BUFFER_UNDERRUN 13 -#define OHCI_CC_NOT_ACCESSED 15 - -/* Some delay needed when changing certain registers. */ -#define OHCI_ENABLE_POWER_DELAY 5 -#define OHCI_READ_DESC_DELAY 5 - -#endif /* _DEV_PCI_OHCIREG_H_ */ diff --git a/sys/bus/usb/ohcivar.h b/sys/bus/usb/ohcivar.h deleted file mode 100644 index a5e8ee70b6..0000000000 --- a/sys/bus/usb/ohcivar.h +++ /dev/null @@ -1,166 +0,0 @@ -/* $NetBSD: ohcivar.h,v 1.30 2001/12/31 12:20:35 augustss Exp $ */ -/* $FreeBSD: src/sys/dev/usb/ohcivar.h,v 1.40.2.1 2005/12/04 05:52:23 iedowse Exp $ */ -/* $DragonFly: src/sys/bus/usb/ohcivar.h,v 1.9 2007/06/30 20:39:22 hasso Exp $ */ - -/* - * Copyright (c) 1998 The NetBSD Foundation, Inc. - * All rights reserved. - * - * This code is derived from software contributed to The NetBSD Foundation - * by Lennart Augustsson (lennart@augustsson.net) at - * Carlstedt Research & Technology. - * - * 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. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the NetBSD - * Foundation, Inc. and its contributors. - * 4. Neither the name of The NetBSD Foundation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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. - */ - -typedef struct ohci_soft_ed { - ohci_ed_t ed; - struct ohci_soft_ed *next; - ohci_physaddr_t physaddr; -} ohci_soft_ed_t; -#define OHCI_SED_SIZE ((sizeof (struct ohci_soft_ed) + OHCI_ED_ALIGN - 1) / OHCI_ED_ALIGN * OHCI_ED_ALIGN) -#define OHCI_SED_CHUNK (PAGE_SIZE / OHCI_SED_SIZE) - -typedef struct ohci_soft_td { - ohci_td_t td; - struct ohci_soft_td *nexttd; /* mirrors nexttd in TD */ - struct ohci_soft_td *dnext; /* next in done list */ - ohci_physaddr_t physaddr; - LIST_ENTRY(ohci_soft_td) hnext; - usbd_xfer_handle xfer; - u_int16_t len; - u_int16_t flags; -#define OHCI_CALL_DONE 0x0001 -#define OHCI_ADD_LEN 0x0002 -} ohci_soft_td_t; -#define OHCI_STD_SIZE ((sizeof (struct ohci_soft_td) + OHCI_TD_ALIGN - 1) / OHCI_TD_ALIGN * OHCI_TD_ALIGN) -#define OHCI_STD_CHUNK (PAGE_SIZE / OHCI_STD_SIZE) - -typedef struct ohci_soft_itd { - ohci_itd_t itd; - struct ohci_soft_itd *nextitd; /* mirrors nexttd in ITD */ - struct ohci_soft_itd *dnext; /* next in done list */ - ohci_physaddr_t physaddr; - LIST_ENTRY(ohci_soft_itd) hnext; - usbd_xfer_handle xfer; - u_int16_t flags; -#define OHCI_ITD_ACTIVE 0x0010 /* Hardware op in progress */ -#define OHCI_ITD_INTFIN 0x0020 /* Hw completion interrupt seen.*/ -#ifdef DIAGNOSTIC - char isdone; -#endif -} ohci_soft_itd_t; -#define OHCI_SITD_SIZE ((sizeof (struct ohci_soft_itd) + OHCI_ITD_ALIGN - 1) / OHCI_ITD_ALIGN * OHCI_ITD_ALIGN) -#define OHCI_SITD_CHUNK (PAGE_SIZE / OHCI_SITD_SIZE) - -#define OHCI_NO_EDS (2*OHCI_NO_INTRS-1) - -#define OHCI_HASH_SIZE 128 - -#define OHCI_SCFLG_DONEINIT 0x0001 /* ohci_init() done. */ - -typedef struct ohci_softc { - struct usbd_bus sc_bus; /* base device */ - int sc_flags; - bus_space_tag_t iot; - bus_space_handle_t ioh; - bus_size_t sc_size; - - void *ih; - - struct resource *io_res; - struct resource *irq_res; - - usb_dma_t sc_hccadma; - struct ohci_hcca *sc_hcca; - ohci_soft_ed_t *sc_eds[OHCI_NO_EDS]; - u_int sc_bws[OHCI_NO_INTRS]; - - u_int32_t sc_eintrs; /* enabled interrupts */ - u_int32_t sc_dintrs; /* delayed interrupts */ - - ohci_soft_ed_t *sc_isoc_head; - ohci_soft_ed_t *sc_ctrl_head; - ohci_soft_ed_t *sc_bulk_head; - - LIST_HEAD(, ohci_soft_td) sc_hash_tds[OHCI_HASH_SIZE]; - LIST_HEAD(, ohci_soft_itd) sc_hash_itds[OHCI_HASH_SIZE]; - - int sc_noport; - u_int8_t sc_addr; /* device address */ - u_int8_t sc_conf; /* device configuration */ - -#ifdef USB_USE_SOFTINTR - char sc_softwake; -#endif /* USB_USE_SOFTINTR */ - - ohci_soft_ed_t *sc_freeeds; - ohci_soft_td_t *sc_freetds; - ohci_soft_itd_t *sc_freeitds; - - STAILQ_HEAD(, usbd_xfer) sc_free_xfers; /* free xfers */ - - usbd_xfer_handle sc_intrxfer; - - ohci_soft_itd_t *sc_sidone; - ohci_soft_td_t *sc_sdone; - - char sc_vendor[16]; - int sc_id_vendor; - - u_int32_t sc_control; /* Preserved during suspend/standby */ - u_int32_t sc_intre; - - u_int sc_overrun_cnt; - struct timeval sc_overrun_ntc; - - struct callout sc_tmo_rhsc; - - char sc_dying; -} ohci_softc_t; - -struct ohci_xfer { - struct usbd_xfer xfer; - struct usb_task abort_task; - u_int32_t ohci_xfer_flags; -}; -#define OHCI_ISOC_DIRTY 0x01 -#define OHCI_XFER_ABORTING 0x02 /* xfer is aborting. */ -#define OHCI_XFER_ABORTWAIT 0x04 /* abort completion is being awaited. */ - -#define OXFER(xfer) ((struct ohci_xfer *)(xfer)) - -usbd_status ohci_init(ohci_softc_t *); -int ohci_intr(void *); -int ohci_detach(ohci_softc_t *, int); - -#define MS_TO_TICKS(ms) ((ms) * hz / 1000) - -void ohci_shutdown(void *v); -void ohci_power(int state, void *priv); diff --git a/sys/bus/usb/rio500_usb.h b/sys/bus/usb/rio500_usb.h deleted file mode 100644 index 2ba791874d..0000000000 --- a/sys/bus/usb/rio500_usb.h +++ /dev/null @@ -1,44 +0,0 @@ -/* ---------------------------------------------------------------------- - - Copyright (C) 2000 Cesar Miquel (miquel@df.uba.ar) - - Redistribution and use in source and binary forms, with or without - modification, are permitted under any licence of your choise which - meets the open source licence definiton - http://www.opensource.org/opd.html such as the GNU licence or the - BSD licence. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License or the BSD license for more details. - - ---------------------------------------------------------------------- - - Modified for FreeBSD by Iwasa Kazmi - - ---------------------------------------------------------------------- */ - -/* - * $FreeBSD: src/sys/dev/usb/rio500_usb.h,v 1.1 2000/04/08 17:02:13 n_hibma Exp $ - * $DragonFly: src/sys/bus/usb/rio500_usb.h,v 1.6 2007/11/05 13:32:27 hasso Exp $ - */ - -#include - -struct RioCommand -{ - u_int16_t length; - int request; - int requesttype; - int value; - int index; - void *buffer; - int timeout; -}; - -#define RIO_SEND_COMMAND _IOWR('U', 200, struct RioCommand) -#define RIO_RECV_COMMAND _IOWR('U', 201, struct RioCommand) - -#define RIO_DIR_OUT 0x0 -#define RIO_DIR_IN 0x1 diff --git a/sys/bus/usb/ugraphire_rdesc.h b/sys/bus/usb/ugraphire_rdesc.h deleted file mode 100644 index c8001c6ef0..0000000000 --- a/sys/bus/usb/ugraphire_rdesc.h +++ /dev/null @@ -1,95 +0,0 @@ -/* - * $NetBSD: usb/ugraphire_rdesc.h,v 1.1 2000/12/29 01:47:49 augustss Exp $ - * $FreeBSD: src/sys/dev/usb/ugraphire_rdesc.h,v 1.1 2002/04/07 17:04:01 joe Exp $ - * $DragonFly: src/sys/bus/usb/ugraphire_rdesc.h,v 1.1 2003/12/30 01:01:44 dillon Exp $ - */ -/* - * Copyright (c) 2000 Nick Hibma - * 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. - */ - -static uByte uhid_graphire_report_descr[] = { - 0x05, 0x0d, /* USAGE_PAGE (Digitizers) */ - 0x09, 0x01, /* USAGE (Digitizer) */ - 0xa1, 0x01, /* COLLECTION (Application) */ - 0x85, 0x02, /* REPORT_ID (2) */ - 0x05, 0x0d, /* USAGE_PAGE (Digitizers) */ - 0x09, 0x01, /* USAGE (Digitizer) */ - 0xa1, 0x00, /* COLLECTION (Physical) */ - 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ - 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ - 0x09, 0x33, /* USAGE (Touch) */ - 0x95, 0x01, /* REPORT_COUNT (1) */ - 0x75, 0x01, /* REPORT_SIZE (1) */ - 0x81, 0x02, /* INPUT (Data,Var,Abs) */ - 0x09, 0x44, /* USAGE (Barrel Switch) */ - 0x95, 0x02, /* REPORT_COUNT (2) */ - 0x75, 0x01, /* REPORT_SIZE (1) */ - 0x81, 0x02, /* INPUT (Data,Var,Abs) */ - 0x09, 0x00, /* USAGE (Undefined) */ - 0x95, 0x02, /* REPORT_COUNT (2) */ - 0x75, 0x01, /* REPORT_SIZE (1) */ - 0x81, 0x03, /* INPUT (Cnst,Var,Abs) */ - 0x09, 0x3c, /* USAGE (Invert) */ - 0x95, 0x01, /* REPORT_COUNT (1) */ - 0x75, 0x01, /* REPORT_SIZE (1) */ - 0x81, 0x02, /* INPUT (Data,Var,Abs) */ - 0x09, 0x38, /* USAGE (Transducer Index) */ - 0x95, 0x01, /* REPORT_COUNT (1) */ - 0x75, 0x01, /* REPORT_SIZE (1) */ - 0x81, 0x02, /* INPUT (Data,Var,Abs) */ - 0x09, 0x32, /* USAGE (In Range) */ - 0x95, 0x01, /* REPORT_COUNT (1) */ - 0x75, 0x01, /* REPORT_SIZE (1) */ - 0x81, 0x02, /* INPUT (Data,Var,Abs) */ - 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */ - 0x09, 0x30, /* USAGE (X) */ - 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ - 0x26, 0xde, 0x27, /* LOGICAL_MAXIMUM (10206) */ - 0x95, 0x01, /* REPORT_COUNT (1) */ - 0x75, 0x10, /* REPORT_SIZE (16) */ - 0x81, 0x02, /* INPUT (Data,Var,Abs) */ - 0x09, 0x31, /* USAGE (Y) */ - 0x26, 0xfe, 0x1c, /* LOGICAL_MAXIMUM (7422) */ - 0x95, 0x01, /* REPORT_COUNT (1) */ - 0x75, 0x10, /* REPORT_SIZE (16) */ - 0x81, 0x02, /* INPUT (Data,Var,Abs) */ - 0x05, 0x0d, /* USAGE_PAGE (Digitizers) */ - 0x09, 0x30, /* USAGE (Tip Pressure) */ - 0x26, 0xff, 0x01, /* LOGICAL_MAXIMUM (511) */ - 0x95, 0x01, /* REPORT_COUNT (1) */ - 0x75, 0x10, /* REPORT_SIZE (16) */ - 0x81, 0x02, /* INPUT (Data,Var,Abs) */ - 0xc0, /* END_COLLECTION */ - 0x05, 0x0d, /* USAGE_PAGE (Digitizers) */ - 0x09, 0x00, /* USAGE (Undefined) */ - 0x85, 0x02, /* REPORT_ID (2) */ - 0x95, 0x01, /* REPORT_COUNT (1) */ - 0xb1, 0x02, /* FEATURE (Data,Var,Abs) */ - 0x09, 0x00, /* USAGE (Undefined) */ - 0x85, 0x03, /* REPORT_ID (3) */ - 0x95, 0x01, /* REPORT_COUNT (1) */ - 0xb1, 0x02, /* FEATURE (Data,Var,Abs) */ - 0xc0, /* END_COLLECTION */ -}; diff --git a/sys/bus/usb/uhci.c b/sys/bus/usb/uhci.c deleted file mode 100644 index 105b47d252..0000000000 --- a/sys/bus/usb/uhci.c +++ /dev/null @@ -1,3497 +0,0 @@ -/* $NetBSD: uhci.c,v 1.170 2003/02/19 01:35:04 augustss Exp $ */ -/* $FreeBSD: src/sys/dev/usb/uhci.c,v 1.162.2.1 2006/03/01 01:59:04 iedowse Exp $ */ - -/* Also already incorporated from NetBSD: - * $NetBSD: uhci.c,v 1.172 2003/02/23 04:19:26 simonb Exp $ - * $NetBSD: uhci.c,v 1.173 2003/05/13 04:41:59 gson Exp $ - * $NetBSD: uhci.c,v 1.175 2003/09/12 16:18:08 mycroft Exp $ - * $NetBSD: uhci.c,v 1.176 2003/11/04 19:11:21 mycroft Exp $ - * $NetBSD: uhci.c,v 1.177 2003/12/29 08:17:10 toshii Exp $ - * $NetBSD: uhci.c,v 1.178 2004/03/02 16:32:05 martin Exp $ - * $NetBSD: uhci.c,v 1.180 2004/07/17 20:12:03 mycroft Exp $ - */ - -/* - * Copyright (c) 1998 The NetBSD Foundation, Inc. - * All rights reserved. - * - * This code is derived from software contributed to The NetBSD Foundation - * by Lennart Augustsson (lennart@augustsson.net) at - * Carlstedt Research & Technology. - * - * 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. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the NetBSD - * Foundation, Inc. and its contributors. - * 4. Neither the name of The NetBSD Foundation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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. - */ - -/* - * USB Universal Host Controller driver. - * Handles e.g. PIIX3 and PIIX4. - * - * UHCI spec: http://developer.intel.com/design/USB/UHCI11D.htm - * USB spec: http://www.usb.org/developers/docs/usbspec.zip - * PIIXn spec: ftp://download.intel.com/design/intarch/datashts/29055002.pdf - * ftp://download.intel.com/design/intarch/datashts/29056201.pdf - */ - -#include -#include -#include -#include -#include -#include -#include -#if defined(DIAGNOSTIC) && defined(__i386__) -#include -#endif -#include -#include -#include -#include - -#include - -#include -#include -#include -#include -#include - -#include -#include - -/* Use bandwidth reclamation for control transfers. Some devices choke on it. */ -/*#define UHCI_CTL_LOOP */ - -#define delay(d) DELAY(d) - -#define MS_TO_TICKS(ms) ((ms) * hz / 1000) - -#ifdef USB_DEBUG -uhci_softc_t *thesc; -#define DPRINTF(x) if (uhcidebug) kprintf x -#define DPRINTFN(n,x) if (uhcidebug>(n)) kprintf x -int uhcidebug = 0; -int uhcinoloop = 0; -SYSCTL_NODE(_hw_usb, OID_AUTO, uhci, CTLFLAG_RW, 0, "USB uhci"); -SYSCTL_INT(_hw_usb_uhci, OID_AUTO, debug, CTLFLAG_RW, - &uhcidebug, 0, "uhci debug level"); -SYSCTL_INT(_hw_usb_uhci, OID_AUTO, loop, CTLFLAG_RW, - &uhcinoloop, 0, "uhci noloop"); -#define bitmask_snprintf(q,f,b,l) ksnprintf((b), (l), "%b", (q), (f)) -#else -#define DPRINTF(x) -#define DPRINTFN(n,x) -#endif - -struct uhci_pipe { - struct usbd_pipe pipe; - int nexttoggle; - - u_char aborting; - usbd_xfer_handle abortstart, abortend; - - /* Info needed for different pipe kinds. */ - union { - /* Control pipe */ - struct { - uhci_soft_qh_t *sqh; - usb_dma_t reqdma; - uhci_soft_td_t *setup, *stat; - u_int length; - } ctl; - /* Interrupt pipe */ - struct { - int npoll; - int isread; - uhci_soft_qh_t **qhs; - } intr; - /* Bulk pipe */ - struct { - uhci_soft_qh_t *sqh; - u_int length; - int isread; - } bulk; - /* Iso pipe */ - struct iso { - uhci_soft_td_t **stds; - int next, inuse; - } iso; - } u; -}; - -static void uhci_globalreset(uhci_softc_t *); -static usbd_status uhci_portreset(uhci_softc_t*, int); -static void uhci_reset(uhci_softc_t *); -static usbd_status uhci_run(uhci_softc_t *, int run); -static uhci_soft_td_t *uhci_alloc_std(uhci_softc_t *); -static void uhci_free_std(uhci_softc_t *, uhci_soft_td_t *); -static uhci_soft_qh_t *uhci_alloc_sqh(uhci_softc_t *); -static void uhci_free_sqh(uhci_softc_t *, uhci_soft_qh_t *); -#if 0 -static void uhci_enter_ctl_q(uhci_softc_t *, uhci_soft_qh_t *, - uhci_intr_info_t *); -static void uhci_exit_ctl_q(uhci_softc_t *, uhci_soft_qh_t *); -#endif - -static void uhci_free_std_chain(uhci_softc_t *, - uhci_soft_td_t *, uhci_soft_td_t *); -static usbd_status uhci_alloc_std_chain(struct uhci_pipe *, - uhci_softc_t *, int, int, u_int16_t, usb_dma_t *, - uhci_soft_td_t **, uhci_soft_td_t **); -static void uhci_poll_hub(void *); -static void uhci_waitintr(uhci_softc_t *, usbd_xfer_handle); -static void uhci_check_intr(uhci_softc_t *, uhci_intr_info_t *); -static void uhci_idone(uhci_intr_info_t *); - -static void uhci_abort_xfer(usbd_xfer_handle, usbd_status status); - -static void uhci_timeout(void *); -static void uhci_timeout_task(void *); -static void uhci_add_ls_ctrl(uhci_softc_t *, uhci_soft_qh_t *); -static void uhci_add_hs_ctrl(uhci_softc_t *, uhci_soft_qh_t *); -static void uhci_add_bulk(uhci_softc_t *, uhci_soft_qh_t *); -static void uhci_remove_ls_ctrl(uhci_softc_t *,uhci_soft_qh_t *); -static void uhci_remove_hs_ctrl(uhci_softc_t *,uhci_soft_qh_t *); -static void uhci_remove_bulk(uhci_softc_t *,uhci_soft_qh_t *); -static int uhci_str(usb_string_descriptor_t *, int, char *); -static void uhci_add_loop(uhci_softc_t *sc); -static void uhci_rem_loop(uhci_softc_t *sc); - -static usbd_status uhci_setup_isoc(usbd_pipe_handle pipe); -static void uhci_device_isoc_enter(usbd_xfer_handle); - -static usbd_status uhci_allocm(struct usbd_bus *, usb_dma_t *, u_int32_t); -static void uhci_freem(struct usbd_bus *, usb_dma_t *); - -static usbd_xfer_handle uhci_allocx(struct usbd_bus *); -static void uhci_freex(struct usbd_bus *, usbd_xfer_handle); - -static usbd_status uhci_device_ctrl_transfer(usbd_xfer_handle); -static usbd_status uhci_device_ctrl_start(usbd_xfer_handle); -static void uhci_device_ctrl_abort(usbd_xfer_handle); -static void uhci_device_ctrl_close(usbd_pipe_handle); -static void uhci_device_ctrl_done(usbd_xfer_handle); - -static usbd_status uhci_device_intr_transfer(usbd_xfer_handle); -static usbd_status uhci_device_intr_start(usbd_xfer_handle); -static void uhci_device_intr_abort(usbd_xfer_handle); -static void uhci_device_intr_close(usbd_pipe_handle); -static void uhci_device_intr_done(usbd_xfer_handle); - -static usbd_status uhci_device_bulk_transfer(usbd_xfer_handle); -static usbd_status uhci_device_bulk_start(usbd_xfer_handle); -static void uhci_device_bulk_abort(usbd_xfer_handle); -static void uhci_device_bulk_close(usbd_pipe_handle); -static void uhci_device_bulk_done(usbd_xfer_handle); - -static usbd_status uhci_device_isoc_transfer(usbd_xfer_handle); -static usbd_status uhci_device_isoc_start(usbd_xfer_handle); -static void uhci_device_isoc_abort(usbd_xfer_handle); -static void uhci_device_isoc_close(usbd_pipe_handle); -static void uhci_device_isoc_done(usbd_xfer_handle); - -static usbd_status uhci_root_ctrl_transfer(usbd_xfer_handle); -static usbd_status uhci_root_ctrl_start(usbd_xfer_handle); -static void uhci_root_ctrl_abort(usbd_xfer_handle); -static void uhci_root_ctrl_close(usbd_pipe_handle); -static void uhci_root_ctrl_done(usbd_xfer_handle); - -static usbd_status uhci_root_intr_transfer(usbd_xfer_handle); -static usbd_status uhci_root_intr_start(usbd_xfer_handle); -static void uhci_root_intr_abort(usbd_xfer_handle); -static void uhci_root_intr_close(usbd_pipe_handle); -static void uhci_root_intr_done(usbd_xfer_handle); - -static usbd_status uhci_open(usbd_pipe_handle); -static void uhci_poll(struct usbd_bus *); -static void uhci_softintr(void *); - -static usbd_status uhci_device_request(usbd_xfer_handle xfer); - -static void uhci_add_intr(uhci_softc_t *, uhci_soft_qh_t *); -static void uhci_remove_intr(uhci_softc_t *, uhci_soft_qh_t *); -static usbd_status uhci_device_setintr(uhci_softc_t *sc, - struct uhci_pipe *pipe, int ival); - -static void uhci_device_clear_toggle(usbd_pipe_handle pipe); -static void uhci_noop(usbd_pipe_handle pipe); - -static __inline uhci_soft_qh_t *uhci_find_prev_qh(uhci_soft_qh_t *, - uhci_soft_qh_t *); - -#ifdef USB_DEBUG -static void uhci_dump_all(uhci_softc_t *); -static void uhci_dumpregs(uhci_softc_t *); -#if 0 -static void uhci_dump_qhs(uhci_soft_qh_t *); -#endif -static void uhci_dump_qh(uhci_soft_qh_t *); -static void uhci_dump_tds(uhci_soft_td_t *); -static void uhci_dump_td(uhci_soft_td_t *); -static void uhci_dump_ii(uhci_intr_info_t *ii); -void uhci_dump(void); -#endif - -#define UBARR(sc) bus_space_barrier((sc)->iot, (sc)->ioh, 0, (sc)->sc_size, \ - BUS_SPACE_BARRIER_READ|BUS_SPACE_BARRIER_WRITE) -#define UWRITE1(sc, r, x) \ - do { UBARR(sc); bus_space_write_1((sc)->iot, (sc)->ioh, (r), (x)); \ - } while (/*CONSTCOND*/0) -#define UWRITE2(sc, r, x) \ - do { UBARR(sc); bus_space_write_2((sc)->iot, (sc)->ioh, (r), (x)); \ - } while (/*CONSTCOND*/0) -#define UWRITE4(sc, r, x) \ - do { UBARR(sc); bus_space_write_4((sc)->iot, (sc)->ioh, (r), (x)); \ - } while (/*CONSTCOND*/0) -#define UREAD1(sc, r) (UBARR(sc), bus_space_read_1((sc)->iot, (sc)->ioh, (r))) -#define UREAD2(sc, r) (UBARR(sc), bus_space_read_2((sc)->iot, (sc)->ioh, (r))) -#define UREAD4(sc, r) (UBARR(sc), bus_space_read_4((sc)->iot, (sc)->ioh, (r))) - -#define UHCICMD(sc, cmd) UWRITE2(sc, UHCI_CMD, cmd) -#define UHCISTS(sc) UREAD2(sc, UHCI_STS) - -#define UHCI_RESET_TIMEOUT 100 /* ms, reset timeout */ - -#define UHCI_CURFRAME(sc) (UREAD2(sc, UHCI_FRNUM) & UHCI_FRNUM_MASK) - -#define UHCI_INTR_ENDPT 1 - -struct usbd_bus_methods uhci_bus_methods = { - uhci_open, - uhci_softintr, - uhci_poll, - uhci_allocm, - uhci_freem, - uhci_allocx, - uhci_freex, -}; - -struct usbd_pipe_methods uhci_root_ctrl_methods = { - uhci_root_ctrl_transfer, - uhci_root_ctrl_start, - uhci_root_ctrl_abort, - uhci_root_ctrl_close, - uhci_noop, - uhci_root_ctrl_done, -}; - -struct usbd_pipe_methods uhci_root_intr_methods = { - uhci_root_intr_transfer, - uhci_root_intr_start, - uhci_root_intr_abort, - uhci_root_intr_close, - uhci_noop, - uhci_root_intr_done, -}; - -struct usbd_pipe_methods uhci_device_ctrl_methods = { - uhci_device_ctrl_transfer, - uhci_device_ctrl_start, - uhci_device_ctrl_abort, - uhci_device_ctrl_close, - uhci_noop, - uhci_device_ctrl_done, -}; - -struct usbd_pipe_methods uhci_device_intr_methods = { - uhci_device_intr_transfer, - uhci_device_intr_start, - uhci_device_intr_abort, - uhci_device_intr_close, - uhci_device_clear_toggle, - uhci_device_intr_done, -}; - -struct usbd_pipe_methods uhci_device_bulk_methods = { - uhci_device_bulk_transfer, - uhci_device_bulk_start, - uhci_device_bulk_abort, - uhci_device_bulk_close, - uhci_device_clear_toggle, - uhci_device_bulk_done, -}; - -struct usbd_pipe_methods uhci_device_isoc_methods = { - uhci_device_isoc_transfer, - uhci_device_isoc_start, - uhci_device_isoc_abort, - uhci_device_isoc_close, - uhci_noop, - uhci_device_isoc_done, -}; - -#define uhci_add_intr_info(sc, ii) \ - LIST_INSERT_HEAD(&(sc)->sc_intrhead, (ii), list) -#define uhci_del_intr_info(ii) \ - do { \ - LIST_REMOVE((ii), list); \ - (ii)->list.le_prev = NULL; \ - } while (0) -#define uhci_active_intr_info(ii) ((ii)->list.le_prev != NULL) - -static __inline uhci_soft_qh_t * -uhci_find_prev_qh(uhci_soft_qh_t *pqh, uhci_soft_qh_t *sqh) -{ - DPRINTFN(15,("uhci_find_prev_qh: pqh=%p sqh=%p\n", pqh, sqh)); - - for (; pqh->hlink != sqh; pqh = pqh->hlink) { -#if defined(DIAGNOSTIC) || defined(USB_DEBUG) - if (le32toh(pqh->qh.qh_hlink) & UHCI_PTR_T) { - kprintf("uhci_find_prev_qh: QH not found\n"); - return (NULL); - } -#endif - } - return (pqh); -} - -void -uhci_globalreset(uhci_softc_t *sc) -{ - UHCICMD(sc, UHCI_CMD_GRESET); /* global reset */ - usb_delay_ms(&sc->sc_bus, USB_BUS_RESET_DELAY); /* wait a little */ - UHCICMD(sc, 0); /* do nothing */ -} - -usbd_status -uhci_init(uhci_softc_t *sc) -{ - usbd_status err; - int i, j; - uhci_soft_qh_t *clsqh, *chsqh, *bsqh, *sqh, *lsqh; - uhci_soft_td_t *std; - - DPRINTFN(1,("uhci_init: start\n")); - -#ifdef USB_DEBUG - thesc = sc; - - if (uhcidebug > 2) - uhci_dumpregs(sc); -#endif - - UWRITE2(sc, UHCI_INTR, 0); /* disable interrupts */ - uhci_globalreset(sc); /* reset the controller */ - uhci_reset(sc); - - /* Allocate and initialize real frame array. */ - err = usb_allocmem(&sc->sc_bus, - UHCI_FRAMELIST_COUNT * sizeof(uhci_physaddr_t), - UHCI_FRAMELIST_ALIGN, &sc->sc_dma); - if (err) - return (err); - sc->sc_pframes = KERNADDR(&sc->sc_dma, 0); - UWRITE2(sc, UHCI_FRNUM, 0); /* set frame number to 0 */ - UWRITE4(sc, UHCI_FLBASEADDR, DMAADDR(&sc->sc_dma, 0)); /* set frame list*/ - - /* - * Allocate a TD, inactive, that hangs from the last QH. - * This is to avoid a bug in the PIIX that makes it run berserk - * otherwise. - */ - std = uhci_alloc_std(sc); - if (std == NULL) - return (USBD_NOMEM); - std->link.std = NULL; - std->td.td_link = htole32(UHCI_PTR_T); - std->td.td_status = htole32(0); /* inactive */ - std->td.td_token = htole32(0); - std->td.td_buffer = htole32(0); - - /* Allocate the dummy QH marking the end and used for looping the QHs.*/ - lsqh = uhci_alloc_sqh(sc); - if (lsqh == NULL) - return (USBD_NOMEM); - lsqh->hlink = NULL; - lsqh->qh.qh_hlink = htole32(UHCI_PTR_T); /* end of QH chain */ - lsqh->elink = std; - lsqh->qh.qh_elink = htole32(std->physaddr | UHCI_PTR_TD); - sc->sc_last_qh = lsqh; - - /* Allocate the dummy QH where bulk traffic will be queued. */ - bsqh = uhci_alloc_sqh(sc); - if (bsqh == NULL) - return (USBD_NOMEM); - bsqh->hlink = lsqh; - bsqh->qh.qh_hlink = htole32(lsqh->physaddr | UHCI_PTR_QH); - bsqh->elink = NULL; - bsqh->qh.qh_elink = htole32(UHCI_PTR_T); - sc->sc_bulk_start = sc->sc_bulk_end = bsqh; - - /* Allocate dummy QH where high speed control traffic will be queued. */ - chsqh = uhci_alloc_sqh(sc); - if (chsqh == NULL) - return (USBD_NOMEM); - chsqh->hlink = bsqh; - chsqh->qh.qh_hlink = htole32(bsqh->physaddr | UHCI_PTR_QH); - chsqh->elink = NULL; - chsqh->qh.qh_elink = htole32(UHCI_PTR_T); - sc->sc_hctl_start = sc->sc_hctl_end = chsqh; - - /* Allocate dummy QH where control traffic will be queued. */ - clsqh = uhci_alloc_sqh(sc); - if (clsqh == NULL) - return (USBD_NOMEM); - clsqh->hlink = chsqh; - clsqh->qh.qh_hlink = htole32(chsqh->physaddr | UHCI_PTR_QH); - clsqh->elink = NULL; - clsqh->qh.qh_elink = htole32(UHCI_PTR_T); - sc->sc_lctl_start = sc->sc_lctl_end = clsqh; - - /* - * Make all (virtual) frame list pointers point to the interrupt - * queue heads and the interrupt queue heads at the control - * queue head and point the physical frame list to the virtual. - */ - for(i = 0; i < UHCI_VFRAMELIST_COUNT; i++) { - std = uhci_alloc_std(sc); - sqh = uhci_alloc_sqh(sc); - if (std == NULL || sqh == NULL) - return (USBD_NOMEM); - std->link.sqh = sqh; - - std->td.td_link = htole32(sqh->physaddr | UHCI_PTR_QH); - std->td.td_status = htole32(UHCI_TD_IOS); /* iso, inactive */ - std->td.td_token = htole32(0); - std->td.td_buffer = htole32(0); - sqh->hlink = clsqh; - sqh->qh.qh_hlink = htole32(clsqh->physaddr | UHCI_PTR_QH); - sqh->elink = NULL; - sqh->qh.qh_elink = htole32(UHCI_PTR_T); - sc->sc_vframes[i].htd = std; - sc->sc_vframes[i].etd = std; - sc->sc_vframes[i].hqh = sqh; - sc->sc_vframes[i].eqh = sqh; - for (j = i; - j < UHCI_FRAMELIST_COUNT; - j += UHCI_VFRAMELIST_COUNT) { - sc->sc_pframes[j] = htole32(std->physaddr); - } - } - - LIST_INIT(&sc->sc_intrhead); - - STAILQ_INIT(&sc->sc_free_xfers); - - callout_init(&sc->sc_poll_handle); - - /* Set up the bus struct. */ - sc->sc_bus.methods = &uhci_bus_methods; - sc->sc_bus.pipe_size = sizeof(struct uhci_pipe); - - UHCICMD(sc, UHCI_CMD_MAXP); /* Assume 64 byte packets at frame end */ - - DPRINTFN(1,("uhci_init: enabling\n")); - - err = uhci_run(sc, 1); /* and here we go... */ - - if (err == 0) { - crit_enter(); - sc->sc_flags |= UHCI_SCFLG_DONEINIT; - UWRITE2(sc, UHCI_INTR, - UHCI_INTR_TOCRCIE | UHCI_INTR_RIE | - UHCI_INTR_IOCE | UHCI_INTR_SPIE); - uhci_intr(sc); - crit_exit(); - } - return (err); -} - -int -uhci_detach(struct uhci_softc *sc, int flags) -{ - usbd_xfer_handle xfer; - int rv = 0; - - UWRITE2(sc, UHCI_INTR, 0); /* disable interrupts */ - uhci_run(sc, 0); - - /* Free all xfers associated with this HC. */ - for (;;) { - xfer = STAILQ_FIRST(&sc->sc_free_xfers); - if (xfer == NULL) - break; - STAILQ_REMOVE_HEAD(&sc->sc_free_xfers, next); - kfree(xfer, M_USB); - } - - /* XXX free other data structures XXX */ - usb_freemem(&sc->sc_bus, &sc->sc_dma); - - return (rv); -} - -usbd_status -uhci_allocm(struct usbd_bus *bus, usb_dma_t *dma, u_int32_t size) -{ - return (usb_allocmem(bus, size, 0, dma)); -} - -void -uhci_freem(struct usbd_bus *bus, usb_dma_t *dma) -{ - usb_freemem(bus, dma); -} - -usbd_xfer_handle -uhci_allocx(struct usbd_bus *bus) -{ - struct uhci_softc *sc = (struct uhci_softc *)bus; - usbd_xfer_handle xfer; - - xfer = STAILQ_FIRST(&sc->sc_free_xfers); - if (xfer != NULL) { - STAILQ_REMOVE_HEAD(&sc->sc_free_xfers, next); -#ifdef DIAGNOSTIC - if (xfer->busy_free != XFER_FREE) { - kprintf("uhci_allocx: xfer=%p not free, 0x%08x\n", xfer, - xfer->busy_free); - } -#endif - } else { - xfer = kmalloc(sizeof(struct uhci_xfer), M_USB, M_INTWAIT); - } - if (xfer != NULL) { - memset(xfer, 0, sizeof (struct uhci_xfer)); - UXFER(xfer)->iinfo.sc = sc; - usb_init_task(&UXFER(xfer)->abort_task, uhci_timeout_task, - xfer); - UXFER(xfer)->uhci_xfer_flags = 0; -#ifdef DIAGNOSTIC - UXFER(xfer)->iinfo.isdone = 1; - xfer->busy_free = XFER_BUSY; -#endif - } - return (xfer); -} - -void -uhci_freex(struct usbd_bus *bus, usbd_xfer_handle xfer) -{ - struct uhci_softc *sc = (struct uhci_softc *)bus; - -#ifdef DIAGNOSTIC - if (xfer->busy_free != XFER_BUSY) { - kprintf("uhci_freex: xfer=%p not busy, 0x%08x\n", xfer, - xfer->busy_free); - return; - } - xfer->busy_free = XFER_FREE; - if (!UXFER(xfer)->iinfo.isdone) { - kprintf("uhci_freex: !isdone\n"); - return; - } -#endif - STAILQ_INSERT_HEAD(&sc->sc_free_xfers, xfer, next); -} - -/* - * Shut down the controller when the system is going down. - */ -void -uhci_shutdown(void *v) -{ - uhci_softc_t *sc = v; - - DPRINTF(("uhci_shutdown: stopping the HC\n")); - uhci_run(sc, 0); /* stop the controller */ -} - -/* - * Handle suspend/resume. - * - * We need to switch to polling mode here, because this routine is - * called from an interrupt context. This is all right since we - * are almost suspended anyway. - */ -void -uhci_power(int why, void *v) -{ - uhci_softc_t *sc = v; - int cmd; - - crit_enter(); - cmd = UREAD2(sc, UHCI_CMD); - - DPRINTF(("uhci_power: sc=%p, why=%d (was %d), cmd=0x%x\n", - sc, why, sc->sc_suspend, cmd)); - - if (why != PWR_RESUME) { -#ifdef USB_DEBUG - if (uhcidebug > 2) - uhci_dumpregs(sc); -#endif - if (sc->sc_intr_xfer != NULL) - callout_stop(&sc->sc_poll_handle); - sc->sc_bus.use_polling++; - uhci_run(sc, 0); /* stop the controller */ - - /* save some state if BIOS doesn't */ - sc->sc_saved_frnum = UREAD2(sc, UHCI_FRNUM); - sc->sc_saved_sof = UREAD1(sc, UHCI_SOF); - - UWRITE2(sc, UHCI_INTR, 0); /* disable intrs */ - - UHCICMD(sc, cmd | UHCI_CMD_EGSM); /* enter global suspend */ - usb_delay_ms(&sc->sc_bus, USB_RESUME_WAIT); - sc->sc_suspend = why; - sc->sc_bus.use_polling--; - DPRINTF(("uhci_power: cmd=0x%x\n", UREAD2(sc, UHCI_CMD))); - } else { -#ifdef DIAGNOSTIC - if (sc->sc_suspend == PWR_RESUME) - kprintf("uhci_power: weird, resume without suspend.\n"); -#endif - sc->sc_bus.use_polling++; - sc->sc_suspend = why; - UWRITE2(sc, UHCI_INTR, 0); /* disable interrupts */ - uhci_globalreset(sc); /* reset the controller */ - uhci_reset(sc); - if (cmd & UHCI_CMD_RS) - uhci_run(sc, 0); /* in case BIOS has started it */ - - uhci_globalreset(sc); - uhci_reset(sc); - - /* restore saved state */ - UWRITE4(sc, UHCI_FLBASEADDR, DMAADDR(&sc->sc_dma, 0)); - UWRITE2(sc, UHCI_FRNUM, sc->sc_saved_frnum); - UWRITE1(sc, UHCI_SOF, sc->sc_saved_sof); - - UHCICMD(sc, cmd | UHCI_CMD_FGR); /* force global resume */ - usb_delay_ms(&sc->sc_bus, USB_RESUME_DELAY); - UHCICMD(sc, cmd & ~UHCI_CMD_EGSM); /* back to normal */ - - /* re-enable intrs */ - UWRITE2(sc, UHCI_INTR, - UHCI_INTR_TOCRCIE | UHCI_INTR_RIE | - UHCI_INTR_IOCE | UHCI_INTR_SPIE); - UHCICMD(sc, UHCI_CMD_MAXP); - uhci_run(sc, 1); /* and start traffic again */ - usb_delay_ms(&sc->sc_bus, USB_RESUME_RECOVERY); - sc->sc_bus.use_polling--; - if (sc->sc_intr_xfer != NULL) - callout_reset(&sc->sc_poll_handle, sc->sc_ival, - uhci_poll_hub, sc->sc_intr_xfer); -#ifdef USB_DEBUG - if (uhcidebug > 2) - uhci_dumpregs(sc); -#endif - } - crit_exit(); -} - -#ifdef USB_DEBUG -static void -uhci_dumpregs(uhci_softc_t *sc) -{ - DPRINTFN(-1,("%s regs: cmd=%04x, sts=%04x, intr=%04x, frnum=%04x, " - "flbase=%08x, sof=%04x, portsc1=%04x, portsc2=%04x\n", - device_get_nameunit(sc->sc_bus.bdev), - UREAD2(sc, UHCI_CMD), - UREAD2(sc, UHCI_STS), - UREAD2(sc, UHCI_INTR), - UREAD2(sc, UHCI_FRNUM), - UREAD4(sc, UHCI_FLBASEADDR), - UREAD1(sc, UHCI_SOF), - UREAD2(sc, UHCI_PORTSC1), - UREAD2(sc, UHCI_PORTSC2))); -} - -void -uhci_dump_td(uhci_soft_td_t *p) -{ - char sbuf[128], sbuf2[128]; - - DPRINTFN(-1,("TD(%p) at %08lx = link=0x%08lx status=0x%08lx " - "token=0x%08lx buffer=0x%08lx\n", - p, (long)p->physaddr, - (long)le32toh(p->td.td_link), - (long)le32toh(p->td.td_status), - (long)le32toh(p->td.td_token), - (long)le32toh(p->td.td_buffer))); - - bitmask_snprintf((u_int32_t)le32toh(p->td.td_link), "\20\1T\2Q\3VF", - sbuf, sizeof(sbuf)); - bitmask_snprintf((u_int32_t)le32toh(p->td.td_status), - "\20\22BITSTUFF\23CRCTO\24NAK\25BABBLE\26DBUFFER\27" - "STALLED\30ACTIVE\31IOC\32ISO\33LS\36SPD", - sbuf2, sizeof(sbuf2)); - - DPRINTFN(-1,(" %s %s,errcnt=%d,actlen=%d pid=%02x,addr=%d,endpt=%d," - "D=%d,maxlen=%d\n", sbuf, sbuf2, - UHCI_TD_GET_ERRCNT(le32toh(p->td.td_status)), - UHCI_TD_GET_ACTLEN(le32toh(p->td.td_status)), - UHCI_TD_GET_PID(le32toh(p->td.td_token)), - UHCI_TD_GET_DEVADDR(le32toh(p->td.td_token)), - UHCI_TD_GET_ENDPT(le32toh(p->td.td_token)), - UHCI_TD_GET_DT(le32toh(p->td.td_token)), - UHCI_TD_GET_MAXLEN(le32toh(p->td.td_token)))); -} - -void -uhci_dump_qh(uhci_soft_qh_t *sqh) -{ - DPRINTFN(-1,("QH(%p) at %08x: hlink=%08x elink=%08x\n", sqh, - (int)sqh->physaddr, le32toh(sqh->qh.qh_hlink), - le32toh(sqh->qh.qh_elink))); -} - -#if 1 -void -uhci_dump(void) -{ - uhci_dump_all(thesc); -} -#endif - -void -uhci_dump_all(uhci_softc_t *sc) -{ - uhci_dumpregs(sc); - kprintf("intrs=%d\n", sc->sc_bus.no_intrs); - /*kprintf("framelist[i].link = %08x\n", sc->sc_framelist[0].link);*/ - uhci_dump_qh(sc->sc_lctl_start); -} - -#if 0 -void -uhci_dump_qhs(uhci_soft_qh_t *sqh) -{ - uhci_dump_qh(sqh); - - /* uhci_dump_qhs displays all the QHs and TDs from the given QH onwards - * Traverses sideways first, then down. - * - * QH1 - * QH2 - * No QH - * TD2.1 - * TD2.2 - * TD1.1 - * etc. - * - * TD2.x being the TDs queued at QH2 and QH1 being referenced from QH1. - */ - - - if (sqh->hlink != NULL && !(le32toh(sqh->qh.qh_hlink) & UHCI_PTR_T)) - uhci_dump_qhs(sqh->hlink); - else - DPRINTF(("No QH\n")); - - if (sqh->elink != NULL && !(le32toh(sqh->qh.qh_elink) & UHCI_PTR_T)) - uhci_dump_tds(sqh->elink); - else - DPRINTF(("No TD\n")); -} -#endif - -void -uhci_dump_tds(uhci_soft_td_t *std) -{ - uhci_soft_td_t *td; - - for(td = std; td != NULL; td = td->link.std) { - uhci_dump_td(td); - - /* Check whether the link pointer in this TD marks - * the link pointer as end of queue. This avoids - * printing the free list in case the queue/TD has - * already been moved there (seatbelt). - */ - if (le32toh(td->td.td_link) & UHCI_PTR_T || - le32toh(td->td.td_link) == 0) - break; - } -} - -static void -uhci_dump_ii(uhci_intr_info_t *ii) -{ - usbd_pipe_handle pipe; - usb_endpoint_descriptor_t *ed; - usbd_device_handle dev; - -#ifdef DIAGNOSTIC -#define DONE ii->isdone -#else -#define DONE 0 -#endif - if (ii == NULL) { - kprintf("ii NULL\n"); - return; - } - if (ii->xfer == NULL) { - kprintf("ii %p: done=%d xfer=NULL\n", - ii, DONE); - return; - } - pipe = ii->xfer->pipe; - if (pipe == NULL) { - kprintf("ii %p: done=%d xfer=%p pipe=NULL\n", - ii, DONE, ii->xfer); - return; - } - if (pipe->endpoint == NULL) { - kprintf("ii %p: done=%d xfer=%p pipe=%p pipe->endpoint=NULL\n", - ii, DONE, ii->xfer, pipe); - return; - } - if (pipe->device == NULL) { - kprintf("ii %p: done=%d xfer=%p pipe=%p pipe->device=NULL\n", - ii, DONE, ii->xfer, pipe); - return; - } - ed = pipe->endpoint->edesc; - dev = pipe->device; - kprintf("ii %p: done=%d xfer=%p dev=%p vid=0x%04x pid=0x%04x addr=%d pipe=%p ep=0x%02x attr=0x%02x\n", - ii, DONE, ii->xfer, dev, - UGETW(dev->ddesc.idVendor), - UGETW(dev->ddesc.idProduct), - dev->address, pipe, - ed->bEndpointAddress, ed->bmAttributes); -#undef DONE -} - -void uhci_dump_iis(struct uhci_softc *sc); -void -uhci_dump_iis(struct uhci_softc *sc) -{ - uhci_intr_info_t *ii; - - kprintf("intr_info list:\n"); - for (ii = LIST_FIRST(&sc->sc_intrhead); ii; ii = LIST_NEXT(ii, list)) - uhci_dump_ii(ii); -} - -void iidump(void); -void iidump(void) { uhci_dump_iis(thesc); } - -#endif - -/* - * This routine is executed periodically and simulates interrupts - * from the root controller interrupt pipe for port status change. - */ -void -uhci_poll_hub(void *addr) -{ - usbd_xfer_handle xfer = addr; - usbd_pipe_handle pipe = xfer->pipe; - uhci_softc_t *sc = (uhci_softc_t *)pipe->device->bus; - u_char *p; - - DPRINTFN(20, ("uhci_poll_hub\n")); - - callout_reset(&sc->sc_poll_handle, sc->sc_ival, uhci_poll_hub, xfer); - - p = KERNADDR(&xfer->dmabuf, 0); - p[0] = 0; - if (UREAD2(sc, UHCI_PORTSC1) & (UHCI_PORTSC_CSC|UHCI_PORTSC_OCIC)) - p[0] |= 1<<1; - if (UREAD2(sc, UHCI_PORTSC2) & (UHCI_PORTSC_CSC|UHCI_PORTSC_OCIC)) - p[0] |= 1<<2; - if (p[0] == 0) - /* No change, try again in a while */ - return; - - xfer->actlen = 1; - xfer->status = USBD_NORMAL_COMPLETION; - crit_enter(); - xfer->device->bus->intr_context++; - usb_transfer_complete(xfer); - xfer->device->bus->intr_context--; - crit_exit(); -} - -void -uhci_root_intr_done(usbd_xfer_handle xfer) -{ -} - -void -uhci_root_ctrl_done(usbd_xfer_handle xfer) -{ -} - -/* - * Let the last QH loop back to the high speed control transfer QH. - * This is what intel calls "bandwidth reclamation" and improves - * USB performance a lot for some devices. - * If we are already looping, just count it. - */ -void -uhci_add_loop(uhci_softc_t *sc) { -#ifdef USB_DEBUG - if (uhcinoloop) - return; -#endif - if (++sc->sc_loops == 1) { - DPRINTFN(5,("uhci_start_loop: add\n")); - /* Note, we don't loop back the soft pointer. */ - sc->sc_last_qh->qh.qh_hlink = - htole32(sc->sc_hctl_start->physaddr | UHCI_PTR_QH); - } -} - -void -uhci_rem_loop(uhci_softc_t *sc) { -#ifdef USB_DEBUG - if (uhcinoloop) - return; -#endif - if (--sc->sc_loops == 0) { - DPRINTFN(5,("uhci_end_loop: remove\n")); - sc->sc_last_qh->qh.qh_hlink = htole32(UHCI_PTR_T); - } -} - -/* Add high speed control QH, called from a critical section. */ -void -uhci_add_hs_ctrl(uhci_softc_t *sc, uhci_soft_qh_t *sqh) -{ - uhci_soft_qh_t *eqh; - - DPRINTFN(10, ("uhci_add_ctrl: sqh=%p\n", sqh)); - eqh = sc->sc_hctl_end; - sqh->hlink = eqh->hlink; - sqh->qh.qh_hlink = eqh->qh.qh_hlink; - eqh->hlink = sqh; - eqh->qh.qh_hlink = htole32(sqh->physaddr | UHCI_PTR_QH); - sc->sc_hctl_end = sqh; -#ifdef UHCI_CTL_LOOP - uhci_add_loop(sc); -#endif -} - -/* Remove high speed control QH, called from a critical section. */ -void -uhci_remove_hs_ctrl(uhci_softc_t *sc, uhci_soft_qh_t *sqh) -{ - uhci_soft_qh_t *pqh; - - DPRINTFN(10, ("uhci_remove_hs_ctrl: sqh=%p\n", sqh)); -#ifdef UHCI_CTL_LOOP - uhci_rem_loop(sc); -#endif - /* - * The T bit should be set in the elink of the QH so that the HC - * doesn't follow the pointer. This condition may fail if the - * the transferred packet was short so that the QH still points - * at the last used TD. - * In this case we set the T bit and wait a little for the HC - * to stop looking at the TD. - */ - if (!(sqh->qh.qh_elink & htole32(UHCI_PTR_T))) { - sqh->qh.qh_elink = htole32(UHCI_PTR_T); - delay(UHCI_QH_REMOVE_DELAY); - } - - pqh = uhci_find_prev_qh(sc->sc_hctl_start, sqh); - pqh->hlink = sqh->hlink; - pqh->qh.qh_hlink = sqh->qh.qh_hlink; - delay(UHCI_QH_REMOVE_DELAY); - if (sc->sc_hctl_end == sqh) - sc->sc_hctl_end = pqh; -} - -/* Add low speed control QH, called from a critical section. */ -void -uhci_add_ls_ctrl(uhci_softc_t *sc, uhci_soft_qh_t *sqh) -{ - uhci_soft_qh_t *eqh; - - DPRINTFN(10, ("uhci_add_ls_ctrl: sqh=%p\n", sqh)); - eqh = sc->sc_lctl_end; - sqh->hlink = eqh->hlink; - sqh->qh.qh_hlink = eqh->qh.qh_hlink; - eqh->hlink = sqh; - eqh->qh.qh_hlink = htole32(sqh->physaddr | UHCI_PTR_QH); - sc->sc_lctl_end = sqh; -} - -/* Remove low speed control QH, called from a critical section. */ -void -uhci_remove_ls_ctrl(uhci_softc_t *sc, uhci_soft_qh_t *sqh) -{ - uhci_soft_qh_t *pqh; - - DPRINTFN(10, ("uhci_remove_ls_ctrl: sqh=%p\n", sqh)); - /* See comment in uhci_remove_hs_ctrl() */ - if (!(sqh->qh.qh_elink & htole32(UHCI_PTR_T))) { - sqh->qh.qh_elink = htole32(UHCI_PTR_T); - delay(UHCI_QH_REMOVE_DELAY); - } - pqh = uhci_find_prev_qh(sc->sc_lctl_start, sqh); - pqh->hlink = sqh->hlink; - pqh->qh.qh_hlink = sqh->qh.qh_hlink; - delay(UHCI_QH_REMOVE_DELAY); - if (sc->sc_lctl_end == sqh) - sc->sc_lctl_end = pqh; -} - -/* Add bulk QH, called from a critical section. */ -void -uhci_add_bulk(uhci_softc_t *sc, uhci_soft_qh_t *sqh) -{ - uhci_soft_qh_t *eqh; - - DPRINTFN(10, ("uhci_add_bulk: sqh=%p\n", sqh)); - eqh = sc->sc_bulk_end; - sqh->hlink = eqh->hlink; - sqh->qh.qh_hlink = eqh->qh.qh_hlink; - eqh->hlink = sqh; - eqh->qh.qh_hlink = htole32(sqh->physaddr | UHCI_PTR_QH); - sc->sc_bulk_end = sqh; - uhci_add_loop(sc); -} - -/* Remove bulk QH, called from a critical section. */ -void -uhci_remove_bulk(uhci_softc_t *sc, uhci_soft_qh_t *sqh) -{ - uhci_soft_qh_t *pqh; - - DPRINTFN(10, ("uhci_remove_bulk: sqh=%p\n", sqh)); - uhci_rem_loop(sc); - /* See comment in uhci_remove_hs_ctrl() */ - if (!(sqh->qh.qh_elink & htole32(UHCI_PTR_T))) { - sqh->qh.qh_elink = htole32(UHCI_PTR_T); - delay(UHCI_QH_REMOVE_DELAY); - } - pqh = uhci_find_prev_qh(sc->sc_bulk_start, sqh); - pqh->hlink = sqh->hlink; - pqh->qh.qh_hlink = sqh->qh.qh_hlink; - delay(UHCI_QH_REMOVE_DELAY); - if (sc->sc_bulk_end == sqh) - sc->sc_bulk_end = pqh; -} - -static int uhci_intr1(uhci_softc_t *); - -int -uhci_intr(void *arg) -{ - uhci_softc_t *sc = arg; - - if (sc->sc_dying || (sc->sc_flags & UHCI_SCFLG_DONEINIT) == 0) - return (0); - - DPRINTFN(15,("uhci_intr: real interrupt\n")); - if (sc->sc_bus.use_polling) { -#ifdef DIAGNOSTIC - DPRINTFN(16, ("uhci_intr: ignored interrupt while polling\n")); -#endif - return (0); - } - - return (uhci_intr1(sc)); -} - -int -uhci_intr1(uhci_softc_t *sc) -{ - - int status; - int ack; - - /* - * It can happen that an interrupt will be delivered to - * us before the device has been fully attached and the - * softc struct has been configured. Usually this happens - * when kldloading the USB support as a module after the - * system has been booted. If we detect this condition, - * we need to squelch the unwanted interrupts until we're - * ready for them. - */ - if (sc->sc_bus.bdev == NULL) { - UWRITE2(sc, UHCI_STS, 0xFFFF); /* ack pending interrupts */ - uhci_run(sc, 0); /* stop the controller */ - UWRITE2(sc, UHCI_INTR, 0); /* disable interrupts */ - return(0); - } - -#ifdef USB_DEBUG - if (uhcidebug > 15) { - DPRINTF(("%s: uhci_intr1\n", device_get_nameunit(sc->sc_bus.bdev))); - uhci_dumpregs(sc); - } -#endif - status = UREAD2(sc, UHCI_STS) & UHCI_STS_ALLINTRS; - if (status == 0) /* The interrupt was not for us. */ - return (0); - - if (sc->sc_suspend != PWR_RESUME) { - device_printf(sc->sc_bus.bdev, - "interrupt while not operating ignored\n"); - UWRITE2(sc, UHCI_STS, status); /* acknowledge the ints */ - return (0); - } - - ack = 0; - if (status & UHCI_STS_USBINT) - ack |= UHCI_STS_USBINT; - if (status & UHCI_STS_USBEI) - ack |= UHCI_STS_USBEI; - if (status & UHCI_STS_RD) { - ack |= UHCI_STS_RD; -#ifdef USB_DEBUG - device_printf(sc->sc_bus.bdev, "resume detect\n"); -#endif - } - if (status & UHCI_STS_HSE) { - ack |= UHCI_STS_HSE; - device_printf(sc->sc_bus.bdev, "host system error\n"); - } - if (status & UHCI_STS_HCPE) { - ack |= UHCI_STS_HCPE; - device_printf(sc->sc_bus.bdev, - "host controller process error\n"); - } - if (status & UHCI_STS_HCH) { - /* no acknowledge needed */ - if (!sc->sc_dying) { - device_printf(sc->sc_bus.bdev, - "host controller halted\n"); -#ifdef USB_DEBUG - uhci_dump_all(sc); -#endif - } - sc->sc_dying = 1; - } - - if (!ack) - return (0); /* nothing to acknowledge */ - UWRITE2(sc, UHCI_STS, ack); /* acknowledge the ints */ - - sc->sc_bus.no_intrs++; - usb_schedsoftintr(&sc->sc_bus); - - DPRINTFN(15, ("%s: uhci_intr: exit\n", device_get_nameunit(sc->sc_bus.bdev))); - - return (1); -} - -void -uhci_softintr(void *v) -{ - uhci_softc_t *sc = v; - uhci_intr_info_t *ii, *nextii; - - DPRINTFN(10,("%s: uhci_softintr (%d)\n", device_get_nameunit(sc->sc_bus.bdev), - sc->sc_bus.intr_context)); - - sc->sc_bus.intr_context++; - - /* - * Interrupts on UHCI really suck. When the host controller - * interrupts because a transfer is completed there is no - * way of knowing which transfer it was. You can scan down - * the TDs and QHs of the previous frame to limit the search, - * but that assumes that the interrupt was not delayed by more - * than 1 ms, which may not always be true (e.g. after debug - * output on a slow console). - * We scan all interrupt descriptors to see if any have - * completed. - */ - LIST_FOREACH_MUTABLE(ii, &sc->sc_intrhead, list, nextii) - uhci_check_intr(sc, ii); - -#ifdef USB_USE_SOFTINTR - if (sc->sc_softwake) { - sc->sc_softwake = 0; - wakeup(&sc->sc_softwake); - } -#endif /* USB_USE_SOFTINTR */ - - sc->sc_bus.intr_context--; -} - -/* Check for an interrupt. */ -void -uhci_check_intr(uhci_softc_t *sc, uhci_intr_info_t *ii) -{ - uhci_soft_td_t *std, *lstd; - u_int32_t status; - - DPRINTFN(15, ("uhci_check_intr: ii=%p\n", ii)); -#ifdef DIAGNOSTIC - if (ii == NULL) { - kprintf("uhci_check_intr: no ii? %p\n", ii); - return; - } -#endif - if (ii->xfer->status == USBD_CANCELLED || - ii->xfer->status == USBD_TIMEOUT) { - DPRINTF(("uhci_check_intr: aborted xfer=%p\n", ii->xfer)); - return; - } - - if (ii->stdstart == NULL) - return; - lstd = ii->stdend; -#ifdef DIAGNOSTIC - if (lstd == NULL) { - kprintf("uhci_check_intr: std==0\n"); - return; - } -#endif - /* - * If the last TD is still active we need to check whether there - * is an error somewhere in the middle, or whether there was a - * short packet (SPD and not ACTIVE). - */ - if (le32toh(lstd->td.td_status) & UHCI_TD_ACTIVE) { - DPRINTFN(12, ("uhci_check_intr: active ii=%p\n", ii)); - for (std = ii->stdstart; std != lstd; std = std->link.std) { - status = le32toh(std->td.td_status); - /* If there's an active TD the xfer isn't done. */ - if (status & UHCI_TD_ACTIVE) - break; - /* Any kind of error makes the xfer done. */ - if (status & UHCI_TD_STALLED) - goto done; - /* We want short packets, and it is short: it's done */ - if ((status & UHCI_TD_SPD) && - UHCI_TD_GET_ACTLEN(status) < - UHCI_TD_GET_MAXLEN(le32toh(std->td.td_token))) { - goto done; - } - } - DPRINTFN(12, ("uhci_check_intr: ii=%p std=%p still active\n", - ii, ii->stdstart)); - return; - } -done: - DPRINTFN(12, ("uhci_check_intr: ii=%p done\n", ii)); - callout_stop(&ii->xfer->timeout_handle); - usb_rem_task(ii->xfer->pipe->device, &UXFER(ii->xfer)->abort_task); - uhci_idone(ii); -} - -/* Called from a critical section. */ -void -uhci_idone(uhci_intr_info_t *ii) -{ - usbd_xfer_handle xfer = ii->xfer; - struct uhci_pipe *upipe = (struct uhci_pipe *)xfer->pipe; - uhci_soft_td_t *std; - u_int32_t status = 0, nstatus; - int actlen; - - DPRINTFN(12, ("uhci_idone: ii=%p\n", ii)); -#ifdef DIAGNOSTIC - { - crit_enter(); - if (ii->isdone) { - crit_exit(); -#ifdef USB_DEBUG - kprintf("uhci_idone: ii is done!\n "); - uhci_dump_ii(ii); -#else - kprintf("uhci_idone: ii=%p is done!\n", ii); -#endif - return; - } - ii->isdone = 1; - crit_exit(); - } -#endif - - if (xfer->nframes != 0) { - /* Isoc transfer, do things differently. */ - uhci_soft_td_t **stds = upipe->u.iso.stds; - int i, n, nframes, len; - - DPRINTFN(5,("uhci_idone: ii=%p isoc ready\n", ii)); - - nframes = xfer->nframes; - actlen = 0; - n = UXFER(xfer)->curframe; - for (i = 0; i < nframes; i++) { - std = stds[n]; -#ifdef USB_DEBUG - if (uhcidebug > 5) { - DPRINTFN(-1,("uhci_idone: isoc TD %d\n", i)); - uhci_dump_td(std); - } -#endif - if (++n >= UHCI_VFRAMELIST_COUNT) - n = 0; - status = le32toh(std->td.td_status); - len = UHCI_TD_GET_ACTLEN(status); - xfer->frlengths[i] = len; - actlen += len; - } - upipe->u.iso.inuse -= nframes; - xfer->actlen = actlen; - xfer->status = USBD_NORMAL_COMPLETION; - goto end; - } - -#ifdef USB_DEBUG - DPRINTFN(10, ("uhci_idone: ii=%p, xfer=%p, pipe=%p ready\n", - ii, xfer, upipe)); - if (uhcidebug > 10) - uhci_dump_tds(ii->stdstart); -#endif - - /* The transfer is done, compute actual length and status. */ - actlen = 0; - for (std = ii->stdstart; std != NULL; std = std->link.std) { - nstatus = le32toh(std->td.td_status); - if (nstatus & UHCI_TD_ACTIVE) - break; - - status = nstatus; - if (UHCI_TD_GET_PID(le32toh(std->td.td_token)) != - UHCI_TD_PID_SETUP) { - actlen += UHCI_TD_GET_ACTLEN(status); - } else { - /* - * UHCI will report CRCTO in addition to a STALL or NAK - * for a SETUP transaction. See section 3.2.2, "TD - * CONTROL AND STATUS". - */ - if (status & (UHCI_TD_STALLED | UHCI_TD_NAK)) - status &= ~UHCI_TD_CRCTO; - } - - } - /* If there are left over TDs we need to update the toggle. */ - if (std != NULL) - upipe->nexttoggle = UHCI_TD_GET_DT(le32toh(std->td.td_token)); - - status &= UHCI_TD_ERROR; - DPRINTFN(10, ("uhci_idone: actlen=%d, status=0x%x\n", - actlen, status)); - xfer->actlen = actlen; - if (status != 0) { -#ifdef USB_DEBUG - char sbuf[128]; - - bitmask_snprintf(status, - "\20\22BITSTUFF\23CRCTO\24NAK\25" - "BABBLE\26DBUFFER\27STALLED\30ACTIVE", - sbuf, sizeof(sbuf)); - - DPRINTFN((status == UHCI_TD_STALLED)*10, - ("uhci_idone: error, addr=%d, endpt=0x%02x, " - "status 0x%s\n", - xfer->pipe->device->address, - xfer->pipe->endpoint->edesc->bEndpointAddress, - sbuf)); -#endif - if (status == UHCI_TD_STALLED) - xfer->status = USBD_STALLED; - else - xfer->status = USBD_IOERROR; /* more info XXX */ - } else { - xfer->status = USBD_NORMAL_COMPLETION; - } - - end: - usb_transfer_complete(xfer); - DPRINTFN(12, ("uhci_idone: ii=%p done\n", ii)); -} - -/* - * Called when a request does not complete. - */ -void -uhci_timeout(void *addr) -{ - uhci_intr_info_t *ii = addr; - struct uhci_xfer *uxfer = UXFER(ii->xfer); - struct uhci_pipe *upipe = (struct uhci_pipe *)uxfer->xfer.pipe; - uhci_softc_t *sc = (uhci_softc_t *)upipe->pipe.device->bus; - - DPRINTF(("uhci_timeout: uxfer=%p\n", uxfer)); - - if (sc->sc_dying) { - uhci_abort_xfer(&uxfer->xfer, USBD_TIMEOUT); - return; - } - - /* Execute the abort in a process context. */ - usb_add_task(uxfer->xfer.pipe->device, &uxfer->abort_task, - USB_TASKQ_HC); -} - -void -uhci_timeout_task(void *addr) -{ - usbd_xfer_handle xfer = addr; - - DPRINTF(("uhci_timeout_task: xfer=%p\n", xfer)); - - crit_enter(); - uhci_abort_xfer(xfer, USBD_TIMEOUT); - crit_exit(); -} - -/* - * Wait here until controller claims to have an interrupt. - * Then call uhci_intr and return. Use timeout to avoid waiting - * too long. - * Only used during boot when interrupts are not enabled yet. - */ -void -uhci_waitintr(uhci_softc_t *sc, usbd_xfer_handle xfer) -{ - int timo = xfer->timeout; - uhci_intr_info_t *ii; - - DPRINTFN(10,("uhci_waitintr: timeout = %dms\n", timo)); - - xfer->status = USBD_IN_PROGRESS; - for (; timo >= 0; timo--) { - usb_delay_ms(&sc->sc_bus, 1); - DPRINTFN(20,("uhci_waitintr: 0x%04x\n", UREAD2(sc, UHCI_STS))); - if (UREAD2(sc, UHCI_STS) & UHCI_STS_ALLINTRS) - uhci_intr1(sc); - if (xfer->status != USBD_IN_PROGRESS) - return; - } - - /* Timeout */ - DPRINTF(("uhci_waitintr: timeout\n")); - for (ii = LIST_FIRST(&sc->sc_intrhead); - ii != NULL && ii->xfer != xfer; - ii = LIST_NEXT(ii, list)) - ; -#ifdef DIAGNOSTIC - if (ii == NULL) - panic("uhci_waitintr: lost intr_info"); -#endif - uhci_idone(ii); -} - -void -uhci_poll(struct usbd_bus *bus) -{ - uhci_softc_t *sc = (uhci_softc_t *)bus; - - crit_enter(); - uhci_intr1(sc); - uhci_softintr(sc); - crit_exit(); -} - -void -uhci_reset(uhci_softc_t *sc) -{ - int n; - - UHCICMD(sc, UHCI_CMD_HCRESET); - /* The reset bit goes low when the controller is done. */ - for (n = 0; n < UHCI_RESET_TIMEOUT && - (UREAD2(sc, UHCI_CMD) & UHCI_CMD_HCRESET); n++) - usb_delay_ms(&sc->sc_bus, 1); - if (n >= UHCI_RESET_TIMEOUT) - device_printf(sc->sc_bus.bdev, "controller did not reset\n"); -} - -usbd_status -uhci_run(uhci_softc_t *sc, int run) -{ - int n, running; - u_int16_t cmd; - - run = run != 0; - crit_enter(); - DPRINTF(("uhci_run: setting run=%d\n", run)); - cmd = UREAD2(sc, UHCI_CMD); - if (run) - cmd |= UHCI_CMD_RS; - else - cmd &= ~UHCI_CMD_RS; - UHCICMD(sc, cmd); - for(n = 0; n < 10; n++) { - running = !(UREAD2(sc, UHCI_STS) & UHCI_STS_HCH); - /* return when we've entered the state we want */ - if (run == running) { - crit_exit(); - DPRINTF(("uhci_run: done cmd=0x%x sts=0x%x\n", - UREAD2(sc, UHCI_CMD), UREAD2(sc, UHCI_STS))); - return (USBD_NORMAL_COMPLETION); - } - usb_delay_ms(&sc->sc_bus, 1); - } - crit_exit(); - device_printf(sc->sc_bus.bdev, "cannot %s\n", run ? "start" : "stop"); - return (USBD_IOERROR); -} - -/* - * Memory management routines. - * uhci_alloc_std allocates TDs - * uhci_alloc_sqh allocates QHs - * These two routines do their own free list management, - * partly for speed, partly because allocating DMAable memory - * has page size granularaity so much memory would be wasted if - * only one TD/QH (32 bytes) was placed in each allocated chunk. - */ - -uhci_soft_td_t * -uhci_alloc_std(uhci_softc_t *sc) -{ - uhci_soft_td_t *std; - usbd_status err; - int i, offs; - usb_dma_t dma; - - if (sc->sc_freetds == NULL) { - DPRINTFN(2,("uhci_alloc_std: allocating chunk\n")); - err = usb_allocmem(&sc->sc_bus, UHCI_STD_SIZE * UHCI_STD_CHUNK, - UHCI_TD_ALIGN, &dma); - if (err) - return (0); - for(i = 0; i < UHCI_STD_CHUNK; i++) { - offs = i * UHCI_STD_SIZE; - std = KERNADDR(&dma, offs); - std->physaddr = DMAADDR(&dma, offs); - std->link.std = sc->sc_freetds; - sc->sc_freetds = std; - } - } - std = sc->sc_freetds; - sc->sc_freetds = std->link.std; - memset(&std->td, 0, sizeof(uhci_td_t)); - return std; -} - -void -uhci_free_std(uhci_softc_t *sc, uhci_soft_td_t *std) -{ -#ifdef DIAGNOSTIC -#define TD_IS_FREE 0x12345678 - if (le32toh(std->td.td_token) == TD_IS_FREE) { - kprintf("uhci_free_std: freeing free TD %p\n", std); - return; - } - std->td.td_token = htole32(TD_IS_FREE); -#endif - std->link.std = sc->sc_freetds; - sc->sc_freetds = std; -} - -uhci_soft_qh_t * -uhci_alloc_sqh(uhci_softc_t *sc) -{ - uhci_soft_qh_t *sqh; - usbd_status err; - int i, offs; - usb_dma_t dma; - - if (sc->sc_freeqhs == NULL) { - DPRINTFN(2, ("uhci_alloc_sqh: allocating chunk\n")); - err = usb_allocmem(&sc->sc_bus, UHCI_SQH_SIZE * UHCI_SQH_CHUNK, - UHCI_QH_ALIGN, &dma); - if (err) - return (0); - for(i = 0; i < UHCI_SQH_CHUNK; i++) { - offs = i * UHCI_SQH_SIZE; - sqh = KERNADDR(&dma, offs); - sqh->physaddr = DMAADDR(&dma, offs); - sqh->hlink = sc->sc_freeqhs; - sc->sc_freeqhs = sqh; - } - } - sqh = sc->sc_freeqhs; - sc->sc_freeqhs = sqh->hlink; - memset(&sqh->qh, 0, sizeof(uhci_qh_t)); - return (sqh); -} - -void -uhci_free_sqh(uhci_softc_t *sc, uhci_soft_qh_t *sqh) -{ - sqh->hlink = sc->sc_freeqhs; - sc->sc_freeqhs = sqh; -} - -void -uhci_free_std_chain(uhci_softc_t *sc, uhci_soft_td_t *std, - uhci_soft_td_t *stdend) -{ - uhci_soft_td_t *p; - - for (; std != stdend; std = p) { - p = std->link.std; - uhci_free_std(sc, std); - } -} - -usbd_status -uhci_alloc_std_chain(struct uhci_pipe *upipe, uhci_softc_t *sc, int len, - int rd, u_int16_t flags, usb_dma_t *dma, - uhci_soft_td_t **sp, uhci_soft_td_t **ep) -{ - uhci_soft_td_t *p, *lastp; - uhci_physaddr_t lastlink; - int i, ntd, l, tog, maxp; - u_int32_t status; - int addr = upipe->pipe.device->address; - int endpt = upipe->pipe.endpoint->edesc->bEndpointAddress; - - DPRINTFN(8, ("uhci_alloc_std_chain: addr=%d endpt=%d len=%d speed=%d " - "flags=0x%x\n", addr, UE_GET_ADDR(endpt), len, - upipe->pipe.device->speed, flags)); - maxp = UGETW(upipe->pipe.endpoint->edesc->wMaxPacketSize); - if (maxp == 0) { - kprintf("uhci_alloc_std_chain: maxp=0\n"); - return (USBD_INVAL); - } - ntd = (len + maxp - 1) / maxp; - if ((flags & USBD_FORCE_SHORT_XFER) && len % maxp == 0) - ntd++; - DPRINTFN(10, ("uhci_alloc_std_chain: maxp=%d ntd=%d\n", maxp, ntd)); - if (ntd == 0) { - *sp = *ep = NULL; - DPRINTFN(-1,("uhci_alloc_std_chain: ntd=0\n")); - return (USBD_NORMAL_COMPLETION); - } - tog = upipe->nexttoggle; - if (ntd % 2 == 0) - tog ^= 1; - upipe->nexttoggle = tog ^ 1; - lastp = NULL; - lastlink = UHCI_PTR_T; - ntd--; - status = UHCI_TD_ZERO_ACTLEN(UHCI_TD_SET_ERRCNT(3) | UHCI_TD_ACTIVE); - if (upipe->pipe.device->speed == USB_SPEED_LOW) - status |= UHCI_TD_LS; - if (flags & USBD_SHORT_XFER_OK) - status |= UHCI_TD_SPD; - for (i = ntd; i >= 0; i--) { - p = uhci_alloc_std(sc); - if (p == NULL) { - uhci_free_std_chain(sc, lastp, NULL); - return (USBD_NOMEM); - } - p->link.std = lastp; - p->td.td_link = htole32(lastlink | UHCI_PTR_VF | UHCI_PTR_TD); - lastp = p; - lastlink = p->physaddr; - p->td.td_status = htole32(status); - if (i == ntd) { - /* last TD */ - l = len % maxp; - if (l == 0 && !(flags & USBD_FORCE_SHORT_XFER)) - l = maxp; - *ep = p; - } else - l = maxp; - p->td.td_token = - htole32(rd ? UHCI_TD_IN (l, endpt, addr, tog) : - UHCI_TD_OUT(l, endpt, addr, tog)); - p->td.td_buffer = htole32(DMAADDR(dma, i * maxp)); - tog ^= 1; - } - *sp = lastp; - DPRINTFN(10, ("uhci_alloc_std_chain: nexttog=%d\n", - upipe->nexttoggle)); - return (USBD_NORMAL_COMPLETION); -} - -void -uhci_device_clear_toggle(usbd_pipe_handle pipe) -{ - struct uhci_pipe *upipe = (struct uhci_pipe *)pipe; - upipe->nexttoggle = 0; -} - -void -uhci_noop(usbd_pipe_handle pipe) -{ -} - -usbd_status -uhci_device_bulk_transfer(usbd_xfer_handle xfer) -{ - usbd_status err; - - /* Insert last in queue. */ - err = usb_insert_transfer(xfer); - if (err) - return (err); - - /* - * Pipe isn't running (otherwise err would be USBD_INPROG), - * so start it first. - */ - return (uhci_device_bulk_start(STAILQ_FIRST(&xfer->pipe->queue))); -} - -usbd_status -uhci_device_bulk_start(usbd_xfer_handle xfer) -{ - struct uhci_pipe *upipe = (struct uhci_pipe *)xfer->pipe; - usbd_device_handle dev = upipe->pipe.device; - uhci_softc_t *sc = (uhci_softc_t *)dev->bus; - uhci_intr_info_t *ii = &UXFER(xfer)->iinfo; - uhci_soft_td_t *data, *dataend; - uhci_soft_qh_t *sqh; - usbd_status err; - int len, isread, endpt; - - DPRINTFN(3, ("uhci_device_bulk_start: xfer=%p len=%d flags=%d ii=%p\n", - xfer, xfer->length, xfer->flags, ii)); - - if (sc->sc_dying) - return (USBD_IOERROR); - -#ifdef DIAGNOSTIC - if (xfer->rqflags & URQ_REQUEST) - panic("uhci_device_bulk_transfer: a request"); -#endif - - len = xfer->length; - endpt = upipe->pipe.endpoint->edesc->bEndpointAddress; - isread = UE_GET_DIR(endpt) == UE_DIR_IN; - sqh = upipe->u.bulk.sqh; - - upipe->u.bulk.isread = isread; - upipe->u.bulk.length = len; - - err = uhci_alloc_std_chain(upipe, sc, len, isread, xfer->flags, - &xfer->dmabuf, &data, &dataend); - if (err) - return (err); - dataend->td.td_status |= htole32(UHCI_TD_IOC); - -#ifdef USB_DEBUG - if (uhcidebug > 8) { - DPRINTF(("uhci_device_bulk_transfer: data(1)\n")); - uhci_dump_tds(data); - } -#endif - - /* Set up interrupt info. */ - ii->xfer = xfer; - ii->stdstart = data; - ii->stdend = dataend; -#ifdef DIAGNOSTIC - if (!ii->isdone) { - kprintf("uhci_device_bulk_transfer: not done, ii=%p\n", ii); - } - ii->isdone = 0; -#endif - - sqh->elink = data; - sqh->qh.qh_elink = htole32(data->physaddr | UHCI_PTR_TD); - - crit_enter(); - uhci_add_bulk(sc, sqh); - uhci_add_intr_info(sc, ii); - - if (xfer->timeout && !sc->sc_bus.use_polling) { - callout_reset(&xfer->timeout_handle, MS_TO_TICKS(xfer->timeout), - uhci_timeout, ii); - } - xfer->status = USBD_IN_PROGRESS; - crit_exit(); - -#ifdef USB_DEBUG - if (uhcidebug > 10) { - DPRINTF(("uhci_device_bulk_transfer: data(2)\n")); - uhci_dump_tds(data); - } -#endif - - if (sc->sc_bus.use_polling) - uhci_waitintr(sc, xfer); - - return (USBD_IN_PROGRESS); -} - -/* Abort a device bulk request. */ -void -uhci_device_bulk_abort(usbd_xfer_handle xfer) -{ - DPRINTF(("uhci_device_bulk_abort:\n")); - uhci_abort_xfer(xfer, USBD_CANCELLED); -} - -/* - * Abort a device request. - * If this routine is called from a critical section. It guarantees that - * the request will be removed from the hardware scheduling and that - * the callback for it will be called with USBD_CANCELLED status. - * It's impossible to guarantee that the requested transfer will not - * have happened since the hardware runs concurrently. - * If the transaction has already happened we rely on the ordinary - * interrupt processing to process it. - */ -void -uhci_abort_xfer(usbd_xfer_handle xfer, usbd_status status) -{ - struct uhci_xfer *uxfer = UXFER(xfer); - uhci_intr_info_t *ii = &uxfer->iinfo; - struct uhci_pipe *upipe = (struct uhci_pipe *)xfer->pipe; - uhci_softc_t *sc = (uhci_softc_t *)upipe->pipe.device->bus; - uhci_soft_td_t *std; - - DPRINTFN(1,("uhci_abort_xfer: xfer=%p, status=%d\n", xfer, status)); - - if (sc->sc_dying) { - /* If we're dying, just do the software part. */ - crit_enter(); - xfer->status = status; /* make software ignore it */ - callout_stop(&xfer->timeout_handle); - usb_rem_task(xfer->pipe->device, &UXFER(xfer)->abort_task); - usb_transfer_complete(xfer); - crit_exit(); - return; - } - -#if 0 - if (xfer->device->bus->intr_context /* || !curproc REMOVED DFly */) - panic("uhci_abort_xfer: not in process context"); -#endif - - /* - * If an abort is already in progress then just wait for it to - * complete and return. - */ - crit_enter(); - if (uxfer->uhci_xfer_flags & UHCI_XFER_ABORTING) { - crit_exit(); - DPRINTFN(2, ("uhci_abort_xfer: already aborting\n")); - /* No need to wait if we're aborting from a timeout. */ - if (status == USBD_TIMEOUT) - return; - /* Override the status which might be USBD_TIMEOUT. */ - xfer->status = status; - DPRINTFN(2, ("uhci_abort_xfer: waiting for abort to finish\n")); - uxfer->uhci_xfer_flags |= UHCI_XFER_ABORTWAIT; - crit_enter(); - while (uxfer->uhci_xfer_flags & UHCI_XFER_ABORTING) - tsleep(&uxfer->uhci_xfer_flags, 0, "uhciaw", 0); - crit_exit(); - return; - } - - /* - * Step 1: Make interrupt routine and hardware ignore xfer. - */ - uxfer->uhci_xfer_flags |= UHCI_XFER_ABORTING; - xfer->status = status; /* make software ignore it */ - callout_stop(&xfer->timeout_handle); - usb_rem_task(xfer->pipe->device, &UXFER(xfer)->abort_task); - DPRINTFN(1,("uhci_abort_xfer: stop ii=%p\n", ii)); - for (std = ii->stdstart; std != NULL; std = std->link.std) - std->td.td_status &= htole32(~(UHCI_TD_ACTIVE | UHCI_TD_IOC)); - crit_exit(); - - /* - * Step 2: Wait until we know hardware has finished any possible - * use of the xfer. Also make sure the soft interrupt routine - * has run. - */ - usb_delay_ms(upipe->pipe.device->bus, 2); /* Hardware finishes in 1ms */ - crit_enter(); -#ifdef USB_USE_SOFTINTR - sc->sc_softwake = 1; -#endif /* USB_USE_SOFTINTR */ - usb_schedsoftintr(&sc->sc_bus); -#ifdef USB_USE_SOFTINTR - DPRINTFN(1,("uhci_abort_xfer: tsleep\n")); - tsleep(&sc->sc_softwake, 0, "uhciab", 0); -#endif /* USB_USE_SOFTINTR */ - - /* - * Step 3: Execute callback. - */ - DPRINTFN(1,("uhci_abort_xfer: callback\n")); -#ifdef DIAGNOSTIC - ii->isdone = 1; -#endif - /* Do the wakeup first to avoid touching the xfer after the callback. */ - uxfer->uhci_xfer_flags &= ~UHCI_XFER_ABORTING; - if (uxfer->uhci_xfer_flags & UHCI_XFER_ABORTWAIT) { - uxfer->uhci_xfer_flags &= ~UHCI_XFER_ABORTWAIT; - wakeup(&uxfer->uhci_xfer_flags); - } - usb_transfer_complete(xfer); - crit_exit(); -} - -/* Close a device bulk pipe. */ -void -uhci_device_bulk_close(usbd_pipe_handle pipe) -{ - struct uhci_pipe *upipe = (struct uhci_pipe *)pipe; - usbd_device_handle dev = upipe->pipe.device; - uhci_softc_t *sc = (uhci_softc_t *)dev->bus; - - uhci_free_sqh(sc, upipe->u.bulk.sqh); - pipe->endpoint->savedtoggle = upipe->nexttoggle; -} - -usbd_status -uhci_device_ctrl_transfer(usbd_xfer_handle xfer) -{ - usbd_status err; - - /* Insert last in queue. */ - err = usb_insert_transfer(xfer); - if (err) - return (err); - - /* - * Pipe isn't running (otherwise err would be USBD_INPROG), - * so start it first. - */ - return (uhci_device_ctrl_start(STAILQ_FIRST(&xfer->pipe->queue))); -} - -usbd_status -uhci_device_ctrl_start(usbd_xfer_handle xfer) -{ - uhci_softc_t *sc = (uhci_softc_t *)xfer->pipe->device->bus; - usbd_status err; - - if (sc->sc_dying) - return (USBD_IOERROR); - -#ifdef DIAGNOSTIC - if (!(xfer->rqflags & URQ_REQUEST)) - panic("uhci_device_ctrl_transfer: not a request"); -#endif - - err = uhci_device_request(xfer); - if (err) - return (err); - - if (sc->sc_bus.use_polling) - uhci_waitintr(sc, xfer); - return (USBD_IN_PROGRESS); -} - -usbd_status -uhci_device_intr_transfer(usbd_xfer_handle xfer) -{ - usbd_status err; - - /* Insert last in queue. */ - err = usb_insert_transfer(xfer); - if (err) - return (err); - - /* - * Pipe isn't running (otherwise err would be USBD_INPROG), - * so start it first. - */ - return (uhci_device_intr_start(STAILQ_FIRST(&xfer->pipe->queue))); -} - -usbd_status -uhci_device_intr_start(usbd_xfer_handle xfer) -{ - struct uhci_pipe *upipe = (struct uhci_pipe *)xfer->pipe; - usbd_device_handle dev = upipe->pipe.device; - uhci_softc_t *sc = (uhci_softc_t *)dev->bus; - uhci_intr_info_t *ii = &UXFER(xfer)->iinfo; - uhci_soft_td_t *data, *dataend; - uhci_soft_qh_t *sqh; - usbd_status err; - int isread, endpt; - int i; - - if (sc->sc_dying) - return (USBD_IOERROR); - - DPRINTFN(3,("uhci_device_intr_transfer: xfer=%p len=%d flags=%d\n", - xfer, xfer->length, xfer->flags)); - -#ifdef DIAGNOSTIC - if (xfer->rqflags & URQ_REQUEST) - panic("uhci_device_intr_transfer: a request"); -#endif - - endpt = upipe->pipe.endpoint->edesc->bEndpointAddress; - isread = UE_GET_DIR(endpt) == UE_DIR_IN; - sqh = upipe->u.bulk.sqh; - - upipe->u.intr.isread = isread; - - err = uhci_alloc_std_chain(upipe, sc, xfer->length, isread, - xfer->flags, &xfer->dmabuf, &data, - &dataend); - if (err) - return (err); - dataend->td.td_status |= htole32(UHCI_TD_IOC); - -#ifdef USB_DEBUG - if (uhcidebug > 10) { - DPRINTF(("uhci_device_intr_transfer: data(1)\n")); - uhci_dump_tds(data); - uhci_dump_qh(upipe->u.intr.qhs[0]); - } -#endif - - crit_enter(); - /* Set up interrupt info. */ - ii->xfer = xfer; - ii->stdstart = data; - ii->stdend = dataend; -#ifdef DIAGNOSTIC - if (!ii->isdone) { - kprintf("uhci_device_intr_transfer: not done, ii=%p\n", ii); - } - ii->isdone = 0; -#endif - - DPRINTFN(10,("uhci_device_intr_transfer: qhs[0]=%p\n", - upipe->u.intr.qhs[0])); - for (i = 0; i < upipe->u.intr.npoll; i++) { - sqh = upipe->u.intr.qhs[i]; - sqh->elink = data; - sqh->qh.qh_elink = htole32(data->physaddr | UHCI_PTR_TD); - } - uhci_add_intr_info(sc, ii); - xfer->status = USBD_IN_PROGRESS; - crit_exit(); - -#ifdef USB_DEBUG - if (uhcidebug > 10) { - DPRINTF(("uhci_device_intr_transfer: data(2)\n")); - uhci_dump_tds(data); - uhci_dump_qh(upipe->u.intr.qhs[0]); - } -#endif - - return (USBD_IN_PROGRESS); -} - -/* Abort a device control request. */ -void -uhci_device_ctrl_abort(usbd_xfer_handle xfer) -{ - DPRINTF(("uhci_device_ctrl_abort:\n")); - uhci_abort_xfer(xfer, USBD_CANCELLED); -} - -/* Close a device control pipe. */ -void -uhci_device_ctrl_close(usbd_pipe_handle pipe) -{ -} - -/* Abort a device interrupt request. */ -void -uhci_device_intr_abort(usbd_xfer_handle xfer) -{ - DPRINTFN(1,("uhci_device_intr_abort: xfer=%p\n", xfer)); - if (xfer->pipe->intrxfer == xfer) { - DPRINTFN(1,("uhci_device_intr_abort: remove\n")); - xfer->pipe->intrxfer = NULL; - } - uhci_abort_xfer(xfer, USBD_CANCELLED); -} - -/* Close a device interrupt pipe. */ -void -uhci_device_intr_close(usbd_pipe_handle pipe) -{ - struct uhci_pipe *upipe = (struct uhci_pipe *)pipe; - uhci_softc_t *sc = (uhci_softc_t *)pipe->device->bus; - int i, npoll; - - /* Unlink descriptors from controller data structures. */ - npoll = upipe->u.intr.npoll; - crit_enter(); - for (i = 0; i < npoll; i++) - uhci_remove_intr(sc, upipe->u.intr.qhs[i]); - crit_exit(); - - /* - * We now have to wait for any activity on the physical - * descriptors to stop. - */ - usb_delay_ms(&sc->sc_bus, 2); - - for(i = 0; i < npoll; i++) - uhci_free_sqh(sc, upipe->u.intr.qhs[i]); - kfree(upipe->u.intr.qhs, M_USBHC); - - /* XXX free other resources */ -} - -usbd_status -uhci_device_request(usbd_xfer_handle xfer) -{ - struct uhci_pipe *upipe = (struct uhci_pipe *)xfer->pipe; - usb_device_request_t *req = &xfer->request; - usbd_device_handle dev = upipe->pipe.device; - uhci_softc_t *sc = (uhci_softc_t *)dev->bus; - int addr = dev->address; - int endpt = upipe->pipe.endpoint->edesc->bEndpointAddress; - uhci_intr_info_t *ii = &UXFER(xfer)->iinfo; - uhci_soft_td_t *setup, *data, *stat, *next, *dataend; - uhci_soft_qh_t *sqh; - int len; - u_int32_t ls; - usbd_status err; - int isread; - - DPRINTFN(3,("uhci_device_control type=0x%02x, request=0x%02x, " - "wValue=0x%04x, wIndex=0x%04x len=%d, addr=%d, endpt=%d\n", - req->bmRequestType, req->bRequest, UGETW(req->wValue), - UGETW(req->wIndex), UGETW(req->wLength), - addr, endpt)); - - ls = dev->speed == USB_SPEED_LOW ? UHCI_TD_LS : 0; - isread = req->bmRequestType & UT_READ; - len = UGETW(req->wLength); - - setup = upipe->u.ctl.setup; - stat = upipe->u.ctl.stat; - sqh = upipe->u.ctl.sqh; - - /* Set up data transaction */ - if (len != 0) { - upipe->nexttoggle = 1; - err = uhci_alloc_std_chain(upipe, sc, len, isread, xfer->flags, - &xfer->dmabuf, &data, &dataend); - if (err) - return (err); - next = data; - dataend->link.std = stat; - dataend->td.td_link = htole32(stat->physaddr | UHCI_PTR_VF | UHCI_PTR_TD); - } else { - next = stat; - } - upipe->u.ctl.length = len; - - memcpy(KERNADDR(&upipe->u.ctl.reqdma, 0), req, sizeof *req); - - setup->link.std = next; - setup->td.td_link = htole32(next->physaddr | UHCI_PTR_VF | UHCI_PTR_TD); - setup->td.td_status = htole32(UHCI_TD_SET_ERRCNT(3) | ls | - UHCI_TD_ACTIVE); - setup->td.td_token = htole32(UHCI_TD_SETUP(sizeof *req, endpt, addr)); - setup->td.td_buffer = htole32(DMAADDR(&upipe->u.ctl.reqdma, 0)); - stat->link.std = NULL; - stat->td.td_link = htole32(UHCI_PTR_T); - stat->td.td_status = htole32(UHCI_TD_SET_ERRCNT(3) | ls | - UHCI_TD_ACTIVE | UHCI_TD_IOC); - - stat->td.td_token = - htole32(isread ? UHCI_TD_OUT(0, endpt, addr, 1) : - UHCI_TD_IN (0, endpt, addr, 1)); - stat->td.td_buffer = htole32(0); - -#ifdef USB_DEBUG - if (uhcidebug > 10) { - DPRINTF(("uhci_device_request: before transfer\n")); - uhci_dump_tds(setup); - } -#endif - - /* Set up interrupt info. */ - ii->xfer = xfer; - ii->stdstart = setup; - ii->stdend = stat; -#ifdef DIAGNOSTIC - if (!ii->isdone) { - kprintf("uhci_device_request: not done, ii=%p\n", ii); - } - ii->isdone = 0; -#endif - - sqh->elink = setup; - sqh->qh.qh_elink = htole32(setup->physaddr | UHCI_PTR_TD); - - crit_enter(); - if (dev->speed == USB_SPEED_LOW) - uhci_add_ls_ctrl(sc, sqh); - else - uhci_add_hs_ctrl(sc, sqh); - uhci_add_intr_info(sc, ii); -#ifdef USB_DEBUG - if (uhcidebug > 12) { - uhci_soft_td_t *std; - uhci_soft_qh_t *xqh; - uhci_soft_qh_t *sxqh; - int maxqh = 0; - uhci_physaddr_t link; - DPRINTF(("uhci_enter_ctl_q: follow from [0]\n")); - for (std = sc->sc_vframes[0].htd, link = 0; - (link & UHCI_PTR_QH) == 0; - std = std->link.std) { - link = le32toh(std->td.td_link); - uhci_dump_td(std); - } - sxqh = (uhci_soft_qh_t *)std; - uhci_dump_qh(sxqh); - for (xqh = sxqh; - xqh != NULL; - xqh = (maxqh++ == 5 || xqh->hlink == sxqh || - xqh->hlink == xqh ? NULL : xqh->hlink)) { - uhci_dump_qh(xqh); - } - DPRINTF(("Enqueued QH:\n")); - uhci_dump_qh(sqh); - uhci_dump_tds(sqh->elink); - } -#endif - if (xfer->timeout && !sc->sc_bus.use_polling) { - callout_reset(&xfer->timeout_handle, MS_TO_TICKS(xfer->timeout), - uhci_timeout, ii); - } - xfer->status = USBD_IN_PROGRESS; - crit_exit(); - - return (USBD_NORMAL_COMPLETION); -} - -usbd_status -uhci_device_isoc_transfer(usbd_xfer_handle xfer) -{ - usbd_status err; - - DPRINTFN(5,("uhci_device_isoc_transfer: xfer=%p\n", xfer)); - - /* Put it on our queue, */ - err = usb_insert_transfer(xfer); - - /* bail out on error, */ - if (err && err != USBD_IN_PROGRESS) - return (err); - - /* XXX should check inuse here */ - - /* insert into schedule, */ - uhci_device_isoc_enter(xfer); - - /* and start if the pipe wasn't running */ - if (!err) - uhci_device_isoc_start(STAILQ_FIRST(&xfer->pipe->queue)); - - return (err); -} - -void -uhci_device_isoc_enter(usbd_xfer_handle xfer) -{ - struct uhci_pipe *upipe = (struct uhci_pipe *)xfer->pipe; - usbd_device_handle dev = upipe->pipe.device; - uhci_softc_t *sc = (uhci_softc_t *)dev->bus; - struct iso *iso = &upipe->u.iso; - uhci_soft_td_t *std; - u_int32_t buf, len, status; - int i, next, nframes; - - DPRINTFN(5,("uhci_device_isoc_enter: used=%d next=%d xfer=%p " - "nframes=%d\n", - iso->inuse, iso->next, xfer, xfer->nframes)); - - if (sc->sc_dying) - return; - - if (xfer->status == USBD_IN_PROGRESS) { - /* This request has already been entered into the frame list */ - kprintf("uhci_device_isoc_enter: xfer=%p in frame list\n", xfer); - /* XXX */ - } - -#ifdef DIAGNOSTIC - if (iso->inuse >= UHCI_VFRAMELIST_COUNT) - kprintf("uhci_device_isoc_enter: overflow!\n"); -#endif - - next = iso->next; - if (next == -1) { - /* Not in use yet, schedule it a few frames ahead. */ - next = (UREAD2(sc, UHCI_FRNUM) + 3) % UHCI_VFRAMELIST_COUNT; - DPRINTFN(2,("uhci_device_isoc_enter: start next=%d\n", next)); - } - - xfer->status = USBD_IN_PROGRESS; - UXFER(xfer)->curframe = next; - - buf = DMAADDR(&xfer->dmabuf, 0); - status = UHCI_TD_ZERO_ACTLEN(UHCI_TD_SET_ERRCNT(0) | - UHCI_TD_ACTIVE | - UHCI_TD_IOS); - nframes = xfer->nframes; - crit_enter(); - for (i = 0; i < nframes; i++) { - std = iso->stds[next]; - if (++next >= UHCI_VFRAMELIST_COUNT) - next = 0; - len = xfer->frlengths[i]; - std->td.td_buffer = htole32(buf); - if (i == nframes - 1) - status |= UHCI_TD_IOC; - std->td.td_status = htole32(status); - std->td.td_token &= htole32(~UHCI_TD_MAXLEN_MASK); - std->td.td_token |= htole32(UHCI_TD_SET_MAXLEN(len)); -#ifdef USB_DEBUG - if (uhcidebug > 5) { - DPRINTFN(5,("uhci_device_isoc_enter: TD %d\n", i)); - uhci_dump_td(std); - } -#endif - buf += len; - } - iso->next = next; - iso->inuse += xfer->nframes; - - crit_exit(); -} - -usbd_status -uhci_device_isoc_start(usbd_xfer_handle xfer) -{ - struct uhci_pipe *upipe = (struct uhci_pipe *)xfer->pipe; - uhci_softc_t *sc = (uhci_softc_t *)upipe->pipe.device->bus; - uhci_intr_info_t *ii = &UXFER(xfer)->iinfo; - uhci_soft_td_t *end; - int i; - - DPRINTFN(5,("uhci_device_isoc_start: xfer=%p\n", xfer)); - - if (sc->sc_dying) - return (USBD_IOERROR); - -#ifdef DIAGNOSTIC - if (xfer->status != USBD_IN_PROGRESS) - kprintf("uhci_device_isoc_start: not in progress %p\n", xfer); -#endif - - /* Find the last TD */ - i = UXFER(xfer)->curframe + xfer->nframes; - if (i >= UHCI_VFRAMELIST_COUNT) - i -= UHCI_VFRAMELIST_COUNT; - end = upipe->u.iso.stds[i]; - -#ifdef DIAGNOSTIC - if (end == NULL) { - kprintf("uhci_device_isoc_start: end == NULL\n"); - return (USBD_INVAL); - } -#endif - - crit_enter(); - - /* Set up interrupt info. */ - ii->xfer = xfer; - ii->stdstart = end; - ii->stdend = end; -#ifdef DIAGNOSTIC - if (!ii->isdone) - kprintf("uhci_device_isoc_start: not done, ii=%p\n", ii); - ii->isdone = 0; -#endif - uhci_add_intr_info(sc, ii); - - crit_exit(); - - return (USBD_IN_PROGRESS); -} - -void -uhci_device_isoc_abort(usbd_xfer_handle xfer) -{ - struct uhci_pipe *upipe = (struct uhci_pipe *)xfer->pipe; - uhci_soft_td_t **stds = upipe->u.iso.stds; - uhci_soft_td_t *std; - int i, n, nframes, maxlen, len; - - crit_enter(); - - /* Transfer is already done. */ - if (xfer->status != USBD_NOT_STARTED && - xfer->status != USBD_IN_PROGRESS) { - crit_exit(); - return; - } - - /* Give xfer the requested abort code. */ - xfer->status = USBD_CANCELLED; - - /* make hardware ignore it, */ - nframes = xfer->nframes; - n = UXFER(xfer)->curframe; - maxlen = 0; - for (i = 0; i < nframes; i++) { - std = stds[n]; - std->td.td_status &= htole32(~(UHCI_TD_ACTIVE | UHCI_TD_IOC)); - len = UHCI_TD_GET_MAXLEN(le32toh(std->td.td_token)); - if (len > maxlen) - maxlen = len; - if (++n >= UHCI_VFRAMELIST_COUNT) - n = 0; - } - - /* and wait until we are sure the hardware has finished. */ - delay(maxlen); - -#ifdef DIAGNOSTIC - UXFER(xfer)->iinfo.isdone = 1; -#endif - /* Run callback and remove from interrupt list. */ - usb_transfer_complete(xfer); - - crit_exit(); -} - -void -uhci_device_isoc_close(usbd_pipe_handle pipe) -{ - struct uhci_pipe *upipe = (struct uhci_pipe *)pipe; - usbd_device_handle dev = upipe->pipe.device; - uhci_softc_t *sc = (uhci_softc_t *)dev->bus; - uhci_soft_td_t *std, *vstd; - struct iso *iso; - int i; - - /* - * Make sure all TDs are marked as inactive. - * Wait for completion. - * Unschedule. - * Deallocate. - */ - iso = &upipe->u.iso; - - for (i = 0; i < UHCI_VFRAMELIST_COUNT; i++) - iso->stds[i]->td.td_status &= htole32(~UHCI_TD_ACTIVE); - usb_delay_ms(&sc->sc_bus, 2); /* wait for completion */ - - crit_enter(); - for (i = 0; i < UHCI_VFRAMELIST_COUNT; i++) { - std = iso->stds[i]; - for (vstd = sc->sc_vframes[i].htd; - vstd != NULL && vstd->link.std != std; - vstd = vstd->link.std) - ; - if (vstd == NULL) { - /*panic*/ - kprintf("uhci_device_isoc_close: %p not found\n", std); - crit_exit(); - return; - } - vstd->link = std->link; - vstd->td.td_link = std->td.td_link; - uhci_free_std(sc, std); - } - crit_exit(); - - kfree(iso->stds, M_USBHC); -} - -usbd_status -uhci_setup_isoc(usbd_pipe_handle pipe) -{ - struct uhci_pipe *upipe = (struct uhci_pipe *)pipe; - usbd_device_handle dev = upipe->pipe.device; - uhci_softc_t *sc = (uhci_softc_t *)dev->bus; - int addr = upipe->pipe.device->address; - int endpt = upipe->pipe.endpoint->edesc->bEndpointAddress; - int rd = UE_GET_DIR(endpt) == UE_DIR_IN; - uhci_soft_td_t *std, *vstd; - u_int32_t token; - struct iso *iso; - int i; - - iso = &upipe->u.iso; - iso->stds = kmalloc(UHCI_VFRAMELIST_COUNT * sizeof (uhci_soft_td_t *), - M_USBHC, M_INTWAIT); - - token = rd ? UHCI_TD_IN (0, endpt, addr, 0) : - UHCI_TD_OUT(0, endpt, addr, 0); - - /* Allocate the TDs and mark as inactive; */ - for (i = 0; i < UHCI_VFRAMELIST_COUNT; i++) { - std = uhci_alloc_std(sc); - if (std == NULL) - goto bad; - std->td.td_status = htole32(UHCI_TD_IOS); /* iso, inactive */ - std->td.td_token = htole32(token); - iso->stds[i] = std; - } - - /* Insert TDs into schedule. */ - crit_enter(); - for (i = 0; i < UHCI_VFRAMELIST_COUNT; i++) { - std = iso->stds[i]; - vstd = sc->sc_vframes[i].htd; - std->link = vstd->link; - std->td.td_link = vstd->td.td_link; - vstd->link.std = std; - vstd->td.td_link = htole32(std->physaddr | UHCI_PTR_TD); - } - crit_exit(); - - iso->next = -1; - iso->inuse = 0; - - return (USBD_NORMAL_COMPLETION); - - bad: - while (--i >= 0) - uhci_free_std(sc, iso->stds[i]); - kfree(iso->stds, M_USBHC); - return (USBD_NOMEM); -} - -void -uhci_device_isoc_done(usbd_xfer_handle xfer) -{ - uhci_intr_info_t *ii = &UXFER(xfer)->iinfo; - - DPRINTFN(4, ("uhci_isoc_done: length=%d\n", xfer->actlen)); - - if (ii->xfer != xfer) - /* Not on interrupt list, ignore it. */ - return; - - if (!uhci_active_intr_info(ii)) - return; - -#ifdef DIAGNOSTIC - if (xfer->busy_free != XFER_BUSY) { - kprintf("uhci_device_isoc_done: xfer=%p not busy 0x%08x\n", - xfer, xfer->busy_free); - return; - } - - if (ii->stdend == NULL) { - kprintf("uhci_device_isoc_done: xfer=%p stdend==NULL\n", xfer); -#ifdef USB_DEBUG - uhci_dump_ii(ii); -#endif - return; - } -#endif - - /* Turn off the interrupt since it is active even if the TD is not. */ - ii->stdend->td.td_status &= htole32(~UHCI_TD_IOC); - - uhci_del_intr_info(ii); /* remove from active list */ - -#ifdef DIAGNOSTIC - if (ii->stdend == NULL) { - kprintf("uhci_device_isoc_done: xfer=%p stdend==NULL\n", xfer); -#ifdef USB_DEBUG - uhci_dump_ii(ii); -#endif - return; - } -#endif -} - -void -uhci_device_intr_done(usbd_xfer_handle xfer) -{ - uhci_intr_info_t *ii = &UXFER(xfer)->iinfo; - uhci_softc_t *sc = ii->sc; - struct uhci_pipe *upipe = (struct uhci_pipe *)xfer->pipe; - uhci_soft_qh_t *sqh; - int i, npoll; - - DPRINTFN(5, ("uhci_device_intr_done: length=%d\n", xfer->actlen)); - - npoll = upipe->u.intr.npoll; - for(i = 0; i < npoll; i++) { - sqh = upipe->u.intr.qhs[i]; - sqh->elink = NULL; - sqh->qh.qh_elink = htole32(UHCI_PTR_T); - } - uhci_free_std_chain(sc, ii->stdstart, NULL); - - /* XXX Wasteful. */ - if (xfer->pipe->repeat) { - uhci_soft_td_t *data, *dataend; - - DPRINTFN(5,("uhci_device_intr_done: requeueing\n")); - - /* This alloc cannot fail since we freed the chain above. */ - uhci_alloc_std_chain(upipe, sc, xfer->length, - upipe->u.intr.isread, xfer->flags, - &xfer->dmabuf, &data, &dataend); - dataend->td.td_status |= htole32(UHCI_TD_IOC); - -#ifdef USB_DEBUG - if (uhcidebug > 10) { - DPRINTF(("uhci_device_intr_done: data(1)\n")); - uhci_dump_tds(data); - uhci_dump_qh(upipe->u.intr.qhs[0]); - } -#endif - - ii->stdstart = data; - ii->stdend = dataend; -#ifdef DIAGNOSTIC - if (!ii->isdone) { - kprintf("uhci_device_intr_done: not done, ii=%p\n", ii); - } - ii->isdone = 0; -#endif - for (i = 0; i < npoll; i++) { - sqh = upipe->u.intr.qhs[i]; - sqh->elink = data; - sqh->qh.qh_elink = htole32(data->physaddr | UHCI_PTR_TD); - } - xfer->status = USBD_IN_PROGRESS; - /* The ii is already on the examined list, just leave it. */ - } else { - DPRINTFN(5,("uhci_device_intr_done: removing\n")); - if (uhci_active_intr_info(ii)) - uhci_del_intr_info(ii); - } -} - -/* Deallocate request data structures */ -void -uhci_device_ctrl_done(usbd_xfer_handle xfer) -{ - uhci_intr_info_t *ii = &UXFER(xfer)->iinfo; - uhci_softc_t *sc = ii->sc; - struct uhci_pipe *upipe = (struct uhci_pipe *)xfer->pipe; - -#ifdef DIAGNOSTIC - if (!(xfer->rqflags & URQ_REQUEST)) - panic("uhci_device_ctrl_done: not a request"); -#endif - - if (!uhci_active_intr_info(ii)) - return; - - uhci_del_intr_info(ii); /* remove from active list */ - - if (upipe->pipe.device->speed == USB_SPEED_LOW) - uhci_remove_ls_ctrl(sc, upipe->u.ctl.sqh); - else - uhci_remove_hs_ctrl(sc, upipe->u.ctl.sqh); - - if (upipe->u.ctl.length != 0) - uhci_free_std_chain(sc, ii->stdstart->link.std, ii->stdend); - - DPRINTFN(5, ("uhci_device_ctrl_done: length=%d\n", xfer->actlen)); -} - -/* Deallocate request data structures */ -void -uhci_device_bulk_done(usbd_xfer_handle xfer) -{ - uhci_intr_info_t *ii = &UXFER(xfer)->iinfo; - uhci_softc_t *sc = ii->sc; - struct uhci_pipe *upipe = (struct uhci_pipe *)xfer->pipe; - - DPRINTFN(5,("uhci_device_bulk_done: xfer=%p ii=%p sc=%p upipe=%p\n", - xfer, ii, sc, upipe)); - - if (!uhci_active_intr_info(ii)) - return; - - uhci_del_intr_info(ii); /* remove from active list */ - - uhci_remove_bulk(sc, upipe->u.bulk.sqh); - - uhci_free_std_chain(sc, ii->stdstart, NULL); - - DPRINTFN(5, ("uhci_device_bulk_done: length=%d\n", xfer->actlen)); -} - -/* Add interrupt QH, called with vflock. */ -void -uhci_add_intr(uhci_softc_t *sc, uhci_soft_qh_t *sqh) -{ - struct uhci_vframe *vf = &sc->sc_vframes[sqh->pos]; - uhci_soft_qh_t *eqh; - - DPRINTFN(4, ("uhci_add_intr: n=%d sqh=%p\n", sqh->pos, sqh)); - - eqh = vf->eqh; - sqh->hlink = eqh->hlink; - sqh->qh.qh_hlink = eqh->qh.qh_hlink; - eqh->hlink = sqh; - eqh->qh.qh_hlink = htole32(sqh->physaddr | UHCI_PTR_QH); - vf->eqh = sqh; - vf->bandwidth++; -} - -/* Remove interrupt QH. */ -void -uhci_remove_intr(uhci_softc_t *sc, uhci_soft_qh_t *sqh) -{ - struct uhci_vframe *vf = &sc->sc_vframes[sqh->pos]; - uhci_soft_qh_t *pqh; - - DPRINTFN(4, ("uhci_remove_intr: n=%d sqh=%p\n", sqh->pos, sqh)); - - /* See comment in uhci_remove_ctrl() */ - if (!(sqh->qh.qh_elink & htole32(UHCI_PTR_T))) { - sqh->qh.qh_elink = htole32(UHCI_PTR_T); - delay(UHCI_QH_REMOVE_DELAY); - } - - pqh = uhci_find_prev_qh(vf->hqh, sqh); - pqh->hlink = sqh->hlink; - pqh->qh.qh_hlink = sqh->qh.qh_hlink; - delay(UHCI_QH_REMOVE_DELAY); - if (vf->eqh == sqh) - vf->eqh = pqh; - vf->bandwidth--; -} - -usbd_status -uhci_device_setintr(uhci_softc_t *sc, struct uhci_pipe *upipe, int ival) -{ - uhci_soft_qh_t *sqh; - int i, npoll; - u_int bestbw, bw, bestoffs, offs; - - DPRINTFN(2, ("uhci_device_setintr: pipe=%p\n", upipe)); - if (ival == 0) { - kprintf("uhci_setintr: 0 interval\n"); - return (USBD_INVAL); - } - - if (ival > UHCI_VFRAMELIST_COUNT) - ival = UHCI_VFRAMELIST_COUNT; - npoll = (UHCI_VFRAMELIST_COUNT + ival - 1) / ival; - DPRINTFN(2, ("uhci_device_setintr: ival=%d npoll=%d\n", ival, npoll)); - - upipe->u.intr.npoll = npoll; - upipe->u.intr.qhs = - kmalloc(npoll * sizeof(uhci_soft_qh_t *), M_USBHC, M_INTWAIT); - - /* - * Figure out which offset in the schedule that has most - * bandwidth left over. - */ -#define MOD(i) ((i) & (UHCI_VFRAMELIST_COUNT-1)) - for (bestoffs = offs = 0, bestbw = ~0; offs < ival; offs++) { - for (bw = i = 0; i < npoll; i++) - bw += sc->sc_vframes[MOD(i * ival + offs)].bandwidth; - if (bw < bestbw) { - bestbw = bw; - bestoffs = offs; - } - } - DPRINTFN(1, ("uhci_device_setintr: bw=%d offs=%d\n", bestbw, bestoffs)); - - for(i = 0; i < npoll; i++) { - upipe->u.intr.qhs[i] = sqh = uhci_alloc_sqh(sc); - sqh->elink = NULL; - sqh->qh.qh_elink = htole32(UHCI_PTR_T); - sqh->pos = MOD(i * ival + bestoffs); - } -#undef MOD - - crit_enter(); - /* Enter QHs into the controller data structures. */ - for(i = 0; i < npoll; i++) - uhci_add_intr(sc, upipe->u.intr.qhs[i]); - crit_exit(); - - DPRINTFN(5, ("uhci_device_setintr: returns %p\n", upipe)); - return (USBD_NORMAL_COMPLETION); -} - -/* Open a new pipe. */ -usbd_status -uhci_open(usbd_pipe_handle pipe) -{ - uhci_softc_t *sc = (uhci_softc_t *)pipe->device->bus; - struct uhci_pipe *upipe = (struct uhci_pipe *)pipe; - usb_endpoint_descriptor_t *ed = pipe->endpoint->edesc; - usbd_status err; - int ival; - - DPRINTFN(1, ("uhci_open: pipe=%p, addr=%d, endpt=%d (%d)\n", - pipe, pipe->device->address, - ed->bEndpointAddress, sc->sc_addr)); - - upipe->aborting = 0; - upipe->nexttoggle = pipe->endpoint->savedtoggle; - - if (pipe->device->address == sc->sc_addr) { - switch (ed->bEndpointAddress) { - case USB_CONTROL_ENDPOINT: - pipe->methods = &uhci_root_ctrl_methods; - break; - case UE_DIR_IN | UHCI_INTR_ENDPT: - pipe->methods = &uhci_root_intr_methods; - break; - default: - return (USBD_INVAL); - } - } else { - switch (ed->bmAttributes & UE_XFERTYPE) { - case UE_CONTROL: - pipe->methods = &uhci_device_ctrl_methods; - upipe->u.ctl.sqh = uhci_alloc_sqh(sc); - if (upipe->u.ctl.sqh == NULL) - goto bad; - upipe->u.ctl.setup = uhci_alloc_std(sc); - if (upipe->u.ctl.setup == NULL) { - uhci_free_sqh(sc, upipe->u.ctl.sqh); - goto bad; - } - upipe->u.ctl.stat = uhci_alloc_std(sc); - if (upipe->u.ctl.stat == NULL) { - uhci_free_sqh(sc, upipe->u.ctl.sqh); - uhci_free_std(sc, upipe->u.ctl.setup); - goto bad; - } - err = usb_allocmem(&sc->sc_bus, - sizeof(usb_device_request_t), - 0, &upipe->u.ctl.reqdma); - if (err) { - uhci_free_sqh(sc, upipe->u.ctl.sqh); - uhci_free_std(sc, upipe->u.ctl.setup); - uhci_free_std(sc, upipe->u.ctl.stat); - goto bad; - } - break; - case UE_INTERRUPT: - pipe->methods = &uhci_device_intr_methods; - ival = pipe->interval; - if (ival == USBD_DEFAULT_INTERVAL) - ival = ed->bInterval; - return (uhci_device_setintr(sc, upipe, ival)); - case UE_ISOCHRONOUS: - pipe->methods = &uhci_device_isoc_methods; - return (uhci_setup_isoc(pipe)); - case UE_BULK: - pipe->methods = &uhci_device_bulk_methods; - upipe->u.bulk.sqh = uhci_alloc_sqh(sc); - if (upipe->u.bulk.sqh == NULL) - goto bad; - break; - } - } - return (USBD_NORMAL_COMPLETION); - - bad: - return (USBD_NOMEM); -} - -/* - * Data structures and routines to emulate the root hub. - */ -usb_device_descriptor_t uhci_devd = { - USB_DEVICE_DESCRIPTOR_SIZE, - UDESC_DEVICE, /* type */ - {0x00, 0x01}, /* USB version */ - UDCLASS_HUB, /* class */ - UDSUBCLASS_HUB, /* subclass */ - UDPROTO_FSHUB, /* protocol */ - 64, /* max packet */ - {0},{0},{0x00,0x01}, /* device id */ - 1,2,0, /* string indicies */ - 1 /* # of configurations */ -}; - -usb_config_descriptor_t uhci_confd = { - USB_CONFIG_DESCRIPTOR_SIZE, - UDESC_CONFIG, - {USB_CONFIG_DESCRIPTOR_SIZE + - USB_INTERFACE_DESCRIPTOR_SIZE + - USB_ENDPOINT_DESCRIPTOR_SIZE}, - 1, - 1, - 0, - UC_SELF_POWERED, - 0 /* max power */ -}; - -usb_interface_descriptor_t uhci_ifcd = { - USB_INTERFACE_DESCRIPTOR_SIZE, - UDESC_INTERFACE, - 0, - 0, - 1, - UICLASS_HUB, - UISUBCLASS_HUB, - UIPROTO_FSHUB, - 0 -}; - -usb_endpoint_descriptor_t uhci_endpd = { - USB_ENDPOINT_DESCRIPTOR_SIZE, - UDESC_ENDPOINT, - UE_DIR_IN | UHCI_INTR_ENDPT, - UE_INTERRUPT, - {8}, - 255 -}; - -usb_hub_descriptor_t uhci_hubd_piix = { - USB_HUB_DESCRIPTOR_SIZE, - UDESC_HUB, - 2, - { UHD_PWR_NO_SWITCH | UHD_OC_INDIVIDUAL, 0 }, - 50, /* power on to power good */ - 0, - { 0x00 }, /* both ports are removable */ -}; - -int -uhci_str(usb_string_descriptor_t *p, int l, char *s) -{ - int i; - - if (l == 0) - return (0); - p->bLength = 2 * strlen(s) + 2; - if (l == 1) - return (1); - p->bDescriptorType = UDESC_STRING; - l -= 2; - for (i = 0; s[i] && l > 1; i++, l -= 2) - USETW2(p->bString[i], 0, s[i]); - return (2*i+2); -} - -/* - * The USB hub protocol requires that SET_FEATURE(PORT_RESET) also - * enables the port, and also states that SET_FEATURE(PORT_ENABLE) - * should not be used by the USB subsystem. As we cannot issue a - * SET_FEATURE(PORT_ENABLE) externally, we must ensure that the port - * will be enabled as part of the reset. - * - * On the VT83C572, the port cannot be successfully enabled until the - * outstanding "port enable change" and "connection status change" - * events have been reset. - */ -static usbd_status -uhci_portreset(uhci_softc_t *sc, int index) -{ - int lim, port, x; - - if (index == 1) - port = UHCI_PORTSC1; - else if (index == 2) - port = UHCI_PORTSC2; - else - return (USBD_IOERROR); - - x = URWMASK(UREAD2(sc, port)); - UWRITE2(sc, port, x | UHCI_PORTSC_PR); - - usb_delay_ms(&sc->sc_bus, USB_PORT_ROOT_RESET_DELAY); - - DPRINTFN(3,("uhci port %d reset, status0 = 0x%04x\n", - index, UREAD2(sc, port))); - - x = URWMASK(UREAD2(sc, port)); - UWRITE2(sc, port, x & ~UHCI_PORTSC_PR); - - delay(100); - - DPRINTFN(3,("uhci port %d reset, status1 = 0x%04x\n", - index, UREAD2(sc, port))); - - x = URWMASK(UREAD2(sc, port)); - UWRITE2(sc, port, x | UHCI_PORTSC_PE); - - for (lim = 10; --lim > 0;) { - usb_delay_ms(&sc->sc_bus, USB_PORT_RESET_DELAY); - - x = UREAD2(sc, port); - - DPRINTFN(3,("uhci port %d iteration %u, status = 0x%04x\n", - index, lim, x)); - - if (!(x & UHCI_PORTSC_CCS)) { - /* - * No device is connected (or was disconnected - * during reset). Consider the port reset. - * The delay must be long enough to ensure on - * the initial iteration that the device - * connection will have been registered. 50ms - * appears to be sufficient, but 20ms is not. - */ - DPRINTFN(3,("uhci port %d loop %u, device detached\n", - index, lim)); - break; - } - - if (x & (UHCI_PORTSC_POEDC | UHCI_PORTSC_CSC)) { - /* - * Port enabled changed and/or connection - * status changed were set. Reset either or - * both raised flags (by writing a 1 to that - * bit), and wait again for state to settle. - */ - UWRITE2(sc, port, URWMASK(x) | - (x & (UHCI_PORTSC_POEDC | UHCI_PORTSC_CSC))); - continue; - } - - if (x & UHCI_PORTSC_PE) - /* Port is enabled */ - break; - - UWRITE2(sc, port, URWMASK(x) | UHCI_PORTSC_PE); - } - - DPRINTFN(3,("uhci port %d reset, status2 = 0x%04x\n", - index, UREAD2(sc, port))); - - if (lim <= 0) { - DPRINTFN(1,("uhci port %d reset timed out\n", index)); - return (USBD_TIMEOUT); - } - - sc->sc_isreset = 1; - return (USBD_NORMAL_COMPLETION); -} - -/* - * Simulate a hardware hub by handling all the necessary requests. - */ -usbd_status -uhci_root_ctrl_transfer(usbd_xfer_handle xfer) -{ - usbd_status err; - - /* Insert last in queue. */ - err = usb_insert_transfer(xfer); - if (err) - return (err); - - /* - * Pipe isn't running (otherwise err would be USBD_INPROG), - * so start it first. - */ - return (uhci_root_ctrl_start(STAILQ_FIRST(&xfer->pipe->queue))); -} - -usbd_status -uhci_root_ctrl_start(usbd_xfer_handle xfer) -{ - uhci_softc_t *sc = (uhci_softc_t *)xfer->pipe->device->bus; - usb_device_request_t *req; - void *buf = NULL; - int port, x; - int len, value, index, status, change, l, totlen = 0; - usb_port_status_t ps; - usbd_status err; - - if (sc->sc_dying) - return (USBD_IOERROR); - -#ifdef DIAGNOSTIC - if (!(xfer->rqflags & URQ_REQUEST)) - panic("uhci_root_ctrl_transfer: not a request"); -#endif - req = &xfer->request; - - DPRINTFN(2,("uhci_root_ctrl_control type=0x%02x request=%02x\n", - req->bmRequestType, req->bRequest)); - - len = UGETW(req->wLength); - value = UGETW(req->wValue); - index = UGETW(req->wIndex); - - if (len != 0) - buf = KERNADDR(&xfer->dmabuf, 0); - -#define C(x,y) ((x) | ((y) << 8)) - switch(C(req->bRequest, req->bmRequestType)) { - case C(UR_CLEAR_FEATURE, UT_WRITE_DEVICE): - case C(UR_CLEAR_FEATURE, UT_WRITE_INTERFACE): - case C(UR_CLEAR_FEATURE, UT_WRITE_ENDPOINT): - /* - * DEVICE_REMOTE_WAKEUP and ENDPOINT_HALT are no-ops - * for the integrated root hub. - */ - break; - case C(UR_GET_CONFIG, UT_READ_DEVICE): - if (len > 0) { - *(u_int8_t *)buf = sc->sc_conf; - totlen = 1; - } - break; - case C(UR_GET_DESCRIPTOR, UT_READ_DEVICE): - DPRINTFN(2,("uhci_root_ctrl_control wValue=0x%04x\n", value)); - switch(value >> 8) { - case UDESC_DEVICE: - if ((value & 0xff) != 0) { - err = USBD_IOERROR; - goto ret; - } - totlen = l = min(len, USB_DEVICE_DESCRIPTOR_SIZE); - USETW(uhci_devd.idVendor, sc->sc_id_vendor); - memcpy(buf, &uhci_devd, l); - break; - case UDESC_CONFIG: - if ((value & 0xff) != 0) { - err = USBD_IOERROR; - goto ret; - } - totlen = l = min(len, USB_CONFIG_DESCRIPTOR_SIZE); - memcpy(buf, &uhci_confd, l); - buf = (char *)buf + l; - len -= l; - l = min(len, USB_INTERFACE_DESCRIPTOR_SIZE); - totlen += l; - memcpy(buf, &uhci_ifcd, l); - buf = (char *)buf + l; - len -= l; - l = min(len, USB_ENDPOINT_DESCRIPTOR_SIZE); - totlen += l; - memcpy(buf, &uhci_endpd, l); - break; - case UDESC_STRING: - if (len == 0) - break; - *(u_int8_t *)buf = 0; - totlen = 1; - switch (value & 0xff) { - case 1: /* Vendor */ - totlen = uhci_str(buf, len, sc->sc_vendor); - break; - case 2: /* Product */ - totlen = uhci_str(buf, len, "UHCI root hub"); - break; - } - break; - default: - err = USBD_IOERROR; - goto ret; - } - break; - case C(UR_GET_INTERFACE, UT_READ_INTERFACE): - if (len > 0) { - *(u_int8_t *)buf = 0; - totlen = 1; - } - break; - case C(UR_GET_STATUS, UT_READ_DEVICE): - if (len > 1) { - USETW(((usb_status_t *)buf)->wStatus,UDS_SELF_POWERED); - totlen = 2; - } - break; - case C(UR_GET_STATUS, UT_READ_INTERFACE): - case C(UR_GET_STATUS, UT_READ_ENDPOINT): - if (len > 1) { - USETW(((usb_status_t *)buf)->wStatus, 0); - totlen = 2; - } - break; - case C(UR_SET_ADDRESS, UT_WRITE_DEVICE): - if (value >= USB_MAX_DEVICES) { - err = USBD_IOERROR; - goto ret; - } - sc->sc_addr = value; - break; - case C(UR_SET_CONFIG, UT_WRITE_DEVICE): - if (value != 0 && value != 1) { - err = USBD_IOERROR; - goto ret; - } - sc->sc_conf = value; - break; - case C(UR_SET_DESCRIPTOR, UT_WRITE_DEVICE): - break; - case C(UR_SET_FEATURE, UT_WRITE_DEVICE): - case C(UR_SET_FEATURE, UT_WRITE_INTERFACE): - case C(UR_SET_FEATURE, UT_WRITE_ENDPOINT): - err = USBD_IOERROR; - goto ret; - case C(UR_SET_INTERFACE, UT_WRITE_INTERFACE): - break; - case C(UR_SYNCH_FRAME, UT_WRITE_ENDPOINT): - break; - /* Hub requests */ - case C(UR_CLEAR_FEATURE, UT_WRITE_CLASS_DEVICE): - break; - case C(UR_CLEAR_FEATURE, UT_WRITE_CLASS_OTHER): - DPRINTFN(3, ("uhci_root_ctrl_control: UR_CLEAR_PORT_FEATURE " - "port=%d feature=%d\n", - index, value)); - if (index == 1) - port = UHCI_PORTSC1; - else if (index == 2) - port = UHCI_PORTSC2; - else { - err = USBD_IOERROR; - goto ret; - } - switch(value) { - case UHF_PORT_ENABLE: - x = URWMASK(UREAD2(sc, port)); - UWRITE2(sc, port, x & ~UHCI_PORTSC_PE); - break; - case UHF_PORT_SUSPEND: - x = URWMASK(UREAD2(sc, port)); - UWRITE2(sc, port, x & ~UHCI_PORTSC_SUSP); - break; - case UHF_PORT_RESET: - x = URWMASK(UREAD2(sc, port)); - UWRITE2(sc, port, x & ~UHCI_PORTSC_PR); - break; - case UHF_C_PORT_CONNECTION: - x = URWMASK(UREAD2(sc, port)); - UWRITE2(sc, port, x | UHCI_PORTSC_CSC); - break; - case UHF_C_PORT_ENABLE: - x = URWMASK(UREAD2(sc, port)); - UWRITE2(sc, port, x | UHCI_PORTSC_POEDC); - break; - case UHF_C_PORT_OVER_CURRENT: - x = URWMASK(UREAD2(sc, port)); - UWRITE2(sc, port, x | UHCI_PORTSC_OCIC); - break; - case UHF_C_PORT_RESET: - sc->sc_isreset = 0; - err = USBD_NORMAL_COMPLETION; - goto ret; - case UHF_PORT_CONNECTION: - case UHF_PORT_OVER_CURRENT: - case UHF_PORT_POWER: - case UHF_PORT_LOW_SPEED: - case UHF_C_PORT_SUSPEND: - default: - err = USBD_IOERROR; - goto ret; - } - break; - case C(UR_GET_BUS_STATE, UT_READ_CLASS_OTHER): - if (index == 1) - port = UHCI_PORTSC1; - else if (index == 2) - port = UHCI_PORTSC2; - else { - err = USBD_IOERROR; - goto ret; - } - if (len > 0) { - *(u_int8_t *)buf = - (UREAD2(sc, port) & UHCI_PORTSC_LS) >> - UHCI_PORTSC_LS_SHIFT; - totlen = 1; - } - break; - case C(UR_GET_DESCRIPTOR, UT_READ_CLASS_DEVICE): - if ((value & 0xff) != 0) { - err = USBD_IOERROR; - goto ret; - } - l = min(len, USB_HUB_DESCRIPTOR_SIZE); - totlen = l; - memcpy(buf, &uhci_hubd_piix, l); - break; - case C(UR_GET_STATUS, UT_READ_CLASS_DEVICE): - if (len != 4) { - err = USBD_IOERROR; - goto ret; - } - memset(buf, 0, len); - totlen = len; - break; - case C(UR_GET_STATUS, UT_READ_CLASS_OTHER): - if (index == 1) - port = UHCI_PORTSC1; - else if (index == 2) - port = UHCI_PORTSC2; - else { - err = USBD_IOERROR; - goto ret; - } - if (len != 4) { - err = USBD_IOERROR; - goto ret; - } - x = UREAD2(sc, port); - status = change = 0; - if (x & UHCI_PORTSC_CCS) - status |= UPS_CURRENT_CONNECT_STATUS; - if (x & UHCI_PORTSC_CSC) - change |= UPS_C_CONNECT_STATUS; - if (x & UHCI_PORTSC_PE) - status |= UPS_PORT_ENABLED; - if (x & UHCI_PORTSC_POEDC) - change |= UPS_C_PORT_ENABLED; - if (x & UHCI_PORTSC_OCI) - status |= UPS_OVERCURRENT_INDICATOR; - if (x & UHCI_PORTSC_OCIC) - change |= UPS_C_OVERCURRENT_INDICATOR; - if (x & UHCI_PORTSC_SUSP) - status |= UPS_SUSPEND; - if (x & UHCI_PORTSC_LSDA) - status |= UPS_LOW_SPEED; - status |= UPS_PORT_POWER; - if (sc->sc_isreset) - change |= UPS_C_PORT_RESET; - USETW(ps.wPortStatus, status); - USETW(ps.wPortChange, change); - l = min(len, sizeof ps); - memcpy(buf, &ps, l); - totlen = l; - break; - case C(UR_SET_DESCRIPTOR, UT_WRITE_CLASS_DEVICE): - err = USBD_IOERROR; - goto ret; - case C(UR_SET_FEATURE, UT_WRITE_CLASS_DEVICE): - break; - case C(UR_SET_FEATURE, UT_WRITE_CLASS_OTHER): - if (index == 1) - port = UHCI_PORTSC1; - else if (index == 2) - port = UHCI_PORTSC2; - else { - err = USBD_IOERROR; - goto ret; - } - switch(value) { - case UHF_PORT_ENABLE: - x = URWMASK(UREAD2(sc, port)); - UWRITE2(sc, port, x | UHCI_PORTSC_PE); - break; - case UHF_PORT_SUSPEND: - x = URWMASK(UREAD2(sc, port)); - UWRITE2(sc, port, x | UHCI_PORTSC_SUSP); - break; - case UHF_PORT_RESET: - err = uhci_portreset(sc, index); - goto ret; - case UHF_PORT_POWER: - /* Pretend we turned on power */ - err = USBD_NORMAL_COMPLETION; - goto ret; - case UHF_C_PORT_CONNECTION: - case UHF_C_PORT_ENABLE: - case UHF_C_PORT_OVER_CURRENT: - case UHF_PORT_CONNECTION: - case UHF_PORT_OVER_CURRENT: - case UHF_PORT_LOW_SPEED: - case UHF_C_PORT_SUSPEND: - case UHF_C_PORT_RESET: - default: - err = USBD_IOERROR; - goto ret; - } - break; - default: - err = USBD_IOERROR; - goto ret; - } - xfer->actlen = totlen; - err = USBD_NORMAL_COMPLETION; - ret: - xfer->status = err; - crit_enter(); - usb_transfer_complete(xfer); - crit_exit(); - return (USBD_IN_PROGRESS); -} - -/* Abort a root control request. */ -void -uhci_root_ctrl_abort(usbd_xfer_handle xfer) -{ - /* Nothing to do, all transfers are synchronous. */ -} - -/* Close the root pipe. */ -void -uhci_root_ctrl_close(usbd_pipe_handle pipe) -{ - DPRINTF(("uhci_root_ctrl_close\n")); -} - -/* Abort a root interrupt request. */ -void -uhci_root_intr_abort(usbd_xfer_handle xfer) -{ - uhci_softc_t *sc = (uhci_softc_t *)xfer->pipe->device->bus; - - callout_stop(&sc->sc_poll_handle); - sc->sc_intr_xfer = NULL; - - if (xfer->pipe->intrxfer == xfer) { - DPRINTF(("uhci_root_intr_abort: remove\n")); - xfer->pipe->intrxfer = 0; - } - xfer->status = USBD_CANCELLED; -#ifdef DIAGNOSTIC - UXFER(xfer)->iinfo.isdone = 1; -#endif - usb_transfer_complete(xfer); -} - -usbd_status -uhci_root_intr_transfer(usbd_xfer_handle xfer) -{ - usbd_status err; - - /* Insert last in queue. */ - err = usb_insert_transfer(xfer); - if (err) - return (err); - - /* - * Pipe isn't running (otherwise err would be USBD_INPROG), - * so start it first. - */ - return (uhci_root_intr_start(STAILQ_FIRST(&xfer->pipe->queue))); -} - -/* Start a transfer on the root interrupt pipe */ -usbd_status -uhci_root_intr_start(usbd_xfer_handle xfer) -{ - usbd_pipe_handle pipe = xfer->pipe; - uhci_softc_t *sc = (uhci_softc_t *)pipe->device->bus; - - DPRINTFN(3, ("uhci_root_intr_start: xfer=%p len=%d flags=%d\n", - xfer, xfer->length, xfer->flags)); - - if (sc->sc_dying) - return (USBD_IOERROR); - - sc->sc_ival = MS_TO_TICKS(xfer->pipe->endpoint->edesc->bInterval); - callout_reset(&sc->sc_poll_handle, sc->sc_ival, uhci_poll_hub, xfer); - sc->sc_intr_xfer = xfer; - return (USBD_IN_PROGRESS); -} - -/* Close the root interrupt pipe. */ -void -uhci_root_intr_close(usbd_pipe_handle pipe) -{ - uhci_softc_t *sc = (uhci_softc_t *)pipe->device->bus; - - callout_stop(&sc->sc_poll_handle); - sc->sc_intr_xfer = NULL; - DPRINTF(("uhci_root_intr_close\n")); -} diff --git a/sys/bus/usb/uhci_pci.c b/sys/bus/usb/uhci_pci.c deleted file mode 100644 index 6a4892afa9..0000000000 --- a/sys/bus/usb/uhci_pci.c +++ /dev/null @@ -1,496 +0,0 @@ -/* - * Copyright (c) 1998 The NetBSD Foundation, Inc. - * All rights reserved. - * - * This code is derived from software contributed to The NetBSD Foundation - * by Lennart Augustsson (augustss@carlstedt.se) at - * Carlstedt Research & Technology. - * - * 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. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the NetBSD - * Foundation, Inc. and its contributors. - * 4. Neither the name of The NetBSD Foundation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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: src/sys/dev/usb/uhci_pci.c,v 1.57 2005/03/01 07:50:11 imp Exp $ - */ - -/* Universal Host Controller Interface - * - * UHCI spec: http://www.intel.com/ - */ - -/* The low level controller code for UHCI has been split into - * PCI probes and UHCI specific code. This was done to facilitate the - * sharing of code between *BSD's - */ - -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include -#include -#include - -#include -#include - -#define PCI_UHCI_VENDORID_INTEL 0x8086 -#define PCI_UHCI_VENDORID_VIA 0x1106 - -#define PCI_UHCI_DEVICEID_PIIX3 0x70208086 -static const char *uhci_device_piix3 = "Intel 82371SB (PIIX3) USB controller"; - -#define PCI_UHCI_DEVICEID_PIIX4 0x71128086 -#define PCI_UHCI_DEVICEID_PIIX4E 0x71128086 /* no separate stepping */ -static const char *uhci_device_piix4 = "Intel 82371AB/EB (PIIX4) USB controller"; - -#define PCI_UHCI_DEVICEID_ICH 0x24128086 -static const char *uhci_device_ich = "Intel 82801AA (ICH) USB controller"; - -#define PCI_UHCI_DEVICEID_ICH0 0x24228086 -static const char *uhci_device_ich0 = "Intel 82801AB (ICH0) USB controller"; - -#define PCI_UHCI_DEVICEID_ICH2_A 0x24428086 -static const char *uhci_device_ich2_a = "Intel 82801BA/BAM (ICH2) USB controller USB-A"; - -#define PCI_UHCI_DEVICEID_ICH2_B 0x24448086 -static const char *uhci_device_ich2_b = "Intel 82801BA/BAM (ICH2) USB controller USB-B"; - -#define PCI_UHCI_DEVICEID_ICH3_A 0x24828086 -static const char *uhci_device_ich3_a = "Intel 82801CA/CAM (ICH3) USB controller USB-A"; - -#define PCI_UHCI_DEVICEID_ICH3_B 0x24848086 -static const char *uhci_device_ich3_b = "Intel 82801CA/CAM (ICH3) USB controller USB-B"; - -#define PCI_UHCI_DEVICEID_ICH3_C 0x24878086 -static const char *uhci_device_ich3_c = "Intel 82801CA/CAM (ICH3) USB controller USB-C"; - -#define PCI_UHCI_DEVICEID_ICH4_A 0x24c28086 -static const char *uhci_device_ich4_a = "Intel 82801DB (ICH4) USB controller USB-A"; - -#define PCI_UHCI_DEVICEID_ICH4_B 0x24c48086 -static const char *uhci_device_ich4_b = "Intel 82801DB (ICH4) USB controller USB-B"; - -#define PCI_UHCI_DEVICEID_ICH4_C 0x24c78086 -static const char *uhci_device_ich4_c = "Intel 82801DB (ICH4) USB controller USB-C"; - -#define PCI_UHCI_DEVICEID_ICH5_A 0x24d28086 -static const char *uhci_device_ich5_a = "Intel 82801EB (ICH5) USB controller USB-A"; - -#define PCI_UHCI_DEVICEID_ICH5_B 0x24d48086 -static const char *uhci_device_ich5_b = "Intel 82801EB (ICH5) USB controller USB-B"; - -#define PCI_UHCI_DEVICEID_ICH5_C 0x24d78086 -static const char *uhci_device_ich5_c = "Intel 82801EB (ICH5) USB controller USB-C"; - -#define PCI_UHCI_DEVICEID_ICH5_D 0x24de8086 -static const char *uhci_device_ich5_d = "Intel 82801EB (ICH5) USB controller USB-D"; - -#define PCI_UHCI_DEVICEID_ICH6_A 0x26588086 -static const char *uhci_device_ich6_a = "Intel 82801FB/FR/FW/FRW (ICH6) USB controller USB-A"; - -#define PCI_UHCI_DEVICEID_ICH6_B 0x26598086 -static const char *uhci_device_ich6_b = "Intel 82801FB/FR/FW/FRW (ICH6) USB controller USB-B"; - -#define PCI_UHCI_DEVICEID_ICH6_C 0x265a8086 -static const char *uhci_device_ich6_c = "Intel 82801FB/FR/FW/FRW (ICH6) USB controller USB-C"; - -#define PCI_UHCI_DEVICEID_ICH6_D 0x265b8086 -static const char *uhci_device_ich6_d = "Intel 82801FB/FR/FW/FRW (ICH6) USB controller USB-D"; - -#define PCI_UHCI_DEVICEID_63XXESB_1 0x26888086 -static const char *uhci_device_esb_1 = "Intel 631XESB/632XESB/3100 USB controller USB-1"; - -#define PCI_UHCI_DEVICEID_63XXESB_2 0x26898086 -static const char *uhci_device_esb_2 = "Intel 631XESB/632XESB/3100 USB controller USB-2"; - -#define PCI_UHCI_DEVICEID_63XXESB_3 0x268a8086 -static const char *uhci_device_esb_3 = "Intel 631XESB/632XESB/3100 USB controller USB-3"; - -#define PCI_UHCI_DEVICEID_63XXESB_4 0x268b8086 -static const char *uhci_device_esb_4 = "Intel 631XESB/632XESB/3100 USB controller USB-4"; - -#define PCI_UHCI_DEVICEID_ICH7_A 0x27c88086 -#define PCI_UHCI_DEVICEID_ICH7_B 0x27c98086 -#define PCI_UHCI_DEVICEID_ICH7_C 0x27ca8086 -#define PCI_UHCI_DEVICEID_ICH7_D 0x27cb8086 -static const char *uhci_device_ich7 = "Intel 82801G (ICH7) USB controller"; - -#define PCI_UHCI_DEVICEID_ICH8_A 0x28308086 -static const char *uhci_device_ich8_a = "Intel 82801H (ICH8) USB controller USB-A"; - -#define PCI_UHCI_DEVICEID_ICH8_B 0x28318086 -static const char *uhci_device_ich8_b = "Intel 82801H (ICH8) USB controller USB-B"; - -#define PCI_UHCI_DEVICEID_ICH8_C 0x28328086 -static const char *uhci_device_ich8_c = "Intel 82801H (ICH8) USB controller USB-C"; - -#define PCI_UHCI_DEVICEID_ICH8_D 0x28348086 -static const char *uhci_device_ich8_d = "Intel 82801H (ICH8) USB controller USB-D"; - -#define PCI_UHCI_DEVICEID_ICH8_E 0x28358086 -static const char *uhci_device_ich8_e = "Intel 82801H (ICH8) USB controller USB-E"; - -#define PCI_UHCI_DEVICEID_ICH9_A 0x29348086 -#define PCI_UHCI_DEVICEID_ICH9_B 0x29358086 -#define PCI_UHCI_DEVICEID_ICH9_C 0x29368086 -#define PCI_UHCI_DEVICEID_ICH9_D 0x29378086 -#define PCI_UHCI_DEVICEID_ICH9_E 0x29388086 -#define PCI_UHCI_DEVICEID_ICH9_F 0x29398086 -static const char *uhci_device_ich9 = "Intel 82801I (ICH9) USB controller"; - -#define PCI_UHCI_DEVICEID_440MX 0x719a8086 -static const char *uhci_device_440mx = "Intel 82443MX USB controller"; - -#define PCI_UHCI_DEVICEID_460GX 0x76028086 -static const char *uhci_device_460gx = "Intel 82372FB/82468GX USB controller"; - -#define PCI_UHCI_DEVICEID_VT83C572 0x30381106 -static const char *uhci_device_vt83c572 = "VIA 83C572 USB controller"; - -static const char *uhci_device_generic = "UHCI (generic) USB controller"; - -#define PCI_UHCI_BASE_REG 0x20 - - -static int uhci_pci_attach(device_t self); -static int uhci_pci_detach(device_t self); -static int uhci_pci_suspend(device_t self); -static int uhci_pci_resume(device_t self); - - -static int -uhci_pci_suspend(device_t self) -{ - uhci_softc_t *sc = device_get_softc(self); - int err; - - err = bus_generic_suspend(self); - if (err) - return err; - uhci_power(PWR_SUSPEND, sc); - - return 0; -} - -static int -uhci_pci_resume(device_t self) -{ - uhci_softc_t *sc = device_get_softc(self); - - pci_write_config(self, PCI_LEGSUP, PCI_LEGSUP_USBPIRQDEN, 2); - - uhci_power(PWR_RESUME, sc); - bus_generic_resume(self); - - return 0; -} - -static const char * -uhci_pci_match(device_t self) -{ - u_int32_t device_id = pci_get_devid(self); - - if (device_id == PCI_UHCI_DEVICEID_PIIX3) { - return (uhci_device_piix3); - } else if (device_id == PCI_UHCI_DEVICEID_PIIX4) { - return (uhci_device_piix4); - } else if (device_id == PCI_UHCI_DEVICEID_ICH) { - return (uhci_device_ich); - } else if (device_id == PCI_UHCI_DEVICEID_ICH0) { - return (uhci_device_ich0); - } else if (device_id == PCI_UHCI_DEVICEID_ICH2_A) { - return (uhci_device_ich2_a); - } else if (device_id == PCI_UHCI_DEVICEID_ICH2_B) { - return (uhci_device_ich2_b); - } else if (device_id == PCI_UHCI_DEVICEID_ICH3_A) { - return (uhci_device_ich3_a); - } else if (device_id == PCI_UHCI_DEVICEID_ICH3_B) { - return (uhci_device_ich3_b); - } else if (device_id == PCI_UHCI_DEVICEID_ICH3_C) { - return (uhci_device_ich3_c); - } else if (device_id == PCI_UHCI_DEVICEID_ICH4_A) { - return (uhci_device_ich4_a); - } else if (device_id == PCI_UHCI_DEVICEID_ICH4_B) { - return (uhci_device_ich4_b); - } else if (device_id == PCI_UHCI_DEVICEID_ICH4_C) { - return (uhci_device_ich4_c); - } else if (device_id == PCI_UHCI_DEVICEID_ICH5_A) { - return (uhci_device_ich5_a); - } else if (device_id == PCI_UHCI_DEVICEID_ICH5_B) { - return (uhci_device_ich5_b); - } else if (device_id == PCI_UHCI_DEVICEID_ICH5_C) { - return (uhci_device_ich5_c); - } else if (device_id == PCI_UHCI_DEVICEID_ICH5_D) { - return (uhci_device_ich5_d); - } else if (device_id == PCI_UHCI_DEVICEID_ICH6_A) { - return (uhci_device_ich6_a); - } else if (device_id == PCI_UHCI_DEVICEID_ICH6_B) { - return (uhci_device_ich6_b); - } else if (device_id == PCI_UHCI_DEVICEID_ICH6_C) { - return (uhci_device_ich6_c); - } else if (device_id == PCI_UHCI_DEVICEID_ICH6_D) { - return (uhci_device_ich6_d); - } else if (device_id == PCI_UHCI_DEVICEID_63XXESB_1) { - return (uhci_device_esb_1); - } else if (device_id == PCI_UHCI_DEVICEID_63XXESB_2) { - return (uhci_device_esb_2); - } else if (device_id == PCI_UHCI_DEVICEID_63XXESB_3) { - return (uhci_device_esb_3); - } else if (device_id == PCI_UHCI_DEVICEID_63XXESB_4) { - return (uhci_device_esb_4); - } else if (device_id == PCI_UHCI_DEVICEID_ICH7_A) { - return (uhci_device_ich7); - } else if (device_id == PCI_UHCI_DEVICEID_ICH7_B) { - return (uhci_device_ich7); - } else if (device_id == PCI_UHCI_DEVICEID_ICH7_C) { - return (uhci_device_ich7); - } else if (device_id == PCI_UHCI_DEVICEID_ICH7_D) { - return (uhci_device_ich7); - } else if (device_id == PCI_UHCI_DEVICEID_ICH8_A) { - return (uhci_device_ich8_a); - } else if (device_id == PCI_UHCI_DEVICEID_ICH8_B) { - return (uhci_device_ich8_b); - } else if (device_id == PCI_UHCI_DEVICEID_ICH8_C) { - return (uhci_device_ich8_c); - } else if (device_id == PCI_UHCI_DEVICEID_ICH8_D) { - return (uhci_device_ich8_d); - } else if (device_id == PCI_UHCI_DEVICEID_ICH8_E) { - return (uhci_device_ich8_e); - } else if (device_id == PCI_UHCI_DEVICEID_ICH9_A) { - return (uhci_device_ich9); - } else if (device_id == PCI_UHCI_DEVICEID_ICH9_B) { - return (uhci_device_ich9); - } else if (device_id == PCI_UHCI_DEVICEID_ICH9_C) { - return (uhci_device_ich9); - } else if (device_id == PCI_UHCI_DEVICEID_ICH9_D) { - return (uhci_device_ich9); - } else if (device_id == PCI_UHCI_DEVICEID_ICH9_E) { - return (uhci_device_ich9); - } else if (device_id == PCI_UHCI_DEVICEID_ICH9_F) { - return (uhci_device_ich9); - } else if (device_id == PCI_UHCI_DEVICEID_440MX) { - return (uhci_device_440mx); - } else if (device_id == PCI_UHCI_DEVICEID_460GX) { - return (uhci_device_460gx); - } else if (device_id == PCI_UHCI_DEVICEID_VT83C572) { - return (uhci_device_vt83c572); - } else { - if (pci_get_class(self) == PCIC_SERIALBUS - && pci_get_subclass(self) == PCIS_SERIALBUS_USB - && pci_get_progif(self) == PCI_INTERFACE_UHCI) { - return (uhci_device_generic); - } - } - - return NULL; /* dunno... */ -} - -static int -uhci_pci_probe(device_t self) -{ - const char *desc = uhci_pci_match(self); - - if (desc) { - device_set_desc(self, desc); - return 0; - } else { - return ENXIO; - } -} - -static int -uhci_pci_attach(device_t self) -{ - uhci_softc_t *sc = device_get_softc(self); - int rid; - int err; - - pci_enable_busmaster(self); - - rid = PCI_UHCI_BASE_REG; - sc->io_res = bus_alloc_resource_any(self, SYS_RES_IOPORT, &rid, - RF_ACTIVE); - if (!sc->io_res) { - device_printf(self, "Could not map ports\n"); - return ENXIO; - } - sc->iot = rman_get_bustag(sc->io_res); - sc->ioh = rman_get_bushandle(sc->io_res); - - /* disable interrupts */ - bus_space_write_2(sc->iot, sc->ioh, UHCI_INTR, 0); - - rid = 0; - sc->irq_res = bus_alloc_resource_any(self, SYS_RES_IRQ, &rid, - RF_SHAREABLE | RF_ACTIVE); - if (sc->irq_res == NULL) { - device_printf(self, "Could not allocate irq\n"); - uhci_pci_detach(self); - return ENXIO; - } - sc->sc_bus.bdev = device_add_child(self, "usb", -1); - if (!sc->sc_bus.bdev) { - device_printf(self, "Could not add USB device\n"); - uhci_pci_detach(self); - return ENOMEM; - } - device_set_ivars(sc->sc_bus.bdev, &sc->sc_bus); - - /* uhci_pci_match must never return NULL if uhci_pci_probe succeeded */ - device_set_desc(sc->sc_bus.bdev, uhci_pci_match(self)); - switch (pci_get_vendor(self)) { - case PCI_UHCI_VENDORID_INTEL: - ksprintf(sc->sc_vendor, "Intel"); - break; - case PCI_UHCI_VENDORID_VIA: - ksprintf(sc->sc_vendor, "VIA"); - break; - default: - if (bootverbose) - device_printf(self, "(New UHCI DeviceId=0x%08x)\n", - pci_get_devid(self)); - ksprintf(sc->sc_vendor, "(0x%04x)", pci_get_vendor(self)); - } - - switch (pci_read_config(self, PCI_USBREV, 1) & PCI_USBREV_MASK) { - case PCI_USBREV_PRE_1_0: - sc->sc_bus.usbrev = USBREV_PRE_1_0; - break; - case PCI_USBREV_1_0: - sc->sc_bus.usbrev = USBREV_1_0; - break; - default: - sc->sc_bus.usbrev = USBREV_UNKNOWN; - break; - } - - err = bus_setup_intr(self, sc->irq_res, 0, - (driver_intr_t *) uhci_intr, sc, &sc->ih, NULL); - if (err) { - device_printf(self, "Could not setup irq, %d\n", err); - sc->ih = NULL; - uhci_pci_detach(self); - return ENXIO; - } - /* - * Set the PIRQD enable bit and switch off all the others. We don't - * want legacy support to interfere with us XXX Does this also mean - * that the BIOS won't touch the keyboard anymore if it is connected - * to the ports of the root hub? - */ -#ifdef USB_DEBUG - if (pci_read_config(self, PCI_LEGSUP, 2) != PCI_LEGSUP_USBPIRQDEN) - device_printf(self, "LegSup = 0x%04x\n", - pci_read_config(self, PCI_LEGSUP, 2)); -#endif - pci_write_config(self, PCI_LEGSUP, PCI_LEGSUP_USBPIRQDEN, 2); - - err = uhci_init(sc); - if (err == 0) - err = device_probe_and_attach(sc->sc_bus.bdev); - - if (err) { - device_printf(self, "USB init failed\n"); - uhci_pci_detach(self); - return EIO; - } - return 0; /* success */ -} - -int -uhci_pci_detach(device_t self) -{ - uhci_softc_t *sc = device_get_softc(self); - - if (sc->sc_flags & UHCI_SCFLG_DONEINIT) { - uhci_detach(sc, 0); - sc->sc_flags &= ~UHCI_SCFLG_DONEINIT; - } - - - if (sc->irq_res && sc->ih) { - int err = bus_teardown_intr(self, sc->irq_res, sc->ih); - - if (err) - /* XXX or should we panic? */ - device_printf(self, "Could not tear down irq, %d\n", - err); - sc->ih = NULL; - } - if (sc->sc_bus.bdev) { - device_delete_child(self, sc->sc_bus.bdev); - sc->sc_bus.bdev = NULL; - } - if (sc->irq_res) { - bus_release_resource(self, SYS_RES_IRQ, 0, sc->irq_res); - sc->irq_res = NULL; - } - if (sc->io_res) { - bus_release_resource(self, SYS_RES_IOPORT, PCI_UHCI_BASE_REG, - sc->io_res); - sc->io_res = NULL; - sc->iot = 0; - sc->ioh = 0; - } - return 0; -} - - -static device_method_t uhci_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, uhci_pci_probe), - DEVMETHOD(device_attach, uhci_pci_attach), - DEVMETHOD(device_detach, uhci_pci_detach), - DEVMETHOD(device_suspend, uhci_pci_suspend), - DEVMETHOD(device_resume, uhci_pci_resume), - DEVMETHOD(device_shutdown, bus_generic_shutdown), - - /* Bus interface */ - DEVMETHOD(bus_print_child, bus_generic_print_child), - - DEVMETHOD_END -}; - -static driver_t uhci_driver = { - "uhci", - uhci_methods, - sizeof(uhci_softc_t), -}; - -static devclass_t uhci_devclass; - -DRIVER_MODULE(uhci, pci, uhci_driver, uhci_devclass, NULL, NULL); -DRIVER_MODULE(uhci, cardbus, uhci_driver, uhci_devclass, NULL, NULL); diff --git a/sys/bus/usb/uhcireg.h b/sys/bus/usb/uhcireg.h deleted file mode 100644 index 06cf34b310..0000000000 --- a/sys/bus/usb/uhcireg.h +++ /dev/null @@ -1,194 +0,0 @@ -/* $NetBSD: uhcireg.h,v 1.15 2002/02/11 11:41:30 augustss Exp $ */ -/* $FreeBSD: src/sys/dev/usb/uhcireg.h,v 1.22 2005/01/06 01:43:28 imp Exp $ */ -/* $DragonFly: src/sys/bus/usb/uhcireg.h,v 1.5 2006/12/10 02:03:56 sephe Exp $ */ - -/* - * Copyright (c) 1998 The NetBSD Foundation, Inc. - * All rights reserved. - * - * This code is derived from software contributed to The NetBSD Foundation - * by Lennart Augustsson (lennart@augustsson.net) at - * Carlstedt Research & Technology. - * - * 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. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the NetBSD - * Foundation, Inc. and its contributors. - * 4. Neither the name of The NetBSD Foundation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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. - */ - -#ifndef _DEV_PCI_UHCIREG_H_ -#define _DEV_PCI_UHCIREG_H_ - -/*** PCI config registers ***/ - -#define PCI_USBREV 0x60 /* USB protocol revision */ -#define PCI_USBREV_MASK 0xff -#define PCI_USBREV_PRE_1_0 0x00 -#define PCI_USBREV_1_0 0x10 -#define PCI_USBREV_1_1 0x11 - -#define PCI_LEGSUP 0xc0 /* Legacy Support register */ -#define PCI_LEGSUP_USBPIRQDEN 0x2000 /* USB PIRQ D Enable */ - -#define PCI_CBIO 0x20 /* configuration base IO */ - -#define PCI_INTERFACE_UHCI 0x00 - -/*** UHCI registers ***/ - -#define UHCI_CMD 0x00 -#define UHCI_CMD_RS 0x0001 -#define UHCI_CMD_HCRESET 0x0002 -#define UHCI_CMD_GRESET 0x0004 -#define UHCI_CMD_EGSM 0x0008 -#define UHCI_CMD_FGR 0x0010 -#define UHCI_CMD_SWDBG 0x0020 -#define UHCI_CMD_CF 0x0040 -#define UHCI_CMD_MAXP 0x0080 - -#define UHCI_STS 0x02 -#define UHCI_STS_USBINT 0x0001 -#define UHCI_STS_USBEI 0x0002 -#define UHCI_STS_RD 0x0004 -#define UHCI_STS_HSE 0x0008 -#define UHCI_STS_HCPE 0x0010 -#define UHCI_STS_HCH 0x0020 -#define UHCI_STS_ALLINTRS 0x003f - -#define UHCI_INTR 0x04 -#define UHCI_INTR_TOCRCIE 0x0001 -#define UHCI_INTR_RIE 0x0002 -#define UHCI_INTR_IOCE 0x0004 -#define UHCI_INTR_SPIE 0x0008 - -#define UHCI_FRNUM 0x06 -#define UHCI_FRNUM_MASK 0x03ff - -#define UHCI_FLBASEADDR 0x08 - -#define UHCI_SOF 0x0c -#define UHCI_SOF_MASK 0x7f - -#define UHCI_PORTSC1 0x010 -#define UHCI_PORTSC2 0x012 -#define UHCI_PORTSC_CCS 0x0001 -#define UHCI_PORTSC_CSC 0x0002 -#define UHCI_PORTSC_PE 0x0004 -#define UHCI_PORTSC_POEDC 0x0008 -#define UHCI_PORTSC_LS 0x0030 -#define UHCI_PORTSC_LS_SHIFT 4 -#define UHCI_PORTSC_RD 0x0040 -#define UHCI_PORTSC_LSDA 0x0100 -#define UHCI_PORTSC_PR 0x0200 -#define UHCI_PORTSC_OCI 0x0400 -#define UHCI_PORTSC_OCIC 0x0800 -#define UHCI_PORTSC_SUSP 0x1000 - -#define URWMASK(x) \ - ((x) & (UHCI_PORTSC_SUSP | UHCI_PORTSC_PR | UHCI_PORTSC_RD | UHCI_PORTSC_PE)) - -#define UHCI_FRAMELIST_COUNT 1024 -#define UHCI_FRAMELIST_ALIGN 4096 - -#define UHCI_TD_ALIGN 16 -#define UHCI_QH_ALIGN 16 - -typedef u_int32_t uhci_physaddr_t; -#define UHCI_PTR_T 0x00000001 -#define UHCI_PTR_TD 0x00000000 -#define UHCI_PTR_QH 0x00000002 -#define UHCI_PTR_VF 0x00000004 - -/* - * Wait this long after a QH has been removed. This gives that HC a - * chance to stop looking at it before it's recycled. - */ -#define UHCI_QH_REMOVE_DELAY 5 - -/* - * The Queue Heads and Transfer Descriptors are accessed - * by both the CPU and the USB controller which run - * concurrently. This means that they have to be accessed - * with great care. As long as the data structures are - * not linked into the controller's frame list they cannot - * be accessed by it and anything goes. As soon as a - * TD is accessible by the controller it "owns" the td_status - * field; it will not be written by the CPU. Similarly - * the controller "owns" the qh_elink field. - */ - -typedef struct { - uhci_physaddr_t td_link; - u_int32_t td_status; -#define UHCI_TD_GET_ACTLEN(s) (((s) + 1) & 0x3ff) -#define UHCI_TD_ZERO_ACTLEN(t) ((t) | 0x3ff) -#define UHCI_TD_BITSTUFF 0x00020000 -#define UHCI_TD_CRCTO 0x00040000 -#define UHCI_TD_NAK 0x00080000 -#define UHCI_TD_BABBLE 0x00100000 -#define UHCI_TD_DBUFFER 0x00200000 -#define UHCI_TD_STALLED 0x00400000 -#define UHCI_TD_ACTIVE 0x00800000 -#define UHCI_TD_IOC 0x01000000 -#define UHCI_TD_IOS 0x02000000 -#define UHCI_TD_LS 0x04000000 -#define UHCI_TD_GET_ERRCNT(s) (((s) >> 27) & 3) -#define UHCI_TD_SET_ERRCNT(n) ((n) << 27) -#define UHCI_TD_SPD 0x20000000 - u_int32_t td_token; -#define UHCI_TD_PID_IN 0x00000069 -#define UHCI_TD_PID_OUT 0x000000e1 -#define UHCI_TD_PID_SETUP 0x0000002d -#define UHCI_TD_GET_PID(s) ((s) & 0xff) -#define UHCI_TD_SET_DEVADDR(a) ((a) << 8) -#define UHCI_TD_GET_DEVADDR(s) (((s) >> 8) & 0x7f) -#define UHCI_TD_SET_ENDPT(e) (((e)&0xf) << 15) -#define UHCI_TD_GET_ENDPT(s) (((s) >> 15) & 0xf) -#define UHCI_TD_SET_DT(t) ((t) << 19) -#define UHCI_TD_GET_DT(s) (((s) >> 19) & 1) -#define UHCI_TD_SET_MAXLEN(l) (((l)-1) << 21) -#define UHCI_TD_GET_MAXLEN(s) ((((s) >> 21) + 1) & 0x7ff) -#define UHCI_TD_MAXLEN_MASK 0xffe00000 - u_int32_t td_buffer; -} uhci_td_t; - -#define UHCI_TD_ERROR (UHCI_TD_BITSTUFF|UHCI_TD_CRCTO|UHCI_TD_BABBLE|UHCI_TD_DBUFFER|UHCI_TD_STALLED) - -#define UHCI_TD_SETUP(len, endp, dev) (UHCI_TD_SET_MAXLEN(len) | \ - UHCI_TD_SET_ENDPT(endp) | UHCI_TD_SET_DEVADDR(dev) | UHCI_TD_PID_SETUP) -#define UHCI_TD_OUT(len, endp, dev, dt) (UHCI_TD_SET_MAXLEN(len) | \ - UHCI_TD_SET_ENDPT(endp) | UHCI_TD_SET_DEVADDR(dev) | \ - UHCI_TD_PID_OUT | UHCI_TD_SET_DT(dt)) -#define UHCI_TD_IN(len, endp, dev, dt) (UHCI_TD_SET_MAXLEN(len) | \ - UHCI_TD_SET_ENDPT(endp) | UHCI_TD_SET_DEVADDR(dev) | UHCI_TD_PID_IN | \ - UHCI_TD_SET_DT(dt)) - -typedef struct { - uhci_physaddr_t qh_hlink; - uhci_physaddr_t qh_elink; -} uhci_qh_t; - -#endif /* _DEV_PCI_UHCIREG_H_ */ diff --git a/sys/bus/usb/uhcivar.h b/sys/bus/usb/uhcivar.h deleted file mode 100644 index e0f1779ee1..0000000000 --- a/sys/bus/usb/uhcivar.h +++ /dev/null @@ -1,201 +0,0 @@ -/* $NetBSD: uhcivar.h,v 1.33 2002/02/11 11:41:30 augustss Exp $ */ -/* $FreeBSD: src/sys/dev/usb/uhcivar.h,v 1.40 2005/03/19 19:08:46 iedowse Exp $ */ -/* $DragonFly: src/sys/bus/usb/uhcivar.h,v 1.9 2007/06/30 20:39:22 hasso Exp $ */ - -/* - * Copyright (c) 1998 The NetBSD Foundation, Inc. - * All rights reserved. - * - * This code is derived from software contributed to The NetBSD Foundation - * by Lennart Augustsson (lennart@augustsson.net) at - * Carlstedt Research & Technology. - * - * 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. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the NetBSD - * Foundation, Inc. and its contributors. - * 4. Neither the name of The NetBSD Foundation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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. - */ - -/* - * To avoid having 1024 TDs for each isochronous transfer we introduce - * a virtual frame list. Every UHCI_VFRAMELIST_COUNT entries in the real - * frame list points to a non-active TD. These, in turn, form the - * starts of the virtual frame list. This also has the advantage that it - * simplifies linking in/out of TDs/QHs in the schedule. - * Furthermore, initially each of the inactive TDs point to an inactive - * QH that forms the start of the interrupt traffic for that slot. - * Each of these QHs point to the same QH that is the start of control - * traffic. This QH points at another QH which is the start of the - * bulk traffic. - * - * UHCI_VFRAMELIST_COUNT should be a power of 2 and <= UHCI_FRAMELIST_COUNT. - */ -#define UHCI_VFRAMELIST_COUNT 128 - -typedef struct uhci_soft_qh uhci_soft_qh_t; -typedef struct uhci_soft_td uhci_soft_td_t; - -typedef union { - struct uhci_soft_qh *sqh; - struct uhci_soft_td *std; -} uhci_soft_td_qh_t; - -/* - * An interrupt info struct contains the information needed to - * execute a requested routine when the controller generates an - * interrupt. Since we cannot know which transfer generated - * the interrupt all structs are linked together so they can be - * searched at interrupt time. - */ -typedef struct uhci_intr_info { - struct uhci_softc *sc; - usbd_xfer_handle xfer; - uhci_soft_td_t *stdstart; - uhci_soft_td_t *stdend; - LIST_ENTRY(uhci_intr_info) list; -#ifdef DIAGNOSTIC - int isdone; -#endif -} uhci_intr_info_t; - -struct uhci_xfer { - struct usbd_xfer xfer; - uhci_intr_info_t iinfo; - struct usb_task abort_task; - int curframe; - u_int32_t uhci_xfer_flags; -}; - -#define UHCI_XFER_ABORTING 0x0001 /* xfer is aborting. */ -#define UHCI_XFER_ABORTWAIT 0x0002 /* abort completion is being awaited. */ - -#define UXFER(xfer) ((struct uhci_xfer *)(xfer)) - -/* - * Extra information that we need for a TD. - */ -struct uhci_soft_td { - uhci_td_t td; /* The real TD, must be first */ - uhci_soft_td_qh_t link; /* soft version of the td_link field */ - uhci_physaddr_t physaddr; /* TD's physical address. */ -}; -/* - * Make the size such that it is a multiple of UHCI_TD_ALIGN. This way - * we can pack a number of soft TD together and have the real TD well - * aligned. - * NOTE: Minimum size is 32 bytes. - */ -#define UHCI_STD_SIZE ((sizeof (struct uhci_soft_td) + UHCI_TD_ALIGN - 1) / UHCI_TD_ALIGN * UHCI_TD_ALIGN) -#define UHCI_STD_CHUNK (PAGE_SIZE / UHCI_STD_SIZE) - -/* - * Extra information that we need for a QH. - */ -struct uhci_soft_qh { - uhci_qh_t qh; /* The real QH, must be first */ - uhci_soft_qh_t *hlink; /* soft version of qh_hlink */ - uhci_soft_td_t *elink; /* soft version of qh_elink */ - uhci_physaddr_t physaddr; /* QH's physical address. */ - int pos; /* Timeslot position */ -}; -/* See comment about UHCI_STD_SIZE. */ -#define UHCI_SQH_SIZE ((sizeof (struct uhci_soft_qh) + UHCI_QH_ALIGN - 1) / UHCI_QH_ALIGN * UHCI_QH_ALIGN) -#define UHCI_SQH_CHUNK (PAGE_SIZE / UHCI_SQH_SIZE) - -/* - * Information about an entry in the virtual frame list. - */ -struct uhci_vframe { - uhci_soft_td_t *htd; /* pointer to dummy TD */ - uhci_soft_td_t *etd; /* pointer to last TD */ - uhci_soft_qh_t *hqh; /* pointer to dummy QH */ - uhci_soft_qh_t *eqh; /* pointer to last QH */ - u_int bandwidth; /* max bandwidth used by this frame */ -}; - -#define UHCI_SCFLG_DONEINIT 0x0001 /* uhci_init() done */ - -typedef struct uhci_softc { - struct usbd_bus sc_bus; /* base device */ - int sc_flags; - bus_space_tag_t iot; - bus_space_handle_t ioh; - bus_size_t sc_size; - void *ih; - - struct resource *io_res; - struct resource *irq_res; - - uhci_physaddr_t *sc_pframes; - usb_dma_t sc_dma; - struct uhci_vframe sc_vframes[UHCI_VFRAMELIST_COUNT]; - - uhci_soft_qh_t *sc_lctl_start; /* dummy QH for low speed control */ - uhci_soft_qh_t *sc_lctl_end; /* last control QH */ - uhci_soft_qh_t *sc_hctl_start; /* dummy QH for high speed control */ - uhci_soft_qh_t *sc_hctl_end; /* last control QH */ - uhci_soft_qh_t *sc_bulk_start; /* dummy QH for bulk */ - uhci_soft_qh_t *sc_bulk_end; /* last bulk transfer */ - uhci_soft_qh_t *sc_last_qh; /* dummy QH at the end */ - u_int32_t sc_loops; /* number of QHs that wants looping */ - - uhci_soft_td_t *sc_freetds; /* TD free list */ - uhci_soft_qh_t *sc_freeqhs; /* QH free list */ - - STAILQ_HEAD(, usbd_xfer) sc_free_xfers; /* free xfers */ - - u_int8_t sc_addr; /* device address */ - u_int8_t sc_conf; /* device configuration */ - - u_int8_t sc_saved_sof; - u_int16_t sc_saved_frnum; - -#ifdef USB_USE_SOFTINTR - char sc_softwake; -#endif /* USB_USE_SOFTINTR */ - - char sc_isreset; - char sc_suspend; - char sc_dying; - - LIST_HEAD(, uhci_intr_info) sc_intrhead; - - /* Info for the root hub interrupt channel. */ - int sc_ival; /* time between root hub intrs */ - usbd_xfer_handle sc_intr_xfer; /* root hub interrupt transfer */ - struct callout sc_poll_handle; - - char sc_vendor[16]; /* vendor string for root hub */ - int sc_id_vendor; /* vendor ID for root hub */ -} uhci_softc_t; - -usbd_status uhci_init(uhci_softc_t *); -int uhci_intr(void *); -int uhci_detach(uhci_softc_t *, int); - -void uhci_shutdown(void *v); -void uhci_power(int state, void *priv); - diff --git a/sys/bus/usb/uhub.c b/sys/bus/usb/uhub.c deleted file mode 100644 index 8d56d8da4e..0000000000 --- a/sys/bus/usb/uhub.c +++ /dev/null @@ -1,739 +0,0 @@ -/* $NetBSD: uhub.c,v 1.68 2004/06/29 06:30:05 mycroft Exp $ */ -/* $FreeBSD: src/sys/dev/usb/uhub.c,v 1.69.2.1 2005/12/18 15:51:31 iedowse Exp $ */ - -/* - * Copyright (c) 1998 The NetBSD Foundation, Inc. - * All rights reserved. - * - * This code is derived from software contributed to The NetBSD Foundation - * by Lennart Augustsson (lennart@augustsson.net) at - * Carlstedt Research & Technology. - * - * 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. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the NetBSD - * Foundation, Inc. and its contributors. - * 4. Neither the name of The NetBSD Foundation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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. - */ - -/* - * USB spec: http://www.usb.org/developers/docs/usbspec.zip - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#define UHUB_INTR_INTERVAL 255 /* ms */ - -#ifdef USB_DEBUG -#define DPRINTF(x) if (uhubdebug) kprintf x -#define DPRINTFN(n,x) if (uhubdebug>(n)) kprintf x -int uhubdebug = 0; -SYSCTL_NODE(_hw_usb, OID_AUTO, uhub, CTLFLAG_RW, 0, "USB uhub"); -SYSCTL_INT(_hw_usb_uhub, OID_AUTO, debug, CTLFLAG_RW, - &uhubdebug, 0, "uhub debug level"); -#else -#define DPRINTF(x) -#define DPRINTFN(n,x) -#endif - -struct uhub_softc { - usbd_device_handle sc_hub; /* USB device */ - usbd_pipe_handle sc_ipipe; /* interrupt pipe */ - u_int8_t sc_status[1]; /* XXX more ports */ - u_char sc_running; -}; -#define UHUB_PROTO(sc) ((sc)->sc_hub->ddesc.bDeviceProtocol) -#define UHUB_IS_HIGH_SPEED(sc) (UHUB_PROTO(sc) != UDPROTO_FSHUB) -#define UHUB_IS_SINGLE_TT(sc) (UHUB_PROTO(sc) == UDPROTO_HSHUBSTT) - -static usbd_status uhub_explore(usbd_device_handle hub); -static void uhub_intr(usbd_xfer_handle, usbd_private_handle,usbd_status); - -static bus_child_detached_t uhub_child_detached; -static bus_child_location_str_t uhub_child_location_str; -static bus_child_pnpinfo_str_t uhub_child_pnpinfo_str; - -/* - * We need two attachment points: - * hub to usb and hub to hub - * Every other driver only connects to hubs - */ - -static device_probe_t uhub_match; -static device_attach_t uhub_attach; -static device_detach_t uhub_detach; - -static devclass_t uhub_devclass; - -static kobj_method_t uhub_methods[] = { - DEVMETHOD(device_probe, uhub_match), - DEVMETHOD(device_attach, uhub_attach), - DEVMETHOD(device_detach, uhub_detach), - DEVMETHOD(bus_child_detached, uhub_child_detached), - DEVMETHOD(bus_child_pnpinfo_str, uhub_child_pnpinfo_str), - DEVMETHOD(bus_child_location_str, uhub_child_location_str), - DEVMETHOD(bus_driver_added, bus_generic_driver_added), - DEVMETHOD(device_suspend, bus_generic_suspend), - DEVMETHOD(device_resume, bus_generic_resume), - DEVMETHOD(device_shutdown, bus_generic_shutdown), - DEVMETHOD_END -}; - -static driver_t uhub_driver = { - "uhub", - uhub_methods, - sizeof(struct uhub_softc) -}; - -MODULE_DEPEND(uhub, usb, 1, 1, 1); - -/* Create the driver instance for the hub connected to usb case. */ -devclass_t uhubroot_devclass; - -static device_method_t uhubroot_methods[] = { - DEVMETHOD(bus_child_detached, uhub_child_detached), - DEVMETHOD(bus_child_location_str, uhub_child_location_str), - DEVMETHOD(bus_child_pnpinfo_str, uhub_child_pnpinfo_str), - DEVMETHOD(bus_driver_added, bus_generic_driver_added), - - DEVMETHOD(device_probe, uhub_match), - DEVMETHOD(device_attach, uhub_attach), - DEVMETHOD(device_detach, uhub_detach), - DEVMETHOD(device_suspend, bus_generic_suspend), - DEVMETHOD(device_resume, bus_generic_resume), - DEVMETHOD(device_shutdown, bus_generic_shutdown), - DEVMETHOD_END -}; - -static driver_t uhubroot_driver = { - "uhub", - uhubroot_methods, - sizeof(struct uhub_softc) -}; - -static int -uhub_match(device_t self) -{ - struct usb_attach_arg *uaa = device_get_ivars(self); - usb_device_descriptor_t *dd = usbd_get_device_descriptor(uaa->device); - - DPRINTFN(5,("uhub_match, dd=%p\n", dd)); - /* - * The subclass for hubs seems to be 0 for some and 1 for others, - * so we just ignore the subclass. - */ - if (uaa->iface == NULL && dd->bDeviceClass == UDCLASS_HUB) - return (UMATCH_DEVCLASS_DEVSUBCLASS); - return (UMATCH_NONE); -} - -static int -uhub_attach(device_t self) -{ - struct uhub_softc *sc = device_get_softc(self); - struct usb_attach_arg *uaa = device_get_ivars(self); - usbd_device_handle dev = uaa->device; - usbd_status err; - struct usbd_hub *hub = NULL; - usb_device_request_t req; - usb_hub_descriptor_t hubdesc; - int p, port, nports, nremov, pwrdly; - usbd_interface_handle iface; - usb_endpoint_descriptor_t *ed; - struct usbd_tt *tts = NULL; - - DPRINTFN(1,("uhub_attach\n")); - sc->sc_hub = dev; - - if (dev->depth > 0 && UHUB_IS_HIGH_SPEED(sc)) { - device_printf(self, - "%s transaction translator%s\n", - UHUB_IS_SINGLE_TT(sc) ? "single" : "multiple", - UHUB_IS_SINGLE_TT(sc) ? "" : "s"); - } - err = usbd_set_config_index(dev, 0, 1); - if (err) { - DPRINTF(("%s: configuration failed, error=%s\n", - device_get_nameunit(self), usbd_errstr(err))); - return ENXIO; - } - - if (dev->depth > USB_HUB_MAX_DEPTH) { - device_printf(self, - "hub depth (%d) exceeded, hub ignored\n", - USB_HUB_MAX_DEPTH); - return ENXIO; - } - - /* Get hub descriptor. */ - req.bmRequestType = UT_READ_CLASS_DEVICE; - req.bRequest = UR_GET_DESCRIPTOR; - USETW2(req.wValue, (dev->address > 1 ? UDESC_HUB : 0), 0); - USETW(req.wIndex, 0); - USETW(req.wLength, USB_HUB_DESCRIPTOR_SIZE); - DPRINTFN(1,("usb_init_hub: getting hub descriptor\n")); - err = usbd_do_request(dev, &req, &hubdesc); - nports = hubdesc.bNbrPorts; - if (!err && nports > 7) { - USETW(req.wLength, USB_HUB_DESCRIPTOR_SIZE + (nports+1) / 8); - err = usbd_do_request(dev, &req, &hubdesc); - } - if (err) { - DPRINTF(("%s: getting hub descriptor failed, error=%s\n", - device_get_nameunit(self), usbd_errstr(err))); - return ENXIO; - } - - for (nremov = 0, port = 1; port <= nports; port++) - if (!UHD_NOT_REMOV(&hubdesc, port)) - nremov++; - device_printf(self, - "%d port%s with %d removable, %s powered\n", - nports, nports != 1 ? "s" : "", - nremov, dev->self_powered ? "self" : "bus"); - - if (nports == 0) { - device_printf(self, "no ports, hub ignored\n"); - goto bad; - } - - hub = kmalloc(sizeof(*hub) + (nports-1) * sizeof(struct usbd_port), - M_USBDEV, M_WAITOK); - dev->hub = hub; - dev->hub->hubdev = self; - hub->explore = uhub_explore; - hub->hubdesc = hubdesc; - - DPRINTFN(1,("usbhub_init_hub: selfpowered=%d, parent=%p, " - "parent->selfpowered=%d\n", - dev->self_powered, dev->powersrc->parent, - dev->powersrc->parent ? - dev->powersrc->parent->self_powered : 0)); - - if (!dev->self_powered && dev->powersrc->parent != NULL && - !dev->powersrc->parent->self_powered) { - device_printf(self, - "bus powered hub connected to bus powered hub, " - "ignored\n"); - goto bad; - } - - /* Set up interrupt pipe. */ - err = usbd_device2interface_handle(dev, 0, &iface); - if (err) { - device_printf(self, "no interface handle\n"); - goto bad; - } - ed = usbd_interface2endpoint_descriptor(iface, 0); - if (ed == NULL) { - device_printf(self, "no endpoint descriptor\n"); - goto bad; - } - if ((ed->bmAttributes & UE_XFERTYPE) != UE_INTERRUPT) { - device_printf(self, "bad interrupt endpoint\n"); - goto bad; - } - - err = usbd_open_pipe_intr(iface, ed->bEndpointAddress, - USBD_SHORT_XFER_OK, &sc->sc_ipipe, sc, sc->sc_status, - sizeof(sc->sc_status), uhub_intr, UHUB_INTR_INTERVAL); - if (err) { - device_printf(self, "cannot open interrupt pipe\n"); - goto bad; - } - - /* Wait with power off for a while. */ - usbd_delay_ms(dev, USB_POWER_DOWN_TIME); - - usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, dev, self); - - /* - * To have the best chance of success we do things in the exact same - * order as Windoze98. This should not be necessary, but some - * devices do not follow the USB specs to the letter. - * - * These are the events on the bus when a hub is attached: - * Get device and config descriptors (see attach code) - * Get hub descriptor (see above) - * For all ports - * turn on power - * wait for power to become stable - * (all below happens in explore code) - * For all ports - * clear C_PORT_CONNECTION - * For all ports - * get port status - * if device connected - * wait 100 ms - * turn on reset - * wait - * clear C_PORT_RESET - * get port status - * proceed with device attachment - */ - - if (UHUB_IS_HIGH_SPEED(sc)) { - tts = kmalloc((UHUB_IS_SINGLE_TT(sc) ? 1 : nports) * - sizeof(struct usbd_tt), M_USBDEV, M_WAITOK); - } - - /* Set up data structures */ - for (p = 0; p < nports; p++) { - struct usbd_port *up = &hub->ports[p]; - up->device = NULL; - up->parent = dev; - up->portno = p+1; - if (dev->self_powered) - /* Self powered hub, give ports maximum current. */ - up->power = USB_MAX_POWER; - else - up->power = USB_MIN_POWER; - up->restartcnt = 0; - if (UHUB_IS_HIGH_SPEED(sc)) { - up->tt = &tts[UHUB_IS_SINGLE_TT(sc) ? 0 : p]; - up->tt->hub = hub; - } else { - up->tt = NULL; - } - } - - /* XXX should check for none, individual, or ganged power? */ - - pwrdly = dev->hub->hubdesc.bPwrOn2PwrGood * UHD_PWRON_FACTOR - + USB_EXTRA_POWER_UP_TIME; - for (port = 1; port <= nports; port++) { - /* Turn the power on. */ - err = usbd_set_port_feature(dev, port, UHF_PORT_POWER); - if (err) - device_printf(self, - "port %d power on failed, %s\n", - port, usbd_errstr(err)); - DPRINTF(("usb_init_port: turn on port %d power\n", port)); - } - - /* Wait for stable power if we are not a root hub */ - if (dev->powersrc->parent != NULL) - usbd_delay_ms(dev, pwrdly); - - /* The usual exploration will finish the setup. */ - - sc->sc_running = 1; - - return 0; - - bad: - if (hub) - kfree(hub, M_USBDEV); - dev->hub = NULL; - return ENXIO; -} - -usbd_status -uhub_explore(usbd_device_handle dev) -{ - usb_hub_descriptor_t *hd = &dev->hub->hubdesc; - device_t self = dev->hub->hubdev; - struct uhub_softc *sc = device_get_softc(self); - struct usbd_port *up; - usbd_status err; - int speed; - int port; - int change, status; - - DPRINTFN(10, ("uhub_explore dev=%p addr=%d\n", dev, dev->address)); - - if (!sc->sc_running) - return (USBD_NOT_STARTED); - - /* Ignore hubs that are too deep. */ - if (dev->depth > USB_HUB_MAX_DEPTH) - return (USBD_TOO_DEEP); - - for(port = 1; port <= hd->bNbrPorts; port++) { - up = &dev->hub->ports[port-1]; - err = usbd_get_port_status(dev, port, &up->status); - if (err) { - DPRINTF(("uhub_explore: get port status failed, " - "error=%s\n", usbd_errstr(err))); - continue; - } - status = UGETW(up->status.wPortStatus); - change = UGETW(up->status.wPortChange); - DPRINTFN(3,("uhub_explore: %s port %d status 0x%04x 0x%04x\n", - device_get_nameunit(self), port, status, change)); - if (change & UPS_C_PORT_ENABLED) { - DPRINTF(("uhub_explore: C_PORT_ENABLED 0x%x\n", change)); - usbd_clear_port_feature(dev, port, UHF_C_PORT_ENABLE); - if (change & UPS_C_CONNECT_STATUS) { - /* Ignore the port error if the device - vanished. */ - } else if (status & UPS_PORT_ENABLED) { - device_printf(self, - "illegal enable change, port %d\n", port); - } else { - /* Port error condition. */ - if (up->restartcnt) /* no message first time */ - device_printf(self, - "port error, restarting " - "port %d\n", port); - - if (up->restartcnt++ < USBD_RESTART_MAX) - goto disco; - else - device_printf(self, - "port error, giving up " - "port %d\n", port); - } - } - if (!(change & UPS_C_CONNECT_STATUS)) { - DPRINTFN(3,("uhub_explore: port=%d !C_CONNECT_" - "STATUS\n", port)); - /* No status change, just do recursive explore. */ - if (up->device != NULL && up->device->hub != NULL) - up->device->hub->explore(up->device); -#if 0 && defined(DIAGNOSTIC) - if (up->device == NULL && - (status & UPS_CURRENT_CONNECT_STATUS)) - device_printf(self, - "connected, no device\n"); -#endif - continue; - } - - /* We have a connect status change, handle it. */ - - DPRINTF(("uhub_explore: status change hub=%d port=%d\n", - dev->address, port)); - usbd_clear_port_feature(dev, port, UHF_C_PORT_CONNECTION); - /*usbd_clear_port_feature(dev, port, UHF_C_PORT_ENABLE);*/ - /* - * If there is already a device on the port the change status - * must mean that is has disconnected. Looking at the - * current connect status is not enough to figure this out - * since a new unit may have been connected before we handle - * the disconnect. - */ - disco: - if (up->device != NULL) { - /* Disconnected */ - DPRINTF(("uhub_explore: device addr=%d disappeared " - "on port %d\n", up->device->address, port)); - usb_disconnect_port(up, self); - usbd_clear_port_feature(dev, port, - UHF_C_PORT_CONNECTION); - } - if (!(status & UPS_CURRENT_CONNECT_STATUS)) { - /* Nothing connected, just ignore it. */ - DPRINTFN(3,("uhub_explore: port=%d !CURRENT_CONNECT" - "_STATUS\n", port)); - continue; - } - - /* Connected */ - - if (!(status & UPS_PORT_POWER)) - device_printf(self, - "strange, connected port %d has no power\n", - port); - - /* Wait for maximum device power up time. */ - usbd_delay_ms(dev, USB_PORT_POWERUP_DELAY); - - /* Reset port, which implies enabling it. */ - if (usbd_reset_port(dev, port, &up->status)) { - device_printf(self, - "port %d reset failed\n", port); - continue; - } - /* Get port status again, it might have changed during reset */ - err = usbd_get_port_status(dev, port, &up->status); - if (err) { - DPRINTF(("uhub_explore: get port status failed, " - "error=%s\n", usbd_errstr(err))); - continue; - } - status = UGETW(up->status.wPortStatus); - change = UGETW(up->status.wPortChange); - if (!(status & UPS_CURRENT_CONNECT_STATUS)) { - /* Nothing connected, just ignore it. */ -#ifdef DIAGNOSTIC - device_printf(self, - "port %d, device disappeared after reset\n", - port); -#endif - continue; - } - -#if 0 - if (UHUB_IS_HIGH_SPEED(sc) && !(status & UPS_HIGH_SPEED)) { - device_printf(self, - "port %d, transaction translation not " - "implemented, low/full speed device ignored\n", - port); - continue; - } -#endif - - /* Figure out device speed */ - if (status & UPS_HIGH_SPEED) - speed = USB_SPEED_HIGH; - else if (status & UPS_LOW_SPEED) - speed = USB_SPEED_LOW; - else - speed = USB_SPEED_FULL; - /* Get device info and set its address. */ - err = usbd_new_device(self, dev->bus, - dev->depth + 1, speed, port, up); - /* XXX retry a few times? */ - if (err) { - DPRINTFN(-1,("uhub_explore: usb_new_device failed, " - "error=%s\n", usbd_errstr(err))); - /* Avoid addressing problems by disabling. */ - /* usbd_reset_port(dev, port, &up->status); */ - - /* - * The unit refused to accept a new address, or had - * some other serious problem. Since we cannot leave - * at 0 we have to disable the port instead. - */ - device_printf(self, - "device problem (%s), disabling port %d\n", - usbd_errstr(err), port); - usbd_clear_port_feature(dev, port, UHF_PORT_ENABLE); - } else { - /* The port set up succeeded, reset error count. */ - up->restartcnt = 0; - - if (up->device->hub) - up->device->hub->explore(up->device); - } - } - return (USBD_NORMAL_COMPLETION); -} - -/* - * Called from process context when the hub is gone. - * Detach all devices on active ports. - */ -static int -uhub_detach(device_t self) -{ - struct uhub_softc *sc = device_get_softc(self); - struct usbd_hub *hub = sc->sc_hub->hub; - struct usbd_port *rup; - int port, nports; - - DPRINTF(("uhub_detach: sc=%port\n", sc)); - - crit_enter(); - - if (hub == NULL) { /* Must be partially working */ - crit_exit(); - return (0); - } - - usbd_abort_pipe(sc->sc_ipipe); - usbd_close_pipe(sc->sc_ipipe); - - nports = hub->hubdesc.bNbrPorts; - for(port = 0; port < nports; port++) { - rup = &hub->ports[port]; - if (rup->device) - usb_disconnect_port(rup, self); - } - - usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_hub, self); - - if (hub->ports[0].tt) - kfree(hub->ports[0].tt, M_USBDEV); - kfree(hub, M_USBDEV); - sc->sc_hub->hub = NULL; - - crit_exit(); - - return (0); -} - -int -uhub_child_location_str(device_t cbdev, device_t child, char *buf, - size_t buflen) -{ - struct uhub_softc *sc = device_get_softc(cbdev); - usbd_device_handle devhub = sc->sc_hub; - usbd_device_handle dev; - int nports; - int port; - int i; - - crit_enter(); - nports = devhub->hub->hubdesc.bNbrPorts; - for (port = 0; port < nports; port++) { - dev = devhub->hub->ports[port].device; - if (dev && dev->subdevs) { - for (i = 0; dev->subdevs[i]; i++) { - if (dev->subdevs[i] == child) { - if (dev->ifacenums == NULL) { - ksnprintf(buf, buflen, - "port=%i", port); - } else { - ksnprintf(buf, buflen, - "port=%i interface=%i", - port, dev->ifacenums[i]); - } - goto found_dev; - } - } - } - } - DPRINTFN(0,("uhub_child_location_str: device not on hub\n")); - buf[0] = '\0'; -found_dev: - crit_exit(); - return (0); -} - -int -uhub_child_pnpinfo_str(device_t cbdev, device_t child, char *buf, - size_t buflen) -{ - struct uhub_softc *sc = device_get_softc(cbdev); - usbd_device_handle devhub = sc->sc_hub; - usbd_device_handle dev; - struct usbd_interface *iface; - char serial[128]; - int nports; - int port; - int i; - - crit_enter(); - nports = devhub->hub->hubdesc.bNbrPorts; - for (port = 0; port < nports; port++) { - dev = devhub->hub->ports[port].device; - if (dev && dev->subdevs) { - for (i = 0; dev->subdevs[i]; i++) { - if (dev->subdevs[i] == child) { - goto found_dev; - } - } - } - } - DPRINTFN(0,("uhub_child_pnpinfo_str: device not on hub\n")); - buf[0] = '\0'; - crit_exit(); - return (0); - -found_dev: - /* XXX can sleep */ - (void)usbd_get_string(dev, dev->ddesc.iSerialNumber, &serial[0]); - if (dev->ifacenums == NULL) { - ksnprintf(buf, buflen, "vendor=0x%04x product=0x%04x " - "devclass=0x%02x devsubclass=0x%02x " - "release=0x%04x sernum=\"%s\"", - UGETW(dev->ddesc.idVendor), UGETW(dev->ddesc.idProduct), - dev->ddesc.bDeviceClass, dev->ddesc.bDeviceSubClass, - UGETW(dev->ddesc.bcdDevice), serial); - } else { - iface = &dev->ifaces[dev->ifacenums[i]]; - ksnprintf(buf, buflen, "vendor=0x%04x product=0x%04x " - "devclass=0x%02x devsubclass=0x%02x " - "release=0x%04x sernum=\"%s\" " - "intclass=0x%02x intsubclass=0x%02x", - UGETW(dev->ddesc.idVendor), UGETW(dev->ddesc.idProduct), - dev->ddesc.bDeviceClass, dev->ddesc.bDeviceSubClass, - UGETW(dev->ddesc.bcdDevice), serial, - iface->idesc->bInterfaceClass, - iface->idesc->bInterfaceSubClass); - } - crit_exit(); - return (0); -} - -static void -uhub_child_detached(device_t self, device_t child) -{ - struct uhub_softc *sc = device_get_softc(self); - usbd_device_handle devhub = sc->sc_hub; - usbd_device_handle dev = NULL; - int nports, port, i = 0; - - crit_enter(); - nports = devhub->hub->hubdesc.bNbrPorts; - for (port = 0; port < nports; port++) { - dev = devhub->hub->ports[port].device; - if (dev && dev->subdevs) { - for (i = 0; dev->subdevs[i]; ++i) { - if (dev->subdevs[i] == child) - goto found_dev; - } - } - } - crit_exit(); - return; - -found_dev: -#if 0 - device_printf(dev->subdevs[i], "at %s", device_get_nameunit(self)); - if (port != 0) - kprintf(" port %d", port); - kprintf(" (addr %d) disconnected\n", dev->address); -#endif - kfree(device_get_ivars(dev->subdevs[i]), M_USB); - dev->subdevs[i] = NULL; - crit_exit(); -} - -/* - * Hub interrupt. - * This an indication that some port has changed status. - * Notify the bus event handler thread that we need - * to be explored again. - */ -void -uhub_intr(usbd_xfer_handle xfer, usbd_private_handle addr, usbd_status status) -{ - struct uhub_softc *sc = addr; - - DPRINTFN(5,("uhub_intr: sc=%p\n", sc)); - if (status == USBD_STALLED) - usbd_clear_endpoint_stall_async(sc->sc_ipipe); - else if (status == USBD_NORMAL_COMPLETION) - usb_needs_explore(sc->sc_hub); -} - -DRIVER_MODULE(uhub, usb, uhubroot_driver, uhubroot_devclass, NULL, NULL); -DRIVER_MODULE(uhub, uhub, uhub_driver, uhub_devclass, usbd_driver_load, NULL); diff --git a/sys/bus/usb/usb.c b/sys/bus/usb/usb.c deleted file mode 100644 index 6737075ee7..0000000000 --- a/sys/bus/usb/usb.c +++ /dev/null @@ -1,996 +0,0 @@ -/* - * $NetBSD: usb.c,v 1.68 2002/02/20 20:30:12 christos Exp $ - * $FreeBSD: src/sys/dev/usb/usb.c,v 1.106 2005/03/27 15:31:23 iedowse Exp $ - */ - -/* Also already merged from NetBSD: - * $NetBSD: usb.c,v 1.70 2002/05/09 21:54:32 augustss Exp $ - * $NetBSD: usb.c,v 1.71 2002/06/01 23:51:04 lukem Exp $ - * $NetBSD: usb.c,v 1.73 2002/09/23 05:51:19 simonb Exp $ - * $NetBSD: usb.c,v 1.80 2003/11/07 17:03:25 wiz Exp $ - */ - -/* - * Copyright (c) 1998 The NetBSD Foundation, Inc. - * All rights reserved. - * - * This code is derived from software contributed to The NetBSD Foundation - * by Lennart Augustsson (lennart@augustsson.net) at - * Carlstedt Research & Technology. - * - * 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. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the NetBSD - * Foundation, Inc. and its contributors. - * 4. Neither the name of The NetBSD Foundation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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. - */ - -/* - * USB specifications and other documentation can be found at - * http://www.usb.org/developers/docs/ and - * http://www.usb.org/developers/devclass_docs/ - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include -#include - -#define USBUNIT(d) (minor(d)) /* usb_discover device nodes, kthread */ -#define USB_DEV_MINOR 255 /* event queue device */ - -MALLOC_DEFINE(M_USB, "USB", "USB"); -MALLOC_DEFINE(M_USBDEV, "USBdev", "USB device"); -MALLOC_DEFINE(M_USBHC, "USBHC", "USB host controller"); - -#include "usb_if.h" - -#include -#include - -/* Define this unconditionally in case a kernel module is loaded that - * has been compiled with debugging options. - */ -SYSCTL_NODE(_hw, OID_AUTO, usb, CTLFLAG_RW, 0, "USB debugging"); - -/* - * XXX: This is a hack! If your USB keyboard doesn't work - * early at boot, try setting this tunable to 0 from - * bootleader: - * - * set hw.usb.hack_defer_exploration=0 - */ -static int hack_defer_exploration = 1; - -#ifdef USB_DEBUG -#define DPRINTF(x) if (usbdebug) kprintf x -#define DPRINTFN(n,x) if (usbdebug>(n)) kprintf x -int usbdebug = 0; -SYSCTL_INT(_hw_usb, OID_AUTO, debug, CTLFLAG_RW, - &usbdebug, 0, "usb debug level"); - -/* - * 0 - do usual exploration - * 1 - do not use timeout exploration - * >1 - do no exploration - */ -int usb_noexplore = 0; -#else -#define DPRINTF(x) -#define DPRINTFN(n,x) -#endif - -struct usb_softc { - cdev_t sc_usbdev; - TAILQ_ENTRY(usb_softc) sc_coldexplist; /* cold needs-explore list */ - usbd_bus_handle sc_bus; /* USB controller */ - struct usbd_port sc_port; /* dummy port for root hub */ - - struct thread *sc_event_thread; - - char sc_dying; -}; - -struct usb_taskq { - TAILQ_HEAD(, usb_task) tasks; - struct thread *task_thread_proc; - const char *name; - int taskcreated; /* task thread exists. */ -}; -static struct usb_taskq usb_taskq[USB_NUM_TASKQS]; - -d_open_t usbopen; -d_close_t usbclose; -d_read_t usbread; -d_ioctl_t usbioctl; -d_kqfilter_t usbkqfilter; - -static void usbfilt_detach(struct knote *); -static int usbfilt(struct knote *, long); - -static struct dev_ops usb_ops = { - { "usb", 0, 0 }, - .d_open = usbopen, - .d_close = usbclose, - .d_read = usbread, - .d_ioctl = usbioctl, - .d_kqfilter = usbkqfilter -}; - -static void usb_discover(device_t); -static bus_child_detached_t usb_child_detached; -static void usb_create_event_thread(device_t); -static void usb_event_thread(void *); -static void usb_task_thread(void *); - -static cdev_t usb_dev; /* The /dev/usb device. */ -static int usb_ndevs; /* Number of /dev/usbN devices. */ -/* Busses to explore at the end of boot-time device configuration */ -static TAILQ_HEAD(, usb_softc) usb_coldexplist = - TAILQ_HEAD_INITIALIZER(usb_coldexplist); - -#define USB_MAX_EVENTS 100 -struct usb_event_q { - struct usb_event ue; - TAILQ_ENTRY(usb_event_q) next; -}; -static TAILQ_HEAD(, usb_event_q) usb_events = - TAILQ_HEAD_INITIALIZER(usb_events); -static int usb_nevents = 0; -static struct kqinfo usb_kqevent; -static struct proc *usb_async_proc; /* process that wants USB SIGIO */ -static int usb_dev_open = 0; -static void usb_add_event(int, struct usb_event *); - -static int usb_get_next_event(struct usb_event *); - -static const char *usbrev_str[] = USBREV_STR; - -static device_probe_t usb_match; -static device_attach_t usb_attach; -static device_detach_t usb_detach; - -static devclass_t usb_devclass; - -static kobj_method_t usb_methods[] = { - DEVMETHOD(device_probe, usb_match), - DEVMETHOD(device_attach, usb_attach), - DEVMETHOD(device_detach, usb_detach), - DEVMETHOD(bus_child_detached, usb_child_detached), - DEVMETHOD(device_suspend, bus_generic_suspend), - DEVMETHOD(device_resume, bus_generic_resume), - DEVMETHOD(device_shutdown, bus_generic_shutdown), - DEVMETHOD_END -}; - -static driver_t usb_driver = { - "usb", - usb_methods, - sizeof(struct usb_softc) -}; - -MODULE_DEPEND(usb, usb, 1, 1, 1); -MODULE_VERSION(usb, 1); - -static int -usb_match(device_t self) -{ - DPRINTF(("usb_match\n")); - return (UMATCH_GENERIC); -} - -static int -usb_attach(device_t self) -{ - struct usb_softc *sc = device_get_softc(self); - void *aux = device_get_ivars(self); - cdev_t tmp_dev; - usbd_device_handle dev; - usbd_status err; - int usbrev; - int speed; - struct usb_event ue; - - TUNABLE_INT_FETCH("hw.usb.hack_defer_exploration", - &hack_defer_exploration); - - DPRINTF(("usb_attach\n")); - - usbd_init(); - sc->sc_bus = aux; - sc->sc_bus->usbctl = sc; - sc->sc_port.power = USB_MAX_POWER; - - usbrev = sc->sc_bus->usbrev; - device_printf(self, "USB revision %s", usbrev_str[usbrev]); - switch (usbrev) { - case USBREV_1_0: - case USBREV_1_1: - speed = USB_SPEED_FULL; - break; - case USBREV_2_0: - speed = USB_SPEED_HIGH; - break; - default: - kprintf(", not supported\n"); - sc->sc_dying = 1; - return ENXIO; - } - kprintf("\n"); - - /* Make sure not to use tsleep() if we are cold booting. */ - if (hack_defer_exploration && cold) - sc->sc_bus->use_polling++; - - ue.u.ue_ctrlr.ue_bus = device_get_unit(self); - usb_add_event(USB_EVENT_CTRLR_ATTACH, &ue); - -#ifdef USB_USE_SOFTINTR - callout_init(&sc->sc_bus->softi); -#endif - - err = usbd_new_device(self, sc->sc_bus, 0, speed, 0, &sc->sc_port); - if (!err) { - dev = sc->sc_port.device; - if (dev->hub == NULL) { - sc->sc_dying = 1; - device_printf(self, - "root device is not a hub\n"); - return ENXIO; - } - sc->sc_bus->root_hub = dev; -#if 1 - /* - * Turning this code off will delay attachment of USB devices - * until the USB event thread is running, which means that - * the keyboard will not work until after cold boot. - */ - if (cold) { - if (hack_defer_exploration) { - /* Explore high-speed busses before others. */ - if (speed == USB_SPEED_HIGH) - dev->hub->explore(sc->sc_bus->root_hub); - else - TAILQ_INSERT_TAIL(&usb_coldexplist, sc, - sc_coldexplist); - } else { - /* - * XXX Exploring high speed devices here will - * hang the system. - */ - if (speed != USB_SPEED_HIGH) - dev->hub->explore(sc->sc_bus->root_hub); - } - } -#endif - } else { - device_printf(self, - "root hub problem, error=%d\n", err); - sc->sc_dying = 1; - } - if (hack_defer_exploration && cold) - sc->sc_bus->use_polling--; - - usb_create_event_thread(self); - - /* - * The per controller devices (used for usb_discover) - * XXX This is redundant now, but old usbd's will want it - */ - tmp_dev = make_dev(&usb_ops, device_get_unit(self), - UID_ROOT, GID_OPERATOR, 0660, - "usb%d", device_get_unit(self)); - sc->sc_usbdev = reference_dev(tmp_dev); - if (usb_ndevs++ == 0) { - /* The device spitting out events */ - tmp_dev = make_dev(&usb_ops, USB_DEV_MINOR, - UID_ROOT, GID_OPERATOR, 0660, "usb"); - usb_dev = reference_dev(tmp_dev); - } - - return 0; -} - -static const char *taskq_names[] = USB_TASKQ_NAMES; - -void -usb_create_event_thread(device_t self) -{ - struct usb_softc *sc = device_get_softc(self); - int i; - - if (kthread_create(usb_event_thread, self, &sc->sc_event_thread, - "%s", device_get_nameunit(self))) { - device_printf(self, - "unable to create event thread for\n"); - panic("usb_create_event_thread"); - } - - for (i = 0; i < USB_NUM_TASKQS; i++) { - struct usb_taskq *taskq = &usb_taskq[i]; - - if (taskq->taskcreated == 0) { - taskq->taskcreated = 1; - taskq->name = taskq_names[i]; - TAILQ_INIT(&taskq->tasks); - if (kthread_create(usb_task_thread, taskq, - &taskq->task_thread_proc, "%s", taskq->name)) { - kprintf("unable to create task thread\n"); - panic("usb_create_event_thread task"); - } - } - } -} - -/* - * Add a task to be performed by the task thread. This function can be - * called from any context and the task will be executed in a process - * context ASAP. - */ -void -usb_add_task(usbd_device_handle dev, struct usb_task *task, int queue) -{ - struct usb_taskq *taskq; - - crit_enter(); - - taskq = &usb_taskq[queue]; - if (task->queue == -1) { - DPRINTFN(2,("usb_add_task: task=%p\n", task)); - TAILQ_INSERT_TAIL(&taskq->tasks, task, next); - task->queue = queue; - } else { - DPRINTFN(3,("usb_add_task: task=%p on q\n", task)); - } - wakeup(&taskq->tasks); - - crit_exit(); -} - -void -usb_do_task(usbd_device_handle dev, struct usb_task *task, int queue, - int time_out) -{ - struct usb_taskq *taskq; - - crit_enter(); - - taskq = &usb_taskq[queue]; - if (task->queue == -1) { - DPRINTFN(2,("usb_add_task: task=%p\n", task)); - TAILQ_INSERT_TAIL(&taskq->tasks, task, next); - task->queue = queue; - } else { - DPRINTFN(3,("usb_add_task: task=%p on q\n", task)); - } - wakeup(&taskq->tasks); - - /* Wait until task is finished */ - tsleep((&taskq->tasks + 1), 0, "usbdotsk", time_out); - - crit_exit(); -} - -void -usb_rem_task(usbd_device_handle dev, struct usb_task *task) -{ - crit_enter(); - if (task->queue != -1) { - TAILQ_REMOVE(&usb_taskq[task->queue].tasks, task, next); - task->queue = -1; - } - crit_exit(); -} - -void -usb_event_thread(void *arg) -{ - device_t self = arg; - struct usb_softc *sc = device_get_softc(self); - - DPRINTF(("usb_event_thread: start\n")); - - /* - * In case this controller is a companion controller to an - * EHCI controller we need to wait until the EHCI controller - * has grabbed the port. - * XXX It would be nicer to do this with a tsleep(), but I don't - * know how to synchronize the creation of the threads so it - * will work. - */ - usb_delay_ms(sc->sc_bus, 500); - - get_mplock(); - crit_enter(); - - /* Make sure first discover does something. */ - sc->sc_bus->needs_explore = 1; - usb_discover(self); - - while (!sc->sc_dying) { -#ifdef USB_DEBUG - if (usb_noexplore < 2) -#endif - usb_discover(self); -#ifdef USB_DEBUG - tsleep(&sc->sc_bus->needs_explore, 0, "usbevt", - usb_noexplore ? 0 : hz * 60); -#else - tsleep(&sc->sc_bus->needs_explore, 0, "usbevt", hz * 60); -#endif - DPRINTFN(2,("usb_event_thread: woke up\n")); - } - sc->sc_event_thread = NULL; - - crit_exit(); - rel_mplock(); - - /* In case parent is waiting for us to exit. */ - wakeup(sc); - - DPRINTF(("usb_event_thread: exit\n")); -} - -void -usb_task_thread(void *arg) -{ - struct usb_task *task; - struct usb_taskq *taskq; - - get_mplock(); - crit_enter(); - - taskq = arg; - DPRINTF(("usb_task_thread: start taskq %s\n", taskq->name)); - - while (usb_ndevs > 0) { - task = TAILQ_FIRST(&taskq->tasks); - if (task == NULL) { - tsleep(&taskq->tasks, 0, "usbtsk", 0); - task = TAILQ_FIRST(&taskq->tasks); - } - DPRINTFN(2,("usb_task_thread: woke up task=%p\n", task)); - if (task != NULL) { - TAILQ_REMOVE(&taskq->tasks, task, next); - task->queue = -1; - crit_exit(); - task->fun(task->arg); - crit_enter(); - wakeup((&taskq->tasks + 1)); - } - } - - crit_exit(); - rel_mplock(); - - taskq->taskcreated = 0; - wakeup(&taskq->taskcreated); - - DPRINTF(("usb_event_thread: exit\n")); -} - -int -usbopen(struct dev_open_args *ap) -{ - cdev_t dev = ap->a_head.a_dev; - int unit = USBUNIT(dev); - struct usb_softc *sc; - - if (unit == USB_DEV_MINOR) { - if (usb_dev_open) - return (EBUSY); - usb_dev_open = 1; - usb_async_proc = NULL; - return (0); - } - - sc = devclass_get_softc(usb_devclass, unit); - if (sc == NULL) - return (ENXIO); - - if (sc->sc_dying) - return (EIO); - - return (0); -} - -int -usbread(struct dev_read_args *ap) -{ - cdev_t dev = ap->a_head.a_dev; - struct uio *uio = ap->a_uio; - struct usb_event ue; - int unit = USBUNIT(dev); - int error, n; - - if (unit != USB_DEV_MINOR) - return (ENODEV); - - if (uio->uio_resid != sizeof(struct usb_event)) - return (EINVAL); - - error = 0; - crit_enter(); - for (;;) { - n = usb_get_next_event(&ue); - if (n != 0) - break; - if (ap->a_ioflag & IO_NDELAY) { - error = EWOULDBLOCK; - break; - } - error = tsleep(&usb_events, PCATCH, "usbrea", 0); - if (error) - break; - } - crit_exit(); - if (!error) - error = uiomove((void *)&ue, uio->uio_resid, uio); - - return (error); -} - -int -usbclose(struct dev_close_args *ap) -{ - cdev_t dev = ap->a_head.a_dev; - int unit = USBUNIT(dev); - - if (unit == USB_DEV_MINOR) { - usb_async_proc = NULL; - usb_dev_open = 0; - } - - return (0); -} - -int -usbioctl(struct dev_ioctl_args *ap) -{ - cdev_t devt = ap->a_head.a_dev; - struct usb_softc *sc; - int unit = USBUNIT(devt); - - if (unit == USB_DEV_MINOR) { - switch (ap->a_cmd) { - case FIOASYNC: - if (*(int *)ap->a_data) - usb_async_proc = curproc; - else - usb_async_proc = NULL; - return (0); - - default: - return (EINVAL); - } - } - - sc = devclass_get_softc(usb_devclass, unit); - - if (sc->sc_dying) - return (EIO); - - switch (ap->a_cmd) { - /* This part should be deleted */ - case USB_DISCOVER: - break; - case USB_REQUEST: - { - struct usb_ctl_request *ur = (void *)ap->a_data; - size_t len = UGETW(ur->ucr_request.wLength); - struct iovec iov; - struct uio uio; - void *ptr = NULL; - int addr = ur->ucr_addr; - usbd_status err; - int error = 0; - - DPRINTF(("usbioctl: USB_REQUEST addr=%d len=%zu\n", addr, len)); - if (len > 32768) - return (EINVAL); - if (addr < 0 || addr >= USB_MAX_DEVICES || - sc->sc_bus->devices[addr] == 0) - return (EINVAL); - if (len != 0) { - iov.iov_base = (caddr_t)ur->ucr_data; - iov.iov_len = len; - uio.uio_iov = &iov; - uio.uio_iovcnt = 1; - uio.uio_resid = len; - uio.uio_offset = 0; - uio.uio_segflg = UIO_USERSPACE; - uio.uio_rw = - ur->ucr_request.bmRequestType & UT_READ ? - UIO_READ : UIO_WRITE; - uio.uio_td = curthread; - ptr = kmalloc(len, M_TEMP, M_WAITOK); - if (uio.uio_rw == UIO_WRITE) { - error = uiomove(ptr, len, &uio); - if (error) - goto ret; - } - } - err = usbd_do_request_flags(sc->sc_bus->devices[addr], - &ur->ucr_request, ptr, ur->ucr_flags, &ur->ucr_actlen, - USBD_DEFAULT_TIMEOUT); - if (err) { - error = EIO; - goto ret; - } - if (len != 0) { - if (uio.uio_rw == UIO_READ) { - error = uiomove(ptr, len, &uio); - if (error) - goto ret; - } - } - ret: - if (ptr) - kfree(ptr, M_TEMP); - return (error); - } - - case USB_DEVICEINFO: - { - struct usb_device_info *di = (void *)ap->a_data; - int addr = di->udi_addr; - usbd_device_handle dev; - - if (addr < 1 || addr >= USB_MAX_DEVICES) - return (EINVAL); - dev = sc->sc_bus->devices[addr]; - if (dev == NULL) - return (ENXIO); - usbd_fill_deviceinfo(dev, di, 1); - break; - } - - case USB_DEVICESTATS: - *(struct usb_device_stats *)ap->a_data = sc->sc_bus->stats; - break; - - default: - return (EINVAL); - } - return (0); -} - -static struct filterops usbfiltops = - { FILTEROP_ISFD, NULL, usbfilt_detach, usbfilt }; - -int -usbkqfilter(struct dev_kqfilter_args *ap) -{ - cdev_t dev = ap->a_head.a_dev; - struct knote *kn = ap->a_kn; - struct klist *klist; - - ap->a_result = 0; - - switch (kn->kn_filter) { - case EVFILT_READ: - kn->kn_fop = &usbfiltops; - kn->kn_hook = (caddr_t)dev; - break; - default: - ap->a_result = EOPNOTSUPP; - return (0); - } - - klist = &usb_kqevent.ki_note; - knote_insert(klist, kn); - - return (0); -} - -static void -usbfilt_detach(struct knote *kn) -{ - struct klist *klist; - - klist = &usb_kqevent.ki_note; - knote_remove(klist, kn); -} - -static int -usbfilt(struct knote *kn, long hint) -{ - cdev_t dev = (cdev_t)kn->kn_hook; - int unit = USBUNIT(dev); - int ready = 0; - - if (unit == USB_DEV_MINOR) { - crit_enter(); - if (usb_nevents > 0) - ready = 1; - crit_exit(); - } - - return (ready); -} - -/* Explore device tree from the root. */ -static void -usb_discover(device_t self) -{ - struct usb_softc *sc = device_get_softc(self); - - DPRINTFN(2,("usb_discover\n")); -#ifdef USB_DEBUG - if (usb_noexplore > 1) - return; -#endif - - /* - * We need mutual exclusion while traversing the device tree, - * but this is guaranteed since this function is only called - * from the event thread for the controller. - */ - crit_enter(); - while (sc->sc_bus->needs_explore && !sc->sc_dying) { - sc->sc_bus->needs_explore = 0; - - crit_exit(); - sc->sc_bus->root_hub->hub->explore(sc->sc_bus->root_hub); - crit_enter(); - - } - crit_exit(); -} - -void -usb_needs_explore(usbd_device_handle dev) -{ - DPRINTFN(2,("usb_needs_explore\n")); - dev->bus->needs_explore = 1; - wakeup(&dev->bus->needs_explore); -} - -/* Called from a critical section */ -int -usb_get_next_event(struct usb_event *ue) -{ - struct usb_event_q *ueq; - - if (usb_nevents <= 0) - return (0); - ueq = TAILQ_FIRST(&usb_events); -#ifdef DIAGNOSTIC - if (ueq == NULL) { - kprintf("usb: usb_nevents got out of sync! %d\n", usb_nevents); - usb_nevents = 0; - return (0); - } -#endif - if (ue) - *ue = ueq->ue; - TAILQ_REMOVE(&usb_events, ueq, next); - kfree(ueq, M_USBDEV); - usb_nevents--; - return (1); -} - -void -usbd_add_dev_event(int type, usbd_device_handle udev) -{ - struct usb_event ue; - - usbd_fill_deviceinfo(udev, &ue.u.ue_device, USB_EVENT_IS_ATTACH(type)); - usb_add_event(type, &ue); -} - -void -usbd_add_drv_event(int type, usbd_device_handle udev, device_t dev) -{ - struct usb_event ue; - - ue.u.ue_driver.ue_cookie = udev->cookie; - strncpy(ue.u.ue_driver.ue_devname, device_get_nameunit(dev), - sizeof ue.u.ue_driver.ue_devname); - usb_add_event(type, &ue); -} - -void -usb_add_event(int type, struct usb_event *uep) -{ - struct usb_event_q *ueq; - struct timeval thetime; - - ueq = kmalloc(sizeof *ueq, M_USBDEV, M_INTWAIT); - ueq->ue = *uep; - ueq->ue.ue_type = type; - microtime(&thetime); - TIMEVAL_TO_TIMESPEC(&thetime, &ueq->ue.ue_time); - - crit_enter(); - if (USB_EVENT_IS_DETACH(type)) { - struct usb_event_q *ueqi, *ueqi_next; - - for (ueqi = TAILQ_FIRST(&usb_events); ueqi; ueqi = ueqi_next) { - ueqi_next = TAILQ_NEXT(ueqi, next); - if (ueqi->ue.u.ue_driver.ue_cookie.cookie == - uep->u.ue_device.udi_cookie.cookie) { - TAILQ_REMOVE(&usb_events, ueqi, next); - kfree(ueqi, M_USBDEV); - usb_nevents--; - ueqi_next = TAILQ_FIRST(&usb_events); - } - } - } - if (usb_nevents >= USB_MAX_EVENTS) { - /* Too many queued events, drop an old one. */ - DPRINTF(("usb: event dropped\n")); - usb_get_next_event(NULL); - } - TAILQ_INSERT_TAIL(&usb_events, ueq, next); - usb_nevents++; - wakeup(&usb_events); - KNOTE(&usb_kqevent.ki_note, 0); - if (usb_async_proc != NULL) { - ksignal(usb_async_proc, SIGIO); - } - crit_exit(); -} - -void -usb_schedsoftintr(usbd_bus_handle bus) -{ - DPRINTFN(10,("usb_schedsoftintr: polling=%d\n", bus->use_polling)); -#ifdef USB_USE_SOFTINTR - if (bus->use_polling) { - bus->methods->soft_intr(bus); - } else { - if (!callout_pending(&bus->softi)) - callout_reset(&bus->softi, 0, bus->methods->soft_intr, - bus); - } -#else - bus->methods->soft_intr(bus); -#endif /* USB_USE_SOFTINTR */ -} - -static int -usb_detach(device_t self) -{ - struct usb_softc *sc = device_get_softc(self); - struct usb_event ue; - - DPRINTF(("usb_detach: start\n")); - - sc->sc_dying = 1; - - /* Make all devices disconnect. */ - if (sc->sc_port.device != NULL) - usb_disconnect_port(&sc->sc_port, self); - - /* Kill off event thread. */ - if (sc->sc_event_thread != NULL) { - wakeup(&sc->sc_bus->needs_explore); - if (tsleep(sc, 0, "usbdet", hz * 60)) - device_printf(self, - "event thread didn't die\n"); - DPRINTF(("usb_detach: event thread dead\n")); - } - - release_dev(sc->sc_usbdev); - - if (--usb_ndevs == 0) { - int i; - - release_dev(usb_dev); - dev_ops_remove_minor(&usb_ops, USB_DEV_MINOR); - usb_dev = NULL; - - for (i = 0; i < USB_NUM_TASKQS; i++) { - struct usb_taskq *taskq = &usb_taskq[i]; - wakeup(&taskq->tasks); - if (tsleep(&taskq->taskcreated, 0, "usbtdt", - hz * 60)) { - kprintf("usb task thread %s didn't die\n", - taskq->name); - } - } - } - - usbd_finish(); - -#ifdef USB_USE_SOFTINTR - callout_stop(&sc->sc_bus->softi); -#endif - - ue.u.ue_ctrlr.ue_bus = device_get_unit(self); - usb_add_event(USB_EVENT_CTRLR_DETACH, &ue); - - return (0); -} - -static void -usb_child_detached(device_t self, device_t child) -{ - struct usb_softc *sc = device_get_softc(self); - - /* XXX, should check it is the right device. */ - sc->sc_port.device = NULL; -} - -/* Explore USB busses at the end of device configuration */ -static void -usb_cold_explore(void *arg) -{ - struct usb_softc *sc; - - TUNABLE_INT_FETCH("hw.usb.hack_defer_exploration", - &hack_defer_exploration); - - if (!hack_defer_exploration) - return; - - KASSERT(cold || TAILQ_EMPTY(&usb_coldexplist), - ("usb_cold_explore: busses to explore when !cold")); - while (!TAILQ_EMPTY(&usb_coldexplist)) { - sc = TAILQ_FIRST(&usb_coldexplist); - TAILQ_REMOVE(&usb_coldexplist, sc, sc_coldexplist); - - sc->sc_bus->use_polling++; - sc->sc_port.device->hub->explore(sc->sc_bus->root_hub); - sc->sc_bus->use_polling--; - } -} - -struct usbd_bus * -usb_getbushandle(struct usb_softc *sc) -{ - return (sc->sc_bus); -} - - -SYSINIT(usb_cold_explore, SI_SUB_CONFIGURE, SI_ORDER_MIDDLE, - usb_cold_explore, NULL); - -DRIVER_MODULE(usb, ohci, usb_driver, usb_devclass, NULL, NULL); -DRIVER_MODULE(usb, uhci, usb_driver, usb_devclass, NULL, NULL); -DRIVER_MODULE(usb, ehci, usb_driver, usb_devclass, NULL, NULL); diff --git a/sys/bus/usb/usb.h b/sys/bus/usb/usb.h deleted file mode 100644 index 2089669b1e..0000000000 --- a/sys/bus/usb/usb.h +++ /dev/null @@ -1,702 +0,0 @@ -/* $NetBSD: usb.h,v 1.69 2002/09/22 23:20:50 augustss Exp $ */ -/* $FreeBSD: src/sys/dev/usb/usb.h,v 1.39.2.1 2006/01/20 22:47:49 mux Exp $ */ -/* $DragonFly: src/sys/bus/usb/usb.h,v 1.8 2007/07/04 06:06:48 hasso Exp $ */ - -/* - * Copyright (c) 1998 The NetBSD Foundation, Inc. - * All rights reserved. - * - * This code is derived from software contributed to The NetBSD Foundation - * by Lennart Augustsson (lennart@augustsson.net) at - * Carlstedt Research & Technology. - * - * 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. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the NetBSD - * Foundation, Inc. and its contributors. - * 4. Neither the name of The NetBSD Foundation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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. - */ - - -#ifndef _USB_H_ -#define _USB_H_ - -#include -#include -#include - -#if defined(_KERNEL) -#include "opt_usb.h" - -#ifdef SYSCTL_DECL -SYSCTL_DECL(_hw_usb); -#endif - -#include - -MALLOC_DECLARE(M_USB); -MALLOC_DECLARE(M_USBDEV); -MALLOC_DECLARE(M_USBHC); -#endif /* _KERNEL */ - -#define PWR_RESUME 0 -#define PWR_SUSPEND 1 - -/* These two defines are used by usbd to autoload the usb kld */ -#define USB_KLD "usb" /* name of usb module */ -#define USB_UHUB "usb/uhub" /* root hub */ - -#define USB_STACK_VERSION 2 - -#define USB_MAX_DEVICES 128 -#define USB_START_ADDR 0 - -#define USB_CONTROL_ENDPOINT 0 -#define USB_MAX_ENDPOINTS 16 - -#define USB_FRAMES_PER_SECOND 1000 - -/* - * The USB records contain some unaligned little-endian word - * components. The U[SG]ETW macros take care of both the alignment - * and endian problem and should always be used to access non-byte - * values. - */ -typedef u_int8_t uByte; -typedef u_int8_t uWord[2]; -typedef u_int8_t uDWord[4]; - -#define USETW2(w,h,l) ((w)[0] = (u_int8_t)(l), (w)[1] = (u_int8_t)(h)) - -#if 1 -#define UGETW(w) ((w)[0] | ((w)[1] << 8)) -#define USETW(w,v) ((w)[0] = (u_int8_t)(v), (w)[1] = (u_int8_t)((v) >> 8)) -#define UGETDW(w) ((w)[0] | ((w)[1] << 8) | ((w)[2] << 16) | ((w)[3] << 24)) -#define USETDW(w,v) ((w)[0] = (u_int8_t)(v), \ - (w)[1] = (u_int8_t)((v) >> 8), \ - (w)[2] = (u_int8_t)((v) >> 16), \ - (w)[3] = (u_int8_t)((v) >> 24)) -#else -/* - * On little-endian machines that can handle unanliged accesses - * (e.g. i386) these macros can be replaced by the following. - */ -#define UGETW(w) (*(u_int16_t *)(w)) -#define USETW(w,v) (*(u_int16_t *)(w) = (v)) -#define UGETDW(w) (*(u_int32_t *)(w)) -#define USETDW(w,v) (*(u_int32_t *)(w) = (v)) -#endif - -#define UPACKED __packed - -typedef struct { - uByte bmRequestType; - uByte bRequest; - uWord wValue; - uWord wIndex; - uWord wLength; -} UPACKED usb_device_request_t; - -#define UT_WRITE 0x00 -#define UT_READ 0x80 -#define UT_STANDARD 0x00 -#define UT_CLASS 0x20 -#define UT_VENDOR 0x40 -#define UT_DEVICE 0x00 -#define UT_INTERFACE 0x01 -#define UT_ENDPOINT 0x02 -#define UT_OTHER 0x03 - -#define UT_READ_DEVICE (UT_READ | UT_STANDARD | UT_DEVICE) -#define UT_READ_INTERFACE (UT_READ | UT_STANDARD | UT_INTERFACE) -#define UT_READ_ENDPOINT (UT_READ | UT_STANDARD | UT_ENDPOINT) -#define UT_WRITE_DEVICE (UT_WRITE | UT_STANDARD | UT_DEVICE) -#define UT_WRITE_INTERFACE (UT_WRITE | UT_STANDARD | UT_INTERFACE) -#define UT_WRITE_ENDPOINT (UT_WRITE | UT_STANDARD | UT_ENDPOINT) -#define UT_READ_CLASS_DEVICE (UT_READ | UT_CLASS | UT_DEVICE) -#define UT_READ_CLASS_INTERFACE (UT_READ | UT_CLASS | UT_INTERFACE) -#define UT_READ_CLASS_OTHER (UT_READ | UT_CLASS | UT_OTHER) -#define UT_READ_CLASS_ENDPOINT (UT_READ | UT_CLASS | UT_ENDPOINT) -#define UT_WRITE_CLASS_DEVICE (UT_WRITE | UT_CLASS | UT_DEVICE) -#define UT_WRITE_CLASS_INTERFACE (UT_WRITE | UT_CLASS | UT_INTERFACE) -#define UT_WRITE_CLASS_OTHER (UT_WRITE | UT_CLASS | UT_OTHER) -#define UT_WRITE_CLASS_ENDPOINT (UT_WRITE | UT_CLASS | UT_ENDPOINT) -#define UT_READ_VENDOR_DEVICE (UT_READ | UT_VENDOR | UT_DEVICE) -#define UT_READ_VENDOR_INTERFACE (UT_READ | UT_VENDOR | UT_INTERFACE) -#define UT_READ_VENDOR_OTHER (UT_READ | UT_VENDOR | UT_OTHER) -#define UT_READ_VENDOR_ENDPOINT (UT_READ | UT_VENDOR | UT_ENDPOINT) -#define UT_WRITE_VENDOR_DEVICE (UT_WRITE | UT_VENDOR | UT_DEVICE) -#define UT_WRITE_VENDOR_INTERFACE (UT_WRITE | UT_VENDOR | UT_INTERFACE) -#define UT_WRITE_VENDOR_OTHER (UT_WRITE | UT_VENDOR | UT_OTHER) -#define UT_WRITE_VENDOR_ENDPOINT (UT_WRITE | UT_VENDOR | UT_ENDPOINT) - -/* Requests */ -#define UR_GET_STATUS 0x00 -#define UR_CLEAR_FEATURE 0x01 -#define UR_SET_FEATURE 0x03 -#define UR_SET_ADDRESS 0x05 -#define UR_GET_DESCRIPTOR 0x06 -#define UDESC_DEVICE 0x01 -#define UDESC_CONFIG 0x02 -#define UDESC_STRING 0x03 -#define UDESC_INTERFACE 0x04 -#define UDESC_ENDPOINT 0x05 -#define UDESC_DEVICE_QUALIFIER 0x06 -#define UDESC_OTHER_SPEED_CONFIGURATION 0x07 -#define UDESC_INTERFACE_POWER 0x08 -#define UDESC_OTG 0x09 -#define UDESC_CS_DEVICE 0x21 /* class specific */ -#define UDESC_CS_CONFIG 0x22 -#define UDESC_CS_STRING 0x23 -#define UDESC_CS_INTERFACE 0x24 -#define UDESC_CS_ENDPOINT 0x25 -#define UDESC_HUB 0x29 -#define UR_SET_DESCRIPTOR 0x07 -#define UR_GET_CONFIG 0x08 -#define UR_SET_CONFIG 0x09 -#define UR_GET_INTERFACE 0x0a -#define UR_SET_INTERFACE 0x0b -#define UR_SYNCH_FRAME 0x0c - -/* Feature numbers */ -#define UF_ENDPOINT_HALT 0 -#define UF_DEVICE_REMOTE_WAKEUP 1 -#define UF_TEST_MODE 2 - -#define USB_MAX_IPACKET 8 /* maximum size of the initial packet */ - -#define USB_2_MAX_CTRL_PACKET 64 -#define USB_2_MAX_BULK_PACKET 512 - -typedef struct { - uByte bLength; - uByte bDescriptorType; - uByte bDescriptorSubtype; -} UPACKED usb_descriptor_t; - -typedef struct { - uByte bLength; - uByte bDescriptorType; - uWord bcdUSB; -#define UD_USB_2_0 0x0200 -#define UD_IS_USB2(d) (UGETW((d)->bcdUSB) >= UD_USB_2_0) - uByte bDeviceClass; - uByte bDeviceSubClass; - uByte bDeviceProtocol; - uByte bMaxPacketSize; - /* The fields below are not part of the initial descriptor. */ - uWord idVendor; - uWord idProduct; - uWord bcdDevice; - uByte iManufacturer; - uByte iProduct; - uByte iSerialNumber; - uByte bNumConfigurations; -} UPACKED usb_device_descriptor_t; -#define USB_DEVICE_DESCRIPTOR_SIZE 18 - -typedef struct { - uByte bLength; - uByte bDescriptorType; - uWord wTotalLength; - uByte bNumInterface; - uByte bConfigurationValue; - uByte iConfiguration; - uByte bmAttributes; -#define UC_BUS_POWERED 0x80 -#define UC_SELF_POWERED 0x40 -#define UC_REMOTE_WAKEUP 0x20 - uByte bMaxPower; /* max current in 2 mA units */ -#define UC_POWER_FACTOR 2 -} UPACKED usb_config_descriptor_t; -#define USB_CONFIG_DESCRIPTOR_SIZE 9 - -typedef struct { - uByte bLength; - uByte bDescriptorType; - uByte bInterfaceNumber; - uByte bAlternateSetting; - uByte bNumEndpoints; - uByte bInterfaceClass; - uByte bInterfaceSubClass; - uByte bInterfaceProtocol; - uByte iInterface; -} UPACKED usb_interface_descriptor_t; -#define USB_INTERFACE_DESCRIPTOR_SIZE 9 - -typedef struct { - uByte bLength; - uByte bDescriptorType; - uByte bEndpointAddress; -#define UE_GET_DIR(a) ((a) & 0x80) -#define UE_SET_DIR(a,d) ((a) | (((d)&1) << 7)) -#define UE_DIR_IN 0x80 -#define UE_DIR_OUT 0x00 -#define UE_ADDR 0x0f -#define UE_GET_ADDR(a) ((a) & UE_ADDR) - uByte bmAttributes; -#define UE_XFERTYPE 0x03 -#define UE_CONTROL 0x00 -#define UE_ISOCHRONOUS 0x01 -#define UE_BULK 0x02 -#define UE_INTERRUPT 0x03 -#define UE_GET_XFERTYPE(a) ((a) & UE_XFERTYPE) -#define UE_ISO_TYPE 0x0c -#define UE_ISO_ASYNC 0x04 -#define UE_ISO_ADAPT 0x08 -#define UE_ISO_SYNC 0x0c -#define UE_GET_ISO_TYPE(a) ((a) & UE_ISO_TYPE) - uWord wMaxPacketSize; - uByte bInterval; -} UPACKED usb_endpoint_descriptor_t; -#define USB_ENDPOINT_DESCRIPTOR_SIZE 7 - -typedef struct { - uByte bLength; - uByte bDescriptorType; - uWord bString[127]; -} UPACKED usb_string_descriptor_t; -#define USB_MAX_STRING_LEN 128 -#define USB_LANGUAGE_TABLE 0 /* # of the string language id table */ - -/* Hub specific request */ -#define UR_GET_BUS_STATE 0x02 -#define UR_CLEAR_TT_BUFFER 0x08 -#define UR_RESET_TT 0x09 -#define UR_GET_TT_STATE 0x0a -#define UR_STOP_TT 0x0b - -/* Hub features */ -#define UHF_C_HUB_LOCAL_POWER 0 -#define UHF_C_HUB_OVER_CURRENT 1 -#define UHF_PORT_CONNECTION 0 -#define UHF_PORT_ENABLE 1 -#define UHF_PORT_SUSPEND 2 -#define UHF_PORT_OVER_CURRENT 3 -#define UHF_PORT_RESET 4 -#define UHF_PORT_POWER 8 -#define UHF_PORT_LOW_SPEED 9 -#define UHF_C_PORT_CONNECTION 16 -#define UHF_C_PORT_ENABLE 17 -#define UHF_C_PORT_SUSPEND 18 -#define UHF_C_PORT_OVER_CURRENT 19 -#define UHF_C_PORT_RESET 20 -#define UHF_PORT_TEST 21 -#define UHF_PORT_INDICATOR 22 - -typedef struct { - uByte bDescLength; - uByte bDescriptorType; - uByte bNbrPorts; - uWord wHubCharacteristics; -#define UHD_PWR 0x0003 -#define UHD_PWR_GANGED 0x0000 -#define UHD_PWR_INDIVIDUAL 0x0001 -#define UHD_PWR_NO_SWITCH 0x0002 -#define UHD_COMPOUND 0x0004 -#define UHD_OC 0x0018 -#define UHD_OC_GLOBAL 0x0000 -#define UHD_OC_INDIVIDUAL 0x0008 -#define UHD_OC_NONE 0x0010 -#define UHD_TT_THINK 0x0060 -#define UHD_TT_THINK_8 0x0000 -#define UHD_TT_THINK_16 0x0020 -#define UHD_TT_THINK_24 0x0040 -#define UHD_TT_THINK_32 0x0060 -#define UHD_PORT_IND 0x0080 - uByte bPwrOn2PwrGood; /* delay in 2 ms units */ -#define UHD_PWRON_FACTOR 2 - uByte bHubContrCurrent; - uByte DeviceRemovable[32]; /* max 255 ports */ -#define UHD_NOT_REMOV(desc, i) \ - (((desc)->DeviceRemovable[(i)/8] >> ((i) % 8)) & 1) - /* deprecated */ uByte PortPowerCtrlMask[1]; -} UPACKED usb_hub_descriptor_t; -#define USB_HUB_DESCRIPTOR_SIZE 9 /* includes deprecated PortPowerCtrlMask */ - -typedef struct { - uByte bLength; - uByte bDescriptorType; - uWord bcdUSB; - uByte bDeviceClass; - uByte bDeviceSubClass; - uByte bDeviceProtocol; - uByte bMaxPacketSize0; - uByte bNumConfigurations; - uByte bReserved; -} UPACKED usb_device_qualifier_t; -#define USB_DEVICE_QUALIFIER_SIZE 10 - -typedef struct { - uByte bLength; - uByte bDescriptorType; - uByte bmAttributes; -#define UOTG_SRP 0x01 -#define UOTG_HNP 0x02 -} UPACKED usb_otg_descriptor_t; - -/* OTG feature selectors */ -#define UOTG_B_HNP_ENABLE 3 -#define UOTG_A_HNP_SUPPORT 4 -#define UOTG_A_ALT_HNP_SUPPORT 5 - -typedef struct { - uWord wStatus; -/* Device status flags */ -#define UDS_SELF_POWERED 0x0001 -#define UDS_REMOTE_WAKEUP 0x0002 -/* Endpoint status flags */ -#define UES_HALT 0x0001 -} UPACKED usb_status_t; - -typedef struct { - uWord wHubStatus; -#define UHS_LOCAL_POWER 0x0001 -#define UHS_OVER_CURRENT 0x0002 - uWord wHubChange; -} UPACKED usb_hub_status_t; - -typedef struct { - uWord wPortStatus; -#define UPS_CURRENT_CONNECT_STATUS 0x0001 -#define UPS_PORT_ENABLED 0x0002 -#define UPS_SUSPEND 0x0004 -#define UPS_OVERCURRENT_INDICATOR 0x0008 -#define UPS_RESET 0x0010 -#define UPS_PORT_POWER 0x0100 -#define UPS_LOW_SPEED 0x0200 -#define UPS_HIGH_SPEED 0x0400 -#define UPS_PORT_TEST 0x0800 -#define UPS_PORT_INDICATOR 0x1000 - uWord wPortChange; -#define UPS_C_CONNECT_STATUS 0x0001 -#define UPS_C_PORT_ENABLED 0x0002 -#define UPS_C_SUSPEND 0x0004 -#define UPS_C_OVERCURRENT_INDICATOR 0x0008 -#define UPS_C_PORT_RESET 0x0010 -} UPACKED usb_port_status_t; - -/* Device class codes */ -#define UDCLASS_IN_INTERFACE 0x00 -#define UDCLASS_COMM 0x02 -#define UDCLASS_HUB 0x09 -#define UDSUBCLASS_HUB 0x00 -#define UDPROTO_FSHUB 0x00 -#define UDPROTO_HSHUBSTT 0x01 -#define UDPROTO_HSHUBMTT 0x02 -#define UDCLASS_DIAGNOSTIC 0xdc -#define UDCLASS_WIRELESS 0xe0 -#define UDSUBCLASS_RF 0x01 -#define UDPROTO_BLUETOOTH 0x01 -#define UDCLASS_VENDOR 0xff - -/* Interface class codes */ -#define UICLASS_UNSPEC 0x00 - -#define UICLASS_AUDIO 0x01 -#define UISUBCLASS_AUDIOCONTROL 1 -#define UISUBCLASS_AUDIOSTREAM 2 -#define UISUBCLASS_MIDISTREAM 3 - -#define UICLASS_CDC 0x02 /* communication */ -#define UISUBCLASS_DIRECT_LINE_CONTROL_MODEL 1 -#define UISUBCLASS_ABSTRACT_CONTROL_MODEL 2 -#define UISUBCLASS_TELEPHONE_CONTROL_MODEL 3 -#define UISUBCLASS_MULTICHANNEL_CONTROL_MODEL 4 -#define UISUBCLASS_CAPI_CONTROLMODEL 5 -#define UISUBCLASS_ETHERNET_NETWORKING_CONTROL_MODEL 6 -#define UISUBCLASS_ATM_NETWORKING_CONTROL_MODEL 7 -#define UIPROTO_CDC_AT 1 - -#define UICLASS_HID 0x03 -#define UISUBCLASS_BOOT 1 -#define UIPROTO_BOOT_KEYBOARD 1 - -#define UICLASS_PHYSICAL 0x05 - -#define UICLASS_IMAGE 0x06 - -#define UICLASS_PRINTER 0x07 -#define UISUBCLASS_PRINTER 1 -#define UIPROTO_PRINTER_UNI 1 -#define UIPROTO_PRINTER_BI 2 -#define UIPROTO_PRINTER_1284 3 - -#define UICLASS_MASS 0x08 -#define UISUBCLASS_RBC 1 -#define UISUBCLASS_SFF8020I 2 -#define UISUBCLASS_QIC157 3 -#define UISUBCLASS_UFI 4 -#define UISUBCLASS_SFF8070I 5 -#define UISUBCLASS_SCSI 6 -#define UIPROTO_MASS_CBI_I 0 -#define UIPROTO_MASS_CBI 1 -#define UIPROTO_MASS_BBB_OLD 2 /* Not in the spec anymore */ -#define UIPROTO_MASS_BBB 80 /* 'P' for the Iomega Zip drive */ - -#define UICLASS_HUB 0x09 -#define UISUBCLASS_HUB 0 -#define UIPROTO_FSHUB 0 -#define UIPROTO_HSHUBSTT 0 /* Yes, same as previous */ -#define UIPROTO_HSHUBMTT 1 - -#define UICLASS_CDC_DATA 0x0a -#define UISUBCLASS_DATA 0 -#define UIPROTO_DATA_ISDNBRI 0x30 /* Physical iface */ -#define UIPROTO_DATA_HDLC 0x31 /* HDLC */ -#define UIPROTO_DATA_TRANSPARENT 0x32 /* Transparent */ -#define UIPROTO_DATA_Q921M 0x50 /* Management for Q921 */ -#define UIPROTO_DATA_Q921 0x51 /* Data for Q921 */ -#define UIPROTO_DATA_Q921TM 0x52 /* TEI multiplexer for Q921 */ -#define UIPROTO_DATA_V42BIS 0x90 /* Data compression */ -#define UIPROTO_DATA_Q931 0x91 /* Euro-ISDN */ -#define UIPROTO_DATA_V120 0x92 /* V.24 rate adaption */ -#define UIPROTO_DATA_CAPI 0x93 /* CAPI 2.0 commands */ -#define UIPROTO_DATA_HOST_BASED 0xfd /* Host based driver */ -#define UIPROTO_DATA_PUF 0xfe /* see Prot. Unit Func. Desc.*/ -#define UIPROTO_DATA_VENDOR 0xff /* Vendor specific */ - -#define UICLASS_SMARTCARD 0x0b - -/*#define UICLASS_FIRM_UPD 0x0c*/ - -#define UICLASS_SECURITY 0x0d - -#define UICLASS_DIAGNOSTIC 0xdc - -#define UICLASS_WIRELESS 0xe0 -#define UISUBCLASS_RF 0x01 -#define UIPROTO_BLUETOOTH 0x01 - -#define UICLASS_APPL_SPEC 0xfe -#define UISUBCLASS_FIRMWARE_DOWNLOAD 1 -#define UISUBCLASS_IRDA 2 -#define UIPROTO_IRDA 0 - -#define UICLASS_VENDOR 0xff -#define UISUBCLASS_XBOX360_CONTROLLER 0x5d -#define UIPROTO_XBOX360_GAMEPAD 0x01 - - -#define USB_HUB_MAX_DEPTH 5 - -/* - * Minimum time a device needs to be powered down to go through - * a power cycle. XXX Are these time in the spec? - */ -#define USB_POWER_DOWN_TIME 200 /* ms */ -#define USB_PORT_POWER_DOWN_TIME 100 /* ms */ - -#if 0 -/* These are the values from the spec. */ -#define USB_PORT_RESET_DELAY 10 /* ms */ -#define USB_PORT_ROOT_RESET_DELAY 50 /* ms */ -#define USB_PORT_RESET_RECOVERY 10 /* ms */ -#define USB_PORT_POWERUP_DELAY 100 /* ms */ -#define USB_SET_ADDRESS_SETTLE 2 /* ms */ -#define USB_RESUME_DELAY (20*5) /* ms */ -#define USB_RESUME_WAIT 10 /* ms */ -#define USB_RESUME_RECOVERY 10 /* ms */ -#define USB_EXTRA_POWER_UP_TIME 0 /* ms */ -#else -/* Allow for marginal (i.e. non-conforming) devices. */ -#define USB_PORT_RESET_DELAY 50 /* ms */ -#define USB_PORT_ROOT_RESET_DELAY 250 /* ms */ -#define USB_PORT_RESET_RECOVERY 250 /* ms */ -#define USB_PORT_POWERUP_DELAY 300 /* ms */ -#define USB_SET_ADDRESS_SETTLE 10 /* ms */ -#define USB_RESUME_DELAY (50*5) /* ms */ -#define USB_RESUME_WAIT 50 /* ms */ -#define USB_RESUME_RECOVERY 50 /* ms */ -#define USB_EXTRA_POWER_UP_TIME 20 /* ms */ -#endif - -#define USB_MIN_POWER 100 /* mA */ -#define USB_MAX_POWER 500 /* mA */ - -#define USB_BUS_RESET_DELAY 100 /* ms XXX?*/ - - -#define USB_UNCONFIG_NO 0 -#define USB_UNCONFIG_INDEX (-1) - -/*** ioctl() related stuff ***/ - -struct usb_ctl_request { - int ucr_addr; - usb_device_request_t ucr_request; - void *ucr_data; - int ucr_flags; -#define USBD_SHORT_XFER_OK 0x04 /* allow short reads */ - int ucr_actlen; /* actual length transferred */ -}; - -struct usb_alt_interface { - int uai_config_index; - int uai_interface_index; - int uai_alt_no; -}; - -#define USB_CURRENT_CONFIG_INDEX (-1) -#define USB_CURRENT_ALT_INDEX (-1) - -struct usb_config_desc { - int ucd_config_index; - usb_config_descriptor_t ucd_desc; -}; - -struct usb_interface_desc { - int uid_config_index; - int uid_interface_index; - int uid_alt_index; - usb_interface_descriptor_t uid_desc; -}; - -struct usb_endpoint_desc { - int ued_config_index; - int ued_interface_index; - int ued_alt_index; - int ued_endpoint_index; - usb_endpoint_descriptor_t ued_desc; -}; - -struct usb_full_desc { - int ufd_config_index; - u_int ufd_size; - u_char *ufd_data; -}; - -struct usb_string_desc { - int usd_string_index; - int usd_language_id; - usb_string_descriptor_t usd_desc; -}; - -struct usb_ctl_report_desc { - int ucrd_size; - u_char ucrd_data[1024]; /* filled data size will vary */ -}; - -typedef struct { u_int32_t cookie; } usb_event_cookie_t; - -#define USB_MAX_DEVNAMES 4 -#define USB_MAX_DEVNAMELEN 16 -struct usb_device_info { - u_int8_t udi_bus; - u_int8_t udi_addr; /* device address */ - usb_event_cookie_t udi_cookie; - char udi_product[USB_MAX_STRING_LEN]; - char udi_vendor[USB_MAX_STRING_LEN]; - char udi_release[8]; - u_int16_t udi_productNo; - u_int16_t udi_vendorNo; - u_int16_t udi_releaseNo; - u_int8_t udi_class; - u_int8_t udi_subclass; - u_int8_t udi_protocol; - u_int8_t udi_config; - u_int8_t udi_speed; -#define USB_SPEED_LOW 1 -#define USB_SPEED_FULL 2 -#define USB_SPEED_HIGH 3 - int udi_power; /* power consumption in mA, 0 if selfpowered */ - int udi_nports; - char udi_devnames[USB_MAX_DEVNAMES][USB_MAX_DEVNAMELEN]; - u_int8_t udi_ports[16];/* hub only: addresses of devices on ports */ -#define USB_PORT_ENABLED 0xff -#define USB_PORT_SUSPENDED 0xfe -#define USB_PORT_POWERED 0xfd -#define USB_PORT_DISABLED 0xfc -}; - -struct usb_ctl_report { - int ucr_report; - u_char ucr_data[1024]; /* filled data size will vary */ -}; - -struct usb_device_stats { - u_long uds_requests[4]; /* indexed by transfer type UE_* */ -}; - -/* Events that can be read from /dev/usb */ -struct usb_event { - int ue_type; -#define USB_EVENT_CTRLR_ATTACH 1 -#define USB_EVENT_CTRLR_DETACH 2 -#define USB_EVENT_DEVICE_ATTACH 3 -#define USB_EVENT_DEVICE_DETACH 4 -#define USB_EVENT_DRIVER_ATTACH 5 -#define USB_EVENT_DRIVER_DETACH 6 -#define USB_EVENT_IS_ATTACH(n) ((n) == USB_EVENT_CTRLR_ATTACH || (n) == USB_EVENT_DEVICE_ATTACH || (n) == USB_EVENT_DRIVER_ATTACH) -#define USB_EVENT_IS_DETACH(n) ((n) == USB_EVENT_CTRLR_DETACH || (n) == USB_EVENT_DEVICE_DETACH || (n) == USB_EVENT_DRIVER_DETACH) - struct timespec ue_time; - union { - struct { - int ue_bus; - } ue_ctrlr; - struct usb_device_info ue_device; - struct { - usb_event_cookie_t ue_cookie; - char ue_devname[16]; - } ue_driver; - } u; -}; - -/* USB controller */ -#define USB_REQUEST _IOWR('U', 1, struct usb_ctl_request) -#define USB_SETDEBUG _IOW ('U', 2, int) -#define USB_DISCOVER _IO ('U', 3) -#define USB_DEVICEINFO _IOWR('U', 4, struct usb_device_info) -#define USB_DEVICESTATS _IOR ('U', 5, struct usb_device_stats) - -/* Generic HID device */ -#define USB_GET_REPORT_DESC _IOR ('U', 21, struct usb_ctl_report_desc) -#define USB_SET_IMMED _IOW ('U', 22, int) -#define USB_GET_REPORT _IOWR('U', 23, struct usb_ctl_report) -#define USB_SET_REPORT _IOW ('U', 24, struct usb_ctl_report) -#define USB_GET_REPORT_ID _IOR ('U', 25, int) - -/* Generic USB device */ -#define USB_GET_CONFIG _IOR ('U', 100, int) -#define USB_SET_CONFIG _IOW ('U', 101, int) -#define USB_GET_ALTINTERFACE _IOWR('U', 102, struct usb_alt_interface) -#define USB_SET_ALTINTERFACE _IOWR('U', 103, struct usb_alt_interface) -#define USB_GET_NO_ALT _IOWR('U', 104, struct usb_alt_interface) -#define USB_GET_DEVICE_DESC _IOR ('U', 105, usb_device_descriptor_t) -#define USB_GET_CONFIG_DESC _IOWR('U', 106, struct usb_config_desc) -#define USB_GET_INTERFACE_DESC _IOWR('U', 107, struct usb_interface_desc) -#define USB_GET_ENDPOINT_DESC _IOWR('U', 108, struct usb_endpoint_desc) -#define USB_GET_FULL_DESC _IOWR('U', 109, struct usb_full_desc) -#define USB_GET_STRING_DESC _IOWR('U', 110, struct usb_string_desc) -#define USB_DO_REQUEST _IOWR('U', 111, struct usb_ctl_request) -#define USB_GET_DEVICEINFO _IOR ('U', 112, struct usb_device_info) -#define USB_SET_SHORT_XFER _IOW ('U', 113, int) -#define USB_SET_TIMEOUT _IOW ('U', 114, int) - -/* Modem device */ -#define USB_GET_CM_OVER_DATA _IOR ('U', 130, int) -#define USB_SET_CM_OVER_DATA _IOW ('U', 131, int) - -#endif /* _USB_H_ */ diff --git a/sys/bus/usb/usb/Makefile b/sys/bus/usb/usb/Makefile deleted file mode 100644 index cd0aedb92f..0000000000 --- a/sys/bus/usb/usb/Makefile +++ /dev/null @@ -1,25 +0,0 @@ -# Makefile - module build for usb.ko - -S = ${.CURDIR}/../../.. -.PATH: $S/bus/pci $S/bus/usb - -KMOD = usb -SRCS = bus_if.h device_if.h usb_if.h usb_if.c \ - opt_usb.h opt_ktr.h \ - hid.c hid.h usbhid.h \ - uhub.c \ - usb.c usb.h \ - usb_mem.c usb_mem.h \ - usb_port.h \ - usb_quirks.c usb_quirks.h \ - usb_subr.c \ - usbdi.c usbdi.h usbdivar.h \ - usbdi_util.c usbdi_util.h \ - usb_ethersubr.c - -SRCS += uhci_pci.c uhci.c uhcireg.h uhcivar.h -SRCS += ohci_pci.c ohci.c ohcireg.h ohcivar.h -SRCS += pci_if.h - -.include - diff --git a/sys/bus/usb/usb_ethersubr.c b/sys/bus/usb/usb_ethersubr.c deleted file mode 100644 index fa990633e3..0000000000 --- a/sys/bus/usb/usb_ethersubr.c +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Copyright (c) 1997, 1998, 1999, 2000 - * Bill Paul . 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. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Bill Paul. - * 4. Neither the name of the author nor the names of any co-contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY Bill Paul 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 Bill Paul OR THE VOICES IN HIS HEAD - * 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: src/sys/dev/usb/usb_ethersubr.c,v 1.17 2003/11/14 11:09:45 johan Exp $ - * $DragonFly: src/sys/bus/usb/usb_ethersubr.c,v 1.21 2008/09/24 14:26:38 sephe Exp $ - */ - -/* - * Callbacks in the USB code operate in a critical section. - * - * It is conceivable that this arrangement could trigger a condition - * where the input queues could get trampled in spite of our best effors - * to prevent it. To work around this, we implement a special input queue - * for USB ethernet adapter drivers. Rather than passing the frames directly - * to ether_input(), we pass them here, then schedule a soft interrupt to - * hand them to ether_input() later, outside of the USB interrupt context. - * - * It's questional as to whether this code should be expanded to - * handle other kinds of devices, or handle USB transfer callbacks - * in general. Right now, I need USB network interfaces to work - * properly. - */ - -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include "usb.h" -#include "usb_ethersubr.h" - -static int netisr_inited = 0; - -static void -usbintr(netmsg_t msg) -{ - struct mbuf *m = msg->packet.nm_packet; - struct ifnet *ifp; - - /* not MPSAFE */ - get_mplock(); - ifp = m->m_pkthdr.rcvif; - ifp->if_input(ifp, m, NULL, -1); - /* the msg is embedded in the mbuf, do not reply it */ - rel_mplock(); -} - -void -usb_register_netisr(void) -{ - if (netisr_inited == 0) { - netisr_inited = 1; - netisr_register(NETISR_USB, usbintr, NULL); - } -} - -/* - * Must be called from a critical section. This should be the case when - * called from a transfer callback routine. Don't trust it, though. - */ -void -usb_ether_input(struct mbuf *m) -{ - crit_enter(); - netisr_queue(NETISR_USB, m); - crit_exit(); -} diff --git a/sys/bus/usb/usb_ethersubr.h b/sys/bus/usb/usb_ethersubr.h deleted file mode 100644 index 87667eb008..0000000000 --- a/sys/bus/usb/usb_ethersubr.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (c) 1997, 1998, 1999, 2000 - * Bill Paul . 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. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Bill Paul. - * 4. Neither the name of the author nor the names of any co-contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY Bill Paul 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 Bill Paul OR THE VOICES IN HIS HEAD - * 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: src/sys/dev/usb/usb_ethersubr.h,v 1.6 2003/03/04 23:19:55 jlemon Exp $ - * $DragonFly: src/sys/bus/usb/usb_ethersubr.h,v 1.5 2005/02/16 22:50:28 joerg Exp $ - */ - -#ifndef _USB_ETHERSUBR_H_ -#define _USB_ETHERSUBR_H_ - -struct usb_qdat { - struct ifnet *ifp; - void (*if_rxstart) (struct ifnet *); -}; - -void usb_register_netisr (void); -void usb_ether_input (struct mbuf *); - -#endif diff --git a/sys/bus/usb/usb_if.m b/sys/bus/usb/usb_if.m deleted file mode 100644 index a3ff90c135..0000000000 --- a/sys/bus/usb/usb_if.m +++ /dev/null @@ -1,43 +0,0 @@ -# -# Copyright (c) 1992-1998 Nick Hibma -# 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, -# without modification, immediately at the beginning of the file. -# 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. -# 3. The name of the author may not be used to endorse or promote products -# derived from this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 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: src/sys/dev/usb/usb_if.m,v 1.9 2000/04/08 14:17:05 dfr Exp $ -# $DragonFly: src/sys/bus/usb/usb_if.m,v 1.3 2003/12/30 01:01:44 dillon Exp $ -# - -# USB interface description -# - -#include - -INTERFACE usb; - -# The device should start probing for new drivers again -# -METHOD int reconfigure { - device_t dev; -}; diff --git a/sys/bus/usb/usb_mem.c b/sys/bus/usb/usb_mem.c deleted file mode 100644 index 9b42f79e56..0000000000 --- a/sys/bus/usb/usb_mem.c +++ /dev/null @@ -1,297 +0,0 @@ -/* - * $NetBSD: usb_mem.c,v 1.26 2003/02/01 06:23:40 thorpej Exp $ - * $FreeBSD: src/sys/dev/usb/usb_mem.c,v 1.5 2003/10/04 22:13:21 joe Exp $ - */ -/* - * Copyright (c) 1998 The NetBSD Foundation, Inc. - * All rights reserved. - * - * This code is derived from software contributed to The NetBSD Foundation - * by Lennart Augustsson (lennart@augustsson.net) at - * Carlstedt Research & Technology. - * - * 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. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the NetBSD - * Foundation, Inc. and its contributors. - * 4. Neither the name of The NetBSD Foundation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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. - */ - -/* - * USB DMA memory allocation. - * We need to allocate a lot of small (many 8 byte, some larger) - * memory blocks that can be used for DMA. Using the bus_dma - * routines directly would incur large overheads in space and time. - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#ifdef DIAGNOSTIC -#include -#endif -#include - -#include -#include -#include /* just for usb_dma_t */ -#include - -#define USBKTR_STRING "ptr=%p bus=%p size=%zu align=%zu" -#define USBKTR_ARGS void *p, usbd_bus_handle bus, size_t size, size_t align - -#if !defined(KTR_USB_MEMORY) -#define KTR_USB_MEMORY KTR_ALL -#endif -KTR_INFO_MASTER(usbmem); -KTR_INFO(KTR_USB_MEMORY, usbmem, alloc_full, 0, USBKTR_STRING, USBKTR_ARGS); -KTR_INFO(KTR_USB_MEMORY, usbmem, alloc_frag, 0, USBKTR_STRING, USBKTR_ARGS); -KTR_INFO(KTR_USB_MEMORY, usbmem, free_full, 0, USBKTR_STRING, USBKTR_ARGS); -KTR_INFO(KTR_USB_MEMORY, usbmem, free_frag, 0, USBKTR_STRING, USBKTR_ARGS); -KTR_INFO(KTR_USB_MEMORY, usbmem, blkalloc, 0, USBKTR_STRING, USBKTR_ARGS); -KTR_INFO(KTR_USB_MEMORY, usbmem, blkalloc2, 0, USBKTR_STRING, USBKTR_ARGS); -KTR_INFO(KTR_USB_MEMORY, usbmem, blkfree, 0, USBKTR_STRING, USBKTR_ARGS); - -#define logmemory(name, ptr, bus, size, align) \ - KTR_LOG(usbmem_ ## name, ptr, bus, size, align); - -#ifdef USB_DEBUG -#define DPRINTF(x) if (usbdebug) kprintf x -#define DPRINTFN(n,x) if (usbdebug>(n)) kprintf x -extern int usbdebug; -#else -#define DPRINTF(x) -#define DPRINTFN(n,x) -#endif - -#define USB_MEM_SMALL 64 -#define USB_MEM_CHUNKS (PAGE_SIZE / USB_MEM_SMALL) -#define USB_MEM_BLOCK (USB_MEM_SMALL * USB_MEM_CHUNKS) - -/* This struct is overlayed on free fragments. */ -struct usb_frag_dma { - usb_dma_block_t *block; - u_int offs; - LIST_ENTRY(usb_frag_dma) next; -}; - -static bus_dmamap_callback_t usbmem_callback; -static usbd_status usb_block_allocmem(bus_dma_tag_t, size_t, size_t, - usb_dma_block_t **); -static void usb_block_freemem(usb_dma_block_t *); - -static LIST_HEAD(, usb_dma_block) usb_blk_freelist = - LIST_HEAD_INITIALIZER(usb_blk_freelist); -static int usb_blk_nfree = 0; -/* XXX should have different free list for different tags (for speed) */ -static LIST_HEAD(, usb_frag_dma) usb_frag_freelist = - LIST_HEAD_INITIALIZER(usb_frag_freelist); - -static void -usbmem_callback(void *arg, bus_dma_segment_t *segs, int nseg, int error) -{ - int i; - usb_dma_block_t *p = arg; - - if (error == EFBIG) { - kprintf("usb: mapping to large\n"); - return; - } - - p->nsegs = nseg; - for (i = 0; i < nseg && i < sizeof p->segs / sizeof *p->segs; i++) - p->segs[i] = segs[i]; -} - -static usbd_status -usb_block_allocmem(bus_dma_tag_t tag, size_t size, size_t align, - usb_dma_block_t **dmap) -{ - usb_dma_block_t *p; - - DPRINTFN(5, ("usb_block_allocmem: size=%lu align=%lu\n", - (u_long)size, (u_long)align)); - - crit_enter(); - /* First check the free list. */ - for (p = LIST_FIRST(&usb_blk_freelist); p; p = LIST_NEXT(p, next)) { - if (p->tag == tag && p->size >= size && p->align >= align) { - LIST_REMOVE(p, next); - usb_blk_nfree--; - crit_exit(); - *dmap = p; - DPRINTFN(6,("usb_block_allocmem: free list size=%lu\n", - (u_long)p->size)); - logmemory(blkalloc2, p, NULL, size, align); - return (USBD_NORMAL_COMPLETION); - } - } - crit_exit(); - - DPRINTFN(6, ("usb_block_allocmem: no free\n")); - p = kmalloc(sizeof *p, M_USB, M_INTWAIT); - logmemory(blkalloc, p, NULL, size, align); - - if (bus_dma_tag_create(tag, align, 0, - BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, - size, NELEM(p->segs), size, BUS_DMA_ALLOCNOW, &p->tag) == ENOMEM) { - goto free; - } - - p->size = size; - p->align = align; - if (bus_dmamem_alloc(p->tag, &p->kaddr, - BUS_DMA_NOWAIT|BUS_DMA_COHERENT, &p->map)) - goto tagfree; - - if (bus_dmamap_load(p->tag, p->map, p->kaddr, p->size, - usbmem_callback, p, 0)) - goto memfree; - - /* XXX - override the tag, ok since we never free it */ - p->tag = tag; - *dmap = p; - return (USBD_NORMAL_COMPLETION); - - /* - * XXX - do we need to _unload? is the order of _free and _destroy - * correct? - */ -memfree: - bus_dmamem_free(p->tag, p->kaddr, p->map); -tagfree: - bus_dma_tag_destroy(p->tag); -free: - kfree(p, M_USB); - return (USBD_NOMEM); -} - -/* - * Do not free the memory unconditionally since we might be called - * from an interrupt context and that is BAD. - * XXX when should we really free? - */ -static void -usb_block_freemem(usb_dma_block_t *p) -{ - DPRINTFN(6, ("usb_block_freemem: size=%lu\n", (u_long)p->size)); - logmemory(blkfree, p, NULL, p->size, p->align); - crit_enter(); - LIST_INSERT_HEAD(&usb_blk_freelist, p, next); - usb_blk_nfree++; - crit_exit(); -} - -usbd_status -usb_allocmem(usbd_bus_handle bus, size_t size, size_t align, usb_dma_t *p) -{ - bus_dma_tag_t tag = bus->dmatag; - usbd_status err; - struct usb_frag_dma *f; - usb_dma_block_t *b; - int i; - - /* compat w/ Net/OpenBSD */ - if (align == 0) - align = 1; - - /* If the request is large then just use a full block. */ - if (size > USB_MEM_SMALL || align > USB_MEM_SMALL) { - DPRINTFN(1, ("usb_allocmem: large alloc %d\n", (int)size)); - size = (size + USB_MEM_BLOCK - 1) & ~(USB_MEM_BLOCK - 1); - err = usb_block_allocmem(tag, size, align, &p->block); - if (!err) { - p->block->fullblock = 1; - p->offs = 0; - p->len = size; - logmemory(alloc_full, p, NULL, size, align); - } - return (err); - } - - crit_enter(); - /* Check for free fragments. */ - for (f = LIST_FIRST(&usb_frag_freelist); f; f = LIST_NEXT(f, next)) - if (f->block->tag == tag) - break; - if (f == NULL) { - DPRINTFN(1, ("usb_allocmem: adding fragments\n")); - err = usb_block_allocmem(tag, USB_MEM_BLOCK, USB_MEM_SMALL,&b); - if (err) { - crit_exit(); - return (err); - } - b->fullblock = 0; - /* XXX - override the tag, ok since we never free it */ - b->tag = tag; - KASSERT(sizeof *f <= USB_MEM_SMALL, ("USB_MEM_SMALL(%d) is too small for struct usb_frag_dma(%zd)", - USB_MEM_SMALL, sizeof *f)); - for (i = 0; i < USB_MEM_BLOCK; i += USB_MEM_SMALL) { - f = (struct usb_frag_dma *)((char *)b->kaddr + i); - f->block = b; - f->offs = i; - LIST_INSERT_HEAD(&usb_frag_freelist, f, next); - } - f = LIST_FIRST(&usb_frag_freelist); - } - p->block = f->block; - p->offs = f->offs; - p->len = USB_MEM_SMALL; - LIST_REMOVE(f, next); - crit_exit(); - logmemory(alloc_frag, p, NULL, size, align); - DPRINTFN(5, ("usb_allocmem: use frag=%p size=%d\n", f, (int)size)); - return (USBD_NORMAL_COMPLETION); -} - -void -usb_freemem(usbd_bus_handle bus, usb_dma_t *p) -{ - struct usb_frag_dma *f; - - if (p->block->fullblock) { - DPRINTFN(1, ("usb_freemem: large free\n")); - usb_block_freemem(p->block); - logmemory(free_full, p, bus, (size_t)0, (size_t)0); - return; - } - logmemory(free_frag, p, bus, (size_t)0, (size_t)0); - f = KERNADDR(p, 0); - f->block = p->block; - f->offs = p->offs; - crit_enter(); - LIST_INSERT_HEAD(&usb_frag_freelist, f, next); - crit_exit(); - DPRINTFN(5, ("usb_freemem: frag=%p\n", f)); -} diff --git a/sys/bus/usb/usb_mem.h b/sys/bus/usb/usb_mem.h deleted file mode 100644 index ee07eb92e2..0000000000 --- a/sys/bus/usb/usb_mem.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - * $NetBSD: usb_mem.h,v 1.18 2002/05/28 17:45:17 augustss Exp $ - * $FreeBSD: src/sys/dev/usb/usb_mem.h,v 1.20 2003/09/01 01:07:24 jmg Exp $ - * $DragonFly: src/sys/bus/usb/usb_mem.h,v 1.5 2007/06/27 12:27:59 hasso Exp $ - */ - -/* - * Copyright (c) 1998 The NetBSD Foundation, Inc. - * All rights reserved. - * - * This code is derived from software contributed to The NetBSD Foundation - * by Lennart Augustsson (lennart@augustsson.net) at - * Carlstedt Research & Technology. - * - * 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. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the NetBSD - * Foundation, Inc. and its contributors. - * 4. Neither the name of The NetBSD Foundation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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. - */ - -typedef struct usb_dma_block { - bus_dma_tag_t tag; - bus_dmamap_t map; - void *kaddr; - bus_dma_segment_t segs[1]; - int nsegs; - size_t size; - size_t align; - int fullblock; - LIST_ENTRY(usb_dma_block) next; -} usb_dma_block_t; - -#define DMAADDR(dma, o) ((dma)->block->segs[0].ds_addr + (dma)->offs + (o)) -#define KERNADDR(dma, o) \ - ((void *)((char *)((dma)->block->kaddr) + (dma)->offs + (o))) - -usbd_status usb_allocmem(usbd_bus_handle,size_t,size_t, usb_dma_t *); -void usb_freemem(usbd_bus_handle, usb_dma_t *); diff --git a/sys/bus/usb/usb_port.h b/sys/bus/usb/usb_port.h deleted file mode 100644 index cda408c251..0000000000 --- a/sys/bus/usb/usb_port.h +++ /dev/null @@ -1,191 +0,0 @@ -/* - * $OpenBSD: usb_port.h,v 1.18 2000/09/06 22:42:10 rahnds Exp $ - * $NetBSD: usb_port.h,v 1.68 2005/07/30 06:14:50 skrll Exp $ - * $FreeBSD: src/sys/dev/usb/usb_port.h,v 1.65 2003/11/09 23:54:21 joe Exp $ - */ - -/* Also already merged from NetBSD: - * $NetBSD: usb_port.h,v 1.57 2002/09/27 20:42:01 thorpej Exp $ - * $NetBSD: usb_port.h,v 1.58 2002/10/01 01:25:26 thorpej Exp $ - */ - -/* - * Copyright (c) 1998 The NetBSD Foundation, Inc. - * All rights reserved. - * - * This code is derived from software contributed to The NetBSD Foundation - * by Lennart Augustsson (lennart@augustsson.net) at - * Carlstedt Research & Technology. - * - * 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. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the NetBSD - * Foundation, Inc. and its contributors. - * 4. Neither the name of The NetBSD Foundation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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. - */ - -#ifndef _USB_PORT_H -#define _USB_PORT_H - -/* - * Macros to ease the import of USB drivers from other BSD systems. Drivers - * in the DragonFly tree don't use any of these macros. - * - * Driver that wants to use these can simply include . - */ - -#include "opt_usb.h" - -#define Static static - -#define device_ptr_t device_t -#define USBBASEDEVICE device_t -#define USBDEV(bdev) (bdev) -#define USBDEVNAME(bdev) device_get_nameunit(bdev) -#define USBDEVUNIT(bdev) device_get_unit(bdev) -#define USBDEVPTRNAME(bdev) device_get_nameunit(bdev) -#define USBGETSOFTC(bdev) (device_get_softc(bdev)) - -#define DECLARE_USB_DMA_T \ - struct usb_dma_block; \ - typedef struct { \ - struct usb_dma_block *block; \ - u_int offs; \ - u_int len; \ - } usb_dma_t - -#define PROC_LOCK(p) -#define PROC_UNLOCK(p) -#define uio_procp uio_td - -typedef struct thread *usb_proc_ptr; - -#define config_pending_incr() -#define config_pending_decr() - -#define usb_kthread_create(f, s) \ - kthread_create(f, s, NULL, "dummy") -#define usb_kthread_create1(f, s, p, name, arg) \ - kthread_create(f, s, p, name, arg) -#define usb_kthread_create2(f, s, p, name) \ - kthread_create(f, s, p, name) - -typedef struct callout usb_callout_t; -#define usb_callout_init(h) callout_init(&(h)) -#define usb_callout(h, t, f, d) callout_reset(&(h), (t), (f), (d)) -#define usb_uncallout(h, f, d) callout_stop(&(h)) - -#define clalloc(p, s, x) (clist_alloc_cblocks((p), (s), (s)), 0) -#define clfree(p) clist_free_cblocks((p)) - -#define config_detach(dev, flag) device_delete_child(device_get_parent(dev), dev) - -typedef struct malloc_type *usb_malloc_type; - -#define USB_DECLARE_DRIVER_INIT(dname, init...) \ -Static device_probe_t __CONCAT(dname,_match); \ -Static device_attach_t __CONCAT(dname,_attach); \ -Static device_detach_t __CONCAT(dname,_detach); \ -\ -Static devclass_t __CONCAT(dname,_devclass); \ -\ -Static device_method_t __CONCAT(dname,_methods)[] = { \ - DEVMETHOD(device_probe, __CONCAT(dname,_match)), \ - DEVMETHOD(device_attach, __CONCAT(dname,_attach)), \ - DEVMETHOD(device_detach, __CONCAT(dname,_detach)), \ - init, \ - DEVMETHOD_END \ -}; \ -\ -Static driver_t __CONCAT(dname,_driver) = { \ - #dname, \ - __CONCAT(dname,_methods), \ - sizeof(struct __CONCAT(dname,_softc)) \ -}; \ -MODULE_DEPEND(dname, usb, 1, 1, 1) - - -#define METHODS_NONE {0,0} -#define USB_DECLARE_DRIVER(dname) USB_DECLARE_DRIVER_INIT(dname, METHODS_NONE) - -#define USB_MATCH(dname) \ -Static int \ -__CONCAT(dname,_match)(device_t self) - -#define USB_MATCH_START(dname, uaa) \ - struct usb_attach_arg *uaa = device_get_ivars(self) - -#define USB_MATCH_SETUP() - -#define USB_ATTACH(dname) \ -Static int \ -__CONCAT(dname,_attach)(device_t self) - -#define USB_ATTACH_START(dname, sc, uaa) \ - struct __CONCAT(dname,_softc) *sc = device_get_softc(self); \ - struct usb_attach_arg *uaa = device_get_ivars(self) - -/* Returns from attach */ -#define USB_ATTACH_ERROR_RETURN return ENXIO -#define USB_ATTACH_SUCCESS_RETURN return 0 - -#define USB_ATTACH_SETUP \ - device_set_desc_copy(self, devinfo) - -#define USB_DETACH(dname) \ -Static int \ -__CONCAT(dname,_detach)(device_t self) - -#define USB_DETACH_START(dname, sc) \ - struct __CONCAT(dname,_softc) *sc = device_get_softc(self) - -#define USB_GET_SC_OPEN(dname, unit, sc) \ - sc = devclass_get_softc(__CONCAT(dname,_devclass), unit); \ - if (sc == NULL) \ - return (ENXIO) - -#define USB_GET_SC(dname, unit, sc) \ - sc = devclass_get_softc(__CONCAT(dname,_devclass), unit) - -#define USB_DO_ATTACH(dev, bdev, parent, args, print, sub) \ - (device_probe_and_attach((bdev)) == 0 ? (bdev) : 0) - -/* conversion from one type of queue to the other */ -#define SIMPLEQ_REMOVE_HEAD STAILQ_REMOVE_HEAD -#define SIMPLEQ_INSERT_HEAD STAILQ_INSERT_HEAD -#define SIMPLEQ_INSERT_TAIL STAILQ_INSERT_TAIL -#define SIMPLEQ_NEXT STAILQ_NEXT -#define SIMPLEQ_FIRST STAILQ_FIRST -#define SIMPLEQ_HEAD STAILQ_HEAD -#define SIMPLEQ_EMPTY STAILQ_EMPTY -#define SIMPLEQ_FOREACH STAILQ_FOREACH -#define SIMPLEQ_INIT STAILQ_INIT -#define SIMPLEQ_HEAD_INITIALIZER STAILQ_HEAD_INITIALIZER -#define SIMPLEQ_ENTRY STAILQ_ENTRY - -#define logprintf kprintf - -#endif /* _USB_PORT_H */ - diff --git a/sys/bus/usb/usb_quirks.c b/sys/bus/usb/usb_quirks.c deleted file mode 100644 index a222f321dc..0000000000 --- a/sys/bus/usb/usb_quirks.c +++ /dev/null @@ -1,197 +0,0 @@ -/* $NetBSD: usb_quirks.c,v 1.50 2004/06/23 02:30:52 mycroft Exp $ */ -/* $FreeBSD: src/sys/dev/usb/usb_quirks.c,v 1.41.2.4 2006/02/15 22:51:08 iedowse Exp $ */ -/* $DragonFly: src/sys/bus/usb/usb_quirks.c,v 1.9 2007/11/05 19:09:42 hasso Exp $ */ - -/* - * Copyright (c) 1998 The NetBSD Foundation, Inc. - * All rights reserved. - * - * This code is derived from software contributed to The NetBSD Foundation - * by Lennart Augustsson (lennart@augustsson.net) at - * Carlstedt Research & Technology. - * - * 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. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the NetBSD - * Foundation, Inc. and its contributors. - * 4. Neither the name of The NetBSD Foundation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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 -#include - -#include -#include - -#ifdef USB_DEBUG -extern int usbdebug; -#endif - -#define ANY 0xffff - -static const struct usbd_quirk_entry { - u_int16_t idVendor; - u_int16_t idProduct; - u_int16_t bcdDevice; - struct usbd_quirks quirks; -} usb_quirks[] = { - /* KYE Niche mouse */ - { .idVendor = 0x0458, .idProduct = 0x0001, .bcdDevice = 0x100, - .quirks = { UQ_NO_SET_PROTO}}, - /* Inside Out Networks EdgePort/4 RS232 */ - { .idVendor = 0x1608, .idProduct = 0x0001, .bcdDevice = 0x094, - .quirks = { UQ_SWAP_UNICODE}}, - /* Dallas Semiconductor J-6502 speakers */ - { .idVendor = 0x04fa, .idProduct = 0x4201, .bcdDevice = 0x0a2, - .quirks = { UQ_BAD_ADC | UQ_AU_NO_XU }}, - /* Altec Lansing ADA70 speakers */ - { .idVendor = 0x04d2, .idProduct = 0x0070, .bcdDevice = 0x103, - .quirks = { UQ_BAD_ADC }}, - /* Altec Lansing ASC495 speakers */ - { .idVendor = 0x04d2, .idProduct = 0xff05, .bcdDevice = 0x000, - .quirks = { UQ_BAD_AUDIO }}, - /* Qtronix Scorpion-980N keyboard */ - { .idVendor = 0x05c7, .idProduct = 0x2011, .bcdDevice = 0x110, - .quirks = { UQ_SPUR_BUT_UP }}, - /* Alcor Micro, Inc. kbd hub */ - { .idVendor = 0x0566, .idProduct = 0x2802, .bcdDevice = 0x001, - .quirks = { UQ_SPUR_BUT_UP }}, - /* MCT Corp. hub */ - { .idVendor = 0x0711, .idProduct = 0x0100, .bcdDevice = 0x102, - .quirks = { UQ_BUS_POWERED }}, - /* MCT Corp. USB-232 interface */ - { .idVendor = 0x0711, .idProduct = 0x0210, .bcdDevice = 0x102, - .quirks = { UQ_BUS_POWERED }}, - /* Metricom Ricochet GS */ - { .idVendor = 0x0870, .idProduct = 0x0001, .bcdDevice = 0x100, - .quirks = { UQ_ASSUME_CM_OVER_DATA }}, - /* Sanyo SCP-4900 USB Phone */ - { .idVendor = 0x0474, .idProduct = 0x0701, .bcdDevice = 0x000, - .quirks = { UQ_ASSUME_CM_OVER_DATA }}, - /* Texas Instruments UT-USB41 hub */ - { .idVendor = 0x0451, .idProduct = 0x1446, .bcdDevice = 0x110, - .quirks = { UQ_POWER_CLAIM }}, - /* Telex Communications Enhanced USB Microphone */ - { .idVendor = 0x0562, .idProduct = 0x0001, .bcdDevice = 0x009, - .quirks = { UQ_AU_NO_FRAC }}, - /* Silicon Portals Inc. YAP Phone */ - { .idVendor = 0x1527, .idProduct = 0x0201, .bcdDevice = 0x100, - .quirks = { UQ_AU_INP_ASYNC }}, - - /* - * XXX All these HP devices should have a revision number, - * but I don't know what they are. - */ - /* HP DeskJet 895C */ - { .idVendor = 0x03f0, .idProduct = 0x0004, .bcdDevice = ANY, - .quirks = { UQ_BROKEN_BIDIR }}, - /* HP DeskJet 880C */ - { .idVendor = 0x03f0, .idProduct = 0x0104, .bcdDevice = ANY, - .quirks = { UQ_BROKEN_BIDIR }}, - /* HP DeskJet 815C */ - { .idVendor = 0x03f0, .idProduct = 0x0204, .bcdDevice = ANY, - .quirks = { UQ_BROKEN_BIDIR }}, - /* HP DeskJet 810C/812C */ - { .idVendor = 0x03f0, .idProduct = 0x0304, .bcdDevice = ANY, - .quirks = { UQ_BROKEN_BIDIR }}, - /* HP DeskJet 830C */ - { .idVendor = 0x03f0, .idProduct = 0x0404, .bcdDevice = ANY, - .quirks = { UQ_BROKEN_BIDIR }}, - /* HP DeskJet 1220C */ - { .idVendor = 0x03f0, .idProduct = 0x0212, .bcdDevice = ANY, - .quirks = { UQ_BROKEN_BIDIR }}, - - /* - * YAMAHA router's ucdDevice is the version of firmware and - * often changes. - */ - /* YAMAHA NetVolante RTA54i Broadband&ISDN Router */ - { .idVendor = 0x0499, .idProduct = 0x4000, .bcdDevice = ANY, - .quirks = { UQ_ASSUME_CM_OVER_DATA }}, - /* YAMAHA NetVolante RTA55i Broadband VoIP Router */ - { .idVendor = 0x0499, .idProduct = 0x4004, .bcdDevice = ANY, - .quirks = { UQ_ASSUME_CM_OVER_DATA }}, - /* YAMAHA NetVolante RTW65b Broadband Wireless Router */ - { .idVendor = 0x0499, .idProduct = 0x4001, .bcdDevice = ANY, - .quirks = { UQ_ASSUME_CM_OVER_DATA }}, - /* YAMAHA NetVolante RTW65i Broadband&ISDN Wireless Router */ - { .idVendor = 0x0499, .idProduct = 0x4002, .bcdDevice = ANY, - .quirks = { UQ_ASSUME_CM_OVER_DATA }}, - - /* Qualcomm CDMA Technologies MSM modem */ - { .idVendor = 0x05c6, .idProduct = 0x3196, .bcdDevice = ANY, - .quirks = { UQ_ASSUME_CM_OVER_DATA }}, - /* Qualcomm CDMA Technologies MSM phone */ - { .idVendor = 0x1004, .idProduct = 0x6000, .bcdDevice = ANY, - .quirks = { UQ_ASSUME_CM_OVER_DATA }}, - /* SUNTAC U-Cable type A3 */ - { .idVendor = 0x05db, .idProduct = 0x000b, .bcdDevice = 0x100, - .quirks = { UQ_ASSUME_CM_OVER_DATA }}, - - /* Devices which should be ignored by uhid */ - /* APC Back-UPS Pro 500 */ - { .idVendor = 0x051d, .idProduct = 0x0002, .bcdDevice = ANY, - .quirks = { UQ_HID_IGNORE }}, - /* Delorme Publishing Earthmate GPS */ - { .idVendor = 0x1163, .idProduct = 0x0100, .bcdDevice = ANY, - .quirks = { UQ_HID_IGNORE }}, - /* MGE UPS Systems ProtectionCenter */ - { .idVendor = 0x0463, .idProduct = 0x0001, .bcdDevice = ANY, - .quirks = { UQ_HID_IGNORE }}, - /* MGE UPS Systems ProtectionCenter */ - { .idVendor = 0x0463, .idProduct = 0xffff, .bcdDevice = ANY, - .quirks = { UQ_HID_IGNORE }}, - - /* Apple usb keyboard */ - { .idVendor = 0x05ac, .idProduct = 0x0221, .bcdDevice = ANY, - .quirks = { UQ_NO_SET_PROTO}}, - - { 0, 0, 0, { 0 } } -}; - -const struct usbd_quirks usbd_no_quirk = { 0 }; - -const struct usbd_quirks * -usbd_find_quirk(usb_device_descriptor_t *d) -{ - const struct usbd_quirk_entry *t; - u_int16_t vendor = UGETW(d->idVendor); - u_int16_t product = UGETW(d->idProduct); - u_int16_t revision = UGETW(d->bcdDevice); - - for (t = usb_quirks; t->idVendor != 0; t++) { - if (t->idVendor == vendor && - t->idProduct == product && - (t->bcdDevice == ANY || t->bcdDevice == revision)) - break; - } -#ifdef USB_DEBUG - if (usbdebug && t->quirks.uq_flags) - kprintf("usbd_find_quirk 0x%04x/0x%04x/%x: %d\n", - UGETW(d->idVendor), UGETW(d->idProduct), - UGETW(d->bcdDevice), t->quirks.uq_flags); -#endif - return (&t->quirks); -} diff --git a/sys/bus/usb/usb_quirks.h b/sys/bus/usb/usb_quirks.h deleted file mode 100644 index bcf1bd40a4..0000000000 --- a/sys/bus/usb/usb_quirks.h +++ /dev/null @@ -1,64 +0,0 @@ -/* $NetBSD: usb_quirks.h,v 1.20 2001/04/15 09:38:01 augustss Exp $ */ -/* $FreeBSD: src/sys/dev/usb/usb_quirks.h,v 1.17.2.3 2006/02/15 22:51:08 iedowse Exp $ */ -/* $DragonFly: src/sys/bus/usb/usb_quirks.h,v 1.4 2006/12/10 02:03:56 sephe Exp $ */ - -/* - * Copyright (c) 1998 The NetBSD Foundation, Inc. - * All rights reserved. - * - * This code is derived from software contributed to The NetBSD Foundation - * by Lennart Augustsson (lennart@augustsson.net) at - * Carlstedt Research & Technology. - * - * 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. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the NetBSD - * Foundation, Inc. and its contributors. - * 4. Neither the name of The NetBSD Foundation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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. - */ - -struct usbd_quirks { - u_int32_t uq_flags; /* Device problems: */ -#define UQ_NO_SET_PROTO 0x0001 /* cannot handle SET PROTOCOL. */ -#define UQ_SWAP_UNICODE 0x0002 /* has some Unicode strings swapped. */ -#define UQ_MS_REVZ 0x0004 /* mouse has Z-axis reversed */ -#define UQ_NO_STRINGS 0x0008 /* string descriptors are broken. */ -#define UQ_BAD_ADC 0x0010 /* bad audio spec version number. */ -#define UQ_BUS_POWERED 0x0020 /* device is bus powered, despite claim */ -#define UQ_BAD_AUDIO 0x0040 /* device claims audio class, but isn't */ -#define UQ_SPUR_BUT_UP 0x0080 /* spurious mouse button up events */ -#define UQ_AU_NO_XU 0x0100 /* audio device has broken extension unit */ -#define UQ_POWER_CLAIM 0x0200 /* hub lies about power status */ -#define UQ_AU_NO_FRAC 0x0400 /* don't adjust for fractional samples */ -#define UQ_AU_INP_ASYNC 0x0800 /* input is async despite claim of adaptive */ -#define UQ_ASSUME_CM_OVER_DATA 0x1000 /* modem device breaks on cm over data */ -#define UQ_BROKEN_BIDIR 0x2000 /* printer has broken bidir mode */ -#define UQ_HID_IGNORE 0x8000 /* device should be ignored by hid class */ - -}; - -extern const struct usbd_quirks usbd_no_quirk; - -const struct usbd_quirks *usbd_find_quirk(usb_device_descriptor_t *); diff --git a/sys/bus/usb/usb_subr.c b/sys/bus/usb/usb_subr.c deleted file mode 100644 index 18c916a46e..0000000000 --- a/sys/bus/usb/usb_subr.c +++ /dev/null @@ -1,1275 +0,0 @@ -/* $NetBSD: usb_subr.c,v 1.99 2002/07/11 21:14:34 augustss Exp $ */ -/* $FreeBSD: src/sys/dev/usb/usb_subr.c,v 1.76.2.3 2006/03/01 01:59:05 iedowse Exp $ */ - -/* Also already have from NetBSD: - * $NetBSD: usb_subr.c,v 1.102 2003/01/01 16:21:50 augustss Exp $ - * $NetBSD: usb_subr.c,v 1.103 2003/01/10 11:19:13 augustss Exp $ - * $NetBSD: usb_subr.c,v 1.111 2004/03/15 10:35:04 augustss Exp $ - * $NetBSD: usb_subr.c,v 1.114 2004/06/23 02:30:52 mycroft Exp $ - * $NetBSD: usb_subr.c,v 1.115 2004/06/23 05:23:19 mycroft Exp $ - * $NetBSD: usb_subr.c,v 1.116 2004/06/23 06:27:54 mycroft Exp $ - * $NetBSD: usb_subr.c,v 1.119 2004/10/23 13:26:33 augustss Exp $ - */ - -/* - * Copyright (c) 1998 The NetBSD Foundation, Inc. - * All rights reserved. - * - * This code is derived from software contributed to The NetBSD Foundation - * by Lennart Augustsson (lennart@augustsson.net) at - * Carlstedt Research & Technology. - * - * 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. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the NetBSD - * Foundation, Inc. and its contributors. - * 4. Neither the name of The NetBSD Foundation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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 "opt_usb.h" - -#include -#include -#include -#include -#include -#include -#include - -#include - -#include -#include -#include -#include - -#define delay(d) DELAY(d) - -#ifdef USB_DEBUG -#define DPRINTF(x) if (usbdebug) kprintf x -#define DPRINTFN(n,x) if (usbdebug>(n)) kprintf x -extern int usbdebug; -#else -#define DPRINTF(x) -#define DPRINTFN(n,x) -#endif - -static usbd_status usbd_set_config(usbd_device_handle, int); -static void usbd_devinfo_vp(usbd_device_handle, char *, char *, int); -static int usbd_getnewaddr(usbd_bus_handle bus); -static void usbd_free_iface_data(usbd_device_handle dev, int ifcno); -static void usbd_kill_pipe(usbd_pipe_handle); -static usbd_status usbd_probe_and_attach(device_t parent, - usbd_device_handle dev, int port, int addr); - -static u_int32_t usb_cookie_no = 0; - -static const char * const usbd_error_strs[] = { - "NORMAL_COMPLETION", - "IN_PROGRESS", - "PENDING_REQUESTS", - "NOT_STARTED", - "INVAL", - "NOMEM", - "CANCELLED", - "BAD_ADDRESS", - "IN_USE", - "NO_ADDR", - "SET_ADDR_FAILED", - "NO_POWER", - "TOO_DEEP", - "IOERROR", - "NOT_CONFIGURED", - "TIMEOUT", - "SHORT_XFER", - "STALLED", - "INTERRUPTED", - "XXX", -}; - -const char * -usbd_errstr(usbd_status err) -{ - static char buffer[5]; - - if (err < USBD_ERROR_MAX) { - return usbd_error_strs[err]; - } else { - ksnprintf(buffer, sizeof buffer, "%d", err); - return buffer; - } -} - -usbd_status -usbd_get_string_desc(usbd_device_handle dev, int sindex, int langid, - usb_string_descriptor_t *sdesc, int *sizep) -{ - usb_device_request_t req; - usbd_status err; - int actlen; - - req.bmRequestType = UT_READ_DEVICE; - req.bRequest = UR_GET_DESCRIPTOR; - USETW2(req.wValue, UDESC_STRING, sindex); - USETW(req.wIndex, langid); - USETW(req.wLength, 2); /* only size byte first */ - err = usbd_do_request_flags(dev, &req, sdesc, USBD_SHORT_XFER_OK, - &actlen, USBD_DEFAULT_TIMEOUT); - if (err) - return (err); - - if (actlen < 2) - return (USBD_SHORT_XFER); - - USETW(req.wLength, sdesc->bLength); /* the whole string */ - err = usbd_do_request_flags(dev, &req, sdesc, USBD_SHORT_XFER_OK, - &actlen, USBD_DEFAULT_TIMEOUT); - if (err) - return (err); - - if (actlen != sdesc->bLength) { - DPRINTFN(-1, ("usbd_get_string_desc: expected %d, got %d\n", - sdesc->bLength, actlen)); - } - - *sizep = actlen; - return (USBD_NORMAL_COMPLETION); -} - -static void -usbd_trim_spaces(char *p) -{ - char *q, *e; - - if (p == NULL) - return; - q = e = p; - while (*q == ' ') /* skip leading spaces */ - q++; - while ((*p = *q++)) /* copy string */ - if (*p++ != ' ') /* remember last non-space */ - e = p; - *e = 0; /* kill trailing spaces */ -} - -static void -usbd_devinfo_vp(usbd_device_handle dev, char *v, char *p, int usedev) -{ - usb_device_descriptor_t *udd = &dev->ddesc; - char *vendor = NULL, *product = NULL; - - if (dev == NULL) { - v[0] = p[0] = '\0'; - return; - } - - if (usedev) { - if (usbd_get_string(dev, udd->iManufacturer, v)) - vendor = NULL; - else - vendor = v; - usbd_trim_spaces(vendor); - if (usbd_get_string(dev, udd->iProduct, p)) - product = NULL; - else - product = p; - usbd_trim_spaces(product); - if (vendor && !*vendor) - vendor = NULL; - if (product && !*product) - product = NULL; - } else { - vendor = NULL; - product = NULL; - } - - if (vendor != NULL && *vendor) - strcpy(v, vendor); - else - ksprintf(v, "vendor 0x%04x", UGETW(udd->idVendor)); - if (product != NULL && *product) - strcpy(p, product); - else - ksprintf(p, "product 0x%04x", UGETW(udd->idProduct)); -} - -int -usbd_printBCD(char *cp, int bcd) -{ - return (ksprintf(cp, "%x.%02x", bcd >> 8, bcd & 0xff)); -} - -void -usbd_devinfo(usbd_device_handle dev, int showclass, char *cp) -{ - usb_device_descriptor_t *udd = &dev->ddesc; - usbd_interface_handle iface; - char vendor[USB_MAX_STRING_LEN]; - char product[USB_MAX_STRING_LEN]; - int bcdDevice, bcdUSB; - usb_interface_descriptor_t *id; - - usbd_devinfo_vp(dev, vendor, product, 1); - cp += ksprintf(cp, "%s %s", vendor, product); - if (showclass & USBD_SHOW_DEVICE_CLASS) - cp += ksprintf(cp, ", class %d/%d", - udd->bDeviceClass, udd->bDeviceSubClass); - bcdUSB = UGETW(udd->bcdUSB); - bcdDevice = UGETW(udd->bcdDevice); - cp += ksprintf(cp, ", rev "); - cp += usbd_printBCD(cp, bcdUSB); - *cp++ = '/'; - cp += usbd_printBCD(cp, bcdDevice); - cp += ksprintf(cp, ", addr %d", dev->address); - if (showclass & USBD_SHOW_INTERFACE_CLASS) - { - /* fetch the interface handle for the first interface */ - (void)usbd_device2interface_handle(dev, 0, &iface); - id = usbd_get_interface_descriptor(iface); - cp += ksprintf(cp, ", iclass %d/%d", - id->bInterfaceClass, id->bInterfaceSubClass); - } - *cp = 0; -} - -/* Delay for a certain number of ms */ -void -usb_delay_ms(usbd_bus_handle bus, u_int ms) -{ - /* Wait at least two clock ticks so we know the time has passed. */ - if (bus->use_polling || cold) - delay((ms+1) * 1000); - else - tsleep(&ms, 0, "usbdly", (ms*hz+999)/1000 + 1); -} - -/* Delay given a device handle. */ -void -usbd_delay_ms(usbd_device_handle dev, u_int ms) -{ - usb_delay_ms(dev->bus, ms); -} - -usbd_status -usbd_reset_port(usbd_device_handle dev, int port, usb_port_status_t *ps) -{ - usb_device_request_t req; - usbd_status err; - int n; - - req.bmRequestType = UT_WRITE_CLASS_OTHER; - req.bRequest = UR_SET_FEATURE; - USETW(req.wValue, UHF_PORT_RESET); - USETW(req.wIndex, port); - USETW(req.wLength, 0); - err = usbd_do_request(dev, &req, 0); - DPRINTFN(1,("usbd_reset_port: port %d reset done, error=%s\n", - port, usbd_errstr(err))); - if (err) - return (err); - n = 10; - do { - /* Wait for device to recover from reset. */ - usbd_delay_ms(dev, USB_PORT_RESET_DELAY); - err = usbd_get_port_status(dev, port, ps); - if (err) { - DPRINTF(("usbd_reset_port: get status failed %d\n", - err)); - return (err); - } - /* If the device disappeared, just give up. */ - if (!(UGETW(ps->wPortStatus) & UPS_CURRENT_CONNECT_STATUS)) - return (USBD_NORMAL_COMPLETION); - } while ((UGETW(ps->wPortChange) & UPS_C_PORT_RESET) == 0 && --n > 0); - if (n == 0) - return (USBD_TIMEOUT); - err = usbd_clear_port_feature(dev, port, UHF_C_PORT_RESET); -#ifdef USB_DEBUG - if (err) - DPRINTF(("usbd_reset_port: clear port feature failed %d\n", - err)); -#endif - - /* Wait for the device to recover from reset. */ - usbd_delay_ms(dev, USB_PORT_RESET_RECOVERY); - return (err); -} - -usb_interface_descriptor_t * -usbd_find_idesc(usb_config_descriptor_t *cd, int ifaceidx, int altidx) -{ - char *p = (char *)cd; - char *end = p + UGETW(cd->wTotalLength); - usb_interface_descriptor_t *d; - int curidx, lastidx, curaidx = 0; - - for (curidx = lastidx = -1; p < end; ) { - d = (usb_interface_descriptor_t *)p; - DPRINTFN(4,("usbd_find_idesc: idx=%d(%d) altidx=%d(%d) len=%d " - "type=%d\n", - ifaceidx, curidx, altidx, curaidx, - d->bLength, d->bDescriptorType)); - if (d->bLength == 0) /* bad descriptor */ - break; - p += d->bLength; - if (p <= end && d->bDescriptorType == UDESC_INTERFACE) { - if (d->bInterfaceNumber != lastidx) { - lastidx = d->bInterfaceNumber; - curidx++; - curaidx = 0; - } else - curaidx++; - if (ifaceidx == curidx && altidx == curaidx) - return (d); - } - } - return (NULL); -} - -usb_endpoint_descriptor_t * -usbd_find_edesc(usb_config_descriptor_t *cd, int ifaceidx, int altidx, - int endptidx) -{ - char *p = (char *)cd; - char *end = p + UGETW(cd->wTotalLength); - usb_interface_descriptor_t *d; - usb_endpoint_descriptor_t *e; - int curidx; - - d = usbd_find_idesc(cd, ifaceidx, altidx); - if (d == NULL) - return (NULL); - if (endptidx >= d->bNumEndpoints) /* quick exit */ - return (NULL); - - curidx = -1; - for (p = (char *)d + d->bLength; p < end; ) { - e = (usb_endpoint_descriptor_t *)p; - if (e->bLength == 0) /* bad descriptor */ - break; - p += e->bLength; - if (p <= end && e->bDescriptorType == UDESC_INTERFACE) - return (NULL); - if (p <= end && e->bDescriptorType == UDESC_ENDPOINT) { - curidx++; - if (curidx == endptidx) - return (e); - } - } - return (NULL); -} - -usbd_status -usbd_fill_iface_data(usbd_device_handle dev, int ifaceidx, int altidx) -{ - usbd_interface_handle ifc = &dev->ifaces[ifaceidx]; - usb_interface_descriptor_t *idesc; - char *p, *end; - int endpt, nendpt; - - DPRINTFN(4,("usbd_fill_iface_data: ifaceidx=%d altidx=%d\n", - ifaceidx, altidx)); - idesc = usbd_find_idesc(dev->cdesc, ifaceidx, altidx); - if (idesc == NULL) - return (USBD_INVAL); - ifc->device = dev; - ifc->idesc = idesc; - ifc->index = ifaceidx; - ifc->altindex = altidx; - nendpt = ifc->idesc->bNumEndpoints; - DPRINTFN(4,("usbd_fill_iface_data: found idesc nendpt=%d\n", nendpt)); - if (nendpt != 0) { - ifc->endpoints = kmalloc(nendpt * sizeof(struct usbd_endpoint), - M_USB, M_INTWAIT); - } else { - ifc->endpoints = NULL; - } - ifc->priv = NULL; - p = (char *)ifc->idesc + ifc->idesc->bLength; - end = (char *)dev->cdesc + UGETW(dev->cdesc->wTotalLength); -#define ed ((usb_endpoint_descriptor_t *)p) - for (endpt = 0; endpt < nendpt; endpt++) { - DPRINTFN(10,("usbd_fill_iface_data: endpt=%d\n", endpt)); - for (; p < end; p += ed->bLength) { - DPRINTFN(10,("usbd_fill_iface_data: p=%p end=%p " - "len=%d type=%d\n", - p, end, ed->bLength, ed->bDescriptorType)); - if (p + ed->bLength <= end && ed->bLength != 0 && - ed->bDescriptorType == UDESC_ENDPOINT) - goto found; - if (ed->bLength == 0 || - ed->bDescriptorType == UDESC_INTERFACE) - break; - } - /* passed end, or bad desc */ - kprintf("usbd_fill_iface_data: bad descriptor(s): %s\n", - ed->bLength == 0 ? "0 length" : - ed->bDescriptorType == UDESC_INTERFACE ? "iface desc": - "out of data"); - goto bad; - found: - ifc->endpoints[endpt].edesc = ed; - if (dev->speed == USB_SPEED_HIGH) { - u_int mps; - /* Control and bulk endpoints have max packet limits. */ - switch (UE_GET_XFERTYPE(ed->bmAttributes)) { - case UE_CONTROL: - mps = USB_2_MAX_CTRL_PACKET; - goto check; - case UE_BULK: - mps = USB_2_MAX_BULK_PACKET; - check: - if (UGETW(ed->wMaxPacketSize) != mps) { - USETW(ed->wMaxPacketSize, mps); -#ifdef DIAGNOSTIC - kprintf("usbd_fill_iface_data: bad max " - "packet size\n"); -#endif - } - break; - default: - break; - } - } - ifc->endpoints[endpt].refcnt = 0; - ifc->endpoints[endpt].savedtoggle = 0; - p += ed->bLength; - } -#undef ed - LIST_INIT(&ifc->pipes); - return (USBD_NORMAL_COMPLETION); - - bad: - if (ifc->endpoints != NULL) { - kfree(ifc->endpoints, M_USB); - ifc->endpoints = NULL; - } - return (USBD_INVAL); -} - -void -usbd_free_iface_data(usbd_device_handle dev, int ifcno) -{ - usbd_interface_handle ifc = &dev->ifaces[ifcno]; - if (ifc->endpoints) - kfree(ifc->endpoints, M_USB); -} - -static usbd_status -usbd_set_config(usbd_device_handle dev, int conf) -{ - usb_device_request_t req; - - req.bmRequestType = UT_WRITE_DEVICE; - req.bRequest = UR_SET_CONFIG; - USETW(req.wValue, conf); - USETW(req.wIndex, 0); - USETW(req.wLength, 0); - return (usbd_do_request(dev, &req, 0)); -} - -usbd_status -usbd_set_config_no(usbd_device_handle dev, int no, int msg) -{ - int index; - usb_config_descriptor_t cd; - usbd_status err; - - if (no == USB_UNCONFIG_NO) - return (usbd_set_config_index(dev, USB_UNCONFIG_INDEX, msg)); - - DPRINTFN(5,("usbd_set_config_no: %d\n", no)); - /* Figure out what config index to use. */ - for (index = 0; index < dev->ddesc.bNumConfigurations; index++) { - err = usbd_get_config_desc(dev, index, &cd); - if (err) - return (err); - if (cd.bConfigurationValue == no) - return (usbd_set_config_index(dev, index, msg)); - } - return (USBD_INVAL); -} - -usbd_status -usbd_set_config_index(usbd_device_handle dev, int index, int msg) -{ - usb_status_t ds; - usb_config_descriptor_t cd, *cdp; - usbd_status err; - int i, ifcidx, nifc, len, selfpowered, power; - - DPRINTFN(5,("usbd_set_config_index: dev=%p index=%d\n", dev, index)); - - if (dev->config != USB_UNCONFIG_NO) { - nifc = dev->cdesc->bNumInterface; - - /* Check that all interfaces are idle */ - for (ifcidx = 0; ifcidx < nifc; ifcidx++) { - if (LIST_EMPTY(&dev->ifaces[ifcidx].pipes)) - continue; - DPRINTF(("usbd_set_config_index: open pipes exist\n")); - return (USBD_IN_USE); - } - - DPRINTF(("usbd_set_config_index: free old config\n")); - /* Free all configuration data structures. */ - for (ifcidx = 0; ifcidx < nifc; ifcidx++) - usbd_free_iface_data(dev, ifcidx); - kfree(dev->ifaces, M_USB); - kfree(dev->cdesc, M_USB); - dev->ifaces = NULL; - dev->cdesc = NULL; - dev->config = USB_UNCONFIG_NO; - } - - if (index == USB_UNCONFIG_INDEX) { - /* We are unconfiguring the device, so leave unallocated. */ - DPRINTF(("usbd_set_config_index: set config 0\n")); - err = usbd_set_config(dev, USB_UNCONFIG_NO); - if (err) - DPRINTF(("usbd_set_config_index: setting config=0 " - "failed, error=%s\n", usbd_errstr(err))); - return (err); - } - - /* Get the short descriptor. */ - err = usbd_get_config_desc(dev, index, &cd); - if (err) - return (err); - len = UGETW(cd.wTotalLength); - cdp = kmalloc(len, M_USB, M_INTWAIT); - /* Get the full descriptor. Try a few times for slow devices. */ - for (i = 0; i < 3; i++) { - err = usbd_get_desc(dev, UDESC_CONFIG, index, len, cdp); - if (!err) - break; - usbd_delay_ms(dev, 200); - } - if (err) - goto bad; - if (cdp->bDescriptorType != UDESC_CONFIG) { - DPRINTFN(-1,("usbd_set_config_index: bad desc %d\n", - cdp->bDescriptorType)); - err = USBD_INVAL; - goto bad; - } - - /* Figure out if the device is self or bus powered. */ - selfpowered = 0; - if (!(dev->quirks->uq_flags & UQ_BUS_POWERED) && - (cdp->bmAttributes & UC_SELF_POWERED)) { - /* May be self powered. */ - if (cdp->bmAttributes & UC_BUS_POWERED) { - /* Must ask device. */ - if (dev->quirks->uq_flags & UQ_POWER_CLAIM) { - /* - * Hub claims to be self powered, but isn't. - * It seems that the power status can be - * determined by the hub characteristics. - */ - usb_hub_descriptor_t hd; - usb_device_request_t req; - req.bmRequestType = UT_READ_CLASS_DEVICE; - req.bRequest = UR_GET_DESCRIPTOR; - USETW(req.wValue, 0); - USETW(req.wIndex, 0); - USETW(req.wLength, USB_HUB_DESCRIPTOR_SIZE); - err = usbd_do_request(dev, &req, &hd); - if (!err && - (UGETW(hd.wHubCharacteristics) & - UHD_PWR_INDIVIDUAL)) - selfpowered = 1; - DPRINTF(("usbd_set_config_index: charac=0x%04x" - ", error=%s\n", - UGETW(hd.wHubCharacteristics), - usbd_errstr(err))); - } else { - err = usbd_get_device_status(dev, &ds); - if (!err && - (UGETW(ds.wStatus) & UDS_SELF_POWERED)) - selfpowered = 1; - DPRINTF(("usbd_set_config_index: status=0x%04x" - ", error=%s\n", - UGETW(ds.wStatus), usbd_errstr(err))); - } - } else - selfpowered = 1; - } - DPRINTF(("usbd_set_config_index: (addr %d) cno=%d attr=0x%02x, " - "selfpowered=%d, power=%d\n", - cdp->bConfigurationValue, dev->address, cdp->bmAttributes, - selfpowered, cdp->bMaxPower * 2)); - - /* Check if we have enough power. */ -#ifdef USB_DEBUG - if (dev->powersrc == NULL) { - DPRINTF(("usbd_set_config_index: No power source?\n")); - return (USBD_IOERROR); - } -#endif - power = cdp->bMaxPower * 2; - if (power > dev->powersrc->power) { - DPRINTF(("power exceeded %d %d\n", power,dev->powersrc->power)); - /* XXX print nicer message. */ - if (msg) - kprintf("%s: device addr %d (config %d) exceeds power " - "budget, %d mA > %d mA\n", - device_get_nameunit(dev->bus->bdev), dev->address, - cdp->bConfigurationValue, - power, dev->powersrc->power); - err = USBD_NO_POWER; - goto bad; - } - dev->power = power; - dev->self_powered = selfpowered; - - /* Set the actual configuration value. */ - DPRINTF(("usbd_set_config_index: set config %d\n", - cdp->bConfigurationValue)); - err = usbd_set_config(dev, cdp->bConfigurationValue); - if (err) { - DPRINTF(("usbd_set_config_index: setting config=%d failed, " - "error=%s\n", - cdp->bConfigurationValue, usbd_errstr(err))); - goto bad; - } - - /* Allocate and fill interface data. */ - nifc = cdp->bNumInterface; - dev->ifaces = kmalloc(nifc * sizeof(struct usbd_interface), - M_USB, M_INTWAIT); - DPRINTFN(5,("usbd_set_config_index: dev=%p cdesc=%p\n", dev, cdp)); - dev->cdesc = cdp; - dev->config = cdp->bConfigurationValue; - for (ifcidx = 0; ifcidx < nifc; ifcidx++) { - err = usbd_fill_iface_data(dev, ifcidx, 0); - if (err) { - while (--ifcidx >= 0) - usbd_free_iface_data(dev, ifcidx); - goto bad; - } - } - - return (USBD_NORMAL_COMPLETION); - - bad: - kfree(cdp, M_USB); - return (err); -} - -/* XXX add function for alternate settings */ - -usbd_status -usbd_setup_pipe(usbd_device_handle dev, usbd_interface_handle iface, - struct usbd_endpoint *ep, int ival, usbd_pipe_handle *pipe) -{ - usbd_pipe_handle p; - usbd_status err; - - DPRINTFN(1,("usbd_setup_pipe: dev=%p iface=%p ep=%p pipe=%p\n", - dev, iface, ep, pipe)); - p = kmalloc(dev->bus->pipe_size, M_USB, M_INTWAIT | M_ZERO); - p->device = dev; - p->iface = iface; - p->endpoint = ep; - ep->refcnt++; - p->refcnt = 1; - p->intrxfer = 0; - p->running = 0; - p->aborting = 0; - p->repeat = 0; - p->interval = ival; - STAILQ_INIT(&p->queue); - err = dev->bus->methods->open_pipe(p); - if (err) { - DPRINTFN(-1,("usbd_setup_pipe: endpoint=0x%x failed, error=" - "%s\n", - ep->edesc->bEndpointAddress, usbd_errstr(err))); - kfree(p, M_USB); - return (err); - } - - *pipe = p; - return (USBD_NORMAL_COMPLETION); -} - -/* Abort the device control pipe. */ -void -usbd_kill_pipe(usbd_pipe_handle pipe) -{ - usbd_abort_pipe(pipe); - pipe->methods->close(pipe); - pipe->endpoint->refcnt--; - kfree(pipe, M_USB); -} - -int -usbd_getnewaddr(usbd_bus_handle bus) -{ - int addr; - - for (addr = 1; addr < USB_MAX_DEVICES; addr++) - if (bus->devices[addr] == 0) - return (addr); - return (-1); -} - - -usbd_status -usbd_probe_and_attach(device_t parent, usbd_device_handle dev, - int port, int addr) -{ - struct usb_attach_arg uaa; - usb_device_descriptor_t *dd = &dev->ddesc; - int found, i, confi, nifaces; - usbd_status err; - device_t *tmpdv; - usbd_interface_handle ifaces[256]; /* 256 is the absolute max */ - char *devinfo; - - /* XXX FreeBSD may leak resources on failure cases -- fixme */ - device_t bdev; - struct usb_attach_arg *uaap; - - devinfo = kmalloc(1024, M_USB, M_NOWAIT); - if (devinfo == NULL) { - device_printf(parent, - "Can't allocate memory for probe string\n"); - return (USBD_NOMEM); - } - bdev = device_add_child(parent, NULL, -1); - if (!bdev) { - kfree(devinfo, M_USB); - device_printf(parent, "Device creation failed\n"); - return (USBD_INVAL); - } - uaap = kmalloc(sizeof(uaa), M_USB, M_WAITOK); - device_set_ivars(bdev, uaap); - uaa.device = dev; - uaa.iface = NULL; - uaa.ifaces = NULL; - uaa.nifaces = 0; - uaa.usegeneric = 0; - uaa.port = port; - uaa.configno = UHUB_UNK_CONFIGURATION; - uaa.ifaceno = UHUB_UNK_INTERFACE; - uaa.vendor = UGETW(dd->idVendor); - uaa.product = UGETW(dd->idProduct); - uaa.release = UGETW(dd->bcdDevice); - uaa.matchlvl = 0; - - /* First try with device specific drivers. */ - DPRINTF(("usbd_probe_and_attach: trying device specific drivers\n")); - - dev->ifacenums = NULL; - dev->subdevs = kmalloc(2 * sizeof(device_t), M_USB, M_WAITOK); - dev->subdevs[0] = bdev; - dev->subdevs[1] = 0; - *uaap = uaa; - usbd_devinfo(dev, 1, devinfo); - device_set_desc_copy(bdev, devinfo); - if (device_probe_and_attach(bdev) == 0) { - kfree(devinfo, M_USB); - return (USBD_NORMAL_COMPLETION); - } - - /* - * Free subdevs so we can reallocate it larger for the number of - * interfaces - */ - tmpdv = dev->subdevs; - dev->subdevs = NULL; - kfree(tmpdv, M_USB); - DPRINTF(("usbd_probe_and_attach: no device specific driver found\n")); - - DPRINTF(("usbd_probe_and_attach: looping over %d configurations\n", - dd->bNumConfigurations)); - /* Next try with interface drivers. */ - for (confi = 0; confi < dd->bNumConfigurations; confi++) { - DPRINTFN(1,("usbd_probe_and_attach: trying config idx=%d\n", - confi)); - err = usbd_set_config_index(dev, confi, 1); - if (err) { -#ifdef USB_DEBUG - DPRINTF(("%s: port %d, set config at addr %d failed, " - "error=%s\n", device_get_nameunit(parent), port, - addr, usbd_errstr(err))); -#else - kprintf("%s: port %d, set config at addr %d failed\n", - device_get_nameunit(parent), port, addr); -#endif - kfree(devinfo, M_USB); - return (err); - } - nifaces = dev->cdesc->bNumInterface; - uaa.configno = dev->cdesc->bConfigurationValue; - for (i = 0; i < nifaces; i++) - ifaces[i] = &dev->ifaces[i]; - uaa.ifaces = ifaces; - uaa.nifaces = nifaces; - dev->subdevs = kmalloc((nifaces+1) * sizeof(device_t), M_USB, - M_WAITOK); - dev->ifacenums = kmalloc((nifaces) * sizeof(*dev->ifacenums), - M_USB, M_WAITOK); - - found = 0; - for (i = 0; i < nifaces; i++) { - if (ifaces[i] == NULL) - continue; /* interface already claimed */ - uaa.iface = ifaces[i]; - uaa.ifaceno = ifaces[i]->idesc->bInterfaceNumber; - dev->subdevs[found] = bdev; - dev->subdevs[found + 1] = 0; - dev->ifacenums[found] = i; - *uaap = uaa; - usbd_devinfo(dev, 1, devinfo); - device_set_desc_copy(bdev, devinfo); - if (device_probe_and_attach(bdev) == 0) { - ifaces[i] = 0; /* consumed */ - found++; - - /* create another child for the next iface */ - bdev = device_add_child(parent, NULL, -1); - if (!bdev) { - device_printf(parent, - "Device add failed\n"); - kfree(devinfo, M_USB); - return (USBD_NORMAL_COMPLETION); - } - uaap = kmalloc(sizeof(uaa), M_USB, M_WAITOK); - device_set_ivars(bdev, uaap); - } else { - dev->subdevs[found] = 0; - } - } - if (found != 0) { - /* remove the last created child. It is unused */ - kfree(uaap, M_USB); - kfree(devinfo, M_USB); - device_delete_child(parent, bdev); - /* kfree(uaap, M_USB); */ /* May be needed? xxx */ - return (USBD_NORMAL_COMPLETION); - } - tmpdv = dev->subdevs; - dev->subdevs = NULL; - kfree(tmpdv, M_USB); - kfree(dev->ifacenums, M_USB); - dev->ifacenums = NULL; - } - /* No interfaces were attached in any of the configurations. */ - - if (dd->bNumConfigurations > 1) /* don't change if only 1 config */ - usbd_set_config_index(dev, 0, 0); - - DPRINTF(("usbd_probe_and_attach: no interface drivers found\n")); - - /* Finally try the generic driver. */ - uaa.iface = NULL; - uaa.usegeneric = 1; - uaa.configno = UHUB_UNK_CONFIGURATION; - uaa.ifaceno = UHUB_UNK_INTERFACE; - dev->subdevs = kmalloc(2 * sizeof(device_t), M_USB, M_WAITOK); - dev->subdevs[0] = bdev; - dev->subdevs[1] = 0; - *uaap = uaa; - usbd_devinfo(dev, 1, devinfo); - device_set_desc_copy(bdev, devinfo); - kfree(devinfo, M_USB); - if (device_probe_and_attach(bdev) == 0) - return (USBD_NORMAL_COMPLETION); - - /* - * The generic attach failed, but leave the device as it is. - * We just did not find any drivers, that's all. The device is - * fully operational and not harming anyone. - */ - DPRINTF(("usbd_probe_and_attach: generic attach failed\n")); - return (USBD_NORMAL_COMPLETION); -} - - -/* - * Called when a new device has been put in the powered state, - * but not yet in the addressed state. - * Get initial descriptor, set the address, get full descriptor, - * and attach a driver. - */ -usbd_status -usbd_new_device(device_t parent, usbd_bus_handle bus, int depth, - int speed, int port, struct usbd_port *up) -{ - usbd_device_handle dev, adev; - struct usbd_device *hub; - usb_device_descriptor_t *dd; - usb_port_status_t ps; - usbd_status err; - int addr; - int i; - int p; - - DPRINTF(("usbd_new_device bus=%p port=%d depth=%d speed=%d\n", - bus, port, depth, speed)); - addr = usbd_getnewaddr(bus); - if (addr < 0) { - kprintf("%s: No free USB addresses, new device ignored.\n", - device_get_nameunit(bus->bdev)); - return (USBD_NO_ADDR); - } - - dev = kmalloc(sizeof *dev, M_USB, M_INTWAIT | M_ZERO); - dev->bus = bus; - - /* Set up default endpoint handle. */ - dev->def_ep.edesc = &dev->def_ep_desc; - - /* Set up default endpoint descriptor. */ - dev->def_ep_desc.bLength = USB_ENDPOINT_DESCRIPTOR_SIZE; - dev->def_ep_desc.bDescriptorType = UDESC_ENDPOINT; - dev->def_ep_desc.bEndpointAddress = USB_CONTROL_ENDPOINT; - dev->def_ep_desc.bmAttributes = UE_CONTROL; - USETW(dev->def_ep_desc.wMaxPacketSize, USB_MAX_IPACKET); - dev->def_ep_desc.bInterval = 0; - - dev->quirks = &usbd_no_quirk; - dev->address = USB_START_ADDR; - dev->ddesc.bMaxPacketSize = 0; - dev->depth = depth; - dev->powersrc = up; - dev->myhub = up->parent; - - up->device = dev; - - /* Locate port on upstream high speed hub */ - for (adev = dev, hub = up->parent; - hub != NULL && hub->speed != USB_SPEED_HIGH; - adev = hub, hub = hub->myhub) - ; - if (hub) { - for (p = 0; p < hub->hub->hubdesc.bNbrPorts; p++) { - if (hub->hub->ports[p].device == adev) { - dev->myhsport = &hub->hub->ports[p]; - goto found; - } - } - panic("usbd_new_device: cannot find HS port"); - found: - DPRINTFN(1,("usbd_new_device: high speed port %d\n", p)); - } else { - dev->myhsport = NULL; - } - dev->speed = speed; - dev->langid = USBD_NOLANG; - dev->cookie.cookie = ++usb_cookie_no; - - /* Establish the default pipe. */ - err = usbd_setup_pipe(dev, 0, &dev->def_ep, USBD_DEFAULT_INTERVAL, - &dev->default_pipe); - if (err) { - usbd_remove_device(dev, up); - return (err); - } - - /* Set the address. Do this early; some devices need that. */ - /* Try a few times in case the device is slow (i.e. outside specs.) */ - DPRINTFN(5,("usbd_new_device: setting device address=%d\n", addr)); - for (i = 0; i < 5; i++) { - err = usbd_set_address(dev, addr); - if (!err) - break; - usbd_delay_ms(dev, 200); - if ((i & 3) == 3) { - DPRINTFN(-1,("usb_new_device: set address %d " - "failed - trying a port reset\n", addr)); - usbd_reset_port(up->parent, port, &ps); - } - } - if (err) { - DPRINTFN(-1,("usb_new_device: set address %d failed\n", addr)); - err = USBD_SET_ADDR_FAILED; - usbd_remove_device(dev, up); - return (err); - } - - /* Allow device time to set new address */ - usbd_delay_ms(dev, USB_SET_ADDRESS_SETTLE); - - /* Kill the pipe */ - usbd_kill_pipe(dev->default_pipe); - dev->default_pipe = NULL; - - dev->address = addr; /* New device address now */ - bus->devices[addr] = dev; - - /* Re-establish the default pipe. */ - err = usbd_setup_pipe(dev, 0, &dev->def_ep, USBD_DEFAULT_INTERVAL, - &dev->default_pipe); - if (err) { - usbd_remove_device(dev, up); - return (err); - } - usbd_delay_ms(dev, 200); - - dd = &dev->ddesc; - /* Get the first 8 bytes of the device descriptor. */ - err = usbd_get_desc(dev, UDESC_DEVICE, 0, USB_MAX_IPACKET, dd); - if (err) { - DPRINTFN(-1, ("usbd_new_device: addr=%d, getting first desc " - "failed\n", addr)); - usbd_remove_device(dev, up); - return (err); - } - - if (speed == USB_SPEED_HIGH) { - /* Max packet size must be 64 (sec 5.5.3). */ - if (dd->bMaxPacketSize != USB_2_MAX_CTRL_PACKET) { -#ifdef DIAGNOSTIC - kprintf("usbd_new_device: addr=%d bad max packet size\n", - addr); -#endif - dd->bMaxPacketSize = USB_2_MAX_CTRL_PACKET; - } - } - - DPRINTF(("usbd_new_device: adding unit addr=%d, rev=%02x, class=%d, " - "subclass=%d, protocol=%d, maxpacket=%d, len=%d, speed=%d\n", - addr,UGETW(dd->bcdUSB), dd->bDeviceClass, dd->bDeviceSubClass, - dd->bDeviceProtocol, dd->bMaxPacketSize, dd->bLength, - dev->speed)); - - if (dd->bDescriptorType != UDESC_DEVICE) { - /* Illegal device descriptor */ - DPRINTFN(-1,("usbd_new_device: illegal descriptor %d\n", - dd->bDescriptorType)); - usbd_remove_device(dev, up); - return (USBD_INVAL); - } - - if (dd->bLength < USB_DEVICE_DESCRIPTOR_SIZE) { - DPRINTFN(-1,("usbd_new_device: bad length %d\n", dd->bLength)); - usbd_remove_device(dev, up); - return (USBD_INVAL); - } - - USETW(dev->def_ep_desc.wMaxPacketSize, dd->bMaxPacketSize); - - err = usbd_reload_device_desc(dev); - if (err) { - DPRINTFN(-1, ("usbd_new_device: addr=%d, getting full desc " - "failed\n", addr)); - usbd_remove_device(dev, up); - return (err); - } - - /* Assume 100mA bus powered for now. Changed when configured. */ - dev->power = USB_MIN_POWER; - dev->self_powered = 0; - - DPRINTF(("usbd_new_device: new dev (addr %d), dev=%p, parent=%p\n", - addr, dev, parent)); - - err = usbd_probe_and_attach(parent, dev, port, addr); - if (err) { - usbd_remove_device(dev, up); - return (err); - } - - usbd_add_dev_event(USB_EVENT_DEVICE_ATTACH, dev); - - return (USBD_NORMAL_COMPLETION); -} - -usbd_status -usbd_reload_device_desc(usbd_device_handle dev) -{ - usbd_status err; - int i; - - /* Get the full device descriptor. */ - for (i = 0; i < 3; ++i) { - err = usbd_get_device_desc(dev, &dev->ddesc); - if (!err) - break; - usbd_delay_ms(dev, 200); - } - if (err) - return (err); - - /* Figure out what's wrong with this device. */ - dev->quirks = usbd_find_quirk(&dev->ddesc); - - return (USBD_NORMAL_COMPLETION); -} - -void -usbd_remove_device(usbd_device_handle dev, struct usbd_port *up) -{ - DPRINTF(("usbd_remove_device: %p\n", dev)); - - if (dev->default_pipe != NULL) - usbd_kill_pipe(dev->default_pipe); - up->device = NULL; - dev->bus->devices[dev->address] = NULL; - - kfree(dev, M_USB); -} - -void -usbd_fill_deviceinfo(usbd_device_handle dev, struct usb_device_info *di, - int usedev) -{ - struct usbd_port *p; - int i, err, s; - - di->udi_bus = device_get_unit(dev->bus->bdev); - di->udi_addr = dev->address; - di->udi_cookie = dev->cookie; - usbd_devinfo_vp(dev, di->udi_vendor, di->udi_product, usedev); - usbd_printBCD(di->udi_release, UGETW(dev->ddesc.bcdDevice)); - di->udi_vendorNo = UGETW(dev->ddesc.idVendor); - di->udi_productNo = UGETW(dev->ddesc.idProduct); - di->udi_releaseNo = UGETW(dev->ddesc.bcdDevice); - di->udi_class = dev->ddesc.bDeviceClass; - di->udi_subclass = dev->ddesc.bDeviceSubClass; - di->udi_protocol = dev->ddesc.bDeviceProtocol; - di->udi_config = dev->config; - di->udi_power = dev->self_powered ? 0 : dev->power; - di->udi_speed = dev->speed; - - if (dev->subdevs != NULL) { - for (i = 0; dev->subdevs[i] && i < USB_MAX_DEVNAMES; i++) { - if (device_is_attached(dev->subdevs[i])) - strlcpy(di->udi_devnames[i], - device_get_nameunit(dev->subdevs[i]), - USB_MAX_DEVNAMELEN); - else - di->udi_devnames[i][0] = 0; - } - } else { - i = 0; - } - for (/*i is set */; i < USB_MAX_DEVNAMES; i++) - di->udi_devnames[i][0] = 0; /* empty */ - - if (dev->hub) { - for (i = 0; - i < NELEM(di->udi_ports) && - i < dev->hub->hubdesc.bNbrPorts; - i++) { - p = &dev->hub->ports[i]; - if (p->device) - err = p->device->address; - else { - s = UGETW(p->status.wPortStatus); - if (s & UPS_PORT_ENABLED) - err = USB_PORT_ENABLED; - else if (s & UPS_SUSPEND) - err = USB_PORT_SUSPENDED; - else if (s & UPS_PORT_POWER) - err = USB_PORT_POWERED; - else - err = USB_PORT_DISABLED; - } - di->udi_ports[i] = err; - } - di->udi_nports = dev->hub->hubdesc.bNbrPorts; - } else - di->udi_nports = 0; -} - -void -usb_free_device(usbd_device_handle dev) -{ - int ifcidx, nifc; - - if (dev->default_pipe != NULL) - usbd_kill_pipe(dev->default_pipe); - if (dev->ifaces != NULL) { - nifc = dev->cdesc->bNumInterface; - for (ifcidx = 0; ifcidx < nifc; ifcidx++) - usbd_free_iface_data(dev, ifcidx); - kfree(dev->ifaces, M_USB); - } - if (dev->cdesc != NULL) - kfree(dev->cdesc, M_USB); - if (dev->subdevs != NULL) - kfree(dev->subdevs, M_USB); - if (dev->ifacenums != NULL) - kfree(dev->ifacenums, M_USB); - kfree(dev, M_USB); -} - -/* - * The general mechanism for detaching drivers works as follows: Each - * driver is responsible for maintaining a reference count on the - * number of outstanding references to its softc (e.g. from - * processing hanging in a read or write). The detach method of the - * driver decrements this counter and flags in the softc that the - * driver is dying and then wakes any sleepers. It then sleeps on the - * softc. Each place that can sleep must maintain the reference - * count. When the reference count drops to -1 (0 is the normal value - * of the reference count) the a wakeup on the softc is performed - * signaling to the detach waiter that all references are gone. - */ - -/* - * Called from process context when we discover that a port has - * been disconnected. - */ -void -usb_disconnect_port(struct usbd_port *up, device_t parent) -{ - usbd_device_handle dev = up->device; - const char *hubname = device_get_nameunit(parent); - int i; - - DPRINTFN(3,("uhub_disconnect: up=%p dev=%p port=%d\n", - up, dev, up->portno)); - -#ifdef DIAGNOSTIC - if (dev == NULL) { - kprintf("usb_disconnect_port: no device\n"); - return; - } -#endif - - if (dev->subdevs != NULL) { - DPRINTFN(3,("usb_disconnect_port: disconnect subdevs\n")); - for (i = 0; dev->subdevs[i]; i++) { - kprintf("%s: at %s", device_get_nameunit(dev->subdevs[i]), - hubname); - if (up->portno != 0) - kprintf(" port %d", up->portno); - kprintf(" (addr %d) disconnected\n", dev->address); - device_delete_child(device_get_parent(dev->subdevs[i]), dev->subdevs[i]); - dev->subdevs[i] = NULL; - } - } - - usbd_add_dev_event(USB_EVENT_DEVICE_DETACH, dev); - dev->bus->devices[dev->address] = NULL; - up->device = NULL; - usb_free_device(dev); -} - diff --git a/sys/bus/usb/usbcdc.h b/sys/bus/usb/usbcdc.h deleted file mode 100644 index 423fc81e9c..0000000000 --- a/sys/bus/usb/usbcdc.h +++ /dev/null @@ -1,184 +0,0 @@ -/* - * $NetBSD: usbcdc.h,v 1.6 2000/04/27 15:26:50 augustss Exp $ - * $FreeBSD: src/sys/dev/usb/usbcdc.h,v 1.10 2003/01/09 04:24:28 imp Exp $ - */ - -/* - * Copyright (c) 1998 The NetBSD Foundation, Inc. - * All rights reserved. - * - * This code is derived from software contributed to The NetBSD Foundation - * by Lennart Augustsson (lennart@augustsson.net) at - * Carlstedt Research & Technology. - * - * 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. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the NetBSD - * Foundation, Inc. and its contributors. - * 4. Neither the name of The NetBSD Foundation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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. - */ - -#ifndef _USBCDC_H_ -#define _USBCDC_H_ - -#define UDESCSUB_CDC_HEADER 0 -#define UDESCSUB_CDC_CM 1 /* Call Management */ -#define UDESCSUB_CDC_ACM 2 /* Abstract Control Model */ -#define UDESCSUB_CDC_DLM 3 /* Direct Line Management */ -#define UDESCSUB_CDC_TRF 4 /* Telephone Ringer */ -#define UDESCSUB_CDC_TCLSR 5 /* Telephone Call ... */ -#define UDESCSUB_CDC_UNION 6 -#define UDESCSUB_CDC_CS 7 /* Country Selection */ -#define UDESCSUB_CDC_TOM 8 /* Telephone Operational Modes */ -#define UDESCSUB_CDC_USBT 9 /* USB Terminal */ -#define UDESCSUB_CDC_ETHERNET 15 /* Ethernet Adapter */ - -typedef struct { - uByte bLength; - uByte bDescriptorType; - uByte bDescriptorSubtype; - uWord bcdCDC; -} usb_cdc_header_descriptor_t; - -typedef struct { - uByte bLength; - uByte bDescriptorType; - uByte bDescriptorSubtype; - uByte bmCapabilities; -#define USB_CDC_CM_DOES_CM 0x01 -#define USB_CDC_CM_OVER_DATA 0x02 - uByte bDataInterface; -} usb_cdc_cm_descriptor_t; - -typedef struct { - uByte bLength; - uByte bDescriptorType; - uByte bDescriptorSubtype; - uByte bmCapabilities; -#define USB_CDC_ACM_HAS_FEATURE 0x01 -#define USB_CDC_ACM_HAS_LINE 0x02 -#define USB_CDC_ACM_HAS_BREAK 0x04 -#define USB_CDC_ACM_HAS_NETWORK_CONN 0x08 -} usb_cdc_acm_descriptor_t; - -typedef struct { - uByte bLength; - uByte bDescriptorType; - uByte bDescriptorSubtype; - uByte bMasterInterface; - uByte bSlaveInterface[1]; -} usb_cdc_union_descriptor_t; - -typedef struct { - uByte bLength; - uByte bDescriptorType; - uByte bDescriptorSubType; - uByte iMACAddress; - uDWord dwEthernetStatistics; - uWord wMaxSegmentSize; - uWord wNumberMCFilters; - uByte bNumberPowerFilters; -} usb_cdc_ethernet_descriptor_t; - -#define UCDC_SEND_ENCAPSULATED_COMMAND 0x00 -#define UCDC_GET_ENCAPSULATED_RESPONSE 0x01 -#define UCDC_SET_COMM_FEATURE 0x02 -#define UCDC_GET_COMM_FEATURE 0x03 -#define UCDC_ABSTRACT_STATE 0x01 -#define UCDC_COUNTRY_SETTING 0x02 -#define UCDC_CLEAR_COMM_FEATURE 0x04 -#define UCDC_SET_LINE_CODING 0x20 -#define UCDC_GET_LINE_CODING 0x21 -#define UCDC_SET_CONTROL_LINE_STATE 0x22 -#define UCDC_LINE_DTR 0x0001 -#define UCDC_LINE_RTS 0x0002 -#define UCDC_SEND_BREAK 0x23 -#define UCDC_BREAK_ON 0xffff -#define UCDC_BREAK_OFF 0x0000 - -typedef struct { - uWord wState; -#define UCDC_IDLE_SETTING 0x0001 -#define UCDC_DATA_MULTIPLEXED 0x0002 -} usb_cdc_abstract_state_t; -#define UCDC_ABSTRACT_STATE_LENGTH 2 - -typedef struct { - uDWord dwDTERate; - uByte bCharFormat; -#define UCDC_STOP_BIT_1 0 -#define UCDC_STOP_BIT_1_5 1 -#define UCDC_STOP_BIT_2 2 - uByte bParityType; -#define UCDC_PARITY_NONE 0 -#define UCDC_PARITY_ODD 1 -#define UCDC_PARITY_EVEN 2 -#define UCDC_PARITY_MARK 3 -#define UCDC_PARITY_SPACE 4 - uByte bDataBits; -} usb_cdc_line_state_t; -#define UCDC_LINE_STATE_LENGTH 7 - -typedef struct { - uByte bmRequestType; -#define UCDC_NOTIFICATION 0xa1 - uByte bNotification; -#define UCDC_N_NETWORK_CONNECTION 0x00 -#define UCDC_N_RESPONSE_AVAILABLE 0x01 -#define UCDC_N_AUX_JACK_HOOK_STATE 0x08 -#define UCDC_N_RING_DETECT 0x09 -#define UCDC_N_SERIAL_STATE 0x20 -#define UCDC_N_CALL_STATE_CHANGED 0x28 -#define UCDC_N_LINE_STATE_CHANGED 0x29 -#define UCDC_N_CONNECTION_SPEED_CHANGE 0x2a - uWord wValue; - uWord wIndex; - uWord wLength; - uByte data[16]; -} usb_cdc_notification_t; -#define UCDC_NOTIFICATION_LENGTH 8 - -/* - * Bits set in the SERIAL STATE notifcation (first byte of data) - */ - -#define UCDC_N_SERIAL_OVERRUN 0x40 -#define UCDC_N_SERIAL_PARITY 0x20 -#define UCDC_N_SERIAL_FRAMING 0x10 -#define UCDC_N_SERIAL_RI 0x08 -#define UCDC_N_SERIAL_BREAK 0x04 -#define UCDC_N_SERIAL_DSR 0x02 -#define UCDC_N_SERIAL_DCD 0x01 - -/* Serial state bit masks */ -#define UCDC_MDM_RXCARRIER 0x01 -#define UCDC_MDM_TXCARRIER 0x02 -#define UCDC_MDM_BREAK 0x04 -#define UCDC_MDM_RING 0x08 -#define UCDC_MDM_FRAMING_ERR 0x10 -#define UCDC_MDM_PARITY_ERR 0x20 -#define UCDC_MDM_OVERRUN_ERR 0x40 - -#endif /* _USBCDC_H_ */ diff --git a/sys/bus/usb/usbdi.c b/sys/bus/usb/usbdi.c deleted file mode 100644 index e6363709d7..0000000000 --- a/sys/bus/usb/usbdi.c +++ /dev/null @@ -1,1245 +0,0 @@ -/* $NetBSD: usbdi.c,v 1.106 2004/10/24 12:52:40 augustss Exp $ */ -/* $FreeBSD: src/sys/dev/usb/usbdi.c,v 1.91.2.1 2005/12/15 00:36:00 iedowse Exp $ */ - -/* - * Copyright (c) 1998 The NetBSD Foundation, Inc. - * All rights reserved. - * - * This code is derived from software contributed to The NetBSD Foundation - * by Lennart Augustsson (lennart@augustsson.net) at - * Carlstedt Research & Technology. - * - * 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. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the NetBSD - * Foundation, Inc. and its contributors. - * 4. Neither the name of The NetBSD Foundation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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 -#include -#include -#include -#include -#include "usb_if.h" -#if defined(DIAGNOSTIC) && defined(__i386__) -#include -#endif -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#define delay(d) DELAY(d) - -#ifdef USB_DEBUG -#define DPRINTF(x) if (usbdebug) kprintf x -#define DPRINTFN(n,x) if (usbdebug>(n)) kprintf x -extern int usbdebug; -#else -#define DPRINTF(x) -#define DPRINTFN(n,x) -#endif - -static usbd_status usbd_ar_pipe(usbd_pipe_handle pipe); -static void usbd_do_request_async_cb - (usbd_xfer_handle, usbd_private_handle, usbd_status); -static void usbd_start_next(usbd_pipe_handle pipe); -static usbd_status usbd_open_pipe_ival - (usbd_interface_handle, u_int8_t, u_int8_t, usbd_pipe_handle *, int); -static int usbd_xfer_isread(usbd_xfer_handle xfer); - -static int usbd_nbuses = 0; - -void -usbd_init(void) -{ - usbd_nbuses++; -} - -void -usbd_finish(void) -{ - --usbd_nbuses; -} - -static __inline int -usbd_xfer_isread(usbd_xfer_handle xfer) -{ - if (xfer->rqflags & URQ_REQUEST) - return (xfer->request.bmRequestType & UT_READ); - else - return (xfer->pipe->endpoint->edesc->bEndpointAddress & - UE_DIR_IN); -} - -#ifdef USB_DEBUG -void -usbd_dump_iface(struct usbd_interface *iface) -{ - kprintf("usbd_dump_iface: iface=%p\n", iface); - if (iface == NULL) - return; - kprintf(" device=%p idesc=%p index=%d altindex=%d priv=%p\n", - iface->device, iface->idesc, iface->index, iface->altindex, - iface->priv); -} - -void -usbd_dump_device(struct usbd_device *dev) -{ - kprintf("usbd_dump_device: dev=%p\n", dev); - if (dev == NULL) - return; - kprintf(" bus=%p default_pipe=%p\n", dev->bus, dev->default_pipe); - kprintf(" address=%d config=%d depth=%d speed=%d self_powered=%d " - "power=%d langid=%d\n", - dev->address, dev->config, dev->depth, dev->speed, - dev->self_powered, dev->power, dev->langid); -} - -void -usbd_dump_endpoint(struct usbd_endpoint *endp) -{ - kprintf("usbd_dump_endpoint: endp=%p\n", endp); - if (endp == NULL) - return; - kprintf(" edesc=%p refcnt=%d\n", endp->edesc, endp->refcnt); - if (endp->edesc) - kprintf(" bEndpointAddress=0x%02x\n", - endp->edesc->bEndpointAddress); -} - -void -usbd_dump_queue(usbd_pipe_handle pipe) -{ - usbd_xfer_handle xfer; - - kprintf("usbd_dump_queue: pipe=%p\n", pipe); - STAILQ_FOREACH(xfer, &pipe->queue, next) { - kprintf(" xfer=%p\n", xfer); - } -} - -void -usbd_dump_pipe(usbd_pipe_handle pipe) -{ - kprintf("usbd_dump_pipe: pipe=%p\n", pipe); - if (pipe == NULL) - return; - usbd_dump_iface(pipe->iface); - usbd_dump_device(pipe->device); - usbd_dump_endpoint(pipe->endpoint); - kprintf(" (usbd_dump_pipe:)\n refcnt=%d running=%d aborting=%d\n", - pipe->refcnt, pipe->running, pipe->aborting); - kprintf(" intrxfer=%p, repeat=%d, interval=%d\n", - pipe->intrxfer, pipe->repeat, pipe->interval); -} -#endif - -usbd_status -usbd_open_pipe(usbd_interface_handle iface, u_int8_t address, - u_int8_t flags, usbd_pipe_handle *pipe) -{ - return (usbd_open_pipe_ival(iface, address, flags, pipe, - USBD_DEFAULT_INTERVAL)); -} - -usbd_status -usbd_open_pipe_ival(usbd_interface_handle iface, u_int8_t address, - u_int8_t flags, usbd_pipe_handle *pipe, int ival) -{ - usbd_pipe_handle p; - struct usbd_endpoint *ep; - usbd_status err; - int i; - - DPRINTFN(3,("usbd_open_pipe: iface=%p address=0x%x flags=0x%x\n", - iface, address, flags)); - - for (i = 0; i < iface->idesc->bNumEndpoints; i++) { - ep = &iface->endpoints[i]; - if (ep->edesc == NULL) - return (USBD_IOERROR); - if (ep->edesc->bEndpointAddress == address) - goto found; - } - return (USBD_BAD_ADDRESS); - found: - if ((flags & USBD_EXCLUSIVE_USE) && ep->refcnt != 0) - return (USBD_IN_USE); - err = usbd_setup_pipe(iface->device, iface, ep, ival, &p); - if (err) - return (err); - LIST_INSERT_HEAD(&iface->pipes, p, next); - *pipe = p; - return (USBD_NORMAL_COMPLETION); -} - -usbd_status -usbd_open_pipe_intr(usbd_interface_handle iface, u_int8_t address, - u_int8_t flags, usbd_pipe_handle *pipe, - usbd_private_handle priv, void *buffer, u_int32_t len, - usbd_callback cb, int ival) -{ - usbd_status err; - usbd_xfer_handle xfer; - usbd_pipe_handle ipipe; - - DPRINTFN(3,("usbd_open_pipe_intr: address=0x%x flags=0x%x len=%d\n", - address, flags, len)); - - err = usbd_open_pipe_ival(iface, address, USBD_EXCLUSIVE_USE, - &ipipe, ival); - if (err) - return (err); - xfer = usbd_alloc_xfer(iface->device); - if (xfer == NULL) { - err = USBD_NOMEM; - goto bad1; - } - usbd_setup_xfer(xfer, ipipe, priv, buffer, len, flags, - USBD_NO_TIMEOUT, cb); - ipipe->intrxfer = xfer; - ipipe->repeat = 1; - err = usbd_transfer(xfer); - *pipe = ipipe; - if (err != USBD_IN_PROGRESS && err) - goto bad2; - return (USBD_NORMAL_COMPLETION); - - bad2: - ipipe->intrxfer = NULL; - ipipe->repeat = 0; - usbd_free_xfer(xfer); - bad1: - usbd_close_pipe(ipipe); - return (err); -} - -usbd_status -usbd_close_pipe(usbd_pipe_handle pipe) -{ -#ifdef DIAGNOSTIC - if (pipe == NULL) { - kprintf("usbd_close_pipe: pipe==NULL\n"); - return (USBD_NORMAL_COMPLETION); - } -#endif - - if (--pipe->refcnt != 0) - return (USBD_NORMAL_COMPLETION); - if (! STAILQ_EMPTY(&pipe->queue)) - return (USBD_PENDING_REQUESTS); - LIST_REMOVE(pipe, next); - pipe->endpoint->refcnt--; - pipe->methods->close(pipe); - if (pipe->intrxfer != NULL) - usbd_free_xfer(pipe->intrxfer); - kfree(pipe, M_USB); - return (USBD_NORMAL_COMPLETION); -} - -usbd_status -usbd_transfer(usbd_xfer_handle xfer) -{ - usbd_pipe_handle pipe = xfer->pipe; - usb_dma_t *dmap = &xfer->dmabuf; - usbd_status err; - u_int size; - int didtry; - - DPRINTFN(5,("usbd_transfer: xfer=%p, flags=%d, pipe=%p, running=%d\n", - xfer, xfer->flags, pipe, pipe->running)); -#ifdef USB_DEBUG - if (usbdebug > 5) - usbd_dump_queue(pipe); -#endif - xfer->done = 0; - - if (pipe->aborting) - return (USBD_CANCELLED); - - size = xfer->length; - /* If there is no buffer, allocate one. */ - if (!(xfer->rqflags & URQ_DEV_DMABUF) && size != 0) { - struct usbd_bus *bus = pipe->device->bus; - -#ifdef DIAGNOSTIC - if (xfer->rqflags & URQ_AUTO_DMABUF) - kprintf("usbd_transfer: has old buffer!\n"); -#endif - err = bus->methods->allocm(bus, dmap, size); - if (err) - return (err); - xfer->rqflags |= URQ_AUTO_DMABUF; - } - - /* Copy data if going out. */ - if (!(xfer->flags & USBD_NO_COPY) && size != 0 && - !usbd_xfer_isread(xfer)) - memcpy(KERNADDR(dmap, 0), xfer->buffer, size); - - err = pipe->methods->transfer(xfer); - - if (err != USBD_IN_PROGRESS && err) { - /* The transfer has not been queued, so free buffer. */ - if (xfer->rqflags & URQ_AUTO_DMABUF) { - struct usbd_bus *bus = pipe->device->bus; - - bus->methods->freem(bus, &xfer->dmabuf); - xfer->rqflags &= ~URQ_AUTO_DMABUF; - } - } - - if (!(xfer->flags & USBD_SYNCHRONOUS)) - return (err); - - /* Sync transfer, wait for completion. */ - if (err != USBD_IN_PROGRESS) - return (err); - crit_enter(); - didtry = 0; - while (!xfer->done) { - if (pipe->device->bus->use_polling) { - pipe->device->bus->methods->do_poll(pipe->device->bus); - if (didtry++ == 0) { - kprintf("Warning: usbd_transfer: not done, " - "retrying."); - } else { - if (didtry == 10) - usbd_abort_pipe(pipe); - kprintf("."); - } - } - tsleep(xfer, 0, "usbsyn", hz); - } - if (didtry) - kprintf(" ok\n"); - crit_exit(); - return (xfer->status); -} - -/* Like usbd_transfer(), but waits for completion. */ -usbd_status -usbd_sync_transfer(usbd_xfer_handle xfer) -{ - xfer->flags |= USBD_SYNCHRONOUS; - return (usbd_transfer(xfer)); -} - -void * -usbd_alloc_buffer(usbd_xfer_handle xfer, u_int32_t size) -{ - struct usbd_bus *bus = xfer->device->bus; - usbd_status err; - -#ifdef DIAGNOSTIC - if (xfer->rqflags & (URQ_DEV_DMABUF | URQ_AUTO_DMABUF)) - kprintf("usbd_alloc_buffer: xfer already has a buffer\n"); -#endif - err = bus->methods->allocm(bus, &xfer->dmabuf, size); - if (err) { - device_printf(bus->bdev, "Unable to allocate %u contig\n", - size); - return (NULL); - } - xfer->rqflags |= URQ_DEV_DMABUF; - return (KERNADDR(&xfer->dmabuf, 0)); -} - -void -usbd_free_buffer(usbd_xfer_handle xfer) -{ -#ifdef DIAGNOSTIC - if (!(xfer->rqflags & (URQ_DEV_DMABUF | URQ_AUTO_DMABUF))) { - kprintf("usbd_free_buffer: no buffer\n"); - return; - } -#endif - xfer->rqflags &= ~(URQ_DEV_DMABUF | URQ_AUTO_DMABUF); - xfer->device->bus->methods->freem(xfer->device->bus, &xfer->dmabuf); -} - -void * -usbd_get_buffer(usbd_xfer_handle xfer) -{ - if (!(xfer->rqflags & URQ_DEV_DMABUF)) - return (0); - return (KERNADDR(&xfer->dmabuf, 0)); -} - -usbd_xfer_handle -usbd_alloc_xfer(usbd_device_handle dev) -{ - usbd_xfer_handle xfer; - - xfer = dev->bus->methods->allocx(dev->bus); - if (xfer == NULL) - return (NULL); - xfer->device = dev; - callout_init(&xfer->timeout_handle); - DPRINTFN(5,("usbd_alloc_xfer() = %p\n", xfer)); - return (xfer); -} - -usbd_status -usbd_free_xfer(usbd_xfer_handle xfer) -{ - DPRINTFN(5,("usbd_free_xfer: %p\n", xfer)); - if (xfer->rqflags & (URQ_DEV_DMABUF | URQ_AUTO_DMABUF)) - usbd_free_buffer(xfer); - xfer->device->bus->methods->freex(xfer->device->bus, xfer); - return (USBD_NORMAL_COMPLETION); -} - -void -usbd_setup_xfer(usbd_xfer_handle xfer, usbd_pipe_handle pipe, - usbd_private_handle priv, void *buffer, u_int32_t length, - u_int16_t flags, u_int32_t timeout, - usbd_callback callback) -{ - xfer->pipe = pipe; - xfer->priv = priv; - xfer->buffer = buffer; - xfer->length = length; - xfer->actlen = 0; - xfer->flags = flags; - xfer->timeout = timeout; - xfer->status = USBD_NOT_STARTED; - xfer->callback = callback; - xfer->rqflags &= ~URQ_REQUEST; - xfer->nframes = 0; -} - -void -usbd_setup_default_xfer(usbd_xfer_handle xfer, usbd_device_handle dev, - usbd_private_handle priv, u_int32_t timeout, - usb_device_request_t *req, void *buffer, - u_int32_t length, u_int16_t flags, - usbd_callback callback) -{ - xfer->pipe = dev->default_pipe; - xfer->priv = priv; - xfer->buffer = buffer; - xfer->length = length; - xfer->actlen = 0; - xfer->flags = flags; - xfer->timeout = timeout; - xfer->status = USBD_NOT_STARTED; - xfer->callback = callback; - xfer->request = *req; - xfer->rqflags |= URQ_REQUEST; - xfer->nframes = 0; -} - -void -usbd_setup_isoc_xfer(usbd_xfer_handle xfer, usbd_pipe_handle pipe, - usbd_private_handle priv, u_int16_t *frlengths, - u_int32_t nframes, u_int16_t flags, usbd_callback callback) -{ - xfer->pipe = pipe; - xfer->priv = priv; - xfer->buffer = 0; - xfer->length = 0; - xfer->actlen = 0; - xfer->flags = flags; - xfer->timeout = USBD_NO_TIMEOUT; - xfer->status = USBD_NOT_STARTED; - xfer->callback = callback; - xfer->rqflags &= ~URQ_REQUEST; - xfer->frlengths = frlengths; - xfer->nframes = nframes; -} - -void -usbd_get_xfer_status(usbd_xfer_handle xfer, usbd_private_handle *priv, - void **buffer, u_int32_t *count, usbd_status *status) -{ - if (priv != NULL) - *priv = xfer->priv; - if (buffer != NULL) - *buffer = xfer->buffer; - if (count != NULL) - *count = xfer->actlen; - if (status != NULL) - *status = xfer->status; -} - -int -usbd_get_speed(usbd_device_handle dev) -{ - return(dev->speed); -} - -usb_config_descriptor_t * -usbd_get_config_descriptor(usbd_device_handle dev) -{ -#ifdef DIAGNOSTIC - if (dev == NULL) { - kprintf("usbd_get_config_descriptor: dev == NULL\n"); - return (NULL); - } -#endif - return (dev->cdesc); -} - -usb_interface_descriptor_t * -usbd_get_interface_descriptor(usbd_interface_handle iface) -{ -#ifdef DIAGNOSTIC - if (iface == NULL) { - kprintf("usbd_get_interface_descriptor: dev == NULL\n"); - return (NULL); - } -#endif - return (iface->idesc); -} - -usb_device_descriptor_t * -usbd_get_device_descriptor(usbd_device_handle dev) -{ - return (&dev->ddesc); -} - -usb_endpoint_descriptor_t * -usbd_interface2endpoint_descriptor(usbd_interface_handle iface, u_int8_t index) -{ - if (index >= iface->idesc->bNumEndpoints) - return (0); - return (iface->endpoints[index].edesc); -} - -usbd_status -usbd_abort_pipe(usbd_pipe_handle pipe) -{ - usbd_status err; - -#ifdef DIAGNOSTIC - if (pipe == NULL) { - kprintf("usbd_close_pipe: pipe==NULL\n"); - return (USBD_NORMAL_COMPLETION); - } -#endif - crit_enter(); - err = usbd_ar_pipe(pipe); - crit_exit(); - return (err); -} - -usbd_status -usbd_abort_default_pipe(usbd_device_handle dev) -{ - return (usbd_abort_pipe(dev->default_pipe)); -} - -usbd_status -usbd_clear_endpoint_stall(usbd_pipe_handle pipe) -{ - usbd_device_handle dev = pipe->device; - usb_device_request_t req; - usbd_status err; - - DPRINTFN(8, ("usbd_clear_endpoint_stall\n")); - - /* - * Clearing en endpoint stall resets the endpoint toggle, so - * do the same to the HC toggle. - */ - pipe->methods->cleartoggle(pipe); - - req.bmRequestType = UT_WRITE_ENDPOINT; - req.bRequest = UR_CLEAR_FEATURE; - USETW(req.wValue, UF_ENDPOINT_HALT); - USETW(req.wIndex, pipe->endpoint->edesc->bEndpointAddress); - USETW(req.wLength, 0); - err = usbd_do_request(dev, &req, 0); -#if 0 -XXX should we do this? - if (!err) { - pipe->state = USBD_PIPE_ACTIVE; - /* XXX activate pipe */ - } -#endif - return (err); -} - -usbd_status -usbd_clear_endpoint_stall_async(usbd_pipe_handle pipe) -{ - usbd_device_handle dev = pipe->device; - usb_device_request_t req; - usbd_status err; - - pipe->methods->cleartoggle(pipe); - - req.bmRequestType = UT_WRITE_ENDPOINT; - req.bRequest = UR_CLEAR_FEATURE; - USETW(req.wValue, UF_ENDPOINT_HALT); - USETW(req.wIndex, pipe->endpoint->edesc->bEndpointAddress); - USETW(req.wLength, 0); - err = usbd_do_request_async(dev, &req, 0); - return (err); -} - -void -usbd_clear_endpoint_toggle(usbd_pipe_handle pipe) -{ - pipe->methods->cleartoggle(pipe); -} - -usbd_status -usbd_endpoint_count(usbd_interface_handle iface, u_int8_t *count) -{ -#ifdef DIAGNOSTIC - if (iface == NULL || iface->idesc == NULL) { - kprintf("usbd_endpoint_count: NULL pointer\n"); - return (USBD_INVAL); - } -#endif - *count = iface->idesc->bNumEndpoints; - return (USBD_NORMAL_COMPLETION); -} - -usbd_status -usbd_interface_count(usbd_device_handle dev, u_int8_t *count) -{ - if (dev->cdesc == NULL) - return (USBD_NOT_CONFIGURED); - *count = dev->cdesc->bNumInterface; - return (USBD_NORMAL_COMPLETION); -} - -void -usbd_interface2device_handle(usbd_interface_handle iface, - usbd_device_handle *dev) -{ - *dev = iface->device; -} - -usbd_status -usbd_device2interface_handle(usbd_device_handle dev, - u_int8_t ifaceno, usbd_interface_handle *iface) -{ - if (dev->cdesc == NULL) - return (USBD_NOT_CONFIGURED); - if (ifaceno >= dev->cdesc->bNumInterface) - return (USBD_INVAL); - *iface = &dev->ifaces[ifaceno]; - return (USBD_NORMAL_COMPLETION); -} - -usbd_device_handle -usbd_pipe2device_handle(usbd_pipe_handle pipe) -{ - return (pipe->device); -} - -/* XXXX use altno */ -usbd_status -usbd_set_interface(usbd_interface_handle iface, int altidx) -{ - usb_device_request_t req; - usbd_status err; - void *endpoints; - - if (LIST_FIRST(&iface->pipes) != 0) - return (USBD_IN_USE); - - endpoints = iface->endpoints; - err = usbd_fill_iface_data(iface->device, iface->index, altidx); - if (err) - return (err); - - /* new setting works, we can free old endpoints */ - if (endpoints != NULL) - kfree(endpoints, M_USB); - -#ifdef DIAGNOSTIC - if (iface->idesc == NULL) { - kprintf("usbd_set_interface: NULL pointer\n"); - return (USBD_INVAL); - } -#endif - - req.bmRequestType = UT_WRITE_INTERFACE; - req.bRequest = UR_SET_INTERFACE; - USETW(req.wValue, iface->idesc->bAlternateSetting); - USETW(req.wIndex, iface->idesc->bInterfaceNumber); - USETW(req.wLength, 0); - return (usbd_do_request(iface->device, &req, 0)); -} - -int -usbd_get_no_alts(usb_config_descriptor_t *cdesc, int ifaceno) -{ - char *p = (char *)cdesc; - char *end = p + UGETW(cdesc->wTotalLength); - usb_interface_descriptor_t *d; - int n; - - for (n = 0; p < end; p += d->bLength) { - d = (usb_interface_descriptor_t *)p; - if (p + d->bLength <= end && - d->bDescriptorType == UDESC_INTERFACE && - d->bInterfaceNumber == ifaceno) - n++; - } - return (n); -} - -int -usbd_get_interface_altindex(usbd_interface_handle iface) -{ - return (iface->altindex); -} - -usbd_status -usbd_get_interface(usbd_interface_handle iface, u_int8_t *aiface) -{ - usb_device_request_t req; - - req.bmRequestType = UT_READ_INTERFACE; - req.bRequest = UR_GET_INTERFACE; - USETW(req.wValue, 0); - USETW(req.wIndex, iface->idesc->bInterfaceNumber); - USETW(req.wLength, 1); - return (usbd_do_request(iface->device, &req, aiface)); -} - -/*** Internal routines ***/ - -/* Dequeue all pipe operations, called from critical section. */ -static usbd_status -usbd_ar_pipe(usbd_pipe_handle pipe) -{ - usbd_xfer_handle xfer; - - DPRINTFN(2,("usbd_ar_pipe: pipe=%p\n", pipe)); -#ifdef USB_DEBUG - if (usbdebug > 5) - usbd_dump_queue(pipe); -#endif - pipe->repeat = 0; - pipe->aborting = 1; - while ((xfer = STAILQ_FIRST(&pipe->queue)) != NULL) { - DPRINTFN(2,("usbd_ar_pipe: pipe=%p xfer=%p (methods=%p)\n", - pipe, xfer, pipe->methods)); - /* Make the HC abort it (and invoke the callback). */ - pipe->methods->abort(xfer); - /* XXX only for non-0 usbd_clear_endpoint_stall(pipe); */ - } - pipe->aborting = 0; - return (USBD_NORMAL_COMPLETION); -} - -/* Called from critical section */ -void -usb_transfer_complete(usbd_xfer_handle xfer) -{ - usbd_pipe_handle pipe = xfer->pipe; - usb_dma_t *dmap = &xfer->dmabuf; - int sync = xfer->flags & USBD_SYNCHRONOUS; - int erred = xfer->status == USBD_CANCELLED || - xfer->status == USBD_TIMEOUT; - int repeat; - int polling; - - DPRINTFN(5, ("usb_transfer_complete: pipe=%p xfer=%p status=%d " - "actlen=%d\n", pipe, xfer, xfer->status, xfer->actlen)); -#ifdef DIAGNOSTIC - if (xfer->busy_free != XFER_ONQU) { - kprintf("usb_transfer_complete: xfer=%p not busy 0x%08x\n", - xfer, xfer->busy_free); - return; - } -#endif - -#ifdef DIAGNOSTIC - if (pipe == NULL) { - kprintf("usbd_transfer_cb: pipe==0, xfer=%p\n", xfer); - return; - } -#endif - repeat = pipe->repeat; - polling = pipe->device->bus->use_polling; - /* XXXX */ - if (polling) - pipe->running = 0; - - if (!(xfer->flags & USBD_NO_COPY) && xfer->actlen != 0 && - usbd_xfer_isread(xfer)) { -#ifdef DIAGNOSTIC - if (xfer->actlen > xfer->length) { - kprintf("usb_transfer_complete: actlen > len %d > %d\n", - xfer->actlen, xfer->length); - xfer->actlen = xfer->length; - } -#endif - memcpy(xfer->buffer, KERNADDR(dmap, 0), xfer->actlen); - } - - /* if we allocated the buffer in usbd_transfer() we free it here. */ - if (xfer->rqflags & URQ_AUTO_DMABUF) { - if (!repeat) { - struct usbd_bus *bus = pipe->device->bus; - bus->methods->freem(bus, dmap); - xfer->rqflags &= ~URQ_AUTO_DMABUF; - } - } - - if (!repeat) { - /* Remove request from queue. */ -#ifdef DIAGNOSTIC - if (xfer != STAILQ_FIRST(&pipe->queue)) - kprintf("usb_transfer_complete: bad dequeue %p != %p\n", - xfer, STAILQ_FIRST(&pipe->queue)); - xfer->busy_free = XFER_BUSY; -#endif - STAILQ_REMOVE_HEAD(&pipe->queue, next); - } - DPRINTFN(5,("usb_transfer_complete: repeat=%d new head=%p\n", - repeat, STAILQ_FIRST(&pipe->queue))); - - /* Count completed transfers. */ - ++pipe->device->bus->stats.uds_requests - [pipe->endpoint->edesc->bmAttributes & UE_XFERTYPE]; - - xfer->done = 1; - if (!xfer->status && xfer->actlen < xfer->length && - !(xfer->flags & USBD_SHORT_XFER_OK)) { - DPRINTFN(-1,("usbd_transfer_cb: short transfer %d<%d\n", - xfer->actlen, xfer->length)); - xfer->status = USBD_SHORT_XFER; - } - - /* - * For repeat operations, call the callback first, as the xfer - * will not go away and the "done" method may modify it. Otherwise - * reverse the order in case the callback wants to free or reuse - * the xfer. - * - * USBD_CALLBACK_LAST is set by the keyboard driver to ensure - * that the xfer is restarted prior to doing the callback. - * Otherwise a CTL-ALT-ESC into the debugger will leave the - * xfer inactive and the keyboard will stop working. - */ - if (repeat && (xfer->flags & USBD_CALLBACK_LAST) == 0) { - if (xfer->callback) - xfer->callback(xfer, xfer->priv, xfer->status); - pipe->methods->done(xfer); - } else { - int status = xfer->status; /* get this before restart */ - pipe->methods->done(xfer); /* restart */ - if (xfer->callback) - xfer->callback(xfer, xfer->priv, status); - } - - if (sync && !polling) - wakeup(xfer); - - if (!repeat) { - /* XXX should we stop the queue on all errors? */ - if (erred && pipe->iface != NULL) /* not control pipe */ - pipe->running = 0; - else - usbd_start_next(pipe); - } -} - -usbd_status -usb_insert_transfer(usbd_xfer_handle xfer) -{ - usbd_pipe_handle pipe = xfer->pipe; - usbd_status err; - - DPRINTFN(5,("usb_insert_transfer: pipe=%p running=%d timeout=%d\n", - pipe, pipe->running, xfer->timeout)); -#ifdef DIAGNOSTIC - if (xfer->busy_free != XFER_BUSY) { - kprintf("usb_insert_transfer: xfer=%p not busy 0x%08x\n", - xfer, xfer->busy_free); - return (USBD_INVAL); - } - xfer->busy_free = XFER_ONQU; -#endif - crit_enter(); - STAILQ_INSERT_TAIL(&pipe->queue, xfer, next); - if (pipe->running) - err = USBD_IN_PROGRESS; - else { - pipe->running = 1; - err = USBD_NORMAL_COMPLETION; - } - crit_exit(); - return (err); -} - -/* Called from critical section */ -void -usbd_start_next(usbd_pipe_handle pipe) -{ - usbd_xfer_handle xfer; - usbd_status err; - -#ifdef DIAGNOSTIC - if (pipe == NULL) { - kprintf("usbd_start_next: pipe == NULL\n"); - return; - } - if (pipe->methods == NULL || pipe->methods->start == NULL) { - kprintf("usbd_start_next: pipe=%p no start method\n", pipe); - return; - } -#endif - - /* Get next request in queue. */ - xfer = STAILQ_FIRST(&pipe->queue); - DPRINTFN(5, ("usbd_start_next: pipe=%p, xfer=%p\n", pipe, xfer)); - if (xfer == NULL) { - pipe->running = 0; - } else { - err = pipe->methods->start(xfer); - if (err != USBD_IN_PROGRESS) { - kprintf("usbd_start_next: error=%d\n", err); - pipe->running = 0; - /* XXX do what? */ - } - } -} - -usbd_status -usbd_do_request(usbd_device_handle dev, usb_device_request_t *req, void *data) -{ - return (usbd_do_request_flags(dev, req, data, 0, 0, - USBD_DEFAULT_TIMEOUT)); -} - -usbd_status -usbd_do_request_flags(usbd_device_handle dev, usb_device_request_t *req, - void *data, u_int16_t flags, int *actlen, u_int32_t timo) -{ - return (usbd_do_request_flags_pipe(dev, dev->default_pipe, req, - data, flags, actlen, timo)); -} - -usbd_status -usbd_do_request_flags_pipe(usbd_device_handle dev, usbd_pipe_handle pipe, - usb_device_request_t *req, void *data, u_int16_t flags, int *actlen, - u_int32_t timeout) -{ - usbd_xfer_handle xfer; - usbd_status err; - -#ifdef DIAGNOSTIC - KASSERT(mycpu->gd_intr_nesting_level == 0, - ("usbd_do_request: in interrupt context")); - if (dev->bus->intr_context) { - kprintf("usbd_do_request: not in process context\n"); - return (USBD_INVAL); - } -#endif - - xfer = usbd_alloc_xfer(dev); - if (xfer == NULL) - return (USBD_NOMEM); - usbd_setup_default_xfer(xfer, dev, 0, timeout, req, - data, UGETW(req->wLength), flags, 0); - xfer->pipe = pipe; - err = usbd_sync_transfer(xfer); -#if defined(USB_DEBUG) || defined(DIAGNOSTIC) - if (xfer->actlen > xfer->length) - DPRINTF(("usbd_do_request: overrun addr=%d type=0x%02x req=0x" - "%02x val=%d index=%d rlen=%d length=%d actlen=%d\n", - dev->address, xfer->request.bmRequestType, - xfer->request.bRequest, UGETW(xfer->request.wValue), - UGETW(xfer->request.wIndex), - UGETW(xfer->request.wLength), - xfer->length, xfer->actlen)); -#endif - if (actlen != NULL) - *actlen = xfer->actlen; - if (err == USBD_STALLED) { - /* - * The control endpoint has stalled. Control endpoints - * should not halt, but some may do so anyway so clear - * any halt condition. - */ - usb_device_request_t treq; - usb_status_t status; - u_int16_t s; - usbd_status nerr; - - treq.bmRequestType = UT_READ_ENDPOINT; - treq.bRequest = UR_GET_STATUS; - USETW(treq.wValue, 0); - USETW(treq.wIndex, 0); - USETW(treq.wLength, sizeof(usb_status_t)); - usbd_setup_default_xfer(xfer, dev, 0, USBD_DEFAULT_TIMEOUT, - &treq, &status,sizeof(usb_status_t), - 0, 0); - nerr = usbd_sync_transfer(xfer); - if (nerr) - goto bad; - s = UGETW(status.wStatus); - DPRINTF(("usbd_do_request: status = 0x%04x\n", s)); - if (!(s & UES_HALT)) - goto bad; - treq.bmRequestType = UT_WRITE_ENDPOINT; - treq.bRequest = UR_CLEAR_FEATURE; - USETW(treq.wValue, UF_ENDPOINT_HALT); - USETW(treq.wIndex, 0); - USETW(treq.wLength, 0); - usbd_setup_default_xfer(xfer, dev, 0, USBD_DEFAULT_TIMEOUT, - &treq, &status, 0, 0, 0); - nerr = usbd_sync_transfer(xfer); - if (nerr) - goto bad; - } - - bad: - usbd_free_xfer(xfer); - return (err); -} - -void -usbd_do_request_async_cb(usbd_xfer_handle xfer, usbd_private_handle priv, - usbd_status status) -{ -#if defined(USB_DEBUG) || defined(DIAGNOSTIC) - if (xfer->actlen > xfer->length) - DPRINTF(("usbd_do_request: overrun addr=%d type=0x%02x req=0x" - "%02x val=%d index=%d rlen=%d length=%d actlen=%d\n", - xfer->pipe->device->address, - xfer->request.bmRequestType, - xfer->request.bRequest, UGETW(xfer->request.wValue), - UGETW(xfer->request.wIndex), - UGETW(xfer->request.wLength), - xfer->length, xfer->actlen)); -#endif - usbd_free_xfer(xfer); -} - -/* - * Execute a request without waiting for completion. - * Can be used from interrupt context. - */ -usbd_status -usbd_do_request_async(usbd_device_handle dev, usb_device_request_t *req, - void *data) -{ - usbd_xfer_handle xfer; - usbd_status err; - - xfer = usbd_alloc_xfer(dev); - if (xfer == NULL) - return (USBD_NOMEM); - usbd_setup_default_xfer(xfer, dev, 0, USBD_DEFAULT_TIMEOUT, req, - data, UGETW(req->wLength), 0, usbd_do_request_async_cb); - err = usbd_transfer(xfer); - if (err != USBD_IN_PROGRESS && err) { - usbd_free_xfer(xfer); - return (err); - } - return (USBD_NORMAL_COMPLETION); -} - -const struct usbd_quirks * -usbd_get_quirks(usbd_device_handle dev) -{ -#ifdef DIAGNOSTIC - if (dev == NULL) { - kprintf("usbd_get_quirks: dev == NULL\n"); - return 0; - } -#endif - return (dev->quirks); -} - -/* XXX do periodic free() of free list */ - -/* - * Called from keyboard driver when in polling mode. - */ -void -usbd_dopoll(usbd_interface_handle iface) -{ - iface->device->bus->methods->do_poll(iface->device->bus); -} - -void -usbd_set_polling(usbd_device_handle dev, int on) -{ - if (on) - dev->bus->use_polling++; - else - dev->bus->use_polling--; - /* When polling we need to make sure there is nothing pending to do. */ - if (dev->bus->use_polling) - dev->bus->methods->soft_intr(dev->bus); -} - - -usb_endpoint_descriptor_t * -usbd_get_endpoint_descriptor(usbd_interface_handle iface, u_int8_t address) -{ - struct usbd_endpoint *ep; - int i; - - for (i = 0; i < iface->idesc->bNumEndpoints; i++) { - ep = &iface->endpoints[i]; - if (ep->edesc->bEndpointAddress == address) - return (iface->endpoints[i].edesc); - } - return (0); -} - -/* - * usbd_ratecheck() can limit the number of error messages that occurs. - * When a device is unplugged it may take up to 0.25s for the hub driver - * to notice it. If the driver continuosly tries to do I/O operations - * this can generate a large number of messages. - */ -int -usbd_ratecheck(struct timeval *last) -{ - if (last->tv_sec == time_uptime) - return (0); - last->tv_sec = time_uptime; - return (1); -} - -/* - * Search for a vendor/product pair in an array. The item size is - * given as an argument. - */ -const struct usb_devno * -usb_match_device(const struct usb_devno *tbl, u_int nentries, u_int sz, - u_int16_t vendor, u_int16_t product) -{ - while (nentries-- > 0) { - u_int16_t tproduct = tbl->ud_product; - if (tbl->ud_vendor == vendor && - (tproduct == product || tproduct == USB_PRODUCT_ANY)) - return (tbl); - tbl = (const struct usb_devno *)((const char *)tbl + sz); - } - return (NULL); -} - - -void -usb_desc_iter_init(usbd_device_handle dev, usbd_desc_iter_t *iter) -{ - const usb_config_descriptor_t *cd = usbd_get_config_descriptor(dev); - - iter->cur = (const uByte *)cd; - iter->end = (const uByte *)cd + UGETW(cd->wTotalLength); -} - -const usb_descriptor_t * -usb_desc_iter_next(usbd_desc_iter_t *iter) -{ - const usb_descriptor_t *desc; - - if (iter->cur + sizeof(usb_descriptor_t) >= iter->end) { - if (iter->cur != iter->end) - kprintf("usb_desc_iter_next: bad descriptor\n"); - return NULL; - } - desc = (const usb_descriptor_t *)iter->cur; - if (desc->bLength == 0) { - kprintf("usb_desc_iter_next: descriptor length = 0\n"); - return NULL; - } - iter->cur += desc->bLength; - if (iter->cur > iter->end) { - kprintf("usb_desc_iter_next: descriptor length too large\n"); - return NULL; - } - return desc; -} - -usbd_status -usbd_get_string(usbd_device_handle dev, int si, char *buf) -{ - int swap = dev->quirks->uq_flags & UQ_SWAP_UNICODE; - usb_string_descriptor_t us; - char *s; - int i, n; - u_int16_t c; - usbd_status err; - int size; - - buf[0] = '\0'; - if (si == 0) - return (USBD_INVAL); - if (dev->quirks->uq_flags & UQ_NO_STRINGS) - return (USBD_STALLED); - if (dev->langid == USBD_NOLANG) { - /* Set up default language */ - err = usbd_get_string_desc(dev, USB_LANGUAGE_TABLE, 0, &us, - &size); - if (err || size < 4) { - DPRINTFN(-1,("usbd_get_string: getting lang failed, using 0\n")); - dev->langid = 0; /* Well, just pick something then */ - } else { - /* Pick the first language as the default. */ - dev->langid = UGETW(us.bString[0]); - } - } - err = usbd_get_string_desc(dev, si, dev->langid, &us, &size); - if (err) - return (err); - s = buf; - n = size / 2 - 1; - for (i = 0; i < n; i++) { - c = UGETW(us.bString[i]); - /* Convert from Unicode, handle buggy strings. */ - if ((c & 0xff00) == 0) - *s++ = c; - else if ((c & 0x00ff) == 0 && swap) - *s++ = c >> 8; - else - *s++ = '?'; - } - *s++ = 0; - return (USBD_NORMAL_COMPLETION); -} - -int -usbd_driver_load(module_t mod, int what, void *arg) -{ - /* XXX should implement something like a function that removes all generic devices */ - - return (0); -} - diff --git a/sys/bus/usb/usbdi.h b/sys/bus/usb/usbdi.h deleted file mode 100644 index 5d8a8ce95e..0000000000 --- a/sys/bus/usb/usbdi.h +++ /dev/null @@ -1,280 +0,0 @@ -/* $NetBSD: usbdi.h,v 1.64 2004/10/23 13:26:34 augustss Exp $ */ -/* $FreeBSD: src/sys/dev/usb/usbdi.h,v 1.59 2005/05/16 06:58:43 imp Exp $ */ - -/* - * Copyright (c) 1998 The NetBSD Foundation, Inc. - * All rights reserved. - * - * This code is derived from software contributed to The NetBSD Foundation - * by Lennart Augustsson (lennart@augustsson.net) at - * Carlstedt Research & Technology. - * - * 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. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the NetBSD - * Foundation, Inc. and its contributors. - * 4. Neither the name of The NetBSD Foundation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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. - */ - -#ifndef _USBDI_H_ -#define _USBDI_H_ - -typedef struct usbd_bus *usbd_bus_handle; -typedef struct usbd_device *usbd_device_handle; -typedef struct usbd_interface *usbd_interface_handle; -typedef struct usbd_pipe *usbd_pipe_handle; -typedef struct usbd_xfer *usbd_xfer_handle; -typedef void *usbd_private_handle; - -typedef enum { /* keep in sync with usbd_status_msgs */ - USBD_NORMAL_COMPLETION = 0, /* must be 0 */ - USBD_IN_PROGRESS, /* 1 */ - /* errors */ - USBD_PENDING_REQUESTS, /* 2 */ - USBD_NOT_STARTED, /* 3 */ - USBD_INVAL, /* 4 */ - USBD_NOMEM, /* 5 */ - USBD_CANCELLED, /* 6 */ - USBD_BAD_ADDRESS, /* 7 */ - USBD_IN_USE, /* 8 */ - USBD_NO_ADDR, /* 9 */ - USBD_SET_ADDR_FAILED, /* 10 */ - USBD_NO_POWER, /* 11 */ - USBD_TOO_DEEP, /* 12 */ - USBD_IOERROR, /* 13 */ - USBD_NOT_CONFIGURED, /* 14 */ - USBD_TIMEOUT, /* 15 */ - USBD_SHORT_XFER, /* 16 */ - USBD_STALLED, /* 17 */ - USBD_INTERRUPTED, /* 18 */ - - USBD_ERROR_MAX /* must be last */ -} usbd_status; - -typedef void (*usbd_callback)(usbd_xfer_handle, usbd_private_handle, - usbd_status); - -/* Open flags */ -#define USBD_EXCLUSIVE_USE 0x01 - -/* Use default (specified by ep. desc.) interval on interrupt pipe */ -#define USBD_DEFAULT_INTERVAL (-1) - -/* Request flags */ -#define USBD_NO_COPY 0x01 /* do not copy data to DMA buffer */ -#define USBD_SYNCHRONOUS 0x02 /* wait for completion */ -/* in usb.h #define USBD_SHORT_XFER_OK 0x04*/ /* allow short reads */ -#define USBD_FORCE_SHORT_XFER 0x08 /* force last short packet on write */ -#define USBD_CALLBACK_LAST 0x10 /* restart xfer BEFORE making callback */ - -#define USBD_NO_TIMEOUT 0 -#define USBD_DEFAULT_TIMEOUT 5000 /* ms = 5 s */ - -usbd_status usbd_open_pipe(usbd_interface_handle, u_int8_t, - u_int8_t, usbd_pipe_handle *); -usbd_status usbd_close_pipe(usbd_pipe_handle); -usbd_status usbd_transfer(usbd_xfer_handle); -usbd_xfer_handle usbd_alloc_xfer(usbd_device_handle); -usbd_status usbd_free_xfer(usbd_xfer_handle); -void usbd_setup_xfer(usbd_xfer_handle, usbd_pipe_handle, - usbd_private_handle, void *, - u_int32_t, u_int16_t, u_int32_t, - usbd_callback); -void usbd_setup_default_xfer(usbd_xfer_handle, usbd_device_handle, - usbd_private_handle, u_int32_t, - usb_device_request_t *, void *, - u_int32_t, u_int16_t, usbd_callback); -void usbd_setup_isoc_xfer(usbd_xfer_handle, usbd_pipe_handle, - usbd_private_handle, u_int16_t *, - u_int32_t, u_int16_t, usbd_callback); -void usbd_get_xfer_status(usbd_xfer_handle, usbd_private_handle *, - void **, u_int32_t *, usbd_status *); -usb_endpoint_descriptor_t *usbd_interface2endpoint_descriptor - (usbd_interface_handle, u_int8_t); -usbd_status usbd_abort_pipe(usbd_pipe_handle); -usbd_status usbd_abort_default_pipe(usbd_device_handle); -usbd_status usbd_clear_endpoint_stall(usbd_pipe_handle); -usbd_status usbd_clear_endpoint_stall_async(usbd_pipe_handle); -void usbd_clear_endpoint_toggle(usbd_pipe_handle); -usbd_status usbd_endpoint_count(usbd_interface_handle, u_int8_t *); -usbd_status usbd_interface_count(usbd_device_handle, u_int8_t *); -void usbd_interface2device_handle(usbd_interface_handle, - usbd_device_handle *); -usbd_status usbd_device2interface_handle(usbd_device_handle, - u_int8_t, usbd_interface_handle *); - -usbd_device_handle usbd_pipe2device_handle(usbd_pipe_handle); -void *usbd_alloc_buffer(usbd_xfer_handle, u_int32_t); -void usbd_free_buffer(usbd_xfer_handle); -void *usbd_get_buffer(usbd_xfer_handle); -usbd_status usbd_sync_transfer(usbd_xfer_handle); -usbd_status usbd_open_pipe_intr(usbd_interface_handle, u_int8_t, - u_int8_t, usbd_pipe_handle *, - usbd_private_handle, void *, - u_int32_t, usbd_callback, int); -usbd_status usbd_do_request(usbd_device_handle, usb_device_request_t *, void *); -usbd_status usbd_do_request_async(usbd_device_handle, - usb_device_request_t *, void *); -usbd_status usbd_do_request_flags(usbd_device_handle, usb_device_request_t *, - void *, u_int16_t, int*, u_int32_t); -usbd_status usbd_do_request_flags_pipe(usbd_device_handle, usbd_pipe_handle, - usb_device_request_t *, void *, u_int16_t, int *, u_int32_t); -usb_interface_descriptor_t *usbd_get_interface_descriptor - (usbd_interface_handle); -usb_config_descriptor_t *usbd_get_config_descriptor(usbd_device_handle); -usb_device_descriptor_t *usbd_get_device_descriptor(usbd_device_handle); -int usbd_get_speed(usbd_device_handle); -usbd_status usbd_set_interface(usbd_interface_handle, int); -int usbd_get_no_alts(usb_config_descriptor_t *, int); -usbd_status usbd_get_interface(usbd_interface_handle, u_int8_t *); -void usbd_fill_deviceinfo(usbd_device_handle, struct usb_device_info *, int); -int usbd_get_interface_altindex(usbd_interface_handle); - -usb_interface_descriptor_t *usbd_find_idesc(usb_config_descriptor_t *, - int, int); -usb_endpoint_descriptor_t *usbd_find_edesc(usb_config_descriptor_t *, - int, int, int); - -void usbd_dopoll(usbd_interface_handle); -void usbd_set_polling(usbd_device_handle, int); - -const char *usbd_errstr(usbd_status); - -void usbd_add_dev_event(int, usbd_device_handle); -void usbd_add_drv_event(int, usbd_device_handle, device_t); - -void usbd_devinfo(usbd_device_handle, int, char *); -const struct usbd_quirks *usbd_get_quirks(usbd_device_handle); -usb_endpoint_descriptor_t *usbd_get_endpoint_descriptor - (usbd_interface_handle, u_int8_t); - -usbd_status usbd_reload_device_desc(usbd_device_handle); - -int usbd_ratecheck(struct timeval *last); - -usbd_status usbd_get_string(usbd_device_handle dev, int si, char *buf); - -/* An iterator for descriptors. */ -typedef struct { - const uByte *cur; - const uByte *end; -} usbd_desc_iter_t; -void usb_desc_iter_init(usbd_device_handle dev, usbd_desc_iter_t *iter); -const usb_descriptor_t *usb_desc_iter_next(usbd_desc_iter_t *iter); - -/* - * The usb_task structs form a queue of things to run in the USB event - * thread. Normally this is just device discovery when a connect/disconnect - * has been detected. But it may also be used by drivers that need to - * perform (short) tasks that must have a process context. - */ -struct usb_task { - TAILQ_ENTRY(usb_task) next; - void (*fun)(void *); - void *arg; - int queue; -}; -#define USB_TASKQ_HC 0 -#define USB_TASKQ_DRIVER 1 -#define USB_NUM_TASKQS 2 -#define USB_TASKQ_NAMES {"usbtask-hc", "usbtask-dr"} - -struct usb_softc; -struct usbd_bus *usb_getbushandle(struct usb_softc *sc); - -void usb_do_task(usbd_device_handle, struct usb_task *, int, int); -void usb_add_task(usbd_device_handle, struct usb_task *, int); -void usb_rem_task(usbd_device_handle, struct usb_task *); -#define usb_init_task(t, f, a) ((t)->fun = (f), (t)->arg = (a), (t)->queue = -1) - -struct usb_devno { - u_int16_t ud_vendor; - u_int16_t ud_product; -}; -#define USB_DEVICE(vid, pid) \ - .ud_vendor = (vid), .ud_product = (pid) -const struct usb_devno *usb_match_device(const struct usb_devno *, - u_int, u_int, u_int16_t, u_int16_t); -#define usb_lookup(tbl, vendor, product) \ - usb_match_device((const struct usb_devno *)(tbl), sizeof (tbl) / sizeof ((tbl)[0]), sizeof ((tbl)[0]), (vendor), (product)) -#define USB_PRODUCT_ANY 0xffff - -/* NetBSD attachment information */ - -/* Attach data */ -struct usb_attach_arg { - int port; - int configno; - int ifaceno; - int vendor; - int product; - int release; - int matchlvl; - usbd_device_handle device; /* current device */ - usbd_interface_handle iface; /* current interface */ - int usegeneric; - usbd_interface_handle *ifaces; /* all interfaces */ - int nifaces; /* number of interfaces */ -}; - -/* FreeBSD needs values less than zero */ -#define UMATCH_VENDOR_PRODUCT_REV (-10) -#define UMATCH_VENDOR_PRODUCT (-20) -#define UMATCH_VENDOR_DEVCLASS_DEVPROTO (-30) -#define UMATCH_DEVCLASS_DEVSUBCLASS_DEVPROTO (-40) -#define UMATCH_DEVCLASS_DEVSUBCLASS (-50) -#define UMATCH_VENDOR_PRODUCT_REV_CONF_IFACE (-60) -#define UMATCH_VENDOR_PRODUCT_CONF_IFACE (-70) -#define UMATCH_VENDOR_IFACESUBCLASS_IFACEPROTO (-80) -#define UMATCH_VENDOR_IFACESUBCLASS (-90) -#define UMATCH_IFACECLASS_IFACESUBCLASS_IFACEPROTO (-100) -#define UMATCH_IFACECLASS_IFACESUBCLASS (-110) -#define UMATCH_IFACECLASS (-120) -#define UMATCH_IFACECLASS_GENERIC (-130) -#define UMATCH_GENERIC (-140) -#define UMATCH_NONE (ENXIO) - -#define USBD_SHOW_DEVICE_CLASS 0x1 -#define USBD_SHOW_INTERFACE_CLASS 0x2 - -int usbd_driver_load(module_t mod, int what, void *arg); - -static __inline int -usb_get_port(device_t dev) -{ - struct usb_attach_arg *uap = device_get_ivars(dev); - return (uap->port); -} - -static __inline struct usbd_interface * -usb_get_iface(device_t dev) -{ - struct usb_attach_arg *uap = device_get_ivars(dev); - return (uap->iface); -} - -#define IPL_USB IPL_BIO - -#endif /* _USBDI_H_ */ diff --git a/sys/bus/usb/usbdi_util.c b/sys/bus/usb/usbdi_util.c deleted file mode 100644 index f5cabd3728..0000000000 --- a/sys/bus/usb/usbdi_util.c +++ /dev/null @@ -1,564 +0,0 @@ -/* $NetBSD: usbdi_util.c,v 1.42 2004/12/03 08:53:40 augustss Exp $ */ -/* $FreeBSD: src/sys/dev/usb/usbdi_util.c,v 1.34 2005/03/01 08:01:22 sobomax Exp $ */ -/* $DragonFly: src/sys/bus/usb/usbdi_util.c,v 1.16 2007/08/02 16:19:17 hasso Exp $ */ - -/* - * Copyright (c) 1998 The NetBSD Foundation, Inc. - * All rights reserved. - * - * This code is derived from software contributed to The NetBSD Foundation - * by Lennart Augustsson (lennart@augustsson.net) at - * Carlstedt Research & Technology. - * - * 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. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the NetBSD - * Foundation, Inc. and its contributors. - * 4. Neither the name of The NetBSD Foundation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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 -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include - -#ifdef USB_DEBUG -#define DPRINTF(x) if (usbdebug) kprintf x -#define DPRINTFN(n,x) if (usbdebug>(n)) kprintf x -extern int usbdebug; -#else -#define DPRINTF(x) -#define DPRINTFN(n,x) -#endif - -usbd_status -usbd_get_desc(usbd_device_handle dev, int type, int index, int len, void *desc) -{ - usb_device_request_t req; - - DPRINTFN(3,("usbd_get_desc: type=%d, index=%d, len=%d\n", - type, index, len)); - - req.bmRequestType = UT_READ_DEVICE; - req.bRequest = UR_GET_DESCRIPTOR; - USETW2(req.wValue, type, index); - USETW(req.wIndex, 0); - USETW(req.wLength, len); - return (usbd_do_request(dev, &req, desc)); -} - -usbd_status -usbd_get_config_desc(usbd_device_handle dev, int confidx, - usb_config_descriptor_t *d) -{ - usbd_status err; - - DPRINTFN(3,("usbd_get_config_desc: confidx=%d\n", confidx)); - err = usbd_get_desc(dev, UDESC_CONFIG, confidx, - USB_CONFIG_DESCRIPTOR_SIZE, d); - if (err) - return (err); - if (d->bDescriptorType != UDESC_CONFIG) { - DPRINTFN(-1,("usbd_get_config_desc: confidx=%d, bad desc " - "len=%d type=%d\n", - confidx, d->bLength, d->bDescriptorType)); - return (USBD_INVAL); - } - return (USBD_NORMAL_COMPLETION); -} - -usbd_status -usbd_get_config_desc_full(usbd_device_handle dev, int conf, void *d, int size) -{ - DPRINTFN(3,("usbd_get_config_desc_full: conf=%d\n", conf)); - return (usbd_get_desc(dev, UDESC_CONFIG, conf, size, d)); -} - -usbd_status -usbd_get_device_desc(usbd_device_handle dev, usb_device_descriptor_t *d) -{ - DPRINTFN(3,("usbd_get_device_desc:\n")); - return (usbd_get_desc(dev, UDESC_DEVICE, - 0, USB_DEVICE_DESCRIPTOR_SIZE, d)); -} - -usbd_status -usbd_get_device_status(usbd_device_handle dev, usb_status_t *st) -{ - usb_device_request_t req; - - req.bmRequestType = UT_READ_DEVICE; - req.bRequest = UR_GET_STATUS; - USETW(req.wValue, 0); - USETW(req.wIndex, 0); - USETW(req.wLength, sizeof(usb_status_t)); - return (usbd_do_request(dev, &req, st)); -} - -usbd_status -usbd_get_hub_status(usbd_device_handle dev, usb_hub_status_t *st) -{ - usb_device_request_t req; - - req.bmRequestType = UT_READ_CLASS_DEVICE; - req.bRequest = UR_GET_STATUS; - USETW(req.wValue, 0); - USETW(req.wIndex, 0); - USETW(req.wLength, sizeof(usb_hub_status_t)); - return (usbd_do_request(dev, &req, st)); -} - -usbd_status -usbd_set_address(usbd_device_handle dev, int addr) -{ - usb_device_request_t req; - - req.bmRequestType = UT_WRITE_DEVICE; - req.bRequest = UR_SET_ADDRESS; - USETW(req.wValue, addr); - USETW(req.wIndex, 0); - USETW(req.wLength, 0); - return usbd_do_request(dev, &req, 0); -} - -usbd_status -usbd_get_port_status(usbd_device_handle dev, int port, usb_port_status_t *ps) -{ - usb_device_request_t req; - - req.bmRequestType = UT_READ_CLASS_OTHER; - req.bRequest = UR_GET_STATUS; - USETW(req.wValue, 0); - USETW(req.wIndex, port); - USETW(req.wLength, sizeof *ps); - return (usbd_do_request(dev, &req, ps)); -} - -usbd_status -usbd_clear_hub_feature(usbd_device_handle dev, int sel) -{ - usb_device_request_t req; - - req.bmRequestType = UT_WRITE_CLASS_DEVICE; - req.bRequest = UR_CLEAR_FEATURE; - USETW(req.wValue, sel); - USETW(req.wIndex, 0); - USETW(req.wLength, 0); - return (usbd_do_request(dev, &req, 0)); -} - -usbd_status -usbd_set_hub_feature(usbd_device_handle dev, int sel) -{ - usb_device_request_t req; - - req.bmRequestType = UT_WRITE_CLASS_DEVICE; - req.bRequest = UR_SET_FEATURE; - USETW(req.wValue, sel); - USETW(req.wIndex, 0); - USETW(req.wLength, 0); - return (usbd_do_request(dev, &req, 0)); -} - -usbd_status -usbd_clear_port_feature(usbd_device_handle dev, int port, int sel) -{ - usb_device_request_t req; - - req.bmRequestType = UT_WRITE_CLASS_OTHER; - req.bRequest = UR_CLEAR_FEATURE; - USETW(req.wValue, sel); - USETW(req.wIndex, port); - USETW(req.wLength, 0); - return (usbd_do_request(dev, &req, 0)); -} - -usbd_status -usbd_set_port_feature(usbd_device_handle dev, int port, int sel) -{ - usb_device_request_t req; - - req.bmRequestType = UT_WRITE_CLASS_OTHER; - req.bRequest = UR_SET_FEATURE; - USETW(req.wValue, sel); - USETW(req.wIndex, port); - USETW(req.wLength, 0); - return (usbd_do_request(dev, &req, 0)); -} - -usbd_status -usbd_get_protocol(usbd_interface_handle iface, u_int8_t *report) -{ - usb_interface_descriptor_t *id = usbd_get_interface_descriptor(iface); - usbd_device_handle dev; - usb_device_request_t req; - - DPRINTFN(4, ("usbd_get_protocol: iface=%p, endpt=%d\n", - iface, id->bInterfaceNumber)); - if (id == NULL) - return (USBD_IOERROR); - usbd_interface2device_handle(iface, &dev); - req.bmRequestType = UT_READ_CLASS_INTERFACE; - req.bRequest = UR_GET_PROTOCOL; - USETW(req.wValue, 0); - USETW(req.wIndex, id->bInterfaceNumber); - USETW(req.wLength, 1); - return (usbd_do_request(dev, &req, report)); -} - -usbd_status -usbd_set_protocol(usbd_interface_handle iface, int report) -{ - usb_interface_descriptor_t *id = usbd_get_interface_descriptor(iface); - usbd_device_handle dev; - usb_device_request_t req; - - DPRINTFN(4, ("usbd_set_protocol: iface=%p, report=%d, endpt=%d\n", - iface, report, id->bInterfaceNumber)); - if (id == NULL) - return (USBD_IOERROR); - usbd_interface2device_handle(iface, &dev); - req.bmRequestType = UT_WRITE_CLASS_INTERFACE; - req.bRequest = UR_SET_PROTOCOL; - USETW(req.wValue, report); - USETW(req.wIndex, id->bInterfaceNumber); - USETW(req.wLength, 0); - return (usbd_do_request(dev, &req, 0)); -} - -usbd_status -usbd_set_report(usbd_interface_handle iface, int type, int id, void *data, - int len) -{ - usb_interface_descriptor_t *ifd = usbd_get_interface_descriptor(iface); - usbd_device_handle dev; - usb_device_request_t req; - - DPRINTFN(4, ("usbd_set_report: len=%d\n", len)); - if (ifd == NULL) - return (USBD_IOERROR); - usbd_interface2device_handle(iface, &dev); - req.bmRequestType = UT_WRITE_CLASS_INTERFACE; - req.bRequest = UR_SET_REPORT; - USETW2(req.wValue, type, id); - USETW(req.wIndex, ifd->bInterfaceNumber); - USETW(req.wLength, len); - return (usbd_do_request(dev, &req, data)); -} - -usbd_status -usbd_set_report_async(usbd_interface_handle iface, int type, int id, void *data, - int len) -{ - usb_interface_descriptor_t *ifd = usbd_get_interface_descriptor(iface); - usbd_device_handle dev; - usb_device_request_t req; - - DPRINTFN(4, ("usbd_set_report_async: len=%d\n", len)); - if (ifd == NULL) - return (USBD_IOERROR); - usbd_interface2device_handle(iface, &dev); - req.bmRequestType = UT_WRITE_CLASS_INTERFACE; - req.bRequest = UR_SET_REPORT; - USETW2(req.wValue, type, id); - USETW(req.wIndex, ifd->bInterfaceNumber); - USETW(req.wLength, len); - return (usbd_do_request_async(dev, &req, data)); -} - -usbd_status -usbd_get_report(usbd_interface_handle iface, int type, int id, void *data, - int len) -{ - usb_interface_descriptor_t *ifd = usbd_get_interface_descriptor(iface); - usbd_device_handle dev; - usb_device_request_t req; - - DPRINTFN(4, ("usbd_get_report: len=%d\n", len)); - if (ifd == NULL) - return (USBD_IOERROR); - usbd_interface2device_handle(iface, &dev); - req.bmRequestType = UT_READ_CLASS_INTERFACE; - req.bRequest = UR_GET_REPORT; - USETW2(req.wValue, type, id); - USETW(req.wIndex, ifd->bInterfaceNumber); - USETW(req.wLength, len); - return (usbd_do_request(dev, &req, data)); -} - -usbd_status -usbd_set_idle(usbd_interface_handle iface, int duration, int id) -{ - usb_interface_descriptor_t *ifd = usbd_get_interface_descriptor(iface); - usbd_device_handle dev; - usb_device_request_t req; - - DPRINTFN(4, ("usbd_set_idle: %d %d\n", duration, id)); - if (ifd == NULL) - return (USBD_IOERROR); - usbd_interface2device_handle(iface, &dev); - req.bmRequestType = UT_WRITE_CLASS_INTERFACE; - req.bRequest = UR_SET_IDLE; - USETW2(req.wValue, duration, id); - USETW(req.wIndex, ifd->bInterfaceNumber); - USETW(req.wLength, 0); - return (usbd_do_request(dev, &req, 0)); -} - -usbd_status -usbd_get_report_descriptor(usbd_device_handle dev, int ifcno, - int size, void *d) -{ - usb_device_request_t req; - - req.bmRequestType = UT_READ_INTERFACE; - req.bRequest = UR_GET_DESCRIPTOR; - USETW2(req.wValue, UDESC_REPORT, 0); /* report id should be 0 */ - USETW(req.wIndex, ifcno); - USETW(req.wLength, size); - return (usbd_do_request(dev, &req, d)); -} - -usb_hid_descriptor_t * -usbd_get_hid_descriptor(usbd_interface_handle ifc) -{ - usb_interface_descriptor_t *idesc = usbd_get_interface_descriptor(ifc); - usbd_device_handle dev; - usb_config_descriptor_t *cdesc; - usb_hid_descriptor_t *hd; - char *p, *end; - - if (idesc == NULL) - return (NULL); - usbd_interface2device_handle(ifc, &dev); - cdesc = usbd_get_config_descriptor(dev); - - p = (char *)idesc + idesc->bLength; - end = (char *)cdesc + UGETW(cdesc->wTotalLength); - - for (; p < end; p += hd->bLength) { - hd = (usb_hid_descriptor_t *)p; - if (p + hd->bLength <= end && hd->bDescriptorType == UDESC_HID) - return (hd); - if (hd->bDescriptorType == UDESC_INTERFACE) - break; - } - return (NULL); -} - -usbd_status -usbd_read_report_desc(usbd_interface_handle ifc, void **descp, int *sizep, - struct malloc_type *mem) -{ - usb_interface_descriptor_t *id; - usb_hid_descriptor_t *hid; - usbd_device_handle dev; - usbd_status err; - - usbd_interface2device_handle(ifc, &dev); - id = usbd_get_interface_descriptor(ifc); - if (id == NULL) - return (USBD_INVAL); - hid = usbd_get_hid_descriptor(ifc); - if (hid == NULL) - return (USBD_IOERROR); - *sizep = UGETW(hid->descrs[0].wDescriptorLength); - *descp = kmalloc(*sizep, mem, M_INTWAIT); - err = usbd_get_report_descriptor(dev, id->bInterfaceNumber, - *sizep, *descp); - if (err) { - kfree(*descp, mem); - *descp = NULL; - return (err); - } - return (USBD_NORMAL_COMPLETION); -} - -usbd_status -usbd_get_config(usbd_device_handle dev, u_int8_t *conf) -{ - usb_device_request_t req; - - req.bmRequestType = UT_READ_DEVICE; - req.bRequest = UR_GET_CONFIG; - USETW(req.wValue, 0); - USETW(req.wIndex, 0); - USETW(req.wLength, 1); - return (usbd_do_request(dev, &req, conf)); -} - -static void usbd_bulk_transfer_cb(usbd_xfer_handle xfer, - usbd_private_handle priv, usbd_status status); -static void -usbd_bulk_transfer_cb(usbd_xfer_handle xfer, usbd_private_handle priv, - usbd_status status) -{ - wakeup(xfer); -} - -usbd_status -usbd_bulk_transfer(usbd_xfer_handle xfer, usbd_pipe_handle pipe, - u_int16_t flags, u_int32_t timeout, void *buf, - u_int32_t *size, char *lbl) -{ - usbd_status err; - int error; - - usbd_setup_xfer(xfer, pipe, 0, buf, *size, - flags, timeout, usbd_bulk_transfer_cb); - DPRINTFN(1, ("usbd_bulk_transfer: start transfer %d bytes\n", *size)); - crit_enter(); - err = usbd_transfer(xfer); - if (err != USBD_IN_PROGRESS) { - crit_exit(); - return (err); - } - error = tsleep((caddr_t)xfer, PCATCH, lbl, 0); - crit_exit(); - if (error) { - DPRINTF(("usbd_bulk_transfer: tsleep=%d\n", error)); - usbd_abort_pipe(pipe); - return (USBD_INTERRUPTED); - } - usbd_get_xfer_status(xfer, NULL, NULL, size, &err); - DPRINTFN(1,("usbd_bulk_transfer: transferred %d\n", *size)); - if (err) { - DPRINTF(("usbd_bulk_transfer: error=%d\n", err)); - usbd_clear_endpoint_stall(pipe); - } - return (err); -} - -static void usbd_intr_transfer_cb(usbd_xfer_handle xfer, - usbd_private_handle priv, usbd_status status); -static void -usbd_intr_transfer_cb(usbd_xfer_handle xfer, usbd_private_handle priv, - usbd_status status) -{ - wakeup(xfer); -} - -usbd_status -usbd_intr_transfer(usbd_xfer_handle xfer, usbd_pipe_handle pipe, - u_int16_t flags, u_int32_t timeout, void *buf, - u_int32_t *size, char *lbl) -{ - usbd_status err; - int error; - - usbd_setup_xfer(xfer, pipe, 0, buf, *size, - flags, timeout, usbd_intr_transfer_cb); - DPRINTFN(1, ("usbd_intr_transfer: start transfer %d bytes\n", *size)); - crit_enter(); /* don't want callback until tsleep() */ - err = usbd_transfer(xfer); - if (err != USBD_IN_PROGRESS) { - crit_exit(); - return (err); - } - error = tsleep(xfer, PCATCH, lbl, 0); - crit_exit(); - if (error) { - DPRINTF(("usbd_intr_transfer: tsleep=%d\n", error)); - usbd_abort_pipe(pipe); - return (USBD_INTERRUPTED); - } - usbd_get_xfer_status(xfer, NULL, NULL, size, &err); - DPRINTFN(1,("usbd_intr_transfer: transferred %d\n", *size)); - if (err) { - DPRINTF(("usbd_intr_transfer: error=%d\n", err)); - usbd_clear_endpoint_stall(pipe); - } - return (err); -} - -void -usb_detach_wait(device_t dv) -{ - DPRINTF(("usb_detach_wait: waiting for %s\n", device_get_nameunit(dv))); - if (tsleep(dv, 0, "usbdet", hz * 60)) - kprintf("usb_detach_wait: %s didn't detach\n", - device_get_nameunit(dv)); - DPRINTF(("usb_detach_wait: %s done\n", device_get_nameunit(dv))); -} - -void -usb_detach_wakeup(device_t dv) -{ - DPRINTF(("usb_detach_wakeup: for %s\n", device_get_nameunit(dv))); - wakeup(dv); -} - -const usb_descriptor_t * -usb_find_desc(usbd_device_handle dev, int type, int subtype) -{ - usbd_desc_iter_t iter; - const usb_descriptor_t *desc; - - usb_desc_iter_init(dev, &iter); - for (;;) { - desc = usb_desc_iter_next(&iter); - if (!desc || (desc->bDescriptorType == type && - (subtype == USBD_SUBTYPE_ANY || - subtype == desc->bDescriptorSubtype))) - break; - } - return desc; -} - -/* same as usb_find_desc(), but searches only in the specified interface. */ -const usb_descriptor_t * -usb_find_desc_if(usbd_device_handle dev, int type, int subtype, - usb_interface_descriptor_t *id) -{ - usbd_desc_iter_t iter; - const usb_descriptor_t *desc; - - usb_desc_iter_init(dev, &iter); - - iter.cur = (void *)id; /* start from the interface desc */ - usb_desc_iter_next(&iter); /* and skip it */ - - while ((desc = usb_desc_iter_next(&iter)) != NULL) { - if (desc->bDescriptorType == UDESC_INTERFACE) { - /* we ran into the next interface --- not found */ - return NULL; - } - if (desc->bDescriptorType == type && - (subtype == USBD_SUBTYPE_ANY || - subtype == desc->bDescriptorSubtype)) - break; - } - return desc; -} - diff --git a/sys/bus/usb/usbdi_util.h b/sys/bus/usb/usbdi_util.h deleted file mode 100644 index ba6d94ac62..0000000000 --- a/sys/bus/usb/usbdi_util.h +++ /dev/null @@ -1,99 +0,0 @@ -/* $NetBSD: usbdi_util.h,v 1.31 2004/12/03 08:53:40 augustss Exp $ */ -/* $FreeBSD: src/sys/dev/usb/usbdi_util.h,v 1.19 2005/03/01 08:01:22 sobomax Exp $ */ -/* $DragonFly: src/sys/bus/usb/usbdi_util.h,v 1.7 2007/08/02 16:19:17 hasso Exp $ */ - -/* - * Copyright (c) 1998 The NetBSD Foundation, Inc. - * All rights reserved. - * - * This code is derived from software contributed to The NetBSD Foundation - * by Lennart Augustsson (lennart@augustsson.net) at - * Carlstedt Research & Technology. - * - * 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. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the NetBSD - * Foundation, Inc. and its contributors. - * 4. Neither the name of The NetBSD Foundation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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. - */ - -usbd_status usbd_get_desc(usbd_device_handle dev, int type, - int index, int len, void *desc); -usbd_status usbd_get_config_desc(usbd_device_handle, int, - usb_config_descriptor_t *); -usbd_status usbd_get_config_desc_full(usbd_device_handle, int, void *, int); -usbd_status usbd_get_device_desc(usbd_device_handle dev, - usb_device_descriptor_t *d); -usbd_status usbd_set_address(usbd_device_handle dev, int addr); -usbd_status usbd_get_port_status(usbd_device_handle, - int, usb_port_status_t *); -usbd_status usbd_set_hub_feature(usbd_device_handle dev, int); -usbd_status usbd_clear_hub_feature(usbd_device_handle, int); -usbd_status usbd_set_port_feature(usbd_device_handle dev, int, int); -usbd_status usbd_clear_port_feature(usbd_device_handle, int, int); -usbd_status usbd_get_device_status(usbd_device_handle, usb_status_t *); -usbd_status usbd_get_hub_status(usbd_device_handle, usb_hub_status_t *); -usbd_status usbd_get_protocol(usbd_interface_handle dev, u_int8_t *report); -usbd_status usbd_set_protocol(usbd_interface_handle dev, int report); -usbd_status usbd_get_report_descriptor(usbd_device_handle dev, int ifcno, - int size, void *d); -struct usb_hid_descriptor *usbd_get_hid_descriptor(usbd_interface_handle ifc); -usbd_status usbd_set_report(usbd_interface_handle iface, int type, int id, - void *data,int len); -usbd_status usbd_set_report_async(usbd_interface_handle iface, int type, - int id, void *data, int len); -usbd_status usbd_get_report(usbd_interface_handle iface, int type, int id, - void *data, int len); -usbd_status usbd_set_idle(usbd_interface_handle iface, int duration, int id); -usbd_status usbd_read_report_desc(usbd_interface_handle ifc, void **descp, - int *sizep, struct malloc_type *mem); -usbd_status usbd_get_config(usbd_device_handle dev, u_int8_t *conf); -usbd_status usbd_get_string_desc(usbd_device_handle dev, int sindex, - int langid, usb_string_descriptor_t *sdesc, - int *sizep); -void usbd_delay_ms(usbd_device_handle, u_int); - - -usbd_status usbd_set_config_no(usbd_device_handle dev, int no, int msg); -usbd_status usbd_set_config_index(usbd_device_handle dev, int index, int msg); - -usbd_status usbd_bulk_transfer(usbd_xfer_handle xfer, usbd_pipe_handle pipe, - u_int16_t flags, u_int32_t timeout, void *buf, - u_int32_t *size, char *lbl); - -usbd_status usbd_intr_transfer(usbd_xfer_handle xfer, usbd_pipe_handle pipe, - u_int16_t flags, u_int32_t timeout, void *buf, - u_int32_t *size, char *lbl); - -void usb_detach_wait(device_t); -void usb_detach_wakeup(device_t); - -const usb_descriptor_t *usb_find_desc(usbd_device_handle dev, int type, - int subtype); -const usb_descriptor_t *usb_find_desc_if(usbd_device_handle dev, int type, - int subtype, - usb_interface_descriptor_t *id); -#define USBD_SUBTYPE_ANY (~0) - diff --git a/sys/bus/usb/usbdivar.h b/sys/bus/usb/usbdivar.h deleted file mode 100644 index c1e4736a1d..0000000000 --- a/sys/bus/usb/usbdivar.h +++ /dev/null @@ -1,293 +0,0 @@ -/* $NetBSD: usbdivar.h,v 1.70 2002/07/11 21:14:36 augustss Exp $ */ -/* $FreeBSD: src/sys/dev/usb/usbdivar.h,v 1.43.2.1 2006/03/01 01:59:05 iedowse Exp $ */ -/* $DragonFly: src/sys/bus/usb/usbdivar.h,v 1.13 2008/05/26 13:56:08 mneumann Exp $ */ - -/* - * Copyright (c) 1998 The NetBSD Foundation, Inc. - * All rights reserved. - * - * This code is derived from software contributed to The NetBSD Foundation - * by Lennart Augustsson (lennart@augustsson.net) at - * Carlstedt Research & Technology. - * - * 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. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the NetBSD - * Foundation, Inc. and its contributors. - * 4. Neither the name of The NetBSD Foundation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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. - */ - - -/* From usb_mem.h */ -struct usb_dma_block; -typedef struct { - struct usb_dma_block *block; - u_int offs; - u_int len; -} usb_dma_t; - -struct usbd_xfer; -struct usbd_pipe; - -struct usbd_endpoint { - usb_endpoint_descriptor_t *edesc; - int refcnt; - int savedtoggle; -}; - -struct usbd_bus_methods { - usbd_status (*open_pipe)(struct usbd_pipe *pipe); - void (*soft_intr)(void *); - void (*do_poll)(struct usbd_bus *); - usbd_status (*allocm)(struct usbd_bus *, usb_dma_t *, - u_int32_t bufsize); - void (*freem)(struct usbd_bus *, usb_dma_t *); - struct usbd_xfer * (*allocx)(struct usbd_bus *); - void (*freex)(struct usbd_bus *, struct usbd_xfer *); -}; - -struct usbd_pipe_methods { - usbd_status (*transfer)(usbd_xfer_handle xfer); - usbd_status (*start)(usbd_xfer_handle xfer); - void (*abort)(usbd_xfer_handle xfer); - void (*close)(usbd_pipe_handle pipe); - void (*cleartoggle)(usbd_pipe_handle pipe); - void (*done)(usbd_xfer_handle xfer); -}; - -struct usbd_tt { - struct usbd_hub *hub; -}; - -struct usbd_port { - usb_port_status_t status; - u_int16_t power; /* mA of current on port */ - u_int8_t portno; - u_int8_t restartcnt; -#define USBD_RESTART_MAX 5 - struct usbd_device *device; /* Connected device */ - struct usbd_device *parent; /* The ports hub */ - struct usbd_tt *tt; /* Transaction translator (if any) */ -}; - -struct usbd_hub { - usbd_status (*explore)(usbd_device_handle hub); - device_t hubdev; - usb_hub_descriptor_t hubdesc; - struct usbd_port ports[1]; -}; - -struct usb_softc; - -/*****/ - -struct usbd_bus { - /* Filled by HC driver */ - device_t bdev; /* base device, host adapter */ - struct usbd_bus_methods *methods; - u_int32_t pipe_size; /* size of a pipe struct */ - /* Filled by usb driver */ - struct usbd_device *root_hub; - usbd_device_handle devices[USB_MAX_DEVICES]; - char needs_explore;/* a hub a signalled a change */ - char use_polling; - struct usb_softc *usbctl; - struct usb_device_stats stats; - int intr_context; - u_int no_intrs; - int usbrev; /* USB revision */ -#define USBREV_UNKNOWN 0 -#define USBREV_PRE_1_0 1 -#define USBREV_1_0 2 -#define USBREV_1_1 3 -#define USBREV_2_0 4 -#define USBREV_STR { "unknown", "pre 1.0", "1.0", "1.1", "2.0" } - -#ifdef USB_USE_SOFTINTR - struct callout softi; -#endif - - bus_dma_tag_t dmatag; /* DMA tag */ -}; - -struct usbd_device { - struct usbd_bus *bus; /* our controller */ - struct usbd_pipe *default_pipe; /* pipe 0 */ - u_int8_t address; /* device addess */ - u_int8_t config; /* current configuration # */ - u_int8_t depth; /* distance from root hub */ - u_int8_t speed; /* low/full/high speed */ - u_int8_t self_powered; /* flag for self powered */ - u_int16_t power; /* mA the device uses */ - int16_t langid; /* language for strings */ -#define USBD_NOLANG (-1) - usb_event_cookie_t cookie; /* unique connection id */ - struct usbd_port *powersrc; /* upstream hub port, or 0 */ - struct usbd_device *myhub; /* upstream hub */ - struct usbd_port *myhsport; /* closest high speed port */ - struct usbd_endpoint def_ep; /* for pipe 0 */ - usb_endpoint_descriptor_t def_ep_desc; /* for pipe 0 */ - struct usbd_interface *ifaces; /* array of all interfaces */ - usb_device_descriptor_t ddesc; /* device descriptor */ - usb_config_descriptor_t *cdesc; /* full config descr */ - const struct usbd_quirks *quirks; /* device quirks, always set */ - struct usbd_hub *hub; /* only if this is a hub */ - device_t *subdevs; /* sub-devices, 0 terminated */ - uint8_t *ifacenums; /* sub-device interfacenumbers */ -}; - -struct usbd_interface { - struct usbd_device *device; - usb_interface_descriptor_t *idesc; - int index; - int altindex; - struct usbd_endpoint *endpoints; - void *priv; - LIST_HEAD(, usbd_pipe) pipes; -}; - -struct usbd_pipe { - struct usbd_interface *iface; - struct usbd_device *device; - struct usbd_endpoint *endpoint; - int refcnt; - char running; - char aborting; - STAILQ_HEAD(, usbd_xfer) queue; - LIST_ENTRY(usbd_pipe) next; - - usbd_xfer_handle intrxfer; /* used for repeating requests */ - char repeat; - int interval; - - /* Filled by HC driver. */ - struct usbd_pipe_methods *methods; -}; - -struct usbd_xfer { - struct usbd_pipe *pipe; - void *priv; - void *buffer; - u_int32_t length; - u_int32_t actlen; - u_int16_t flags; - u_int32_t timeout; - usbd_status status; - usbd_callback callback; - __volatile char done; -#ifdef DIAGNOSTIC - u_int32_t busy_free; -#define XFER_FREE 0x46524545 -#define XFER_BUSY 0x42555359 -#define XFER_ONQU 0x4f4e5155 -#endif - - /* For control pipe */ - usb_device_request_t request; - - /* For isoc */ - u_int16_t *frlengths; - int nframes; - - /* For memory allocation */ - struct usbd_device *device; - usb_dma_t dmabuf; - - int rqflags; -#define URQ_REQUEST 0x01 -#define URQ_AUTO_DMABUF 0x10 -#define URQ_DEV_DMABUF 0x20 - - STAILQ_ENTRY(usbd_xfer) next; - - void *hcpriv; /* private use by the HC driver */ - - struct callout timeout_handle; -}; - -void usbd_init(void); -void usbd_finish(void); - -#ifdef USB_DEBUG -void usbd_dump_iface(struct usbd_interface *iface); -void usbd_dump_device(struct usbd_device *dev); -void usbd_dump_endpoint(struct usbd_endpoint *endp); -void usbd_dump_queue(usbd_pipe_handle pipe); -void usbd_dump_pipe(usbd_pipe_handle pipe); -#endif - -/* Routines from usb_subr.c */ -int usbctlprint(void *, const char *); -void usb_delay_ms(usbd_bus_handle, u_int); -usbd_status usbd_reset_port(usbd_device_handle dev, - int port, usb_port_status_t *ps); -usbd_status usbd_setup_pipe(usbd_device_handle dev, - usbd_interface_handle iface, - struct usbd_endpoint *, int, - usbd_pipe_handle *pipe); -usbd_status usbd_new_device(device_t parent, - usbd_bus_handle bus, int depth, - int lowspeed, int port, - struct usbd_port *); -void usbd_remove_device(usbd_device_handle, struct usbd_port *); -int usbd_printBCD(char *cp, int bcd); -usbd_status usbd_fill_iface_data(usbd_device_handle dev, int i, int a); -void usb_free_device(usbd_device_handle); - -usbd_status usb_insert_transfer(usbd_xfer_handle xfer); -void usb_transfer_complete(usbd_xfer_handle xfer); -void usb_disconnect_port(struct usbd_port *up, device_t); - -/* Routines from usb.c */ -void usb_needs_explore(usbd_device_handle); -void usb_schedsoftintr(struct usbd_bus *); - -/* Locator stuff. */ - -/* XXX these values are used to statically bind some elements in the USB tree - * to specific driver instances. This should be somehow emulated in FreeBSD - * but can be done later on. - * The values are copied from the files.usb file in the NetBSD sources. - */ -#define UHUBCF_PORT_DEFAULT -1 -#define UHUBCF_CONFIGURATION_DEFAULT -1 -#define UHUBCF_INTERFACE_DEFAULT -1 -#define UHUBCF_VENDOR_DEFAULT -1 -#define UHUBCF_PRODUCT_DEFAULT -1 -#define UHUBCF_RELEASE_DEFAULT -1 - -#define uhubcf_port cf_loc[UHUBCF_PORT] -#define uhubcf_configuration cf_loc[UHUBCF_CONFIGURATION] -#define uhubcf_interface cf_loc[UHUBCF_INTERFACE] -#define uhubcf_vendor cf_loc[UHUBCF_VENDOR] -#define uhubcf_product cf_loc[UHUBCF_PRODUCT] -#define uhubcf_release cf_loc[UHUBCF_RELEASE] -#define UHUB_UNK_PORT UHUBCF_PORT_DEFAULT /* wildcarded 'port' */ -#define UHUB_UNK_CONFIGURATION UHUBCF_CONFIGURATION_DEFAULT /* wildcarded 'configuration' */ -#define UHUB_UNK_INTERFACE UHUBCF_INTERFACE_DEFAULT /* wildcarded 'interface' */ -#define UHUB_UNK_VENDOR UHUBCF_VENDOR_DEFAULT /* wildcarded 'vendor' */ -#define UHUB_UNK_PRODUCT UHUBCF_PRODUCT_DEFAULT /* wildcarded 'product' */ -#define UHUB_UNK_RELEASE UHUBCF_RELEASE_DEFAULT /* wildcarded 'release' */ - diff --git a/sys/bus/usb/usbhid.h b/sys/bus/usb/usbhid.h deleted file mode 100644 index 08d294df93..0000000000 --- a/sys/bus/usb/usbhid.h +++ /dev/null @@ -1,190 +0,0 @@ -/* - * $NetBSD: usbhid.h,v 1.9 2000/09/03 19:09:14 augustss Exp $ - * $FreeBSD: src/sys/dev/usb/usbhid.h,v 1.13 2002/01/02 20:16:53 joe Exp $ - * $DragonFly: src/sys/bus/usb/usbhid.h,v 1.4 2007/12/30 20:02:56 hasso Exp $ - */ - -/* - * Copyright (c) 1998 The NetBSD Foundation, Inc. - * All rights reserved. - * - * This code is derived from software contributed to The NetBSD Foundation - * by Lennart Augustsson (lennart@augustsson.net) at - * Carlstedt Research & Technology. - * - * 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. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the NetBSD - * Foundation, Inc. and its contributors. - * 4. Neither the name of The NetBSD Foundation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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. - */ - - -#ifndef _USBHID_H_ -#define _USBHID_H_ - -#define UR_GET_HID_DESCRIPTOR 0x06 -#define UDESC_HID 0x21 -#define UDESC_REPORT 0x22 -#define UDESC_PHYSICAL 0x23 -#define UR_SET_HID_DESCRIPTOR 0x07 -#define UR_GET_REPORT 0x01 -#define UR_SET_REPORT 0x09 -#define UR_GET_IDLE 0x02 -#define UR_SET_IDLE 0x0a -#define UR_GET_PROTOCOL 0x03 -#define UR_SET_PROTOCOL 0x0b - -typedef struct usb_hid_descriptor { - uByte bLength; - uByte bDescriptorType; - uWord bcdHID; - uByte bCountryCode; - uByte bNumDescriptors; - struct { - uByte bDescriptorType; - uWord wDescriptorLength; - } descrs[1]; -} UPACKED usb_hid_descriptor_t; -#define USB_HID_DESCRIPTOR_SIZE(n) (9+(n)*3) - -/* Usage pages */ -#define HUP_UNDEFINED 0x0000 -#define HUP_GENERIC_DESKTOP 0x0001 -#define HUP_SIMULATION 0x0002 -#define HUP_VR_CONTROLS 0x0003 -#define HUP_SPORTS_CONTROLS 0x0004 -#define HUP_GAMING_CONTROLS 0x0005 -#define HUP_KEYBOARD 0x0007 -#define HUP_LEDS 0x0008 -#define HUP_BUTTON 0x0009 -#define HUP_ORDINALS 0x000a -#define HUP_TELEPHONY 0x000b -#define HUP_CONSUMER 0x000c -#define HUP_DIGITIZERS 0x000d -#define HUP_PHYSICAL_IFACE 0x000e -#define HUP_UNICODE 0x0010 -#define HUP_ALPHANUM_DISPLAY 0x0014 -#define HUP_MONITOR 0x0080 -#define HUP_MONITOR_ENUM_VAL 0x0081 -#define HUP_VESA_VC 0x0082 -#define HUP_VESA_CMD 0x0083 -#define HUP_POWER 0x0084 -#define HUP_BATTERY_SYSTEM 0x0085 -#define HUP_BARCODE_SCANNER 0x008b -#define HUP_SCALE 0x008c -#define HUP_CAMERA_CONTROL 0x0090 -#define HUP_ARCADE 0x0091 -#define HUP_MICROSOFT 0xff00 - -/* Usages, generic desktop */ -#define HUG_POINTER 0x0001 -#define HUG_MOUSE 0x0002 -#define HUG_JOYSTICK 0x0004 -#define HUG_GAME_PAD 0x0005 -#define HUG_KEYBOARD 0x0006 -#define HUG_KEYPAD 0x0007 -#define HUG_X 0x0030 -#define HUG_Y 0x0031 -#define HUG_Z 0x0032 -#define HUG_RX 0x0033 -#define HUG_RY 0x0034 -#define HUG_RZ 0x0035 -#define HUG_SLIDER 0x0036 -#define HUG_DIAL 0x0037 -#define HUG_WHEEL 0x0038 -#define HUG_HAT_SWITCH 0x0039 -#define HUG_COUNTED_BUFFER 0x003a -#define HUG_BYTE_COUNT 0x003b -#define HUG_MOTION_WAKEUP 0x003c -#define HUG_VX 0x0040 -#define HUG_VY 0x0041 -#define HUG_VZ 0x0042 -#define HUG_VBRX 0x0043 -#define HUG_VBRY 0x0044 -#define HUG_VBRZ 0x0045 -#define HUG_VNO 0x0046 -#define HUG_SYSTEM_CONTROL 0x0080 -#define HUG_SYSTEM_POWER_DOWN 0x0081 -#define HUG_SYSTEM_SLEEP 0x0082 -#define HUG_SYSTEM_WAKEUP 0x0083 -#define HUG_SYSTEM_CONTEXT_MENU 0x0084 -#define HUG_SYSTEM_MAIN_MENU 0x0085 -#define HUG_SYSTEM_APP_MENU 0x0086 -#define HUG_SYSTEM_MENU_HELP 0x0087 -#define HUG_SYSTEM_MENU_EXIT 0x0088 -#define HUG_SYSTEM_MENU_SELECT 0x0089 -#define HUG_SYSTEM_MENU_RIGHT 0x008a -#define HUG_SYSTEM_MENU_LEFT 0x008b -#define HUG_SYSTEM_MENU_UP 0x008c -#define HUG_SYSTEM_MENU_DOWN 0x008d - -/* Usages Digitizers */ -#define HUD_UNDEFINED 0x0000 -#define HUD_TIP_PRESSURE 0x0030 -#define HUD_BARREL_PRESSURE 0x0031 -#define HUD_IN_RANGE 0x0032 -#define HUD_TOUCH 0x0033 -#define HUD_UNTOUCH 0x0034 -#define HUD_TAP 0x0035 -#define HUD_QUALITY 0x0036 -#define HUD_DATA_VALID 0x0037 -#define HUD_TRANSDUCER_INDEX 0x0038 -#define HUD_TABLET_FKEYS 0x0039 -#define HUD_PROGRAM_CHANGE_KEYS 0x003a -#define HUD_BATTERY_STRENGTH 0x003b -#define HUD_INVERT 0x003c -#define HUD_X_TILT 0x003d -#define HUD_Y_TILT 0x003e -#define HUD_AZIMUTH 0x003f -#define HUD_ALTITUDE 0x0040 -#define HUD_TWIST 0x0041 -#define HUD_TIP_SWITCH 0x0042 -#define HUD_SEC_TIP_SWITCH 0x0043 -#define HUD_BARREL_SWITCH 0x0044 -#define HUD_ERASER 0x0045 -#define HUD_TABLET_PICK 0x0046 - -/* Usages, Consumer */ -#define HUC_AC_PAN 0x0238 - -#define HID_USAGE2(p,u) (((p) << 16) | u) - -#define UHID_INPUT_REPORT 0x01 -#define UHID_OUTPUT_REPORT 0x02 -#define UHID_FEATURE_REPORT 0x03 - -/* Bits in the input/output/feature items */ -#define HIO_CONST 0x001 -#define HIO_VARIABLE 0x002 -#define HIO_RELATIVE 0x004 -#define HIO_WRAP 0x008 -#define HIO_NONLINEAR 0x010 -#define HIO_NOPREF 0x020 -#define HIO_NULLSTATE 0x040 -#define HIO_VOLATILE 0x080 -#define HIO_BUFBYTES 0x100 - -#endif /* _USBHID_H_ */ diff --git a/sys/conf/files b/sys/conf/files index 0861a74af6..85c5588456 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -166,7 +166,6 @@ dev/disk/nata/ata-lowlevel.c optional nata dev/disk/nata/ata-pci.c optional nata pci dev/disk/nata/ata-queue.c optional nata dev/disk/nata/ata-raid.c optional nataraid -dev/disk/nata/ata-usb.c optional natausb oldusb dev/disk/nata/atapi-cam.c optional natapicam dev/disk/nata/atapi-cd.c optional natapicd dev/disk/nata/atapi-fd.c optional natapifd @@ -1668,53 +1667,6 @@ vm/vm_zeroidle.c standard vm/vm_zone.c standard # # USB support -bus/usb/usb_if.m optional oldusb -bus/usb/uhci.c optional uhci oldusb -bus/usb/uhci_pci.c optional uhci oldusb -bus/usb/ohci.c optional ohci oldusb -bus/usb/ohci_pci.c optional ohci oldusb -bus/usb/ehci.c optional ehci oldusb -bus/usb/ehci_pci.c optional ehci oldusb -dev/usbmisc/ucom/ucom.c optional ucom oldusb -dev/usbmisc/uvisor/uvisor.c optional uvisor ucom oldusb -dev/usbmisc/uvscom/uvscom.c optional uvscom ucom oldusb -bus/usb/usb.c optional oldusb -bus/usb/usbdi.c optional oldusb -bus/usb/usbdi_util.c optional oldusb -bus/usb/usb_ethersubr.c optional oldusb -bus/usb/usb_mem.c optional oldusb -bus/usb/usb_subr.c optional oldusb -bus/usb/usb_quirks.c optional oldusb -bus/usb/hid.c optional oldusb -bus/usb/uhub.c optional oldusb -dev/usbmisc/moscom/moscom.c optional moscom ucom oldusb -dev/usbmisc/ubt/ubt.c optional ubt oldusb -dev/usbmisc/uark/uark.c optional uark ucom oldusb -dev/usbmisc/uchcom/uchcom.c optional uchcom ucom oldusb -dev/usbmisc/ufm/ufm.c optional ufm oldusb -dev/usbmisc/ubsa/ubsa.c optional ubsa ucom oldusb -dev/usbmisc/uftdi/uftdi.c optional uftdi ucom oldusb -dev/usbmisc/ugen/ugen.c optional ugen oldusb -dev/usbmisc/ugen/ugenbuf.c optional ugen oldusb -dev/usbmisc/ugensa/ugensa.c optional ugensa ucom oldusb -dev/usbmisc/uhid/uhid.c optional uhid oldusb -dev/usbmisc/umct/umct.c optional umct ucom oldusb -dev/usbmisc/ums/ums.c optional ums oldusb -dev/usbmisc/uplcom/uplcom.c optional uplcom ucom oldusb -dev/usbmisc/urio/urio.c optional urio oldusb -dev/usbmisc/uslcom/uslcom.c optional uslcom ucom oldusb -dev/usbmisc/uticom/uticom.c optional uticom ucom oldusb -dev/usbmisc/ulpt/ulpt.c optional ulpt oldusb -dev/usbmisc/ukbd/ukbd.c optional ukbd oldusb -dev/usbmisc/umass/umass.c optional umass oldusb -dev/usbmisc/umodem/umodem.c optional umodem oldusb -dev/usbmisc/uscanner/uscanner.c optional uscanner oldusb -dev/netif/aue/if_aue.c optional aue oldusb -dev/netif/axe/if_axe.c optional axe oldusb -dev/netif/cue/if_cue.c optional cue oldusb -dev/netif/kue/if_kue.c optional kue oldusb -dev/netif/lgue/if_lgue.c optional lgue oldusb -dev/netif/rue/if_rue.c optional rue oldusb dev/netif/lnc/am7990.c optional lnc dev/netif/lnc/am79900.c optional lnc dev/netif/lnc/if_lnc_pci.c optional lnc pci @@ -1780,8 +1732,6 @@ dev/sound/pcm/mixer_if.m optional pcm dev/sound/pcm/sndstat.c optional pcm dev/sound/pcm/sound.c optional pcm dev/sound/pcm/vchan.c optional pcm -dev/sound/usb/uaudio.c optional snd_uaudio oldusb -dev/sound/usb/uaudio_pcm.c optional snd_uaudio oldusb # # These files in libkern/ are those needed by all architectures. Some # of the files in libkern/ are only needed on some architectures, e.g., diff --git a/sys/conf/kmod.mk b/sys/conf/kmod.mk index e4383f8015..c15b969527 100644 --- a/sys/conf/kmod.mk +++ b/sys/conf/kmod.mk @@ -307,7 +307,7 @@ MFILES?= kern/bus_if.m kern/device_if.m bus/iicbus/iicbb_if.m \ bus/iicbus/iicbus_if.m bus/isa/isa_if.m dev/netif/mii_layer/miibus_if.m \ bus/pccard/card_if.m bus/pccard/power_if.m bus/pci/pci_if.m \ bus/pci/pcib_if.m \ - bus/ppbus/ppbus_if.m bus/smbus/smbus_if.m \ + bus/ppbus/ppbus_if.m bus/smbus/smbus_if.m bus/u4b/usb_if.m \ dev/acpica/acpi_if.m dev/acpica/acpi_wmi_if.m dev/disk/nata/ata_if.m \ dev/disk/sdhci/sdhci_if.m \ dev/sound/pcm/ac97_if.m dev/sound/pcm/channel_if.m \ @@ -317,12 +317,6 @@ MFILES?= kern/bus_if.m kern/device_if.m bus/iicbus/iicbb_if.m \ dev/virtual/virtio/virtio/virtio_bus_if.m \ dev/virtual/virtio/virtio/virtio_if.m -.if !defined(WANT_OLDUSB) -MFILES+=bus/u4b/usb_if.m -.else -MFILES+=bus/usb/usb_if.m -.endif - .for _srcsrc in ${MFILES} .for _ext in c h .for _src in ${SRCS:M${_srcsrc:T:R}.${_ext}} diff --git a/sys/config/GENERIC b/sys/config/GENERIC index 4def3495b0..01804622db 100644 --- a/sys/config/GENERIC +++ b/sys/config/GENERIC @@ -339,20 +339,6 @@ pseudo-device cryptodev # USB support # -# NOTE: If you enable 'oldusb' you must also disable 'usb' and rebuild -# the world with WANT_OLDUSB=true in /etc/make.conf, in addition -# to rebuilding the kernel. -# -#device oldusb # use this instead of usb for the old stack -#device natausb # ATA-over-USB support (oldusb) -#device ugen # Generic (oldusb) -#device uscanner # Scanners (oldusb) -#device urio # Diamond Rio MP3 Player (oldusb) -device aue # ADMtek USB ethernet -device cue # CATC USB ethernet -device kue # Kawasaki LSI USB ethernet -#device rue # RealTek 8150 based USB ethernet (oldusb) - device usb # USB Bus (required) device uhci # UHCI PCI->USB interface device ohci # OHCI PCI->USB interface @@ -363,9 +349,11 @@ device umass # Disks/Mass storage - Requires scbus and da device ums # Mouse # USB Ethernet, requires mii device axe # ASIX Electronics USB Ethernet +device aue # ADMtek USB ethernet +device cue # CATC USB ethernet +device kue # Kawasaki LSI USB ethernet # USB wireless NICs, requires wlan, wlan_amrr #device rum # Ralink Technology RT2501USB/RT2601USB -#device ural # Ralink Technology RT2500USB # FireWire support device firewire # FireWire bus code diff --git a/sys/config/LINT b/sys/config/LINT index 37f49c4368..ff2a5807b3 100644 --- a/sys/config/LINT +++ b/sys/config/LINT @@ -2089,41 +2089,6 @@ device mly # USB support # -# NOTE: If you enable 'oldusb' you must also disable 'usb' and rebuild -# the world with WANT_OLDUSB=true in /etc/make.conf, in addition -# to rebuilding the kernel. -# -# Use this instead of usb for the old stack -#device oldusb -#device natausb # ATA-over-USB support (oldusb) -# -# USB Bluetooth (oldusb) -#device ubt -# Generic USB device driver (oldusb) -#device ugen -# USB Rio (MP3 Player) (oldusb) -#device urio -# USB scanners (oldusb) -#device uscanner -# USB com devices (oldusb) -#device moscom -#device uticom -# -# USB CDC ethernet (oldusb) -#Supports the LG P-500 smartphone. -#device lgue -# -# RealTek 8150 based USB ethernet device (oldusb): -# Melco LUA-KTX -# GREEN HOUSE GH-USB100B -# Billionton ThumbLAN USBKR2-100B -#device rue -# -# Ralink Technology RT2500USB (oldusb) -#device ural -# -# USB sound (oldusb) -#device "snd_uaudio" # UHCI controller device uhci diff --git a/sys/config/LINT64 b/sys/config/LINT64 index 237f7bec3c..daa458fdf4 100644 --- a/sys/config/LINT64 +++ b/sys/config/LINT64 @@ -1920,41 +1920,6 @@ device mly # USB support # -# NOTE: If you enable 'oldusb' you must also disable 'usb' and rebuild -# the world with WANT_OLDUSB=true in /etc/make.conf, in addition -# to rebuilding the kernel. -# -# Use this instead of usb for the old stack -#device oldusb -#device natausb # ATA-over-USB support (oldusb) -# -# USB Bluetooth (oldusb) -#device ubt -# Generic USB device driver (oldusb) -#device ugen -# USB Rio (MP3 Player) (oldusb) -#device urio -# USB scanners (oldusb) -#device uscanner -# USB com devices (oldusb) -#device moscom -#device uticom -# -# USB CDC ethernet (oldusb) -#Supports the LG P-500 smartphone. -#device lgue -# -# RealTek 8150 based USB ethernet device (oldusb): -# Melco LUA-KTX -# GREEN HOUSE GH-USB100B -# Billionton ThumbLAN USBKR2-100B -#device rue -# -# Ralink Technology RT2500USB (oldusb) -#device ural -# -# USB sound (oldusb) -#device "snd_uaudio" # UHCI controller device uhci diff --git a/sys/config/SOEKRIS b/sys/config/SOEKRIS index 1232e62de8..159124671f 100644 --- a/sys/config/SOEKRIS +++ b/sys/config/SOEKRIS @@ -171,18 +171,6 @@ pseudo-device cryptodev # USB support # -# NOTE: If you enable 'oldusb' you must also disable 'usb' and rebuild -# the world with WANT_OLDUSB=true in /etc/make.conf, in addition -# to rebuilding the kernel. -# -#device oldusb # use this instead of usb for the old stack -#device natausb # ATA-over-USB support (oldusb) -#device ugen # Generic (oldusb) -#device uscanner # Scanners (oldusb) -#device urio # Diamond Rio MP3 Player (oldusb) -device aue # ADMtek USB ethernet -#device rue # RealTek 8150 based USB ethernet (oldusb) - device usb # USB Bus (required) device uhci # UHCI PCI->USB interface device ohci # OHCI PCI->USB interface @@ -191,3 +179,4 @@ device ukbd # Keyboard device ulpt # Printer device umass # Disks/Mass storage - Requires scbus and da device ums # Mouse +device aue # ADMtek USB ethernet diff --git a/sys/config/X86_64_GENERIC b/sys/config/X86_64_GENERIC index effc1363e6..d8c0b15af6 100644 --- a/sys/config/X86_64_GENERIC +++ b/sys/config/X86_64_GENERIC @@ -313,20 +313,6 @@ pseudo-device crypto # core crypto support, used by wlan # USB support # -# NOTE: If you enable 'oldusb' you must also disable 'usb' and rebuild -# the world with WANT_OLDUSB=true in /etc/make.conf, in addition -# to rebuilding the kernel. -# -#device oldusb # use this instead of usb for the old stack -#device natausb # ATA-over-USB support (oldusb) -#device ugen # Generic (oldusb) -#device uscanner # Scanners (oldusb) -#device urio # Diamond Rio MP3 Player (oldusb) -device aue # ADMtek USB ethernet -device cue # CATC USB ethernet -device kue # Kawasaki LSI USB ethernet -#device rue # RealTek 8150 based USB ethernet (oldusb) - device usb # USB Bus (required) device uhci # UHCI PCI->USB interface device ohci # OHCI PCI->USB interface @@ -337,9 +323,11 @@ device umass # Disks/Mass storage - Requires scbus and da device ums # Mouse # USB Ethernet, requires mii device axe # ASIX Electronics USB Ethernet +device aue # ADMtek USB ethernet +device cue # CATC USB ethernet +device kue # Kawasaki LSI USB ethernet # USB wireless NICs, requires wlan, wlan_amrr #device rum # Ralink Technology RT2501USB/RT2601USB -#device ural # Ralink Technology RT2500USB # FireWire support device firewire # FireWire bus code diff --git a/sys/dev/Makefile b/sys/dev/Makefile index 26429d7009..aacba424cb 100644 --- a/sys/dev/Makefile +++ b/sys/dev/Makefile @@ -17,10 +17,6 @@ SUBDIR= \ video \ virtual -.if defined(WANT_OLDUSB) -SUBDIR+=usbmisc -.endif - .for dir in ${SUBDIR} .if empty(DEV_SUPPORT:M${dir}) && empty(DEV_SUPPORT:M${dir}/*) SUBDIR:= ${SUBDIR:N${dir}} diff --git a/sys/dev/disk/nata/Makefile b/sys/dev/disk/nata/Makefile index 656684fade..2ea3886603 100644 --- a/sys/dev/disk/nata/Makefile +++ b/sys/dev/disk/nata/Makefile @@ -1,8 +1,4 @@ SUBDIR= nata natacard natadisk nataisa natapci natapicd natapifd \ natapist natapicam nataraid -.if defined(WANT_OLDUSB) -SUBDIR+= natausb -.endif - .include diff --git a/sys/dev/disk/nata/ata-usb.c b/sys/dev/disk/nata/ata-usb.c deleted file mode 100644 index e645c7c5f3..0000000000 --- a/sys/dev/disk/nata/ata-usb.c +++ /dev/null @@ -1,989 +0,0 @@ -/*- - * Copyright (c) 2006 Søren Schmidt - * 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, - * without modification, immediately at the beginning of the file. - * 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 ``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 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: src/sys/dev/ata/ata-usb.c,v 1.4 2006/03/31 08:09:05 sos Exp $ - */ - -#include "opt_ata.h" - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include "ata-all.h" -#include "ata_if.h" - -/* Command Block Wrapper */ -struct bbb_cbw { - u_int8_t signature[4]; -#define CBWSIGNATURE 0x43425355 - - u_int8_t tag[4]; - u_int8_t transfer_length[4]; - u_int8_t flags; -#define CBWFLAGS_OUT 0x00 -#define CBWFLAGS_IN 0x80 - - u_int8_t lun; - u_int8_t length; -#define CBWCDBLENGTH 16 - - u_int8_t cdb[CBWCDBLENGTH]; -}; - -/* Command Status Wrapper */ -struct bbb_csw { - u_int8_t signature[4]; -#define CSWSIGNATURE 0x53425355 - - u_int8_t tag[4]; - u_int8_t residue[4]; - u_int8_t status; -#define CSWSTATUS_GOOD 0x0 -#define CSWSTATUS_FAILED 0x1 -#define CSWSTATUS_PHASE 0x2 -}; - -/* USB-ATA 'controller' softc */ -struct atausb_softc { - device_t dev; /* base device */ - usbd_interface_handle iface; /* interface */ - int ifaceno; /* interface number */ - u_int8_t bulkin; /* endpoint address's */ - u_int8_t bulkout; - u_int8_t bulkirq; - usbd_pipe_handle bulkin_pipe; /* pipe handle's */ - usbd_pipe_handle bulkout_pipe; - usbd_pipe_handle bulkirq_pipe; - int maxlun; - int timeout; - struct ata_request *ata_request; - usb_device_request_t usb_request; - struct bbb_cbw cbw; - struct bbb_csw csw; - -#define ATAUSB_T_BBB_CBW 0 -#define ATAUSB_T_BBB_DATA 1 -#define ATAUSB_T_BBB_DCLEAR 2 -#define ATAUSB_T_BBB_CSW1 3 -#define ATAUSB_T_BBB_CSW2 4 -#define ATAUSB_T_BBB_SCLEAR 5 -#define ATAUSB_T_BBB_RESET1 6 -#define ATAUSB_T_BBB_RESET2 7 -#define ATAUSB_T_BBB_RESET3 8 -#define ATAUSB_T_MAX 9 - usbd_xfer_handle transfer[ATAUSB_T_MAX]; - - int state; -#define ATAUSB_S_ATTACH 0 -#define ATAUSB_S_IDLE 1 -#define ATAUSB_S_BBB_COMMAND 2 -#define ATAUSB_S_BBB_DATA 3 -#define ATAUSB_S_BBB_DCLEAR 4 -#define ATAUSB_S_BBB_STATUS1 5 -#define ATAUSB_S_BBB_SCLEAR 6 -#define ATAUSB_S_BBB_STATUS2 7 -#define ATAUSB_S_BBB_RESET1 8 -#define ATAUSB_S_BBB_RESET2 9 -#define ATAUSB_S_BBB_RESET3 10 -#define ATAUSB_S_DETACH 11 - - struct spinlock locked_mtx; - struct ata_channel *locked_ch; - struct ata_channel *restart_ch; -}; - -static int atausbdebug = 0; - -/* prototypes*/ -static usbd_status atausb_start(struct atausb_softc *sc, usbd_pipe_handle pipe, void *buffer, int buflen, int flags, usbd_xfer_handle xfer); -static usbd_status atausb_ctl_start(struct atausb_softc *sc, usbd_device_handle udev, usb_device_request_t *req, void *buffer, int buflen, int flags, usbd_xfer_handle xfer); -static void atausb_clear_stall(struct atausb_softc *sc, u_int8_t endpt, usbd_pipe_handle pipe, int state, usbd_xfer_handle xfer); -static void atausb_bbb_reset(struct atausb_softc *sc); -static int atausb_bbb_start(struct ata_request *request); -static void atausb_bbb_finish(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status err); -int ata_usbchannel_begin_transaction(struct ata_request *request); -int ata_usbchannel_end_transaction(struct ata_request *request); - - -/* - * USB frontend part - */ -static device_probe_t atausb_match; -static device_attach_t atausb_attach; -static device_detach_t atausb_detach; - -static devclass_t atausb_devclass; - -static kobj_method_t atausb_methods[] = { - DEVMETHOD(device_probe, atausb_match), - DEVMETHOD(device_attach, atausb_attach), - DEVMETHOD(device_detach, atausb_detach), - DEVMETHOD_END -}; - -static driver_t atausb_driver = { - "atausb", - atausb_methods, - sizeof(struct atausb_softc) -}; - -MODULE_DEPEND(atausb, usb, 1, 1, 1); -DRIVER_MODULE(atausb, uhub, atausb_driver, atausb_devclass, NULL, NULL); -MODULE_VERSION(atausb, 1); - -static int -atausb_match(device_t dev) -{ - struct usb_attach_arg *uaa = device_get_ivars(dev); - usb_interface_descriptor_t *id; - - if (uaa->iface == NULL) - return UMATCH_NONE; - - id = usbd_get_interface_descriptor(uaa->iface); - if (!id || id->bInterfaceClass != UICLASS_MASS) - return UMATCH_NONE; - - switch (id->bInterfaceSubClass) { - case UISUBCLASS_QIC157: - case UISUBCLASS_RBC: - case UISUBCLASS_SCSI: - case UISUBCLASS_SFF8020I: - case UISUBCLASS_SFF8070I: - case UISUBCLASS_UFI: - switch (id->bInterfaceProtocol) { - case UIPROTO_MASS_CBI: - case UIPROTO_MASS_CBI_I: - case UIPROTO_MASS_BBB: - case UIPROTO_MASS_BBB_OLD: - return UMATCH_IFACECLASS_IFACESUBCLASS_IFACEPROTO; - default: - return UMATCH_IFACECLASS_IFACESUBCLASS; - } - break; - default: - return UMATCH_IFACECLASS; - } -} - -static int -atausb_attach(device_t dev) -{ - struct atausb_softc *sc = device_get_softc(dev); - struct usb_attach_arg *uaa = device_get_ivars(dev); - usb_interface_descriptor_t *id; - usb_endpoint_descriptor_t *ed; - usbd_device_handle udev; - usb_device_request_t request; - char devinfo[1024], *proto, *subclass; - u_int8_t maxlun; - int err, i; - - sc->dev = dev; - usbd_devinfo(uaa->device, 0, devinfo); - device_set_desc_copy(dev, devinfo); - sc->bulkin = sc->bulkout = sc->bulkirq = -1; - sc->bulkin_pipe = sc->bulkout_pipe= sc->bulkirq_pipe = NULL; - sc->iface = uaa->iface; - sc->ifaceno = uaa->ifaceno; - sc->maxlun = 0; - sc->timeout = 5000; - sc->locked_ch = NULL; - sc->restart_ch = NULL; - spin_init(&sc->locked_mtx, "atausbattach"); - - id = usbd_get_interface_descriptor(sc->iface); - switch (id->bInterfaceProtocol) { - case UIPROTO_MASS_BBB: - case UIPROTO_MASS_BBB_OLD: - proto = "Bulk-Only"; - break; - case UIPROTO_MASS_CBI: - proto = "CBI"; - break; - case UIPROTO_MASS_CBI_I: - proto = "CBI with CCI"; - break; - default: - proto = "Unknown"; - } - switch (id->bInterfaceSubClass) { - case UISUBCLASS_RBC: - subclass = "RBC"; - break; - case UISUBCLASS_QIC157: - case UISUBCLASS_SFF8020I: - case UISUBCLASS_SFF8070I: - subclass = "ATAPI"; - break; - case UISUBCLASS_SCSI: - subclass = "SCSI"; - break; - case UISUBCLASS_UFI: - subclass = "UFI"; - break; - default: - subclass = "Unknown"; - } - device_printf(dev, "using %s over %s\n", subclass, proto); - if (strcmp(proto, "Bulk-Only") || - (strcmp(subclass, "ATAPI") && strcmp(subclass, "SCSI"))) - return ENXIO; - - for (i = 0 ; i < id->bNumEndpoints ; i++) { - if (!(ed = usbd_interface2endpoint_descriptor(sc->iface, i))) { - device_printf(sc->dev, "could not read endpoint descriptor\n"); - return ENXIO; - } - if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && - (ed->bmAttributes & UE_XFERTYPE) == UE_BULK) { - sc->bulkin = ed->bEndpointAddress; - } - if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT && - (ed->bmAttributes & UE_XFERTYPE) == UE_BULK) { - sc->bulkout = ed->bEndpointAddress; - } - if (id->bInterfaceProtocol == UIPROTO_MASS_CBI_I && - UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && - (ed->bmAttributes & UE_XFERTYPE) == UE_INTERRUPT) { - sc->bulkirq = ed->bEndpointAddress; - } - } - - /* check whether we found at least the endpoints we need */ - if (!sc->bulkin || !sc->bulkout) { - device_printf(sc->dev, "needed endpoints not found (%d,%d)\n", - sc->bulkin, sc->bulkout); - atausb_detach(dev); - return ENXIO; - } - - /* open the pipes */ - if (usbd_open_pipe(sc->iface, sc->bulkout, - USBD_EXCLUSIVE_USE, &sc->bulkout_pipe)) { - device_printf(sc->dev, "cannot open bulkout pipe (%d)\n", sc->bulkout); - atausb_detach(dev); - return ENXIO; - } - if (usbd_open_pipe(sc->iface, sc->bulkin, - USBD_EXCLUSIVE_USE, &sc->bulkin_pipe)) { - device_printf(sc->dev, "cannot open bulkin pipe (%d)\n", sc->bulkin); - atausb_detach(dev); - return ENXIO; - } - if (id->bInterfaceProtocol == UIPROTO_MASS_CBI_I) { - if (usbd_open_pipe(sc->iface, sc->bulkirq, - USBD_EXCLUSIVE_USE, &sc->bulkirq_pipe)) { - device_printf(sc->dev, "cannot open bulkirq pipe (%d)\n", - sc->bulkirq); - atausb_detach(dev); - return ENXIO; - } - } - sc->state = ATAUSB_S_ATTACH; - - /* alloc needed number of transfer handles */ - for (i = 0; i < ATAUSB_T_MAX; i++) { - sc->transfer[i] = usbd_alloc_xfer(uaa->device); - if (!sc->transfer[i]) { - device_printf(sc->dev, "out of memory\n"); - atausb_detach(dev); - return ENXIO; - } - } - - /* driver is ready to process requests here */ - sc->state = ATAUSB_S_IDLE; - - /* get number of devices so we can add matching channels */ - usbd_interface2device_handle(sc->iface, &udev); - request.bmRequestType = UT_READ_CLASS_INTERFACE; - request.bRequest = 0xfe; /* GET_MAX_LUN; */ - USETW(request.wValue, 0); - USETW(request.wIndex, sc->ifaceno); - USETW(request.wLength, sizeof(maxlun)); - switch ((err = usbd_do_request(udev, &request, &maxlun))) { - case USBD_NORMAL_COMPLETION: - if (bootverbose) - device_printf(sc->dev, "maxlun=%d\n", maxlun); - sc->maxlun = maxlun; - break; - default: - if (bootverbose) - device_printf(sc->dev, "get maxlun not supported %s\n", - usbd_errstr(err)); - } - - /* ata channels are children to this USB control device */ - for (i = 0; i <= sc->maxlun; i++) { - /* XXX TGEN devclass_find_free_unit() implementation */ - int freeunit = 2; - while (freeunit < devclass_get_maxunit(ata_devclass) && - devclass_get_device(ata_devclass, freeunit) != NULL) - freeunit++; - if (!device_add_child(sc->dev, "ata", freeunit)) { - device_printf(sc->dev, "failed to attach ata child device\n"); - atausb_detach(dev); - return ENXIO; - } - } - bus_generic_attach(sc->dev); - return 0; -} - -static int -atausb_detach(device_t dev) -{ - struct atausb_softc *sc = device_get_softc(dev); - usbd_device_handle udev; - device_t *children; - int nchildren, i; - - /* signal that device is going away */ - sc->state = ATAUSB_S_DETACH; - - /* abort all the pipes in case there are active transfers */ - usbd_interface2device_handle(sc->iface, &udev); - usbd_abort_pipe(udev->default_pipe); - if (sc->bulkout_pipe) - usbd_abort_pipe(sc->bulkout_pipe); - if (sc->bulkin_pipe) - usbd_abort_pipe(sc->bulkin_pipe); - if (sc->bulkirq_pipe) - usbd_abort_pipe(sc->bulkirq_pipe); - - /* detach & delete all children */ - if (!device_get_children(dev, &children, &nchildren)) { - for (i = 0; i < nchildren; i++) - device_delete_child(dev, children[i]); - kfree(children, M_TEMP); - } - - /* free the transfers */ - for (i = 0; i < ATAUSB_T_MAX; i++) - if (sc->transfer[i]) - usbd_free_xfer(sc->transfer[i]); - - /* remove all the pipes */ - if (sc->bulkout_pipe) - usbd_close_pipe(sc->bulkout_pipe); - if (sc->bulkin_pipe) - usbd_close_pipe(sc->bulkin_pipe); - if (sc->bulkirq_pipe) - usbd_close_pipe(sc->bulkirq_pipe); - - spin_uninit(&sc->locked_mtx); - return 0; -} - - -/* - * Generic USB transfer routines - */ -static usbd_status -atausb_start(struct atausb_softc *sc, usbd_pipe_handle pipe, - void *buffer, int buflen, int flags, usbd_xfer_handle xfer) -{ - usbd_status err; - - if (sc->state == ATAUSB_S_DETACH) - return USBD_NOT_STARTED; - - usbd_setup_xfer(xfer, pipe, (void *)sc, buffer, buflen, flags, - sc->timeout, atausb_bbb_finish); - err = usbd_transfer(xfer); - if (err && (err != USBD_IN_PROGRESS)) { - if (atausbdebug) - device_printf(sc->dev, "failed to setup transfer, %s\n", - usbd_errstr(err)); - return err; - } - return USBD_NORMAL_COMPLETION; -} - -static usbd_status -atausb_ctl_start(struct atausb_softc *sc, usbd_device_handle udev, - usb_device_request_t *req, void *buffer, int buflen, int flags, - usbd_xfer_handle xfer) -{ - usbd_status err; - - if (sc->state == ATAUSB_S_DETACH) - return USBD_NOT_STARTED; - - usbd_setup_default_xfer(xfer, udev, (void *)sc, sc->timeout, req, - buffer, buflen, flags, atausb_bbb_finish); - err = usbd_transfer(xfer); - if (err && (err != USBD_IN_PROGRESS)) { - if (atausbdebug) - device_printf(sc->dev, "failed to setup ctl transfer, %s\n", - usbd_errstr(err)); - return err; - } - return USBD_NORMAL_COMPLETION; -} - -static void -atausb_clear_stall(struct atausb_softc *sc, u_int8_t endpt, - usbd_pipe_handle pipe, int state, usbd_xfer_handle xfer) -{ - usbd_device_handle udev; - - if (atausbdebug) - device_printf(sc->dev, "clear endpoint 0x%02x stall\n", endpt); - usbd_interface2device_handle(sc->iface, &udev); - sc->state = state; - usbd_clear_endpoint_toggle(pipe); - sc->usb_request.bmRequestType = UT_WRITE_ENDPOINT; - sc->usb_request.bRequest = UR_CLEAR_FEATURE; - USETW(sc->usb_request.wValue, UF_ENDPOINT_HALT); - USETW(sc->usb_request.wIndex, endpt); - USETW(sc->usb_request.wLength, 0); - atausb_ctl_start(sc, udev, &sc->usb_request, NULL, 0, 0, xfer); -} - - -/* - * Bulk-Only transport part - */ -static void -atausb_bbb_reset(struct atausb_softc *sc) -{ - usbd_device_handle udev; - - if (atausbdebug) - device_printf(sc->dev, "Bulk Reset\n"); - sc->timeout = 5000; - sc->state = ATAUSB_S_BBB_RESET1; - usbd_interface2device_handle(sc->iface, &udev); - sc->usb_request.bmRequestType = UT_WRITE_CLASS_INTERFACE; - sc->usb_request.bRequest = 0xff; /* bulk-only reset */ - USETW(sc->usb_request.wValue, 0); - USETW(sc->usb_request.wIndex, sc->ifaceno); - USETW(sc->usb_request.wLength, 0); - atausb_ctl_start(sc, udev, &sc->usb_request, NULL, - 0, 0, sc->transfer[ATAUSB_T_BBB_RESET1]); -} - -static int -atausb_bbb_start(struct ata_request *request) -{ - struct atausb_softc *sc = - device_get_softc(device_get_parent(request->parent)); - struct ata_channel *ch = device_get_softc(request->parent); - - sc->timeout = (request->timeout * 1000) + 5000; - USETDW(sc->cbw.signature, CBWSIGNATURE); - USETDW(sc->cbw.tag, UGETDW(sc->cbw.tag) + 1); - USETDW(sc->cbw.transfer_length, request->bytecount); - sc->cbw.flags = (request->flags & ATA_R_READ) ? CBWFLAGS_IN : CBWFLAGS_OUT; - sc->cbw.lun = ch->unit; - sc->cbw.length = 16; - bzero(sc->cbw.cdb, 16); - bcopy(request->u.atapi.ccb, sc->cbw.cdb, 12); /* XXX SOS */ - sc->state = ATAUSB_S_BBB_COMMAND; - if (atausb_start(sc, sc->bulkout_pipe, &sc->cbw, sizeof(struct bbb_cbw), - 0, sc->transfer[ATAUSB_T_BBB_CBW])) { - request->result = EIO; - if (atausbdebug) - device_printf(request->dev, "cannot setup USB transfer\n"); - atausb_bbb_reset(sc); - return ATA_OP_FINISHED; - } - return ATA_OP_CONTINUES; -} - -static void -atausb_bbb_finish(usbd_xfer_handle xfer, usbd_private_handle priv, - usbd_status err) -{ - struct atausb_softc *sc = (struct atausb_softc *)priv; - struct ata_request *request = sc->ata_request; - usbd_xfer_handle next_xfer; - - /* device_printf(sc->dev, "BBB state %d: %s\n", sc->state, - usbd_errstr(err)); */ - - if (sc->state == ATAUSB_S_DETACH) { - device_printf(sc->dev, "WARNING - device has been removed\n"); - return; - } - - switch (sc->state) { - case ATAUSB_S_BBB_COMMAND: /* command transport phase */ - if (err) { - if (atausbdebug) - device_printf(sc->dev, "failed to send CBW\n"); - request->result = EIO; - atausb_bbb_reset(sc); - return; - } - - /* next is data transport phase, setup transfer */ - sc->state = ATAUSB_S_BBB_DATA; - if (request->flags & ATA_R_READ) { - if (atausb_start(sc, sc->bulkin_pipe, - request->data, request->bytecount, - USBD_SHORT_XFER_OK, - sc->transfer[ATAUSB_T_BBB_DATA])) { - request->result = EIO; - atausb_bbb_reset(sc); - } - return; - } - if (request->flags & ATA_R_WRITE) { - if (atausb_start(sc, sc->bulkout_pipe, - request->data, request->bytecount, - 0, sc->transfer[ATAUSB_T_BBB_DATA])) { - request->result = EIO; - atausb_bbb_reset(sc); - } - return; - } - /* FALLTHROUGH */ - - case ATAUSB_S_BBB_DATA: /* data transport phase */ - if (request->flags & (ATA_R_READ | ATA_R_WRITE)) { - usbd_get_xfer_status(xfer, NULL, NULL, &request->donecount, NULL); - if (err) { - if (atausbdebug) - device_printf(sc->dev, "data %s count %d failed: %s\n", - (request->flags & ATA_R_READ?"read":"write"), - request->bytecount, usbd_errstr(err)); - if (err == USBD_STALLED) { - atausb_clear_stall(sc, - (request->flags & ATA_R_READ ? - sc->bulkin : sc->bulkout), - (request->flags & ATA_R_READ ? - sc->bulkin_pipe : sc->bulkout_pipe), - ATAUSB_S_BBB_DCLEAR, - sc->transfer[ATAUSB_T_BBB_DCLEAR]); - } - else { - request->result = EIO; - atausb_bbb_reset(sc); - } - return; - } - } - /* FALLTHROUGH */ - - case ATAUSB_S_BBB_DCLEAR: /* stall clear after data phase */ - case ATAUSB_S_BBB_SCLEAR: /* stall clear after status phase */ - if (err) { - if (atausbdebug) - device_printf(sc->dev, "bulk%s stall clear failed %s\n", - (request->flags & ATA_R_READ ? "in" : "out"), - usbd_errstr(err)); - request->result = EIO; - atausb_bbb_reset(sc); - return; - } - - if (sc->state == ATAUSB_S_BBB_COMMAND || - sc->state == ATAUSB_S_BBB_DATA || - sc->state == ATAUSB_S_BBB_DCLEAR) { - /* first attempt on status transport phase setup transfer */ - sc->state = ATAUSB_S_BBB_STATUS1; - next_xfer = sc->transfer[ATAUSB_T_BBB_CSW1]; - } - else { - /* second attempt of fetching status */ - sc->state = ATAUSB_S_BBB_STATUS2; - next_xfer = sc->transfer[ATAUSB_T_BBB_CSW2]; - } - if (atausb_start(sc, sc->bulkin_pipe, &sc->csw, sizeof(struct bbb_csw), - USBD_SHORT_XFER_OK, next_xfer)) { - request->result = EIO; - atausb_bbb_reset(sc); - } - return; - - case ATAUSB_S_BBB_STATUS1: /* status transfer first attempt */ - case ATAUSB_S_BBB_STATUS2: /* status transfer second attempt */ - if (err) { - if (atausbdebug) - device_printf(sc->dev, "cannot get CSW, %s%s\n", - usbd_errstr(err), - sc->state == ATAUSB_S_BBB_STATUS1 ? ", retry":""); - if (sc->state == ATAUSB_S_BBB_STATUS1) { - atausb_clear_stall(sc, sc->bulkin, sc->bulkin_pipe, - ATAUSB_S_BBB_SCLEAR, - sc->transfer[ATAUSB_T_BBB_SCLEAR]); - } - else { - request->result = EIO; - atausb_bbb_reset(sc); - } - return; - } - - int residue = UGETDW(sc->csw.residue); - - if (!residue && - (request->bytecount - request->donecount)) - residue = request->bytecount - request->donecount; - - /* check CSW and handle eventual error */ - if (UGETDW(sc->csw.signature) != CSWSIGNATURE) { - if (atausbdebug) - device_printf(sc->dev, "bad CSW signature 0x%08x != 0x%08x\n", - UGETDW(sc->csw.signature), CSWSIGNATURE); - request->result = EIO; - atausb_bbb_reset(sc); - return; - } - else if (UGETDW(sc->csw.tag) != UGETDW(sc->cbw.tag)) { - if (atausbdebug) - device_printf(sc->dev, "bad CSW tag %d != %d\n", - UGETDW(sc->csw.tag), UGETDW(sc->cbw.tag)); - request->result = EIO; - atausb_bbb_reset(sc); - return; - } - else if (sc->csw.status > CSWSTATUS_PHASE) { - if (atausbdebug) - device_printf(sc->dev, "bad CSW status %d > %d\n", - sc->csw.status, CSWSTATUS_PHASE); - request->result = EIO; - atausb_bbb_reset(sc); - return; - } - else if (sc->csw.status == CSWSTATUS_PHASE) { - if (atausbdebug) - device_printf(sc->dev, "phase error residue = %d\n", residue); - request->result = EIO; - atausb_bbb_reset(sc); - return; - } - else if (request->donecount > request->bytecount) { - if (atausbdebug) - device_printf(sc->dev, "buffer overrun %d > %d", - request->donecount, request->bytecount); - request->result = EIO; - atausb_bbb_reset(sc); - return; - } - else if (sc->csw.status == CSWSTATUS_FAILED) { - if (atausbdebug) - device_printf(sc->dev, "CSWSTATUS_FAILED\n"); - request->error = ATA_E_ATAPI_SENSE_MASK ; - sc->state = ATAUSB_S_IDLE; - ata_interrupt(device_get_softc(request->parent)); - return; - } - else { - sc->state = ATAUSB_S_IDLE; - ata_interrupt(device_get_softc(request->parent)); - return; - } - /* NOT REACHED */ - - case ATAUSB_S_BBB_RESET1: - if (err) - if (atausbdebug) - device_printf(sc->dev, - "BBB reset failure: %s\n", usbd_errstr(err)); - atausb_clear_stall(sc, sc->bulkin, sc->bulkin_pipe, - ATAUSB_S_BBB_RESET2, - sc->transfer[ATAUSB_T_BBB_RESET2]); - return; - - case ATAUSB_S_BBB_RESET2: - if (err) - if (atausbdebug) - device_printf(sc->dev, "BBB bulkin clear stall failure: %s\n", - usbd_errstr(err)); - atausb_clear_stall(sc, sc->bulkout, sc->bulkout_pipe, - ATAUSB_S_BBB_RESET3, - sc->transfer[ATAUSB_T_BBB_RESET3]); - return; - - case ATAUSB_S_BBB_RESET3: - if (err) - if (atausbdebug) - device_printf(sc->dev, "BBB bulk-out clear stall failure: %s\n", - usbd_errstr(err)); - sc->state = ATAUSB_S_IDLE; - if (request) { - if (err) - request->result = ENXIO; - else - request->result = EIO; - ata_interrupt(device_get_softc(request->parent)); - } - return; - - default: - if (atausbdebug) - device_printf(sc->dev, "unknown state %d", sc->state); - } -} - - -/* - * ATA backend part - */ -struct atapi_inquiry { - u_int8_t device_type; - u_int8_t device_modifier; - u_int8_t version; - u_int8_t response_format; - u_int8_t length; - u_int8_t reserved[2]; - u_int8_t flags; - u_int8_t vendor[8]; - u_int8_t product[16]; - u_int8_t revision[4]; - /* u_int8_t crap[60]; */ -}; - -int -ata_usbchannel_begin_transaction(struct ata_request *request) -{ - struct atausb_softc *sc = - device_get_softc(device_get_parent(request->parent)); - - if (atausbdebug > 1) - device_printf(request->dev, "begin_transaction %s\n", - ata_cmd2str(request)); - - /* sanity just in case */ - if (sc->state != ATAUSB_S_IDLE) { - kprintf("begin is busy (%d)\n", sc->state); - request->result = EBUSY; - return ATA_OP_FINISHED; - } - - /* XXX SOS convert the request into the format used, only BBB for now*/ - sc->ata_request = request; - - /* ATA/ATAPI IDENTIFY needs special treatment */ - if (!(request->flags & ATA_R_ATAPI)) { - if (request->u.ata.command != ATA_ATAPI_IDENTIFY) { - device_printf(request->dev,"%s unsupported\n",ata_cmd2str(request)); - request->result = EIO; - return ATA_OP_FINISHED; - } - request->flags |= ATA_R_ATAPI; - bzero(request->u.atapi.ccb, 16); - request->u.atapi.ccb[0] = ATAPI_INQUIRY; - request->u.atapi.ccb[4] = 255; /* sizeof(struct atapi_inquiry); */ - request->data += 256; /* arbitrary offset into ata_param */ - request->bytecount = 255; /* sizeof(struct atapi_inquiry); */ - } - return atausb_bbb_start(request); -} - -int -ata_usbchannel_end_transaction(struct ata_request *request) -{ - if (atausbdebug > 1) - device_printf(request->dev, "end_transaction %s\n", - ata_cmd2str(request)); - - /* XXX SOS convert the request from the format used, only BBB for now*/ - - /* ATA/ATAPI IDENTIFY needs special treatment */ - if ((request->flags & ATA_R_ATAPI) && - (request->u.atapi.ccb[0] == ATAPI_INQUIRY)) { - struct ata_device *atadev = device_get_softc(request->dev); - struct atapi_inquiry *inquiry = (struct atapi_inquiry *)request->data; - u_int16_t *ptr; - - /* convert inquiry data into simple ata_param like format */ - atadev->param.config = ATA_PROTO_ATAPI | ATA_PROTO_ATAPI_12; - atadev->param.config |= (inquiry->device_type & 0x1f) << 8; - bzero(atadev->param.model, sizeof(atadev->param.model)); - strncpy(atadev->param.model, inquiry->vendor, 8); - strcpy(atadev->param.model, " "); - strncpy(atadev->param.model, inquiry->product, 16); - ptr = (u_int16_t*)(atadev->param.model + sizeof(atadev->param.model)); - while (--ptr >= (u_int16_t*)atadev->param.model) - *ptr = ntohs(*ptr); - strncpy(atadev->param.revision, inquiry->revision, 4); - ptr=(u_int16_t*)(atadev->param.revision+sizeof(atadev->param.revision)); - while (--ptr >= (u_int16_t*)atadev->param.revision) - *ptr = ntohs(*ptr); - request->result = 0; - } - return ATA_OP_FINISHED; -} - -static int -ata_usbchannel_probe(device_t dev) -{ - struct ata_channel *ch = device_get_softc(dev); - device_t *children; - int count, i; - char buffer[32]; - - /* take care of green memory */ - bzero(ch, sizeof(struct ata_channel)); - - /* find channel number on this controller */ - device_get_children(device_get_parent(dev), &children, &count); - for (i = 0; i < count; i++) { - if (children[i] == dev) - ch->unit = i; - } - kfree(children, M_TEMP); - - ksprintf(buffer, "USB lun %d", ch->unit); - device_set_desc_copy(dev, buffer); - - return 0; -} - -static int -ata_usbchannel_attach(device_t dev) -{ - struct ata_channel *ch = device_get_softc(dev); - - /* initialize the softc basics */ - ch->dev = dev; - ch->state = ATA_IDLE; - ch->hw.begin_transaction = ata_usbchannel_begin_transaction; - ch->hw.end_transaction = ata_usbchannel_end_transaction; - ch->hw.status = NULL; - ch->hw.command = NULL; - spin_init(&ch->state_mtx, "usbattach_state"); - spin_init(&ch->queue_mtx, "usbattach_queue"); - ata_queue_init(ch); - - /* XXX SOS reset the controller HW, the channel and device(s) */ - /* ATA_RESET(dev); */ - - /* probe and attach device on this channel */ - ch->devices = ATA_ATAPI_MASTER; - ata_identify(dev); - return 0; -} - -static int -ata_usbchannel_detach(device_t dev) -{ - struct ata_channel *ch = device_get_softc(dev); - device_t *children; - int nchildren, i; - - /* detach & delete all children */ - if (!device_get_children(dev, &children, &nchildren)) { - for (i = 0; i < nchildren; i++) - if (children[i]) - device_delete_child(dev, children[i]); - kfree(children, M_TEMP); - } - spin_uninit(&ch->state_mtx); - spin_uninit(&ch->queue_mtx); - return 0; -} - -static void -ata_usbchannel_setmode(device_t parent, device_t dev) -{ - struct atausb_softc *sc = device_get_softc(GRANDPARENT(dev)); - struct ata_device *atadev = device_get_softc(dev); - usbd_device_handle udev; - - usbd_interface2device_handle(sc->iface, &udev); - if (usbd_get_speed(udev) == USB_SPEED_HIGH) - atadev->mode = ATA_USB2; - else - atadev->mode = ATA_USB1; -} - -static int -ata_usbchannel_locking(device_t dev, int flags) -{ - struct atausb_softc *sc = device_get_softc(device_get_parent(dev)); - struct ata_channel *ch = device_get_softc(dev); - int res = -1; - - - spin_lock(&sc->locked_mtx); - switch (flags) { - case ATA_LF_LOCK: - if (sc->locked_ch == NULL) - sc->locked_ch = ch; - if (sc->locked_ch != ch) - sc->restart_ch = ch; - break; - - case ATA_LF_UNLOCK: - if (sc->locked_ch == ch) { - sc->locked_ch = NULL; - if (sc->restart_ch) { - ch = sc->restart_ch; - sc->restart_ch = NULL; - spin_unlock(&sc->locked_mtx); - ata_start(ch->dev); - return res; - } - } - break; - - case ATA_LF_WHICH: - break; - } - if (sc->locked_ch) - res = sc->locked_ch->unit; - spin_unlock(&sc->locked_mtx); - return res; -} - -static device_method_t ata_usbchannel_methods[] = { - /* device interface */ - DEVMETHOD(device_probe, ata_usbchannel_probe), - DEVMETHOD(device_attach, ata_usbchannel_attach), - DEVMETHOD(device_detach, ata_usbchannel_detach), - - /* ATA methods */ - DEVMETHOD(ata_setmode, ata_usbchannel_setmode), - DEVMETHOD(ata_locking, ata_usbchannel_locking), - /* DEVMETHOD(ata_reset, ata_usbchannel_reset), */ - - DEVMETHOD_END -}; - -static driver_t ata_usbchannel_driver = { - "ata", - ata_usbchannel_methods, - sizeof(struct ata_channel), -}; - -DRIVER_MODULE(ata, atausb, ata_usbchannel_driver, ata_devclass, NULL, NULL); -MODULE_DEPEND(atausb, ata, 1, 1, 1); diff --git a/sys/dev/disk/nata/natausb/Makefile b/sys/dev/disk/nata/natausb/Makefile deleted file mode 100644 index 511daa74cf..0000000000 --- a/sys/dev/disk/nata/natausb/Makefile +++ /dev/null @@ -1,9 +0,0 @@ -# $DragonFly: src/sys/dev/disk/nata/natausb/Makefile,v 1.3 2006/12/10 23:39:43 tgen Exp $ - -.PATH: ${.CURDIR}/../../../../dev/disk/nata - -KMOD= natausb -SRCS= ata-usb.c -SRCS+= opt_ata.h opt_usb.h ata_if.h device_if.h bus_if.h pci_if.h - -.include diff --git a/sys/dev/netif/Makefile b/sys/dev/netif/Makefile index 3ebf82b4f7..d3ca2a7b86 100644 --- a/sys/dev/netif/Makefile +++ b/sys/dev/netif/Makefile @@ -13,8 +13,4 @@ SUBDIR+=ar ed sbni sr # SUBDIR+= acx bwi iwl rtw # .endif -.if defined(WANT_OLDUSB) -SUBDIR+=aue axe cue kue lgue rue -.endif - .include diff --git a/sys/dev/netif/aue/Makefile b/sys/dev/netif/aue/Makefile deleted file mode 100644 index 091ae814cf..0000000000 --- a/sys/dev/netif/aue/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -# $FreeBSD: src/sys/modules/aue/Makefile,v 1.2 2000/01/28 11:26:27 bde Exp $ -# $DragonFly: src/sys/dev/netif/aue/Makefile,v 1.4 2006/06/25 11:02:38 corecode Exp $ - -KMOD = if_aue -SRCS = if_aue.c opt_usb.h device_if.h bus_if.h -SRCS += miibus_if.h - -.include diff --git a/sys/dev/netif/aue/if_aue.c b/sys/dev/netif/aue/if_aue.c deleted file mode 100644 index 7abe2f1642..0000000000 --- a/sys/dev/netif/aue/if_aue.c +++ /dev/null @@ -1,1482 +0,0 @@ -/*- - * Copyright (c) 1997, 1998, 1999, 2000 - * Bill Paul . 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. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Bill Paul. - * 4. Neither the name of the author nor the names of any co-contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY Bill Paul 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 Bill Paul OR THE VOICES IN HIS HEAD - * 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: src/sys/dev/usb/if_aue.c,v 1.78 2003/12/17 14:23:07 sanpei Exp $ - */ - -/* - * ADMtek AN986 Pegasus and AN8511 Pegasus II USB to ethernet driver. - * Datasheet is available from http://www.admtek.com.tw. - * - * Written by Bill Paul - * Electrical Engineering Department - * Columbia University, New York City - */ - -/* - * The Pegasus chip uses four USB "endpoints" to provide 10/100 ethernet - * support: the control endpoint for reading/writing registers, burst - * read endpoint for packet reception, burst write for packet transmission - * and one for "interrupts." The chip uses the same RX filter scheme - * as the other ADMtek ethernet parts: one perfect filter entry for the - * the station address and a 64-bit multicast hash table. The chip supports - * both MII and HomePNA attachments. - * - * Since the maximum data transfer speed of USB is supposed to be 12Mbps, - * you're never really going to get 100Mbps speeds from this device. I - * think the idea is to allow the device to connect to 10 or 100Mbps - * networks, not necessarily to provide 100Mbps performance. Also, since - * the controller uses an external PHY chip, it's possible that board - * designers might simply choose a 10Mbps PHY. - * - * Registers are accessed using usbd_do_request(). Packet transfers are - * done using usbd_transfer() and friends. - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include "../mii_layer/mii.h" -#include "../mii_layer/miivar.h" - -#include "if_auereg.h" - -MODULE_DEPEND(aue, usb, 1, 1, 1); -MODULE_DEPEND(aue, miibus, 1, 1, 1); - -/* "controller miibus0" required. See GENERIC if you get errors here. */ -#include "miibus_if.h" - -struct aue_type { - struct usb_devno aue_dev; - u_int16_t aue_flags; -#define LSYS 0x0001 /* use Linksys reset */ -#define PNA 0x0002 /* has Home PNA */ -#define PII 0x0004 /* Pegasus II chip */ -}; - -static const struct aue_type aue_devs[] = { - {{ USB_DEVICE(0x03f0, 0x811c) }, PII }, /* HP HN210E */ - {{ USB_DEVICE(0x0411, 0x0001) }, 0 }, /* Melco LUA-TX */ - {{ USB_DEVICE(0x0411, 0x0005) }, 0 }, /* Melco LUA-TX */ - {{ USB_DEVICE(0x0411, 0x0009) }, PII }, /* Melco LUA2-TX */ - {{ USB_DEVICE(0x045e, 0x007a) }, PII }, /* Microsoft MN110 */ - {{ USB_DEVICE(0x04bb, 0x0904) }, 0 }, /* I-O DATA USB ETTX */ - {{ USB_DEVICE(0x04bb, 0x0913) }, PII }, /* I-O DATA USB ETTX */ - {{ USB_DEVICE(0x0506, 0x4601) }, PII }, /* 3com HomeConnect 3C460B */ - {{ USB_DEVICE(0x050d, 0x0121) }, PII }, /* Belkin USB to LAN Converter */ - {{ USB_DEVICE(0x056e, 0x200c) }, 0 }, /* Elecom LD-USB/TX */ - {{ USB_DEVICE(0x056e, 0x4002) }, LSYS }, /* Elecom LD-USB/TX */ - {{ USB_DEVICE(0x056e, 0x4005) }, PII }, /* Elecom LD-USBL/TX */ - {{ USB_DEVICE(0x056e, 0x400b) }, 0 }, /* Elecom LD-USB/TX */ - {{ USB_DEVICE(0x056e, 0xabc1) }, LSYS }, /* Elecom LD-USB/TX */ - {{ USB_DEVICE(0x05cc, 0x3000) }, 0 }, /* Elsa Microlink USB2Ethernet */ - {{ USB_DEVICE(0x066b, 0x200c) }, LSYS|PII }, /* Linksys USB10TX */ - {{ USB_DEVICE(0x066b, 0x2202) }, LSYS }, /* Linksys USB10T */ - {{ USB_DEVICE(0x066b, 0x2203) }, LSYS }, /* Linksys USB100TX */ - {{ USB_DEVICE(0x066b, 0x2204) }, LSYS|PNA }, /* Linksys USB100H1 */ - {{ USB_DEVICE(0x066b, 0x2206) }, LSYS }, /* Linksys USB10TA */ - {{ USB_DEVICE(0x066b, 0x400b) }, LSYS|PII }, /* Linksys USB10TX */ - {{ USB_DEVICE(0x067c, 0x1001) }, PII }, /* Siemens SpeedStream USB */ - {{ USB_DEVICE(0x0707, 0x0200) }, 0 }, /* SMC 2202USB */ - {{ USB_DEVICE(0x0707, 0x0201) }, PII }, /* SMC 2206USB */ - {{ USB_DEVICE(0x07a6, 0x0986) }, PNA }, /* ADMtek AN986 */ - {{ USB_DEVICE(0x07a6, 0x8511) }, PII }, /* ADMtek AN8511 */ - {{ USB_DEVICE(0x07a6, 0x8513) }, PII }, /* ADMtek AN8513 */ - {{ USB_DEVICE(0x07aa, 0x0004) }, 0 }, /* Corega FEther USB-TX */ - {{ USB_DEVICE(0x07aa, 0x000d) }, PII }, /* Corega FEther USB-TXS */ - {{ USB_DEVICE(0x07b8, 0x110c) }, PNA|PII }, /* AboCom XX1 */ - {{ USB_DEVICE(0x07b8, 0x200c) }, PII }, /* AboCom XX2 */ - {{ USB_DEVICE(0x07b8, 0x4002) }, LSYS }, /* AboCom UFE1000 */ - {{ USB_DEVICE(0x07b8, 0x4003) }, 0 }, /* AboCom DSB650TX_PNA */ - {{ USB_DEVICE(0x07b8, 0x4004) }, PNA }, /* AboCom XX4 */ - {{ USB_DEVICE(0x07b8, 0x4007) }, PNA }, /* AboCom XX5 */ - {{ USB_DEVICE(0x07b8, 0x400b) }, PII }, /* AboCom XX6 */ - {{ USB_DEVICE(0x07b8, 0x400c) }, PII }, /* AboCom XX7 */ - {{ USB_DEVICE(0x07b8, 0x4102) }, PII }, /* AboCom XX8 */ - {{ USB_DEVICE(0x07b8, 0x4104) }, PNA }, /* AboCom XX9 */ - {{ USB_DEVICE(0x07b8, 0xabc1) }, 0 }, /* AboCom XX10 */ - {{ USB_DEVICE(0x083a, 0x1046) }, 0 }, /* Accton USB320-EC */ - {{ USB_DEVICE(0x083a, 0x5046) }, PII }, /* Accton SpeedStream 1001 */ - {{ USB_DEVICE(0x08d1, 0x0003) }, PII }, /* SmartBridges smartNIC 2 PnP */ - {{ USB_DEVICE(0x08dd, 0x0986) }, 0 }, /* Billionton USB100N */ - {{ USB_DEVICE(0x08dd, 0x0987) }, PNA }, /* Billionton USB100LP */ - {{ USB_DEVICE(0x08dd, 0x0988) }, 0 }, /* Billionton USB100EL */ - {{ USB_DEVICE(0x08dd, 0x8511) }, PII }, /* Billionton USBE100 */ - {{ USB_DEVICE(0x0951, 0x000a) }, 0 }, /* Kingston KNU101TX */ - {{ USB_DEVICE(0x0e66, 0x400c) }, PII }, /* Hawking UF100 */ - {{ USB_DEVICE(0x15e8, 0x9100) }, 0 }, /* SOHOware NUB100 */ - {{ USB_DEVICE(0x2001, 0x200c) }, LSYS|PII },/* D-Link DSB650TX4 */ - {{ USB_DEVICE(0x2001, 0x4001) }, LSYS }, /* D-Link DSB650TX1 */ - {{ USB_DEVICE(0x2001, 0x4002) }, LSYS }, /* D-Link DSB650TX */ - {{ USB_DEVICE(0x2001, 0x4003) }, PNA }, /* D-Link DSB650TX_PNA */ - {{ USB_DEVICE(0x2001, 0x400b) }, LSYS|PII }, /* D-Link DSB650TX3 */ - {{ USB_DEVICE(0x2001, 0x4102) }, LSYS|PII }, /* D-Link DSB650TX2 */ - {{ USB_DEVICE(0x2001, 0xabc1) }, LSYS }, /* D-Link DSB650 */ -}; -#define aue_lookup(v, p) ((const struct aue_type *)usb_lookup(aue_devs, v, p)) - -static int aue_match(device_t); -static int aue_attach(device_t); -static int aue_detach(device_t); - -static void aue_reset_pegasus_II(struct aue_softc *sc); -static int aue_tx_list_init(struct aue_softc *); -static int aue_rx_list_init(struct aue_softc *); -static int aue_newbuf(struct aue_softc *, struct aue_chain *, struct mbuf *); -static int aue_encap(struct aue_softc *, struct mbuf *, int); -#ifdef AUE_INTR_PIPE -static void aue_intr(usbd_xfer_handle, usbd_private_handle, usbd_status); -#endif -static void aue_rxeof(usbd_xfer_handle, usbd_private_handle, usbd_status); -static void aue_txeof(usbd_xfer_handle, usbd_private_handle, usbd_status); -static void aue_tick(void *); -static void aue_rxstart(struct ifnet *); -static void aue_start(struct ifnet *, struct ifaltq_subque *); -static int aue_ioctl(struct ifnet *, u_long, caddr_t, struct ucred *); -static void aue_init(void *); -static void aue_stop(struct aue_softc *); -static void aue_watchdog(struct ifnet *); -static void aue_shutdown(device_t); -static int aue_ifmedia_upd(struct ifnet *); -static void aue_ifmedia_sts(struct ifnet *, struct ifmediareq *); - -static void aue_eeprom_getword(struct aue_softc *, int, u_int16_t *); -static void aue_read_eeprom(struct aue_softc *, caddr_t, int, int, int); -static int aue_miibus_readreg(device_t, int, int); -static int aue_miibus_writereg(device_t, int, int, int); -static void aue_miibus_statchg(device_t); - -static void aue_setmulti(struct aue_softc *); -static void aue_reset(struct aue_softc *); - -static int aue_csr_read_1(struct aue_softc *, int); -static int aue_csr_write_1(struct aue_softc *, int, int); -static int aue_csr_read_2(struct aue_softc *, int); -static int aue_csr_write_2(struct aue_softc *, int, int); - -static device_method_t aue_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, aue_match), - DEVMETHOD(device_attach, aue_attach), - DEVMETHOD(device_detach, aue_detach), - DEVMETHOD(device_shutdown, aue_shutdown), - - /* bus interface */ - DEVMETHOD(bus_print_child, bus_generic_print_child), - DEVMETHOD(bus_driver_added, bus_generic_driver_added), - - /* MII interface */ - DEVMETHOD(miibus_readreg, aue_miibus_readreg), - DEVMETHOD(miibus_writereg, aue_miibus_writereg), - DEVMETHOD(miibus_statchg, aue_miibus_statchg), - - DEVMETHOD_END -}; - -static driver_t aue_driver = { - "aue", - aue_methods, - sizeof(struct aue_softc) -}; - -static devclass_t aue_devclass; - -DECLARE_DUMMY_MODULE(if_aue); -DRIVER_MODULE(aue, uhub, aue_driver, aue_devclass, usbd_driver_load, NULL); -DRIVER_MODULE(miibus, aue, miibus_driver, miibus_devclass, NULL, NULL); - -#define AUE_SETBIT(sc, reg, x) \ - aue_csr_write_1(sc, reg, aue_csr_read_1(sc, reg) | (x)) - -#define AUE_CLRBIT(sc, reg, x) \ - aue_csr_write_1(sc, reg, aue_csr_read_1(sc, reg) & ~(x)) - -static int -aue_csr_read_1(struct aue_softc *sc, int reg) -{ - usb_device_request_t req; - usbd_status err; - u_int8_t val = 0; - - if (sc->aue_dying) - return(0); - - AUE_LOCK(sc); - - req.bmRequestType = UT_READ_VENDOR_DEVICE; - req.bRequest = AUE_UR_READREG; - USETW(req.wValue, 0); - USETW(req.wIndex, reg); - USETW(req.wLength, 1); - - err = usbd_do_request(sc->aue_udev, &req, &val); - - AUE_UNLOCK(sc); - - if (err) { - return (0); - } - - return (val); -} - -static int -aue_csr_read_2(struct aue_softc *sc, int reg) -{ - usb_device_request_t req; - usbd_status err; - u_int16_t val = 0; - - if (sc->aue_dying) - return (0); - - AUE_LOCK(sc); - - req.bmRequestType = UT_READ_VENDOR_DEVICE; - req.bRequest = AUE_UR_READREG; - USETW(req.wValue, 0); - USETW(req.wIndex, reg); - USETW(req.wLength, 2); - - err = usbd_do_request(sc->aue_udev, &req, &val); - - AUE_UNLOCK(sc); - - if (err) { - return (0); - } - - return (val); -} - -static int -aue_csr_write_1(struct aue_softc *sc, int reg, int val) -{ - usb_device_request_t req; - usbd_status err; - - if (sc->aue_dying) - return (0); - - AUE_LOCK(sc); - - req.bmRequestType = UT_WRITE_VENDOR_DEVICE; - req.bRequest = AUE_UR_WRITEREG; - USETW(req.wValue, val); - USETW(req.wIndex, reg); - USETW(req.wLength, 1); - - err = usbd_do_request(sc->aue_udev, &req, &val); - - AUE_UNLOCK(sc); - - if (err) { - return (-1); - } - - return (0); -} - -static int -aue_csr_write_2(struct aue_softc *sc, int reg, int val) -{ - usb_device_request_t req; - usbd_status err; - - if (sc->aue_dying) - return (0); - - AUE_LOCK(sc); - - req.bmRequestType = UT_WRITE_VENDOR_DEVICE; - req.bRequest = AUE_UR_WRITEREG; - USETW(req.wValue, val); - USETW(req.wIndex, reg); - USETW(req.wLength, 2); - - err = usbd_do_request(sc->aue_udev, &req, &val); - - AUE_UNLOCK(sc); - - if (err) { - return (-1); - } - - return (0); -} - -/* - * Read a word of data stored in the EEPROM at address 'addr.' - */ -static void -aue_eeprom_getword(struct aue_softc *sc, int addr, u_int16_t *dest) -{ - int i; - u_int16_t word = 0; - - aue_csr_write_1(sc, AUE_EE_REG, addr); - aue_csr_write_1(sc, AUE_EE_CTL, AUE_EECTL_READ); - - for (i = 0; i < AUE_TIMEOUT; i++) { - if (aue_csr_read_1(sc, AUE_EE_CTL) & AUE_EECTL_DONE) - break; - } - - if (i == AUE_TIMEOUT) - if_printf(&sc->arpcom.ac_if, "EEPROM read timed out\n"); - - word = aue_csr_read_2(sc, AUE_EE_DATA); - *dest = word; - - return; -} - -/* - * Read a sequence of words from the EEPROM. - */ -static void -aue_read_eeprom(struct aue_softc *sc, caddr_t dest, int off, int cnt, int swap) -{ - int i; - u_int16_t word = 0, *ptr; - - for (i = 0; i < cnt; i++) { - aue_eeprom_getword(sc, off + i, &word); - ptr = (u_int16_t *)(dest + (i * 2)); - if (swap) - *ptr = ntohs(word); - else - *ptr = word; - } - - return; -} - -static int -aue_miibus_readreg(device_t dev, int phy, int reg) -{ - struct aue_softc *sc = device_get_softc(dev); - int i; - u_int16_t val = 0; - - /* - * The Am79C901 HomePNA PHY actually contains - * two transceivers: a 1Mbps HomePNA PHY and a - * 10Mbps full/half duplex ethernet PHY with - * NWAY autoneg. However in the ADMtek adapter, - * only the 1Mbps PHY is actually connected to - * anything, so we ignore the 10Mbps one. It - * happens to be configured for MII address 3, - * so we filter that out. - */ - if (sc->aue_vendor == 0x07a6 && sc->aue_product == 0x0986) { - if (phy == 3) - return (0); -#ifdef notdef - if (phy != 1) - return (0); -#endif - } - - aue_csr_write_1(sc, AUE_PHY_ADDR, phy); - aue_csr_write_1(sc, AUE_PHY_CTL, reg | AUE_PHYCTL_READ); - - for (i = 0; i < AUE_TIMEOUT; i++) { - if (aue_csr_read_1(sc, AUE_PHY_CTL) & AUE_PHYCTL_DONE) - break; - } - - if (i == AUE_TIMEOUT) - if_printf(&sc->arpcom.ac_if, "MII read timed out\n"); - - val = aue_csr_read_2(sc, AUE_PHY_DATA); - - return (val); -} - -static int -aue_miibus_writereg(device_t dev, int phy, int reg, int data) -{ - struct aue_softc *sc = device_get_softc(dev); - int i; - - if (phy == 3) - return (0); - - aue_csr_write_2(sc, AUE_PHY_DATA, data); - aue_csr_write_1(sc, AUE_PHY_ADDR, phy); - aue_csr_write_1(sc, AUE_PHY_CTL, reg | AUE_PHYCTL_WRITE); - - for (i = 0; i < AUE_TIMEOUT; i++) { - if (aue_csr_read_1(sc, AUE_PHY_CTL) & AUE_PHYCTL_DONE) - break; - } - - if (i == AUE_TIMEOUT) - if_printf(&sc->arpcom.ac_if, "MII read timed out\n"); - - return(0); -} - -static void -aue_miibus_statchg(device_t dev) -{ - struct aue_softc *sc = device_get_softc(dev); - struct mii_data *mii = GET_MII(sc); - - AUE_CLRBIT(sc, AUE_CTL0, AUE_CTL0_RX_ENB | AUE_CTL0_TX_ENB); - if (IFM_SUBTYPE(mii->mii_media_active) == IFM_100_TX) { - AUE_SETBIT(sc, AUE_CTL1, AUE_CTL1_SPEEDSEL); - } else { - AUE_CLRBIT(sc, AUE_CTL1, AUE_CTL1_SPEEDSEL); - } - - if ((mii->mii_media_active & IFM_GMASK) == IFM_FDX) - AUE_SETBIT(sc, AUE_CTL1, AUE_CTL1_DUPLEX); - else - AUE_CLRBIT(sc, AUE_CTL1, AUE_CTL1_DUPLEX); - - AUE_SETBIT(sc, AUE_CTL0, AUE_CTL0_RX_ENB | AUE_CTL0_TX_ENB); - - /* - * Set the LED modes on the LinkSys adapter. - * This turns on the 'dual link LED' bin in the auxmode - * register of the Broadcom PHY. - */ - if (sc->aue_flags & LSYS) { - u_int16_t auxmode; - auxmode = aue_miibus_readreg(dev, 0, 0x1b); - aue_miibus_writereg(dev, 0, 0x1b, auxmode | 0x04); - } - - return; -} - -#define AUE_BITS 6 - -static void -aue_setmulti(struct aue_softc *sc) -{ - struct ifnet *ifp; - struct ifmultiaddr *ifma; - u_int32_t h = 0, i; - - ifp = &sc->arpcom.ac_if; - - if (ifp->if_flags & IFF_ALLMULTI || ifp->if_flags & IFF_PROMISC) { - AUE_SETBIT(sc, AUE_CTL0, AUE_CTL0_ALLMULTI); - return; - } - - AUE_CLRBIT(sc, AUE_CTL0, AUE_CTL0_ALLMULTI); - - /* first, zot all the existing hash bits */ - for (i = 0; i < 8; i++) - aue_csr_write_1(sc, AUE_MAR0 + i, 0); - - /* now program new ones */ - TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) - { - if (ifma->ifma_addr->sa_family != AF_LINK) - continue; - h = ether_crc32_le(LLADDR((struct sockaddr_dl *) - ifma->ifma_addr), ETHER_ADDR_LEN) & ((1 << AUE_BITS) - 1); - AUE_SETBIT(sc, AUE_MAR + (h >> 3), 1 << (h & 0x7)); - } - - return; -} - -static void -aue_reset_pegasus_II(struct aue_softc *sc) -{ - /* Magic constants taken from Linux driver. */ - aue_csr_write_1(sc, AUE_REG_1D, 0); - aue_csr_write_1(sc, AUE_REG_7B, 2); -#if 0 - if ((sc->aue_flags & HAS_HOME_PNA) && mii_mode) - aue_csr_write_1(sc, AUE_REG_81, 6); - else -#endif - aue_csr_write_1(sc, AUE_REG_81, 2); -} - -static void -aue_reset(struct aue_softc *sc) -{ - int i; - - AUE_SETBIT(sc, AUE_CTL1, AUE_CTL1_RESETMAC); - - for (i = 0; i < AUE_TIMEOUT; i++) { - if (!(aue_csr_read_1(sc, AUE_CTL1) & AUE_CTL1_RESETMAC)) - break; - } - - if (i == AUE_TIMEOUT) - if_printf(&sc->arpcom.ac_if, "reset failed\n"); - - /* - * The PHY(s) attached to the Pegasus chip may be held - * in reset until we flip on the GPIO outputs. Make sure - * to set the GPIO pins high so that the PHY(s) will - * be enabled. - * - * Note: We force all of the GPIO pins low first, *then* - * enable the ones we want. - */ - aue_csr_write_1(sc, AUE_GPIO0, AUE_GPIO_OUT0|AUE_GPIO_SEL0); - aue_csr_write_1(sc, AUE_GPIO0, AUE_GPIO_OUT0|AUE_GPIO_SEL0|AUE_GPIO_SEL1); - - if (sc->aue_flags & LSYS) { - /* Grrr. LinkSys has to be different from everyone else. */ - aue_csr_write_1(sc, AUE_GPIO0, - AUE_GPIO_SEL0 | AUE_GPIO_SEL1); - aue_csr_write_1(sc, AUE_GPIO0, - AUE_GPIO_SEL0 | AUE_GPIO_SEL1 | AUE_GPIO_OUT0); - } - - if (sc->aue_flags & PII) - aue_reset_pegasus_II(sc); - - /* Wait a little while for the chip to get its brains in order. */ - DELAY(10000); - - return; -} - -/* - * Probe for a Pegasus chip. - */ -static int -aue_match(device_t self) -{ - struct usb_attach_arg *uaa = device_get_ivars(self); - - if (uaa->iface != NULL) - return (UMATCH_NONE); - - return (aue_lookup(uaa->vendor, uaa->product) != NULL ? - UMATCH_VENDOR_PRODUCT : UMATCH_NONE); -} - -/* - * Attach the interface. Allocate softc structures, do ifmedia - * setup and ethernet/BPF attach. - */ -static int -aue_attach(device_t self) -{ - struct aue_softc *sc = device_get_softc(self); - struct usb_attach_arg *uaa = device_get_ivars(self); - u_char eaddr[ETHER_ADDR_LEN]; - struct ifnet *ifp; - usbd_interface_handle iface; - usbd_status err; - usb_interface_descriptor_t *id; - usb_endpoint_descriptor_t *ed; - int i; - - sc->aue_udev = uaa->device; - callout_init(&sc->aue_stat_timer); - - if (usbd_set_config_no(sc->aue_udev, AUE_CONFIG_NO, 0)) { - device_printf(self, "setting config no %d failed\n", - AUE_CONFIG_NO); - return ENXIO; - } - - err = usbd_device2interface_handle(uaa->device, AUE_IFACE_IDX, &iface); - if (err) { - device_printf(self, "getting interface handle failed\n"); - return ENXIO; - } - - sc->aue_iface = iface; - sc->aue_flags = aue_lookup(uaa->vendor, uaa->product)->aue_flags; - - sc->aue_product = uaa->product; - sc->aue_vendor = uaa->vendor; - - id = usbd_get_interface_descriptor(sc->aue_iface); - - /* Find endpoints. */ - for (i = 0; i < id->bNumEndpoints; i++) { - ed = usbd_interface2endpoint_descriptor(iface, i); - if (ed == NULL) { - device_printf(self, "couldn't get ep %d\n", i); - return ENXIO; - } - if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && - UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) { - sc->aue_ed[AUE_ENDPT_RX] = ed->bEndpointAddress; - } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT && - UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) { - sc->aue_ed[AUE_ENDPT_TX] = ed->bEndpointAddress; - } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && - UE_GET_XFERTYPE(ed->bmAttributes) == UE_INTERRUPT) { - sc->aue_ed[AUE_ENDPT_INTR] = ed->bEndpointAddress; - } - } - - AUE_LOCK(sc); - - ifp = &sc->arpcom.ac_if; - if_initname(ifp, device_get_name(self), device_get_unit(self)); - - /* Reset the adapter. */ - aue_reset(sc); - - /* - * Get station address from the EEPROM. - */ - aue_read_eeprom(sc, (caddr_t)&eaddr, 0, 3, 0); - - ifp->if_softc = sc; - ifp->if_mtu = ETHERMTU; - ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; - ifp->if_ioctl = aue_ioctl; - ifp->if_start = aue_start; - ifp->if_watchdog = aue_watchdog; - ifp->if_init = aue_init; - ifp->if_baudrate = 10000000; - ifq_set_maxlen(&ifp->if_snd, IFQ_MAXLEN); - ifq_set_ready(&ifp->if_snd); - - /* - * Do MII setup. - * NOTE: Doing this causes child devices to be attached to us, - * which we would normally disconnect at in the detach routine - * using device_delete_child(). However the USB code is set up - * such that when this driver is removed, all children devices - * are removed as well. In effect, the USB code ends up detaching - * all of our children for us, so we don't have to do is ourselves - * in aue_detach(). It's important to point this out since if - * we *do* try to detach the child devices ourselves, we will - * end up getting the children deleted twice, which will crash - * the system. - */ - if (mii_phy_probe(self, &sc->aue_miibus, - aue_ifmedia_upd, aue_ifmedia_sts)) { - device_printf(self, "MII without any PHY!\n"); - AUE_UNLOCK(sc); - return ENXIO; - } - - /* - * Call MI attach routine. - */ - ether_ifattach(ifp, eaddr, NULL); - usb_register_netisr(); - sc->aue_dying = 0; - - AUE_UNLOCK(sc); - return 0; -} - -static int -aue_detach(device_t dev) -{ - struct aue_softc *sc; - struct ifnet *ifp; - - sc = device_get_softc(dev); - AUE_LOCK(sc); - ifp = &sc->arpcom.ac_if; - - sc->aue_dying = 1; - callout_stop(&sc->aue_stat_timer); - ether_ifdetach(ifp); - - if (sc->aue_ep[AUE_ENDPT_TX] != NULL) - usbd_abort_pipe(sc->aue_ep[AUE_ENDPT_TX]); - if (sc->aue_ep[AUE_ENDPT_RX] != NULL) - usbd_abort_pipe(sc->aue_ep[AUE_ENDPT_RX]); -#ifdef AUE_INTR_PIPE - if (sc->aue_ep[AUE_ENDPT_INTR] != NULL) - usbd_abort_pipe(sc->aue_ep[AUE_ENDPT_INTR]); -#endif - - AUE_UNLOCK(sc); - - return (0); -} - -/* - * Initialize an RX descriptor and attach an MBUF cluster. - */ -static int -aue_newbuf(struct aue_softc *sc, struct aue_chain *c, struct mbuf *m) -{ - struct mbuf *m_new = NULL; - - if (m == NULL) { - m_new = m_getcl(MB_DONTWAIT, MT_DATA, M_PKTHDR); - if (m_new == NULL) { - if_printf(&sc->arpcom.ac_if, - "no memory for rx list -- packet dropped!\n"); - return (ENOBUFS); - } - m_new->m_len = m_new->m_pkthdr.len = MCLBYTES; - } else { - m_new = m; - m_new->m_len = m_new->m_pkthdr.len = MCLBYTES; - m_new->m_data = m_new->m_ext.ext_buf; - } - - m_adj(m_new, ETHER_ALIGN); - c->aue_mbuf = m_new; - - return (0); -} - -static int -aue_rx_list_init(struct aue_softc *sc) -{ - struct aue_cdata *cd; - struct aue_chain *c; - int i; - - cd = &sc->aue_cdata; - for (i = 0; i < AUE_RX_LIST_CNT; i++) { - c = &cd->aue_rx_chain[i]; - c->aue_sc = sc; - c->aue_idx = i; - if (aue_newbuf(sc, c, NULL) == ENOBUFS) - return (ENOBUFS); - if (c->aue_xfer == NULL) { - c->aue_xfer = usbd_alloc_xfer(sc->aue_udev); - if (c->aue_xfer == NULL) - return (ENOBUFS); - } - } - - return (0); -} - -static int -aue_tx_list_init(struct aue_softc *sc) -{ - struct aue_cdata *cd; - struct aue_chain *c; - int i; - - cd = &sc->aue_cdata; - for (i = 0; i < AUE_TX_LIST_CNT; i++) { - c = &cd->aue_tx_chain[i]; - c->aue_sc = sc; - c->aue_idx = i; - c->aue_mbuf = NULL; - if (c->aue_xfer == NULL) { - c->aue_xfer = usbd_alloc_xfer(sc->aue_udev); - if (c->aue_xfer == NULL) - return (ENOBUFS); - } - c->aue_buf = kmalloc(AUE_BUFSZ, M_USBDEV, M_WAITOK); - } - - return (0); -} - -#ifdef AUE_INTR_PIPE -static void -aue_intr(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status) -{ - struct aue_softc *sc = priv; - struct ifnet *ifp; - struct aue_intrpkt *p; - - AUE_LOCK(sc); - ifp = &sc->arpcom.ac_if; - - if (!(ifp->if_flags & IFF_RUNNING)) { - AUE_UNLOCK(sc); - return; - } - - if (status != USBD_NORMAL_COMPLETION) { - if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) { - AUE_UNLOCK(sc); - return; - } - if_printf(ifp, "usb error on intr: %s\n", usbd_errstr(status)); - if (status == USBD_STALLED) - usbd_clear_endpoint_stall(sc->aue_ep[AUE_ENDPT_RX]); - AUE_UNLOCK(sc); - return; - } - - usbd_get_xfer_status(xfer, NULL, (void **)&p, NULL, NULL); - - if (p->aue_txstat0) - ifp->if_oerrors++; - - if (p->aue_txstat0 & (AUE_TXSTAT0_LATECOLL & AUE_TXSTAT0_EXCESSCOLL)) - ifp->if_collisions++; - - AUE_UNLOCK(sc); - return; -} -#endif - -static void -aue_rxstart(struct ifnet *ifp) -{ - struct aue_softc *sc; - struct aue_chain *c; - - sc = ifp->if_softc; - AUE_LOCK(sc); - c = &sc->aue_cdata.aue_rx_chain[sc->aue_cdata.aue_rx_prod]; - - if (aue_newbuf(sc, c, NULL) == ENOBUFS) { - IFNET_STAT_INC(ifp, ierrors, 1); - AUE_UNLOCK(sc); - return; - } - - /* Setup new transfer. */ - usbd_setup_xfer(c->aue_xfer, sc->aue_ep[AUE_ENDPT_RX], - c, mtod(c->aue_mbuf, char *), AUE_BUFSZ, USBD_SHORT_XFER_OK, - USBD_NO_TIMEOUT, aue_rxeof); - usbd_transfer(c->aue_xfer); - - AUE_UNLOCK(sc); - return; -} - -/* - * A frame has been uploaded: pass the resulting mbuf chain up to - * the higher level protocols. - */ -static void -aue_rxeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status) -{ - struct aue_chain *c = priv; - struct aue_softc *sc = c->aue_sc; - struct mbuf *m; - struct ifnet *ifp; - int total_len = 0; - struct aue_rxpkt r; - - if (sc->aue_dying) - return; - - ifp = &sc->arpcom.ac_if; - - if (!(ifp->if_flags & IFF_RUNNING)) - return; - - if (status != USBD_NORMAL_COMPLETION) { - if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) - return; - if (usbd_ratecheck(&sc->aue_rx_notice)) { - if_printf(ifp, "usb error on rx: %s\n", - usbd_errstr(status)); - } - if (status == USBD_STALLED) - usbd_clear_endpoint_stall(sc->aue_ep[AUE_ENDPT_RX]); - goto done; - } - - usbd_get_xfer_status(xfer, NULL, NULL, &total_len, NULL); - - if (total_len <= 4 + ETHER_CRC_LEN) { - IFNET_STAT_INC(ifp, ierrors, 1); - goto done; - } - - m = c->aue_mbuf; - bcopy(mtod(m, char *) + total_len - 4, (char *)&r, sizeof(r)); - - /* Turn off all the non-error bits in the rx status word. */ - r.aue_rxstat &= AUE_RXSTAT_MASK; - - if (r.aue_rxstat) { - IFNET_STAT_INC(ifp, ierrors, 1); - goto done; - } - - /* No errors; receive the packet. */ - total_len -= (4 + ETHER_CRC_LEN); - - IFNET_STAT_INC(ifp, ipackets, 1); - m->m_pkthdr.rcvif = ifp; - m->m_pkthdr.len = m->m_len = total_len; - - /* Put the packet on the special USB input queue. */ - usb_ether_input(m); - aue_rxstart(ifp); - return; -done: - - /* Setup new transfer. */ - usbd_setup_xfer(xfer, sc->aue_ep[AUE_ENDPT_RX], - c, mtod(c->aue_mbuf, char *), AUE_BUFSZ, USBD_SHORT_XFER_OK, - USBD_NO_TIMEOUT, aue_rxeof); - usbd_transfer(xfer); -} - -/* - * A frame was downloaded to the chip. It's safe for us to clean up - * the list buffers. - */ -static void -aue_txeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status) -{ - struct aue_chain *c = priv; - struct aue_softc *sc = c->aue_sc; - struct ifnet *ifp; - usbd_status err; - - ifp = &sc->arpcom.ac_if; - - if (status != USBD_NORMAL_COMPLETION) { - if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) - return; - if_printf(ifp, "usb error on tx: %s\n", usbd_errstr(status)); - if (status == USBD_STALLED) - usbd_clear_endpoint_stall(sc->aue_ep[AUE_ENDPT_TX]); - return; - } - - usbd_get_xfer_status(c->aue_xfer, NULL, NULL, NULL, &err); - if (err) - IFNET_STAT_INC(ifp, oerrors, 1); - else - IFNET_STAT_INC(ifp, opackets, 1); - - /* XXX should hold serializer */ - ifp->if_timer = 0; - ifq_clr_oactive(&ifp->if_snd); - - if (!ifq_is_empty(&ifp->if_snd)) - if_devstart_sched(ifp); -} - -static void -aue_tick(void *xsc) -{ - struct aue_softc *sc = xsc; - struct ifnet *ifp; - struct mii_data *mii; - - if (sc == NULL) - return; - - ifp = &sc->arpcom.ac_if; - - lwkt_serialize_enter(ifp->if_serializer); - - mii = GET_MII(sc); - if (mii == NULL) { - lwkt_serialize_exit(ifp->if_serializer); - return; - } - - mii_tick(mii); - if (!sc->aue_link && mii->mii_media_status & IFM_ACTIVE && - IFM_SUBTYPE(mii->mii_media_active) != IFM_NONE) { - sc->aue_link++; - if (!ifq_is_empty(&ifp->if_snd)) - if_devstart_sched(ifp); - } - - callout_reset(&sc->aue_stat_timer, hz, aue_tick, sc); - - lwkt_serialize_exit(ifp->if_serializer); -} - -static int -aue_encap(struct aue_softc *sc, struct mbuf *m, int idx) -{ - int total_len; - struct aue_chain *c; - usbd_status err; - - c = &sc->aue_cdata.aue_tx_chain[idx]; - - /* - * Copy the mbuf data into a contiguous buffer, leaving two - * bytes at the beginning to hold the frame length. - */ - m_copydata(m, 0, m->m_pkthdr.len, c->aue_buf + 2); - c->aue_mbuf = m; - - total_len = m->m_pkthdr.len + 2; - - /* - * The ADMtek documentation says that the packet length is - * supposed to be specified in the first two bytes of the - * transfer, however it actually seems to ignore this info - * and base the frame size on the bulk transfer length. - */ - c->aue_buf[0] = (u_int8_t)m->m_pkthdr.len; - c->aue_buf[1] = (u_int8_t)(m->m_pkthdr.len >> 8); - - m_freem(c->aue_mbuf); - c->aue_mbuf = NULL; - m = NULL; - - usbd_setup_xfer(c->aue_xfer, sc->aue_ep[AUE_ENDPT_TX], - c, c->aue_buf, total_len, USBD_FORCE_SHORT_XFER, - 10000, aue_txeof); - - /* Transmit */ - err = usbd_transfer(c->aue_xfer); - if (err != USBD_IN_PROGRESS) { - aue_stop(sc); - return (EIO); - } - - sc->aue_cdata.aue_tx_cnt++; - - return (0); -} - -static void -aue_start(struct ifnet *ifp, struct ifaltq_subque *ifsq) -{ - struct aue_softc *sc = ifp->if_softc; - struct mbuf *m_head = NULL; - - ASSERT_ALTQ_SQ_DEFAULT(ifp, ifsq); - AUE_LOCK(sc); - - if (!sc->aue_link) { - ifq_purge(&ifp->if_snd); - AUE_UNLOCK(sc); - return; - } - - if ((ifp->if_flags & IFF_RUNNING) == 0 || - ifq_is_oactive(&ifp->if_snd)) { - AUE_UNLOCK(sc); - return; - } - - m_head = ifq_dequeue(&ifp->if_snd); - if (m_head == NULL) { - AUE_UNLOCK(sc); - return; - } - - if (aue_encap(sc, m_head, 0)) { - /* aue_encap() will free m_head, if we reach here */ - ifq_set_oactive(&ifp->if_snd); - AUE_UNLOCK(sc); - return; - } - - /* - * If there's a BPF listener, bounce a copy of this frame - * to him. - */ - BPF_MTAP(ifp, m_head); - - ifq_set_oactive(&ifp->if_snd); - - /* - * Set a timeout in case the chip goes out to lunch. - */ - ifp->if_timer = 5; - AUE_UNLOCK(sc); - - return; -} - -static void -aue_init(void *xsc) -{ - struct aue_softc *sc = xsc; - struct ifnet *ifp = &sc->arpcom.ac_if; - struct mii_data *mii = GET_MII(sc); - struct aue_chain *c; - usbd_status err; - int i; - - AUE_LOCK(sc); - - if (ifp->if_flags & IFF_RUNNING) { - AUE_UNLOCK(sc); - return; - } - - /* - * Cancel pending I/O and free all RX/TX buffers. - */ - aue_reset(sc); - - /* Set MAC address */ - for (i = 0; i < ETHER_ADDR_LEN; i++) - aue_csr_write_1(sc, AUE_PAR0 + i, sc->arpcom.ac_enaddr[i]); - - /* If we want promiscuous mode, set the allframes bit. */ - if (ifp->if_flags & IFF_PROMISC) - AUE_SETBIT(sc, AUE_CTL2, AUE_CTL2_RX_PROMISC); - else - AUE_CLRBIT(sc, AUE_CTL2, AUE_CTL2_RX_PROMISC); - - /* Init TX ring. */ - if (aue_tx_list_init(sc) == ENOBUFS) { - if_printf(&sc->arpcom.ac_if, "tx list init failed\n"); - AUE_UNLOCK(sc); - return; - } - - /* Init RX ring. */ - if (aue_rx_list_init(sc) == ENOBUFS) { - if_printf(&sc->arpcom.ac_if, "rx list init failed\n"); - AUE_UNLOCK(sc); - return; - } - -#ifdef AUE_INTR_PIPE - sc->aue_cdata.aue_ibuf = kmalloc(AUE_INTR_PKTLEN, M_USBDEV, M_WAITOK); -#endif - - /* Load the multicast filter. */ - aue_setmulti(sc); - - /* Enable RX and TX */ - aue_csr_write_1(sc, AUE_CTL0, AUE_CTL0_RXSTAT_APPEND | AUE_CTL0_RX_ENB); - AUE_SETBIT(sc, AUE_CTL0, AUE_CTL0_TX_ENB); - AUE_SETBIT(sc, AUE_CTL2, AUE_CTL2_EP3_CLR); - - mii_mediachg(mii); - - /* Open RX and TX pipes. */ - err = usbd_open_pipe(sc->aue_iface, sc->aue_ed[AUE_ENDPT_RX], - USBD_EXCLUSIVE_USE, &sc->aue_ep[AUE_ENDPT_RX]); - if (err) { - if_printf(&sc->arpcom.ac_if, "open rx pipe failed: %s\n", - usbd_errstr(err)); - AUE_UNLOCK(sc); - return; - } - err = usbd_open_pipe(sc->aue_iface, sc->aue_ed[AUE_ENDPT_TX], - USBD_EXCLUSIVE_USE, &sc->aue_ep[AUE_ENDPT_TX]); - if (err) { - if_printf(&sc->arpcom.ac_if, "open tx pipe failed: %s\n", - usbd_errstr(err)); - AUE_UNLOCK(sc); - return; - } - -#ifdef AUE_INTR_PIPE - err = usbd_open_pipe_intr(sc->aue_iface, sc->aue_ed[AUE_ENDPT_INTR], - USBD_SHORT_XFER_OK, &sc->aue_ep[AUE_ENDPT_INTR], sc, - sc->aue_cdata.aue_ibuf, AUE_INTR_PKTLEN, aue_intr, - AUE_INTR_INTERVAL); - if (err) { - if_printf(&sc->arpcom.ac_if, "open intr pipe failed: %s\n", - usbd_errstr(err)); - AUE_UNLOCK(sc); - return; - } -#endif - - /* Start up the receive pipe. */ - for (i = 0; i < AUE_RX_LIST_CNT; i++) { - c = &sc->aue_cdata.aue_rx_chain[i]; - usbd_setup_xfer(c->aue_xfer, sc->aue_ep[AUE_ENDPT_RX], - c, mtod(c->aue_mbuf, char *), AUE_BUFSZ, - USBD_SHORT_XFER_OK, USBD_NO_TIMEOUT, aue_rxeof); - usbd_transfer(c->aue_xfer); - } - - ifp->if_flags |= IFF_RUNNING; - ifq_clr_oactive(&ifp->if_snd); - - callout_reset(&sc->aue_stat_timer, hz, aue_tick, sc); - - AUE_UNLOCK(sc); - - return; -} - -/* - * Set media options. - */ -static int -aue_ifmedia_upd(struct ifnet *ifp) -{ - struct aue_softc *sc = ifp->if_softc; - struct mii_data *mii = GET_MII(sc); - - sc->aue_link = 0; - if (mii->mii_instance) { - struct mii_softc *miisc; - LIST_FOREACH(miisc, &mii->mii_phys, mii_list) - mii_phy_reset(miisc); - } - mii_mediachg(mii); - - return (0); -} - -/* - * Report current media status. - */ -static void -aue_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr) -{ - struct aue_softc *sc = ifp->if_softc; - struct mii_data *mii = GET_MII(sc); - - mii_pollstat(mii); - ifmr->ifm_active = mii->mii_media_active; - ifmr->ifm_status = mii->mii_media_status; - - return; -} - -static int -aue_ioctl(struct ifnet *ifp, u_long command, caddr_t data, struct ucred *cr) -{ - struct aue_softc *sc = ifp->if_softc; - struct ifreq *ifr = (struct ifreq *)data; - struct mii_data *mii; - int error = 0; - - AUE_LOCK(sc); - - switch(command) { - case SIOCSIFFLAGS: - if (ifp->if_flags & IFF_UP) { - if (ifp->if_flags & IFF_RUNNING && - ifp->if_flags & IFF_PROMISC && - !(sc->aue_if_flags & IFF_PROMISC)) { - AUE_SETBIT(sc, AUE_CTL2, AUE_CTL2_RX_PROMISC); - } else if (ifp->if_flags & IFF_RUNNING && - !(ifp->if_flags & IFF_PROMISC) && - sc->aue_if_flags & IFF_PROMISC) { - AUE_CLRBIT(sc, AUE_CTL2, AUE_CTL2_RX_PROMISC); - } else if (!(ifp->if_flags & IFF_RUNNING)) - aue_init(sc); - } else { - if (ifp->if_flags & IFF_RUNNING) - aue_stop(sc); - } - sc->aue_if_flags = ifp->if_flags; - error = 0; - break; - case SIOCADDMULTI: - case SIOCDELMULTI: - aue_setmulti(sc); - error = 0; - break; - case SIOCGIFMEDIA: - case SIOCSIFMEDIA: - mii = GET_MII(sc); - error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, command); - break; - default: - error = ether_ioctl(ifp, command, data); - break; - } - - AUE_UNLOCK(sc); - - return (error); -} - -static void -aue_watchdog(struct ifnet *ifp) -{ - struct aue_softc *sc = ifp->if_softc; - struct aue_chain *c; - usbd_status stat; - - ASSERT_SERIALIZED(ifp->if_serializer); - - IFNET_STAT_INC(ifp, oerrors, 1); - if_printf(ifp, "watchdog timeout\n"); - - c = &sc->aue_cdata.aue_tx_chain[0]; - usbd_get_xfer_status(c->aue_xfer, NULL, NULL, NULL, &stat); - aue_txeof(c->aue_xfer, c, stat); -} - -/* - * Stop the adapter and free any mbufs allocated to the - * RX and TX lists. - */ -static void -aue_stop(struct aue_softc *sc) -{ - usbd_status err; - struct ifnet *ifp; - int i; - - AUE_LOCK(sc); - ifp = &sc->arpcom.ac_if; - ifp->if_timer = 0; - - aue_csr_write_1(sc, AUE_CTL0, 0); - aue_csr_write_1(sc, AUE_CTL1, 0); - aue_reset(sc); - callout_stop(&sc->aue_stat_timer); - - /* Stop transfers. */ - if (sc->aue_ep[AUE_ENDPT_RX] != NULL) { - err = usbd_abort_pipe(sc->aue_ep[AUE_ENDPT_RX]); - if (err) { - if_printf(ifp, "abort rx pipe failed: %s\n", - usbd_errstr(err)); - } - err = usbd_close_pipe(sc->aue_ep[AUE_ENDPT_RX]); - if (err) { - if_printf(ifp, "close rx pipe failed: %s\n", - usbd_errstr(err)); - } - sc->aue_ep[AUE_ENDPT_RX] = NULL; - } - - if (sc->aue_ep[AUE_ENDPT_TX] != NULL) { - err = usbd_abort_pipe(sc->aue_ep[AUE_ENDPT_TX]); - if (err) { - if_printf(ifp, "abort tx pipe failed: %s\n", - usbd_errstr(err)); - } - err = usbd_close_pipe(sc->aue_ep[AUE_ENDPT_TX]); - if (err) { - if_printf(ifp, "close tx pipe failed: %s\n", - usbd_errstr(err)); - } - sc->aue_ep[AUE_ENDPT_TX] = NULL; - } - -#ifdef AUE_INTR_PIPE - if (sc->aue_ep[AUE_ENDPT_INTR] != NULL) { - err = usbd_abort_pipe(sc->aue_ep[AUE_ENDPT_INTR]); - if (err) { - if_printf(ifp, "abort intr pipe failed: %s\n", - usbd_errstr(err)); - } - err = usbd_close_pipe(sc->aue_ep[AUE_ENDPT_INTR]); - if (err) { - if_printf(ifp, "close intr pipe failed: %s\n", - usbd_errstr(err)); - } - sc->aue_ep[AUE_ENDPT_INTR] = NULL; - } -#endif - - /* Free RX resources. */ - for (i = 0; i < AUE_RX_LIST_CNT; i++) { - if (sc->aue_cdata.aue_rx_chain[i].aue_buf != NULL) { - kfree(sc->aue_cdata.aue_rx_chain[i].aue_buf, M_USBDEV); - sc->aue_cdata.aue_rx_chain[i].aue_buf = NULL; - } - if (sc->aue_cdata.aue_rx_chain[i].aue_mbuf != NULL) { - m_freem(sc->aue_cdata.aue_rx_chain[i].aue_mbuf); - sc->aue_cdata.aue_rx_chain[i].aue_mbuf = NULL; - } - if (sc->aue_cdata.aue_rx_chain[i].aue_xfer != NULL) { - usbd_free_xfer(sc->aue_cdata.aue_rx_chain[i].aue_xfer); - sc->aue_cdata.aue_rx_chain[i].aue_xfer = NULL; - } - } - - /* Free TX resources. */ - for (i = 0; i < AUE_TX_LIST_CNT; i++) { - if (sc->aue_cdata.aue_tx_chain[i].aue_buf != NULL) { - kfree(sc->aue_cdata.aue_tx_chain[i].aue_buf, M_USBDEV); - sc->aue_cdata.aue_tx_chain[i].aue_buf = NULL; - } - if (sc->aue_cdata.aue_tx_chain[i].aue_mbuf != NULL) { - m_freem(sc->aue_cdata.aue_tx_chain[i].aue_mbuf); - sc->aue_cdata.aue_tx_chain[i].aue_mbuf = NULL; - } - if (sc->aue_cdata.aue_tx_chain[i].aue_xfer != NULL) { - usbd_free_xfer(sc->aue_cdata.aue_tx_chain[i].aue_xfer); - sc->aue_cdata.aue_tx_chain[i].aue_xfer = NULL; - } - } - -#ifdef AUE_INTR_PIPE - if (sc->aue_cdata.aue_ibuf != NULL) { - kfree(sc->aue_cdata.aue_ibuf, M_USBDEV); - sc->aue_cdata.aue_ibuf = NULL; - } -#endif - - sc->aue_link = 0; - - ifp->if_flags &= ~IFF_RUNNING; - ifq_clr_oactive(&ifp->if_snd); - AUE_UNLOCK(sc); - - return; -} - -/* - * Stop all chip I/O so that the kernel's probe routines don't - * get confused by errant DMAs when rebooting. - */ -static void -aue_shutdown(device_t dev) -{ - struct aue_softc *sc; - struct ifnet *ifp; - - sc = device_get_softc(dev); - sc->aue_dying++; - - ifp = &sc->arpcom.ac_if; - - lwkt_serialize_enter(ifp->if_serializer); - aue_reset(sc); - aue_stop(sc); - lwkt_serialize_exit(ifp->if_serializer); -} diff --git a/sys/dev/netif/aue/if_auereg.h b/sys/dev/netif/aue/if_auereg.h deleted file mode 100644 index be9a23eee9..0000000000 --- a/sys/dev/netif/aue/if_auereg.h +++ /dev/null @@ -1,250 +0,0 @@ -/* - * Copyright (c) 1997, 1998, 1999 - * Bill Paul . 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. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Bill Paul. - * 4. Neither the name of the author nor the names of any co-contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY Bill Paul 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 Bill Paul OR THE VOICES IN HIS HEAD - * 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: src/sys/dev/usb/if_auereg.h,v 1.17 2003/10/04 21:41:01 joe Exp $ - * $DragonFly: src/sys/dev/netif/aue/if_auereg.h,v 1.7 2005/05/25 11:42:59 joerg Exp $ - */ - -/* - * Register definitions for ADMtek Pegasus AN986 USB to Ethernet - * chip. The Pegasus uses a total of four USB endpoints: the control - * endpoint (0), a bulk read endpoint for receiving packets (1), - * a bulk write endpoint for sending packets (2) and an interrupt - * endpoint for passing RX and TX status (3). Endpoint 0 is used - * to read and write the ethernet module's registers. All registers - * are 8 bits wide. - * - * Packet transfer is done in 64 byte chunks. The last chunk in a - * transfer is denoted by having a length less that 64 bytes. For - * the RX case, the data includes an optional RX status word. - */ - -#define AUE_UR_READREG 0xF0 -#define AUE_UR_WRITEREG 0xF1 - -#define AUE_CONFIG_NO 1 -#define AUE_IFACE_IDX 0 - -/* - * Note that while the ADMtek technically has four - * endpoints, the control endpoint (endpoint 0) is - * regarded as special by the USB code and drivers - * don't have direct access to it. (We access it - * using usbd_do_request() when reading/writing - * registers.) Consequently, our endpoint indexes - * don't match those in the ADMtek Pegasus manual: - * we consider the RX data endpoint to be index 0 - * and work up from there. - */ -#define AUE_ENDPT_RX 0x0 -#define AUE_ENDPT_TX 0x1 -#define AUE_ENDPT_INTR 0x2 -#define AUE_ENDPT_MAX 0x3 - -#define AUE_INTR_PKTLEN 0x8 - -#define AUE_CTL0 0x00 -#define AUE_CTL1 0x01 -#define AUE_CTL2 0x02 -#define AUE_MAR0 0x08 -#define AUE_MAR1 0x09 -#define AUE_MAR2 0x0A -#define AUE_MAR3 0x0B -#define AUE_MAR4 0x0C -#define AUE_MAR5 0x0D -#define AUE_MAR6 0x0E -#define AUE_MAR7 0x0F -#define AUE_MAR AUE_MAR0 -#define AUE_PAR0 0x10 -#define AUE_PAR1 0x11 -#define AUE_PAR2 0x12 -#define AUE_PAR3 0x13 -#define AUE_PAR4 0x14 -#define AUE_PAR5 0x15 -#define AUE_PAR AUE_PAR0 -#define AUE_PAUSE0 0x18 -#define AUE_PAUSE1 0x19 -#define AUE_PAUSE AUE_PAUSE0 -#define AUE_RX_FLOWCTL_CNT 0x1A -#define AUE_RX_FLOWCTL_FIFO 0x1B -#define AUE_REG_1D 0x1D -#define AUE_EE_REG 0x20 -#define AUE_EE_DATA0 0x21 -#define AUE_EE_DATA1 0x22 -#define AUE_EE_DATA AUE_EE_DATA0 -#define AUE_EE_CTL 0x23 -#define AUE_PHY_ADDR 0x25 -#define AUE_PHY_DATA0 0x26 -#define AUE_PHY_DATA1 0x27 -#define AUE_PHY_DATA AUE_PHY_DATA0 -#define AUE_PHY_CTL 0x28 -#define AUE_USB_STS 0x2A -#define AUE_TXSTAT0 0x2B -#define AUE_TXSTAT1 0x2C -#define AUE_TXSTAT AUE_TXSTAT0 -#define AUE_RXSTAT 0x2D -#define AUE_PKTLOST0 0x2E -#define AUE_PKTLOST1 0x2F -#define AUE_PKTLOST AUE_PKTLOST0 - -#define AUE_REG_7B 0x7B -#define AUE_GPIO0 0x7E -#define AUE_GPIO1 0x7F -#define AUE_REG_81 0x81 - -#define AUE_CTL0_INCLUDE_RXCRC 0x01 -#define AUE_CTL0_ALLMULTI 0x02 -#define AUE_CTL0_STOP_BACKOFF 0x04 -#define AUE_CTL0_RXSTAT_APPEND 0x08 -#define AUE_CTL0_WAKEON_ENB 0x10 -#define AUE_CTL0_RXPAUSE_ENB 0x20 -#define AUE_CTL0_RX_ENB 0x40 -#define AUE_CTL0_TX_ENB 0x80 - -#define AUE_CTL1_HOMELAN 0x04 -#define AUE_CTL1_RESETMAC 0x08 -#define AUE_CTL1_SPEEDSEL 0x10 /* 0 = 10mbps, 1 = 100mbps */ -#define AUE_CTL1_DUPLEX 0x20 /* 0 = half, 1 = full */ -#define AUE_CTL1_DELAYHOME 0x40 - -#define AUE_CTL2_EP3_CLR 0x01 /* reading EP3 clrs status regs */ -#define AUE_CTL2_RX_BADFRAMES 0x02 -#define AUE_CTL2_RX_PROMISC 0x04 -#define AUE_CTL2_LOOPBACK 0x08 -#define AUE_CTL2_EEPROMWR_ENB 0x10 -#define AUE_CTL2_EEPROM_LOAD 0x20 - -#define AUE_EECTL_WRITE 0x01 -#define AUE_EECTL_READ 0x02 -#define AUE_EECTL_DONE 0x04 - -#define AUE_PHYCTL_PHYREG 0x1F -#define AUE_PHYCTL_WRITE 0x20 -#define AUE_PHYCTL_READ 0x40 -#define AUE_PHYCTL_DONE 0x80 - -#define AUE_USBSTS_SUSPEND 0x01 -#define AUE_USBSTS_RESUME 0x02 - -#define AUE_TXSTAT0_JABTIMO 0x04 -#define AUE_TXSTAT0_CARLOSS 0x08 -#define AUE_TXSTAT0_NOCARRIER 0x10 -#define AUE_TXSTAT0_LATECOLL 0x20 -#define AUE_TXSTAT0_EXCESSCOLL 0x40 -#define AUE_TXSTAT0_UNDERRUN 0x80 - -#define AUE_TXSTAT1_PKTCNT 0x0F -#define AUE_TXSTAT1_FIFO_EMPTY 0x40 -#define AUE_TXSTAT1_FIFO_FULL 0x80 - -#define AUE_RXSTAT_OVERRUN 0x01 -#define AUE_RXSTAT_PAUSE 0x02 - -#define AUE_GPIO_IN0 0x01 -#define AUE_GPIO_OUT0 0x02 -#define AUE_GPIO_SEL0 0x04 -#define AUE_GPIO_IN1 0x08 -#define AUE_GPIO_OUT1 0x10 -#define AUE_GPIO_SEL1 0x20 - -struct aue_intrpkt { - u_int8_t aue_txstat0; - u_int8_t aue_txstat1; - u_int8_t aue_rxstat; - u_int8_t aue_rxlostpkt0; - u_int8_t aue_rxlostpkt1; - u_int8_t aue_wakeupstat; - u_int8_t aue_rsvd; -}; - -struct aue_rxpkt { - u_int16_t aue_pktlen; - u_int8_t aue_rxstat; -}; - -#define AUE_RXSTAT_MCAST 0x01 -#define AUE_RXSTAT_GIANT 0x02 -#define AUE_RXSTAT_RUNT 0x04 -#define AUE_RXSTAT_CRCERR 0x08 -#define AUE_RXSTAT_DRIBBLE 0x10 -#define AUE_RXSTAT_MASK 0x1E - -#define AUE_TX_LIST_CNT 1 -#define AUE_RX_LIST_CNT 1 - -struct aue_softc; - -struct aue_chain { - struct aue_softc *aue_sc; - usbd_xfer_handle aue_xfer; - char *aue_buf; - struct mbuf *aue_mbuf; - int aue_idx; -}; - -struct aue_cdata { - struct aue_chain aue_tx_chain[AUE_TX_LIST_CNT]; - struct aue_chain aue_rx_chain[AUE_RX_LIST_CNT]; - struct aue_intrpkt *aue_ibuf; - int aue_tx_prod; - int aue_tx_cons; - int aue_tx_cnt; - int aue_rx_prod; -}; - -#define AUE_INC(x, y) (x) = (x + 1) % y - -struct aue_softc { -#define GET_MII(sc) (device_get_softc((sc)->aue_miibus)) - struct arpcom arpcom; - device_t aue_miibus; - usbd_device_handle aue_udev; - usbd_interface_handle aue_iface; - u_int16_t aue_vendor; - u_int16_t aue_product; - int aue_ed[AUE_ENDPT_MAX]; - usbd_pipe_handle aue_ep[AUE_ENDPT_MAX]; - u_int8_t aue_link; - int aue_if_flags; - struct aue_cdata aue_cdata; - struct callout aue_stat_timer; - u_int16_t aue_flags; - char aue_dying; - struct timeval aue_rx_notice; -}; - -#define AUE_LOCK(_sc) -#define AUE_UNLOCK(_sc) - -#define AUE_TIMEOUT 1000 -#define AUE_BUFSZ 1536 -#define AUE_MIN_FRAMELEN 60 -#define AUE_INTR_INTERVAL 100 /* ms */ diff --git a/sys/dev/netif/axe/Makefile b/sys/dev/netif/axe/Makefile deleted file mode 100644 index 90210e7848..0000000000 --- a/sys/dev/netif/axe/Makefile +++ /dev/null @@ -1,7 +0,0 @@ -# $DragonFly: src/sys/dev/netif/axe/Makefile,v 1.3 2006/06/25 11:02:38 corecode Exp $ - -KMOD = if_axe -SRCS = if_axe.c opt_usb.h device_if.h bus_if.h -SRCS += miibus_if.h - -.include diff --git a/sys/dev/netif/axe/if_axe.c b/sys/dev/netif/axe/if_axe.c deleted file mode 100644 index b9f0a562b5..0000000000 --- a/sys/dev/netif/axe/if_axe.c +++ /dev/null @@ -1,1069 +0,0 @@ -/* - * Copyright (c) 1997, 1998, 1999, 2000-2003 - * Bill Paul . 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. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Bill Paul. - * 4. Neither the name of the author nor the names of any co-contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY Bill Paul 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 Bill Paul OR THE VOICES IN HIS HEAD - * 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: src/sys/dev/usb/if_axe.c,v 1.10 2003/12/08 07:54:14 obrien Exp $ - */ -/* - * ASIX Electronics AX88172 USB 2.0 ethernet driver. Used in the - * LinkSys USB200M and various other adapters. - * - * Manuals available from: - * http://www.asix.com.tw/datasheet/mac/Ax88172.PDF - * Note: you need the manual for the AX88170 chip (USB 1.x ethernet - * controller) to find the definitions for the RX control register. - * http://www.asix.com.tw/datasheet/mac/Ax88170.PDF - * - * Written by Bill Paul - * Senior Engineer - * Wind River Systems - */ - -/* - * The AX88172 provides USB ethernet supports at 10 and 100Mbps. - * It uses an external PHY (reference designs use a RealTek chip), - * and has a 64-bit multicast hash filter. There is some information - * missing from the manual which one needs to know in order to make - * the chip function: - * - * - You must set bit 7 in the RX control register, otherwise the - * chip won't receive any packets. - * - You must initialize all 3 IPG registers, or you won't be able - * to send any packets. - * - * Note that this device appears to only support loading the station - * address via autload from the EEPROM (i.e. there's no way to manaully - * set it). - * - * (Adam Weinberger wanted me to name this driver if_gir.c.) - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include - -#include -#include -#include -#include -#include - -#include "../mii_layer//mii.h" -#include "../mii_layer/miivar.h" - -/* "controller miibus0" required. See GENERIC if you get errors here. */ -#include "miibus_if.h" - -#include "if_axereg.h" - -/* - * Various supported device vendors/products. - */ -static struct usb_devno axe_devs[] = { - { USB_DEVICE(0x0411, 0x003d) }, /* Melco LUA-U2-KTX */ - { USB_DEVICE(0x04f1, 0x3008) }, /* JVC MP-PRX1 */ - { USB_DEVICE(0x077b, 0x2226) }, /* Linksys USB200M */ - { USB_DEVICE(0x0846, 0x1040) }, /* BayNETGEAR FA120 */ - { USB_DEVICE(0x086e, 0x1920) }, /* System Talks SGC-X2UL */ - { USB_DEVICE(0x0b95, 0x1720) }, /* ASIX Electronics AX88172 */ - { USB_DEVICE(0x2001, 0x1a00) }, /* D-Link DUBE100 */ - { USB_DEVICE(0x6189, 0x182d) }, /* Sitecom LN029 */ -}; - -static int axe_match(device_t); -static int axe_attach(device_t); -static int axe_detach(device_t); - -static int axe_tx_list_init(struct axe_softc *); -static int axe_rx_list_init(struct axe_softc *); -static int axe_newbuf(struct axe_softc *, struct axe_chain *, struct mbuf *); -static int axe_encap(struct axe_softc *, struct mbuf *, int); -static void axe_rxeof(usbd_xfer_handle, usbd_private_handle, usbd_status); -static void axe_txeof(usbd_xfer_handle, usbd_private_handle, usbd_status); -static void axe_tick(void *); -static void axe_rxstart(struct ifnet *); -static void axe_start(struct ifnet *, struct ifaltq_subque *); -static int axe_ioctl(struct ifnet *, u_long, caddr_t, struct ucred *); -static void axe_init(void *); -static void axe_stop(struct axe_softc *); -static void axe_watchdog(struct ifnet *); -static void axe_shutdown(device_t); -static int axe_miibus_readreg(device_t, int, int); -static int axe_miibus_writereg(device_t, int, int, int); -static void axe_miibus_statchg(device_t); -static int axe_cmd(struct axe_softc *, int, int, int, void *); -static int axe_ifmedia_upd(struct ifnet *); -static void axe_ifmedia_sts(struct ifnet *, struct ifmediareq *); - -static void axe_setmulti(struct axe_softc *); - -static device_method_t axe_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, axe_match), - DEVMETHOD(device_attach, axe_attach), - DEVMETHOD(device_detach, axe_detach), - DEVMETHOD(device_shutdown, axe_shutdown), - - /* bus interface */ - DEVMETHOD(bus_print_child, bus_generic_print_child), - DEVMETHOD(bus_driver_added, bus_generic_driver_added), - - /* MII interface */ - DEVMETHOD(miibus_readreg, axe_miibus_readreg), - DEVMETHOD(miibus_writereg, axe_miibus_writereg), - DEVMETHOD(miibus_statchg, axe_miibus_statchg), - - DEVMETHOD_END -}; - -static driver_t axe_driver = { - "axe", - axe_methods, - sizeof(struct axe_softc) -}; - -static devclass_t axe_devclass; - -DRIVER_MODULE(axe, uhub, axe_driver, axe_devclass, usbd_driver_load, NULL); -DRIVER_MODULE(miibus, axe, miibus_driver, miibus_devclass, NULL, NULL); -MODULE_DEPEND(axe, usb, 1, 1, 1); -MODULE_DEPEND(axe, miibus, 1, 1, 1); - -static int -axe_cmd(struct axe_softc *sc, int cmd, int index, int val, void *buf) -{ - usb_device_request_t req; - usbd_status err; - - if (sc->axe_dying) - return(0); - - if (AXE_CMD_DIR(cmd)) - req.bmRequestType = UT_WRITE_VENDOR_DEVICE; - else - req.bmRequestType = UT_READ_VENDOR_DEVICE; - req.bRequest = AXE_CMD_CMD(cmd); - USETW(req.wValue, val); - USETW(req.wIndex, index); - USETW(req.wLength, AXE_CMD_LEN(cmd)); - - err = usbd_do_request(sc->axe_udev, &req, buf); - - if (err) - return(-1); - - return(0); -} - -static int -axe_miibus_readreg(device_t dev, int phy, int reg) -{ - struct axe_softc *sc = device_get_softc(dev); - usbd_status err; - u_int16_t val; - - if (sc->axe_dying) { - return(0); - } - -#ifdef notdef - /* - * The chip tells us the MII address of any supported - * PHYs attached to the chip, so only read from those. - */ - - if (sc->axe_phyaddrs[0] != AXE_NOPHY && phy != sc->axe_phyaddrs[0]) { - return (0); - } - - if (sc->axe_phyaddrs[1] != AXE_NOPHY && phy != sc->axe_phyaddrs[1]) { - return (0); - } -#endif - if (sc->axe_phyaddrs[0] != 0xFF && sc->axe_phyaddrs[0] != phy) { - return (0); - } - - axe_cmd(sc, AXE_CMD_MII_OPMODE_SW, 0, 0, NULL); - err = axe_cmd(sc, AXE_CMD_MII_READ_REG, reg, phy, &val); - axe_cmd(sc, AXE_CMD_MII_OPMODE_HW, 0, 0, NULL); - - if (err) { - if_printf(&sc->arpcom.ac_if, "read PHY failed\n"); - return(-1); - } - - if (val) - sc->axe_phyaddrs[0] = phy; - - return (val); -} - -static int -axe_miibus_writereg(device_t dev, int phy, int reg, int val) -{ - struct axe_softc *sc = device_get_softc(dev); - usbd_status err; - - if (sc->axe_dying) { - return(0); - } - - axe_cmd(sc, AXE_CMD_MII_OPMODE_SW, 0, 0, NULL); - err = axe_cmd(sc, AXE_CMD_MII_WRITE_REG, reg, phy, &val); - axe_cmd(sc, AXE_CMD_MII_OPMODE_HW, 0, 0, NULL); - - if (err) { - if_printf(&sc->arpcom.ac_if, "write PHY failed\n"); - return(-1); - } - - return (0); -} - -static void -axe_miibus_statchg(device_t dev) -{ -#ifdef notdef - struct axe_softc *sc = device_get_softc(dev); - struct mii_data *mii = GET_MII(sc); -#endif - /* doesn't seem to be necessary */ - - return; -} - -/* - * Set media options. - */ -static int -axe_ifmedia_upd(struct ifnet *ifp) -{ - struct axe_softc *sc = ifp->if_softc; - struct mii_data *mii = GET_MII(sc); - - sc->axe_link = 0; - if (mii->mii_instance) { - struct mii_softc *miisc; - LIST_FOREACH(miisc, &mii->mii_phys, mii_list) - mii_phy_reset(miisc); - } - mii_mediachg(mii); - - return (0); -} - -/* - * Report current media status. - */ -static void -axe_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr) -{ - struct axe_softc *sc = ifp->if_softc; - struct mii_data *mii = GET_MII(sc); - - mii_pollstat(mii); - ifmr->ifm_active = mii->mii_media_active; - ifmr->ifm_status = mii->mii_media_status; - - return; -} - -static void -axe_setmulti(struct axe_softc *sc) -{ - struct ifnet *ifp = &sc->arpcom.ac_if; - struct ifmultiaddr *ifma; - u_int32_t h = 0; - u_int16_t rxmode; - u_int8_t hashtbl[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; - - axe_cmd(sc, AXE_CMD_RXCTL_READ, 0, 0, &rxmode); - - if (ifp->if_flags & IFF_ALLMULTI || ifp->if_flags & IFF_PROMISC) { - rxmode |= AXE_RXCMD_ALLMULTI; - axe_cmd(sc, AXE_CMD_RXCTL_WRITE, 0, rxmode, NULL); - return; - } else - rxmode &= ~AXE_RXCMD_ALLMULTI; - - TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { - if (ifma->ifma_addr->sa_family != AF_LINK) - continue; - h = ether_crc32_be( - LLADDR((struct sockaddr_dl *)ifma->ifma_addr), - ETHER_ADDR_LEN); - /* the filter bit position */ - h = (h >> 26) & 0x0000003F; - hashtbl[h / 8] |= 1 << (h % 8); - } - - axe_cmd(sc, AXE_CMD_WRITE_MCAST, 0, 0, &hashtbl); - axe_cmd(sc, AXE_CMD_RXCTL_WRITE, 0, rxmode, NULL); -} - -static void -axe_reset(struct axe_softc *sc) -{ - if (sc->axe_dying) - return; - - if (usbd_set_config_no(sc->axe_udev, AXE_CONFIG_NO, 1) || - usbd_device2interface_handle(sc->axe_udev, AXE_IFACE_IDX, - &sc->axe_iface)) { - if_printf(&sc->arpcom.ac_if, - "getting interface handle failed\n"); - } - - /* Wait a little while for the chip to get its brains in order. */ - DELAY(1000); - return; -} - -/* - * Probe for a AX88172 chip. - */ -static int -axe_match(device_t self) -{ - struct usb_attach_arg *uaa = device_get_ivars(self); - - if (!uaa->iface) - return(UMATCH_NONE); - - return (usb_lookup(axe_devs, uaa->vendor, uaa->product) != NULL ? - UMATCH_VENDOR_PRODUCT : UMATCH_NONE); -} - -/* - * Attach the interface. Allocate softc structures, do ifmedia - * setup and ethernet/BPF attach. - */ -static int -axe_attach(device_t self) -{ - struct axe_softc *sc = device_get_softc(self); - struct usb_attach_arg *uaa = device_get_ivars(self); - u_char eaddr[ETHER_ADDR_LEN]; - struct ifnet *ifp; - usb_interface_descriptor_t *id; - usb_endpoint_descriptor_t *ed; - int i; - - sc->axe_udev = uaa->device; - callout_init(&sc->axe_stat_timer); - - if (usbd_set_config_no(sc->axe_udev, AXE_CONFIG_NO, 1)) { - device_printf(self, "setting config no %d failed\n", - AXE_CONFIG_NO); - return ENXIO; - } - - if (usbd_device2interface_handle(uaa->device, - AXE_IFACE_IDX, &sc->axe_iface)) { - device_printf(self, "getting interface handle failed\n"); - return ENXIO; - } - - id = usbd_get_interface_descriptor(sc->axe_iface); - - /* Find endpoints. */ - for (i = 0; i < id->bNumEndpoints; i++) { - ed = usbd_interface2endpoint_descriptor(sc->axe_iface, i); - if (!ed) { - device_printf(self, "couldn't get ep %d\n", i); - return ENXIO; - } - if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && - UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) { - sc->axe_ed[AXE_ENDPT_RX] = ed->bEndpointAddress; - } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT && - UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) { - sc->axe_ed[AXE_ENDPT_TX] = ed->bEndpointAddress; - } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && - UE_GET_XFERTYPE(ed->bmAttributes) == UE_INTERRUPT) { - sc->axe_ed[AXE_ENDPT_INTR] = ed->bEndpointAddress; - } - } - - /* - * Get station address. - */ - axe_cmd(sc, AXE_CMD_READ_NODEID, 0, 0, &eaddr); - - /* - * Load IPG values and PHY indexes. - */ - axe_cmd(sc, AXE_CMD_READ_IPG012, 0, 0, &sc->axe_ipgs); - axe_cmd(sc, AXE_CMD_READ_PHYID, 0, 0, &sc->axe_phyaddrs); - - /* - * Work around broken adapters that appear to lie about - * their PHY addresses. - */ - sc->axe_phyaddrs[0] = sc->axe_phyaddrs[1] = 0xFF; - - ifp = &sc->arpcom.ac_if; - ifp->if_softc = sc; - if_initname(ifp, device_get_name(self), device_get_unit(self)); - ifp->if_mtu = ETHERMTU; - ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; - ifp->if_ioctl = axe_ioctl; - ifp->if_start = axe_start; - ifp->if_watchdog = axe_watchdog; - ifp->if_init = axe_init; - ifp->if_baudrate = 10000000; - ifq_set_maxlen(&ifp->if_snd, IFQ_MAXLEN); - ifq_set_ready(&ifp->if_snd); - - if (mii_phy_probe(self, &sc->axe_miibus, - axe_ifmedia_upd, axe_ifmedia_sts)) { - device_printf(self, "MII without any PHY!\n"); - return ENXIO; - } - - /* - * Call MI attach routine. - */ - - ether_ifattach(ifp, eaddr, NULL); - - sc->axe_dying = 0; - - usb_register_netisr(); - - return 0; -} - -static int -axe_detach(device_t dev) -{ - struct axe_softc *sc = device_get_softc(dev); - struct ifnet *ifp = &sc->arpcom.ac_if; - - sc->axe_dying = 1; - callout_stop(&sc->axe_stat_timer); - ether_ifdetach(ifp); - - if (sc->axe_ep[AXE_ENDPT_TX] != NULL) - usbd_abort_pipe(sc->axe_ep[AXE_ENDPT_TX]); - if (sc->axe_ep[AXE_ENDPT_RX] != NULL) - usbd_abort_pipe(sc->axe_ep[AXE_ENDPT_RX]); - if (sc->axe_ep[AXE_ENDPT_INTR] != NULL) - usbd_abort_pipe(sc->axe_ep[AXE_ENDPT_INTR]); - - return(0); -} - -/* - * Initialize an RX descriptor and attach an MBUF cluster. - */ -static int -axe_newbuf(struct axe_softc *sc, struct axe_chain *c, struct mbuf *m) -{ - struct mbuf *m_new = NULL; - - if (m == NULL) { - m_new = m_getcl(MB_DONTWAIT, MT_DATA, M_PKTHDR); - if (m_new == NULL) { - if_printf(&sc->arpcom.ac_if, "no memory for rx list " - "-- packet dropped!\n"); - return(ENOBUFS); - } - m_new->m_len = m_new->m_pkthdr.len = MCLBYTES; - } else { - m_new = m; - m_new->m_len = m_new->m_pkthdr.len = MCLBYTES; - m_new->m_data = m_new->m_ext.ext_buf; - } - - m_adj(m_new, ETHER_ALIGN); - c->axe_mbuf = m_new; - - return(0); -} - -static int -axe_rx_list_init(struct axe_softc *sc) -{ - struct axe_cdata *cd; - struct axe_chain *c; - int i; - - cd = &sc->axe_cdata; - for (i = 0; i < AXE_RX_LIST_CNT; i++) { - c = &cd->axe_rx_chain[i]; - c->axe_sc = sc; - c->axe_idx = i; - if (axe_newbuf(sc, c, NULL) == ENOBUFS) - return(ENOBUFS); - if (c->axe_xfer == NULL) { - c->axe_xfer = usbd_alloc_xfer(sc->axe_udev); - if (c->axe_xfer == NULL) - return(ENOBUFS); - } - } - - return(0); -} - -static int -axe_tx_list_init(struct axe_softc *sc) -{ - struct axe_cdata *cd; - struct axe_chain *c; - int i; - - cd = &sc->axe_cdata; - for (i = 0; i < AXE_TX_LIST_CNT; i++) { - c = &cd->axe_tx_chain[i]; - c->axe_sc = sc; - c->axe_idx = i; - c->axe_mbuf = NULL; - if (c->axe_xfer == NULL) { - c->axe_xfer = usbd_alloc_xfer(sc->axe_udev); - if (c->axe_xfer == NULL) - return(ENOBUFS); - } - c->axe_buf = kmalloc(AXE_BUFSZ, M_USBDEV, M_WAITOK); - } - - return(0); -} - -static void -axe_rxstart(struct ifnet *ifp) -{ - struct axe_softc *sc = ifp->if_softc; - struct axe_chain *c; - - c = &sc->axe_cdata.axe_rx_chain[sc->axe_cdata.axe_rx_prod]; - - if (axe_newbuf(sc, c, NULL) == ENOBUFS) { - IFNET_STAT_INC(ifp, ierrors, 1); - return; - } - - /* Setup new transfer. */ - usbd_setup_xfer(c->axe_xfer, sc->axe_ep[AXE_ENDPT_RX], - c, mtod(c->axe_mbuf, char *), AXE_BUFSZ, USBD_SHORT_XFER_OK, - USBD_NO_TIMEOUT, axe_rxeof); - usbd_transfer(c->axe_xfer); -} - -/* - * A frame has been uploaded: pass the resulting mbuf chain up to - * the higher level protocols. - */ -static void -axe_rxeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status) -{ - struct axe_chain *c = priv; - struct axe_softc *sc = c->axe_sc; - struct ifnet *ifp = &sc->arpcom.ac_if; - struct mbuf *m; - int total_len = 0; - - lwkt_serialize_enter(ifp->if_serializer); - - if (!(ifp->if_flags & IFF_RUNNING)) { - lwkt_serialize_exit(ifp->if_serializer); - return; - } - - if (status != USBD_NORMAL_COMPLETION) { - if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) { - lwkt_serialize_exit(ifp->if_serializer); - return; - } - if (usbd_ratecheck(&sc->axe_rx_notice)) { - if_printf(ifp, "usb error on rx: %s\n", - usbd_errstr(status)); - } - if (status == USBD_STALLED) - usbd_clear_endpoint_stall(sc->axe_ep[AXE_ENDPT_RX]); - goto done; - } - - usbd_get_xfer_status(xfer, NULL, NULL, &total_len, NULL); - - m = c->axe_mbuf; - - if (total_len < sizeof(struct ether_header)) { - IFNET_STAT_INC(ifp, ierrors, 1); - goto done; - } - - IFNET_STAT_INC(ifp, ipackets, 1); - m->m_pkthdr.rcvif = ifp; - m->m_pkthdr.len = m->m_len = total_len; - - /* Put the packet on the special USB input queue. */ - usb_ether_input(m); - axe_rxstart(ifp); - lwkt_serialize_exit(ifp->if_serializer); - return; -done: - /* Setup new transfer. */ - usbd_setup_xfer(c->axe_xfer, sc->axe_ep[AXE_ENDPT_RX], - c, mtod(c->axe_mbuf, char *), AXE_BUFSZ, USBD_SHORT_XFER_OK, - USBD_NO_TIMEOUT, axe_rxeof); - usbd_transfer(c->axe_xfer); - lwkt_serialize_exit(ifp->if_serializer); -} - -/* - * A frame was downloaded to the chip. It's safe for us to clean up - * the list buffers. - */ - -static void -axe_txeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status) -{ - struct axe_chain *c = priv; - struct axe_softc *sc = c->axe_sc; - struct ifnet *ifp = &sc->arpcom.ac_if; - usbd_status err; - - lwkt_serialize_enter(ifp->if_serializer); - if (status != USBD_NORMAL_COMPLETION) { - if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) { - lwkt_serialize_exit(ifp->if_serializer); - return; - } - if_printf(ifp, "usb error on tx: %s\n", usbd_errstr(status)); - if (status == USBD_STALLED) - usbd_clear_endpoint_stall(sc->axe_ep[AXE_ENDPT_TX]); - lwkt_serialize_exit(ifp->if_serializer); - return; - } - - ifp->if_timer = 0; - ifq_clr_oactive(&ifp->if_snd); - usbd_get_xfer_status(c->axe_xfer, NULL, NULL, NULL, &err); - - if (c->axe_mbuf != NULL) { - m_freem(c->axe_mbuf); - c->axe_mbuf = NULL; - } - - if (err) - IFNET_STAT_INC(ifp, oerrors, 1); - else - IFNET_STAT_INC(ifp, opackets, 1); - - if (!ifq_is_empty(&ifp->if_snd)) - if_devstart(ifp); - - lwkt_serialize_exit(ifp->if_serializer); -} - -static void -axe_tick(void *xsc) -{ - struct axe_softc *sc = xsc; - struct ifnet *ifp = &sc->arpcom.ac_if; - struct mii_data *mii; - - mii = GET_MII(sc); - if (mii == NULL) - return; - - lwkt_serialize_enter(ifp->if_serializer); - mii_tick(mii); - if (!sc->axe_link && mii->mii_media_status & IFM_ACTIVE && - IFM_SUBTYPE(mii->mii_media_active) != IFM_NONE) { - sc->axe_link++; - if (!ifq_is_empty(&ifp->if_snd)) - if_devstart(ifp); - } - callout_reset(&sc->axe_stat_timer, hz, axe_tick, sc); - lwkt_serialize_exit(ifp->if_serializer); -} - -static int -axe_encap(struct axe_softc *sc, struct mbuf *m, int idx) -{ - struct axe_chain *c; - usbd_status err; - - c = &sc->axe_cdata.axe_tx_chain[idx]; - - /* - * Copy the mbuf data into a contiguous buffer, leaving two - * bytes at the beginning to hold the frame length. - */ - m_copydata(m, 0, m->m_pkthdr.len, c->axe_buf); - c->axe_mbuf = m; - - usbd_setup_xfer(c->axe_xfer, sc->axe_ep[AXE_ENDPT_TX], - c, c->axe_buf, m->m_pkthdr.len, USBD_FORCE_SHORT_XFER, - 10000, axe_txeof); - - /* Transmit */ - err = usbd_transfer(c->axe_xfer); - if (err != USBD_IN_PROGRESS) { - axe_stop(sc); - return(EIO); - } - - sc->axe_cdata.axe_tx_cnt++; - - return(0); -} - -static void -axe_start(struct ifnet *ifp, struct ifaltq_subque *ifsq) -{ - struct axe_softc *sc = ifp->if_softc; - struct mbuf *m_head = NULL; - - ASSERT_ALTQ_SQ_DEFAULT(ifp, ifsq); - - if (!sc->axe_link) { - ifq_purge(&ifp->if_snd); - return; - } - - if (ifq_is_oactive(&ifp->if_snd)) { - return; - } - - m_head = ifq_dequeue(&ifp->if_snd); - if (m_head == NULL) - return; - - if (axe_encap(sc, m_head, 0)) { - /* axe_encap() will free m_head, if we reach here */ - ifq_set_oactive(&ifp->if_snd); - return; - } - - /* - * If there's a BPF listener, bounce a copy of this frame - * to him. - */ - BPF_MTAP(ifp, m_head); - - ifq_set_oactive(&ifp->if_snd); - - /* - * Set a timeout in case the chip goes out to lunch. - */ - ifp->if_timer = 5; -} - -static void -axe_init(void *xsc) -{ - struct axe_softc *sc = xsc; - struct ifnet *ifp = &sc->arpcom.ac_if; - struct axe_chain *c; - usbd_status err; - int i, rxmode; - - if (ifp->if_flags & IFF_RUNNING) { - return; - } - - /* - * Cancel pending I/O and free all RX/TX buffers. - */ - - axe_reset(sc); - -#ifdef notdef - /* Set MAC address */ - axe_mac(sc, sc->arpcom.ac_enaddr, 1); -#endif - - /* Enable RX logic. */ - - /* Init TX ring. */ - if (axe_tx_list_init(sc) == ENOBUFS) { - if_printf(ifp, "tx list init failed\n"); - return; - } - - /* Init RX ring. */ - if (axe_rx_list_init(sc) == ENOBUFS) { - if_printf(ifp, "rx list init failed\n"); - return; - } - - /* Set transmitter IPG values */ - axe_cmd(sc, AXE_CMD_WRITE_IPG0, 0, sc->axe_ipgs[0], NULL); - axe_cmd(sc, AXE_CMD_WRITE_IPG1, 0, sc->axe_ipgs[1], NULL); - axe_cmd(sc, AXE_CMD_WRITE_IPG2, 0, sc->axe_ipgs[2], NULL); - - /* Enable receiver, set RX mode */ - rxmode = AXE_RXCMD_UNICAST|AXE_RXCMD_MULTICAST|AXE_RXCMD_ENABLE; - - /* If we want promiscuous mode, set the allframes bit. */ - if (ifp->if_flags & IFF_PROMISC) - rxmode |= AXE_RXCMD_PROMISC; - - if (ifp->if_flags & IFF_BROADCAST) - rxmode |= AXE_RXCMD_BROADCAST; - - axe_cmd(sc, AXE_CMD_RXCTL_WRITE, 0, rxmode, NULL); - - /* Load the multicast filter. */ - axe_setmulti(sc); - - /* Open RX and TX pipes. */ - err = usbd_open_pipe(sc->axe_iface, sc->axe_ed[AXE_ENDPT_RX], - USBD_EXCLUSIVE_USE, &sc->axe_ep[AXE_ENDPT_RX]); - if (err) { - if_printf(ifp, "open rx pipe failed: %s\n", usbd_errstr(err)); - return; - } - - err = usbd_open_pipe(sc->axe_iface, sc->axe_ed[AXE_ENDPT_TX], - USBD_EXCLUSIVE_USE, &sc->axe_ep[AXE_ENDPT_TX]); - if (err) { - if_printf(ifp, "open tx pipe failed: %s\n", usbd_errstr(err)); - return; - } - - /* Start up the receive pipe. */ - for (i = 0; i < AXE_RX_LIST_CNT; i++) { - c = &sc->axe_cdata.axe_rx_chain[i]; - usbd_setup_xfer(c->axe_xfer, sc->axe_ep[AXE_ENDPT_RX], - c, mtod(c->axe_mbuf, char *), AXE_BUFSZ, - USBD_SHORT_XFER_OK, USBD_NO_TIMEOUT, axe_rxeof); - usbd_transfer(c->axe_xfer); - } - - ifp->if_flags |= IFF_RUNNING; - ifq_clr_oactive(&ifp->if_snd); - - callout_reset(&sc->axe_stat_timer, hz, axe_tick, sc); -} - -static int -axe_ioctl(struct ifnet *ifp, u_long command, caddr_t data, struct ucred *cr) -{ - struct axe_softc *sc = ifp->if_softc; - struct ifreq *ifr = (struct ifreq *)data; - struct mii_data *mii; - u_int16_t rxmode; - int error = 0; - - switch(command) { - case SIOCSIFFLAGS: - if (ifp->if_flags & IFF_UP) { - if (ifp->if_flags & IFF_RUNNING && - ifp->if_flags & IFF_PROMISC && - !(sc->axe_if_flags & IFF_PROMISC)) { - axe_cmd(sc, AXE_CMD_RXCTL_READ, 0, 0, &rxmode); - rxmode |= AXE_RXCMD_PROMISC; - axe_cmd(sc, AXE_CMD_RXCTL_WRITE, - 0, rxmode, NULL); - axe_setmulti(sc); - } else if (ifp->if_flags & IFF_RUNNING && - !(ifp->if_flags & IFF_PROMISC) && - sc->axe_if_flags & IFF_PROMISC) { - axe_cmd(sc, AXE_CMD_RXCTL_READ, 0, 0, &rxmode); - rxmode &= ~AXE_RXCMD_PROMISC; - axe_cmd(sc, AXE_CMD_RXCTL_WRITE, - 0, rxmode, NULL); - axe_setmulti(sc); - } else if (!(ifp->if_flags & IFF_RUNNING)) - axe_init(sc); - } else { - if (ifp->if_flags & IFF_RUNNING) - axe_stop(sc); - } - sc->axe_if_flags = ifp->if_flags; - error = 0; - break; - case SIOCADDMULTI: - case SIOCDELMULTI: - axe_setmulti(sc); - error = 0; - break; - case SIOCGIFMEDIA: - case SIOCSIFMEDIA: - mii = GET_MII(sc); - error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, command); - break; - - default: - error = ether_ioctl(ifp, command, data); - break; - } - return(error); -} - -static void -axe_watchdog(struct ifnet *ifp) -{ - struct axe_softc *sc = ifp->if_softc; - struct axe_chain *c; - usbd_status stat; - - IFNET_STAT_INC(ifp, oerrors, 1); - if_printf(ifp, "watchdog timeout\n"); - - c = &sc->axe_cdata.axe_tx_chain[0]; - usbd_get_xfer_status(c->axe_xfer, NULL, NULL, NULL, &stat); - axe_txeof(c->axe_xfer, c, stat); - - if (!ifq_is_empty(&ifp->if_snd)) - if_devstart(ifp); -} - -/* - * Stop the adapter and free any mbufs allocated to the - * RX and TX lists. - */ -static void -axe_stop(struct axe_softc *sc) -{ - usbd_status err; - struct ifnet *ifp; - int i; - - ifp = &sc->arpcom.ac_if; - ifp->if_timer = 0; - - callout_stop(&sc->axe_stat_timer); - - /* Stop transfers. */ - if (sc->axe_ep[AXE_ENDPT_RX] != NULL) { - err = usbd_abort_pipe(sc->axe_ep[AXE_ENDPT_RX]); - if (err) { - if_printf(ifp, "abort rx pipe failed: %s\n", - usbd_errstr(err)); - } - err = usbd_close_pipe(sc->axe_ep[AXE_ENDPT_RX]); - if (err) { - if_printf(ifp, "close rx pipe failed: %s\n", - usbd_errstr(err)); - } - sc->axe_ep[AXE_ENDPT_RX] = NULL; - } - - if (sc->axe_ep[AXE_ENDPT_TX] != NULL) { - err = usbd_abort_pipe(sc->axe_ep[AXE_ENDPT_TX]); - if (err) { - if_printf(ifp, "abort tx pipe failed: %s\n", - usbd_errstr(err)); - } - err = usbd_close_pipe(sc->axe_ep[AXE_ENDPT_TX]); - if (err) { - if_printf(ifp, "close tx pipe failed: %s\n", - usbd_errstr(err)); - } - sc->axe_ep[AXE_ENDPT_TX] = NULL; - } - - if (sc->axe_ep[AXE_ENDPT_INTR] != NULL) { - err = usbd_abort_pipe(sc->axe_ep[AXE_ENDPT_INTR]); - if (err) { - if_printf(ifp, "abort intr pipe failed: %s\n", - usbd_errstr(err)); - } - err = usbd_close_pipe(sc->axe_ep[AXE_ENDPT_INTR]); - if (err) { - if_printf(ifp, "close intr pipe failed: %s\n", - usbd_errstr(err)); - } - sc->axe_ep[AXE_ENDPT_INTR] = NULL; - } - - axe_reset(sc); - - /* Free RX resources. */ - for (i = 0; i < AXE_RX_LIST_CNT; i++) { - if (sc->axe_cdata.axe_rx_chain[i].axe_buf != NULL) { - kfree(sc->axe_cdata.axe_rx_chain[i].axe_buf, M_USBDEV); - sc->axe_cdata.axe_rx_chain[i].axe_buf = NULL; - } - if (sc->axe_cdata.axe_rx_chain[i].axe_mbuf != NULL) { - m_freem(sc->axe_cdata.axe_rx_chain[i].axe_mbuf); - sc->axe_cdata.axe_rx_chain[i].axe_mbuf = NULL; - } - if (sc->axe_cdata.axe_rx_chain[i].axe_xfer != NULL) { - usbd_free_xfer(sc->axe_cdata.axe_rx_chain[i].axe_xfer); - sc->axe_cdata.axe_rx_chain[i].axe_xfer = NULL; - } - } - - /* Free TX resources. */ - for (i = 0; i < AXE_TX_LIST_CNT; i++) { - if (sc->axe_cdata.axe_tx_chain[i].axe_buf != NULL) { - kfree(sc->axe_cdata.axe_tx_chain[i].axe_buf, M_USBDEV); - sc->axe_cdata.axe_tx_chain[i].axe_buf = NULL; - } - if (sc->axe_cdata.axe_tx_chain[i].axe_mbuf != NULL) { - m_freem(sc->axe_cdata.axe_tx_chain[i].axe_mbuf); - sc->axe_cdata.axe_tx_chain[i].axe_mbuf = NULL; - } - if (sc->axe_cdata.axe_tx_chain[i].axe_xfer != NULL) { - usbd_free_xfer(sc->axe_cdata.axe_tx_chain[i].axe_xfer); - sc->axe_cdata.axe_tx_chain[i].axe_xfer = NULL; - } - } - - ifp->if_flags &= ~IFF_RUNNING; - ifq_clr_oactive(&ifp->if_snd); - sc->axe_link = 0; -} - -/* - * Stop all chip I/O so that the kernel's probe routines don't - * get confused by errant DMAs when rebooting. - */ -static void -axe_shutdown(device_t dev) -{ - struct axe_softc *sc; - - sc = device_get_softc(dev); - - axe_stop(sc); -} diff --git a/sys/dev/netif/axe/if_axereg.h b/sys/dev/netif/axe/if_axereg.h deleted file mode 100644 index 251ae6adb5..0000000000 --- a/sys/dev/netif/axe/if_axereg.h +++ /dev/null @@ -1,158 +0,0 @@ -/* - * Copyright (c) 1997, 1998, 1999, 2000-2003 - * Bill Paul . 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. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Bill Paul. - * 4. Neither the name of the author nor the names of any co-contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY Bill Paul 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 Bill Paul OR THE VOICES IN HIS HEAD - * 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: src/sys/dev/usb/if_axereg.h,v 1.2 2003/06/15 21:45:43 wpaul Exp $ - * $DragonFly: src/sys/dev/netif/axe/if_axereg.h,v 1.5 2007/11/05 13:32:27 hasso Exp $ - */ - -/* - * Definitions for the ASIX Electronics AX88172 to ethernet controller. - */ - - -/* - * Vendor specific commands - * ASIX conveniently doesn't document the 'set NODEID' command in their - * datasheet (thanks a lot guys). - * To make handling these commands easier, I added some extra data - * which is decided by the axe_cmd() routine. Commands are encoded - * in 16 bites, with the format: LDCC. L and D are both nibbles in - * the high byte. L represents the data length (0 to 15) and D - * represents the direction (0 for vendor read, 1 for vendor write). - * CC is the command byte, as specified in the manual. - */ - -#define AXE_CMD_DIR(x) (((x) & 0x0F00) >> 8) -#define AXE_CMD_LEN(x) (((x) & 0xF000) >> 12) -#define AXE_CMD_CMD(x) ((x) & 0x00FF) - -#define AXE_CMD_READ_RXTX_SRAM 0x2002 -#define AXE_CMD_WRITE_RX_SRAM 0x0103 -#define AXE_CMD_WRITE_TX_SRAM 0x0104 -#define AXE_CMD_MII_OPMODE_SW 0x0106 -#define AXE_CMD_MII_READ_REG 0x2007 -#define AXE_CMD_MII_WRITE_REG 0x2108 -#define AXE_CMD_MII_READ_OPMODE 0x1009 -#define AXE_CMD_MII_OPMODE_HW 0x010A -#define AXE_CMD_SROM_READ 0x200B -#define AXE_CMD_SROM_WRITE 0x010C -#define AXE_CMD_SROM_WR_ENABLE 0x010D -#define AXE_CMD_SROM_WR_DISABLE 0x010E -#define AXE_CMD_RXCTL_READ 0x200F -#define AXE_CMD_RXCTL_WRITE 0x0110 -#define AXE_CMD_READ_IPG012 0x3011 -#define AXE_CMD_WRITE_IPG0 0x0112 -#define AXE_CMD_WRITE_IPG1 0x0113 -#define AXE_CMD_WRITE_IPG2 0x0114 -#define AXE_CMD_READ_MCAST 0x8015 -#define AXE_CMD_WRITE_MCAST 0x8116 -#define AXE_CMD_READ_NODEID 0x6017 -#define AXE_CMD_WRITE_NODEID 0x6118 -#define AXE_CMD_READ_PHYID 0x2019 -#define AXE_CMD_READ_MEDIA 0x101A -#define AXE_CMD_WRITE_MEDIA 0x011B -#define AXE_CMD_READ_MONITOR_MODE 0x101C -#define AXE_CMD_WRITE_MONITOR_MODE 0x011D -#define AXE_CMD_READ_GPIO 0x101E -#define AXE_CMD_WRITE_GPIO 0x011F - -#define AXE_RXCMD_PROMISC 0x0001 -#define AXE_RXCMD_ALLMULTI 0x0002 -#define AXE_RXCMD_UNICAST 0x0004 -#define AXE_RXCMD_BROADCAST 0x0008 -#define AXE_RXCMD_MULTICAST 0x0010 -#define AXE_RXCMD_ENABLE 0x0080 - -#define AXE_NOPHY 0xE0 - -#define AXE_TIMEOUT 1000 -#define AXE_BUFSZ 1536 -#define AXE_MIN_FRAMELEN 60 -#define AXE_RX_FRAMES 1 -#define AXE_TX_FRAMES 1 - -#define AXE_RX_LIST_CNT 1 -#define AXE_TX_LIST_CNT 1 - -#define AXE_CTL_READ 0x01 -#define AXE_CTL_WRITE 0x02 - -#define AXE_CONFIG_NO 1 -#define AXE_IFACE_IDX 0 - -/* - * The interrupt endpoint is currently unused - * by the ASIX part. - */ -#define AXE_ENDPT_RX 0x0 -#define AXE_ENDPT_TX 0x1 -#define AXE_ENDPT_INTR 0x2 -#define AXE_ENDPT_MAX 0x3 - -struct axe_softc; - -struct axe_chain { - struct axe_softc *axe_sc; - usbd_xfer_handle axe_xfer; - char *axe_buf; - struct mbuf *axe_mbuf; - int axe_accum; - int axe_idx; -}; - -struct axe_cdata { - struct axe_chain axe_tx_chain[AXE_TX_LIST_CNT]; - struct axe_chain axe_rx_chain[AXE_RX_LIST_CNT]; - int axe_tx_prod; - int axe_tx_cons; - int axe_tx_cnt; - int axe_rx_prod; -}; - -#define AXE_INC(x, y) (x) = (x + 1) % y - -struct axe_softc { -#define GET_MII(sc) (device_get_softc((sc)->axe_miibus)) - struct arpcom arpcom; - device_t axe_miibus; - usbd_device_handle axe_udev; - usbd_interface_handle axe_iface; - int axe_ed[AXE_ENDPT_MAX]; - usbd_pipe_handle axe_ep[AXE_ENDPT_MAX]; - int axe_if_flags; - struct axe_cdata axe_cdata; - struct callout axe_stat_timer; - char axe_dying; - int axe_link; - unsigned char axe_ipgs[3]; - unsigned char axe_phyaddrs[2]; - struct timeval axe_rx_notice; -}; diff --git a/sys/dev/netif/cue/Makefile b/sys/dev/netif/cue/Makefile deleted file mode 100644 index e5aa866b0d..0000000000 --- a/sys/dev/netif/cue/Makefile +++ /dev/null @@ -1,7 +0,0 @@ -# $FreeBSD: src/sys/modules/cue/Makefile,v 1.2 2000/01/28 11:26:27 bde Exp $ -# $DragonFly: src/sys/dev/netif/cue/Makefile,v 1.5 2006/11/18 10:00:19 swildner Exp $ - -KMOD = if_cue -SRCS = if_cue.c opt_usb.h device_if.h bus_if.h - -.include diff --git a/sys/dev/netif/cue/if_cue.c b/sys/dev/netif/cue/if_cue.c deleted file mode 100644 index 00c1247ba7..0000000000 --- a/sys/dev/netif/cue/if_cue.c +++ /dev/null @@ -1,1150 +0,0 @@ -/* - * Copyright (c) 1997, 1998, 1999, 2000 - * Bill Paul . 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. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Bill Paul. - * 4. Neither the name of the author nor the names of any co-contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY Bill Paul 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 Bill Paul OR THE VOICES IN HIS HEAD - * 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: src/sys/dev/usb/if_cue.c,v 1.45 2003/12/08 07:54:14 obrien Exp $ - */ - -/* - * CATC USB-EL1210A USB to ethernet driver. Used in the CATC Netmate - * adapters and others. - * - * Written by Bill Paul - * Electrical Engineering Department - * Columbia University, New York City - */ - -/* - * The CATC USB-EL1210A provides USB ethernet support at 10Mbps. The - * RX filter uses a 512-bit multicast hash table, single perfect entry - * for the station address, and promiscuous mode. Unlike the ADMtek - * and KLSI chips, the CATC ASIC supports read and write combining - * mode where multiple packets can be transfered using a single bulk - * transaction, which helps performance a great deal. - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include "if_cuereg.h" - -/* - * Various supported device vendors/products. - */ -static struct usb_devno cue_devs[] = { - { USB_DEVICE(0x0423, 0x000a) }, /* CATC Netmate */ - { USB_DEVICE(0x0423, 0x000c) }, /* CATC Netmate2 */ - { USB_DEVICE(0x08d1, 0x0001) }, /* SmartBridges SmartLink */ -}; - -static int cue_match(device_t); -static int cue_attach(device_t); -static int cue_detach(device_t); - -static int cue_tx_list_init(struct cue_softc *); -static int cue_rx_list_init(struct cue_softc *); -static int cue_newbuf(struct cue_softc *, struct cue_chain *, struct mbuf *); -static int cue_encap(struct cue_softc *, struct mbuf *, int); -static void cue_rxeof(usbd_xfer_handle, usbd_private_handle, usbd_status); -static void cue_txeof(usbd_xfer_handle, usbd_private_handle, usbd_status); -static void cue_tick(void *); -static void cue_rxstart(struct ifnet *); -static void cue_start(struct ifnet *, struct ifaltq_subque *); -static int cue_ioctl(struct ifnet *, u_long, caddr_t, struct ucred *); -static void cue_init(void *); -static void cue_stop(struct cue_softc *); -static void cue_watchdog(struct ifnet *); -static void cue_shutdown(device_t); - -static void cue_setmulti(struct cue_softc *); -static void cue_reset(struct cue_softc *); - -static int cue_csr_read_1(struct cue_softc *, int); -static int cue_csr_write_1(struct cue_softc *, int, int); -static int cue_csr_read_2(struct cue_softc *, int); -#ifdef notdef -static int cue_csr_write_2(struct cue_softc *, int, int); -#endif -static int cue_mem(struct cue_softc *, int, int, void *, int); -static int cue_getmac(struct cue_softc *, void *); - -static device_method_t cue_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, cue_match), - DEVMETHOD(device_attach, cue_attach), - DEVMETHOD(device_detach, cue_detach), - DEVMETHOD(device_shutdown, cue_shutdown), - - DEVMETHOD_END -}; - -static driver_t cue_driver = { - "cue", - cue_methods, - sizeof(struct cue_softc) -}; - -static devclass_t cue_devclass; - -DECLARE_DUMMY_MODULE(if_cue); -DRIVER_MODULE(cue, uhub, cue_driver, cue_devclass, usbd_driver_load, NULL); -MODULE_DEPEND(cue, usb, 1, 1, 1); - -#define CUE_SETBIT(sc, reg, x) \ - cue_csr_write_1(sc, reg, cue_csr_read_1(sc, reg) | (x)) - -#define CUE_CLRBIT(sc, reg, x) \ - cue_csr_write_1(sc, reg, cue_csr_read_1(sc, reg) & ~(x)) - -static int -cue_csr_read_1(struct cue_softc *sc, int reg) -{ - usb_device_request_t req; - usbd_status err; - u_int8_t val = 0; - - if (sc->cue_dying) - return(0); - - CUE_LOCK(sc); - - req.bmRequestType = UT_READ_VENDOR_DEVICE; - req.bRequest = CUE_CMD_READREG; - USETW(req.wValue, 0); - USETW(req.wIndex, reg); - USETW(req.wLength, 1); - - err = usbd_do_request(sc->cue_udev, &req, &val); - - CUE_UNLOCK(sc); - - if (err) - return(0); - - return(val); -} - -static int -cue_csr_read_2(struct cue_softc *sc, int reg) -{ - usb_device_request_t req; - usbd_status err; - u_int16_t val = 0; - - if (sc->cue_dying) - return(0); - - CUE_LOCK(sc); - - req.bmRequestType = UT_READ_VENDOR_DEVICE; - req.bRequest = CUE_CMD_READREG; - USETW(req.wValue, 0); - USETW(req.wIndex, reg); - USETW(req.wLength, 2); - - err = usbd_do_request(sc->cue_udev, &req, &val); - - CUE_UNLOCK(sc); - - if (err) - return(0); - - return(val); -} - -static int -cue_csr_write_1(struct cue_softc *sc, int reg, int val) -{ - usb_device_request_t req; - usbd_status err; - - if (sc->cue_dying) - return(0); - - CUE_LOCK(sc); - - req.bmRequestType = UT_WRITE_VENDOR_DEVICE; - req.bRequest = CUE_CMD_WRITEREG; - USETW(req.wValue, val); - USETW(req.wIndex, reg); - USETW(req.wLength, 0); - - err = usbd_do_request(sc->cue_udev, &req, NULL); - - CUE_UNLOCK(sc); - - if (err) - return(-1); - - return(0); -} - -#ifdef notdef -static int -cue_csr_write_2(struct cue_softc *sc, int reg, int val) -{ - usb_device_request_t req; - usbd_status err; - - if (sc->cue_dying) - return(0); - - CUE_LOCK(sc); - - req.bmRequestType = UT_WRITE_VENDOR_DEVICE; - req.bRequest = CUE_CMD_WRITEREG; - USETW(req.wValue, val); - USETW(req.wIndex, reg); - USETW(req.wLength, 0); - - err = usbd_do_request(sc->cue_udev, &req, NULL); - - CUE_UNLOCK(sc); - - if (err) - return(-1); - - return(0); -} -#endif - -static int -cue_mem(struct cue_softc *sc, int cmd, int addr, void *buf, int len) -{ - usb_device_request_t req; - usbd_status err; - - if (sc->cue_dying) - return(0); - - CUE_LOCK(sc); - - if (cmd == CUE_CMD_READSRAM) - req.bmRequestType = UT_READ_VENDOR_DEVICE; - else - req.bmRequestType = UT_WRITE_VENDOR_DEVICE; - req.bRequest = cmd; - USETW(req.wValue, 0); - USETW(req.wIndex, addr); - USETW(req.wLength, len); - - err = usbd_do_request(sc->cue_udev, &req, buf); - - CUE_UNLOCK(sc); - - if (err) - return(-1); - - return(0); -} - -static int -cue_getmac(struct cue_softc *sc, void *buf) -{ - usb_device_request_t req; - usbd_status err; - - if (sc->cue_dying) - return(0); - - CUE_LOCK(sc); - - req.bmRequestType = UT_READ_VENDOR_DEVICE; - req.bRequest = CUE_CMD_GET_MACADDR; - USETW(req.wValue, 0); - USETW(req.wIndex, 0); - USETW(req.wLength, ETHER_ADDR_LEN); - - err = usbd_do_request(sc->cue_udev, &req, buf); - - CUE_UNLOCK(sc); - - if (err) { - if_printf(&sc->arpcom.ac_if, "read MAC address failed\n"); - return(-1); - } - - return(0); -} - -#define CUE_BITS 9 - -static void -cue_setmulti(struct cue_softc *sc) -{ - struct ifnet *ifp; - struct ifmultiaddr *ifma; - u_int32_t h = 0, i; - - ifp = &sc->arpcom.ac_if; - - if (ifp->if_flags & IFF_ALLMULTI || ifp->if_flags & IFF_PROMISC) { - for (i = 0; i < CUE_MCAST_TABLE_LEN; i++) - sc->cue_mctab[i] = 0xFF; - cue_mem(sc, CUE_CMD_WRITESRAM, CUE_MCAST_TABLE_ADDR, - &sc->cue_mctab, CUE_MCAST_TABLE_LEN); - return; - } - - /* first, zot all the existing hash bits */ - for (i = 0; i < CUE_MCAST_TABLE_LEN; i++) - sc->cue_mctab[i] = 0; - - /* now program new ones */ - TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) - { - if (ifma->ifma_addr->sa_family != AF_LINK) - continue; - h = ether_crc32_le( - LLADDR((struct sockaddr_dl *)ifma->ifma_addr), - ETHER_ADDR_LEN) & ((1 << CUE_BITS) - 1); - sc->cue_mctab[h >> 3] |= 1 << (h & 0x7); - } - - /* - * Also include the broadcast address in the filter - * so we can receive broadcast frames. - */ - if (ifp->if_flags & IFF_BROADCAST) { - h = ether_crc32_le(ifp->if_broadcastaddr, ETHER_ADDR_LEN) & - ((1 << CUE_BITS) - 1); - sc->cue_mctab[h >> 3] |= 1 << (h & 0x7); - } - - cue_mem(sc, CUE_CMD_WRITESRAM, CUE_MCAST_TABLE_ADDR, - &sc->cue_mctab, CUE_MCAST_TABLE_LEN); - - return; -} - -static void -cue_reset(struct cue_softc *sc) -{ - usb_device_request_t req; - usbd_status err; - - if (sc->cue_dying) - return; - - req.bmRequestType = UT_WRITE_VENDOR_DEVICE; - req.bRequest = CUE_CMD_RESET; - USETW(req.wValue, 0); - USETW(req.wIndex, 0); - USETW(req.wLength, 0); - err = usbd_do_request(sc->cue_udev, &req, NULL); - if (err) - if_printf(&sc->arpcom.ac_if, "reset failed\n"); - - /* Wait a little while for the chip to get its brains in order. */ - DELAY(1000); - return; -} - -/* - * Probe for a Pegasus chip. - */ -static int -cue_match(device_t self) -{ - struct usb_attach_arg *uaa = device_get_ivars(self); - - if (uaa->iface == NULL) - return(UMATCH_NONE); - - return (usb_lookup(cue_devs, uaa->vendor, uaa->product) != NULL) ? - UMATCH_VENDOR_PRODUCT : UMATCH_NONE; -} - -/* - * Attach the interface. Allocate softc structures, do ifmedia - * setup and ethernet/BPF attach. - */ -static int -cue_attach(device_t self) -{ - struct cue_softc *sc = device_get_softc(self); - struct usb_attach_arg *uaa = device_get_ivars(self); - u_char eaddr[ETHER_ADDR_LEN]; - struct ifnet *ifp; - usb_interface_descriptor_t *id; - usb_endpoint_descriptor_t *ed; - int i; - - sc->cue_iface = uaa->iface; - sc->cue_udev = uaa->device; - callout_init(&sc->cue_stat_timer); - - if (usbd_set_config_no(sc->cue_udev, CUE_CONFIG_NO, 0)) { - device_printf(self, "setting config no %d failed\n", - CUE_CONFIG_NO); - return ENXIO; - } - - id = usbd_get_interface_descriptor(uaa->iface); - - /* Find endpoints. */ - for (i = 0; i < id->bNumEndpoints; i++) { - ed = usbd_interface2endpoint_descriptor(uaa->iface, i); - if (!ed) { - device_printf(self, "couldn't get ep %d\n", i); - return ENXIO; - } - if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && - UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) { - sc->cue_ed[CUE_ENDPT_RX] = ed->bEndpointAddress; - } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT && - UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) { - sc->cue_ed[CUE_ENDPT_TX] = ed->bEndpointAddress; - } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && - UE_GET_XFERTYPE(ed->bmAttributes) == UE_INTERRUPT) { - sc->cue_ed[CUE_ENDPT_INTR] = ed->bEndpointAddress; - } - } - - CUE_LOCK(sc); - - ifp = &sc->arpcom.ac_if; - if_initname(ifp, device_get_name(self), device_get_unit(self)); - -#ifdef notdef - /* Reset the adapter. */ - cue_reset(sc); -#endif - /* - * Get station address. - */ - cue_getmac(sc, &eaddr); - - ifp->if_softc = sc; - ifp->if_mtu = ETHERMTU; - ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; - ifp->if_ioctl = cue_ioctl; - ifp->if_start = cue_start; - ifp->if_watchdog = cue_watchdog; - ifp->if_init = cue_init; - ifp->if_baudrate = 10000000; - ifq_set_maxlen(&ifp->if_snd, IFQ_MAXLEN); - ifq_set_ready(&ifp->if_snd); - - /* - * Call MI attach routine. - */ - ether_ifattach(ifp, eaddr, NULL); - usb_register_netisr(); - sc->cue_dying = 0; - - CUE_UNLOCK(sc); - return 0; -} - -static int -cue_detach(device_t dev) -{ - struct cue_softc *sc; - struct ifnet *ifp; - - sc = device_get_softc(dev); - CUE_LOCK(sc); - ifp = &sc->arpcom.ac_if; - - sc->cue_dying = 1; - callout_stop(&sc->cue_stat_timer); - ether_ifdetach(ifp); - - if (sc->cue_ep[CUE_ENDPT_TX] != NULL) - usbd_abort_pipe(sc->cue_ep[CUE_ENDPT_TX]); - if (sc->cue_ep[CUE_ENDPT_RX] != NULL) - usbd_abort_pipe(sc->cue_ep[CUE_ENDPT_RX]); - if (sc->cue_ep[CUE_ENDPT_INTR] != NULL) - usbd_abort_pipe(sc->cue_ep[CUE_ENDPT_INTR]); - - CUE_UNLOCK(sc); - - return(0); -} - -/* - * Initialize an RX descriptor and attach an MBUF cluster. - */ -static int -cue_newbuf(struct cue_softc *sc, struct cue_chain *c, struct mbuf *m) -{ - struct mbuf *m_new = NULL; - - if (m == NULL) { - MGETHDR(m_new, MB_DONTWAIT, MT_DATA); - if (m_new == NULL) { - if_printf(&sc->arpcom.ac_if, "no memory for rx list " - "-- packet dropped!\n"); - return(ENOBUFS); - } - - MCLGET(m_new, MB_DONTWAIT); - if (!(m_new->m_flags & M_EXT)) { - if_printf(&sc->arpcom.ac_if, "no memory for rx list " - "-- packet dropped!\n"); - m_freem(m_new); - return(ENOBUFS); - } - m_new->m_len = m_new->m_pkthdr.len = MCLBYTES; - } else { - m_new = m; - m_new->m_len = m_new->m_pkthdr.len = MCLBYTES; - m_new->m_data = m_new->m_ext.ext_buf; - } - - m_adj(m_new, ETHER_ALIGN); - c->cue_mbuf = m_new; - - return(0); -} - -static int -cue_rx_list_init(struct cue_softc *sc) -{ - struct cue_cdata *cd; - struct cue_chain *c; - int i; - - cd = &sc->cue_cdata; - for (i = 0; i < CUE_RX_LIST_CNT; i++) { - c = &cd->cue_rx_chain[i]; - c->cue_sc = sc; - c->cue_idx = i; - if (cue_newbuf(sc, c, NULL) == ENOBUFS) - return(ENOBUFS); - if (c->cue_xfer == NULL) { - c->cue_xfer = usbd_alloc_xfer(sc->cue_udev); - if (c->cue_xfer == NULL) - return(ENOBUFS); - } - } - - return(0); -} - -static int -cue_tx_list_init(struct cue_softc *sc) -{ - struct cue_cdata *cd; - struct cue_chain *c; - int i; - - cd = &sc->cue_cdata; - for (i = 0; i < CUE_TX_LIST_CNT; i++) { - c = &cd->cue_tx_chain[i]; - c->cue_sc = sc; - c->cue_idx = i; - c->cue_mbuf = NULL; - if (c->cue_xfer == NULL) { - c->cue_xfer = usbd_alloc_xfer(sc->cue_udev); - if (c->cue_xfer == NULL) - return(ENOBUFS); - } - c->cue_buf = kmalloc(CUE_BUFSZ, M_USBDEV, M_WAITOK); - } - - return(0); -} - -static void -cue_rxstart(struct ifnet *ifp) -{ - struct cue_softc *sc; - struct cue_chain *c; - - sc = ifp->if_softc; - CUE_LOCK(sc); - c = &sc->cue_cdata.cue_rx_chain[sc->cue_cdata.cue_rx_prod]; - - if (cue_newbuf(sc, c, NULL) == ENOBUFS) { - IFNET_STAT_INC(ifp, ierrors, 1); - CUE_UNLOCK(sc); - return; - } - - /* Setup new transfer. */ - usbd_setup_xfer(c->cue_xfer, sc->cue_ep[CUE_ENDPT_RX], - c, mtod(c->cue_mbuf, char *), CUE_BUFSZ, USBD_SHORT_XFER_OK, - USBD_NO_TIMEOUT, cue_rxeof); - usbd_transfer(c->cue_xfer); - CUE_UNLOCK(sc); - - return; -} - -/* - * A frame has been uploaded: pass the resulting mbuf chain up to - * the higher level protocols. - */ -static void -cue_rxeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status) -{ - struct cue_softc *sc; - struct cue_chain *c; - struct mbuf *m; - struct ifnet *ifp; - int total_len = 0; - u_int16_t len; - - c = priv; - sc = c->cue_sc; - CUE_LOCK(sc); - ifp = &sc->arpcom.ac_if; - - if (!(ifp->if_flags & IFF_RUNNING)) { - CUE_UNLOCK(sc); - return; - } - - if (status != USBD_NORMAL_COMPLETION) { - if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) { - CUE_UNLOCK(sc); - return; - } - if (usbd_ratecheck(&sc->cue_rx_notice)) { - if_printf(ifp, "usb error on rx: %s\n", - usbd_errstr(status)); - } - if (status == USBD_STALLED) - usbd_clear_endpoint_stall(sc->cue_ep[CUE_ENDPT_RX]); - goto done; - } - - usbd_get_xfer_status(xfer, NULL, NULL, &total_len, NULL); - - m = c->cue_mbuf; - len = *mtod(m, u_int16_t *); - - /* No errors; receive the packet. */ - total_len = len; - - if (len < sizeof(struct ether_header)) { - IFNET_STAT_INC(ifp, ierrors, 1); - goto done; - } - - IFNET_STAT_INC(ifp, ipackets, 1); - m_adj(m, sizeof(u_int16_t)); - m->m_pkthdr.rcvif = ifp; - m->m_pkthdr.len = m->m_len = total_len; - - /* Put the packet on the special USB input queue. */ - usb_ether_input(m); - cue_rxstart(ifp); - - CUE_UNLOCK(sc); - - return; -done: - /* Setup new transfer. */ - usbd_setup_xfer(c->cue_xfer, sc->cue_ep[CUE_ENDPT_RX], - c, mtod(c->cue_mbuf, char *), CUE_BUFSZ, USBD_SHORT_XFER_OK, - USBD_NO_TIMEOUT, cue_rxeof); - usbd_transfer(c->cue_xfer); - CUE_UNLOCK(sc); - - return; -} - -/* - * A frame was downloaded to the chip. It's safe for us to clean up - * the list buffers. - */ - -static void -cue_txeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status) -{ - struct cue_softc *sc; - struct cue_chain *c; - struct ifnet *ifp; - usbd_status err; - - c = priv; - sc = c->cue_sc; - CUE_LOCK(sc); - ifp = &sc->arpcom.ac_if; - - if (status != USBD_NORMAL_COMPLETION) { - if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) { - CUE_UNLOCK(sc); - return; - } - if_printf(ifp, "usb error on tx: %s\n", usbd_errstr(status)); - if (status == USBD_STALLED) - usbd_clear_endpoint_stall(sc->cue_ep[CUE_ENDPT_TX]); - CUE_UNLOCK(sc); - return; - } - - ifp->if_timer = 0; - ifq_clr_oactive(&ifp->if_snd); - usbd_get_xfer_status(c->cue_xfer, NULL, NULL, NULL, &err); - - if (c->cue_mbuf != NULL) { - m_freem(c->cue_mbuf); - c->cue_mbuf = NULL; - } - - if (err) - IFNET_STAT_INC(ifp, oerrors, 1); - else - IFNET_STAT_INC(ifp, opackets, 1); - - if (!ifq_is_empty(&ifp->if_snd)) - if_devstart(ifp); - - CUE_UNLOCK(sc); - - return; -} - -static void -cue_tick(void *xsc) -{ - struct cue_softc *sc; - struct ifnet *ifp; - - sc = xsc; - - if (sc == NULL) - return; - - CUE_LOCK(sc); - - ifp = &sc->arpcom.ac_if; - - IFNET_STAT_INC(ifp, collisions, - cue_csr_read_2(sc, CUE_TX_SINGLECOLL)); - IFNET_STAT_INC(ifp, collisions, - cue_csr_read_2(sc, CUE_TX_MULTICOLL)); - IFNET_STAT_INC(ifp, collisions, - cue_csr_read_2(sc, CUE_TX_EXCESSCOLL)); - - if (cue_csr_read_2(sc, CUE_RX_FRAMEERR)) - IFNET_STAT_INC(ifp, ierrors, 1); - - callout_reset(&sc->cue_stat_timer, hz, cue_tick, sc); - - CUE_UNLOCK(sc); - - return; -} - -static int -cue_encap(struct cue_softc *sc, struct mbuf *m, int idx) -{ - int total_len; - struct cue_chain *c; - usbd_status err; - - c = &sc->cue_cdata.cue_tx_chain[idx]; - - /* - * Copy the mbuf data into a contiguous buffer, leaving two - * bytes at the beginning to hold the frame length. - */ - m_copydata(m, 0, m->m_pkthdr.len, c->cue_buf + 2); - c->cue_mbuf = m; - - total_len = m->m_pkthdr.len + 2; - - /* The first two bytes are the frame length */ - c->cue_buf[0] = (u_int8_t)m->m_pkthdr.len; - c->cue_buf[1] = (u_int8_t)(m->m_pkthdr.len >> 8); - - usbd_setup_xfer(c->cue_xfer, sc->cue_ep[CUE_ENDPT_TX], - c, c->cue_buf, total_len, 0, 10000, cue_txeof); - - /* Transmit */ - err = usbd_transfer(c->cue_xfer); - if (err != USBD_IN_PROGRESS) { - cue_stop(sc); - return(EIO); - } - - sc->cue_cdata.cue_tx_cnt++; - - return(0); -} - -static void -cue_start(struct ifnet *ifp, struct ifaltq_subque *ifsq) -{ - struct cue_softc *sc; - struct mbuf *m_head = NULL; - - ASSERT_ALTQ_SQ_DEFAULT(ifp, ifsq); - - sc = ifp->if_softc; - CUE_LOCK(sc); - - if (ifq_is_oactive(&ifp->if_snd)) { - CUE_UNLOCK(sc); - return; - } - - m_head = ifq_dequeue(&ifp->if_snd); - if (m_head == NULL) { - CUE_UNLOCK(sc); - return; - } - - if (cue_encap(sc, m_head, 0)) { - /* cue_encap() will free m_head, if we reach here */ - ifq_set_oactive(&ifp->if_snd); - CUE_UNLOCK(sc); - return; - } - - /* - * If there's a BPF listener, bounce a copy of this frame - * to him. - */ - BPF_MTAP(ifp, m_head); - - ifq_set_oactive(&ifp->if_snd); - - /* - * Set a timeout in case the chip goes out to lunch. - */ - ifp->if_timer = 5; - CUE_UNLOCK(sc); - - return; -} - -static void -cue_init(void *xsc) -{ - struct cue_softc *sc = xsc; - struct ifnet *ifp = &sc->arpcom.ac_if; - struct cue_chain *c; - usbd_status err; - int i; - - if (ifp->if_flags & IFF_RUNNING) - return; - - CUE_LOCK(sc); - - /* - * Cancel pending I/O and free all RX/TX buffers. - */ -#ifdef foo - cue_reset(sc); -#endif - - /* Set MAC address */ - for (i = 0; i < ETHER_ADDR_LEN; i++) - cue_csr_write_1(sc, CUE_PAR0 - i, sc->arpcom.ac_enaddr[i]); - - /* Enable RX logic. */ - cue_csr_write_1(sc, CUE_ETHCTL, CUE_ETHCTL_RX_ON|CUE_ETHCTL_MCAST_ON); - - /* If we want promiscuous mode, set the allframes bit. */ - if (ifp->if_flags & IFF_PROMISC) { - CUE_SETBIT(sc, CUE_ETHCTL, CUE_ETHCTL_PROMISC); - } else { - CUE_CLRBIT(sc, CUE_ETHCTL, CUE_ETHCTL_PROMISC); - } - - /* Init TX ring. */ - if (cue_tx_list_init(sc) == ENOBUFS) { - if_printf(ifp, "tx list init failed\n"); - CUE_UNLOCK(sc); - return; - } - - /* Init RX ring. */ - if (cue_rx_list_init(sc) == ENOBUFS) { - if_printf(ifp, "rx list init failed\n"); - CUE_UNLOCK(sc); - return; - } - - /* Load the multicast filter. */ - cue_setmulti(sc); - - /* - * Set the number of RX and TX buffers that we want - * to reserve inside the ASIC. - */ - cue_csr_write_1(sc, CUE_RX_BUFPKTS, CUE_RX_FRAMES); - cue_csr_write_1(sc, CUE_TX_BUFPKTS, CUE_TX_FRAMES); - - /* Set advanced operation modes. */ - cue_csr_write_1(sc, CUE_ADVANCED_OPMODES, - CUE_AOP_EMBED_RXLEN|0x01); /* 1 wait state */ - - /* Program the LED operation. */ - cue_csr_write_1(sc, CUE_LEDCTL, CUE_LEDCTL_FOLLOW_LINK); - - /* Open RX and TX pipes. */ - err = usbd_open_pipe(sc->cue_iface, sc->cue_ed[CUE_ENDPT_RX], - USBD_EXCLUSIVE_USE, &sc->cue_ep[CUE_ENDPT_RX]); - if (err) { - if_printf(ifp, "open rx pipe failed: %s\n", usbd_errstr(err)); - CUE_UNLOCK(sc); - return; - } - err = usbd_open_pipe(sc->cue_iface, sc->cue_ed[CUE_ENDPT_TX], - USBD_EXCLUSIVE_USE, &sc->cue_ep[CUE_ENDPT_TX]); - if (err) { - if_printf(ifp, "open tx pipe failed: %s\n", usbd_errstr(err)); - CUE_UNLOCK(sc); - return; - } - - /* Start up the receive pipe. */ - for (i = 0; i < CUE_RX_LIST_CNT; i++) { - c = &sc->cue_cdata.cue_rx_chain[i]; - usbd_setup_xfer(c->cue_xfer, sc->cue_ep[CUE_ENDPT_RX], - c, mtod(c->cue_mbuf, char *), CUE_BUFSZ, - USBD_SHORT_XFER_OK, USBD_NO_TIMEOUT, cue_rxeof); - usbd_transfer(c->cue_xfer); - } - - ifp->if_flags |= IFF_RUNNING; - ifq_clr_oactive(&ifp->if_snd); - - CUE_UNLOCK(sc); - - callout_reset(&sc->cue_stat_timer, hz, cue_tick, sc); -} - -static int -cue_ioctl(struct ifnet *ifp, u_long command, caddr_t data, struct ucred *cr) -{ - struct cue_softc *sc = ifp->if_softc; - int error = 0; - - CUE_LOCK(sc); - - switch(command) { - case SIOCSIFFLAGS: - if (ifp->if_flags & IFF_UP) { - if (ifp->if_flags & IFF_RUNNING && - ifp->if_flags & IFF_PROMISC && - !(sc->cue_if_flags & IFF_PROMISC)) { - CUE_SETBIT(sc, CUE_ETHCTL, CUE_ETHCTL_PROMISC); - cue_setmulti(sc); - } else if (ifp->if_flags & IFF_RUNNING && - !(ifp->if_flags & IFF_PROMISC) && - sc->cue_if_flags & IFF_PROMISC) { - CUE_CLRBIT(sc, CUE_ETHCTL, CUE_ETHCTL_PROMISC); - cue_setmulti(sc); - } else if (!(ifp->if_flags & IFF_RUNNING)) - cue_init(sc); - } else { - if (ifp->if_flags & IFF_RUNNING) - cue_stop(sc); - } - sc->cue_if_flags = ifp->if_flags; - error = 0; - break; - case SIOCADDMULTI: - case SIOCDELMULTI: - cue_setmulti(sc); - error = 0; - break; - default: - error = ether_ioctl(ifp, command, data); - break; - } - - CUE_UNLOCK(sc); - - return(error); -} - -static void -cue_watchdog(struct ifnet *ifp) -{ - struct cue_softc *sc; - struct cue_chain *c; - usbd_status stat; - - sc = ifp->if_softc; - CUE_LOCK(sc); - - IFNET_STAT_INC(ifp, oerrors, 1); - if_printf(ifp, "watchdog timeout\n"); - - c = &sc->cue_cdata.cue_tx_chain[0]; - usbd_get_xfer_status(c->cue_xfer, NULL, NULL, NULL, &stat); - cue_txeof(c->cue_xfer, c, stat); - - if (!ifq_is_empty(&ifp->if_snd)) - if_devstart(ifp); - CUE_UNLOCK(sc); - - return; -} - -/* - * Stop the adapter and free any mbufs allocated to the - * RX and TX lists. - */ -static void -cue_stop(struct cue_softc *sc) -{ - usbd_status err; - struct ifnet *ifp; - int i; - - CUE_LOCK(sc); - - ifp = &sc->arpcom.ac_if; - ifp->if_timer = 0; - - cue_csr_write_1(sc, CUE_ETHCTL, 0); - cue_reset(sc); - callout_stop(&sc->cue_stat_timer); - - /* Stop transfers. */ - if (sc->cue_ep[CUE_ENDPT_RX] != NULL) { - err = usbd_abort_pipe(sc->cue_ep[CUE_ENDPT_RX]); - if (err) { - if_printf(ifp, "abort rx pipe failed: %s\n", - usbd_errstr(err)); - } - err = usbd_close_pipe(sc->cue_ep[CUE_ENDPT_RX]); - if (err) { - if_printf(ifp, "close rx pipe failed: %s\n", - usbd_errstr(err)); - } - sc->cue_ep[CUE_ENDPT_RX] = NULL; - } - - if (sc->cue_ep[CUE_ENDPT_TX] != NULL) { - err = usbd_abort_pipe(sc->cue_ep[CUE_ENDPT_TX]); - if (err) { - if_printf(ifp, "abort tx pipe failed: %s\n", - usbd_errstr(err)); - } - err = usbd_close_pipe(sc->cue_ep[CUE_ENDPT_TX]); - if (err) { - if_printf(ifp, "close tx pipe failed: %s\n", - usbd_errstr(err)); - } - sc->cue_ep[CUE_ENDPT_TX] = NULL; - } - - if (sc->cue_ep[CUE_ENDPT_INTR] != NULL) { - err = usbd_abort_pipe(sc->cue_ep[CUE_ENDPT_INTR]); - if (err) { - if_printf(ifp, "abort intr pipe failed: %s\n", - usbd_errstr(err)); - } - err = usbd_close_pipe(sc->cue_ep[CUE_ENDPT_INTR]); - if (err) { - if_printf(ifp, "close intr pipe failed: %s\n", - usbd_errstr(err)); - } - sc->cue_ep[CUE_ENDPT_INTR] = NULL; - } - - /* Free RX resources. */ - for (i = 0; i < CUE_RX_LIST_CNT; i++) { - if (sc->cue_cdata.cue_rx_chain[i].cue_buf != NULL) { - kfree(sc->cue_cdata.cue_rx_chain[i].cue_buf, M_USBDEV); - sc->cue_cdata.cue_rx_chain[i].cue_buf = NULL; - } - if (sc->cue_cdata.cue_rx_chain[i].cue_mbuf != NULL) { - m_freem(sc->cue_cdata.cue_rx_chain[i].cue_mbuf); - sc->cue_cdata.cue_rx_chain[i].cue_mbuf = NULL; - } - if (sc->cue_cdata.cue_rx_chain[i].cue_xfer != NULL) { - usbd_free_xfer(sc->cue_cdata.cue_rx_chain[i].cue_xfer); - sc->cue_cdata.cue_rx_chain[i].cue_xfer = NULL; - } - } - - /* Free TX resources. */ - for (i = 0; i < CUE_TX_LIST_CNT; i++) { - if (sc->cue_cdata.cue_tx_chain[i].cue_buf != NULL) { - kfree(sc->cue_cdata.cue_tx_chain[i].cue_buf, M_USBDEV); - sc->cue_cdata.cue_tx_chain[i].cue_buf = NULL; - } - if (sc->cue_cdata.cue_tx_chain[i].cue_mbuf != NULL) { - m_freem(sc->cue_cdata.cue_tx_chain[i].cue_mbuf); - sc->cue_cdata.cue_tx_chain[i].cue_mbuf = NULL; - } - if (sc->cue_cdata.cue_tx_chain[i].cue_xfer != NULL) { - usbd_free_xfer(sc->cue_cdata.cue_tx_chain[i].cue_xfer); - sc->cue_cdata.cue_tx_chain[i].cue_xfer = NULL; - } - } - - ifp->if_flags &= ~IFF_RUNNING; - ifq_clr_oactive(&ifp->if_snd); - CUE_UNLOCK(sc); - - return; -} - -/* - * Stop all chip I/O so that the kernel's probe routines don't - * get confused by errant DMAs when rebooting. - */ -static void -cue_shutdown(device_t dev) -{ - struct cue_softc *sc; - - sc = device_get_softc(dev); - - CUE_LOCK(sc); - cue_reset(sc); - cue_stop(sc); - CUE_UNLOCK(sc); - - return; -} diff --git a/sys/dev/netif/cue/if_cuereg.h b/sys/dev/netif/cue/if_cuereg.h deleted file mode 100644 index df8cfbb791..0000000000 --- a/sys/dev/netif/cue/if_cuereg.h +++ /dev/null @@ -1,180 +0,0 @@ -/* - * Copyright (c) 1997, 1998, 1999, 2000 - * Bill Paul . 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. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Bill Paul. - * 4. Neither the name of the author nor the names of any co-contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY Bill Paul 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 Bill Paul OR THE VOICES IN HIS HEAD - * 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: src/sys/dev/usb/if_cuereg.h,v 1.12 2003/10/04 21:41:01 joe Exp $ - * $DragonFly: src/sys/dev/netif/cue/if_cuereg.h,v 1.8 2007/11/05 13:32:27 hasso Exp $ - */ - -/* - * Definitions for the CATC Netmate II USB to ethernet controller. - */ - - -/* - * Vendor specific control commands. - */ -#define CUE_CMD_RESET 0xF4 -#define CUE_CMD_GET_MACADDR 0xF2 -#define CUE_CMD_WRITEREG 0xFA -#define CUE_CMD_READREG 0xFB -#define CUE_CMD_READSRAM 0xF1 -#define CUE_CMD_WRITESRAM 0xFC - -/* - * Internal registers - */ -#define CUE_TX_BUFCNT 0x20 -#define CUE_RX_BUFCNT 0x21 -#define CUE_ADVANCED_OPMODES 0x22 -#define CUE_TX_BUFPKTS 0x23 -#define CUE_RX_BUFPKTS 0x24 -#define CUE_RX_MAXCHAIN 0x25 - -#define CUE_ETHCTL 0x60 -#define CUE_ETHSTS 0x61 -#define CUE_PAR5 0x62 -#define CUE_PAR4 0x63 -#define CUE_PAR3 0x64 -#define CUE_PAR2 0x65 -#define CUE_PAR1 0x66 -#define CUE_PAR0 0x67 - -/* Error counters, all 16 bits wide. */ -#define CUE_TX_SINGLECOLL 0x69 -#define CUE_TX_MULTICOLL 0x6B -#define CUE_TX_EXCESSCOLL 0x6D -#define CUE_RX_FRAMEERR 0x6F - -#define CUE_LEDCTL 0x81 - -/* Advenced operating mode register */ -#define CUE_AOP_SRAMWAITS 0x03 -#define CUE_AOP_EMBED_RXLEN 0x08 -#define CUE_AOP_RXCOMBINE 0x10 -#define CUE_AOP_TXCOMBINE 0x20 -#define CUE_AOP_EVEN_PKT_READS 0x40 -#define CUE_AOP_LOOPBK 0x80 - -/* Ethernet control register */ -#define CUE_ETHCTL_RX_ON 0x01 -#define CUE_ETHCTL_LINK_POLARITY 0x02 -#define CUE_ETHCTL_LINK_FORCE_OK 0x04 -#define CUE_ETHCTL_MCAST_ON 0x08 -#define CUE_ETHCTL_PROMISC 0x10 - -/* Ethernet status register */ -#define CUE_ETHSTS_NO_CARRIER 0x01 -#define CUE_ETHSTS_LATECOLL 0x02 -#define CUE_ETHSTS_EXCESSCOLL 0x04 -#define CUE_ETHSTS_TXBUF_AVAIL 0x08 -#define CUE_ETHSTS_BAD_POLARITY 0x10 -#define CUE_ETHSTS_LINK_OK 0x20 - -/* LED control register */ -#define CUE_LEDCTL_BLINK_1X 0x00 -#define CUE_LEDCTL_BLINK_2X 0x01 -#define CUE_LEDCTL_BLINK_QUARTER_ON 0x02 -#define CUE_LEDCTL_BLINK_QUARTER_OFF 0x03 -#define CUE_LEDCTL_OFF 0x04 -#define CUE_LEDCTL_FOLLOW_LINK 0x08 - -/* - * Address in ASIC's internal SRAM where the - * multicast hash table lives. The table is 64 bytes long, - * giving us a 512-bit table. We have to set the bit that - * corresponds to the broadcast address in order to enable - * reception of broadcast frames. - */ -#define CUE_MCAST_TABLE_ADDR 0xFA80 -#define CUE_MCAST_TABLE_LEN 64 - -#define CUE_TIMEOUT 1000 -#define CUE_BUFSZ 1536 -#define CUE_MIN_FRAMELEN 60 -#define CUE_RX_FRAMES 1 -#define CUE_TX_FRAMES 1 - -#define CUE_RX_LIST_CNT 1 -#define CUE_TX_LIST_CNT 1 - -#define CUE_CTL_READ 0x01 -#define CUE_CTL_WRITE 0x02 - -#define CUE_CONFIG_NO 1 - -/* - * The interrupt endpoint is currently unused - * by the KLSI part. - */ -#define CUE_ENDPT_RX 0x0 -#define CUE_ENDPT_TX 0x1 -#define CUE_ENDPT_INTR 0x2 -#define CUE_ENDPT_MAX 0x3 - -struct cue_softc; - -struct cue_chain { - struct cue_softc *cue_sc; - usbd_xfer_handle cue_xfer; - char *cue_buf; - struct mbuf *cue_mbuf; - int cue_accum; - int cue_idx; -}; - -struct cue_cdata { - struct cue_chain cue_tx_chain[CUE_TX_LIST_CNT]; - struct cue_chain cue_rx_chain[CUE_RX_LIST_CNT]; - int cue_tx_prod; - int cue_tx_cons; - int cue_tx_cnt; - int cue_rx_prod; -}; - -#define CUE_INC(x, y) (x) = (x + 1) % y - -struct cue_softc { - struct arpcom arpcom; - usbd_device_handle cue_udev; - usbd_interface_handle cue_iface; - int cue_ed[CUE_ENDPT_MAX]; - usbd_pipe_handle cue_ep[CUE_ENDPT_MAX]; - u_int8_t cue_mctab[CUE_MCAST_TABLE_LEN]; - int cue_if_flags; - u_int16_t cue_rxfilt; - struct cue_cdata cue_cdata; - struct callout cue_stat_timer; - char cue_dying; - struct timeval cue_rx_notice; -}; - -#define CUE_LOCK(_sc) -#define CUE_UNLOCK(_sc) diff --git a/sys/dev/netif/kue/Makefile b/sys/dev/netif/kue/Makefile deleted file mode 100644 index e98976d528..0000000000 --- a/sys/dev/netif/kue/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -# $FreeBSD: src/sys/modules/kue/Makefile,v 1.2 2000/01/28 11:26:30 bde Exp $ -# $DragonFly: src/sys/dev/netif/kue/Makefile,v 1.5 2006/11/18 10:00:19 swildner Exp $ - -S = ${.CURDIR}/../.. -KMOD = if_kue -SRCS = if_kue.c opt_usb.h device_if.h bus_if.h - -.include diff --git a/sys/dev/netif/kue/if_kue.c b/sys/dev/netif/kue/if_kue.c deleted file mode 100644 index e58cbe1972..0000000000 --- a/sys/dev/netif/kue/if_kue.c +++ /dev/null @@ -1,1105 +0,0 @@ -/* - * Copyright (c) 1997, 1998, 1999, 2000 - * Bill Paul . 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. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Bill Paul. - * 4. Neither the name of the author nor the names of any co-contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY Bill Paul 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 Bill Paul OR THE VOICES IN HIS HEAD - * 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: src/sys/dev/usb/if_kue.c,v 1.17.2.9 2003/04/13 02:39:25 murray Exp $ - */ - -/* - * Kawasaki LSI KL5KUSB101B USB to ethernet adapter driver. - * - * Written by Bill Paul - * Electrical Engineering Department - * Columbia University, New York City - */ - -/* - * The KLSI USB to ethernet adapter chip contains an USB serial interface, - * ethernet MAC and embedded microcontroller (called the QT Engine). - * The chip must have firmware loaded into it before it will operate. - * Packets are passed between the chip and host via bulk transfers. - * There is an interrupt endpoint mentioned in the software spec, however - * it's currently unused. This device is 10Mbps half-duplex only, hence - * there is no media selection logic. The MAC supports a 128 entry - * multicast filter, though the exact size of the filter can depend - * on the firmware. Curiously, while the software spec describes various - * ethernet statistics counters, my sample adapter and firmware combination - * claims not to support any statistics counters at all. - * - * Note that once we load the firmware in the device, we have to be - * careful not to load it again: if you restart your computer but - * leave the adapter attached to the USB controller, it may remain - * powered on and retain its firmware. In this case, we don't need - * to load the firmware a second time. - * - * Special thanks to Rob Furr for providing an ADS Technologies - * adapter for development and testing. No monkeys were harmed during - * the development of this driver. - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include - -#include -#include -#include -#include -#include - -#include "if_kuereg.h" -#include - -MODULE_DEPEND(kue, usb, 1, 1, 1); - -/* - * Various supported device vendors/products. - */ -static const struct usb_devno kue_devs[] = { - { USB_DEVICE(0x03e8, 0x0008) }, /* AOX USB101 */ - { USB_DEVICE(0x04bb, 0x0901) }, /* I-O DATA USBETT */ - { USB_DEVICE(0x0506, 0x03e8) }, /* 3Com 3C19250 */ - { USB_DEVICE(0x0557, 0x2002) }, /* ATen UC10T */ - { USB_DEVICE(0x0565, 0x0002) }, /* Peracom Ethernet adapter */ - { USB_DEVICE(0x0565, 0x0003) }, /* Peracom Ethernet adapter*/ - { USB_DEVICE(0x0565, 0x0005) }, /* Peracom Ethernet adapter */ - { USB_DEVICE(0x05e9, 0x0008) }, /* AOX (rebranded Kawasaki?) USB101*/ - { USB_DEVICE(0x05e9, 0x0008) }, /* Kawasaki LSI DUH3E10BT */ - { USB_DEVICE(0x05e9, 0x0009) }, /* Kawasaki LSI DUH3E10BTN */ - { USB_DEVICE(0x066b, 0x2202) }, /* Linksys USB10T */ - { USB_DEVICE(0x06e1, 0x0008) }, /* ADS UBS-10BT */ - { USB_DEVICE(0x0707, 0x0100) }, /* SMC 2102USB */ - { USB_DEVICE(0x07aa, 0x0001) }, /* Corega USB-T*/ - { USB_DEVICE(0x07b8, 0x4000) }, /* AboCom URE450 */ - { USB_DEVICE(0x0846, 0x1001) }, /* Netgear EA101 */ - { USB_DEVICE(0x1645, 0x0005) }, /* Entrega E45*/ - { USB_DEVICE(0x2001, 0x4000) }, /* D-Link DSB650C */ -}; - -static int kue_match(device_t); -static int kue_attach(device_t); -static int kue_detach(device_t); -static void kue_shutdown(device_t); -static int kue_tx_list_init(struct kue_softc *); -static int kue_rx_list_init(struct kue_softc *); -static int kue_newbuf(struct kue_softc *, struct kue_chain *, struct mbuf *); -static int kue_encap(struct kue_softc *, struct mbuf *, int); -static void kue_rxeof(usbd_xfer_handle, usbd_private_handle, usbd_status); -static void kue_txeof(usbd_xfer_handle, usbd_private_handle, usbd_status); -static void kue_start(struct ifnet *, struct ifaltq_subque *); -static void kue_rxstart(struct ifnet *); -static int kue_ioctl(struct ifnet *, u_long, caddr_t, struct ucred *); -static void kue_init(void *); -static void kue_stop(struct kue_softc *); -static void kue_watchdog(struct ifnet *); - -static void kue_setmulti(struct kue_softc *); -static void kue_reset(struct kue_softc *); - -static usbd_status kue_do_request(usbd_device_handle, - usb_device_request_t *, void *); -static usbd_status kue_ctl(struct kue_softc *, int, u_int8_t, - u_int16_t, char *, int); -static usbd_status kue_setword(struct kue_softc *, u_int8_t, u_int16_t); -static int kue_load_fw(struct kue_softc *); - -static device_method_t kue_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, kue_match), - DEVMETHOD(device_attach, kue_attach), - DEVMETHOD(device_detach, kue_detach), - DEVMETHOD(device_shutdown, kue_shutdown), - - DEVMETHOD_END -}; - -static driver_t kue_driver = { - "kue", - kue_methods, - sizeof(struct kue_softc) -}; - -static devclass_t kue_devclass; - -DECLARE_DUMMY_MODULE(if_kue); -DRIVER_MODULE(kue, uhub, kue_driver, kue_devclass, usbd_driver_load, NULL); - -/* - * We have a custom do_request function which is almost like the - * regular do_request function, except it has a much longer timeout. - * Why? Because we need to make requests over the control endpoint - * to download the firmware to the device, which can take longer - * than the default timeout. - */ -static usbd_status -kue_do_request(usbd_device_handle dev, usb_device_request_t *req, void *data) -{ - usbd_xfer_handle xfer; - usbd_status err; - - xfer = usbd_alloc_xfer(dev); - usbd_setup_default_xfer(xfer, dev, 0, 500000, req, - data, UGETW(req->wLength), USBD_SHORT_XFER_OK, 0); - err = usbd_sync_transfer(xfer); - usbd_free_xfer(xfer); - return(err); -} - -static usbd_status -kue_setword(struct kue_softc *sc, u_int8_t breq, u_int16_t word) -{ - usbd_device_handle dev; - usb_device_request_t req; - usbd_status err; - - if (sc->kue_dying) - return(USBD_NORMAL_COMPLETION); - - dev = sc->kue_udev; - - KUE_LOCK(sc); - - req.bmRequestType = UT_WRITE_VENDOR_DEVICE; - - req.bRequest = breq; - USETW(req.wValue, word); - USETW(req.wIndex, 0); - USETW(req.wLength, 0); - - err = kue_do_request(dev, &req, NULL); - - KUE_UNLOCK(sc); - - return(err); -} - -static usbd_status -kue_ctl(struct kue_softc *sc, int rw, u_int8_t breq, u_int16_t val, - char *data, int len) -{ - usbd_device_handle dev; - usb_device_request_t req; - usbd_status err; - - dev = sc->kue_udev; - - if (sc->kue_dying) - return(USBD_NORMAL_COMPLETION); - - KUE_LOCK(sc); - - if (rw == KUE_CTL_WRITE) - req.bmRequestType = UT_WRITE_VENDOR_DEVICE; - else - req.bmRequestType = UT_READ_VENDOR_DEVICE; - - req.bRequest = breq; - USETW(req.wValue, val); - USETW(req.wIndex, 0); - USETW(req.wLength, len); - - err = kue_do_request(dev, &req, data); - - KUE_UNLOCK(sc); - - return(err); -} - -static int -kue_load_fw(struct kue_softc *sc) -{ - usbd_status err; - usb_device_descriptor_t *dd; - int hwrev; - - dd = &sc->kue_udev->ddesc; - hwrev = UGETW(dd->bcdDevice); - - /* - * First, check if we even need to load the firmware. - * If the device was still attached when the system was - * rebooted, it may already have firmware loaded in it. - * If this is the case, we don't need to do it again. - * And in fact, if we try to load it again, we'll hang, - * so we have to avoid this condition if we don't want - * to look stupid. - * - * We can test this quickly by checking the bcdRevision - * code. The NIC will return a different revision code if - * it's probed while the firmware is still loaded and - * running. - */ - if (hwrev == 0x0202) - return(0); - - /* Load code segment */ - err = kue_ctl(sc, KUE_CTL_WRITE, KUE_CMD_SEND_SCAN, - 0, kue_code_seg, sizeof(kue_code_seg)); - if (err) { - kprintf("kue%d: failed to load code segment: %s\n", - sc->kue_unit, usbd_errstr(err)); - return(ENXIO); - } - - /* Load fixup segment */ - err = kue_ctl(sc, KUE_CTL_WRITE, KUE_CMD_SEND_SCAN, - 0, kue_fix_seg, sizeof(kue_fix_seg)); - if (err) { - kprintf("kue%d: failed to load fixup segment: %s\n", - sc->kue_unit, usbd_errstr(err)); - return(ENXIO); - } - - /* Send trigger command. */ - err = kue_ctl(sc, KUE_CTL_WRITE, KUE_CMD_SEND_SCAN, - 0, kue_trig_seg, sizeof(kue_trig_seg)); - if (err) { - kprintf("kue%d: failed to load trigger segment: %s\n", - sc->kue_unit, usbd_errstr(err)); - return(ENXIO); - } - - return(0); -} - -static void -kue_setmulti(struct kue_softc *sc) -{ - struct ifnet *ifp; - struct ifmultiaddr *ifma; - int i = 0; - - ifp = &sc->arpcom.ac_if; - - if (ifp->if_flags & IFF_ALLMULTI || ifp->if_flags & IFF_PROMISC) { - sc->kue_rxfilt |= KUE_RXFILT_ALLMULTI; - sc->kue_rxfilt &= ~KUE_RXFILT_MULTICAST; - kue_setword(sc, KUE_CMD_SET_PKT_FILTER, sc->kue_rxfilt); - return; - } - - sc->kue_rxfilt &= ~KUE_RXFILT_ALLMULTI; - - TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { - if (ifma->ifma_addr->sa_family != AF_LINK) - continue; - /* - * If there are too many addresses for the - * internal filter, switch over to allmulti mode. - */ - if (i == KUE_MCFILTCNT(sc)) - break; - bcopy(LLADDR((struct sockaddr_dl *)ifma->ifma_addr), - KUE_MCFILT(sc, i), ETHER_ADDR_LEN); - i++; - } - - if (i == KUE_MCFILTCNT(sc)) - sc->kue_rxfilt |= KUE_RXFILT_ALLMULTI; - else { - sc->kue_rxfilt |= KUE_RXFILT_MULTICAST; - kue_ctl(sc, KUE_CTL_WRITE, KUE_CMD_SET_MCAST_FILTERS, - i, sc->kue_mcfilters, i * ETHER_ADDR_LEN); - } - - kue_setword(sc, KUE_CMD_SET_PKT_FILTER, sc->kue_rxfilt); - - return; -} - -/* - * Issue a SET_CONFIGURATION command to reset the MAC. This should be - * done after the firmware is loaded into the adapter in order to - * bring it into proper operation. - */ -static void -kue_reset(struct kue_softc *sc) -{ - if (usbd_set_config_no(sc->kue_udev, KUE_CONFIG_NO, 0) || - usbd_device2interface_handle(sc->kue_udev, KUE_IFACE_IDX, - &sc->kue_iface)) { - kprintf("kue%d: getting interface handle failed\n", - sc->kue_unit); - } - - /* Wait a little while for the chip to get its brains in order. */ - DELAY(1000); - return; -} - -/* - * Probe for a KLSI chip. - */ -static int -kue_match(device_t self) -{ - struct usb_attach_arg *uaa = device_get_ivars(self); - - if (uaa->iface == NULL) - return(UMATCH_NONE); - - return (usb_lookup(kue_devs, uaa->vendor, uaa->product) != NULL ? - UMATCH_VENDOR_PRODUCT : UMATCH_NONE); -} - -/* - * Attach the interface. Allocate softc structures, do - * setup and ethernet/BPF attach. - */ -static int -kue_attach(device_t self) -{ - struct kue_softc *sc = device_get_softc(self); - struct usb_attach_arg *uaa = device_get_ivars(self); - struct ifnet *ifp; - usb_interface_descriptor_t *id; - usb_endpoint_descriptor_t *ed; - int i; - - sc->kue_iface = uaa->iface; - sc->kue_udev = uaa->device; - sc->kue_unit = device_get_unit(self); - - id = usbd_get_interface_descriptor(uaa->iface); - - /* Find endpoints. */ - for (i = 0; i < id->bNumEndpoints; i++) { - ed = usbd_interface2endpoint_descriptor(uaa->iface, i); - if (!ed) { - kprintf("kue%d: couldn't get ep %d\n", - sc->kue_unit, i); - return ENXIO; - } - if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && - UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) { - sc->kue_ed[KUE_ENDPT_RX] = ed->bEndpointAddress; - } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT && - UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) { - sc->kue_ed[KUE_ENDPT_TX] = ed->bEndpointAddress; - } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && - UE_GET_XFERTYPE(ed->bmAttributes) == UE_INTERRUPT) { - sc->kue_ed[KUE_ENDPT_INTR] = ed->bEndpointAddress; - } - } - -#if defined(__FreeBSD__) && __FreeBSD_version >= 500000 - mtx_init(&sc->kue_mtx, device_get_nameunit(self), MTX_NETWORK_LOCK, - MTX_DEF | MTX_RECURSE); -#endif - KUE_LOCK(sc); - - /* Load the firmware into the NIC. */ - if (kue_load_fw(sc)) { - KUE_UNLOCK(sc); -#if defined(__FreeBSD__) && __FreeBSD_version >= 500000 - mtx_destroy(&sc->kue_mtx); -#endif - return ENXIO; - } - - /* Reset the adapter. */ - kue_reset(sc); - - /* Read ethernet descriptor */ - kue_ctl(sc, KUE_CTL_READ, KUE_CMD_GET_ETHER_DESCRIPTOR, - 0, (char *)&sc->kue_desc, sizeof(sc->kue_desc)); - - sc->kue_mcfilters = kmalloc(KUE_MCFILTCNT(sc) * ETHER_ADDR_LEN, - M_USBDEV, M_WAITOK); - - ifp = &sc->arpcom.ac_if; - ifp->if_softc = sc; - if_initname(ifp, "kue", sc->kue_unit); - ifp->if_mtu = ETHERMTU; - ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; - ifp->if_ioctl = kue_ioctl; - ifp->if_start = kue_start; - ifp->if_watchdog = kue_watchdog; - ifp->if_init = kue_init; - ifp->if_baudrate = 10000000; - ifq_set_maxlen(&ifp->if_snd, IFQ_MAXLEN); - ifq_set_ready(&ifp->if_snd); - - /* - * Call MI attach routine. - */ - ether_ifattach(ifp, sc->kue_desc.kue_macaddr, NULL); - usb_register_netisr(); - sc->kue_dying = 0; - - KUE_UNLOCK(sc); - - return 0; -} - -static int -kue_detach(device_t dev) -{ - struct kue_softc *sc; - struct ifnet *ifp; - - sc = device_get_softc(dev); - KUE_LOCK(sc); - ifp = &sc->arpcom.ac_if; - - sc->kue_dying = 1; - - if (ifp != NULL) - ether_ifdetach(ifp); - - if (sc->kue_ep[KUE_ENDPT_TX] != NULL) - usbd_abort_pipe(sc->kue_ep[KUE_ENDPT_TX]); - if (sc->kue_ep[KUE_ENDPT_RX] != NULL) - usbd_abort_pipe(sc->kue_ep[KUE_ENDPT_RX]); - if (sc->kue_ep[KUE_ENDPT_INTR] != NULL) - usbd_abort_pipe(sc->kue_ep[KUE_ENDPT_INTR]); - - if (sc->kue_mcfilters != NULL) - kfree(sc->kue_mcfilters, M_USBDEV); - - KUE_UNLOCK(sc); -#if defined(__FreeBSD__) && __FreeBSD_version >= 500000 - mtx_destroy(&sc->kue_mtx); -#endif - - return(0); -} - -/* - * Initialize an RX descriptor and attach an MBUF cluster. - */ -static int -kue_newbuf(struct kue_softc *sc, struct kue_chain *c, struct mbuf *m) -{ - struct mbuf *m_new = NULL; - - if (m == NULL) { - MGETHDR(m_new, MB_DONTWAIT, MT_DATA); - if (m_new == NULL) { - kprintf("kue%d: no memory for rx list " - "-- packet dropped!\n", sc->kue_unit); - return(ENOBUFS); - } - - MCLGET(m_new, MB_DONTWAIT); - if (!(m_new->m_flags & M_EXT)) { - kprintf("kue%d: no memory for rx list " - "-- packet dropped!\n", sc->kue_unit); - m_freem(m_new); - return(ENOBUFS); - } - m_new->m_len = m_new->m_pkthdr.len = MCLBYTES; - } else { - m_new = m; - m_new->m_len = m_new->m_pkthdr.len = MCLBYTES; - m_new->m_data = m_new->m_ext.ext_buf; - } - - c->kue_mbuf = m_new; - - return(0); -} - -static int -kue_rx_list_init(struct kue_softc *sc) -{ - struct kue_cdata *cd; - struct kue_chain *c; - int i; - - cd = &sc->kue_cdata; - for (i = 0; i < KUE_RX_LIST_CNT; i++) { - c = &cd->kue_rx_chain[i]; - c->kue_sc = sc; - c->kue_idx = i; - if (kue_newbuf(sc, c, NULL) == ENOBUFS) - return(ENOBUFS); - if (c->kue_xfer == NULL) { - c->kue_xfer = usbd_alloc_xfer(sc->kue_udev); - if (c->kue_xfer == NULL) - return(ENOBUFS); - } - } - - return(0); -} - -static int -kue_tx_list_init(struct kue_softc *sc) -{ - struct kue_cdata *cd; - struct kue_chain *c; - int i; - - cd = &sc->kue_cdata; - for (i = 0; i < KUE_TX_LIST_CNT; i++) { - c = &cd->kue_tx_chain[i]; - c->kue_sc = sc; - c->kue_idx = i; - c->kue_mbuf = NULL; - if (c->kue_xfer == NULL) { - c->kue_xfer = usbd_alloc_xfer(sc->kue_udev); - if (c->kue_xfer == NULL) - return(ENOBUFS); - } - c->kue_buf = kmalloc(KUE_BUFSZ, M_USBDEV, M_WAITOK); - } - - return(0); -} - -static void -kue_rxstart(struct ifnet *ifp) -{ - struct kue_softc *sc; - struct kue_chain *c; - - sc = ifp->if_softc; - KUE_LOCK(sc); - c = &sc->kue_cdata.kue_rx_chain[sc->kue_cdata.kue_rx_prod]; - - if (kue_newbuf(sc, c, NULL) == ENOBUFS) { - IFNET_STAT_INC(ifp, ierrors, 1); - return; - } - - /* Setup new transfer. */ - usbd_setup_xfer(c->kue_xfer, sc->kue_ep[KUE_ENDPT_RX], - c, mtod(c->kue_mbuf, char *), KUE_BUFSZ, USBD_SHORT_XFER_OK, - USBD_NO_TIMEOUT, kue_rxeof); - usbd_transfer(c->kue_xfer); - - KUE_UNLOCK(sc); - - return; -} - -/* - * A frame has been uploaded: pass the resulting mbuf chain up to - * the higher level protocols. - */ -static void -kue_rxeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status) -{ - struct kue_softc *sc; - struct kue_chain *c; - struct mbuf *m; - struct ifnet *ifp; - int total_len = 0; - u_int16_t len; - - c = priv; - sc = c->kue_sc; - KUE_LOCK(sc); - ifp = &sc->arpcom.ac_if; - - if (!(ifp->if_flags & IFF_RUNNING)) { - KUE_UNLOCK(sc); - return; - } - - if (status != USBD_NORMAL_COMPLETION) { - if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) { - KUE_UNLOCK(sc); - return; - } - if (usbd_ratecheck(&sc->kue_rx_notice)) - kprintf("kue%d: usb error on rx: %s\n", sc->kue_unit, - usbd_errstr(status)); - if (status == USBD_STALLED) - usbd_clear_endpoint_stall(sc->kue_ep[KUE_ENDPT_RX]); - goto done; - } - - usbd_get_xfer_status(xfer, NULL, NULL, &total_len, NULL); - m = c->kue_mbuf; - if (total_len <= 1) - goto done; - - len = *mtod(m, u_int16_t *); - m_adj(m, sizeof(u_int16_t)); - - /* No errors; receive the packet. */ - total_len = len; - - if (len < sizeof(struct ether_header)) { - IFNET_STAT_INC(ifp, ierrors, 1); - goto done; - } - - IFNET_STAT_INC(ifp, ipackets, 1); - m->m_pkthdr.rcvif = ifp; - m->m_pkthdr.len = m->m_len = total_len; - - /* Put the packet on the special USB input queue. */ - usb_ether_input(m); - kue_rxstart(ifp); - - KUE_UNLOCK(sc); - - return; -done: - - /* Setup new transfer. */ - usbd_setup_xfer(c->kue_xfer, sc->kue_ep[KUE_ENDPT_RX], - c, mtod(c->kue_mbuf, char *), KUE_BUFSZ, USBD_SHORT_XFER_OK, - USBD_NO_TIMEOUT, kue_rxeof); - usbd_transfer(c->kue_xfer); - KUE_UNLOCK(sc); - - return; -} - -/* - * A frame was downloaded to the chip. It's safe for us to clean up - * the list buffers. - */ - -static void -kue_txeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status) -{ - struct kue_softc *sc; - struct kue_chain *c; - struct ifnet *ifp; - usbd_status err; - - c = priv; - sc = c->kue_sc; - KUE_LOCK(sc); - - ifp = &sc->arpcom.ac_if; - ifp->if_timer = 0; - ifq_clr_oactive(&ifp->if_snd); - - if (status != USBD_NORMAL_COMPLETION) { - if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) { - KUE_UNLOCK(sc); - return; - } - kprintf("kue%d: usb error on tx: %s\n", sc->kue_unit, - usbd_errstr(status)); - if (status == USBD_STALLED) - usbd_clear_endpoint_stall(sc->kue_ep[KUE_ENDPT_TX]); - KUE_UNLOCK(sc); - return; - } - - usbd_get_xfer_status(c->kue_xfer, NULL, NULL, NULL, &err); - - if (c->kue_mbuf != NULL) { - m_freem(c->kue_mbuf); - c->kue_mbuf = NULL; - } - - if (err) - IFNET_STAT_INC(ifp, oerrors, 1); - else - IFNET_STAT_INC(ifp, opackets, 1); - - if (!ifq_is_empty(&ifp->if_snd)) - if_devstart(ifp); - - KUE_UNLOCK(sc); - - return; -} - -static int -kue_encap(struct kue_softc *sc, struct mbuf *m, int idx) -{ - int total_len; - struct kue_chain *c; - usbd_status err; - - c = &sc->kue_cdata.kue_tx_chain[idx]; - - /* - * Copy the mbuf data into a contiguous buffer, leaving two - * bytes at the beginning to hold the frame length. - */ - m_copydata(m, 0, m->m_pkthdr.len, c->kue_buf + 2); - c->kue_mbuf = m; - - total_len = m->m_pkthdr.len + 2; - total_len += 64 - (total_len % 64); - - /* Frame length is specified in the first 2 bytes of the buffer. */ - c->kue_buf[0] = (u_int8_t)m->m_pkthdr.len; - c->kue_buf[1] = (u_int8_t)(m->m_pkthdr.len >> 8); - - usbd_setup_xfer(c->kue_xfer, sc->kue_ep[KUE_ENDPT_TX], - c, c->kue_buf, total_len, 0, 10000, kue_txeof); - - /* Transmit */ - err = usbd_transfer(c->kue_xfer); - if (err != USBD_IN_PROGRESS) { - kue_stop(sc); - return(EIO); - } - - sc->kue_cdata.kue_tx_cnt++; - - return(0); -} - -static void -kue_start(struct ifnet *ifp, struct ifaltq_subque *ifsq) -{ - struct kue_softc *sc; - struct mbuf *m_head = NULL; - - ASSERT_ALTQ_SQ_DEFAULT(ifp, ifsq); - - sc = ifp->if_softc; - KUE_LOCK(sc); - - if (ifq_is_oactive(&ifp->if_snd)) { - KUE_UNLOCK(sc); - return; - } - - m_head = ifq_dequeue(&ifp->if_snd); - if (m_head == NULL) { - KUE_UNLOCK(sc); - return; - } - - if (kue_encap(sc, m_head, 0)) { - /* kue_encap() will free m_head, if we reach here */ - ifq_set_oactive(&ifp->if_snd); - KUE_UNLOCK(sc); - return; - } - - /* - * If there's a BPF listener, bounce a copy of this frame - * to him. - */ - BPF_MTAP(ifp, m_head); - - ifq_set_oactive(&ifp->if_snd); - - /* - * Set a timeout in case the chip goes out to lunch. - */ - ifp->if_timer = 5; - KUE_UNLOCK(sc); - - return; -} - -static void -kue_init(void *xsc) -{ - struct kue_softc *sc = xsc; - struct ifnet *ifp = &sc->arpcom.ac_if; - struct kue_chain *c; - usbd_status err; - int i; - - KUE_LOCK(sc); - - if (ifp->if_flags & IFF_RUNNING) { - KUE_UNLOCK(sc); - return; - } - - /* Set MAC address */ - kue_ctl(sc, KUE_CTL_WRITE, KUE_CMD_SET_MAC, - 0, sc->arpcom.ac_enaddr, ETHER_ADDR_LEN); - - sc->kue_rxfilt = KUE_RXFILT_UNICAST|KUE_RXFILT_BROADCAST; - - /* If we want promiscuous mode, set the allframes bit. */ - if (ifp->if_flags & IFF_PROMISC) - sc->kue_rxfilt |= KUE_RXFILT_PROMISC; - - kue_setword(sc, KUE_CMD_SET_PKT_FILTER, sc->kue_rxfilt); - - /* I'm not sure how to tune these. */ -#ifdef notdef - /* - * Leave this one alone for now; setting it - * wrong causes lockups on some machines/controllers. - */ - kue_setword(sc, KUE_CMD_SET_SOFS, 1); -#endif - kue_setword(sc, KUE_CMD_SET_URB_SIZE, 64); - - /* Init TX ring. */ - if (kue_tx_list_init(sc) == ENOBUFS) { - kprintf("kue%d: tx list init failed\n", sc->kue_unit); - KUE_UNLOCK(sc); - return; - } - - /* Init RX ring. */ - if (kue_rx_list_init(sc) == ENOBUFS) { - kprintf("kue%d: rx list init failed\n", sc->kue_unit); - KUE_UNLOCK(sc); - return; - } - - /* Load the multicast filter. */ - kue_setmulti(sc); - - /* Open RX and TX pipes. */ - err = usbd_open_pipe(sc->kue_iface, sc->kue_ed[KUE_ENDPT_RX], - USBD_EXCLUSIVE_USE, &sc->kue_ep[KUE_ENDPT_RX]); - if (err) { - kprintf("kue%d: open rx pipe failed: %s\n", - sc->kue_unit, usbd_errstr(err)); - KUE_UNLOCK(sc); - return; - } - - err = usbd_open_pipe(sc->kue_iface, sc->kue_ed[KUE_ENDPT_TX], - USBD_EXCLUSIVE_USE, &sc->kue_ep[KUE_ENDPT_TX]); - if (err) { - kprintf("kue%d: open tx pipe failed: %s\n", - sc->kue_unit, usbd_errstr(err)); - KUE_UNLOCK(sc); - return; - } - - /* Start up the receive pipe. */ - for (i = 0; i < KUE_RX_LIST_CNT; i++) { - c = &sc->kue_cdata.kue_rx_chain[i]; - usbd_setup_xfer(c->kue_xfer, sc->kue_ep[KUE_ENDPT_RX], - c, mtod(c->kue_mbuf, char *), KUE_BUFSZ, - USBD_SHORT_XFER_OK, USBD_NO_TIMEOUT, kue_rxeof); - usbd_transfer(c->kue_xfer); - } - - ifp->if_flags |= IFF_RUNNING; - ifq_clr_oactive(&ifp->if_snd) - - KUE_UNLOCK(sc); - - return; -} - -static int -kue_ioctl(struct ifnet *ifp, u_long command, caddr_t data, struct ucred *cr) -{ - struct kue_softc *sc = ifp->if_softc; - int error = 0; - - KUE_LOCK(sc); - - switch(command) { - case SIOCSIFFLAGS: - if (ifp->if_flags & IFF_UP) { - if (ifp->if_flags & IFF_RUNNING && - ifp->if_flags & IFF_PROMISC && - !(sc->kue_if_flags & IFF_PROMISC)) { - sc->kue_rxfilt |= KUE_RXFILT_PROMISC; - kue_setword(sc, KUE_CMD_SET_PKT_FILTER, - sc->kue_rxfilt); - } else if (ifp->if_flags & IFF_RUNNING && - !(ifp->if_flags & IFF_PROMISC) && - sc->kue_if_flags & IFF_PROMISC) { - sc->kue_rxfilt &= ~KUE_RXFILT_PROMISC; - kue_setword(sc, KUE_CMD_SET_PKT_FILTER, - sc->kue_rxfilt); - } else if (!(ifp->if_flags & IFF_RUNNING)) - kue_init(sc); - } else { - if (ifp->if_flags & IFF_RUNNING) - kue_stop(sc); - } - sc->kue_if_flags = ifp->if_flags; - error = 0; - break; - case SIOCADDMULTI: - case SIOCDELMULTI: - kue_setmulti(sc); - error = 0; - break; - default: - error = ether_ioctl(ifp, command, data); - break; - } - - KUE_UNLOCK(sc); - - return(error); -} - -static void -kue_watchdog(struct ifnet *ifp) -{ - struct kue_softc *sc; - struct kue_chain *c; - usbd_status stat; - - sc = ifp->if_softc; - KUE_LOCK(sc); - IFNET_STAT_INC(ifp, oerrors, 1); - kprintf("kue%d: watchdog timeout\n", sc->kue_unit); - - c = &sc->kue_cdata.kue_tx_chain[0]; - usbd_get_xfer_status(c->kue_xfer, NULL, NULL, NULL, &stat); - kue_txeof(c->kue_xfer, c, stat); - - if (!ifq_is_empty(&ifp->if_snd)) - if_devstart(ifp); - KUE_UNLOCK(sc); - - return; -} - -/* - * Stop the adapter and free any mbufs allocated to the - * RX and TX lists. - */ -static void -kue_stop(struct kue_softc *sc) -{ - usbd_status err; - struct ifnet *ifp; - int i; - - KUE_LOCK(sc); - ifp = &sc->arpcom.ac_if; - ifp->if_timer = 0; - - /* Stop transfers. */ - if (sc->kue_ep[KUE_ENDPT_RX] != NULL) { - err = usbd_abort_pipe(sc->kue_ep[KUE_ENDPT_RX]); - if (err) { - kprintf("kue%d: abort rx pipe failed: %s\n", - sc->kue_unit, usbd_errstr(err)); - } - err = usbd_close_pipe(sc->kue_ep[KUE_ENDPT_RX]); - if (err) { - kprintf("kue%d: close rx pipe failed: %s\n", - sc->kue_unit, usbd_errstr(err)); - } - sc->kue_ep[KUE_ENDPT_RX] = NULL; - } - - if (sc->kue_ep[KUE_ENDPT_TX] != NULL) { - err = usbd_abort_pipe(sc->kue_ep[KUE_ENDPT_TX]); - if (err) { - kprintf("kue%d: abort tx pipe failed: %s\n", - sc->kue_unit, usbd_errstr(err)); - } - err = usbd_close_pipe(sc->kue_ep[KUE_ENDPT_TX]); - if (err) { - kprintf("kue%d: close tx pipe failed: %s\n", - sc->kue_unit, usbd_errstr(err)); - } - sc->kue_ep[KUE_ENDPT_TX] = NULL; - } - - if (sc->kue_ep[KUE_ENDPT_INTR] != NULL) { - err = usbd_abort_pipe(sc->kue_ep[KUE_ENDPT_INTR]); - if (err) { - kprintf("kue%d: abort intr pipe failed: %s\n", - sc->kue_unit, usbd_errstr(err)); - } - err = usbd_close_pipe(sc->kue_ep[KUE_ENDPT_INTR]); - if (err) { - kprintf("kue%d: close intr pipe failed: %s\n", - sc->kue_unit, usbd_errstr(err)); - } - sc->kue_ep[KUE_ENDPT_INTR] = NULL; - } - - /* Free RX resources. */ - for (i = 0; i < KUE_RX_LIST_CNT; i++) { - if (sc->kue_cdata.kue_rx_chain[i].kue_buf != NULL) { - kfree(sc->kue_cdata.kue_rx_chain[i].kue_buf, M_USBDEV); - sc->kue_cdata.kue_rx_chain[i].kue_buf = NULL; - } - if (sc->kue_cdata.kue_rx_chain[i].kue_mbuf != NULL) { - m_freem(sc->kue_cdata.kue_rx_chain[i].kue_mbuf); - sc->kue_cdata.kue_rx_chain[i].kue_mbuf = NULL; - } - if (sc->kue_cdata.kue_rx_chain[i].kue_xfer != NULL) { - usbd_free_xfer(sc->kue_cdata.kue_rx_chain[i].kue_xfer); - sc->kue_cdata.kue_rx_chain[i].kue_xfer = NULL; - } - } - - /* Free TX resources. */ - for (i = 0; i < KUE_TX_LIST_CNT; i++) { - if (sc->kue_cdata.kue_tx_chain[i].kue_buf != NULL) { - kfree(sc->kue_cdata.kue_tx_chain[i].kue_buf, M_USBDEV); - sc->kue_cdata.kue_tx_chain[i].kue_buf = NULL; - } - if (sc->kue_cdata.kue_tx_chain[i].kue_mbuf != NULL) { - m_freem(sc->kue_cdata.kue_tx_chain[i].kue_mbuf); - sc->kue_cdata.kue_tx_chain[i].kue_mbuf = NULL; - } - if (sc->kue_cdata.kue_tx_chain[i].kue_xfer != NULL) { - usbd_free_xfer(sc->kue_cdata.kue_tx_chain[i].kue_xfer); - sc->kue_cdata.kue_tx_chain[i].kue_xfer = NULL; - } - } - - ifp->if_flags &= ~IFF_RUNNING; - ifq_clr_oactive(&ifp->if_snd); - KUE_UNLOCK(sc); - - return; -} - -/* - * Stop all chip I/O so that the kernel's probe routines don't - * get confused by errant DMAs when rebooting. - */ -static void -kue_shutdown(device_t dev) -{ - struct kue_softc *sc; - - sc = device_get_softc(dev); - - kue_stop(sc); - - return; -} diff --git a/sys/dev/netif/kue/if_kuereg.h b/sys/dev/netif/kue/if_kuereg.h deleted file mode 100644 index 80c81dbc2b..0000000000 --- a/sys/dev/netif/kue/if_kuereg.h +++ /dev/null @@ -1,181 +0,0 @@ -/* - * Copyright (c) 1997, 1998, 1999, 2000 - * Bill Paul . 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. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Bill Paul. - * 4. Neither the name of the author nor the names of any co-contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY Bill Paul 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 Bill Paul OR THE VOICES IN HIS HEAD - * 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: src/sys/dev/usb/if_kuereg.h,v 1.13 2003/10/04 21:41:01 joe Exp $ - * $DragonFly: src/sys/dev/netif/kue/if_kuereg.h,v 1.5 2007/11/05 13:32:27 hasso Exp $ - */ - -/* - * Definitions for the KLSI KL5KUSB101B USB to ethernet controller. - * The KLSI part is controlled via vendor control requests, the structure - * of which depend a bit on the firmware running on the internal - * microcontroller. The one exception is the 'send scan data' command, - * which is used to load the firmware. - */ - -#define KUE_CMD_GET_ETHER_DESCRIPTOR 0x00 -#define KUE_CMD_SET_MCAST_FILTERS 0x01 -#define KUE_CMD_SET_PKT_FILTER 0x02 -#define KUE_CMD_GET_ETHERSTATS 0x03 -#define KUE_CMD_GET_GPIO 0x04 -#define KUE_CMD_SET_GPIO 0x05 -#define KUE_CMD_SET_MAC 0x06 -#define KUE_CMD_GET_MAC 0x07 -#define KUE_CMD_SET_URB_SIZE 0x08 -#define KUE_CMD_SET_SOFS 0x09 -#define KUE_CMD_SET_EVEN_PKTS 0x0A -#define KUE_CMD_SEND_SCAN 0xFF - -struct kue_ether_desc { - u_int8_t kue_len; - u_int8_t kue_rsvd0; - u_int8_t kue_rsvd1; - u_int8_t kue_macaddr[ETHER_ADDR_LEN]; - u_int8_t kue_etherstats[4]; - u_int8_t kue_maxseg[2]; - u_int8_t kue_mcastfilt[2]; - u_int8_t kue_rsvd2; -}; - -#define KUE_ETHERSTATS(x) \ - (*(u_int32_t *)&(x)->kue_desc.kue_etherstats) -#define KUE_MAXSEG(x) \ - (*(u_int16_t *)&(x)->kue_desc.kue_maxseg) -#define KUE_MCFILTCNT(x) \ - ((*(u_int16_t *)&(x)->kue_desc.kue_mcastfilt) & 0x7FFF) -#define KUE_MCFILT(x, y) \ - (char *)&(sc->kue_mcfilters[y * ETHER_ADDR_LEN]) - -#define KUE_STAT_TX_OK 0x00000001 -#define KUE_STAT_RX_OK 0x00000002 -#define KUE_STAT_TX_ERR 0x00000004 -#define KUE_STAT_RX_ERR 0x00000008 -#define KUE_STAT_RX_NOBUF 0x00000010 -#define KUE_STAT_TX_UCAST_BYTES 0x00000020 -#define KUE_STAT_TX_UCAST_FRAMES 0x00000040 -#define KUE_STAT_TX_MCAST_BYTES 0x00000080 -#define KUE_STAT_TX_MCAST_FRAMES 0x00000100 -#define KUE_STAT_TX_BCAST_BYTES 0x00000200 -#define KUE_STAT_TX_BCAST_FRAMES 0x00000400 -#define KUE_STAT_RX_UCAST_BYTES 0x00000800 -#define KUE_STAT_RX_UCAST_FRAMES 0x00001000 -#define KUE_STAT_RX_MCAST_BYTES 0x00002000 -#define KUE_STAT_RX_MCAST_FRAMES 0x00004000 -#define KUE_STAT_RX_BCAST_BYTES 0x00008000 -#define KUE_STAT_RX_BCAST_FRAMES 0x00010000 -#define KUE_STAT_RX_CRCERR 0x00020000 -#define KUE_STAT_TX_QUEUE_LENGTH 0x00040000 -#define KUE_STAT_RX_ALIGNERR 0x00080000 -#define KUE_STAT_TX_SINGLECOLL 0x00100000 -#define KUE_STAT_TX_MULTICOLL 0x00200000 -#define KUE_STAT_TX_DEFERRED 0x00400000 -#define KUE_STAT_TX_MAXCOLLS 0x00800000 -#define KUE_STAT_RX_OVERRUN 0x01000000 -#define KUE_STAT_TX_UNDERRUN 0x02000000 -#define KUE_STAT_TX_SQE_ERR 0x04000000 -#define KUE_STAT_TX_CARRLOSS 0x08000000 -#define KUE_STAT_RX_LATECOLL 0x10000000 - -#define KUE_RXFILT_PROMISC 0x0001 -#define KUE_RXFILT_ALLMULTI 0x0002 -#define KUE_RXFILT_UNICAST 0x0004 -#define KUE_RXFILT_BROADCAST 0x0008 -#define KUE_RXFILT_MULTICAST 0x0010 - -#define KUE_TIMEOUT 1000 -#define KUE_BUFSZ 1536 -#define KUE_MIN_FRAMELEN 60 - -#define KUE_RX_LIST_CNT 1 -#define KUE_TX_LIST_CNT 1 - -#define KUE_CTL_READ 0x01 -#define KUE_CTL_WRITE 0x02 - -#define KUE_CONFIG_NO 1 -#define KUE_IFACE_IDX 0 - -/* - * The interrupt endpoint is currently unused - * by the KLSI part. - */ -#define KUE_ENDPT_RX 0x0 -#define KUE_ENDPT_TX 0x1 -#define KUE_ENDPT_INTR 0x2 -#define KUE_ENDPT_MAX 0x3 - -struct kue_softc; - -struct kue_chain { - struct kue_softc *kue_sc; - usbd_xfer_handle kue_xfer; - char *kue_buf; - struct mbuf *kue_mbuf; - int kue_idx; -}; - -struct kue_cdata { - struct kue_chain kue_tx_chain[KUE_TX_LIST_CNT]; - struct kue_chain kue_rx_chain[KUE_RX_LIST_CNT]; - int kue_tx_prod; - int kue_tx_cons; - int kue_tx_cnt; - int kue_rx_prod; -}; - -#define KUE_INC(x, y) (x) = (x + 1) % y - -struct kue_softc { - struct arpcom arpcom; - usbd_device_handle kue_udev; - usbd_interface_handle kue_iface; - struct kue_ether_desc kue_desc; - int kue_ed[KUE_ENDPT_MAX]; - usbd_pipe_handle kue_ep[KUE_ENDPT_MAX]; - int kue_unit; - int kue_if_flags; - u_int16_t kue_rxfilt; - u_int8_t *kue_mcfilters; - struct kue_cdata kue_cdata; -#if defined(__FreeBSD__) && __FreeBSD_version >= 500000 - struct mtx kue_mtx; -#endif - char kue_dying; - struct timeval kue_rx_notice; -}; - -#if 0 -#define KUE_LOCK(_sc) mtx_lock(&(_sc)->kue_mtx) -#define KUE_UNLOCK(_sc) mtx_unlock(&(_sc)->kue_mtx) -#else -#define KUE_LOCK(_sc) -#define KUE_UNLOCK(_sc) -#endif diff --git a/sys/dev/netif/lgue/Makefile b/sys/dev/netif/lgue/Makefile deleted file mode 100644 index 7779f95938..0000000000 --- a/sys/dev/netif/lgue/Makefile +++ /dev/null @@ -1,10 +0,0 @@ -# XXX Some notes - -# Declare Name of kernel module -KMOD = if_lgue - -# Enumerate Source files for kernel module -SRCS = if_lgue.c opt_usb.h device_if.h bus_if.h - -# Include kernel module makefile -.include diff --git a/sys/dev/netif/lgue/if_lgue.c b/sys/dev/netif/lgue/if_lgue.c deleted file mode 100644 index a0b6615382..0000000000 --- a/sys/dev/netif/lgue/if_lgue.c +++ /dev/null @@ -1,864 +0,0 @@ -/* - * LG-P500 Smartphone - * Written by Yellow Rabbit - */ - -/* - * XXX - * USB: - * Takes two interfaces. - * IN and OUT endpoints on the data interface (altsetting). - * Interrupt endpoint on the control interface. - * - * NET: - * Transfer frames without modification (AS IS). - */ - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include "if_lgue.h" - -/* - * Supported device vendors/products - */ -static struct usb_devno lgue_devs[] = { - { USB_DEVICE(0x1004, 0x61a2) } /* LG P500 */ -}; - -static int lgue_match(device_t); -static int lgue_attach(device_t); -static int lgue_detach(device_t); - -static void lgue_start(struct ifnet *, struct ifaltq_subque *); -static void lgue_stop(struct lgue_softc *); -static void lgue_init(void *); -static void lgue_watchdog(struct ifnet *); -static int lgue_ioctl(struct ifnet *, u_long, caddr_t, struct ucred *); - -static int lgue_encap(struct lgue_softc *, struct mbuf *); -static int lgue_start_transfer(struct lgue_softc *); - -static void lgue_txeof(usbd_xfer_handle, usbd_private_handle, usbd_status); - -static int lgue_newbuf(struct lgue_softc *, int, struct mbuf **); -static void lgue_rxstart(struct ifnet *); -static void lgue_rxeof(usbd_xfer_handle, usbd_private_handle, usbd_status); - -static void lgue_intrstart(struct ifnet *); -static void lgue_intreof(usbd_xfer_handle, usbd_private_handle, usbd_status); - -static int lgue_get_data_iface_no(usbd_device_handle, - usb_interface_descriptor_t *); - -static int lgue_getmac(struct lgue_softc *, void *); -static int lgue_getmtu(struct lgue_softc *); - -static int hex(char); - -static device_method_t lgue_methods[] = { - DEVMETHOD(device_probe, lgue_match), - DEVMETHOD(device_attach, lgue_attach), - DEVMETHOD(device_detach, lgue_detach), - - DEVMETHOD_END -}; - -static driver_t lgue_driver = { - "lgue", - lgue_methods, - sizeof(struct lgue_softc) -}; - -static devclass_t lgue_devclass; - -DECLARE_DUMMY_MODULE(if_lgue); -DRIVER_MODULE(lgue, uhub, lgue_driver, lgue_devclass, usbd_driver_load, NULL); -MODULE_DEPEND(lgue, usb, 1, 1, 1); - -/* - * Probe chip - */ -static int -lgue_match(device_t dev) -{ - struct usb_attach_arg *uaa; - usb_interface_descriptor_t *id; - - uaa = device_get_ivars(dev); - if (uaa->iface == NULL) - return(UMATCH_NONE); - - if (usb_lookup(lgue_devs, uaa->vendor, uaa->product) != NULL) { - id = usbd_get_interface_descriptor(uaa->iface); - if (id != NULL && - id->bInterfaceClass == UICLASS_CDC && - id->bInterfaceSubClass == UISUBCLASS_ETHERNET_NETWORKING_CONTROL_MODEL) - return(UMATCH_VENDOR_PRODUCT); - } - return(UMATCH_NONE); -} - -/* - * Attach the interface. - */ -static int -lgue_attach(device_t dev) -{ - struct lgue_softc *sc; - struct usb_attach_arg *uaa; - struct ifnet *ifp; - usb_interface_descriptor_t *id; - usb_endpoint_descriptor_t *ed; - int i; - u_char eaddr[ETHER_ADDR_LEN]; - usbd_status err; - - sc = device_get_softc(dev); - uaa = device_get_ivars(dev); - - sc->lgue_ctl_iface = uaa->iface; - sc->lgue_udev = uaa->device; - - /* It has only config but in case... */ - if (usbd_set_config_no(sc->lgue_udev, LGUE_CONFIG_NO, 0)) { - device_printf(dev, "setting config no %d failed\n", - LGUE_CONFIG_NO); - return(ENXIO); - } - - /* Get control and data intefaces */ - id = usbd_get_interface_descriptor(uaa->iface); - sc->lgue_ctl_iface_no = id->bInterfaceNumber; - sc->lgue_data_iface_no = lgue_get_data_iface_no(sc->lgue_udev, id); - - if (sc->lgue_data_iface_no == -1) { - device_printf(dev, "no data interface number\n"); - goto bad; - } - - /* Claim data interface */ - for (i = 0; i < uaa->nifaces; ++i) { - if (uaa->ifaces[i] != NULL) { - id = usbd_get_interface_descriptor(uaa->ifaces[i]); - if (id != NULL && - id->bInterfaceNumber == sc->lgue_data_iface_no) { - err = usbd_set_interface(uaa->ifaces[i], - LGUE_ALTERNATE_SETTING); - if ( err != USBD_NORMAL_COMPLETION) { - device_printf(dev, - "no alternate data interface. err:%s\n", - usbd_errstr(err)); - goto bad; - } - sc->lgue_data_iface = uaa->ifaces[i]; - uaa->ifaces[i] = NULL; - } - } - } - if (sc->lgue_data_iface == NULL) { - device_printf(dev, "no data interface\n"); - goto bad; - } - - /* Find data interface endpoints */ - id = usbd_get_interface_descriptor(sc->lgue_data_iface); - sc->lgue_ed[LGUE_ENDPT_RX] = sc->lgue_ed[LGUE_ENDPT_TX] = -1; - for (i = 0; i < id->bNumEndpoints; ++i) { - ed = usbd_interface2endpoint_descriptor(sc->lgue_data_iface, i); - if (!ed) { - device_printf(dev, - "couldn't get endpoint descriptor %d\n", i); - goto bad; - } - if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && - UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) { - sc->lgue_ed[LGUE_ENDPT_RX] = ed->bEndpointAddress; - } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT && - UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) { - sc->lgue_ed[LGUE_ENDPT_TX] = ed->bEndpointAddress; - } - } - - if (sc->lgue_ed[LGUE_ENDPT_RX] == -1) { - device_printf(dev, "couldn't find data bilk in\n"); - goto bad; - } - if (sc->lgue_ed[LGUE_ENDPT_TX] == -1) { - device_printf(dev, "couldn't find data bilk out\n"); - goto bad; - } - - /* Find control interface endpoint */ - id = usbd_get_interface_descriptor(sc->lgue_ctl_iface); - sc->lgue_ed[LGUE_ENDPT_INTR] = -1; - for (i = 0; i < id->bNumEndpoints; ++i) { - ed = usbd_interface2endpoint_descriptor(sc->lgue_ctl_iface, i); - if (!ed) { - device_printf(dev, - "couldn't get endpoint descriptor %d\n", i); - goto bad; - } - if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && - UE_GET_XFERTYPE(ed->bmAttributes) == UE_INTERRUPT) { - sc->lgue_ed[LGUE_ENDPT_INTR] = ed->bEndpointAddress; - } - } - - if (sc->lgue_ed[LGUE_ENDPT_INTR] == -1) { - device_printf(dev, "couldn't find interrupt bilk in\n"); - goto bad; - } - - /* Create interface */ - ifp = &sc->lgue_arpcom.ac_if; - ifp->if_softc = sc; - if_initname(ifp, device_get_name(dev), device_get_unit(dev)); - lgue_getmac(sc, eaddr); - - ifp->if_mtu = lgue_getmtu(sc); - ifp->if_data.ifi_mtu = ifp->if_mtu; - ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; - ifp->if_baudrate = 10000000; - ifp->if_ioctl = lgue_ioctl; - ifp->if_start = lgue_start; - ifp->if_watchdog = lgue_watchdog; - ifp->if_init = lgue_init; - ifq_set_maxlen(&ifp->if_snd, IFQ_MAXLEN); - ifq_set_ready(&ifp->if_snd); - - /* Call attach routine */ - ether_ifattach(ifp, eaddr, NULL); - usb_register_netisr(); - sc->lgue_dying = 0; - return(0); - -bad: - return(ENXIO); -} - -/* - * Device detached. - */ -static int -lgue_detach(device_t dev) -{ - struct lgue_softc *sc; - struct ifnet *ifp; - - sc = device_get_softc(dev); - ifp = &sc->lgue_arpcom.ac_if; - ether_ifdetach(ifp); - - if (sc->lgue_ep[LGUE_ENDPT_TX] != NULL) - usbd_abort_pipe(sc->lgue_ep[LGUE_ENDPT_TX]); - if (sc->lgue_ep[LGUE_ENDPT_RX] != NULL) - usbd_abort_pipe(sc->lgue_ep[LGUE_ENDPT_RX]); - if (sc->lgue_ep[LGUE_ENDPT_INTR] != NULL) - usbd_abort_pipe(sc->lgue_ep[LGUE_ENDPT_INTR]); - return(0); -} - -/* - * Find data interface. - */ -int -lgue_get_data_iface_no(usbd_device_handle dev, usb_interface_descriptor_t *id) -{ - const usb_cdc_union_descriptor_t *cud; - - cud = (const usb_cdc_union_descriptor_t *)usb_find_desc_if(dev, - UDESC_CS_INTERFACE, UDESCSUB_CDC_UNION, id); - return(cud ? cud->bSlaveInterface[0] : -1); -} - -/* - * Get hard max mtu - */ -static int -lgue_getmtu(struct lgue_softc *sc) -{ - const usb_cdc_ethernet_descriptor_t *ced; - usb_interface_descriptor_t *id; - - id = usbd_get_interface_descriptor(sc->lgue_ctl_iface); - if (id == NULL) { - kprintf("usbd_get_interface_descriptor() returned NULL\n"); - return(ETHERMTU); - } - - ced = (const usb_cdc_ethernet_descriptor_t *)usb_find_desc_if(sc->lgue_udev, - UDESC_CS_INTERFACE, UDESCSUB_CDC_ETHERNET, id); - if (ced == NULL) { - kprintf("usb_find_desc_if() returned NULL\n"); - return(ETHERMTU); - } - return(UGETW(ced->wMaxSegmentSize)); -} - -/* - * Get mac address - */ -static int -lgue_getmac(struct lgue_softc *sc, void *buf) -{ - const usb_cdc_ethernet_descriptor_t *ced; - usb_interface_descriptor_t *id; - char sbuf[ETHER_ADDR_LEN * 2 + 1]; - usbd_status err; - int i; - - id = usbd_get_interface_descriptor(sc->lgue_ctl_iface); - if (id == NULL) goto bad; - ced = (const usb_cdc_ethernet_descriptor_t *)usb_find_desc_if(sc->lgue_udev, - UDESC_CS_INTERFACE, UDESCSUB_CDC_ETHERNET, id); - if (ced == NULL) goto bad; - - err = usbd_get_string(sc->lgue_udev, ced->iMACAddress, sbuf); - if(err) { - kprintf("Read MAC address failed\n"); - goto bad; - } - - for (i = 0; i < ETHER_ADDR_LEN; ++i) { - ((uByte *)buf)[i] = (hex(sbuf[i * 2]) << 4) + hex(sbuf[(i * 2) + 1]); - } - return(0); -bad: - return(-1); -} - -/* - * Listen INTR pipe - */ -static void -lgue_intrstart(struct ifnet *ifp) -{ - struct lgue_softc *sc; - - sc = ifp->if_softc; - usbd_setup_xfer(sc->lgue_intr_xfer, sc->lgue_ep[LGUE_ENDPT_INTR], sc, - sc->lgue_intr_buf, LGUE_BUFSZ, - USBD_SHORT_XFER_OK, USBD_NO_TIMEOUT, lgue_intreof); - usbd_transfer(sc->lgue_intr_xfer); -} - -/* - * INTR arrived - */ -static void -lgue_intreof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status) -{ - struct ifnet *ifp; - struct lgue_softc *sc; - - sc = priv; - if (sc->lgue_dying) - return; - - ifp = &sc->lgue_arpcom.ac_if; - lwkt_serialize_enter(ifp->if_serializer); - if (status != USBD_NORMAL_COMPLETION) { - if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) { - lwkt_serialize_exit(ifp->if_serializer); - return; - } - if_printf(ifp, "usb error on intr: %s\n", usbd_errstr(status)); - if (status == USBD_STALLED) - usbd_clear_endpoint_stall(sc->lgue_ep[LGUE_ENDPT_INTR]); - lwkt_serialize_exit(ifp->if_serializer); - return; - } - lgue_intrstart(ifp); - lwkt_serialize_exit(ifp->if_serializer); -} - -/* - * Encap packet & send - */ -static int -lgue_encap(struct lgue_softc *sc, struct mbuf *m) -{ - struct ifnet *ifp; - struct lgue_queue_entry *entry; - - ifp = &sc->lgue_arpcom.ac_if; - entry = kmalloc(sizeof(struct lgue_queue_entry), M_USBDEV , M_NOWAIT); - if (entry == NULL) { - if_printf(ifp, "no memory for internal queue entry\n"); - return(ENOBUFS); - } - entry->entry_mbuf = m; - - /* Put packet into internal queue tail */ - STAILQ_INSERT_TAIL(&sc->lgue_tx_queue, entry, entry_next); - return(0); -} - -/* - * Start transfer from internal queue - */ -static int -lgue_start_transfer(struct lgue_softc *sc) { - usbd_status err; - struct lgue_queue_entry *entry; - struct ifnet *ifp; - - if (STAILQ_EMPTY(&sc->lgue_tx_queue)) - return(0); - - ifp = &sc->lgue_arpcom.ac_if; - entry = STAILQ_FIRST(&sc->lgue_tx_queue); - STAILQ_REMOVE_HEAD(&sc->lgue_tx_queue, entry_next); - - m_copydata(entry->entry_mbuf, 0, entry->entry_mbuf->m_pkthdr.len, - sc->lgue_tx_buf); - - /* Transmit */ - usbd_setup_xfer(sc->lgue_tx_xfer, sc->lgue_ep[LGUE_ENDPT_TX], sc, - sc->lgue_tx_buf, entry->entry_mbuf->m_pkthdr.len, - USBD_SHORT_XFER_OK, USBD_NO_TIMEOUT, lgue_txeof); - err = usbd_transfer(sc->lgue_tx_xfer); - if (err != USBD_IN_PROGRESS) { - m_freem(entry->entry_mbuf); - kfree(entry, M_USBDEV); - lgue_stop(sc); - ifq_clr_oactive(&ifp->if_snd); - return(EIO); - } - - m_freem(entry->entry_mbuf); - kfree(entry, M_USBDEV); - - sc->lgue_tx_cnt++; - ifq_set_oactive(&ifp->if_snd); - ifp->if_timer = 5; - return(0); -} - -/* - * End of sending - */ -static void -lgue_txeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status) -{ - struct ifnet *ifp; - struct lgue_softc *sc; - usbd_status err; - - sc = priv; - if (sc->lgue_dying) - return; - - ifp = &sc->lgue_arpcom.ac_if; - - if (status != USBD_NORMAL_COMPLETION) { - if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) - return; - if (status == USBD_STALLED) - usbd_clear_endpoint_stall(sc->lgue_ep[LGUE_ENDPT_TX]); - return; - } - usbd_get_xfer_status(sc->lgue_tx_xfer, NULL, NULL, NULL,&err); - if (err) - IFNET_STAT_INC(ifp, oerrors, 1); - else - IFNET_STAT_INC(ifp, opackets, 1); - - if (!STAILQ_EMPTY(&sc->lgue_tx_queue)) { - if_devstart_sched(ifp); - } - - ifp->if_timer = 0; - ifq_clr_oactive(&ifp->if_snd); -} - -/* - * Start transfer - */ -static void -lgue_start(struct ifnet *ifp, struct ifaltq_subque *ifsq) -{ - struct lgue_softc *sc; - struct mbuf *m_head; - - ASSERT_ALTQ_SQ_DEFAULT(ifp, ifsq); - - sc = ifp->if_softc; - if (sc->lgue_dying) - return; - - if (ifq_is_oactive(&ifp->if_snd)) { - return; - } - - /* To internal queue */ - while ((m_head = ifq_dequeue(&ifp->if_snd)) != NULL) { - if (lgue_encap(sc, m_head)) { - m_freem(m_head); - break; - } - /* Filter */ - BPF_MTAP(ifp, m_head); - } - - lgue_start_transfer(sc); -} - -/* - * Stop - */ -static void -lgue_stop(struct lgue_softc *sc) -{ - struct ifnet *ifp; - usbd_status err; - struct lgue_queue_entry *entry; - - if (sc->lgue_dying) - return; - sc->lgue_dying = 1; - - ifp = &sc->lgue_arpcom.ac_if; - - /* Stop transfers */ - if (sc->lgue_ep[LGUE_ENDPT_TX] != NULL) { - err = usbd_abort_pipe(sc->lgue_ep[LGUE_ENDPT_TX]); - if (err) { - if_printf(ifp, "abort tx pipe failed:%s\n", - usbd_errstr(err)); - } - err = usbd_close_pipe(sc->lgue_ep[LGUE_ENDPT_TX]); - if (err) { - if_printf(ifp, "close tx pipe failed:%s\n", - usbd_errstr(err)); - } - } - if (sc->lgue_ep[LGUE_ENDPT_RX] != NULL) { - err = usbd_abort_pipe(sc->lgue_ep[LGUE_ENDPT_RX]); - if (err) { - if_printf(ifp, "abort rx pipe failed:%s\n", - usbd_errstr(err)); - } - err = usbd_close_pipe(sc->lgue_ep[LGUE_ENDPT_RX]); - if (err) { - if_printf(ifp, "close rx pipe failed:%s\n", - usbd_errstr(err)); - } - } - if (sc->lgue_ep[LGUE_ENDPT_INTR] != NULL) { - err = usbd_abort_pipe(sc->lgue_ep[LGUE_ENDPT_INTR]); - if (err) { - if_printf(ifp, "abort intr pipe failed:%s\n", - usbd_errstr(err)); - } - err = usbd_close_pipe(sc->lgue_ep[LGUE_ENDPT_INTR]); - if (err) { - if_printf(ifp, "close intr pipe failed:%s\n", - usbd_errstr(err)); - } - } - - /* Free tx buffers */ - if (sc->lgue_tx_buf != NULL) { - kfree(sc->lgue_tx_buf, M_USBDEV); - sc->lgue_tx_buf = NULL; - } - if (sc->lgue_tx_xfer != NULL) { - usbd_free_xfer(sc->lgue_tx_xfer); - sc->lgue_tx_xfer = NULL; - } - - /* Free rx buffers */ - if (sc->lgue_rx_buf != NULL) { - kfree(sc->lgue_rx_buf, M_USBDEV); - sc->lgue_rx_buf = NULL; - } - if (sc->lgue_rx_xfer != NULL) { - usbd_free_xfer(sc->lgue_rx_xfer); - sc->lgue_rx_xfer = NULL; - } - - /* Free intr buffer */ - if (sc->lgue_intr_buf != NULL) { - kfree(sc->lgue_intr_buf, M_USBDEV); - sc->lgue_intr_buf = NULL; - } - if (sc->lgue_intr_xfer != NULL) { - usbd_free_xfer(sc->lgue_intr_xfer); - sc->lgue_intr_xfer = NULL; - } - - /* Clear internal queue */ - while (!STAILQ_EMPTY(&sc->lgue_tx_queue)) { - entry = STAILQ_FIRST(&sc->lgue_tx_queue); - STAILQ_REMOVE_HEAD(&sc->lgue_tx_queue, entry_next); - m_freem(entry->entry_mbuf); - kfree(entry, M_USBDEV); - } - - ifp->if_flags &= ~IFF_RUNNING; - ifq_clr_oactive(&ifp->if_snd); -} - -/* - * Init - */ -static void -lgue_init(void *xsc) -{ - struct lgue_softc *sc; - struct ifnet *ifp; - usbd_status err; - - sc = xsc; - ifp = &sc->lgue_arpcom.ac_if; - - if (ifp->if_flags & IFF_RUNNING) - return; - - /* Create RX and TX bufs */ - if (sc->lgue_tx_xfer == NULL) { - sc->lgue_tx_xfer = usbd_alloc_xfer(sc->lgue_udev); - if (sc->lgue_tx_xfer == NULL) { - if_printf(ifp, "tx buffer allocate failed\n"); - return; - } - } - sc->lgue_tx_buf = kmalloc(LGUE_BUFSZ, M_USBDEV, M_WAITOK); - - if (sc->lgue_rx_xfer == NULL) { - sc->lgue_rx_xfer = usbd_alloc_xfer(sc->lgue_udev); - if (sc->lgue_rx_xfer == NULL) { - if_printf(ifp, "rx buffer allocate failed\n"); - return; - } - } - sc->lgue_rx_buf = kmalloc(LGUE_BUFSZ, M_USBDEV, M_WAITOK); - - /* Create INTR buf */ - if (sc->lgue_intr_xfer == NULL) { - sc->lgue_intr_xfer = usbd_alloc_xfer(sc->lgue_udev); - if (sc->lgue_intr_xfer == NULL) { - if_printf(ifp, "intr buffer allocate failed\n"); - return; - } - } - sc->lgue_intr_buf = kmalloc(LGUE_BUFSZ, M_USBDEV, M_WAITOK); - - /* Open RX and TX pipes. */ - err = usbd_open_pipe(sc->lgue_data_iface, sc->lgue_ed[LGUE_ENDPT_RX], - USBD_EXCLUSIVE_USE, &sc->lgue_ep[LGUE_ENDPT_RX]); - if (err) { - if_printf(ifp, "open RX pipe failed: %s\n", usbd_errstr(err)); - return; - } - err = usbd_open_pipe(sc->lgue_data_iface, sc->lgue_ed[LGUE_ENDPT_TX], - USBD_EXCLUSIVE_USE, &sc->lgue_ep[LGUE_ENDPT_TX]); - if (err) { - if_printf(ifp, "open TX pipe failed: %s\n", usbd_errstr(err)); - return; - } - /* Open INTR pipe. */ - err = usbd_open_pipe(sc->lgue_ctl_iface, sc->lgue_ed[LGUE_ENDPT_INTR], - USBD_EXCLUSIVE_USE, &sc->lgue_ep[LGUE_ENDPT_INTR]); - if (err) { - if_printf(ifp, "open INTR pipe failed: %s\n", usbd_errstr(err)); - return; - } - - /* Create internal queue */ - STAILQ_INIT(&sc->lgue_tx_queue); - - ifp->if_flags |= IFF_RUNNING; - ifq_clr_oactive(&ifp->if_snd); - - sc->lgue_dying = 0; - - lgue_rxstart(ifp); - lgue_intrstart(ifp); -} - -/* - * New mbuf - */ -static int -lgue_newbuf(struct lgue_softc *sc, int len, struct mbuf **m_buf) -{ - struct ifnet *ifp; - - ifp = &sc->lgue_arpcom.ac_if; - *m_buf = NULL; - - /* Allocate mbuf */ - *m_buf = m_getcl(MB_DONTWAIT, MT_DATA, MT_HEADER); - if (*m_buf == NULL) { - if_printf(ifp, " no memory for rx buffer --- packet dropped!\n"); - return(ENOBUFS); - } - (*m_buf)->m_len = (*m_buf)->m_pkthdr.len = MCLBYTES; - m_adj(*m_buf, ETHER_ALIGN); - return(0); -} - -/* - * Start read - */ -static void -lgue_rxstart(struct ifnet *ifp) -{ - struct lgue_softc *sc; - - sc = ifp->if_softc; - if (sc->lgue_dying) - return; - - usbd_setup_xfer(sc->lgue_rx_xfer, sc->lgue_ep[LGUE_ENDPT_RX], sc, - sc->lgue_rx_buf, LGUE_BUFSZ, - USBD_SHORT_XFER_OK, USBD_NO_TIMEOUT, lgue_rxeof); - usbd_transfer(sc->lgue_rx_xfer); -} - -/* - * A frame has been uploaded: pass the resulting mbuf up to - * the higher level protocols. - */ -static void -lgue_rxeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status) -{ - struct lgue_softc *sc; - struct mbuf *m; - struct ifnet *ifp; - int total_len; - - sc = priv; - if (sc->lgue_dying) - return; - - ifp = &sc->lgue_arpcom.ac_if; - - total_len = 0; - - if (!(ifp->if_flags & IFF_RUNNING)) - return; - - if (status != USBD_NORMAL_COMPLETION) { - if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) - return; - if (usbd_ratecheck(&sc->lgue_rx_notice)) { - if_printf(ifp, "usb error on rx:%s\n", - usbd_errstr(status)); - } - if (status == USBD_STALLED) - usbd_clear_endpoint_stall(sc->lgue_ep[LGUE_ENDPT_RX]); - goto done; - } - - usbd_get_xfer_status(xfer, NULL, NULL, &total_len, NULL); - - if (total_len < sizeof(struct ether_header)) { - IFNET_STAT_INC(ifp, ierrors, 1); - goto done; - } - - if (lgue_newbuf(sc, total_len, &m) == ENOBUFS) { - IFNET_STAT_INC(ifp, ierrors, 1); - return; - } - - IFNET_STAT_INC(ifp, ipackets, 1); - m_copyback(m, 0, total_len, sc->lgue_rx_buf); - m->m_pkthdr.rcvif = ifp; - m->m_pkthdr.len = m->m_len = total_len; - - usb_ether_input(m); - lgue_rxstart(ifp); - return; -done: - usbd_setup_xfer(sc->lgue_rx_xfer, sc->lgue_ep[LGUE_ENDPT_RX], sc, - sc->lgue_rx_buf, LGUE_BUFSZ, - USBD_SHORT_XFER_OK, USBD_NO_TIMEOUT, lgue_rxeof); - usbd_transfer(sc->lgue_rx_xfer); -} - -/* - * Control - */ -static int -lgue_ioctl(struct ifnet *ifp, u_long command, caddr_t data, struct ucred *cr) -{ - struct lgue_softc *sc; - struct ifreq *ifr; - int err; - - err = 0; - ifr = (struct ifreq *)data; - sc = ifp->if_softc; - - switch(command) { - case SIOCSIFFLAGS: - if (ifp->if_flags & IFF_UP) { - if (!(ifp->if_flags & IFF_RUNNING)) - lgue_init(sc); - } else if (ifp->if_flags & IFF_RUNNING) { - lgue_stop(sc); - } - sc->lgue_if_flags = ifp->if_flags; - err = 0; - break; -#if 0 - case SIOCADDMULTI: - case SIOCDELMULTI: - err = 0; - break; -#endif - case SIOCSIFMTU: - ifp->if_mtu = ifr->ifr_mtu; - break; - default: - err = ether_ioctl(ifp, command, data); - break; - } - return(err); -} - -/* - * Watchdog - */ -static void -lgue_watchdog(struct ifnet *ifp) -{ - IFNET_STAT_INC(ifp, oerrors, 1); - - if (!ifq_is_empty(&ifp->if_snd)) - if_devstart_sched(ifp); -} - -/* - * Hex -> bin - */ -static int -hex(char ch) -{ - if ((ch >= 'a') && (ch <= 'f')) return (ch-'a'+10); - if ((ch >= '0') && (ch <= '9')) return (ch-'0'); - if ((ch >= 'A') && (ch <= 'F')) return (ch-'A'+10); - return (-1); -} diff --git a/sys/dev/netif/lgue/if_lgue.h b/sys/dev/netif/lgue/if_lgue.h deleted file mode 100644 index 8c1b6324be..0000000000 --- a/sys/dev/netif/lgue/if_lgue.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Definitions for LG USB CDC - */ - -#define LGUE_CONFIG_NO 1 - -#define LGUE_ALTERNATE_SETTING 1 - -#define LGUE_ENDPT_RX 0x0 -#define LGUE_ENDPT_TX 0x1 -#define LGUE_ENDPT_INTR 0x2 -#define LGUE_ENDPT_MAX 0x3 - -#define LGUE_BUFSZ 1600 - -/* - * Internal queue entry - */ -struct lgue_queue_entry { - /* - int entry_len; - char entry_tx_buf[LGUE_BUFSZ]; - */ - struct mbuf *entry_mbuf; - STAILQ_ENTRY(lgue_queue_entry) entry_next; -}; - - -struct lgue_softc { - struct arpcom lgue_arpcom; - usbd_device_handle lgue_udev; - int lgue_ed[LGUE_ENDPT_MAX]; - usbd_pipe_handle lgue_ep[LGUE_ENDPT_MAX]; - - int lgue_ctl_iface_no; - usbd_interface_handle lgue_ctl_iface; /* control interface */ - int lgue_data_iface_no; - usbd_interface_handle lgue_data_iface; /* data interface */ - - char lgue_dying; - int lgue_if_flags; - - int lgue_tx_cnt; - usbd_xfer_handle lgue_tx_xfer; - char *lgue_tx_buf; - - int lgue_rx_cnt; - usbd_xfer_handle lgue_rx_xfer; - struct timeval lgue_rx_notice; - char *lgue_rx_buf; - - usbd_xfer_handle lgue_intr_xfer; - char *lgue_intr_buf; - - /* Internal queue */ - STAILQ_HEAD(, lgue_queue_entry) lgue_tx_queue; -}; diff --git a/sys/dev/netif/ndis/Makefile b/sys/dev/netif/ndis/Makefile index 28cbab3dba..0a1939fc54 100644 --- a/sys/dev/netif/ndis/Makefile +++ b/sys/dev/netif/ndis/Makefile @@ -1,14 +1,8 @@ # $FreeBSD: src/sys/modules/if_ndis/Makefile,v 1.6 2005/09/27 18:10:35 mlaier Exp $ KMOD= if_ndis -SRCS= if_ndis.c if_ndis_pci.c if_ndis_pccard.c +SRCS= if_ndis.c if_ndis_pci.c if_ndis_pccard.c if_ndis_u4b.c SRCS+= device_if.h bus_if.h pci_if.h card_if.h -SRCS+= opt_usb.h use_oldusb.h - -.if !defined(WANT_OLDUSB) -SRCS+= if_ndis_u4b.c -.else -SRCS+= if_ndis_usb.c -.endif +SRCS+= opt_usb.h .include diff --git a/sys/dev/netif/ndis/if_ndis.c b/sys/dev/netif/ndis/if_ndis.c index 489bb77f71..d76c8fe373 100644 --- a/sys/dev/netif/ndis/if_ndis.c +++ b/sys/dev/netif/ndis/if_ndis.c @@ -35,8 +35,6 @@ * then hacked upon mercilessly by me. */ -#include "use_oldusb.h" - #include #include #include @@ -73,13 +71,8 @@ #include #include -#if NOLDUSB == 0 #include #include -#else -#include -#include -#endif #include #include @@ -87,11 +80,7 @@ #include #include #include -#if NOLDUSB == 0 #include -#else -#include -#endif #include #define NDIS_DEBUG @@ -560,19 +549,11 @@ ndis_attach(device_t dev) lockinit(&sc->ndis_lock, "network driver", 0, LK_CANRECURSE); KeInitializeSpinLock(&sc->ndis_rxlock); -#if NOLDUSB == 0 KeInitializeSpinLock(&sc->ndisusb_tasklock); KeInitializeSpinLock(&sc->ndisusb_xferdonelock); -#else - KeInitializeSpinLock(&sc->ndisusb_xferlock); -#endif InitializeListHead(&sc->ndis_shlist); -#if NOLDUSB == 0 InitializeListHead(&sc->ndisusb_tasklist); InitializeListHead(&sc->ndisusb_xferdonelist); -#else - InitializeListHead(&sc->ndisusb_xferlist); -#endif callout_init_mp(&sc->ndis_stat_callout); if (sc->ndis_iftype == PCMCIABus) { @@ -636,14 +617,10 @@ ndis_attach(device_t dev) sc->ndis_startitem = IoAllocateWorkItem(sc->ndis_block->nmb_deviceobj); sc->ndis_resetitem = IoAllocateWorkItem(sc->ndis_block->nmb_deviceobj); sc->ndis_inputitem = IoAllocateWorkItem(sc->ndis_block->nmb_deviceobj); -#if NOLDUSB == 0 sc->ndisusb_xferdoneitem = IoAllocateWorkItem(sc->ndis_block->nmb_deviceobj); sc->ndisusb_taskitem = IoAllocateWorkItem(sc->ndis_block->nmb_deviceobj); -#else - sc->ndisusb_xferitem = IoAllocateWorkItem(sc->ndis_block->nmb_deviceobj); -#endif KeInitializeDpc(&sc->ndis_rxdpc, ndis_rxeof_xfr_wrap, sc->ndis_block); /* Call driver's init routine. */ @@ -1077,15 +1054,10 @@ ndis_detach(device_t dev) IoFreeWorkItem(sc->ndis_resetitem); if (sc->ndis_inputitem != NULL) IoFreeWorkItem(sc->ndis_inputitem); -#if NOLDUSB == 0 if (sc->ndisusb_xferdoneitem != NULL) IoFreeWorkItem(sc->ndisusb_xferdoneitem); if (sc->ndisusb_taskitem != NULL) IoFreeWorkItem(sc->ndisusb_taskitem); -#else - if (sc->ndisusb_xferitem != NULL) - IoFreeWorkItem(sc->ndisusb_xferitem); -#endif bus_generic_detach(dev); ndis_unload_driver(sc); diff --git a/sys/dev/netif/ndis/if_ndis_pccard.c b/sys/dev/netif/ndis/if_ndis_pccard.c index 99be0b2c84..3e7a9b4905 100644 --- a/sys/dev/netif/ndis/if_ndis_pccard.c +++ b/sys/dev/netif/ndis/if_ndis_pccard.c @@ -32,8 +32,6 @@ * $FreeBSD: src/sys/dev/if_ndis/if_ndis_pccard.c,v 1.21 2012/11/17 01:51:54 svnexp Exp $ */ -#include "use_oldusb.h" - #include #include #include @@ -53,13 +51,8 @@ #include -#if NOLDUSB == 0 #include #include -#else -#include -#include -#endif #include #include diff --git a/sys/dev/netif/ndis/if_ndis_pci.c b/sys/dev/netif/ndis/if_ndis_pci.c index 27b86c1e13..45ad02415f 100644 --- a/sys/dev/netif/ndis/if_ndis_pci.c +++ b/sys/dev/netif/ndis/if_ndis_pci.c @@ -32,8 +32,6 @@ * $FreeBSD: src/sys/dev/if_ndis/if_ndis_pci.c,v 1.26 2010/12/19 11:14:34 tijl Exp $ */ -#include "use_oldusb.h" - #include #include #include @@ -54,13 +52,8 @@ #include #include -#if NOLDUSB == 0 #include #include -#else -#include -#include -#endif #include #include diff --git a/sys/dev/netif/ndis/if_ndis_usb.c b/sys/dev/netif/ndis/if_ndis_usb.c deleted file mode 100644 index 9a878673da..0000000000 --- a/sys/dev/netif/ndis/if_ndis_usb.c +++ /dev/null @@ -1,263 +0,0 @@ -/*- - * Copyright (c) 2005 - * Bill Paul . 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. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Bill Paul. - * 4. Neither the name of the author nor the names of any co-contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY Bill Paul 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 Bill Paul OR THE VOICES IN HIS HEAD - * 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: src/sys/dev/if_ndis/if_ndis_usb.c,v 1.10 2008/12/27 08:03:32 weongyo Exp $ - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include - -#include -#include -#include -#include -#include - -#include - -#include -#include -#include -#include -#include -#include -#include - -SYSCTL_NODE(_hw, OID_AUTO, ndisusb, CTLFLAG_RD, 0, "NDIS USB driver parameters"); - -MODULE_DEPEND(if_ndis, usb, 1, 1, 1); - -static device_probe_t ndisusb_match; -static device_attach_t ndisusb_attach; -static device_detach_t ndisusb_detach; -static bus_get_resource_list_t ndis_get_resource_list; - -extern int ndisdrv_modevent (module_t, int, void *); -extern int ndis_attach (device_t); -extern int ndis_shutdown (device_t); -extern int ndis_detach (device_t); -extern int ndis_suspend (device_t); -extern int ndis_resume (device_t); - -extern unsigned char drv_data[]; - -static device_method_t ndis_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, ndisusb_match), - DEVMETHOD(device_attach, ndisusb_attach), - DEVMETHOD(device_detach, ndisusb_detach), - DEVMETHOD(device_shutdown, ndis_shutdown), - - /* bus interface */ - DEVMETHOD(bus_print_child, bus_generic_print_child), - DEVMETHOD(bus_driver_added, bus_generic_driver_added), - DEVMETHOD(bus_get_resource_list, ndis_get_resource_list), - - DEVMETHOD_END -}; - -static driver_t ndis_driver = { - "ndis", - ndis_methods, - sizeof(struct ndis_softc) -}; - -static devclass_t ndis_devclass; - -DRIVER_MODULE(if_ndis, uhub, ndis_driver, ndis_devclass, ndisdrv_modevent, - NULL); - -static int -ndisusb_devcompare(interface_type bustype, struct ndis_usb_type *t, device_t dev) -{ - struct usb_attach_arg *uaa; - - if (bustype != PNPBus) - return (FALSE); - - uaa = device_get_ivars(dev); - - while (t->ndis_name != NULL) { - if ((uaa->vendor == t->ndis_vid) && - (uaa->product == t->ndis_did)) { - device_set_desc(dev, t->ndis_name); - return (TRUE); - } - t++; - } - - return (FALSE); -} - -static int -ndisusb_match(device_t self) -{ - struct drvdb_ent *db; - struct usb_attach_arg *uaa = device_get_ivars(self); - - if (windrv_lookup(0, "USB Bus") == NULL) - return (UMATCH_NONE); - - if (uaa->iface != NULL) - return (UMATCH_NONE); - - db = windrv_match((matchfuncptr)ndisusb_devcompare, self); - if (db == NULL) - return (UMATCH_NONE); - - return (UMATCH_VENDOR_PRODUCT); -} - -static int -ndisusb_attach(device_t self) -{ - struct drvdb_ent *db; - struct ndisusb_softc *dummy = device_get_softc(self); - struct usb_attach_arg *uaa = device_get_ivars(self); - struct ndis_softc *sc; - struct ndis_usb_type *t; - driver_object *drv; - int devidx = 0; - usbd_status status; - - wlan_serialize_enter(); - sc = (struct ndis_softc *)dummy; - - if (uaa->device == NULL) { - wlan_serialize_exit(); - return ENXIO; - } - - db = windrv_match((matchfuncptr)ndisusb_devcompare, self); - if (db == NULL) { - wlan_serialize_exit(); - return (ENXIO); - } - - sc->ndis_dev = self; - sc->ndis_dobj = db->windrv_object; - sc->ndis_regvals = db->windrv_regvals; - sc->ndis_iftype = PNPBus; - - /* Create PDO for this device instance */ - - drv = windrv_lookup(0, "USB Bus"); - windrv_create_pdo(drv, self); - - status = usbd_set_config_no(uaa->device, NDISUSB_CONFIG_NO, 0); - if (status != USBD_NORMAL_COMPLETION) { - device_printf(self, "setting config no failed\n"); - wlan_serialize_exit(); - return (ENXIO); - } - - /* Figure out exactly which device we matched. */ - - t = db->windrv_devlist; - - while (t->ndis_name != NULL) { - if ((uaa->vendor == t->ndis_vid) && - (uaa->product == t->ndis_did)) { - sc->ndis_devidx = devidx; - break; - } - t++; - devidx++; - } - - if (ndis_attach(self) != 0) { - wlan_serialize_exit(); - return ENXIO; - } - - usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, uaa->device, self); - - wlan_serialize_exit(); - return 0; -} - -static int -ndisusb_detach(device_t self) -{ - int i, error; - struct ndis_softc *sc = device_get_softc(self); - struct usb_attach_arg *uaa = device_get_ivars(self); - - wlan_serialize_enter(); - sc->ndisusb_status |= NDISUSB_STATUS_DETACH; - - for (i = 0; i < NDISUSB_ENDPT_MAX; i++) { - if (sc->ndisusb_ep[i] == NULL) - continue; - - usbd_abort_pipe(sc->ndisusb_ep[i]); - usbd_close_pipe(sc->ndisusb_ep[i]); - sc->ndisusb_ep[i] = NULL; - } - - if (sc->ndisusb_iin_buf != NULL) { - kfree(sc->ndisusb_iin_buf, M_USBDEV); - sc->ndisusb_iin_buf = NULL; - } - - ndis_pnpevent_nic(self, NDIS_PNP_EVENT_SURPRISE_REMOVED); - - usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, uaa->device, self); - - error = ndis_detach(self); - - wlan_serialize_exit(); - return error; -} - -static struct resource_list * -ndis_get_resource_list(device_t dev, device_t child) -{ - struct ndis_softc *sc; - - sc = device_get_softc(dev); - return (BUS_GET_RESOURCE_LIST(device_get_parent(sc->ndis_dev), dev)); -} diff --git a/sys/dev/netif/ndis/if_ndisvar.h b/sys/dev/netif/ndis/if_ndisvar.h index 03fbdc69a3..8840b777fc 100644 --- a/sys/dev/netif/ndis/if_ndisvar.h +++ b/sys/dev/netif/ndis/if_ndisvar.h @@ -32,8 +32,6 @@ * $FreeBSD: src/sys/dev/if_ndis/if_ndisvar.h,v 1.39 2009/05/02 15:14:18 thompsa Exp $ */ -#include "use_oldusb.h" - #define NDIS_DEFAULT_NODENAME "FreeBSD NDIS node" #define NDIS_NODENAME_LEN 32 @@ -115,7 +113,6 @@ struct ndis_vap { }; #define NDIS_VAP(vap) ((struct ndis_vap *)(vap)) -#if NOLDUSB == 0 #define NDISUSB_CONFIG_NO 0 #define NDISUSB_IFACE_INDEX 0 /* XXX at USB2 there's no USBD_NO_TIMEOUT macro anymore */ @@ -153,18 +150,6 @@ struct ndisusb_task { void *nt_ctx; list_entry nt_tasklist; }; -#else /* !NOLDUSB == 0 */ -#define NDISUSB_CONFIG_NO 1 -#define NDISUSB_IFACE_INDEX 0 -#define NDISUSB_INTR_TIMEOUT 1000 -#define NDISUSB_TX_TIMEOUT 10000 -struct ndisusb_xfer { - usbd_xfer_handle nx_xfer; - usbd_private_handle nx_priv; - usbd_status nx_status; - list_entry nx_xferlist; -}; -#endif struct ndis_softc { struct ifnet *ifp; @@ -242,7 +227,6 @@ struct ndis_softc { int ndis_tx_timer; int ndis_hang_timer; -#if NOLDUSB == 0 struct usb_device *ndisusb_dev; struct lock ndisusb_lock; struct ndisusb_ep ndisusb_dread_ep; @@ -270,33 +254,3 @@ struct ndis_softc { #define NDISUSB_LOCK(_sc) lockmgr(&(_sc)->ndisusb_lock, LK_EXCLUSIVE) #define NDISUSB_UNLOCK(_sc) lockmgr(&(_sc)->ndisusb_lock, LK_RELEASE) #define NDISUSB_LOCK_ASSERT(_sc, t) KKASSERT(lockstatus(&(_sc)->ndisusb_lock, curthread) != 0) -#else /* !NOLDUSB == 0 */ - io_workitem *ndisusb_xferitem; - list_entry ndisusb_xferlist; - kspin_lock ndisusb_xferlock; -#define NDISUSB_ENDPT_BOUT 0 -#define NDISUSB_ENDPT_BIN 1 -#define NDISUSB_ENDPT_IIN 2 -#define NDISUSB_ENDPT_IOUT 3 -#define NDISUSB_ENDPT_MAX 4 - usbd_pipe_handle ndisusb_ep[NDISUSB_ENDPT_MAX]; - char *ndisusb_iin_buf; - int ndisusb_status; -#define NDISUSB_STATUS_DETACH 0x1 -}; - -#define NDISMTX_LOCK(_sc) lockmgr(&(_sc)->ndis_lock, LK_EXCLUSIVE) -#define NDISMTX_UNLOCK(_sc) lockmgr(&(_sc)->ndis_lock, LK_RELEASE) -#define NDISUSB_LOCK(_sc) get_mplock() -#define NDISUSB_UNLOCK(_sc) rel_mplock() -#define NDIS_LOCK(_sc) do { \ - if ((_sc)->ndis_iftype == PNPBus) \ - NDISUSB_LOCK(_sc); \ - NDISMTX_LOCK(_sc); \ -} while (0) -#define NDIS_UNLOCK(_sc) do { \ - if ((_sc)->ndis_iftype == PNPBus) \ - NDISUSB_UNLOCK(_sc); \ - NDISMTX_UNLOCK(_sc); \ -} while (0) -#endif diff --git a/sys/dev/netif/rue/Makefile b/sys/dev/netif/rue/Makefile deleted file mode 100644 index ddad325af3..0000000000 --- a/sys/dev/netif/rue/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -# $FreeBSD: src/sys/modules/rue/Makefile,v 1.2 2004/06/27 12:33:16 imp Exp $ -# $DragonFly: src/sys/dev/netif/rue/Makefile,v 1.1 2005/09/19 02:53:27 sephe Exp $ - -KMOD= if_rue -SRCS= if_rue.c -SRCS+= miibus_if.h device_if.h bus_if.h opt_usb.h - -.include diff --git a/sys/dev/netif/rue/if_rue.c b/sys/dev/netif/rue/if_rue.c deleted file mode 100644 index 99aacf5c19..0000000000 --- a/sys/dev/netif/rue/if_rue.c +++ /dev/null @@ -1,1380 +0,0 @@ -/*- - * Copyright (c) 2001-2003, Shunsuke Akiyama . - * 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. - */ -/*- - * Copyright (c) 1997, 1998, 1999, 2000 - * Bill Paul . 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. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Bill Paul. - * 4. Neither the name of the author nor the names of any co-contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY Bill Paul 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 Bill Paul OR THE VOICES IN HIS HEAD - * 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: src/sys/dev/usb/if_rue.c,v 1.14 2004/06/09 14:34:03 naddy Exp $ - */ - -/* - * RealTek RTL8150 USB to fast ethernet controller driver. - * Datasheet is available from - * ftp://ftp.realtek.com.tw/lancard/data_sheet/8150/. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include - -#include -#include -#include -#include -#include - -#include -#include - -#include - -#include "miibus_if.h" - -#ifdef RUE_DEBUG -SYSCTL_NODE(_hw, OID_AUTO, rue, CTLFLAG_RW, 0, "USB rue"); - -static int rue_debug = 0; -SYSCTL_INT(_hw_rue, OID_AUTO, debug, CTLFLAG_RW, &rue_debug, 0, - "rue debug level"); - -/* XXX DPRINTF/DPRINTFN can be used only after rue_attach() */ -#define DPRINTFN(n, x) do { if (rue_debug > (n)) if_printf x; } while (0) -#else -#define DPRINTFN(n, x) -#endif -#define DPRINTF(x) DPRINTFN(0, x) - -/* - * Various supported device vendors/products. - */ - -static const struct usb_devno rue_devs[] = { - { USB_DEVICE(0x0411, 0x0012) }, /* Melco LUA-KTX*/ - { USB_DEVICE(0x0bda, 0x8150) }, /* Realtek USBKR100 (GREEN HOUSE) */ -}; - -static int rue_match(device_t); -static int rue_attach(device_t); -static int rue_detach(device_t); - -static int rue_tx_list_init(struct rue_softc *); -static int rue_rx_list_init(struct rue_softc *); -static int rue_newbuf(struct rue_softc *, struct rue_chain *, struct mbuf *); -static int rue_encap(struct rue_softc *, struct mbuf *, int); -#ifdef RUE_INTR_PIPE -static void rue_intr(usbd_xfer_handle, usbd_private_handle, usbd_status); -#endif -static void rue_rxeof(usbd_xfer_handle, usbd_private_handle, usbd_status); -static void rue_txeof(usbd_xfer_handle, usbd_private_handle, usbd_status); -static void rue_tick(void *); -static void rue_rxstart(struct ifnet *); -static void rue_start(struct ifnet *, struct ifaltq_subque *); -static int rue_ioctl(struct ifnet *, u_long, caddr_t, struct ucred *); -static void rue_init(void *); -static void rue_stop(struct rue_softc *); -static void rue_watchdog(struct ifnet *); -static void rue_shutdown(device_t); -static int rue_ifmedia_upd(struct ifnet *); -static void rue_ifmedia_sts(struct ifnet *, struct ifmediareq *); - -static int rue_miibus_readreg(device_t, int, int); -static int rue_miibus_writereg(device_t, int, int, int); -static void rue_miibus_statchg(device_t); - -static void rue_setmulti(struct rue_softc *); -static void rue_reset(struct rue_softc *); - -static int rue_read_mem(struct rue_softc *, u_int16_t, void *, u_int16_t); -static int rue_write_mem(struct rue_softc *, u_int16_t, void *, u_int16_t); -static int rue_csr_read_1(struct rue_softc *, int); -static int rue_csr_write_1(struct rue_softc *, int, u_int8_t); -static int rue_csr_read_2(struct rue_softc *, int); -static int rue_csr_write_2(struct rue_softc *, int, u_int16_t); -static int rue_csr_write_4(struct rue_softc *, int, u_int32_t); - -static device_method_t rue_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, rue_match), - DEVMETHOD(device_attach, rue_attach), - DEVMETHOD(device_detach, rue_detach), - DEVMETHOD(device_shutdown, rue_shutdown), - - /* Bus interface */ - DEVMETHOD(bus_print_child, bus_generic_print_child), - DEVMETHOD(bus_driver_added, bus_generic_driver_added), - - /* MII interface */ - DEVMETHOD(miibus_readreg, rue_miibus_readreg), - DEVMETHOD(miibus_writereg, rue_miibus_writereg), - DEVMETHOD(miibus_statchg, rue_miibus_statchg), - - DEVMETHOD_END -}; - -static driver_t rue_driver = { - "rue", - rue_methods, - sizeof(struct rue_softc) -}; - -static devclass_t rue_devclass; - -DRIVER_MODULE(rue, uhub, rue_driver, rue_devclass, usbd_driver_load, NULL); -DRIVER_MODULE(miibus, rue, miibus_driver, miibus_devclass, NULL, NULL); -MODULE_DEPEND(rue, usb, 1, 1, 1); -MODULE_DEPEND(rue, miibus, 1, 1, 1); - -#define RUE_SETBIT(sc, reg, x) \ - rue_csr_write_1(sc, reg, rue_csr_read_1(sc, reg) | (x)) - -#define RUE_CLRBIT(sc, reg, x) \ - rue_csr_write_1(sc, reg, rue_csr_read_1(sc, reg) & ~(x)) - -#define RUE_SETBIT_2(sc, reg, x) \ - rue_csr_write_2(sc, reg, rue_csr_read_2(sc, reg) | (x)) - -#define RUE_CLRBIT_2(sc, reg, x) \ - rue_csr_write_2(sc, reg, rue_csr_read_2(sc, reg) & ~(x)) - -static int -rue_read_mem(struct rue_softc *sc, u_int16_t addr, void *buf, u_int16_t len) -{ - usb_device_request_t req; - usbd_status err; - - if (sc->rue_dying) - return (0); - - req.bmRequestType = UT_READ_VENDOR_DEVICE; - req.bRequest = UR_SET_ADDRESS; - USETW(req.wValue, addr); - USETW(req.wIndex, 0); - USETW(req.wLength, len); - - err = usbd_do_request(sc->rue_udev, &req, buf); - - if (err) { - if_printf(&sc->arpcom.ac_if, "control pipe read failed: %s\n", - usbd_errstr(err)); - return (-1); - } - - return (0); -} - -static int -rue_write_mem(struct rue_softc *sc, u_int16_t addr, void *buf, u_int16_t len) -{ - usb_device_request_t req; - usbd_status err; - - if (sc->rue_dying) - return (0); - - req.bmRequestType = UT_WRITE_VENDOR_DEVICE; - req.bRequest = UR_SET_ADDRESS; - USETW(req.wValue, addr); - USETW(req.wIndex, 0); - USETW(req.wLength, len); - - err = usbd_do_request(sc->rue_udev, &req, buf); - - if (err) { - if_printf(&sc->arpcom.ac_if, "control pipe write failed: %s\n", - usbd_errstr(err)); - return (-1); - } - - return (0); -} - -static int -rue_csr_read_1(struct rue_softc *sc, int reg) -{ - int err; - u_int8_t val = 0; - - err = rue_read_mem(sc, reg, &val, 1); - - if (err) - return (0); - - return (val); -} - -static int -rue_csr_read_2(struct rue_softc *sc, int reg) -{ - int err; - u_int16_t val = 0; - uWord w; - - USETW(w, val); - err = rue_read_mem(sc, reg, &w, 2); - val = UGETW(w); - - if (err) - return (0); - - return (val); -} - -static int -rue_csr_write_1(struct rue_softc *sc, int reg, u_int8_t val) -{ - int err; - - err = rue_write_mem(sc, reg, &val, 1); - - if (err) - return (-1); - - return (0); -} - -static int -rue_csr_write_2(struct rue_softc *sc, int reg, u_int16_t val) -{ - int err; - uWord w; - - USETW(w, val); - err = rue_write_mem(sc, reg, &w, 2); - - if (err) - return (-1); - - return (0); -} - -static int -rue_csr_write_4(struct rue_softc *sc, int reg, u_int32_t val) -{ - int err; - uDWord dw; - - USETDW(dw, val); - err = rue_write_mem(sc, reg, &dw, 4); - - if (err) - return (-1); - - return (0); -} - -static int -rue_miibus_readreg(device_t dev, int phy, int reg) -{ - struct rue_softc *sc = device_get_softc(dev); - int rval; - int ruereg; - - if (phy != 0) /* RTL8150 supports PHY == 0, only */ - return (0); - - switch (reg) { - case MII_BMCR: - ruereg = RUE_BMCR; - break; - case MII_BMSR: - ruereg = RUE_BMSR; - break; - case MII_ANAR: - ruereg = RUE_ANAR; - break; - case MII_ANER: - ruereg = RUE_AER; - break; - case MII_ANLPAR: - ruereg = RUE_ANLP; - break; - case MII_PHYIDR1: - case MII_PHYIDR2: - return (0); - break; - default: - if (RUE_REG_MIN <= reg && reg <= RUE_REG_MAX) { - rval = rue_csr_read_1(sc, reg); - return (rval); - } - if_printf(&sc->arpcom.ac_if, "bad phy register\n"); - return (0); - } - - if (sc->arpcom.ac_if.if_serializer && - IS_SERIALIZED(sc->arpcom.ac_if.if_serializer)) { - RUE_UNLOCK(sc); - rval = rue_csr_read_2(sc, ruereg); - RUE_LOCK(sc); - } else { - rval = rue_csr_read_2(sc, ruereg); - } - - return (rval); -} - -static int -rue_miibus_writereg(device_t dev, int phy, int reg, int data) -{ - struct rue_softc *sc = device_get_softc(dev); - int ruereg; - - if (phy != 0) /* RTL8150 supports PHY == 0, only */ - return (0); - - switch (reg) { - case MII_BMCR: - ruereg = RUE_BMCR; - break; - case MII_BMSR: - ruereg = RUE_BMSR; - break; - case MII_ANAR: - ruereg = RUE_ANAR; - break; - case MII_ANER: - ruereg = RUE_AER; - break; - case MII_ANLPAR: - ruereg = RUE_ANLP; - break; - case MII_PHYIDR1: - case MII_PHYIDR2: - return (0); - break; - default: - if (RUE_REG_MIN <= reg && reg <= RUE_REG_MAX) { - rue_csr_write_1(sc, reg, data); - return (0); - } - if_printf(&sc->arpcom.ac_if, "bad phy register\n"); - return (0); - } - if (sc->arpcom.ac_if.if_serializer && - IS_SERIALIZED(sc->arpcom.ac_if.if_serializer)) { - RUE_UNLOCK(sc); - rue_csr_write_2(sc, ruereg, data); - RUE_LOCK(sc); - } else { - rue_csr_write_2(sc, ruereg, data); - } - - return (0); -} - -static void -rue_miibus_statchg(device_t dev) -{ -} - -/* - * Program the 64-bit multicast hash filter. - */ - -static void -rue_setmulti(struct rue_softc *sc) -{ - struct ifnet *ifp; - int h = 0; - u_int32_t hashes[2] = { 0, 0 }; - struct ifmultiaddr *ifma; - u_int32_t rxcfg; - int mcnt = 0; - - ifp = &sc->arpcom.ac_if; - - rxcfg = rue_csr_read_2(sc, RUE_RCR); - - if (ifp->if_flags & IFF_ALLMULTI || ifp->if_flags & IFF_PROMISC) { - rxcfg |= (RUE_RCR_AAM | RUE_RCR_AAP); - rxcfg &= ~RUE_RCR_AM; - rue_csr_write_2(sc, RUE_RCR, rxcfg); - rue_csr_write_4(sc, RUE_MAR0, 0xFFFFFFFF); - rue_csr_write_4(sc, RUE_MAR4, 0xFFFFFFFF); - return; - } - - /* first, zot all the existing hash bits */ - rue_csr_write_4(sc, RUE_MAR0, 0); - rue_csr_write_4(sc, RUE_MAR4, 0); - - /* now program new ones */ - TAILQ_FOREACH (ifma, &ifp->if_multiaddrs, ifma_link) { - if (ifma->ifma_addr->sa_family != AF_LINK) - continue; - h = ether_crc32_be(LLADDR((struct sockaddr_dl *) - ifma->ifma_addr), ETHER_ADDR_LEN) >> 26; - if (h < 32) - hashes[0] |= (1 << h); - else - hashes[1] |= (1 << (h - 32)); - mcnt++; - } - - if (mcnt) - rxcfg |= RUE_RCR_AM; - else - rxcfg &= ~RUE_RCR_AM; - - rxcfg &= ~(RUE_RCR_AAM | RUE_RCR_AAP); - - rue_csr_write_2(sc, RUE_RCR, rxcfg); - rue_csr_write_4(sc, RUE_MAR0, hashes[0]); - rue_csr_write_4(sc, RUE_MAR4, hashes[1]); -} - -static void -rue_reset(struct rue_softc *sc) -{ - int i; - - rue_csr_write_1(sc, RUE_CR, RUE_CR_SOFT_RST); - - for (i = 0; i < RUE_TIMEOUT; i++) { - DELAY(500); - if (!(rue_csr_read_1(sc, RUE_CR) & RUE_CR_SOFT_RST)) - break; - } - if (i == RUE_TIMEOUT) - if_printf(&sc->arpcom.ac_if, "reset never completed!\n"); - - DELAY(10000); -} - -/* - * Probe for a RTL8150 chip. - */ - -static int -rue_match(device_t self) -{ - struct usb_attach_arg *uaa = device_get_ivars(self); - - if (uaa->iface == NULL) - return (UMATCH_NONE); - - return (usb_lookup(rue_devs, uaa->vendor, uaa->product) != NULL ? - UMATCH_VENDOR_PRODUCT : UMATCH_NONE); -} - -/* - * Attach the interface. Allocate softc structures, do ifmedia - * setup and ethernet/BPF attach. - */ - -static int -rue_attach(device_t self) -{ - struct rue_softc *sc = device_get_softc(self); - struct usb_attach_arg *uaa = device_get_ivars(self); - uint8_t eaddr[ETHER_ADDR_LEN]; - struct ifnet *ifp; - usb_interface_descriptor_t *id; - usb_endpoint_descriptor_t *ed; - int i; - - sc->rue_udev = uaa->device; - - if (usbd_set_config_no(sc->rue_udev, RUE_CONFIG_NO, 0)) { - device_printf(self, "setting config no %d failed\n", - RUE_CONFIG_NO); - return ENXIO; - } - - if (usbd_device2interface_handle(uaa->device, RUE_IFACE_IDX, - &sc->rue_iface)) { - device_printf(self, "getting interface handle failed\n"); - return ENXIO; - } - - id = usbd_get_interface_descriptor(sc->rue_iface); - - /* Find endpoints */ - for (i = 0; i < id->bNumEndpoints; i++) { - ed = usbd_interface2endpoint_descriptor(sc->rue_iface, i); - if (ed == NULL) { - device_printf(self, "couldn't get ep %d\n", i); - return ENXIO; - } - if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && - UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) { - sc->rue_ed[RUE_ENDPT_RX] = ed->bEndpointAddress; - } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT && - UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) { - sc->rue_ed[RUE_ENDPT_TX] = ed->bEndpointAddress; - } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && - UE_GET_XFERTYPE(ed->bmAttributes) == UE_INTERRUPT) { - sc->rue_ed[RUE_ENDPT_INTR] = ed->bEndpointAddress; - } - } - - ifp = &sc->arpcom.ac_if; - if_initname(ifp, device_get_name(self), device_get_unit(self)); - - /* Reset the adapter */ - rue_reset(sc); - - /* Get station address from the EEPROM */ - if (rue_read_mem(sc, RUE_EEPROM_IDR0, eaddr, ETHER_ADDR_LEN)) { - device_printf(self, "couldn't get station address\n"); - return ENXIO; - } - - ifp->if_softc = sc; - ifp->if_mtu = ETHERMTU; - ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; - ifp->if_ioctl = rue_ioctl; - ifp->if_start = rue_start; - ifp->if_watchdog = rue_watchdog; - ifp->if_init = rue_init; - ifp->if_baudrate = 10000000; - ifq_set_maxlen(&ifp->if_snd, IFQ_MAXLEN); - ifq_set_ready(&ifp->if_snd); - - /* MII setup */ - if (mii_phy_probe(self, &sc->rue_miibus, - rue_ifmedia_upd, rue_ifmedia_sts)) { - device_printf(self, "MII without any PHY!\n"); - return ENXIO; - } - - /* Call MI attach routine */ - ether_ifattach(ifp, eaddr, NULL); - - callout_init(&sc->rue_stat_ch); - sc->rue_dying = 0; - - usb_register_netisr(); - - return 0; -} - -static int -rue_detach(device_t dev) -{ - struct rue_softc *sc; - struct ifnet *ifp; - - sc = device_get_softc(dev); - RUE_LOCK(sc); - ifp = &sc->arpcom.ac_if; - - sc->rue_dying = 1; - callout_stop(&sc->rue_stat_ch); - - ether_ifdetach(ifp); - - if (sc->rue_ep[RUE_ENDPT_TX] != NULL) - usbd_abort_pipe(sc->rue_ep[RUE_ENDPT_TX]); - if (sc->rue_ep[RUE_ENDPT_RX] != NULL) - usbd_abort_pipe(sc->rue_ep[RUE_ENDPT_RX]); -#ifdef RUE_INTR_PIPE - if (sc->rue_ep[RUE_ENDPT_INTR] != NULL) - usbd_abort_pipe(sc->rue_ep[RUE_ENDPT_INTR]); -#endif - - RUE_UNLOCK(sc); - - return (0); -} - -/* - * Initialize an RX descriptor and attach an MBUF cluster. - */ - -static int -rue_newbuf(struct rue_softc *sc, struct rue_chain *c, struct mbuf *m) -{ - struct mbuf *m_new = NULL; - - if (m == NULL) { - m_new = m_getcl(MB_DONTWAIT, MT_DATA, M_PKTHDR); - if (m_new == NULL) { - if_printf(&sc->arpcom.ac_if, "no memory for rx list " - "-- packet dropped!\n"); - return (ENOBUFS); - } - m_new->m_len = m_new->m_pkthdr.len = MCLBYTES; - } else { - m_new = m; - m_new->m_len = m_new->m_pkthdr.len = MCLBYTES; - m_new->m_data = m_new->m_ext.ext_buf; - } - - m_adj(m_new, ETHER_ALIGN); - c->rue_mbuf = m_new; - - return (0); -} - -static int -rue_rx_list_init(struct rue_softc *sc) -{ - struct rue_cdata *cd; - struct rue_chain *c; - int i; - - cd = &sc->rue_cdata; - for (i = 0; i < RUE_RX_LIST_CNT; i++) { - c = &cd->rue_rx_chain[i]; - c->rue_sc = sc; - c->rue_idx = i; - if (rue_newbuf(sc, c, NULL) == ENOBUFS) - return (ENOBUFS); - if (c->rue_xfer == NULL) { - c->rue_xfer = usbd_alloc_xfer(sc->rue_udev); - if (c->rue_xfer == NULL) - return (ENOBUFS); - } - } - - return (0); -} - -static int -rue_tx_list_init(struct rue_softc *sc) -{ - struct rue_cdata *cd; - struct rue_chain *c; - int i; - - cd = &sc->rue_cdata; - for (i = 0; i < RUE_TX_LIST_CNT; i++) { - c = &cd->rue_tx_chain[i]; - c->rue_sc = sc; - c->rue_idx = i; - c->rue_mbuf = NULL; - if (c->rue_xfer == NULL) { - c->rue_xfer = usbd_alloc_xfer(sc->rue_udev); - if (c->rue_xfer == NULL) - return (ENOBUFS); - } - c->rue_buf = kmalloc(RUE_BUFSZ, M_USBDEV, M_WAITOK); - } - - return (0); -} - -#ifdef RUE_INTR_PIPE -static void -rue_intr(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status) -{ - struct rue_softc *sc = priv; - struct ifnet *ifp; - struct rue_intrpkt *p; - - RUE_LOCK(sc); - ifp = &sc->arpcom.ac_if; - - if (!(ifp->if_flags & IFF_RUNNING)) { - RUE_UNLOCK(sc); - return; - } - - if (status != USBD_NORMAL_COMPLETION) { - if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) { - RUE_UNLOCK(sc); - return; - } - if_printf(ifp, "usb error on intr: %s\n", usbd_errstr(status)); - if (status == USBD_STALLED) - usbd_clear_endpoint_stall(sc->rue_ep[RUE_ENDPT_INTR]); - RUE_UNLOCK(sc); - return; - } - - usbd_get_xfer_status(xfer, NULL, (void **)&p, NULL, NULL); - - IFNET_STAT_INC(ifp, ierrors, p->rue_rxlost_cnt); - IFNET_STAT_INC(ifp, ierrors, p->rue_crcerr_cnt); - IFNET_STAT_INC(ifp, collisions, p->rue_col_cnt); - - RUE_UNLOCK(sc); -} -#endif - -static void -rue_rxstart(struct ifnet *ifp) -{ - struct rue_softc *sc; - struct rue_chain *c; - - sc = ifp->if_softc; - c = &sc->rue_cdata.rue_rx_chain[sc->rue_cdata.rue_rx_prod]; - - if (rue_newbuf(sc, c, NULL) == ENOBUFS) { - IFNET_STAT_INC(ifp, ierrors, 1); - return; - } - - /* Setup new transfer. */ - usbd_setup_xfer(c->rue_xfer, sc->rue_ep[RUE_ENDPT_RX], - c, mtod(c->rue_mbuf, char *), RUE_BUFSZ, USBD_SHORT_XFER_OK, - USBD_NO_TIMEOUT, rue_rxeof); - usbd_transfer(c->rue_xfer); -} - -/* - * A frame has been uploaded: pass the resulting mbuf chain up to - * the higher level protocols. - */ - -static void -rue_rxeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status) -{ - struct rue_chain *c = priv; - struct rue_softc *sc = c->rue_sc; - struct mbuf *m; - struct ifnet *ifp; - int total_len = 0; - struct rue_rxpkt r; - - if (sc->rue_dying) - return; - RUE_LOCK(sc); - ifp = &sc->arpcom.ac_if; - - if (!(ifp->if_flags & IFF_RUNNING)) { - RUE_UNLOCK(sc); - return; - } - - if (status != USBD_NORMAL_COMPLETION) { - if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) { - RUE_UNLOCK(sc); - return; - } - if (usbd_ratecheck(&sc->rue_rx_notice)) { - if_printf(ifp, "usb error on rx: %s\n", - usbd_errstr(status)); - } - if (status == USBD_STALLED) - usbd_clear_endpoint_stall(sc->rue_ep[RUE_ENDPT_RX]); - goto done; - } - - usbd_get_xfer_status(xfer, NULL, NULL, &total_len, NULL); - - if (total_len <= ETHER_CRC_LEN) { - IFNET_STAT_INC(ifp, ierrors, 1); - goto done; - } - - m = c->rue_mbuf; - bcopy(mtod(m, char *) + total_len - 4, (char *)&r, sizeof (r)); - - /* Check recieve packet was valid or not */ - if ((r.rue_rxstat & RUE_RXSTAT_VALID) == 0) { - IFNET_STAT_INC(ifp, ierrors, 1); - goto done; - } - - /* No errors; receive the packet. */ - total_len -= ETHER_CRC_LEN; - - IFNET_STAT_INC(ifp, ipackets, 1); - m->m_pkthdr.rcvif = ifp; - m->m_pkthdr.len = m->m_len = total_len; - - /* Put the packet on the special USB input queue. */ - usb_ether_input(m); - rue_rxstart(ifp); - RUE_UNLOCK(sc); - return; - - done: - /* Setup new transfer. */ - usbd_setup_xfer(xfer, sc->rue_ep[RUE_ENDPT_RX], - c, mtod(c->rue_mbuf, char *), RUE_BUFSZ, - USBD_SHORT_XFER_OK, USBD_NO_TIMEOUT, rue_rxeof); - usbd_transfer(xfer); - RUE_UNLOCK(sc); -} - -/* - * A frame was downloaded to the chip. It's safe for us to clean up - * the list buffers. - */ - -static void -rue_txeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status) -{ - struct rue_chain *c = priv; - struct rue_softc *sc = c->rue_sc; - struct ifnet *ifp; - usbd_status err; - - RUE_LOCK(sc); - - ifp = &sc->arpcom.ac_if; - - if (status != USBD_NORMAL_COMPLETION) { - if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) { - RUE_UNLOCK(sc); - return; - } - if_printf(ifp, "usb error on tx: %s\n", usbd_errstr(status)); - if (status == USBD_STALLED) - usbd_clear_endpoint_stall(sc->rue_ep[RUE_ENDPT_TX]); - RUE_UNLOCK(sc); - return; - } - - ifp->if_timer = 0; - ifq_clr_oactive(&ifp->if_snd); - usbd_get_xfer_status(c->rue_xfer, NULL, NULL, NULL, &err); - - if (c->rue_mbuf != NULL) { - m_freem(c->rue_mbuf); - c->rue_mbuf = NULL; - } - - if (err) - IFNET_STAT_INC(ifp, oerrors, 1); - else - IFNET_STAT_INC(ifp, opackets, 1); - - if (!ifq_is_empty(&ifp->if_snd)) - if_devstart(ifp); - - RUE_UNLOCK(sc); -} - -static void -rue_tick(void *xsc) -{ - struct rue_softc *sc = xsc; - struct ifnet *ifp; - struct mii_data *mii; - - if (sc == NULL) - return; - - RUE_LOCK(sc); - - ifp = &sc->arpcom.ac_if; - mii = GET_MII(sc); - if (mii == NULL) { - RUE_UNLOCK(sc); - return; - } - - /* - * USB mii functions make usb calls, we must unlock to avoid - * deadlocking on the usb bus if the request queue is full. - */ - RUE_UNLOCK(sc); - mii_tick(mii); - RUE_LOCK(sc); - - if (!(sc->rue_link && mii->mii_media_status & IFM_ACTIVE) && - IFM_SUBTYPE(mii->mii_media_active) != IFM_NONE) { - sc->rue_link++; - if (!ifq_is_empty(&ifp->if_snd)) - if_devstart(ifp); - } - - callout_reset(&sc->rue_stat_ch, hz, rue_tick, sc); - - RUE_UNLOCK(sc); -} - -static int -rue_encap(struct rue_softc *sc, struct mbuf *m, int idx) -{ - int total_len; - struct rue_chain *c; - usbd_status err; - - c = &sc->rue_cdata.rue_tx_chain[idx]; - - /* - * Copy the mbuf data into a contiguous buffer - */ - m_copydata(m, 0, m->m_pkthdr.len, c->rue_buf); - c->rue_mbuf = m; - - total_len = m->m_pkthdr.len; - - /* - * This is an undocumented behavior. - * RTL8150 chip doesn't send frame length smaller than - * RUE_MIN_FRAMELEN (60) byte packet. - */ - if (total_len < RUE_MIN_FRAMELEN) - total_len = RUE_MIN_FRAMELEN; - - usbd_setup_xfer(c->rue_xfer, sc->rue_ep[RUE_ENDPT_TX], - c, c->rue_buf, total_len, USBD_FORCE_SHORT_XFER, - 10000, rue_txeof); - - /* Transmit */ - err = usbd_transfer(c->rue_xfer); - if (err != USBD_IN_PROGRESS) { - rue_stop(sc); - return (EIO); - } - - sc->rue_cdata.rue_tx_cnt++; - - return (0); -} - -static void -rue_start(struct ifnet *ifp, struct ifaltq_subque *ifsq) -{ - struct rue_softc *sc = ifp->if_softc; - struct mbuf *m_head = NULL; - - ASSERT_ALTQ_SQ_DEFAULT(ifp, ifsq); - - if (!sc->rue_link) { - ifq_purge(&ifp->if_snd); - return; - } - - if (ifq_is_oactive(&ifp->if_snd)) { - return; - } - - m_head = ifq_dequeue(&ifp->if_snd); - if (m_head == NULL) { - return; - } - - if (rue_encap(sc, m_head, 0)) { - /* rue_encap() will free m_head, if we reach here */ - ifq_set_oactive(&ifp->if_snd); - return; - } - - /* - * If there's a BPF listener, bounce a copy of this frame - * to him. - */ - BPF_MTAP(ifp, m_head); - - ifq_set_oactive(&ifp->if_snd); - - /* - * Set a timeout in case the chip goes out to lunch. - */ - ifp->if_timer = 5; -} - -static void -rue_init(void *xsc) -{ - struct rue_softc *sc = xsc; - struct ifnet *ifp = &sc->arpcom.ac_if; - struct mii_data *mii = GET_MII(sc); - struct rue_chain *c; - usbd_status err; - int i; - int rxcfg; - - if (ifp->if_flags & IFF_RUNNING) { - return; - } - - /* - * Cancel pending I/O and free all RX/TX buffers. - */ - rue_reset(sc); - - /* Set MAC address */ - rue_write_mem(sc, RUE_IDR0, sc->arpcom.ac_enaddr, ETHER_ADDR_LEN); - - /* Init TX ring. */ - if (rue_tx_list_init(sc) == ENOBUFS) { - if_printf(ifp, "tx list init failed\n"); - return; - } - - /* Init RX ring. */ - if (rue_rx_list_init(sc) == ENOBUFS) { - if_printf(ifp, "rx list init failed\n"); - return; - } - -#ifdef RUE_INTR_PIPE - sc->rue_cdata.rue_ibuf = kmalloc(RUE_INTR_PKTLEN, M_USBDEV, M_WAITOK); -#endif - - /* - * Set the initial TX and RX configuration. - */ - rue_csr_write_1(sc, RUE_TCR, RUE_TCR_CONFIG); - - rxcfg = RUE_RCR_CONFIG; - - /* Set capture broadcast bit to capture broadcast frames. */ - if (ifp->if_flags & IFF_BROADCAST) - rxcfg |= RUE_RCR_AB; - else - rxcfg &= ~RUE_RCR_AB; - - /* If we want promiscuous mode, set the allframes bit. */ - if (ifp->if_flags & IFF_PROMISC) - rxcfg |= RUE_RCR_AAP; - else - rxcfg &= ~RUE_RCR_AAP; - - rue_csr_write_2(sc, RUE_RCR, rxcfg); - - /* Load the multicast filter. */ - rue_setmulti(sc); - - /* Enable RX and TX */ - rue_csr_write_1(sc, RUE_CR, (RUE_CR_TE | RUE_CR_RE | RUE_CR_EP3CLREN)); - - mii_mediachg(mii); - - /* Open RX and TX pipes. */ - err = usbd_open_pipe(sc->rue_iface, sc->rue_ed[RUE_ENDPT_RX], - USBD_EXCLUSIVE_USE, &sc->rue_ep[RUE_ENDPT_RX]); - if (err) { - if_printf(ifp, "open rx pipe failed: %s\n", usbd_errstr(err)); - return; - } - err = usbd_open_pipe(sc->rue_iface, sc->rue_ed[RUE_ENDPT_TX], - USBD_EXCLUSIVE_USE, &sc->rue_ep[RUE_ENDPT_TX]); - if (err) { - if_printf(ifp, "open tx pipe failed: %s\n", usbd_errstr(err)); - return; - } - -#ifdef RUE_INTR_PIPE - err = usbd_open_pipe_intr(sc->rue_iface, sc->rue_ed[RUE_ENDPT_INTR], - USBD_SHORT_XFER_OK, - &sc->rue_ep[RUE_ENDPT_INTR], sc, - sc->rue_cdata.rue_ibuf, RUE_INTR_PKTLEN, - rue_intr, RUE_INTR_INTERVAL); - if (err) { - if_printf(ifp, "open intr pipe failed: %s\n", usbd_errstr(err)); - return; - } -#endif - - /* Start up the receive pipe. */ - for (i = 0; i < RUE_RX_LIST_CNT; i++) { - c = &sc->rue_cdata.rue_rx_chain[i]; - usbd_setup_xfer(c->rue_xfer, sc->rue_ep[RUE_ENDPT_RX], - c, mtod(c->rue_mbuf, char *), RUE_BUFSZ, - USBD_SHORT_XFER_OK, USBD_NO_TIMEOUT, rue_rxeof); - usbd_transfer(c->rue_xfer); - } - - ifp->if_flags |= IFF_RUNNING; - ifq_clr_oactive(&ifp->if_snd); - - callout_reset(&sc->rue_stat_ch, hz, rue_tick, sc); -} - -/* - * Set media options. - */ - -static int -rue_ifmedia_upd(struct ifnet *ifp) -{ - struct rue_softc *sc = ifp->if_softc; - struct mii_data *mii = GET_MII(sc); - - sc->rue_link = 0; - if (mii->mii_instance) { - struct mii_softc *miisc; - LIST_FOREACH (miisc, &mii->mii_phys, mii_list) - mii_phy_reset(miisc); - } - mii_mediachg(mii); - - return (0); -} - -/* - * Report current media status. - */ - -static void -rue_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr) -{ - struct rue_softc *sc = ifp->if_softc; - struct mii_data *mii = GET_MII(sc); - - mii_pollstat(mii); - ifmr->ifm_active = mii->mii_media_active; - ifmr->ifm_status = mii->mii_media_status; -} - -static int -rue_ioctl(struct ifnet *ifp, u_long command, caddr_t data, struct ucred *cr) -{ - struct rue_softc *sc = ifp->if_softc; - struct ifreq *ifr = (struct ifreq *)data; - struct mii_data *mii; - int error = 0; - - switch (command) { - case SIOCSIFFLAGS: - if (ifp->if_flags & IFF_UP) { - if (ifp->if_flags & IFF_RUNNING && - ifp->if_flags & IFF_PROMISC && - !(sc->rue_if_flags & IFF_PROMISC)) { - RUE_SETBIT_2(sc, RUE_RCR, - (RUE_RCR_AAM | RUE_RCR_AAP)); - rue_setmulti(sc); - } else if (ifp->if_flags & IFF_RUNNING && - !(ifp->if_flags & IFF_PROMISC) && - sc->rue_if_flags & IFF_PROMISC) { - RUE_CLRBIT_2(sc, RUE_RCR, - (RUE_RCR_AAM | RUE_RCR_AAP)); - rue_setmulti(sc); - } else if (!(ifp->if_flags & IFF_RUNNING)) - rue_init(sc); - } else { - if (ifp->if_flags & IFF_RUNNING) - rue_stop(sc); - } - sc->rue_if_flags = ifp->if_flags; - error = 0; - break; - case SIOCADDMULTI: - case SIOCDELMULTI: - rue_setmulti(sc); - error = 0; - break; - case SIOCGIFMEDIA: - case SIOCSIFMEDIA: - /* - * mii calls unfortunately issue usb commands which can - * deadlock against usb completions. - */ - mii = GET_MII(sc); - error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, command); - break; - default: - error = ether_ioctl(ifp, command, data); - break; - } - - return (error); -} - -static void -rue_watchdog(struct ifnet *ifp) -{ - struct rue_softc *sc = ifp->if_softc; - struct rue_chain *c; - usbd_status stat; - - IFNET_STAT_INC(ifp, oerrors, 1); - if_printf(ifp, "watchdog timeout\n"); - - c = &sc->rue_cdata.rue_tx_chain[0]; - usbd_get_xfer_status(c->rue_xfer, NULL, NULL, NULL, &stat); - - RUE_UNLOCK(sc); - rue_txeof(c->rue_xfer, c, stat); - RUE_LOCK(sc); - - if (!ifq_is_empty(&ifp->if_snd)) - if_devstart(ifp); -} - -/* - * Stop the adapter and free any mbufs allocated to the - * RX and TX lists. - */ - -static void -rue_stop(struct rue_softc *sc) -{ - usbd_status err; - struct ifnet *ifp; - int i; - - ifp = &sc->arpcom.ac_if; - ifp->if_timer = 0; - - rue_csr_write_1(sc, RUE_CR, 0x00); - rue_reset(sc); - - callout_stop(&sc->rue_stat_ch); - - /* Stop transfers. */ - RUE_UNLOCK(sc); - if (sc->rue_ep[RUE_ENDPT_RX] != NULL) { - err = usbd_abort_pipe(sc->rue_ep[RUE_ENDPT_RX]); - if (err) { - if_printf(ifp, "abort rx pipe failed: %s\n", - usbd_errstr(err)); - } - err = usbd_close_pipe(sc->rue_ep[RUE_ENDPT_RX]); - if (err) { - if_printf(ifp, "close rx pipe failed: %s\n", - usbd_errstr(err)); - } - sc->rue_ep[RUE_ENDPT_RX] = NULL; - } - - if (sc->rue_ep[RUE_ENDPT_TX] != NULL) { - err = usbd_abort_pipe(sc->rue_ep[RUE_ENDPT_TX]); - if (err) { - if_printf(ifp, "abort tx pipe failed: %s\n", - usbd_errstr(err)); - } - err = usbd_close_pipe(sc->rue_ep[RUE_ENDPT_TX]); - if (err) { - if_printf(ifp, "close tx pipe failed: %s\n", - usbd_errstr(err)); - } - sc->rue_ep[RUE_ENDPT_TX] = NULL; - } - -#ifdef RUE_INTR_PIPE - if (sc->rue_ep[RUE_ENDPT_INTR] != NULL) { - err = usbd_abort_pipe(sc->rue_ep[RUE_ENDPT_INTR]); - if (err) { - if_printf(ifp, "abort intr pipe failed: %s\n", - usbd_errstr(err)); - } - err = usbd_close_pipe(sc->rue_ep[RUE_ENDPT_INTR]); - if (err) { - if_printf(ifp, "close intr pipe failed: %s\n", - usbd_errstr(err)); - } - sc->rue_ep[RUE_ENDPT_INTR] = NULL; - } -#endif - RUE_LOCK(sc); - - /* Free RX resources. */ - for (i = 0; i < RUE_RX_LIST_CNT; i++) { - if (sc->rue_cdata.rue_rx_chain[i].rue_buf != NULL) { - kfree(sc->rue_cdata.rue_rx_chain[i].rue_buf, M_USBDEV); - sc->rue_cdata.rue_rx_chain[i].rue_buf = NULL; - } - if (sc->rue_cdata.rue_rx_chain[i].rue_mbuf != NULL) { - m_freem(sc->rue_cdata.rue_rx_chain[i].rue_mbuf); - sc->rue_cdata.rue_rx_chain[i].rue_mbuf = NULL; - } - if (sc->rue_cdata.rue_rx_chain[i].rue_xfer != NULL) { - usbd_free_xfer(sc->rue_cdata.rue_rx_chain[i].rue_xfer); - sc->rue_cdata.rue_rx_chain[i].rue_xfer = NULL; - } - } - - /* Free TX resources. */ - for (i = 0; i < RUE_TX_LIST_CNT; i++) { - if (sc->rue_cdata.rue_tx_chain[i].rue_buf != NULL) { - kfree(sc->rue_cdata.rue_tx_chain[i].rue_buf, M_USBDEV); - sc->rue_cdata.rue_tx_chain[i].rue_buf = NULL; - } - if (sc->rue_cdata.rue_tx_chain[i].rue_mbuf != NULL) { - m_freem(sc->rue_cdata.rue_tx_chain[i].rue_mbuf); - sc->rue_cdata.rue_tx_chain[i].rue_mbuf = NULL; - } - if (sc->rue_cdata.rue_tx_chain[i].rue_xfer != NULL) { - usbd_free_xfer(sc->rue_cdata.rue_tx_chain[i].rue_xfer); - sc->rue_cdata.rue_tx_chain[i].rue_xfer = NULL; - } - } - -#ifdef RUE_INTR_PIPE - if (sc->rue_cdata.rue_ibuf != NULL) { - kfree(sc->rue_cdata.rue_ibuf, M_USBDEV); - sc->rue_cdata.rue_ibuf = NULL; - } -#endif - - sc->rue_link = 0; - - ifp->if_flags &= ~IFF_RUNNING; - ifq_clr_oactive(&ifp->if_snd); -} - -/* - * Stop all chip I/O so that the kernel's probe routines don't - * get confused by errant DMAs when rebooting. - */ - -static void -rue_shutdown(device_t dev) -{ - struct rue_softc *sc; - - sc = device_get_softc(dev); - - sc->rue_dying++; - RUE_LOCK(sc); - rue_reset(sc); - rue_stop(sc); - RUE_UNLOCK(sc); -} diff --git a/sys/dev/netif/rue/if_ruereg.h b/sys/dev/netif/rue/if_ruereg.h deleted file mode 100644 index c9f600ceda..0000000000 --- a/sys/dev/netif/rue/if_ruereg.h +++ /dev/null @@ -1,228 +0,0 @@ -/*- - * Copyright (c) 2001-2003, Shunsuke Akiyama . - * 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: src/sys/dev/usb/if_ruereg.h,v 1.3 2004/05/23 12:35:24 iedowse Exp $ - * $DragonFly: src/sys/dev/netif/rue/if_ruereg.h,v 1.2 2007/11/05 13:32:27 hasso Exp $ - */ - -#ifndef _IF_RUEREG_H_ -#define _IF_RUEREG_H_ - -#define RUE_INTR_PIPE 1 /* Use INTR PIPE */ - -#define RUE_CONFIG_NO 1 -#define RUE_IFACE_IDX 0 - -#define RUE_ENDPT_RX 0x0 -#define RUE_ENDPT_TX 0x1 -#define RUE_ENDPT_INTR 0x2 -#define RUE_ENDPT_MAX 0x3 - -#define RUE_INTR_PKTLEN 0x8 - -#define RUE_TIMEOUT 1000 -#define RUE_BUFSZ 1536 -#define RUE_MIN_FRAMELEN 60 -#define RUE_INTR_INTERVAL 100 /* ms */ - -/* - * Registers - */ - -#define RUE_IDR0 0x0120 -#define RUE_IDR1 0x0121 -#define RUE_IDR2 0x0122 -#define RUE_IDR3 0x0123 -#define RUE_IDR4 0x0124 -#define RUE_IDR5 0x0125 - -#define RUE_MAR0 0x0126 -#define RUE_MAR1 0x0127 -#define RUE_MAR2 0x0128 -#define RUE_MAR3 0x0129 -#define RUE_MAR4 0x012A -#define RUE_MAR5 0x012B -#define RUE_MAR6 0x012C -#define RUE_MAR7 0x012D - -#define RUE_CR 0x012E /* B, R/W */ -#define RUE_CR_SOFT_RST 0x10 -#define RUE_CR_RE 0x08 -#define RUE_CR_TE 0x04 -#define RUE_CR_EP3CLREN 0x02 - -#define RUE_TCR 0x012F /* B, R/W */ -#define RUE_TCR_TXRR1 0x80 -#define RUE_TCR_TXRR0 0x40 -#define RUE_TCR_IFG1 0x10 -#define RUE_TCR_IFG0 0x08 -#define RUE_TCR_NOCRC 0x01 -#define RUE_TCR_CONFIG (RUE_TCR_TXRR1|RUE_TCR_TXRR0|RUE_TCR_IFG1|RUE_TCR_IFG0) - -#define RUE_RCR 0x0130 /* W, R/W */ -#define RUE_RCR_TAIL 0x80 -#define RUE_RCR_AER 0x40 -#define RUE_RCR_AR 0x20 -#define RUE_RCR_AM 0x10 -#define RUE_RCR_AB 0x08 -#define RUE_RCR_AD 0x04 -#define RUE_RCR_AAM 0x02 -#define RUE_RCR_AAP 0x01 -#define RUE_RCR_CONFIG (RUE_RCR_TAIL|RUE_RCR_AD) - -#define RUE_TSR 0x0132 -#define RUE_RSR 0x0133 -#define RUE_CON0 0x0135 -#define RUE_CON1 0x0136 -#define RUE_MSR 0x0137 -#define RUE_PHYADD 0x0138 -#define RUE_PHYDAT 0x0139 - -#define RUE_PHYCNT 0x013B /* B, R/W */ -#define RUE_PHYCNT_PHYOWN 0x40 -#define RUE_PHYCNT_RWCR 0x20 - -#define RUE_GPPC 0x013D -#define RUE_WAKECNT 0x013E - -#define RUE_BMCR 0x0140 -#define RUE_BMCR_SPD_SET 0x2000 -#define RUE_BMCR_DUPLEX 0x0100 - -#define RUE_BMSR 0x0142 - -#define RUE_ANAR 0x0144 /* W, R/W */ -#define RUE_ANAR_PAUSE 0x0400 - -#define RUE_ANLP 0x0146 /* W, R/O */ -#define RUE_ANLP_PAUSE 0x0400 - -#define RUE_AER 0x0148 - -#define RUE_NWAYT 0x014A -#define RUE_CSCR 0x014C - -#define RUE_CRC0 0x014E -#define RUE_CRC1 0x0150 -#define RUE_CRC2 0x0152 -#define RUE_CRC3 0x0154 -#define RUE_CRC4 0x0156 - -#define RUE_BYTEMASK0 0x0158 -#define RUE_BYTEMASK1 0x0160 -#define RUE_BYTEMASK2 0x0168 -#define RUE_BYTEMASK3 0x0170 -#define RUE_BYTEMASK4 0x0178 - -#define RUE_PHY1 0x0180 -#define RUE_PHY2 0x0184 - -#define RUE_TW1 0x0186 - -#define RUE_REG_MIN 0x0120 -#define RUE_REG_MAX 0x0189 - -/* - * EEPROM address declarations - */ - -#define RUE_EEPROM_BASE 0x1200 - -#define RUE_EEPROM_IDR0 (RUE_EEPROM_BASE + 0x02) -#define RUE_EEPROM_IDR1 (RUE_EEPROM_BASE + 0x03) -#define RUE_EEPROM_IDR2 (RUE_EEPROM_BASE + 0x03) -#define RUE_EEPROM_IDR3 (RUE_EEPROM_BASE + 0x03) -#define RUE_EEPROM_IDR4 (RUE_EEPROM_BASE + 0x03) -#define RUE_EEPROM_IDR5 (RUE_EEPROM_BASE + 0x03) - -#define RUE_EEPROM_INTERVAL (RUE_EEPROM_BASE + 0x17) - -struct rue_intrpkt { - uint8_t rue_tsr; - uint8_t rue_rsr; - uint8_t rue_gep_msr; - uint8_t rue_waksr; - uint8_t rue_txok_cnt; - uint8_t rue_rxlost_cnt; - uint8_t rue_crcerr_cnt; - uint8_t rue_col_cnt; -}; - -struct rue_rxpkt { - uint16_t rue_pktlen : 12; - uint16_t rue_rxstat : 4; -}; - -#define RUE_RXSTAT_VALID 0x01 -#define RUE_RXSTAT_RUNT 0x02 -#define RUE_RXSTAT_PMATCH 0x04 -#define RUE_RXSTAT_MCAST 0x08 - -#define RUE_RXSTAT_MASK RUE_RXSTAT_VALID - -#define RUE_TX_LIST_CNT 1 -#define RUE_RX_LIST_CNT 1 - -struct rue_softc; - -struct rue_chain { - struct rue_softc *rue_sc; - usbd_xfer_handle rue_xfer; - char *rue_buf; - struct mbuf *rue_mbuf; - int rue_idx; -}; - -struct rue_cdata { - struct rue_chain rue_tx_chain[RUE_TX_LIST_CNT]; - struct rue_chain rue_rx_chain[RUE_RX_LIST_CNT]; - struct rue_intrpkt *rue_ibuf; - int rue_tx_prod; - int rue_tx_cons; - int rue_tx_cnt; - int rue_rx_prod; -}; - -struct rue_softc { - struct arpcom arpcom; - device_t rue_miibus; - usbd_device_handle rue_udev; - usbd_interface_handle rue_iface; - int rue_ed[RUE_ENDPT_MAX]; - usbd_pipe_handle rue_ep[RUE_ENDPT_MAX]; - uint8_t rue_link; - int rue_if_flags; - struct rue_cdata rue_cdata; - struct callout rue_stat_ch; - char rue_dying; - struct timeval rue_rx_notice; -}; - -#define GET_MII(sc) (device_get_softc((sc)->rue_miibus)) - -#define RUE_LOCK(_sc) lwkt_serialize_enter((_sc)->arpcom.ac_if.if_serializer) -#define RUE_UNLOCK(_sc) lwkt_serialize_exit((_sc)->arpcom.ac_if.if_serializer) - -#endif /* _IF_RUEREG_H_ */ diff --git a/sys/dev/sound/driver/Makefile b/sys/dev/sound/driver/Makefile index 0ffe82ea55..bded3b4620 100644 --- a/sys/dev/sound/driver/Makefile +++ b/sys/dev/sound/driver/Makefile @@ -5,8 +5,4 @@ SUBDIR += envy24ht es137x fm801 hda ich maestro maestro3 neomagic SUBDIR += solo spicds t4dwave via8233 via82c686 vibes SUBDIR += driver -.if defined(WANT_OLDUSB) -SUBDIR += uaudio -.endif - .include diff --git a/sys/dev/sound/driver/uaudio/Makefile b/sys/dev/sound/driver/uaudio/Makefile deleted file mode 100644 index a8df8bc757..0000000000 --- a/sys/dev/sound/driver/uaudio/Makefile +++ /dev/null @@ -1,10 +0,0 @@ -# $FreeBSD: src/sys/modules/sound/driver/uaudio/Makefile,v 1.3 2004/12/29 08:50:35 imp Exp $ -# $DragonFly: src/sys/dev/sound/driver/uaudio/Makefile,v 1.3 2007/01/04 21:47:01 corecode Exp $ - -.PATH: ${.CURDIR}/../../../../dev/sound/usb - -KMOD= snd_uaudio -SRCS= device_if.h bus_if.h opt_usb.h -SRCS+= uaudio.c uaudio_pcm.c - -.include diff --git a/sys/dev/sound/usb/uaudio.c b/sys/dev/sound/usb/uaudio.c deleted file mode 100644 index 703825bc4e..0000000000 --- a/sys/dev/sound/usb/uaudio.c +++ /dev/null @@ -1,3146 +0,0 @@ -/* $NetBSD: uaudio.c,v 1.91 2004/11/05 17:46:14 kent Exp $ */ -/* $FreeBSD: src/sys/dev/sound/usb/uaudio.c,v 1.14.2.2 2006/04/04 17:34:10 ariff Exp $ */ - -/*- - * Copyright (c) 1999 The NetBSD Foundation, Inc. - * All rights reserved. - * - * This code is derived from software contributed to The NetBSD Foundation - * by Lennart Augustsson (lennart@augustsson.net) at - * Carlstedt Research & Technology. - * - * 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. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the NetBSD - * Foundation, Inc. and its contributors. - * 4. Neither the name of The NetBSD Foundation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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. - */ - -/* - * USB audio specs: http://www.usb.org/developers/devclass_docs/audio10.pdf - * http://www.usb.org/developers/devclass_docs/frmts10.pdf - * http://www.usb.org/developers/devclass_docs/termt10.pdf - */ - -/* - * Also merged: - * $NetBSD: uaudio.c,v 1.94 2005/01/15 15:19:53 kent Exp $ - * $NetBSD: uaudio.c,v 1.95 2005/01/16 06:02:19 dsainty Exp $ - * $NetBSD: uaudio.c,v 1.96 2005/01/16 12:46:00 kent Exp $ - * $NetBSD: uaudio.c,v 1.97 2005/02/24 08:19:38 martin Exp $ - */ - -#include -#include -#include -#include -#include -#include -#include /* for bootverbose */ -#include -#include -#include -#include -#include -#include -#include -#include - -#include /* XXXXX */ -#include -#include "feeder_if.h" - -#include -#include -#include -#include - -#include -#include - -/* #define USB_DEBUG */ -/* #define UAUDIO_MULTIPLE_ENDPOINTS */ -#ifdef USB_DEBUG -#define DPRINTF(x) do { if (uaudiodebug) kprintf x; } while (0) -#define DPRINTFN(n,x) do { if (uaudiodebug>(n)) kprintf x; } while (0) -int uaudiodebug = 0; -SYSCTL_NODE(_hw_usb, OID_AUTO, uaudio, CTLFLAG_RW, 0, "USB uaudio"); -SYSCTL_INT(_hw_usb_uaudio, OID_AUTO, debug, CTLFLAG_RW, - &uaudiodebug, 0, "uaudio debug level"); -#else -#define DPRINTF(x) -#define DPRINTFN(n,x) -#endif - -#define UAUDIO_NCHANBUFS 6 /* number of outstanding request */ -#define UAUDIO_NFRAMES 20 /* ms of sound in each request */ - - -#define MIX_MAX_CHAN 8 -struct mixerctl { - uint16_t wValue[MIX_MAX_CHAN]; /* using nchan */ - uint16_t wIndex; - uint8_t nchan; - uint8_t type; -#define MIX_ON_OFF 1 -#define MIX_SIGNED_16 2 -#define MIX_UNSIGNED_16 3 -#define MIX_SIGNED_8 4 -#define MIX_SELECTOR 5 -#define MIX_SIZE(n) ((n) == MIX_SIGNED_16 || (n) == MIX_UNSIGNED_16 ? 2 : 1) -#define MIX_UNSIGNED(n) ((n) == MIX_UNSIGNED_16) - int minval, maxval; - u_int delta; - u_int mul; - unsigned ctl; -#define MAX_SELECTOR_INPUT_PIN 256 - uint8_t slctrtype[MAX_SELECTOR_INPUT_PIN]; - uint8_t class; -}; -#define MAKE(h,l) (((h) << 8) | (l)) - -struct as_info { - uint8_t alt; - uint8_t encoding; - uint8_t attributes; /* Copy of bmAttributes of - * usb_audio_streaming_endpoint_descriptor - */ - usbd_interface_handle ifaceh; - const usb_interface_descriptor_t *idesc; - const usb_endpoint_descriptor_audio_t *edesc; - const usb_endpoint_descriptor_audio_t *edesc1; - const struct usb_audio_streaming_type1_descriptor *asf1desc; - int sc_busy; /* currently used */ -}; - -struct chan { - struct pcm_channel *pcm_ch; - usbd_pipe_handle pipe; - usbd_pipe_handle sync_pipe; - - u_int sample_size; - u_int sample_rate; - u_int bytes_per_frame; - u_int fraction; /* fraction/1000 is the extra samples/frame */ - u_int residue; /* accumulates the fractional samples */ - - u_char *start; /* upper layer buffer start */ - u_char *end; /* upper layer buffer end */ - u_char *cur; /* current position in upper layer buffer */ - int blksize; /* chunk size to report up */ - int transferred; /* transferred bytes not reported up */ - - int altidx; /* currently used altidx */ - - int curchanbuf; - struct chanbuf { - struct chan *chan; - usbd_xfer_handle xfer; - u_char *buffer; - u_int16_t sizes[UAUDIO_NFRAMES]; - u_int16_t offsets[UAUDIO_NFRAMES]; - u_int16_t size; - } chanbufs[UAUDIO_NCHANBUFS]; - - struct uaudio_softc *sc; /* our softc */ - u_int32_t format; - int precision; - int channels; -}; - -struct uaudio_softc { - device_t sc_dev; /* base device */ - usbd_device_handle sc_udev; /* USB device */ - int sc_ac_iface; /* Audio Control interface */ - usbd_interface_handle sc_ac_ifaceh; - struct chan sc_playchan; /* play channel */ - struct chan sc_recchan; /* record channel */ - int sc_nullalt; - int sc_audio_rev; - struct as_info *sc_alts; /* alternate settings */ - int sc_nalts; /* # of alternate settings */ - int sc_altflags; -#define HAS_8 0x01 -#define HAS_16 0x02 -#define HAS_8U 0x04 -#define HAS_ALAW 0x08 -#define HAS_MULAW 0x10 -#define UA_NOFRAC 0x20 /* don't do sample rate adjustment */ -#define HAS_24 0x40 -#define HAS_32 0x80 - int sc_mode; /* play/record capability */ - struct mixerctl *sc_ctls; /* mixer controls */ - int sc_nctls; /* # of mixer controls */ - device_t sc_audiodev; - char sc_dying; - struct sbuf uaudio_sndstat; - int uaudio_sndstat_flag; -}; - -struct terminal_list { - int size; - uint16_t terminals[1]; -}; -#define TERMINAL_LIST_SIZE(N) (offsetof(struct terminal_list, terminals) \ - + sizeof(uint16_t) * (N)) - -struct io_terminal { - union { - const usb_descriptor_t *desc; - const struct usb_audio_input_terminal *it; - const struct usb_audio_output_terminal *ot; - const struct usb_audio_mixer_unit *mu; - const struct usb_audio_selector_unit *su; - const struct usb_audio_feature_unit *fu; - const struct usb_audio_processing_unit *pu; - const struct usb_audio_extension_unit *eu; - } d; - int inputs_size; - struct terminal_list **inputs; /* list of source input terminals */ - struct terminal_list *output; /* list of destination output terminals */ - int direct; /* directly connected to an output terminal */ -}; - -#define UAC_OUTPUT 0 -#define UAC_INPUT 1 -#define UAC_EQUAL 2 -#define UAC_RECORD 3 -#define UAC_NCLASSES 4 -#ifdef USB_DEBUG -#define AudioCinputs "inputs" -#define AudioCoutputs "outputs" -#define AudioCrecord "record" -#define AudioCequalization "equalization" -static const char *uac_names[] = { - AudioCoutputs, AudioCinputs, AudioCequalization, AudioCrecord, -}; -#endif - -static usbd_status uaudio_identify_ac - (struct uaudio_softc *, const usb_config_descriptor_t *); -static usbd_status uaudio_identify_as - (struct uaudio_softc *, const usb_config_descriptor_t *); -static usbd_status uaudio_process_as - (struct uaudio_softc *, const char *, int *, int, - const usb_interface_descriptor_t *); - -static void uaudio_add_alt(struct uaudio_softc *, const struct as_info *); - -static const usb_interface_descriptor_t *uaudio_find_iface - (const char *, int, int *, int); - -static void uaudio_mixer_add_ctl(struct uaudio_softc *, struct mixerctl *); - -#ifdef USB_DEBUG -static void uaudio_dump_cluster(const struct usb_audio_cluster *); -#endif -static struct usb_audio_cluster uaudio_get_cluster - (int, const struct io_terminal *); -static void uaudio_add_input - (struct uaudio_softc *, const struct io_terminal *, int); -static void uaudio_add_output - (struct uaudio_softc *, const struct io_terminal *, int); -static void uaudio_add_mixer - (struct uaudio_softc *, const struct io_terminal *, int); -static void uaudio_add_selector - (struct uaudio_softc *, const struct io_terminal *, int); -#ifdef USB_DEBUG -static const char *uaudio_get_terminal_name(int); -#endif -static int uaudio_determine_class - (const struct io_terminal *, struct mixerctl *); -static int uaudio_feature_name(const struct io_terminal *, - struct mixerctl *); -static void uaudio_add_feature - (struct uaudio_softc *, const struct io_terminal *, int); -static void uaudio_add_processing_updown - (struct uaudio_softc *, const struct io_terminal *, int); -static void uaudio_add_processing - (struct uaudio_softc *, const struct io_terminal *, int); -static void uaudio_add_extension - (struct uaudio_softc *, const struct io_terminal *, int); -static struct terminal_list *uaudio_merge_terminal_list - (const struct io_terminal *); -static struct terminal_list *uaudio_io_terminaltype - (int, struct io_terminal *, int); -static usbd_status uaudio_identify - (struct uaudio_softc *, const usb_config_descriptor_t *); - -static int uaudio_signext(int, int); -static int uaudio_bsd2value(struct mixerctl *, int); -static int uaudio_get(struct uaudio_softc *, int, int, int, int, int); -static void uaudio_set - (struct uaudio_softc *, int, int, int, int, int, int); -static void uaudio_ctl_set - (struct uaudio_softc *, int, struct mixerctl *, int, int); - -static usbd_status uaudio_set_speed(struct uaudio_softc *, int, u_int); - -static usbd_status uaudio_chan_open(struct uaudio_softc *, struct chan *); -static void uaudio_chan_close(struct uaudio_softc *, struct chan *); -static usbd_status uaudio_chan_alloc_buffers - (struct uaudio_softc *, struct chan *); -static void uaudio_chan_free_buffers(struct uaudio_softc *, struct chan *); - -static void uaudio_chan_ptransfer(struct chan *); -static void uaudio_chan_pintr - (usbd_xfer_handle, usbd_private_handle, usbd_status); - -static void uaudio_chan_rtransfer(struct chan *); -static void uaudio_chan_rintr - (usbd_xfer_handle, usbd_private_handle, usbd_status); - -static int audio_attach_mi(device_t); -static int uaudio_init_params(struct uaudio_softc * sc, struct chan *ch, int mode); -static int uaudio_sndstat_prepare_pcm(struct sbuf *s, device_t dev, int verbose); - -/* for NetBSD compatibility */ -#define AUMODE_PLAY 0x01 -#define AUMODE_RECORD 0x02 - -#define AUDIO_PROP_FULLDUPLEX 0x01 - -#define AUDIO_ENCODING_ULAW 1 -#define AUDIO_ENCODING_ALAW 2 -#define AUDIO_ENCODING_SLINEAR_LE 6 -#define AUDIO_ENCODING_SLINEAR_BE 7 -#define AUDIO_ENCODING_ULINEAR_LE 8 -#define AUDIO_ENCODING_ULINEAR_BE 9 - -static device_probe_t uaudio_match; -static device_attach_t uaudio_attach; -static device_detach_t uaudio_detach; - -static devclass_t uaudio_devclass; - -static kobj_method_t uaudio_methods[] = { - DEVMETHOD(device_probe, uaudio_match), - DEVMETHOD(device_attach, uaudio_attach), - DEVMETHOD(device_detach, uaudio_detach), - DEVMETHOD(device_suspend, bus_generic_suspend), - DEVMETHOD(device_resume, bus_generic_resume), - DEVMETHOD(device_shutdown, bus_generic_shutdown), - DEVMETHOD(bus_print_child, bus_generic_print_child), - DEVMETHOD_END -}; - -static driver_t uaudio_driver = { - "uaudio", - uaudio_methods, - sizeof(struct uaudio_softc) -}; - -MODULE_DEPEND(uaudio, usb, 1, 1, 1); - -static int -uaudio_match(device_t self) -{ - struct usb_attach_arg *uaa = device_get_ivars(self); - usb_interface_descriptor_t *id; - - if (uaa->iface == NULL) - return UMATCH_NONE; - - id = usbd_get_interface_descriptor(uaa->iface); - /* Trigger on the control interface. */ - if (id == NULL || - id->bInterfaceClass != UICLASS_AUDIO || - id->bInterfaceSubClass != UISUBCLASS_AUDIOCONTROL || - (usbd_get_quirks(uaa->device)->uq_flags & UQ_BAD_AUDIO)) - return UMATCH_NONE; - - return UMATCH_IFACECLASS_IFACESUBCLASS; -} - -static int -uaudio_attach(device_t self) -{ - struct uaudio_softc *sc = device_get_softc(self); - struct usb_attach_arg *uaa = device_get_ivars(self); - usb_interface_descriptor_t *id; - usb_config_descriptor_t *cdesc; - char devinfo[1024]; - usbd_status err; - int i, j, found; - - usbd_devinfo(uaa->device, 0, devinfo); - sc->sc_dev = self; - device_set_desc_copy(self, devinfo); - - sc->sc_udev = uaa->device; - - cdesc = usbd_get_config_descriptor(sc->sc_udev); - if (cdesc == NULL) { - kprintf("%s: failed to get configuration descriptor\n", - device_get_nameunit(sc->sc_dev)); - return ENXIO; - } - - err = uaudio_identify(sc, cdesc); - if (err) { - kprintf("%s: audio descriptors make no sense, error=%d\n", - device_get_nameunit(sc->sc_dev), err); - return ENXIO; - } - - sc->sc_ac_ifaceh = uaa->iface; - /* Pick up the AS interface. */ - for (i = 0; i < uaa->nifaces; i++) { - if (uaa->ifaces[i] == NULL) - continue; - id = usbd_get_interface_descriptor(uaa->ifaces[i]); - if (id == NULL) - continue; - found = 0; - for (j = 0; j < sc->sc_nalts; j++) { - if (id->bInterfaceNumber == - sc->sc_alts[j].idesc->bInterfaceNumber) { - sc->sc_alts[j].ifaceh = uaa->ifaces[i]; - found = 1; - } - } - if (found) - uaa->ifaces[i] = NULL; - } - - for (j = 0; j < sc->sc_nalts; j++) { - if (sc->sc_alts[j].ifaceh == NULL) { - kprintf("%s: alt %d missing AS interface(s)\n", - device_get_nameunit(sc->sc_dev), j); - return ENXIO; - } - } - - kprintf("%s: audio rev %d.%02x\n", device_get_nameunit(sc->sc_dev), - sc->sc_audio_rev >> 8, sc->sc_audio_rev & 0xff); - - sc->sc_playchan.sc = sc->sc_recchan.sc = sc; - sc->sc_playchan.altidx = -1; - sc->sc_recchan.altidx = -1; - - if (usbd_get_quirks(sc->sc_udev)->uq_flags & UQ_AU_NO_FRAC) - sc->sc_altflags |= UA_NOFRAC; - -#ifndef USB_DEBUG - if (bootverbose) -#endif - kprintf("%s: %d mixer controls\n", device_get_nameunit(sc->sc_dev), - sc->sc_nctls); - - DPRINTF(("uaudio_attach: doing audio_attach_mi\n")); - sc->sc_dying = 0; - if (audio_attach_mi(sc->sc_dev)) { - kprintf("audio_attach_mi failed\n"); - return ENXIO; - } - - return 0; -} - -static int -uaudio_detach(device_t self) -{ - struct uaudio_softc *sc = device_get_softc(self); - - sbuf_delete(&(sc->uaudio_sndstat)); - sc->uaudio_sndstat_flag = 0; - - sc->sc_dying = 1; - -#if 0 /* XXX */ - /* Wait for outstanding requests to complete. */ - usbd_delay_ms(sc->sc_udev, UAUDIO_NCHANBUFS * UAUDIO_NFRAMES); -#endif - - /* do nothing ? */ - return bus_generic_detach(sc->sc_dev); -} - -static const usb_interface_descriptor_t * -uaudio_find_iface(const char *buf, int size, int *offsp, int subtype) -{ - const usb_interface_descriptor_t *d; - - while (*offsp < size) { - d = (const void *)(buf + *offsp); - *offsp += d->bLength; - if (d->bDescriptorType == UDESC_INTERFACE && - d->bInterfaceClass == UICLASS_AUDIO && - d->bInterfaceSubClass == subtype) - return d; - } - return NULL; -} - -static void -uaudio_mixer_add_ctl(struct uaudio_softc *sc, struct mixerctl *mc) -{ - int res; - size_t len; - struct mixerctl *nmc; - - if (mc->class < UAC_NCLASSES) { - DPRINTF(("%s: adding %s.%d\n", - __func__, uac_names[mc->class], mc->ctl)); - } else { - DPRINTF(("%s: adding %d\n", __func__, mc->ctl)); - } - - len = sizeof(*mc) * (sc->sc_nctls + 1); - nmc = kmalloc(len, M_USBDEV, M_WAITOK); - - /* Copy old data, if there was any */ - if (sc->sc_nctls != 0) { - memcpy(nmc, sc->sc_ctls, sizeof(*mc) * (sc->sc_nctls)); - kfree(sc->sc_ctls, M_USBDEV); - } - sc->sc_ctls = nmc; - - mc->delta = 0; - if (mc->type == MIX_ON_OFF) { - mc->minval = 0; - mc->maxval = 1; - } else if (mc->type == MIX_SELECTOR) { - ; - } else { - /* Determine min and max values. */ - mc->minval = uaudio_signext(mc->type, - uaudio_get(sc, GET_MIN, UT_READ_CLASS_INTERFACE, - mc->wValue[0], mc->wIndex, - MIX_SIZE(mc->type))); - mc->maxval = 1 + uaudio_signext(mc->type, - uaudio_get(sc, GET_MAX, UT_READ_CLASS_INTERFACE, - mc->wValue[0], mc->wIndex, - MIX_SIZE(mc->type))); - mc->mul = mc->maxval - mc->minval; - if (mc->mul == 0) - mc->mul = 1; - res = uaudio_get(sc, GET_RES, UT_READ_CLASS_INTERFACE, - mc->wValue[0], mc->wIndex, - MIX_SIZE(mc->type)); - if (res > 0) - mc->delta = (res * 255 + mc->mul/2) / mc->mul; - } - - sc->sc_ctls[sc->sc_nctls++] = *mc; - -#ifdef USB_DEBUG - if (uaudiodebug > 2) { - int i; - DPRINTF(("uaudio_mixer_add_ctl: wValue=%04x",mc->wValue[0])); - for (i = 1; i < mc->nchan; i++) - DPRINTF((",%04x", mc->wValue[i])); - DPRINTF((" wIndex=%04x type=%d ctl='%d' " - "min=%d max=%d\n", - mc->wIndex, mc->type, mc->ctl, - mc->minval, mc->maxval)); - } -#endif -} - -#ifdef USB_DEBUG -static void -uaudio_dump_cluster(const struct usb_audio_cluster *cl) -{ - static const char *channel_names[16] = { - "LEFT", "RIGHT", "CENTER", "LFE", - "LEFT_SURROUND", "RIGHT_SURROUND", "LEFT_CENTER", "RIGHT_CENTER", - "SURROUND", "LEFT_SIDE", "RIGHT_SIDE", "TOP", - "RESERVED12", "RESERVED13", "RESERVED14", "RESERVED15", - }; - int cc, i, first; - - cc = UGETW(cl->wChannelConfig); - kprintf("cluster: bNrChannels=%u wChannelConfig=0x%.4x", - cl->bNrChannels, cc); - first = TRUE; - for (i = 0; cc != 0; i++) { - if (cc & 1) { - kprintf("%c%s", first ? '<' : ',', channel_names[i]); - first = FALSE; - } - cc = cc >> 1; - } - kprintf("> iChannelNames=%u", cl->iChannelNames); -} -#endif - -static struct usb_audio_cluster -uaudio_get_cluster(int id, const struct io_terminal *iot) -{ - struct usb_audio_cluster r; - const usb_descriptor_t *dp; - int i; - - for (i = 0; i < 25; i++) { /* avoid infinite loops */ - dp = iot[id].d.desc; - if (dp == NULL) - goto bad; - switch (dp->bDescriptorSubtype) { - case UDESCSUB_AC_INPUT: - r.bNrChannels = iot[id].d.it->bNrChannels; - USETW(r.wChannelConfig, UGETW(iot[id].d.it->wChannelConfig)); - r.iChannelNames = iot[id].d.it->iChannelNames; - return r; - case UDESCSUB_AC_OUTPUT: - id = iot[id].d.ot->bSourceId; - break; - case UDESCSUB_AC_MIXER: - r = *(const struct usb_audio_cluster *) - &iot[id].d.mu->baSourceId[iot[id].d.mu->bNrInPins]; - return r; - case UDESCSUB_AC_SELECTOR: - /* XXX This is not really right */ - id = iot[id].d.su->baSourceId[0]; - break; - case UDESCSUB_AC_FEATURE: - id = iot[id].d.fu->bSourceId; - break; - case UDESCSUB_AC_PROCESSING: - r = *(const struct usb_audio_cluster *) - &iot[id].d.pu->baSourceId[iot[id].d.pu->bNrInPins]; - return r; - case UDESCSUB_AC_EXTENSION: - r = *(const struct usb_audio_cluster *) - &iot[id].d.eu->baSourceId[iot[id].d.eu->bNrInPins]; - return r; - default: - goto bad; - } - } - bad: - kprintf("uaudio_get_cluster: bad data\n"); - memset(&r, 0, sizeof r); - return r; - -} - -static void -uaudio_add_input(struct uaudio_softc *sc, const struct io_terminal *iot, int id) -{ -#ifdef USB_DEBUG - const struct usb_audio_input_terminal *d = iot[id].d.it; - - DPRINTFN(2,("uaudio_add_input: bTerminalId=%d wTerminalType=0x%04x " - "bAssocTerminal=%d bNrChannels=%d wChannelConfig=%d " - "iChannelNames=%d iTerminal=%d\n", - d->bTerminalId, UGETW(d->wTerminalType), d->bAssocTerminal, - d->bNrChannels, UGETW(d->wChannelConfig), - d->iChannelNames, d->iTerminal)); -#endif -} - -static void -uaudio_add_output(struct uaudio_softc *sc, const struct io_terminal *iot, int id) -{ -#ifdef USB_DEBUG - const struct usb_audio_output_terminal *d; - - d = iot[id].d.ot; - DPRINTFN(2,("uaudio_add_output: bTerminalId=%d wTerminalType=0x%04x " - "bAssocTerminal=%d bSourceId=%d iTerminal=%d\n", - d->bTerminalId, UGETW(d->wTerminalType), d->bAssocTerminal, - d->bSourceId, d->iTerminal)); -#endif -} - -static void -uaudio_add_mixer(struct uaudio_softc *sc, const struct io_terminal *iot, int id) -{ - const struct usb_audio_mixer_unit *d = iot[id].d.mu; - const struct usb_audio_mixer_unit_1 *d1; - int c, chs, ichs, ochs, i, o, bno, p, mo, mc, k; - const uByte *bm; - struct mixerctl mix; - - DPRINTFN(2,("uaudio_add_mixer: bUnitId=%d bNrInPins=%d\n", - d->bUnitId, d->bNrInPins)); - - /* Compute the number of input channels */ - ichs = 0; - for (i = 0; i < d->bNrInPins; i++) - ichs += uaudio_get_cluster(d->baSourceId[i], iot).bNrChannels; - - /* and the number of output channels */ - d1 = (const struct usb_audio_mixer_unit_1 *)&d->baSourceId[d->bNrInPins]; - ochs = d1->bNrChannels; - DPRINTFN(2,("uaudio_add_mixer: ichs=%d ochs=%d\n", ichs, ochs)); - - bm = d1->bmControls; - mix.wIndex = MAKE(d->bUnitId, sc->sc_ac_iface); - uaudio_determine_class(&iot[id], &mix); - mix.type = MIX_SIGNED_16; - -#define BIT(bno) ((bm[bno / 8] >> (7 - bno % 8)) & 1) - for (p = i = 0; i < d->bNrInPins; i++) { - chs = uaudio_get_cluster(d->baSourceId[i], iot).bNrChannels; - mc = 0; - for (c = 0; c < chs; c++) { - mo = 0; - for (o = 0; o < ochs; o++) { - bno = (p + c) * ochs + o; - if (BIT(bno)) - mo++; - } - if (mo == 1) - mc++; - } - if (mc == chs && chs <= MIX_MAX_CHAN) { - k = 0; - for (c = 0; c < chs; c++) - for (o = 0; o < ochs; o++) { - bno = (p + c) * ochs + o; - if (BIT(bno)) - mix.wValue[k++] = - MAKE(p+c+1, o+1); - } - - mix.nchan = chs; - uaudio_mixer_add_ctl(sc, &mix); - } else { - /* XXX */ - } -#undef BIT - p += chs; - } - -} - -static void -uaudio_add_selector(struct uaudio_softc *sc, const struct io_terminal *iot, int id) -{ - const struct usb_audio_selector_unit *d; - struct mixerctl mix; - int i; - struct mixerctl dummy; - - d = iot[id].d.su; - DPRINTFN(2,("uaudio_add_selector: bUnitId=%d bNrInPins=%d\n", - d->bUnitId, d->bNrInPins)); - mix.wIndex = MAKE(d->bUnitId, sc->sc_ac_iface); - mix.wValue[0] = MAKE(0, 0); - uaudio_determine_class(&iot[id], &mix); - mix.nchan = 1; - mix.type = MIX_SELECTOR; - mix.ctl = SOUND_MIXER_NRDEVICES; /* XXXXX */ - mix.minval = 1; - mix.maxval = d->bNrInPins; - mix.mul = mix.maxval - mix.minval; - for (i = 0; i < MAX_SELECTOR_INPUT_PIN; i++) { - mix.slctrtype[i] = SOUND_MIXER_NRDEVICES; - } - for (i = mix.minval; i <= mix.maxval; i++) { - mix.slctrtype[i - 1] = uaudio_feature_name(&iot[d->baSourceId[i - 1]], &dummy); - } - - uaudio_mixer_add_ctl(sc, &mix); -} - -#ifdef USB_DEBUG -static const char * -uaudio_get_terminal_name(int terminal_type) -{ - static char buf[100]; - - switch (terminal_type) { - /* USB terminal types */ - case UAT_UNDEFINED: return "UAT_UNDEFINED"; - case UAT_STREAM: return "UAT_STREAM"; - case UAT_VENDOR: return "UAT_VENDOR"; - /* input terminal types */ - case UATI_UNDEFINED: return "UATI_UNDEFINED"; - case UATI_MICROPHONE: return "UATI_MICROPHONE"; - case UATI_DESKMICROPHONE: return "UATI_DESKMICROPHONE"; - case UATI_PERSONALMICROPHONE: return "UATI_PERSONALMICROPHONE"; - case UATI_OMNIMICROPHONE: return "UATI_OMNIMICROPHONE"; - case UATI_MICROPHONEARRAY: return "UATI_MICROPHONEARRAY"; - case UATI_PROCMICROPHONEARR: return "UATI_PROCMICROPHONEARR"; - /* output terminal types */ - case UATO_UNDEFINED: return "UATO_UNDEFINED"; - case UATO_SPEAKER: return "UATO_SPEAKER"; - case UATO_HEADPHONES: return "UATO_HEADPHONES"; - case UATO_DISPLAYAUDIO: return "UATO_DISPLAYAUDIO"; - case UATO_DESKTOPSPEAKER: return "UATO_DESKTOPSPEAKER"; - case UATO_ROOMSPEAKER: return "UATO_ROOMSPEAKER"; - case UATO_COMMSPEAKER: return "UATO_COMMSPEAKER"; - case UATO_SUBWOOFER: return "UATO_SUBWOOFER"; - /* bidir terminal types */ - case UATB_UNDEFINED: return "UATB_UNDEFINED"; - case UATB_HANDSET: return "UATB_HANDSET"; - case UATB_HEADSET: return "UATB_HEADSET"; - case UATB_SPEAKERPHONE: return "UATB_SPEAKERPHONE"; - case UATB_SPEAKERPHONEESUP: return "UATB_SPEAKERPHONEESUP"; - case UATB_SPEAKERPHONEECANC: return "UATB_SPEAKERPHONEECANC"; - /* telephony terminal types */ - case UATT_UNDEFINED: return "UATT_UNDEFINED"; - case UATT_PHONELINE: return "UATT_PHONELINE"; - case UATT_TELEPHONE: return "UATT_TELEPHONE"; - case UATT_DOWNLINEPHONE: return "UATT_DOWNLINEPHONE"; - /* external terminal types */ - case UATE_UNDEFINED: return "UATE_UNDEFINED"; - case UATE_ANALOGCONN: return "UATE_ANALOGCONN"; - case UATE_LINECONN: return "UATE_LINECONN"; - case UATE_LEGACYCONN: return "UATE_LEGACYCONN"; - case UATE_DIGITALAUIFC: return "UATE_DIGITALAUIFC"; - case UATE_SPDIF: return "UATE_SPDIF"; - case UATE_1394DA: return "UATE_1394DA"; - case UATE_1394DV: return "UATE_1394DV"; - /* embedded function terminal types */ - case UATF_UNDEFINED: return "UATF_UNDEFINED"; - case UATF_CALIBNOISE: return "UATF_CALIBNOISE"; - case UATF_EQUNOISE: return "UATF_EQUNOISE"; - case UATF_CDPLAYER: return "UATF_CDPLAYER"; - case UATF_DAT: return "UATF_DAT"; - case UATF_DCC: return "UATF_DCC"; - case UATF_MINIDISK: return "UATF_MINIDISK"; - case UATF_ANALOGTAPE: return "UATF_ANALOGTAPE"; - case UATF_PHONOGRAPH: return "UATF_PHONOGRAPH"; - case UATF_VCRAUDIO: return "UATF_VCRAUDIO"; - case UATF_VIDEODISCAUDIO: return "UATF_VIDEODISCAUDIO"; - case UATF_DVDAUDIO: return "UATF_DVDAUDIO"; - case UATF_TVTUNERAUDIO: return "UATF_TVTUNERAUDIO"; - case UATF_SATELLITE: return "UATF_SATELLITE"; - case UATF_CABLETUNER: return "UATF_CABLETUNER"; - case UATF_DSS: return "UATF_DSS"; - case UATF_RADIORECV: return "UATF_RADIORECV"; - case UATF_RADIOXMIT: return "UATF_RADIOXMIT"; - case UATF_MULTITRACK: return "UATF_MULTITRACK"; - case UATF_SYNTHESIZER: return "UATF_SYNTHESIZER"; - default: - ksnprintf(buf, sizeof(buf), "unknown type (0x%.4x)", terminal_type); - return buf; - } -} -#endif - -static int -uaudio_determine_class(const struct io_terminal *iot, struct mixerctl *mix) -{ - int terminal_type; - - if (iot == NULL || iot->output == NULL) { - mix->class = UAC_OUTPUT; - return 0; - } - terminal_type = 0; - if (iot->output->size == 1) - terminal_type = iot->output->terminals[0]; - /* - * If the only output terminal is USB, - * the class is UAC_RECORD. - */ - if ((terminal_type & 0xff00) == (UAT_UNDEFINED & 0xff00)) { - mix->class = UAC_RECORD; - if (iot->inputs_size == 1 - && iot->inputs[0] != NULL - && iot->inputs[0]->size == 1) - return iot->inputs[0]->terminals[0]; - else - return 0; - } - /* - * If the ultimate destination of the unit is just one output - * terminal and the unit is connected to the output terminal - * directly, the class is UAC_OUTPUT. - */ - if (terminal_type != 0 && iot->direct) { - mix->class = UAC_OUTPUT; - return terminal_type; - } - /* - * If the unit is connected to just one input terminal, - * the class is UAC_INPUT. - */ - if (iot->inputs_size == 1 && iot->inputs[0] != NULL - && iot->inputs[0]->size == 1) { - mix->class = UAC_INPUT; - return iot->inputs[0]->terminals[0]; - } - /* - * Otherwise, the class is UAC_OUTPUT. - */ - mix->class = UAC_OUTPUT; - return terminal_type; -} - -static int -uaudio_feature_name(const struct io_terminal *iot, struct mixerctl *mix) -{ - int terminal_type; - - terminal_type = uaudio_determine_class(iot, mix); - if (mix->class == UAC_RECORD && terminal_type == 0) - return SOUND_MIXER_IMIX; - DPRINTF(("%s: terminal_type=%s\n", __func__, - uaudio_get_terminal_name(terminal_type))); - switch (terminal_type) { - case UAT_STREAM: - return SOUND_MIXER_PCM; - - case UATI_MICROPHONE: - case UATI_DESKMICROPHONE: - case UATI_PERSONALMICROPHONE: - case UATI_OMNIMICROPHONE: - case UATI_MICROPHONEARRAY: - case UATI_PROCMICROPHONEARR: - return SOUND_MIXER_MIC; - - case UATO_SPEAKER: - case UATO_DESKTOPSPEAKER: - case UATO_ROOMSPEAKER: - case UATO_COMMSPEAKER: - return SOUND_MIXER_SPEAKER; - - case UATE_ANALOGCONN: - case UATE_LINECONN: - case UATE_LEGACYCONN: - return SOUND_MIXER_LINE; - - case UATE_DIGITALAUIFC: - case UATE_SPDIF: - case UATE_1394DA: - case UATE_1394DV: - return SOUND_MIXER_ALTPCM; - - case UATF_CDPLAYER: - return SOUND_MIXER_CD; - - case UATF_SYNTHESIZER: - return SOUND_MIXER_SYNTH; - - case UATF_VIDEODISCAUDIO: - case UATF_DVDAUDIO: - case UATF_TVTUNERAUDIO: - return SOUND_MIXER_VIDEO; - -/* telephony terminal types */ - case UATT_UNDEFINED: - case UATT_PHONELINE: - case UATT_TELEPHONE: - case UATT_DOWNLINEPHONE: - return SOUND_MIXER_PHONEIN; -/* return SOUND_MIXER_PHONEOUT;*/ - - case UATF_RADIORECV: - case UATF_RADIOXMIT: - return SOUND_MIXER_RADIO; - - case UAT_UNDEFINED: - case UAT_VENDOR: - case UATI_UNDEFINED: -/* output terminal types */ - case UATO_UNDEFINED: - case UATO_DISPLAYAUDIO: - case UATO_SUBWOOFER: - case UATO_HEADPHONES: -/* bidir terminal types */ - case UATB_UNDEFINED: - case UATB_HANDSET: - case UATB_HEADSET: - case UATB_SPEAKERPHONE: - case UATB_SPEAKERPHONEESUP: - case UATB_SPEAKERPHONEECANC: -/* external terminal types */ - case UATE_UNDEFINED: -/* embedded function terminal types */ - case UATF_UNDEFINED: - case UATF_CALIBNOISE: - case UATF_EQUNOISE: - case UATF_DAT: - case UATF_DCC: - case UATF_MINIDISK: - case UATF_ANALOGTAPE: - case UATF_PHONOGRAPH: - case UATF_VCRAUDIO: - case UATF_SATELLITE: - case UATF_CABLETUNER: - case UATF_DSS: - case UATF_MULTITRACK: - case 0xffff: - default: - DPRINTF(("%s: 'master' for 0x%.4x\n", __func__, terminal_type)); - return SOUND_MIXER_VOLUME; - } - return SOUND_MIXER_VOLUME; -} - -static void -uaudio_add_feature(struct uaudio_softc *sc, const struct io_terminal *iot, int id) -{ - const struct usb_audio_feature_unit *d; - const uByte *ctls; - int ctlsize; - int nchan; - u_int fumask, mmask, cmask; - struct mixerctl mix; - int chan, ctl, i, unit; - int mixernumber; - -#define GET(i) (ctls[(i)*ctlsize] | \ - (ctlsize > 1 ? ctls[(i)*ctlsize+1] << 8 : 0)) - d = iot[id].d.fu; - ctls = d->bmaControls; - ctlsize = d->bControlSize; - nchan = (d->bLength - 7) / ctlsize; - mmask = GET(0); - /* Figure out what we can control */ - for (cmask = 0, chan = 1; chan < nchan; chan++) { - DPRINTFN(9,("uaudio_add_feature: chan=%d mask=%x\n", - chan, GET(chan))); - cmask |= GET(chan); - } - - if (nchan > MIX_MAX_CHAN) - nchan = MIX_MAX_CHAN; - unit = d->bUnitId; - mix.wIndex = MAKE(unit, sc->sc_ac_iface); - for (ctl = MUTE_CONTROL; ctl < LOUDNESS_CONTROL; ctl++) { - fumask = FU_MASK(ctl); - DPRINTFN(4,("uaudio_add_feature: ctl=%d fumask=0x%04x\n", - ctl, fumask)); - if (mmask & fumask) { - mix.nchan = 1; - mix.wValue[0] = MAKE(ctl, 0); - } else if (cmask & fumask) { - mix.nchan = nchan - 1; - for (i = 1; i < nchan; i++) { - if (GET(i) & fumask) - mix.wValue[i-1] = MAKE(ctl, i); - else - mix.wValue[i-1] = -1; - } - } else { - continue; - } -#undef GET - - mixernumber = uaudio_feature_name(&iot[id], &mix); - - switch (ctl) { - case MUTE_CONTROL: - mix.type = MIX_ON_OFF; - mix.ctl = SOUND_MIXER_NRDEVICES; - break; - case VOLUME_CONTROL: - mix.type = MIX_SIGNED_16; - mix.ctl = mixernumber; - break; - case BASS_CONTROL: - mix.type = MIX_SIGNED_8; - mix.ctl = SOUND_MIXER_BASS; - break; - case MID_CONTROL: - mix.type = MIX_SIGNED_8; - mix.ctl = SOUND_MIXER_NRDEVICES; /* XXXXX */ - break; - case TREBLE_CONTROL: - mix.type = MIX_SIGNED_8; - mix.ctl = SOUND_MIXER_TREBLE; - break; - case GRAPHIC_EQUALIZER_CONTROL: - continue; /* XXX don't add anything */ - break; - case AGC_CONTROL: - mix.type = MIX_ON_OFF; - mix.ctl = SOUND_MIXER_NRDEVICES; /* XXXXX */ - break; - case DELAY_CONTROL: - mix.type = MIX_UNSIGNED_16; - mix.ctl = SOUND_MIXER_NRDEVICES; /* XXXXX */ - break; - case BASS_BOOST_CONTROL: - mix.type = MIX_ON_OFF; - mix.ctl = SOUND_MIXER_NRDEVICES; /* XXXXX */ - break; - case LOUDNESS_CONTROL: - mix.type = MIX_ON_OFF; - mix.ctl = SOUND_MIXER_LOUD; /* Is this correct ? */ - break; - } - uaudio_mixer_add_ctl(sc, &mix); - } -} - -static void -uaudio_add_processing_updown(struct uaudio_softc *sc, - const struct io_terminal *iot, int id) -{ - const struct usb_audio_processing_unit *d; - const struct usb_audio_processing_unit_1 *d1; - const struct usb_audio_processing_unit_updown *ud; - struct mixerctl mix; - int i; - - d = iot[id].d.pu; - d1 = (const struct usb_audio_processing_unit_1 *) - &d->baSourceId[d->bNrInPins]; - ud = (const struct usb_audio_processing_unit_updown *) - &d1->bmControls[d1->bControlSize]; - DPRINTFN(2,("uaudio_add_processing_updown: bUnitId=%d bNrModes=%d\n", - d->bUnitId, ud->bNrModes)); - - if (!(d1->bmControls[0] & UA_PROC_MASK(UD_MODE_SELECT_CONTROL))) { - DPRINTF(("uaudio_add_processing_updown: no mode select\n")); - return; - } - - mix.wIndex = MAKE(d->bUnitId, sc->sc_ac_iface); - mix.nchan = 1; - mix.wValue[0] = MAKE(UD_MODE_SELECT_CONTROL, 0); - uaudio_determine_class(&iot[id], &mix); - mix.type = MIX_ON_OFF; /* XXX */ - - for (i = 0; i < ud->bNrModes; i++) { - DPRINTFN(2,("uaudio_add_processing_updown: i=%d bm=0x%x\n", - i, UGETW(ud->waModes[i]))); - /* XXX */ - } - uaudio_mixer_add_ctl(sc, &mix); -} - -static void -uaudio_add_processing(struct uaudio_softc *sc, const struct io_terminal *iot, int id) -{ - const struct usb_audio_processing_unit *d; - const struct usb_audio_processing_unit_1 *d1; - int ptype; - struct mixerctl mix; - - d = iot[id].d.pu; - d1 = (const struct usb_audio_processing_unit_1 *) - &d->baSourceId[d->bNrInPins]; - ptype = UGETW(d->wProcessType); - DPRINTFN(2,("uaudio_add_processing: wProcessType=%d bUnitId=%d " - "bNrInPins=%d\n", ptype, d->bUnitId, d->bNrInPins)); - - if (d1->bmControls[0] & UA_PROC_ENABLE_MASK) { - mix.wIndex = MAKE(d->bUnitId, sc->sc_ac_iface); - mix.nchan = 1; - mix.wValue[0] = MAKE(XX_ENABLE_CONTROL, 0); - uaudio_determine_class(&iot[id], &mix); - mix.type = MIX_ON_OFF; - uaudio_mixer_add_ctl(sc, &mix); - } - - switch(ptype) { - case UPDOWNMIX_PROCESS: - uaudio_add_processing_updown(sc, iot, id); - break; - case DOLBY_PROLOGIC_PROCESS: - case P3D_STEREO_EXTENDER_PROCESS: - case REVERBATION_PROCESS: - case CHORUS_PROCESS: - case DYN_RANGE_COMP_PROCESS: - default: -#ifdef USB_DEBUG - kprintf("uaudio_add_processing: unit %d, type=%d not impl.\n", - d->bUnitId, ptype); -#endif - break; - } -} - -static void -uaudio_add_extension(struct uaudio_softc *sc, const struct io_terminal *iot, int id) -{ - const struct usb_audio_extension_unit *d; - const struct usb_audio_extension_unit_1 *d1; - struct mixerctl mix; - - d = iot[id].d.eu; - d1 = (const struct usb_audio_extension_unit_1 *) - &d->baSourceId[d->bNrInPins]; - DPRINTFN(2,("uaudio_add_extension: bUnitId=%d bNrInPins=%d\n", - d->bUnitId, d->bNrInPins)); - - if (usbd_get_quirks(sc->sc_udev)->uq_flags & UQ_AU_NO_XU) - return; - - if (d1->bmControls[0] & UA_EXT_ENABLE_MASK) { - mix.wIndex = MAKE(d->bUnitId, sc->sc_ac_iface); - mix.nchan = 1; - mix.wValue[0] = MAKE(UA_EXT_ENABLE, 0); - uaudio_determine_class(&iot[id], &mix); - mix.type = MIX_ON_OFF; - uaudio_mixer_add_ctl(sc, &mix); - } -} - -static struct terminal_list* -uaudio_merge_terminal_list(const struct io_terminal *iot) -{ - struct terminal_list *tml; - uint16_t *ptm; - int i, len; - - len = 0; - if (iot->inputs == NULL) - return NULL; - for (i = 0; i < iot->inputs_size; i++) { - if (iot->inputs[i] != NULL) - len += iot->inputs[i]->size; - } - tml = kmalloc(TERMINAL_LIST_SIZE(len), M_TEMP, M_WAITOK); - tml->size = 0; - ptm = tml->terminals; - for (i = 0; i < iot->inputs_size; i++) { - if (iot->inputs[i] == NULL) - continue; - if (iot->inputs[i]->size > len) - break; - memcpy(ptm, iot->inputs[i]->terminals, - iot->inputs[i]->size * sizeof(uint16_t)); - tml->size += iot->inputs[i]->size; - ptm += iot->inputs[i]->size; - len -= iot->inputs[i]->size; - } - return tml; -} - -static struct terminal_list * -uaudio_io_terminaltype(int outtype, struct io_terminal *iot, int id) -{ - struct terminal_list *tml; - struct io_terminal *it; - int src_id, i; - - it = &iot[id]; - if (it->output != NULL) { - /* already has outtype? */ - for (i = 0; i < it->output->size; i++) - if (it->output->terminals[i] == outtype) - return uaudio_merge_terminal_list(it); - tml = kmalloc(TERMINAL_LIST_SIZE(it->output->size + 1), - M_TEMP, M_WAITOK); - memcpy(tml, it->output, TERMINAL_LIST_SIZE(it->output->size)); - tml->terminals[it->output->size] = outtype; - tml->size++; - kfree(it->output, M_TEMP); - it->output = tml; - if (it->inputs != NULL) { - for (i = 0; i < it->inputs_size; i++) - if (it->inputs[i] != NULL) - kfree(it->inputs[i], M_TEMP); - kfree(it->inputs, M_TEMP); - } - it->inputs_size = 0; - it->inputs = NULL; - } else { /* end `iot[id] != NULL' */ - it->inputs_size = 0; - it->inputs = NULL; - it->output = kmalloc(TERMINAL_LIST_SIZE(1), M_TEMP, M_WAITOK); - it->output->terminals[0] = outtype; - it->output->size = 1; - it->direct = FALSE; - } - - switch (it->d.desc->bDescriptorSubtype) { - case UDESCSUB_AC_INPUT: - it->inputs = kmalloc(sizeof(struct terminal_list *), - M_TEMP, M_WAITOK); - tml = kmalloc(TERMINAL_LIST_SIZE(1), M_TEMP, M_WAITOK); - it->inputs[0] = tml; - tml->terminals[0] = UGETW(it->d.it->wTerminalType); - tml->size = 1; - it->inputs_size = 1; - return uaudio_merge_terminal_list(it); - case UDESCSUB_AC_FEATURE: - src_id = it->d.fu->bSourceId; - it->inputs = kmalloc(sizeof(struct terminal_list *), - M_TEMP, M_WAITOK); - it->inputs[0] = uaudio_io_terminaltype(outtype, iot, src_id); - it->inputs_size = 1; - return uaudio_merge_terminal_list(it); - case UDESCSUB_AC_OUTPUT: - it->inputs = kmalloc(sizeof(struct terminal_list *), - M_TEMP, M_WAITOK); - src_id = it->d.ot->bSourceId; - it->inputs[0] = uaudio_io_terminaltype(outtype, iot, src_id); - it->inputs_size = 1; - iot[src_id].direct = TRUE; - return NULL; - case UDESCSUB_AC_MIXER: - it->inputs_size = 0; - it->inputs = kmalloc(sizeof(struct terminal_list *) * - it->d.mu->bNrInPins, M_TEMP, M_WAITOK); - for (i = 0; i < it->d.mu->bNrInPins; i++) { - src_id = it->d.mu->baSourceId[i]; - it->inputs[i] = uaudio_io_terminaltype(outtype, iot, - src_id); - it->inputs_size++; - } - return uaudio_merge_terminal_list(it); - case UDESCSUB_AC_SELECTOR: - it->inputs_size = 0; - it->inputs = kmalloc(sizeof(struct terminal_list *) * - it->d.su->bNrInPins, M_TEMP, M_WAITOK); - for (i = 0; i < it->d.su->bNrInPins; i++) { - src_id = it->d.su->baSourceId[i]; - it->inputs[i] = uaudio_io_terminaltype(outtype, iot, - src_id); - it->inputs_size++; - } - return uaudio_merge_terminal_list(it); - case UDESCSUB_AC_PROCESSING: - it->inputs_size = 0; - it->inputs = kmalloc(sizeof(struct terminal_list *) * - it->d.pu->bNrInPins, M_TEMP, M_WAITOK); - for (i = 0; i < it->d.pu->bNrInPins; i++) { - src_id = it->d.pu->baSourceId[i]; - it->inputs[i] = uaudio_io_terminaltype(outtype, iot, - src_id); - it->inputs_size++; - } - return uaudio_merge_terminal_list(it); - case UDESCSUB_AC_EXTENSION: - it->inputs_size = 0; - it->inputs = kmalloc(sizeof(struct terminal_list *) * - it->d.eu->bNrInPins, M_TEMP, M_WAITOK); - for (i = 0; i < it->d.eu->bNrInPins; i++) { - src_id = it->d.eu->baSourceId[i]; - it->inputs[i] = uaudio_io_terminaltype(outtype, iot, - src_id); - it->inputs_size++; - } - return uaudio_merge_terminal_list(it); - case UDESCSUB_AC_HEADER: - default: - return NULL; - } -} - -static usbd_status -uaudio_identify(struct uaudio_softc *sc, const usb_config_descriptor_t *cdesc) -{ - usbd_status err; - - err = uaudio_identify_ac(sc, cdesc); - if (err) - return err; - return uaudio_identify_as(sc, cdesc); -} - -static void -uaudio_add_alt(struct uaudio_softc *sc, const struct as_info *ai) -{ - size_t len; - struct as_info *nai; - - len = sizeof(*ai) * (sc->sc_nalts + 1); - nai = kmalloc(len, M_USBDEV, M_WAITOK); - - /* Copy old data, if there was any */ - if (sc->sc_nalts != 0) { - memcpy(nai, sc->sc_alts, sizeof(*ai) * (sc->sc_nalts)); - kfree(sc->sc_alts, M_USBDEV); - } - sc->sc_alts = nai; - DPRINTFN(2,("uaudio_add_alt: adding alt=%d, enc=%d\n", - ai->alt, ai->encoding)); - sc->sc_alts[sc->sc_nalts++] = *ai; -} - -static usbd_status -uaudio_process_as(struct uaudio_softc *sc, const char *buf, int *offsp, - int size, const usb_interface_descriptor_t *id) -#define offs (*offsp) -{ - const struct usb_audio_streaming_interface_descriptor *asid; - const struct usb_audio_streaming_type1_descriptor *asf1d; - const usb_endpoint_descriptor_audio_t *ed; - const usb_endpoint_descriptor_audio_t *epdesc1; - const struct usb_audio_streaming_endpoint_descriptor *sed; - int format, chan, prec, enc; - int dir, type, sync; - struct as_info ai; - const char *format_str; - - asid = (const void *)(buf + offs); - - if (asid->bDescriptorType != UDESC_CS_INTERFACE || - asid->bDescriptorSubtype != AS_GENERAL) - return USBD_INVAL; - DPRINTF(("uaudio_process_as: asid: bTerminakLink=%d wFormatTag=%d\n", - asid->bTerminalLink, UGETW(asid->wFormatTag))); - offs += asid->bLength; - if (offs > size) - return USBD_INVAL; - - asf1d = (const void *)(buf + offs); - if (asf1d->bDescriptorType != UDESC_CS_INTERFACE || - asf1d->bDescriptorSubtype != FORMAT_TYPE) - return USBD_INVAL; - offs += asf1d->bLength; - if (offs > size) - return USBD_INVAL; - - if (asf1d->bFormatType != FORMAT_TYPE_I) { - kprintf("%s: ignored setting with type %d format\n", - device_get_nameunit(sc->sc_dev), UGETW(asid->wFormatTag)); - return USBD_NORMAL_COMPLETION; - } - - ed = (const void *)(buf + offs); - if (ed->bDescriptorType != UDESC_ENDPOINT) - return USBD_INVAL; - DPRINTF(("uaudio_process_as: endpoint[0] bLength=%d bDescriptorType=%d " - "bEndpointAddress=%d bmAttributes=0x%x wMaxPacketSize=%d " - "bInterval=%d bRefresh=%d bSynchAddress=%d\n", - ed->bLength, ed->bDescriptorType, ed->bEndpointAddress, - ed->bmAttributes, UGETW(ed->wMaxPacketSize), - ed->bInterval, ed->bRefresh, ed->bSynchAddress)); - offs += ed->bLength; - if (offs > size) - return USBD_INVAL; - if (UE_GET_XFERTYPE(ed->bmAttributes) != UE_ISOCHRONOUS) - return USBD_INVAL; - - dir = UE_GET_DIR(ed->bEndpointAddress); - type = UE_GET_ISO_TYPE(ed->bmAttributes); - if ((usbd_get_quirks(sc->sc_udev)->uq_flags & UQ_AU_INP_ASYNC) && - dir == UE_DIR_IN && type == UE_ISO_ADAPT) - type = UE_ISO_ASYNC; - - /* We can't handle endpoints that need a sync pipe yet. */ - sync = FALSE; - if (dir == UE_DIR_IN && type == UE_ISO_ADAPT) { - sync = TRUE; -#ifndef UAUDIO_MULTIPLE_ENDPOINTS - kprintf("%s: ignored input endpoint of type adaptive\n", - device_get_nameunit(sc->sc_dev)); - return USBD_NORMAL_COMPLETION; -#endif - } - if (dir != UE_DIR_IN && type == UE_ISO_ASYNC) { - sync = TRUE; -#ifndef UAUDIO_MULTIPLE_ENDPOINTS - kprintf("%s: ignored output endpoint of type async\n", - device_get_nameunit(sc->sc_dev)); - return USBD_NORMAL_COMPLETION; -#endif - } - - sed = (const void *)(buf + offs); - if (sed->bDescriptorType != UDESC_CS_ENDPOINT || - sed->bDescriptorSubtype != AS_GENERAL) - return USBD_INVAL; - DPRINTF((" streadming_endpoint: offset=%d bLength=%d\n", offs, sed->bLength)); - offs += sed->bLength; - if (offs > size) - return USBD_INVAL; - - if (sync && id->bNumEndpoints <= 1) { - kprintf("%s: a sync-pipe endpoint but no other endpoint\n", - device_get_nameunit(sc->sc_dev)); - return USBD_INVAL; - } - if (!sync && id->bNumEndpoints > 1) { - kprintf("%s: non sync-pipe endpoint but multiple endpoints\n", - device_get_nameunit(sc->sc_dev)); - return USBD_INVAL; - } - epdesc1 = NULL; - if (id->bNumEndpoints > 1) { - epdesc1 = (const void*)(buf + offs); - if (epdesc1->bDescriptorType != UDESC_ENDPOINT) - return USBD_INVAL; - DPRINTF(("uaudio_process_as: endpoint[1] bLength=%d " - "bDescriptorType=%d bEndpointAddress=%d " - "bmAttributes=0x%x wMaxPacketSize=%d bInterval=%d " - "bRefresh=%d bSynchAddress=%d\n", - epdesc1->bLength, epdesc1->bDescriptorType, - epdesc1->bEndpointAddress, epdesc1->bmAttributes, - UGETW(epdesc1->wMaxPacketSize), epdesc1->bInterval, - epdesc1->bRefresh, epdesc1->bSynchAddress)); - offs += epdesc1->bLength; - if (offs > size) - return USBD_INVAL; - if (epdesc1->bSynchAddress != 0) { - kprintf("%s: invalid endpoint: bSynchAddress=0\n", - device_get_nameunit(sc->sc_dev)); - return USBD_INVAL; - } - if (UE_GET_XFERTYPE(epdesc1->bmAttributes) != UE_ISOCHRONOUS) { - kprintf("%s: invalid endpoint: bmAttributes=0x%x\n", - device_get_nameunit(sc->sc_dev), epdesc1->bmAttributes); - return USBD_INVAL; - } - if (epdesc1->bEndpointAddress != ed->bSynchAddress) { - kprintf("%s: invalid endpoint addresses: " - "ep[0]->bSynchAddress=0x%x " - "ep[1]->bEndpointAddress=0x%x\n", - device_get_nameunit(sc->sc_dev), ed->bSynchAddress, - epdesc1->bEndpointAddress); - return USBD_INVAL; - } - /* UE_GET_ADDR(epdesc1->bEndpointAddress), and epdesc1->bRefresh */ - } - - format = UGETW(asid->wFormatTag); - chan = asf1d->bNrChannels; - prec = asf1d->bBitResolution; - if (prec != 8 && prec != 16 && prec != 24 && prec != 32) { - kprintf("%s: ignored setting with precision %d\n", - device_get_nameunit(sc->sc_dev), prec); - return USBD_NORMAL_COMPLETION; - } - switch (format) { - case UA_FMT_PCM: - if (prec == 8) { - sc->sc_altflags |= HAS_8; - } else if (prec == 16) { - sc->sc_altflags |= HAS_16; - } else if (prec == 24) { - sc->sc_altflags |= HAS_24; - } else if (prec == 32) { - sc->sc_altflags |= HAS_32; - } - enc = AUDIO_ENCODING_SLINEAR_LE; - format_str = "pcm"; - break; - case UA_FMT_PCM8: - enc = AUDIO_ENCODING_ULINEAR_LE; - sc->sc_altflags |= HAS_8U; - format_str = "pcm8"; - break; - case UA_FMT_ALAW: - enc = AUDIO_ENCODING_ALAW; - sc->sc_altflags |= HAS_ALAW; - format_str = "alaw"; - break; - case UA_FMT_MULAW: - enc = AUDIO_ENCODING_ULAW; - sc->sc_altflags |= HAS_MULAW; - format_str = "mulaw"; - break; - case UA_FMT_IEEE_FLOAT: - default: - kprintf("%s: ignored setting with format %d\n", - device_get_nameunit(sc->sc_dev), format); - return USBD_NORMAL_COMPLETION; - } -#ifdef USB_DEBUG - kprintf("%s: %s: %dch, %d/%dbit, %s,", device_get_nameunit(sc->sc_dev), - dir == UE_DIR_IN ? "recording" : "playback", - chan, prec, asf1d->bSubFrameSize * 8, format_str); - if (asf1d->bSamFreqType == UA_SAMP_CONTNUOUS) { - kprintf(" %d-%dHz\n", UA_SAMP_LO(asf1d), UA_SAMP_HI(asf1d)); - } else { - int r; - kprintf(" %d", UA_GETSAMP(asf1d, 0)); - for (r = 1; r < asf1d->bSamFreqType; r++) - kprintf(",%d", UA_GETSAMP(asf1d, r)); - kprintf("Hz\n"); - } -#endif - if (sc->uaudio_sndstat_flag != 0) { - sbuf_printf(&(sc->uaudio_sndstat), "\n\t"); - sbuf_printf(&(sc->uaudio_sndstat), - "mode %d:(%s) %dch, %d/%dbit, %s,", - id->bAlternateSetting, - dir == UE_DIR_IN ? "input" : "output", - chan, prec, asf1d->bSubFrameSize * 8, format_str); - if (asf1d->bSamFreqType == UA_SAMP_CONTNUOUS) { - sbuf_printf(&(sc->uaudio_sndstat), " %d-%dHz", - UA_SAMP_LO(asf1d), UA_SAMP_HI(asf1d)); - } else { - int r; - sbuf_printf(&(sc->uaudio_sndstat), - " %d", UA_GETSAMP(asf1d, 0)); - for (r = 1; r < asf1d->bSamFreqType; r++) - sbuf_printf(&(sc->uaudio_sndstat), - ",%d", UA_GETSAMP(asf1d, r)); - sbuf_printf(&(sc->uaudio_sndstat), "Hz"); - } - } - - ai.alt = id->bAlternateSetting; - ai.encoding = enc; - ai.attributes = sed->bmAttributes; - ai.idesc = id; - ai.edesc = ed; - ai.edesc1 = epdesc1; - ai.asf1desc = asf1d; - ai.sc_busy = 0; - ai.ifaceh = NULL; - uaudio_add_alt(sc, &ai); -#ifdef USB_DEBUG - if (ai.attributes & UA_SED_FREQ_CONTROL) - DPRINTFN(1, ("uaudio_process_as: FREQ_CONTROL\n")); - if (ai.attributes & UA_SED_PITCH_CONTROL) - DPRINTFN(1, ("uaudio_process_as: PITCH_CONTROL\n")); -#endif - sc->sc_mode |= (dir == UE_DIR_OUT) ? AUMODE_PLAY : AUMODE_RECORD; - - return USBD_NORMAL_COMPLETION; -} -#undef offs - -static usbd_status -uaudio_identify_as(struct uaudio_softc *sc, - const usb_config_descriptor_t *cdesc) -{ - const usb_interface_descriptor_t *id; - const char *buf; - int size, offs; - - size = UGETW(cdesc->wTotalLength); - buf = (const char *)cdesc; - - /* Locate the AudioStreaming interface descriptor. */ - offs = 0; - id = uaudio_find_iface(buf, size, &offs, UISUBCLASS_AUDIOSTREAM); - if (id == NULL) - return USBD_INVAL; - - sc->uaudio_sndstat_flag = 0; - if (sbuf_new(&(sc->uaudio_sndstat), NULL, 4096, SBUF_AUTOEXTEND) != NULL) - sc->uaudio_sndstat_flag = 1; - - /* Loop through all the alternate settings. */ - while (offs <= size) { - DPRINTFN(2, ("uaudio_identify: interface=%d offset=%d\n", - id->bInterfaceNumber, offs)); - switch (id->bNumEndpoints) { - case 0: - DPRINTFN(2, ("uaudio_identify: AS null alt=%d\n", - id->bAlternateSetting)); - sc->sc_nullalt = id->bAlternateSetting; - break; - case 1: -#ifdef UAUDIO_MULTIPLE_ENDPOINTS - case 2: -#endif - uaudio_process_as(sc, buf, &offs, size, id); - break; - default: - kprintf("%s: ignored audio interface with %d " - "endpoints\n", - device_get_nameunit(sc->sc_dev), id->bNumEndpoints); - break; - } - id = uaudio_find_iface(buf, size, &offs,UISUBCLASS_AUDIOSTREAM); - if (id == NULL) - break; - } - - sbuf_finish(&(sc->uaudio_sndstat)); - - if (offs > size) - return USBD_INVAL; - DPRINTF(("uaudio_identify_as: %d alts available\n", sc->sc_nalts)); - - if (sc->sc_mode == 0) { - kprintf("%s: no usable endpoint found\n", - device_get_nameunit(sc->sc_dev)); - return USBD_INVAL; - } - - return USBD_NORMAL_COMPLETION; -} - -static usbd_status -uaudio_identify_ac(struct uaudio_softc *sc, const usb_config_descriptor_t *cdesc) -{ - struct io_terminal* iot; - const usb_interface_descriptor_t *id; - const struct usb_audio_control_descriptor *acdp; - const usb_descriptor_t *dp; - const struct usb_audio_output_terminal *pot; - struct terminal_list *tml; - const char *buf, *ibuf, *ibufend; - int size, offs, aclen, ndps, i, j; - - size = UGETW(cdesc->wTotalLength); - buf = (const char *)cdesc; - - /* Locate the AudioControl interface descriptor. */ - offs = 0; - id = uaudio_find_iface(buf, size, &offs, UISUBCLASS_AUDIOCONTROL); - if (id == NULL) - return USBD_INVAL; - if (offs + sizeof *acdp > size) - return USBD_INVAL; - sc->sc_ac_iface = id->bInterfaceNumber; - DPRINTFN(2,("uaudio_identify_ac: AC interface is %d\n", sc->sc_ac_iface)); - - /* A class-specific AC interface header should follow. */ - ibuf = buf + offs; - acdp = (const struct usb_audio_control_descriptor *)ibuf; - if (acdp->bDescriptorType != UDESC_CS_INTERFACE || - acdp->bDescriptorSubtype != UDESCSUB_AC_HEADER) - return USBD_INVAL; - aclen = UGETW(acdp->wTotalLength); - if (offs + aclen > size) - return USBD_INVAL; - - if (!(usbd_get_quirks(sc->sc_udev)->uq_flags & UQ_BAD_ADC) && - UGETW(acdp->bcdADC) != UAUDIO_VERSION) - return USBD_INVAL; - - sc->sc_audio_rev = UGETW(acdp->bcdADC); - DPRINTFN(2,("uaudio_identify_ac: found AC header, vers=%03x, len=%d\n", - sc->sc_audio_rev, aclen)); - - sc->sc_nullalt = -1; - - /* Scan through all the AC specific descriptors */ - ibufend = ibuf + aclen; - dp = (const usb_descriptor_t *)ibuf; - ndps = 0; - iot = kmalloc(sizeof(struct io_terminal) * 256, - M_TEMP, M_WAITOK | M_ZERO); - for (;;) { - ibuf += dp->bLength; - if (ibuf >= ibufend) - break; - dp = (const usb_descriptor_t *)ibuf; - if (ibuf + dp->bLength > ibufend) { - kfree(iot, M_TEMP); - return USBD_INVAL; - } - if (dp->bDescriptorType != UDESC_CS_INTERFACE) { - kprintf("uaudio_identify_ac: skip desc type=0x%02x\n", - dp->bDescriptorType); - continue; - } - i = ((const struct usb_audio_input_terminal *)dp)->bTerminalId; - iot[i].d.desc = dp; - if (i > ndps) - ndps = i; - } - ndps++; - - /* construct io_terminal */ - for (i = 0; i < ndps; i++) { - dp = iot[i].d.desc; - if (dp == NULL) - continue; - if (dp->bDescriptorSubtype != UDESCSUB_AC_OUTPUT) - continue; - pot = iot[i].d.ot; - tml = uaudio_io_terminaltype(UGETW(pot->wTerminalType), iot, i); - if (tml != NULL) - kfree(tml, M_TEMP); - } - -#ifdef USB_DEBUG - for (i = 0; i < 256; i++) { - struct usb_audio_cluster cluster; - - if (iot[i].d.desc == NULL) - continue; - kprintf("id %d:\t", i); - switch (iot[i].d.desc->bDescriptorSubtype) { - case UDESCSUB_AC_INPUT: - kprintf("AC_INPUT type=%s\n", uaudio_get_terminal_name - (UGETW(iot[i].d.it->wTerminalType))); - kprintf("\t"); - cluster = uaudio_get_cluster(i, iot); - uaudio_dump_cluster(&cluster); - kprintf("\n"); - break; - case UDESCSUB_AC_OUTPUT: - kprintf("AC_OUTPUT type=%s ", uaudio_get_terminal_name - (UGETW(iot[i].d.ot->wTerminalType))); - kprintf("src=%d\n", iot[i].d.ot->bSourceId); - break; - case UDESCSUB_AC_MIXER: - kprintf("AC_MIXER src="); - for (j = 0; j < iot[i].d.mu->bNrInPins; j++) - kprintf("%d ", iot[i].d.mu->baSourceId[j]); - kprintf("\n\t"); - cluster = uaudio_get_cluster(i, iot); - uaudio_dump_cluster(&cluster); - kprintf("\n"); - break; - case UDESCSUB_AC_SELECTOR: - kprintf("AC_SELECTOR src="); - for (j = 0; j < iot[i].d.su->bNrInPins; j++) - kprintf("%d ", iot[i].d.su->baSourceId[j]); - kprintf("\n"); - break; - case UDESCSUB_AC_FEATURE: - kprintf("AC_FEATURE src=%d\n", iot[i].d.fu->bSourceId); - break; - case UDESCSUB_AC_PROCESSING: - kprintf("AC_PROCESSING src="); - for (j = 0; j < iot[i].d.pu->bNrInPins; j++) - kprintf("%d ", iot[i].d.pu->baSourceId[j]); - kprintf("\n\t"); - cluster = uaudio_get_cluster(i, iot); - uaudio_dump_cluster(&cluster); - kprintf("\n"); - break; - case UDESCSUB_AC_EXTENSION: - kprintf("AC_EXTENSION src="); - for (j = 0; j < iot[i].d.eu->bNrInPins; j++) - kprintf("%d ", iot[i].d.eu->baSourceId[j]); - kprintf("\n\t"); - cluster = uaudio_get_cluster(i, iot); - uaudio_dump_cluster(&cluster); - kprintf("\n"); - break; - default: - kprintf("unknown audio control (subtype=%d)\n", - iot[i].d.desc->bDescriptorSubtype); - } - for (j = 0; j < iot[i].inputs_size; j++) { - int k; - kprintf("\tinput%d: ", j); - tml = iot[i].inputs[j]; - if (tml == NULL) { - kprintf("NULL\n"); - continue; - } - for (k = 0; k < tml->size; k++) - kprintf("%s ", uaudio_get_terminal_name - (tml->terminals[k])); - kprintf("\n"); - } - kprintf("\toutput: "); - tml = iot[i].output; - for (j = 0; j < tml->size; j++) - kprintf("%s ", uaudio_get_terminal_name(tml->terminals[j])); - kprintf("\n"); - } -#endif - - for (i = 0; i < ndps; i++) { - dp = iot[i].d.desc; - if (dp == NULL) - continue; - DPRINTF(("uaudio_identify_ac: id=%d subtype=%d\n", - i, dp->bDescriptorSubtype)); - switch (dp->bDescriptorSubtype) { - case UDESCSUB_AC_HEADER: - kprintf("uaudio_identify_ac: unexpected AC header\n"); - break; - case UDESCSUB_AC_INPUT: - uaudio_add_input(sc, iot, i); - break; - case UDESCSUB_AC_OUTPUT: - uaudio_add_output(sc, iot, i); - break; - case UDESCSUB_AC_MIXER: - uaudio_add_mixer(sc, iot, i); - break; - case UDESCSUB_AC_SELECTOR: - uaudio_add_selector(sc, iot, i); - break; - case UDESCSUB_AC_FEATURE: - uaudio_add_feature(sc, iot, i); - break; - case UDESCSUB_AC_PROCESSING: - uaudio_add_processing(sc, iot, i); - break; - case UDESCSUB_AC_EXTENSION: - uaudio_add_extension(sc, iot, i); - break; - default: - kprintf("uaudio_identify_ac: bad AC desc subtype=0x%02x\n", - dp->bDescriptorSubtype); - break; - } - } - - /* delete io_terminal */ - for (i = 0; i < 256; i++) { - if (iot[i].d.desc == NULL) - continue; - if (iot[i].inputs != NULL) { - for (j = 0; j < iot[i].inputs_size; j++) { - if (iot[i].inputs[j] != NULL) - kfree(iot[i].inputs[j], M_TEMP); - } - kfree(iot[i].inputs, M_TEMP); - } - if (iot[i].output != NULL) - kfree(iot[i].output, M_TEMP); - iot[i].d.desc = NULL; - } - kfree(iot, M_TEMP); - - return USBD_NORMAL_COMPLETION; -} - -static int -uaudio_get(struct uaudio_softc *sc, int which, int type, int wValue, - int wIndex, int len) -{ - usb_device_request_t req; - uint8_t data[4]; - usbd_status err; - int val; - - if (sc->sc_dying) - return EIO; - - if (wValue == -1) - return 0; - - req.bmRequestType = type; - req.bRequest = which; - USETW(req.wValue, wValue); - USETW(req.wIndex, wIndex); - USETW(req.wLength, len); - DPRINTFN(2,("uaudio_get: type=0x%02x req=0x%02x wValue=0x%04x " - "wIndex=0x%04x len=%d\n", - type, which, wValue, wIndex, len)); - err = usbd_do_request(sc->sc_udev, &req, data); - if (err) { - DPRINTF(("uaudio_get: err=%s\n", usbd_errstr(err))); - return -1; - } - switch (len) { - case 1: - val = data[0]; - break; - case 2: - val = data[0] | (data[1] << 8); - break; - default: - DPRINTF(("uaudio_get: bad length=%d\n", len)); - return -1; - } - DPRINTFN(2,("uaudio_get: val=%d\n", val)); - return val; -} - -static void -uaudio_set(struct uaudio_softc *sc, int which, int type, int wValue, - int wIndex, int len, int val) -{ - usb_device_request_t req; - uint8_t data[4]; - usbd_status err; - - if (sc->sc_dying) - return; - - if (wValue == -1) - return; - - req.bmRequestType = type; - req.bRequest = which; - USETW(req.wValue, wValue); - USETW(req.wIndex, wIndex); - USETW(req.wLength, len); - switch (len) { - case 1: - data[0] = val; - break; - case 2: - data[0] = val; - data[1] = val >> 8; - break; - default: - return; - } - DPRINTFN(2,("uaudio_set: type=0x%02x req=0x%02x wValue=0x%04x " - "wIndex=0x%04x len=%d, val=%d\n", - type, which, wValue, wIndex, len, val & 0xffff)); - err = usbd_do_request(sc->sc_udev, &req, data); -#ifdef USB_DEBUG - if (err) - DPRINTF(("uaudio_set: err=%d\n", err)); -#endif -} - -static int -uaudio_signext(int type, int val) -{ - if (!MIX_UNSIGNED(type)) { - if (MIX_SIZE(type) == 2) - val = (int16_t)val; - else - val = (int8_t)val; - } - return val; -} - -int -uaudio_bsd2value(struct mixerctl *mc, int val) -{ - DPRINTFN(5,("uaudio_bsd2value: type=%03x val=%d min=%d max=%d ", - mc->type, val, mc->minval, mc->maxval)); - if (mc->type == MIX_ON_OFF) { - val = (val != 0); - } else if (mc->type == MIX_SELECTOR) { - if (val < mc->minval || val > mc->maxval) - val = mc->minval; - } else - val = (val + mc->delta/2) * mc->mul / 255 + mc->minval; - DPRINTFN(5, ("val'=%d\n", val)); - return val; -} - -static void -uaudio_ctl_set(struct uaudio_softc *sc, int which, struct mixerctl *mc, - int chan, int val) -{ - val = uaudio_bsd2value(mc, val); - uaudio_set(sc, which, UT_WRITE_CLASS_INTERFACE, mc->wValue[chan], - mc->wIndex, MIX_SIZE(mc->type), val); -} - -/* Set up a pipe for a channel. */ -static usbd_status -uaudio_chan_open(struct uaudio_softc *sc, struct chan *ch) -{ - struct as_info *as; - int endpt; - usbd_status err; - - if (sc->sc_dying) - return EIO; - - as = &sc->sc_alts[ch->altidx]; - endpt = as->edesc->bEndpointAddress; - DPRINTF(("uaudio_chan_open: endpt=0x%02x, speed=%d, alt=%d\n", - endpt, ch->sample_rate, as->alt)); - - /* Set alternate interface corresponding to the mode. */ - err = usbd_set_interface(as->ifaceh, as->alt); - if (err) - return err; - - /* - * If just one sampling rate is supported, - * no need to call uaudio_set_speed(). - * Roland SD-90 freezes by a SAMPLING_FREQ_CONTROL request. - */ - if (as->asf1desc->bSamFreqType != 1) { - err = uaudio_set_speed(sc, endpt, ch->sample_rate); - if (err) - DPRINTF(("uaudio_chan_open: set_speed failed err=%s\n", - usbd_errstr(err))); - } - - ch->pipe = 0; - ch->sync_pipe = 0; - DPRINTF(("uaudio_chan_open: create pipe to 0x%02x\n", endpt)); - err = usbd_open_pipe(as->ifaceh, endpt, 0, &ch->pipe); - if (err) - return err; - if (as->edesc1 != NULL) { - endpt = as->edesc1->bEndpointAddress; - DPRINTF(("uaudio_chan_open: create sync-pipe to 0x%02x\n", endpt)); - err = usbd_open_pipe(as->ifaceh, endpt, 0, &ch->sync_pipe); - } - return err; -} - -static void -uaudio_chan_close(struct uaudio_softc *sc, struct chan *ch) -{ - struct as_info *as; - - if (sc->sc_dying) - return ; - - as = &sc->sc_alts[ch->altidx]; - as->sc_busy = 0; - if (sc->sc_nullalt >= 0) { - DPRINTF(("uaudio_chan_close: set null alt=%d\n", - sc->sc_nullalt)); - usbd_set_interface(as->ifaceh, sc->sc_nullalt); - } - if (ch->pipe) { - usbd_abort_pipe(ch->pipe); - usbd_close_pipe(ch->pipe); - } - if (ch->sync_pipe) { - usbd_abort_pipe(ch->sync_pipe); - usbd_close_pipe(ch->sync_pipe); - } -} - -static usbd_status -uaudio_chan_alloc_buffers(struct uaudio_softc *sc, struct chan *ch) -{ - usbd_xfer_handle xfer; - void *buf; - int i, size; - - size = (ch->bytes_per_frame + ch->sample_size) * UAUDIO_NFRAMES; - for (i = 0; i < UAUDIO_NCHANBUFS; i++) { - xfer = usbd_alloc_xfer(sc->sc_udev); - if (xfer == 0) - goto bad; - ch->chanbufs[i].xfer = xfer; - buf = usbd_alloc_buffer(xfer, size); - if (buf == NULL) { - i++; - goto bad; - } - ch->chanbufs[i].buffer = buf; - ch->chanbufs[i].chan = ch; - } - - return USBD_NORMAL_COMPLETION; - -bad: - while (--i >= 0) - /* implicit buffer kfree */ - usbd_free_xfer(ch->chanbufs[i].xfer); - return USBD_NOMEM; -} - -static void -uaudio_chan_free_buffers(struct uaudio_softc *sc, struct chan *ch) -{ - int i; - - for (i = 0; i < UAUDIO_NCHANBUFS; i++) - usbd_free_xfer(ch->chanbufs[i].xfer); -} - -/* Called at splusb() */ -static void -uaudio_chan_ptransfer(struct chan *ch) -{ - struct chanbuf *cb; - int i, n, size, residue, total; - - if (ch->sc->sc_dying) - return; - - /* Pick the next channel buffer. */ - cb = &ch->chanbufs[ch->curchanbuf]; - if (++ch->curchanbuf >= UAUDIO_NCHANBUFS) - ch->curchanbuf = 0; - - /* Compute the size of each frame in the next transfer. */ - residue = ch->residue; - total = 0; - for (i = 0; i < UAUDIO_NFRAMES; i++) { - size = ch->bytes_per_frame; - residue += ch->fraction; - if (residue >= USB_FRAMES_PER_SECOND) { - if ((ch->sc->sc_altflags & UA_NOFRAC) == 0) - size += ch->sample_size; - residue -= USB_FRAMES_PER_SECOND; - } - cb->sizes[i] = size; - total += size; - } - ch->residue = residue; - cb->size = total; - - /* - * Transfer data from upper layer buffer to channel buffer, taking - * care of wrapping the upper layer buffer. - */ - n = min(total, ch->end - ch->cur); - memcpy(cb->buffer, ch->cur, n); - ch->cur += n; - if (ch->cur >= ch->end) - ch->cur = ch->start; - if (total > n) { - total -= n; - memcpy(cb->buffer + n, ch->cur, total); - ch->cur += total; - } - -#ifdef USB_DEBUG - if (uaudiodebug > 8) { - DPRINTF(("uaudio_chan_ptransfer: buffer=%p, residue=0.%03d\n", - cb->buffer, ch->residue)); - for (i = 0; i < UAUDIO_NFRAMES; i++) { - DPRINTF((" [%d] length %d\n", i, cb->sizes[i])); - } - } -#endif - - DPRINTFN(5,("uaudio_chan_transfer: ptransfer xfer=%p\n", cb->xfer)); - /* Fill the request */ - usbd_setup_isoc_xfer(cb->xfer, ch->pipe, cb, cb->sizes, - UAUDIO_NFRAMES, USBD_NO_COPY, - uaudio_chan_pintr); - - (void)usbd_transfer(cb->xfer); -} - -static void -uaudio_chan_pintr(usbd_xfer_handle xfer, usbd_private_handle priv, - usbd_status status) -{ - struct chanbuf *cb; - struct chan *ch; - u_int32_t count; - - cb = priv; - ch = cb->chan; - /* Return if we are aborting. */ - if (status == USBD_CANCELLED) - return; - - usbd_get_xfer_status(xfer, NULL, NULL, &count, NULL); - DPRINTFN(5,("uaudio_chan_pintr: count=%d, transferred=%d\n", - count, ch->transferred)); -#ifdef DIAGNOSTIC - if (count != cb->size) { - kprintf("uaudio_chan_pintr: count(%d) != size(%d)\n", - count, cb->size); - } -#endif - - ch->transferred += cb->size; - - crit_enter(); - chn_intr(ch->pcm_ch); - crit_exit(); - - /* start next transfer */ - uaudio_chan_ptransfer(ch); -} - -/* Called at splusb() */ -static void -uaudio_chan_rtransfer(struct chan *ch) -{ - struct chanbuf *cb; - int i, size, residue, total; - - if (ch->sc->sc_dying) - return; - - /* Pick the next channel buffer. */ - cb = &ch->chanbufs[ch->curchanbuf]; - if (++ch->curchanbuf >= UAUDIO_NCHANBUFS) - ch->curchanbuf = 0; - - /* Compute the size of each frame in the next transfer. */ - residue = ch->residue; - total = 0; - for (i = 0; i < UAUDIO_NFRAMES; i++) { - size = ch->bytes_per_frame; - cb->sizes[i] = size; - cb->offsets[i] = total; - total += size; - } - ch->residue = residue; - cb->size = total; - -#ifdef USB_DEBUG - if (uaudiodebug > 8) { - DPRINTF(("uaudio_chan_rtransfer: buffer=%p, residue=0.%03d\n", - cb->buffer, ch->residue)); - for (i = 0; i < UAUDIO_NFRAMES; i++) { - DPRINTF((" [%d] length %d\n", i, cb->sizes[i])); - } - } -#endif - - DPRINTFN(5,("uaudio_chan_rtransfer: transfer xfer=%p\n", cb->xfer)); - /* Fill the request */ - usbd_setup_isoc_xfer(cb->xfer, ch->pipe, cb, cb->sizes, - UAUDIO_NFRAMES, USBD_NO_COPY, - uaudio_chan_rintr); - - (void)usbd_transfer(cb->xfer); -} - -static void -uaudio_chan_rintr(usbd_xfer_handle xfer, usbd_private_handle priv, - usbd_status status) -{ - struct chanbuf *cb = priv; - struct chan *ch = cb->chan; - u_int32_t count; - int i, n, frsize; - - /* Return if we are aborting. */ - if (status == USBD_CANCELLED) - return; - - usbd_get_xfer_status(xfer, NULL, NULL, &count, NULL); - DPRINTFN(5,("uaudio_chan_rintr: count=%d, transferred=%d\n", - count, ch->transferred)); - - /* count < cb->size is normal for asynchronous source */ -#ifdef DIAGNOSTIC - if (count > cb->size) { - kprintf("uaudio_chan_rintr: count(%d) > size(%d)\n", - count, cb->size); - } -#endif - - /* - * Transfer data from channel buffer to upper layer buffer, taking - * care of wrapping the upper layer buffer. - */ - for(i = 0; i < UAUDIO_NFRAMES; i++) { - frsize = cb->sizes[i]; - n = min(frsize, ch->end - ch->cur); - memcpy(ch->cur, cb->buffer + cb->offsets[i], n); - ch->cur += n; - if (ch->cur >= ch->end) - ch->cur = ch->start; - if (frsize > n) { - memcpy(ch->cur, cb->buffer + cb->offsets[i] + n, - frsize - n); - ch->cur += frsize - n; - } - } - - /* Call back to upper layer */ - ch->transferred += count; - - crit_enter(); - chn_intr(ch->pcm_ch); - crit_exit(); - - /* start next transfer */ - uaudio_chan_rtransfer(ch); -} - -static usbd_status -uaudio_set_speed(struct uaudio_softc *sc, int endpt, u_int speed) -{ - usb_device_request_t req; - uint8_t data[3]; - - DPRINTFN(5,("uaudio_set_speed: endpt=%d speed=%u\n", endpt, speed)); - req.bmRequestType = UT_WRITE_CLASS_ENDPOINT; - req.bRequest = SET_CUR; - USETW2(req.wValue, SAMPLING_FREQ_CONTROL, 0); - USETW(req.wIndex, endpt); - USETW(req.wLength, 3); - data[0] = speed; - data[1] = speed >> 8; - data[2] = speed >> 16; - - return usbd_do_request(sc->sc_udev, &req, data); -} - - -/************************************************************/ -int -uaudio_init_params(struct uaudio_softc *sc, struct chan *ch, int mode) -{ - int i, j, enc; - int samples_per_frame, sample_size; - - if ((sc->sc_playchan.pipe != NULL) || (sc->sc_recchan.pipe != NULL)) - return (-1); - - switch(ch->format & 0x000FFFFF) { - case AFMT_U8: - enc = AUDIO_ENCODING_ULINEAR_LE; - ch->precision = 8; - break; - case AFMT_S8: - enc = AUDIO_ENCODING_SLINEAR_LE; - ch->precision = 8; - break; - case AFMT_A_LAW: /* ? */ - enc = AUDIO_ENCODING_ALAW; - ch->precision = 8; - break; - case AFMT_MU_LAW: /* ? */ - enc = AUDIO_ENCODING_ULAW; - ch->precision = 8; - break; - case AFMT_S16_LE: - enc = AUDIO_ENCODING_SLINEAR_LE; - ch->precision = 16; - break; - case AFMT_S16_BE: - enc = AUDIO_ENCODING_SLINEAR_BE; - ch->precision = 16; - break; - case AFMT_U16_LE: - enc = AUDIO_ENCODING_ULINEAR_LE; - ch->precision = 16; - break; - case AFMT_U16_BE: - enc = AUDIO_ENCODING_ULINEAR_BE; - ch->precision = 16; - break; - case AFMT_S24_LE: - enc = AUDIO_ENCODING_SLINEAR_LE; - ch->precision = 24; - break; - case AFMT_S24_BE: - enc = AUDIO_ENCODING_SLINEAR_BE; - ch->precision = 24; - break; - case AFMT_U24_LE: - enc = AUDIO_ENCODING_ULINEAR_LE; - ch->precision = 24; - break; - case AFMT_U24_BE: - enc = AUDIO_ENCODING_ULINEAR_BE; - ch->precision = 24; - break; - case AFMT_S32_LE: - enc = AUDIO_ENCODING_SLINEAR_LE; - ch->precision = 32; - break; - case AFMT_S32_BE: - enc = AUDIO_ENCODING_SLINEAR_BE; - ch->precision = 32; - break; - case AFMT_U32_LE: - enc = AUDIO_ENCODING_ULINEAR_LE; - ch->precision = 32; - break; - case AFMT_U32_BE: - enc = AUDIO_ENCODING_ULINEAR_BE; - ch->precision = 32; - break; - default: - enc = 0; - ch->precision = 16; - kprintf("Unknown format %x\n", ch->format); - } - - if (ch->format & AFMT_STEREO) { - ch->channels = 2; - } else { - ch->channels = 1; - } - -/* for (mode = ...... */ - for (i = 0; i < sc->sc_nalts; i++) { - const struct usb_audio_streaming_type1_descriptor *a1d = - sc->sc_alts[i].asf1desc; - if (ch->channels == a1d->bNrChannels && - ch->precision == a1d->bBitResolution && -#if 0 - enc == sc->sc_alts[i].encoding) { -#else - enc == sc->sc_alts[i].encoding && - (mode == AUMODE_PLAY ? UE_DIR_OUT : UE_DIR_IN) == - UE_GET_DIR(sc->sc_alts[i].edesc->bEndpointAddress)) { -#endif - if (a1d->bSamFreqType == UA_SAMP_CONTNUOUS) { - DPRINTFN(2,("uaudio_set_params: cont %d-%d\n", - UA_SAMP_LO(a1d), UA_SAMP_HI(a1d))); - if (UA_SAMP_LO(a1d) <= ch->sample_rate && - ch->sample_rate <= UA_SAMP_HI(a1d)) { - if (mode == AUMODE_PLAY) - sc->sc_playchan.altidx = i; - else - sc->sc_recchan.altidx = i; - goto found; - } - } else { - for (j = 0; j < a1d->bSamFreqType; j++) { - DPRINTFN(2,("uaudio_set_params: disc #" - "%d: %d\n", j, UA_GETSAMP(a1d, j))); - /* XXX allow for some slack */ - if (UA_GETSAMP(a1d, j) == - ch->sample_rate) { - if (mode == AUMODE_PLAY) - sc->sc_playchan.altidx = i; - else - sc->sc_recchan.altidx = i; - goto found; - } - } - } - } - } - /* return (EINVAL); */ - if (mode == AUMODE_PLAY) - kprintf("uaudio: This device can't play in rate=%d.\n", ch->sample_rate); - else - kprintf("uaudio: This device can't record in rate=%d.\n", ch->sample_rate); - return (-1); - - found: -#if 0 /* XXX */ - p->sw_code = swcode; - p->factor = factor; - if (usemode == mode) - sc->sc_curaltidx = i; -#endif -/* } */ - - sample_size = ch->precision * ch->channels / 8; - samples_per_frame = ch->sample_rate / USB_FRAMES_PER_SECOND; - ch->fraction = ch->sample_rate % USB_FRAMES_PER_SECOND; - ch->sample_size = sample_size; - ch->bytes_per_frame = samples_per_frame * sample_size; - ch->residue = 0; - - ch->cur = ch->start; - ch->transferred = 0; - ch->curchanbuf = 0; - return (0); -} - -struct uaudio_conversion { - uint8_t uaudio_fmt; - uint8_t uaudio_prec; - uint32_t freebsd_fmt; -}; - -const struct uaudio_conversion const accepted_conversion[] = { - {AUDIO_ENCODING_ULINEAR_LE, 8, AFMT_U8}, - {AUDIO_ENCODING_ULINEAR_LE, 16, AFMT_U16_LE}, - {AUDIO_ENCODING_ULINEAR_LE, 24, AFMT_U24_LE}, - {AUDIO_ENCODING_ULINEAR_LE, 32, AFMT_U32_LE}, - {AUDIO_ENCODING_ULINEAR_BE, 16, AFMT_U16_BE}, - {AUDIO_ENCODING_ULINEAR_BE, 24, AFMT_U24_BE}, - {AUDIO_ENCODING_ULINEAR_BE, 32, AFMT_U32_BE}, - {AUDIO_ENCODING_SLINEAR_LE, 8, AFMT_S8}, - {AUDIO_ENCODING_SLINEAR_LE, 16, AFMT_S16_LE}, - {AUDIO_ENCODING_SLINEAR_LE, 24, AFMT_S24_LE}, - {AUDIO_ENCODING_SLINEAR_LE, 32, AFMT_S32_LE}, - {AUDIO_ENCODING_SLINEAR_BE, 16, AFMT_S16_BE}, - {AUDIO_ENCODING_SLINEAR_BE, 24, AFMT_S24_BE}, - {AUDIO_ENCODING_SLINEAR_BE, 32, AFMT_S32_BE}, - {AUDIO_ENCODING_ALAW, 8, AFMT_A_LAW}, - {AUDIO_ENCODING_ULAW, 8, AFMT_MU_LAW}, - {0,0,0} -}; - -unsigned -uaudio_query_formats(device_t dev, int reqdir, unsigned maxfmt, struct pcmchan_caps *cap) -{ - struct uaudio_softc *sc; - const struct usb_audio_streaming_type1_descriptor *asf1d; - const struct uaudio_conversion *iterator; - unsigned fmtcount, foundcount; - u_int32_t fmt; - uint8_t format, numchan, subframesize, prec, dir, iscontinuous; - int freq, freq_min, freq_max; - char *numchannel_descr; - char freq_descr[64]; - int i,r; - - sc = device_get_softc(dev); - if (sc == NULL) - return 0; - - cap->minspeed = cap->maxspeed = 0; - foundcount = fmtcount = 0; - - for (i = 0; i < sc->sc_nalts; i++) { - dir = UE_GET_DIR(sc->sc_alts[i].edesc->bEndpointAddress); - - if ((dir == UE_DIR_OUT) != (reqdir == PCMDIR_PLAY)) - continue; - - asf1d = sc->sc_alts[i].asf1desc; - format = sc->sc_alts[i].encoding; - - numchan = asf1d->bNrChannels; - subframesize = asf1d->bSubFrameSize; - prec = asf1d->bBitResolution; /* precision */ - iscontinuous = asf1d->bSamFreqType == UA_SAMP_CONTNUOUS; - - if (iscontinuous) - ksnprintf(freq_descr, sizeof(freq_descr), "continuous min %d max %d", UA_SAMP_LO(asf1d), UA_SAMP_HI(asf1d)); - else - ksnprintf(freq_descr, sizeof(freq_descr), "fixed frequency (%d listed formats)", asf1d->bSamFreqType); - - if (numchan == 1) - numchannel_descr = " (mono)"; - else if (numchan == 2) - numchannel_descr = " (stereo)"; - else - numchannel_descr = ""; - - if (bootverbose) { - device_printf(dev, "uaudio_query_formats: found a native %s channel%s %s %dbit %dbytes/subframe X %d channels = %d bytes per sample\n", - (dir==UE_DIR_OUT)?"playback":"record", - numchannel_descr, freq_descr, - prec, subframesize, numchan, subframesize*numchan); - } - /* - * Now start rejecting the ones that don't map to FreeBSD - */ - - if (numchan != 1 && numchan != 2) - continue; - - for (iterator = accepted_conversion ; iterator->uaudio_fmt != 0 ; iterator++) - if (iterator->uaudio_fmt == format && iterator->uaudio_prec == prec) - break; - - if (iterator->uaudio_fmt == 0) - continue; - - fmt = iterator->freebsd_fmt; - - if (numchan == 2) - fmt |= AFMT_STEREO; - - foundcount++; - - if (fmtcount >= maxfmt) - continue; - - cap->fmtlist[fmtcount++] = fmt; - - if (iscontinuous) { - freq_min = UA_SAMP_LO(asf1d); - freq_max = UA_SAMP_HI(asf1d); - - if (cap->minspeed == 0 || freq_min < cap->minspeed) - cap->minspeed = freq_min; - if (cap->maxspeed == 0) - cap->maxspeed = cap->minspeed; - if (freq_max > cap->maxspeed) - cap->maxspeed = freq_max; - } else { - for (r = 0; r < asf1d->bSamFreqType; r++) { - freq = UA_GETSAMP(asf1d, r); - if (cap->minspeed == 0 || freq < cap->minspeed) - cap->minspeed = freq; - if (cap->maxspeed == 0) - cap->maxspeed = cap->minspeed; - if (freq > cap->maxspeed) - cap->maxspeed = freq; - } - } - } - cap->fmtlist[fmtcount] = 0; - return foundcount; -} - -void -uaudio_chan_set_param_pcm_dma_buff(device_t dev, u_char *start, u_char *end, - struct pcm_channel *pc, int dir) -{ - struct uaudio_softc *sc; - struct chan *ch; - - sc = device_get_softc(dev); -#ifndef NO_RECORDING - if (dir == PCMDIR_PLAY) - ch = &sc->sc_playchan; - else - ch = &sc->sc_recchan; -#else - ch = &sc->sc_playchan; -#endif - - ch->start = start; - ch->end = end; - - ch->pcm_ch = pc; - - return; -} - -void -uaudio_chan_set_param_blocksize(device_t dev, u_int32_t blocksize, int dir) -{ - struct uaudio_softc *sc; - struct chan *ch; - - sc = device_get_softc(dev); -#ifndef NO_RECORDING - if (dir == PCMDIR_PLAY) - ch = &sc->sc_playchan; - else - ch = &sc->sc_recchan; -#else - ch = &sc->sc_playchan; -#endif - - ch->blksize = blocksize; - - return; -} - -int -uaudio_chan_set_param_speed(device_t dev, u_int32_t speed, int reqdir) -{ - const struct uaudio_conversion *iterator; - struct uaudio_softc *sc; - struct chan *ch; - int i, r, score, hiscore, bestspeed; - - sc = device_get_softc(dev); -#ifndef NO_RECORDING - if (reqdir == PCMDIR_PLAY) - ch = &sc->sc_playchan; - else - ch = &sc->sc_recchan; -#else - ch = &sc->sc_playchan; -#endif - /* - * We are successful if we find an endpoint that matches our selected format and it - * supports the requested speed. - */ - hiscore = 0; - bestspeed = 1; - for (i = 0; i < sc->sc_nalts; i++) { - int dir = UE_GET_DIR(sc->sc_alts[i].edesc->bEndpointAddress); - int format = sc->sc_alts[i].encoding; - const struct usb_audio_streaming_type1_descriptor *asf1d = sc->sc_alts[i].asf1desc; - int iscontinuous = asf1d->bSamFreqType == UA_SAMP_CONTNUOUS; - - if ((dir == UE_DIR_OUT) != (reqdir == PCMDIR_PLAY)) - continue; - - for (iterator = accepted_conversion ; iterator->uaudio_fmt != 0 ; iterator++) - if (iterator->uaudio_fmt != format || iterator->freebsd_fmt != (ch->format&0xfffffff)) - continue; - if (iscontinuous) { - if (speed >= UA_SAMP_LO(asf1d) && speed <= UA_SAMP_HI(asf1d)) { - ch->sample_rate = speed; - return speed; - } else if (speed < UA_SAMP_LO(asf1d)) { - score = 0xfff * speed / UA_SAMP_LO(asf1d); - if (score > hiscore) { - bestspeed = UA_SAMP_LO(asf1d); - hiscore = score; - } - } else if (speed < UA_SAMP_HI(asf1d)) { - score = 0xfff * UA_SAMP_HI(asf1d) / speed; - if (score > hiscore) { - bestspeed = UA_SAMP_HI(asf1d); - hiscore = score; - } - } - continue; - } - for (r = 0; r < asf1d->bSamFreqType; r++) { - if (speed == UA_GETSAMP(asf1d, r)) { - ch->sample_rate = speed; - return speed; - } - if (speed > UA_GETSAMP(asf1d, r)) - score = 0xfff * UA_GETSAMP(asf1d, r) / speed; - else - score = 0xfff * speed / UA_GETSAMP(asf1d, r); - if (score > hiscore) { - bestspeed = UA_GETSAMP(asf1d, r); - hiscore = score; - } - } - } - if (bestspeed != 1) { - ch->sample_rate = bestspeed; - return bestspeed; - } - - return 0; -} - -int -uaudio_chan_getptr(device_t dev, int dir) -{ - struct uaudio_softc *sc; - struct chan *ch; - int ptr; - - sc = device_get_softc(dev); -#ifndef NO_RECORDING - if (dir == PCMDIR_PLAY) - ch = &sc->sc_playchan; - else - ch = &sc->sc_recchan; -#else - ch = &sc->sc_playchan; -#endif - - ptr = ch->cur - ch->start; - - return ptr; -} - -void -uaudio_chan_set_param_format(device_t dev, u_int32_t format, int dir) -{ - struct uaudio_softc *sc; - struct chan *ch; - - sc = device_get_softc(dev); -#ifndef NO_RECORDING - if (dir == PCMDIR_PLAY) - ch = &sc->sc_playchan; - else - ch = &sc->sc_recchan; -#else - ch = &sc->sc_playchan; -#endif - - ch->format = format; - - return; -} - -int -uaudio_halt_out_dma(device_t dev) -{ - struct uaudio_softc *sc; - - sc = device_get_softc(dev); - - DPRINTF(("uaudio_halt_out_dma: enter\n")); - if (sc->sc_playchan.pipe != NULL) { - uaudio_chan_close(sc, &sc->sc_playchan); - sc->sc_playchan.pipe = 0; - uaudio_chan_free_buffers(sc, &sc->sc_playchan); - } - return (0); -} - -int -uaudio_halt_in_dma(device_t dev) -{ - struct uaudio_softc *sc; - - sc = device_get_softc(dev); - - if (sc->sc_dying) - return (EIO); - - DPRINTF(("uaudio_halt_in_dma: enter\n")); - if (sc->sc_recchan.pipe != NULL) { - uaudio_chan_close(sc, &sc->sc_recchan); - sc->sc_recchan.pipe = NULL; - uaudio_chan_free_buffers(sc, &sc->sc_recchan); -/* sc->sc_recchan.intr = NULL; */ - } - return (0); -} - -int -uaudio_trigger_input(device_t dev) -{ - struct uaudio_softc *sc; - struct chan *ch; - usbd_status err; - int i; - - sc = device_get_softc(dev); - ch = &sc->sc_recchan; - - if (sc->sc_dying) - return (EIO); - -/* uaudio_chan_set_param(ch, start, end, blksize) */ - if (uaudio_init_params(sc, ch, AUMODE_RECORD)) - return (EIO); - - err = uaudio_chan_alloc_buffers(sc, ch); - if (err) - return (EIO); - - err = uaudio_chan_open(sc, ch); - if (err) { - uaudio_chan_free_buffers(sc, ch); - return (EIO); - } - -/* ch->intr = intr; - ch->arg = arg; */ - - crit_enter(); - for (i = 0; i < UAUDIO_NCHANBUFS-1; i++) /* XXX -1 shouldn't be needed */ - uaudio_chan_rtransfer(ch); - crit_exit(); - - return (0); -} - -int -uaudio_trigger_output(device_t dev) -{ - struct uaudio_softc *sc; - struct chan *ch; - usbd_status err; - int i; - - sc = device_get_softc(dev); - ch = &sc->sc_playchan; - - if (sc->sc_dying) - return (EIO); - - if (uaudio_init_params(sc, ch, AUMODE_PLAY)) - return (EIO); - - err = uaudio_chan_alloc_buffers(sc, ch); - if (err) - return (EIO); - - err = uaudio_chan_open(sc, ch); - if (err) { - uaudio_chan_free_buffers(sc, ch); - return (EIO); - } - - crit_enter(); - for (i = 0; i < UAUDIO_NCHANBUFS-1; i++) /* XXX */ - uaudio_chan_ptransfer(ch); - crit_exit(); - - return (0); -} - -u_int32_t -uaudio_query_mix_info(device_t dev) -{ - int i; - u_int32_t mask = 0; - struct uaudio_softc *sc; - struct mixerctl *mc; - - sc = device_get_softc(dev); - for (i=0; i < sc->sc_nctls; i++) { - mc = &sc->sc_ctls[i]; - if (mc->ctl != SOUND_MIXER_NRDEVICES) { - /* Set device mask bits. - See /usr/include/machine/soundcard.h */ - mask |= (1 << mc->ctl); - } - } - return mask; -} - -u_int32_t -uaudio_query_recsrc_info(device_t dev) -{ - int i, rec_selector_id; - u_int32_t mask = 0; - struct uaudio_softc *sc; - struct mixerctl *mc; - - sc = device_get_softc(dev); - rec_selector_id = -1; - for (i=0; i < sc->sc_nctls; i++) { - mc = &sc->sc_ctls[i]; - if (mc->ctl == SOUND_MIXER_NRDEVICES && - mc->type == MIX_SELECTOR && mc->class == UAC_RECORD) { - if (rec_selector_id == -1) { - rec_selector_id = i; - } else { - kprintf("There are many selectors. Can't recognize which selector is a record source selector.\n"); - return mask; - } - } - } - if (rec_selector_id == -1) - return mask; - mc = &sc->sc_ctls[rec_selector_id]; - for (i = mc->minval; i <= mc->maxval; i++) { - if (mc->slctrtype[i - 1] == SOUND_MIXER_NRDEVICES) - continue; - mask |= 1 << mc->slctrtype[i - 1]; - } - return mask; -} - -void -uaudio_mixer_set(device_t dev, unsigned type, unsigned left, unsigned right) -{ - int i; - struct uaudio_softc *sc; - struct mixerctl *mc; - - sc = device_get_softc(dev); - for (i=0; i < sc->sc_nctls; i++) { - mc = &sc->sc_ctls[i]; - if (mc->ctl == type) { - if (mc->nchan == 2) { - /* set Right */ - uaudio_ctl_set(sc, SET_CUR, mc, 1, (int)(right*255)/100); - } - /* set Left or Mono */ - uaudio_ctl_set(sc, SET_CUR, mc, 0, (int)(left*255)/100); - } - } - return; -} - -u_int32_t -uaudio_mixer_setrecsrc(device_t dev, u_int32_t src) -{ - int i, rec_selector_id; - struct uaudio_softc *sc; - struct mixerctl *mc; - - sc = device_get_softc(dev); - rec_selector_id = -1; - for (i=0; i < sc->sc_nctls; i++) { - mc = &sc->sc_ctls[i]; - if (mc->ctl == SOUND_MIXER_NRDEVICES && - mc->type == MIX_SELECTOR && mc->class == UAC_RECORD) { - if (rec_selector_id == -1) { - rec_selector_id = i; - } else { - return src; /* Can't recognize which selector is record source selector */ - } - } - } - if (rec_selector_id == -1) - return src; - mc = &sc->sc_ctls[rec_selector_id]; - for (i = mc->minval; i <= mc->maxval; i++) { - if (src != (1 << mc->slctrtype[i - 1])) - continue; - uaudio_ctl_set(sc, SET_CUR, mc, 0, i); - return (1 << mc->slctrtype[i - 1]); - } - uaudio_ctl_set(sc, SET_CUR, mc, 0, mc->minval); - return (1 << mc->slctrtype[mc->minval - 1]); -} - -static int -uaudio_sndstat_prepare_pcm(struct sbuf *s, device_t dev, int verbose) -{ - struct snddev_info *d; - struct snddev_channel *sce; - struct pcm_channel *c; - struct pcm_feeder *f; - int pc, rc, vc; - device_t pa_dev = device_get_parent(dev); - struct uaudio_softc *sc = device_get_softc(pa_dev); - - if (verbose < 1) - return 0; - - d = device_get_softc(dev); - if (!d) - return ENXIO; - - snd_mtxlock(d->lock); - if (SLIST_EMPTY(&d->channels)) { - sbuf_printf(s, " (mixer only)"); - snd_mtxunlock(d->lock); - return 0; - } - pc = rc = vc = 0; - SLIST_FOREACH(sce, &d->channels, link) { - c = sce->channel; - if (c->direction == PCMDIR_PLAY) { - if (c->flags & CHN_F_VIRTUAL) - vc++; - else - pc++; - } else - rc++; - } - sbuf_printf(s, " (%dp/%dr/%dv channels%s%s)", - d->playcount, d->reccount, d->vchancount, - (d->flags & SD_F_SIMPLEX)? "" : " duplex", -#ifdef USING_DEVFS - (device_get_unit(dev) == snd_unit)? " default" : "" -#else - "" -#endif - ); - - if (sc->uaudio_sndstat_flag != 0) { - sbuf_cat(s, sbuf_data(&(sc->uaudio_sndstat))); - } - - if (verbose <= 1) { - snd_mtxunlock(d->lock); - return 0; - } - - SLIST_FOREACH(sce, &d->channels, link) { - c = sce->channel; - sbuf_printf(s, "\n\t"); - - KASSERT(c->bufhard != NULL && c->bufsoft != NULL, - ("hosed pcm channel setup")); - - /* it would be better to indent child channels */ - sbuf_printf(s, "%s[%s]: ", c->parentchannel? c->parentchannel->name : "", c->name); - sbuf_printf(s, "spd %d", c->speed); - if (c->speed != sndbuf_getspd(c->bufhard)) - sbuf_printf(s, "/%d", sndbuf_getspd(c->bufhard)); - sbuf_printf(s, ", fmt 0x%08x", c->format); - if (c->format != sndbuf_getfmt(c->bufhard)) - sbuf_printf(s, "/0x%08x", sndbuf_getfmt(c->bufhard)); - sbuf_printf(s, ", flags 0x%08x, 0x%08x", c->flags, c->feederflags); - if (c->pid != -1) - sbuf_printf(s, ", pid %d", c->pid); - sbuf_printf(s, "\n\t"); - - sbuf_printf(s, "interrupts %d, ", c->interrupts); - if (c->direction == PCMDIR_REC) - sbuf_printf(s, "overruns %d, hfree %d, sfree %d", - c->xruns, sndbuf_getfree(c->bufhard), sndbuf_getfree(c->bufsoft)); - else - sbuf_printf(s, "underruns %d, ready %d", - c->xruns, sndbuf_getready(c->bufsoft)); - sbuf_printf(s, "\n\t"); - - sbuf_printf(s, "{%s}", (c->direction == PCMDIR_REC)? "hardware" : "userland"); - sbuf_printf(s, " -> "); - f = c->feeder; - while (f->source != NULL) - f = f->source; - while (f != NULL) { - sbuf_printf(s, "%s", f->class->name); - if (f->desc->type == FEEDER_FMT) - sbuf_printf(s, "(0x%08x -> 0x%08x)", f->desc->in, f->desc->out); - if (f->desc->type == FEEDER_RATE) - sbuf_printf(s, "(%d -> %d)", FEEDER_GET(f, FEEDRATE_SRC), FEEDER_GET(f, FEEDRATE_DST)); - if (f->desc->type == FEEDER_ROOT || f->desc->type == FEEDER_MIXER) - sbuf_printf(s, "(0x%08x)", f->desc->out); - sbuf_printf(s, " -> "); - f = f->parent; - } - sbuf_printf(s, "{%s}", (c->direction == PCMDIR_REC)? "userland" : "hardware"); - } - snd_mtxunlock(d->lock); - - return 0; -} - -void -uaudio_sndstat_register(device_t dev) -{ - struct snddev_info *d = device_get_softc(dev); - sndstat_register(dev, d->status, uaudio_sndstat_prepare_pcm); -} - -static int -audio_attach_mi(device_t dev) -{ - device_t child; - struct sndcard_func *func; - - /* Attach the children. */ - /* PCM Audio */ - func = kmalloc(sizeof(struct sndcard_func), M_DEVBUF, M_WAITOK | M_ZERO); - func->func = SCF_PCM; - child = device_add_child(dev, "pcm", -1); - device_set_ivars(child, func); - - bus_generic_attach(dev); - - return 0; /* XXXXX */ -} - -DRIVER_MODULE(uaudio, uhub, uaudio_driver, uaudio_devclass, usbd_driver_load, NULL); -MODULE_VERSION(uaudio, 1); - diff --git a/sys/dev/sound/usb/uaudio.h b/sys/dev/sound/usb/uaudio.h deleted file mode 100644 index 6cb05c2882..0000000000 --- a/sys/dev/sound/usb/uaudio.h +++ /dev/null @@ -1,54 +0,0 @@ -/* $FreeBSD: src/sys/dev/sound/usb/uaudio.h,v 1.6.2.1 2005/12/30 19:55:54 netchild Exp $ */ -/* $DragonFly: src/sys/dev/sound/usb/uaudio.h,v 1.3 2007/01/04 21:47:03 corecode Exp $ */ - -/*- - * Copyright (c) 2000-2002 Hiroyuki Aizu - * - * 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. - */ - -#if 0 -#define NO_RECORDING /* XXX: some routines missing from uaudio.c */ -#endif - -/* Defined in uaudio.c, used in uaudio_pcm,c */ - -void uaudio_chan_set_param_pcm_dma_buff(device_t dev, u_char *start, - u_char *end, struct pcm_channel *pc, int dir); -int uaudio_trigger_output(device_t dev); -int uaudio_halt_out_dma(device_t dev); -#ifndef NO_RECORDING -int uaudio_trigger_input(device_t dev); -int uaudio_halt_in_dma(device_t dev); -#endif -void uaudio_chan_set_param(device_t, u_char *, u_char *); -void uaudio_chan_set_param_blocksize(device_t dev, u_int32_t blocksize, int dir); -int uaudio_chan_set_param_speed(device_t dev, u_int32_t speed, int reqdir); -void uaudio_chan_set_param_format(device_t dev, u_int32_t format,int dir); -int uaudio_chan_getptr(device_t dev, int); -void uaudio_mixer_set(device_t dev, unsigned type, unsigned left, - unsigned right); -u_int32_t uaudio_mixer_setrecsrc(device_t dev, u_int32_t src); -u_int32_t uaudio_query_mix_info(device_t dev); -u_int32_t uaudio_query_recsrc_info(device_t dev); -unsigned uaudio_query_formats(device_t dev, int dir, unsigned maxfmt, struct pcmchan_caps *fmt); -void uaudio_sndstat_register(device_t dev); diff --git a/sys/dev/sound/usb/uaudio_pcm.c b/sys/dev/sound/usb/uaudio_pcm.c deleted file mode 100644 index 7bf8e79fa1..0000000000 --- a/sys/dev/sound/usb/uaudio_pcm.c +++ /dev/null @@ -1,417 +0,0 @@ -/* $FreeBSD: src/sys/dev/sound/usb/uaudio_pcm.c,v 1.15.2.2 2007/05/13 20:53:40 ariff Exp $ */ - -/*- - * Copyright (c) 2000-2002 Hiroyuki Aizu - * - * 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 -#include -#include - -#include - -#include "mixer_if.h" - -struct ua_info; - -struct ua_chinfo { - struct ua_info *parent; - struct pcm_channel *channel; - struct snd_dbuf *buffer; - u_char *buf; - int dir, hwch; - u_int32_t fmt, spd, blksz; /* XXXXX */ -}; - -struct ua_info { - device_t sc_dev; - u_int32_t bufsz; - struct ua_chinfo pch, rch; -#define FORMAT_NUM 32 - u_int32_t ua_playfmt[FORMAT_NUM*2+1]; /* FORMAT_NUM format * (stereo or mono) + endptr */ - u_int32_t ua_recfmt[FORMAT_NUM*2+1]; /* FORMAT_NUM format * (stereo or mono) + endptr */ - struct pcmchan_caps ua_playcaps; - struct pcmchan_caps ua_reccaps; -}; - -#define UAUDIO_DEFAULT_BUFSZ 16*1024 - -/************************************************************/ -static void * -ua_chan_init(kobj_t obj, void *devinfo, struct snd_dbuf *b, struct pcm_channel *c, int dir) -{ - device_t pa_dev; - - struct ua_info *sc = devinfo; - struct ua_chinfo *ch = (dir == PCMDIR_PLAY)? &sc->pch : &sc->rch; - - ch->parent = sc; - ch->channel = c; - ch->buffer = b; - ch->dir = dir; - - pa_dev = device_get_parent(sc->sc_dev); - - ch->buf = kmalloc(sc->bufsz, M_DEVBUF, M_WAITOK); - if (sndbuf_setup(b, ch->buf, sc->bufsz) != 0) { - kfree(ch->buf, M_DEVBUF); - return NULL; - } - uaudio_chan_set_param_pcm_dma_buff(pa_dev, ch->buf, ch->buf+sc->bufsz, ch->channel, dir); - if (bootverbose) - device_printf(pa_dev, "%s buf %p\n", (dir == PCMDIR_PLAY)? - "play" : "rec", sndbuf_getbuf(ch->buffer)); - - ch->dir = dir; -#ifndef NO_RECORDING - ch->hwch = 1; - if (dir == PCMDIR_PLAY) - ch->hwch = 2; -#else - ch->hwch = 2; -#endif - - return ch; -} - -static int -ua_chan_free(kobj_t obj, void *data) -{ - struct ua_chinfo *ua = data; - - if (ua->buf != NULL) - kfree(ua->buf, M_DEVBUF); - return 0; -} - -static int -ua_chan_setformat(kobj_t obj, void *data, u_int32_t format) -{ - device_t pa_dev; - struct ua_info *ua; - - struct ua_chinfo *ch = data; - - /* - * At this point, no need to query as we shouldn't select an unsorted format - */ - ua = ch->parent; - pa_dev = device_get_parent(ua->sc_dev); - uaudio_chan_set_param_format(pa_dev, format, ch->dir); - - ch->fmt = format; - return 0; -} - -static int -ua_chan_setspeed(kobj_t obj, void *data, u_int32_t speed) -{ - struct ua_chinfo *ch; - device_t pa_dev; - int bestspeed; - - ch = data; - pa_dev = device_get_parent(ch->parent->sc_dev); - - if ((bestspeed = uaudio_chan_set_param_speed(pa_dev, speed, ch->dir))) - ch->spd = bestspeed; - - return ch->spd; -} - -static int -ua_chan_setblocksize(kobj_t obj, void *data, u_int32_t blocksize) -{ - device_t pa_dev; - struct ua_chinfo *ch = data; - struct ua_info *ua = ch->parent; - - if (blocksize) { - RANGE(blocksize, 128, ua->bufsz / 2); - if (sndbuf_resize(ch->buffer, ua->bufsz/blocksize, blocksize) != 0) { - ch->blksz = blocksize; - } - } - pa_dev = device_get_parent(ua->sc_dev); - uaudio_chan_set_param_blocksize(pa_dev, blocksize, ch->dir); - - return ch->blksz; -} - -static int -ua_chan_trigger(kobj_t obj, void *data, int go) -{ - device_t pa_dev; - struct ua_info *ua; - struct ua_chinfo *ch = data; - - if (go == PCMTRIG_EMLDMAWR || go == PCMTRIG_EMLDMARD) - return 0; - - ua = ch->parent; - pa_dev = device_get_parent(ua->sc_dev); - - /* XXXXX */ - if (ch->dir == PCMDIR_PLAY) { - if (go == PCMTRIG_START) { - uaudio_trigger_output(pa_dev); - } else { - uaudio_halt_out_dma(pa_dev); - } - } else { -#ifndef NO_RECORDING - if (go == PCMTRIG_START) - uaudio_trigger_input(pa_dev); - else - uaudio_halt_in_dma(pa_dev); -#endif - } - - return 0; -} - -static int -ua_chan_getptr(kobj_t obj, void *data) -{ - device_t pa_dev; - struct ua_info *ua; - struct ua_chinfo *ch = data; - - ua = ch->parent; - pa_dev = device_get_parent(ua->sc_dev); - - return uaudio_chan_getptr(pa_dev, ch->dir); -} - -static struct pcmchan_caps * -ua_chan_getcaps(kobj_t obj, void *data) -{ - struct ua_chinfo *ch; - - ch = data; - return (ch->dir == PCMDIR_PLAY) ? &(ch->parent->ua_playcaps) : &(ch->parent->ua_reccaps); -} - -static kobj_method_t ua_chan_methods[] = { - KOBJMETHOD(channel_init, ua_chan_init), - KOBJMETHOD(channel_free, ua_chan_free), - KOBJMETHOD(channel_setformat, ua_chan_setformat), - KOBJMETHOD(channel_setspeed, ua_chan_setspeed), - KOBJMETHOD(channel_setblocksize, ua_chan_setblocksize), - KOBJMETHOD(channel_trigger, ua_chan_trigger), - KOBJMETHOD(channel_getptr, ua_chan_getptr), - KOBJMETHOD(channel_getcaps, ua_chan_getcaps), - KOBJMETHOD_END -}; - -CHANNEL_DECLARE(ua_chan); - -/************************************************************/ -static int -ua_mixer_init(struct snd_mixer *m) -{ - u_int32_t mask; - device_t pa_dev; - struct snddev_info *d; - struct ua_info *ua = mix_getdevinfo(m); - - pa_dev = device_get_parent(ua->sc_dev); - d = device_get_softc(ua->sc_dev); - - mask = uaudio_query_mix_info(pa_dev); - if (d != NULL) { - if (!(mask & SOUND_MASK_PCM)) { - /* - * Emulate missing pcm mixer controller - * through FEEDER_VOLUME - */ - d->flags |= SD_F_SOFTPCMVOL; - } - if (!(mask & SOUND_MASK_VOLUME)) { - mix_setparentchild(m, SOUND_MIXER_VOLUME, - SOUND_MASK_PCM); - mix_setrealdev(m, SOUND_MIXER_VOLUME, - SOUND_MIXER_NONE); - } - } - mix_setdevs(m, mask); - - mask = uaudio_query_recsrc_info(pa_dev); - mix_setrecdevs(m, mask); - - return 0; -} - -static int -ua_mixer_set(struct snd_mixer *m, unsigned type, unsigned left, unsigned right) -{ - device_t pa_dev; - struct ua_info *ua = mix_getdevinfo(m); - - pa_dev = device_get_parent(ua->sc_dev); - uaudio_mixer_set(pa_dev, type, left, right); - - return left | (right << 8); -} - -static int -ua_mixer_setrecsrc(struct snd_mixer *m, u_int32_t src) -{ - device_t pa_dev; - struct ua_info *ua = mix_getdevinfo(m); - - pa_dev = device_get_parent(ua->sc_dev); - return uaudio_mixer_setrecsrc(pa_dev, src); -} - -static kobj_method_t ua_mixer_methods[] = { - KOBJMETHOD(mixer_init, ua_mixer_init), - KOBJMETHOD(mixer_set, ua_mixer_set), - KOBJMETHOD(mixer_setrecsrc, ua_mixer_setrecsrc), - - KOBJMETHOD_END -}; -MIXER_DECLARE(ua_mixer); -/************************************************************/ - - -static int -ua_probe(device_t dev) -{ - char *s; - struct sndcard_func *func; - - /* The parent device has already been probed. */ - - func = device_get_ivars(dev); - if (func == NULL || func->func != SCF_PCM) - return (ENXIO); - - s = "USB Audio"; - - device_set_desc(dev, s); - return BUS_PROBE_DEFAULT; -} - -static int -ua_attach(device_t dev) -{ - struct ua_info *ua; - char status[SND_STATUSLEN]; - device_t pa_dev; - u_int32_t nplay, nrec; - int i; - - ua = kmalloc(sizeof *ua, M_DEVBUF, M_ZERO | M_WAITOK); - - ua->sc_dev = dev; - - pa_dev = device_get_parent(dev); - - ua->bufsz = pcm_getbuffersize(dev, 4096, UAUDIO_DEFAULT_BUFSZ, 65536); - if (bootverbose) - device_printf(dev, "using a default buffer size of %jd\n", (intmax_t)ua->bufsz); - - if (mixer_init(dev, &ua_mixer_class, ua)) { - goto bad; - } - - ksnprintf(status, SND_STATUSLEN, "at ? %s", PCM_KLDSTRING(snd_uaudio)); - - ua->ua_playcaps.fmtlist = ua->ua_playfmt; - ua->ua_reccaps.fmtlist = ua->ua_recfmt; - nplay = uaudio_query_formats(pa_dev, PCMDIR_PLAY, FORMAT_NUM * 2, &ua->ua_playcaps); - nrec = uaudio_query_formats(pa_dev, PCMDIR_REC, FORMAT_NUM * 2, &ua->ua_reccaps); - - if (nplay > 1) - nplay = 1; - if (nrec > 1) - nrec = 1; - -#ifndef NO_RECORDING - if (pcm_register(dev, ua, nplay, nrec)) { -#else - if (pcm_register(dev, ua, nplay, 0)) { -#endif - goto bad; - } - - sndstat_unregister(dev); - uaudio_sndstat_register(dev); - - for (i = 0; i < nplay; i++) { - pcm_addchan(dev, PCMDIR_PLAY, &ua_chan_class, ua); - } -#ifndef NO_RECORDING - for (i = 0; i < nrec; i++) { - pcm_addchan(dev, PCMDIR_REC, &ua_chan_class, ua); - } -#endif - pcm_setstatus(dev, status); - - return 0; - -bad: kfree(ua, M_DEVBUF); - return ENXIO; -} - -static int -ua_detach(device_t dev) -{ - int r; - struct ua_info *sc; - - r = pcm_unregister(dev); - if (r) - return r; - - sc = pcm_getdevinfo(dev); - kfree(sc, M_DEVBUF); - - return 0; -} - -/************************************************************/ - -static device_method_t ua_pcm_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, ua_probe), - DEVMETHOD(device_attach, ua_attach), - DEVMETHOD(device_detach, ua_detach), - - DEVMETHOD_END -}; - -static driver_t ua_pcm_driver = { - "pcm", - ua_pcm_methods, - PCM_SOFTC_SIZE, -}; - - -DRIVER_MODULE(ua_pcm, uaudio, ua_pcm_driver, pcm_devclass, NULL, NULL); -MODULE_DEPEND(ua_pcm, uaudio, 1, 1, 1); -MODULE_DEPEND(ua_pcm, sound, SOUND_MINVER, SOUND_PREFVER, SOUND_MAXVER); -MODULE_VERSION(ua_pcm, 1); diff --git a/sys/dev/sound/usb/uaudioreg.h b/sys/dev/sound/usb/uaudioreg.h deleted file mode 100644 index 99af52db22..0000000000 --- a/sys/dev/sound/usb/uaudioreg.h +++ /dev/null @@ -1,405 +0,0 @@ -/* $NetBSD: uaudioreg.h,v 1.12 2004/11/05 19:08:29 kent Exp $ */ -/* $FreeBSD: src/sys/dev/sound/usb/uaudioreg.h,v 1.4 2005/01/06 01:43:22 imp Exp $ */ -/* $DragonFly: src/sys/dev/sound/usb/uaudioreg.h,v 1.3 2007/01/04 21:47:03 corecode Exp $ */ - -/*- - * Copyright (c) 1999 The NetBSD Foundation, Inc. - * All rights reserved. - * - * This code is derived from software contributed to The NetBSD Foundation - * by Lennart Augustsson (lennart@augustsson.net) at - * Carlstedt Research & Technology. - * - * 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. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the NetBSD - * Foundation, Inc. and its contributors. - * 4. Neither the name of The NetBSD Foundation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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. - */ - -#define UAUDIO_VERSION 0x100 - -#define UDESC_CS_CONFIG 0x22 -#define UDESC_CS_STRING 0x23 -#define UDESC_CS_INTERFACE 0x24 -#define UDESC_CS_ENDPOINT 0x25 - -#define UDESCSUB_AC_HEADER 1 -#define UDESCSUB_AC_INPUT 2 -#define UDESCSUB_AC_OUTPUT 3 -#define UDESCSUB_AC_MIXER 4 -#define UDESCSUB_AC_SELECTOR 5 -#define UDESCSUB_AC_FEATURE 6 -#define UDESCSUB_AC_PROCESSING 7 -#define UDESCSUB_AC_EXTENSION 8 - -/* The first fields are identical to usb_endpoint_descriptor_t */ -typedef struct { - uByte bLength; - uByte bDescriptorType; - uByte bEndpointAddress; - uByte bmAttributes; - uWord wMaxPacketSize; - uByte bInterval; - /* - * The following two entries are only used by the Audio Class. - * And according to the specs the Audio Class is the only one - * allowed to extend the endpoint descriptor. - * Who knows what goes on in the minds of the people in the USB - * standardization? :-( - */ - uByte bRefresh; - uByte bSynchAddress; -} UPACKED usb_endpoint_descriptor_audio_t; - -struct usb_audio_control_descriptor { - uByte bLength; - uByte bDescriptorType; - uByte bDescriptorSubtype; - uWord bcdADC; - uWord wTotalLength; - uByte bInCollection; - uByte baInterfaceNr[1]; -} UPACKED; - -struct usb_audio_streaming_interface_descriptor { - uByte bLength; - uByte bDescriptorType; - uByte bDescriptorSubtype; - uByte bTerminalLink; - uByte bDelay; - uWord wFormatTag; -} UPACKED; - -struct usb_audio_streaming_endpoint_descriptor { - uByte bLength; - uByte bDescriptorType; - uByte bDescriptorSubtype; - uByte bmAttributes; -#define UA_SED_FREQ_CONTROL 0x01 -#define UA_SED_PITCH_CONTROL 0x02 -#define UA_SED_MAXPACKETSONLY 0x80 - uByte bLockDelayUnits; - uWord wLockDelay; -} UPACKED; - -struct usb_audio_streaming_type1_descriptor { - uByte bLength; - uByte bDescriptorType; - uByte bDescriptorSubtype; - uByte bFormatType; - uByte bNrChannels; - uByte bSubFrameSize; - uByte bBitResolution; - uByte bSamFreqType; -#define UA_SAMP_CONTNUOUS 0 - uByte tSamFreq[3*2]; /* room for low and high */ -#define UA_GETSAMP(p, n) ((p)->tSamFreq[(n)*3+0] | ((p)->tSamFreq[(n)*3+1] << 8) | ((p)->tSamFreq[(n)*3+2] << 16)) -#define UA_SAMP_LO(p) UA_GETSAMP(p, 0) -#define UA_SAMP_HI(p) UA_GETSAMP(p, 1) -} UPACKED; - -struct usb_audio_cluster { - uByte bNrChannels; - uWord wChannelConfig; -#define UA_CHANNEL_LEFT 0x0001 -#define UA_CHANNEL_RIGHT 0x0002 -#define UA_CHANNEL_CENTER 0x0004 -#define UA_CHANNEL_LFE 0x0008 -#define UA_CHANNEL_L_SURROUND 0x0010 -#define UA_CHANNEL_R_SURROUND 0x0020 -#define UA_CHANNEL_L_CENTER 0x0040 -#define UA_CHANNEL_R_CENTER 0x0080 -#define UA_CHANNEL_SURROUND 0x0100 -#define UA_CHANNEL_L_SIDE 0x0200 -#define UA_CHANNEL_R_SIDE 0x0400 -#define UA_CHANNEL_TOP 0x0800 - uByte iChannelNames; -} UPACKED; - -/* Shared by all units and terminals */ -struct usb_audio_unit { - uByte bLength; - uByte bDescriptorType; - uByte bDescriptorSubtype; - uByte bUnitId; -}; - -/* UDESCSUB_AC_INPUT */ -struct usb_audio_input_terminal { - uByte bLength; - uByte bDescriptorType; - uByte bDescriptorSubtype; - uByte bTerminalId; - uWord wTerminalType; - uByte bAssocTerminal; - uByte bNrChannels; - uWord wChannelConfig; - uByte iChannelNames; - uByte iTerminal; -} UPACKED; - -/* UDESCSUB_AC_OUTPUT */ -struct usb_audio_output_terminal { - uByte bLength; - uByte bDescriptorType; - uByte bDescriptorSubtype; - uByte bTerminalId; - uWord wTerminalType; - uByte bAssocTerminal; - uByte bSourceId; - uByte iTerminal; -} UPACKED; - -/* UDESCSUB_AC_MIXER */ -struct usb_audio_mixer_unit { - uByte bLength; - uByte bDescriptorType; - uByte bDescriptorSubtype; - uByte bUnitId; - uByte bNrInPins; - uByte baSourceId[255]; /* [bNrInPins] */ - /* struct usb_audio_mixer_unit_1 */ -} UPACKED; -struct usb_audio_mixer_unit_1 { - uByte bNrChannels; - uWord wChannelConfig; - uByte iChannelNames; - uByte bmControls[255]; /* [bNrChannels] */ - /*uByte iMixer;*/ -} UPACKED; - -/* UDESCSUB_AC_SELECTOR */ -struct usb_audio_selector_unit { - uByte bLength; - uByte bDescriptorType; - uByte bDescriptorSubtype; - uByte bUnitId; - uByte bNrInPins; - uByte baSourceId[255]; /* [bNrInPins] */ - /* uByte iSelector; */ -} UPACKED; - -/* UDESCSUB_AC_FEATURE */ -struct usb_audio_feature_unit { - uByte bLength; - uByte bDescriptorType; - uByte bDescriptorSubtype; - uByte bUnitId; - uByte bSourceId; - uByte bControlSize; - uByte bmaControls[255]; /* size for more than enough */ - /* uByte iFeature; */ -} UPACKED; - -/* UDESCSUB_AC_PROCESSING */ -struct usb_audio_processing_unit { - uByte bLength; - uByte bDescriptorType; - uByte bDescriptorSubtype; - uByte bUnitId; - uWord wProcessType; - uByte bNrInPins; - uByte baSourceId[255]; /* [bNrInPins] */ - /* struct usb_audio_processing_unit_1 */ -} UPACKED; -struct usb_audio_processing_unit_1{ - uByte bNrChannels; - uWord wChannelConfig; - uByte iChannelNames; - uByte bControlSize; - uByte bmControls[255]; /* [bControlSize] */ -#define UA_PROC_ENABLE_MASK 1 -} UPACKED; - -struct usb_audio_processing_unit_updown { - uByte iProcessing; - uByte bNrModes; - uWord waModes[255]; /* [bNrModes] */ -} UPACKED; - -/* UDESCSUB_AC_EXTENSION */ -struct usb_audio_extension_unit { - uByte bLength; - uByte bDescriptorType; - uByte bDescriptorSubtype; - uByte bUnitId; - uWord wExtensionCode; - uByte bNrInPins; - uByte baSourceId[255]; /* [bNrInPins] */ - /* struct usb_audio_extension_unit_1 */ -} UPACKED; -struct usb_audio_extension_unit_1 { - uByte bNrChannels; - uWord wChannelConfig; - uByte iChannelNames; - uByte bControlSize; - uByte bmControls[255]; /* [bControlSize] */ -#define UA_EXT_ENABLE_MASK 1 -#define UA_EXT_ENABLE 1 - /*uByte iExtension;*/ -} UPACKED; - -/* USB terminal types */ -#define UAT_UNDEFINED 0x0100 -#define UAT_STREAM 0x0101 -#define UAT_VENDOR 0x01ff -/* input terminal types */ -#define UATI_UNDEFINED 0x0200 -#define UATI_MICROPHONE 0x0201 -#define UATI_DESKMICROPHONE 0x0202 -#define UATI_PERSONALMICROPHONE 0x0203 -#define UATI_OMNIMICROPHONE 0x0204 -#define UATI_MICROPHONEARRAY 0x0205 -#define UATI_PROCMICROPHONEARR 0x0206 -/* output terminal types */ -#define UATO_UNDEFINED 0x0300 -#define UATO_SPEAKER 0x0301 -#define UATO_HEADPHONES 0x0302 -#define UATO_DISPLAYAUDIO 0x0303 -#define UATO_DESKTOPSPEAKER 0x0304 -#define UATO_ROOMSPEAKER 0x0305 -#define UATO_COMMSPEAKER 0x0306 -#define UATO_SUBWOOFER 0x0307 -/* bidir terminal types */ -#define UATB_UNDEFINED 0x0400 -#define UATB_HANDSET 0x0401 -#define UATB_HEADSET 0x0402 -#define UATB_SPEAKERPHONE 0x0403 -#define UATB_SPEAKERPHONEESUP 0x0404 -#define UATB_SPEAKERPHONEECANC 0x0405 -/* telephony terminal types */ -#define UATT_UNDEFINED 0x0500 -#define UATT_PHONELINE 0x0501 -#define UATT_TELEPHONE 0x0502 -#define UATT_DOWNLINEPHONE 0x0503 -/* external terminal types */ -#define UATE_UNDEFINED 0x0600 -#define UATE_ANALOGCONN 0x0601 -#define UATE_DIGITALAUIFC 0x0602 -#define UATE_LINECONN 0x0603 -#define UATE_LEGACYCONN 0x0604 -#define UATE_SPDIF 0x0605 -#define UATE_1394DA 0x0606 -#define UATE_1394DV 0x0607 -/* embedded function terminal types */ -#define UATF_UNDEFINED 0x0700 -#define UATF_CALIBNOISE 0x0701 -#define UATF_EQUNOISE 0x0702 -#define UATF_CDPLAYER 0x0703 -#define UATF_DAT 0x0704 -#define UATF_DCC 0x0705 -#define UATF_MINIDISK 0x0706 -#define UATF_ANALOGTAPE 0x0707 -#define UATF_PHONOGRAPH 0x0708 -#define UATF_VCRAUDIO 0x0709 -#define UATF_VIDEODISCAUDIO 0x070a -#define UATF_DVDAUDIO 0x070b -#define UATF_TVTUNERAUDIO 0x070c -#define UATF_SATELLITE 0x070d -#define UATF_CABLETUNER 0x070e -#define UATF_DSS 0x070f -#define UATF_RADIORECV 0x0710 -#define UATF_RADIOXMIT 0x0711 -#define UATF_MULTITRACK 0x0712 -#define UATF_SYNTHESIZER 0x0713 - - -#define SET_CUR 0x01 -#define GET_CUR 0x81 -#define SET_MIN 0x02 -#define GET_MIN 0x82 -#define SET_MAX 0x03 -#define GET_MAX 0x83 -#define SET_RES 0x04 -#define GET_RES 0x84 -#define SET_MEM 0x05 -#define GET_MEM 0x85 -#define GET_STAT 0xff - -#define MUTE_CONTROL 0x01 -#define VOLUME_CONTROL 0x02 -#define BASS_CONTROL 0x03 -#define MID_CONTROL 0x04 -#define TREBLE_CONTROL 0x05 -#define GRAPHIC_EQUALIZER_CONTROL 0x06 -#define AGC_CONTROL 0x07 -#define DELAY_CONTROL 0x08 -#define BASS_BOOST_CONTROL 0x09 -#define LOUDNESS_CONTROL 0x0a - -#define FU_MASK(u) (1 << ((u)-1)) - -#define MASTER_CHAN 0 - -#define AS_GENERAL 1 -#define FORMAT_TYPE 2 -#define FORMAT_SPECIFIC 3 - -#define UA_FMT_PCM 1 -#define UA_FMT_PCM8 2 -#define UA_FMT_IEEE_FLOAT 3 -#define UA_FMT_ALAW 4 -#define UA_FMT_MULAW 5 -#define UA_FMT_MPEG 0x1001 -#define UA_FMT_AC3 0x1002 - -#define SAMPLING_FREQ_CONTROL 0x01 -#define PITCH_CONTROL 0x02 - -#define FORMAT_TYPE_UNDEFINED 0 -#define FORMAT_TYPE_I 1 -#define FORMAT_TYPE_II 2 -#define FORMAT_TYPE_III 3 - -#define UA_PROC_MASK(n) (1<< ((n)-1)) -#define PROCESS_UNDEFINED 0 -#define XX_ENABLE_CONTROL 1 -#define UPDOWNMIX_PROCESS 1 -#define UD_ENABLE_CONTROL 1 -#define UD_MODE_SELECT_CONTROL 2 -#define DOLBY_PROLOGIC_PROCESS 2 -#define DP_ENABLE_CONTROL 1 -#define DP_MODE_SELECT_CONTROL 2 -#define P3D_STEREO_EXTENDER_PROCESS 3 -#define P3D_ENABLE_CONTROL 1 -#define P3D_SPACIOUSNESS_CONTROL 2 -#define REVERBATION_PROCESS 4 -#define RV_ENABLE_CONTROL 1 -#define RV_LEVEL_CONTROL 2 -#define RV_TIME_CONTROL 3 -#define RV_FEEDBACK_CONTROL 4 -#define CHORUS_PROCESS 5 -#define CH_ENABLE_CONTROL 1 -#define CH_LEVEL_CONTROL 2 -#define CH_RATE_CONTROL 3 -#define CH_DEPTH_CONTROL 4 -#define DYN_RANGE_COMP_PROCESS 6 -#define DR_ENABLE_CONTROL 1 -#define DR_COMPRESSION_RATE_CONTROL 2 -#define DR_MAXAMPL_CONTROL 3 -#define DR_THRESHOLD_CONTROL 4 -#define DR_ATTACK_TIME_CONTROL 5 -#define DR_RELEASE_TIME_CONTROL 6 diff --git a/sys/dev/usbmisc/Makefile b/sys/dev/usbmisc/Makefile deleted file mode 100644 index 7328e99348..0000000000 --- a/sys/dev/usbmisc/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -# $DragonFly: src/sys/dev/usbmisc/Makefile,v 1.10 2008/02/11 18:13:58 hasso Exp $ -# - -SUBDIR= moscom uark ubsa ubt uchcom ucom ufm uftdi ugen ugensa uhid ukbd ulpt \ - umass umct umodem ums uplcom uscanner uslcom uticom uvisor \ - uvscom - -.include diff --git a/sys/dev/usbmisc/moscom/Makefile b/sys/dev/usbmisc/moscom/Makefile deleted file mode 100644 index f94854da5f..0000000000 --- a/sys/dev/usbmisc/moscom/Makefile +++ /dev/null @@ -1,9 +0,0 @@ -# $DragonFly: src/sys/dev/usbmisc/moscom/Makefile,v 1.1 2007/11/07 08:57:18 hasso Exp $ - -S= ${.CURDIR}/../.. -.PATH: $S/dev/usb - -KMOD= moscom -SRCS= moscom.c opt_usb.h device_if.h bus_if.h - -.include diff --git a/sys/dev/usbmisc/moscom/moscom.c b/sys/dev/usbmisc/moscom/moscom.c deleted file mode 100644 index ec92208883..0000000000 --- a/sys/dev/usbmisc/moscom/moscom.c +++ /dev/null @@ -1,449 +0,0 @@ -/* $OpenBSD: src/sys/dev/usb/moscom.c,v 1.11 2007/10/11 18:33:14 deraadt Exp $ */ - -/* - * Copyright (c) 2006 Jonathan Gray - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include - -#define MOSCOMBUFSZ 256 -#define MOSCOM_CONFIG_NO 0 -#define MOSCOM_IFACE_NO 0 - -#define MOSCOM_READ 0x0d -#define MOSCOM_WRITE 0x0e -#define MOSCOM_UART_REG 0x0300 -#define MOSCOM_VEND_REG 0x0000 - -#define MOSCOM_TXBUF 0x00 /* Write */ -#define MOSCOM_RXBUF 0x00 /* Read */ -#define MOSCOM_INT 0x01 -#define MOSCOM_FIFO 0x02 /* Write */ -#define MOSCOM_ISR 0x02 /* Read */ -#define MOSCOM_LCR 0x03 -#define MOSCOM_MCR 0x04 -#define MOSCOM_LSR 0x05 -#define MOSCOM_MSR 0x06 -#define MOSCOM_SCRATCH 0x07 -#define MOSCOM_DIV_LO 0x08 -#define MOSCOM_DIV_HI 0x09 -#define MOSCOM_EFR 0x0a -#define MOSCOM_XON1 0x0b -#define MOSCOM_XON2 0x0c -#define MOSCOM_XOFF1 0x0d -#define MOSCOM_XOFF2 0x0e - -#define MOSCOM_BAUDLO 0x00 -#define MOSCOM_BAUDHI 0x01 - -#define MOSCOM_INT_RXEN 0x01 -#define MOSCOM_INT_TXEN 0x02 -#define MOSCOM_INT_RSEN 0x04 -#define MOSCOM_INT_MDMEM 0x08 -#define MOSCOM_INT_SLEEP 0x10 -#define MOSCOM_INT_XOFF 0x20 -#define MOSCOM_INT_RTS 0x40 - -#define MOSCOM_FIFO_EN 0x01 -#define MOSCOM_FIFO_RXCLR 0x02 -#define MOSCOM_FIFO_TXCLR 0x04 -#define MOSCOM_FIFO_DMA_BLK 0x08 -#define MOSCOM_FIFO_TXLVL_MASK 0x30 -#define MOSCOM_FIFO_TXLVL_8 0x00 -#define MOSCOM_FIFO_TXLVL_16 0x10 -#define MOSCOM_FIFO_TXLVL_32 0x20 -#define MOSCOM_FIFO_TXLVL_56 0x30 -#define MOSCOM_FIFO_RXLVL_MASK 0xc0 -#define MOSCOM_FIFO_RXLVL_8 0x00 -#define MOSCOM_FIFO_RXLVL_16 0x40 -#define MOSCOM_FIFO_RXLVL_56 0x80 -#define MOSCOM_FIFO_RXLVL_80 0xc0 - -#define MOSCOM_ISR_MDM 0x00 -#define MOSCOM_ISR_NONE 0x01 -#define MOSCOM_ISR_TX 0x02 -#define MOSCOM_ISR_RX 0x04 -#define MOSCOM_ISR_LINE 0x06 -#define MOSCOM_ISR_RXTIMEOUT 0x0c -#define MOSCOM_ISR_RX_XOFF 0x10 -#define MOSCOM_ISR_RTSCTS 0x20 -#define MOSCOM_ISR_FIFOEN 0xc0 - -#define MOSCOM_LCR_DBITS(x) (x - 5) -#define MOSCOM_LCR_STOP_BITS_1 0x00 -#define MOSCOM_LCR_STOP_BITS_2 0x04 /* 2 if 6-8 bits/char or 1.5 if 5 */ -#define MOSCOM_LCR_PARITY_NONE 0x00 -#define MOSCOM_LCR_PARITY_ODD 0x08 -#define MOSCOM_LCR_PARITY_EVEN 0x18 -#define MOSCOM_LCR_BREAK 0x40 -#define MOSCOM_LCR_DIVLATCH_EN 0x80 - -#define MOSCOM_MCR_DTR 0x01 -#define MOSCOM_MCR_RTS 0x02 -#define MOSCOM_MCR_LOOP 0x04 -#define MOSCOM_MCR_INTEN 0x08 -#define MOSCOM_MCR_LOOPBACK 0x10 -#define MOSCOM_MCR_XONANY 0x20 -#define MOSCOM_MCR_IRDA_EN 0x40 -#define MOSCOM_MCR_BAUD_DIV4 0x80 - -#define MOSCOM_LSR_RXDATA 0x01 -#define MOSCOM_LSR_RXOVER 0x02 -#define MOSCOM_LSR_RXPAR_ERR 0x04 -#define MOSCOM_LSR_RXFRM_ERR 0x08 -#define MOSCOM_LSR_RXBREAK 0x10 -#define MOSCOM_LSR_TXEMPTY 0x20 -#define MOSCOM_LSR_TXALLEMPTY 0x40 -#define MOSCOM_LSR_TXFIFO_ERR 0x80 - -#define MOSCOM_MSR_CTS_CHG 0x01 -#define MOSCOM_MSR_DSR_CHG 0x02 -#define MOSCOM_MSR_RI_CHG 0x04 -#define MOSCOM_MSR_CD_CHG 0x08 -#define MOSCOM_MSR_CTS 0x10 -#define MOSCOM_MSR_RTS 0x20 -#define MOSCOM_MSR_RI 0x40 -#define MOSCOM_MSR_CD 0x80 - -#define MOSCOM_BAUD_REF 115200 - -struct moscom_softc { - struct ucom_softc sc_ucom; - u_char sc_msr; - u_char sc_lsr; - u_char sc_lcr; -}; - -static void moscom_get_status(void *, int, u_char *, u_char *); -static void moscom_set(void *, int, int, int); -static int moscom_param(void *, int, struct termios *); -static int moscom_open(void *, int); -static int moscom_cmd(struct moscom_softc *, int, int); - -struct ucom_callback moscom_callback = { - moscom_get_status, - moscom_set, - moscom_param, - NULL, - moscom_open, - NULL, - NULL, - NULL, -}; - -static const struct usb_devno moscom_devs[] = { - { USB_DEVICE(0x9710, 0x7703) } /* MosChip MCS7703 serial port */ -}; - -static device_probe_t moscom_match; -static device_attach_t moscom_attach; -static device_detach_t moscom_detach; - -static device_method_t moscom_methods[] = { - DEVMETHOD(device_probe, moscom_match), - DEVMETHOD(device_attach, moscom_attach), - DEVMETHOD(device_detach, moscom_detach), - DEVMETHOD_END -}; - -static driver_t moscom_driver = { - "ucom", - moscom_methods, - sizeof (struct moscom_softc) -}; - -DRIVER_MODULE(moscom, uhub, moscom_driver, ucom_devclass, usbd_driver_load, NULL); -MODULE_DEPEND(moscom, usb, 1, 1, 1); -MODULE_DEPEND(moscom, ucom, UCOM_MINVER, UCOM_PREFVER, UCOM_MAXVER); -MODULE_VERSION(moscom, 1); - -static int -moscom_match(device_t self) -{ - struct usb_attach_arg *uaa = device_get_ivars(self); - - if (uaa->iface != NULL) - return UMATCH_NONE; - - return (usb_lookup(moscom_devs, uaa->vendor, uaa->product) != NULL) ? - UMATCH_VENDOR_PRODUCT : UMATCH_NONE; -} - -static int -moscom_attach(device_t self) -{ - struct moscom_softc *sc = device_get_softc(self); - struct usb_attach_arg *uaa = device_get_ivars(self); - struct ucom_softc *ucom; - usb_interface_descriptor_t *id; - usb_endpoint_descriptor_t *ed; - usbd_status error; - int i; - - bzero(sc, sizeof (struct moscom_softc)); - ucom = &sc->sc_ucom; - ucom->sc_dev = self; - ucom->sc_udev = uaa->device; - ucom->sc_iface = uaa->iface; - - if (usbd_set_config_index(ucom->sc_udev, MOSCOM_CONFIG_NO, 1) != 0) { - device_printf(ucom->sc_dev, "could not set configuration no\n"); - ucom->sc_dying = 1; - return ENXIO; - } - - /* get the first interface handle */ - error = usbd_device2interface_handle(ucom->sc_udev, MOSCOM_IFACE_NO, - &ucom->sc_iface); - if (error != 0) { - device_printf(ucom->sc_dev, "could not get interface handle\n"); - ucom->sc_dying = 1; - return ENXIO; - } - - id = usbd_get_interface_descriptor(ucom->sc_iface); - - ucom->sc_bulkin_no = ucom->sc_bulkout_no = -1; - for (i = 0; i < id->bNumEndpoints; i++) { - ed = usbd_interface2endpoint_descriptor(ucom->sc_iface, i); - if (ed == NULL) { - device_printf(ucom->sc_dev, "no endpoint descriptor " - "found for %d\n", i); - ucom->sc_dying = 1; - return ENXIO; - } - - if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && - UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) - ucom->sc_bulkin_no = ed->bEndpointAddress; - else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT && - UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) - ucom->sc_bulkout_no = ed->bEndpointAddress; - } - - if (ucom->sc_bulkin_no == -1 || ucom->sc_bulkout_no == -1) { - device_printf(ucom->sc_dev, "missing endpoint\n"); - ucom->sc_dying = 1; - return ENXIO; - } - - ucom->sc_parent = sc; - ucom->sc_portno = UCOM_UNK_PORTNO; - ucom->sc_ibufsize = MOSCOMBUFSZ; - ucom->sc_obufsize = MOSCOMBUFSZ; - ucom->sc_ibufsizepad = MOSCOMBUFSZ; - ucom->sc_opkthdrlen = 0; - ucom->sc_callback = &moscom_callback; - - usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, ucom->sc_udev, - ucom->sc_dev); - - return 0; -} - -static int -moscom_detach(device_t self) -{ - struct moscom_softc *sc = device_get_softc(self); - int rv = 0; - - sc->sc_ucom.sc_dying = 1; - rv = ucom_detach(&sc->sc_ucom); - usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_ucom.sc_udev, - sc->sc_ucom.sc_dev); - - return (rv); -} - -#if 0 /* endif */ -int -moscom_activate(struct device *self, enum devact act) -{ - struct moscom_softc *sc = (struct moscom_softc *)self; - int rv = 0; - - switch (act) { - case DVACT_ACTIVATE: - break; - - case DVACT_DEACTIVATE: - if (sc->sc_subdev != NULL) - rv = config_deactivate(sc->sc_subdev); - sc->sc_ucom.sc_dying = 1; - break; - } - return (rv); -} -#endif - -static int -moscom_open(void *vsc, int portno) -{ - struct moscom_softc *sc = vsc; - usb_device_request_t req; - - if (sc->sc_ucom.sc_dying) - return (EIO); - - /* Purge FIFOs or odd things happen */ - if (moscom_cmd(sc, MOSCOM_FIFO, 0x00) != 0) - return (EIO); - - if (moscom_cmd(sc, MOSCOM_FIFO, MOSCOM_FIFO_EN | - MOSCOM_FIFO_RXCLR | MOSCOM_FIFO_TXCLR | - MOSCOM_FIFO_DMA_BLK | MOSCOM_FIFO_RXLVL_MASK) != 0) - return (EIO); - - /* Magic tell device we're ready for data command */ - req.bmRequestType = UT_WRITE_VENDOR_DEVICE; - req.bRequest = MOSCOM_WRITE; - USETW(req.wValue, 0x08); - USETW(req.wIndex, MOSCOM_INT); - USETW(req.wLength, 0); - if (usbd_do_request(sc->sc_ucom.sc_udev, &req, NULL) != 0) - return (EIO); - - return (0); -} - -static void -moscom_set(void *vsc, int portno, int reg, int onoff) -{ - struct moscom_softc *sc = vsc; - int val; - - switch (reg) { - case UCOM_SET_DTR: - val = onoff ? MOSCOM_MCR_DTR : 0; - break; - case UCOM_SET_RTS: - val = onoff ? MOSCOM_MCR_RTS : 0; - break; - case UCOM_SET_BREAK: - val = sc->sc_lcr; - if (onoff) - val |= MOSCOM_LCR_BREAK; - moscom_cmd(sc, MOSCOM_LCR, val); - return; - default: - return; - } - - moscom_cmd(sc, MOSCOM_MCR, val); -} - -static int -moscom_param(void *vsc, int portno, struct termios *t) -{ - struct moscom_softc *sc = (struct moscom_softc *)vsc; - int data; - - if (t->c_ospeed <= 0 || t->c_ospeed > 115200) - return (EINVAL); - - data = MOSCOM_BAUD_REF / t->c_ospeed; - - if (data == 0 || data > 0xffff) - return (EINVAL); - - moscom_cmd(sc, MOSCOM_LCR, MOSCOM_LCR_DIVLATCH_EN); - moscom_cmd(sc, MOSCOM_BAUDLO, data & 0xFF); - moscom_cmd(sc, MOSCOM_BAUDHI, (data >> 8) & 0xFF); - - if (ISSET(t->c_cflag, CSTOPB)) - data = MOSCOM_LCR_STOP_BITS_2; - else - data = MOSCOM_LCR_STOP_BITS_1; - if (ISSET(t->c_cflag, PARENB)) { - if (ISSET(t->c_cflag, PARODD)) - data |= MOSCOM_LCR_PARITY_ODD; - else - data |= MOSCOM_LCR_PARITY_EVEN; - } else - data |= MOSCOM_LCR_PARITY_NONE; - switch (ISSET(t->c_cflag, CSIZE)) { - case CS5: - data |= MOSCOM_LCR_DBITS(5); - break; - case CS6: - data |= MOSCOM_LCR_DBITS(6); - break; - case CS7: - data |= MOSCOM_LCR_DBITS(7); - break; - case CS8: - data |= MOSCOM_LCR_DBITS(8); - break; - } - - sc->sc_lcr = data; - moscom_cmd(sc, MOSCOM_LCR, sc->sc_lcr); - -#if 0 - /* XXX flow control */ - if (ISSET(t->c_cflag, CRTSCTS)) - /* rts/cts flow ctl */ - } else if (ISSET(t->c_iflag, IXON|IXOFF)) { - /* xon/xoff flow ctl */ - } else { - /* disable flow ctl */ - } -#endif - - return (0); -} - -static void -moscom_get_status(void *vsc, int portno, u_char *lsr, u_char *msr) -{ - struct moscom_softc *sc = vsc; - - if (msr != NULL) - *msr = sc->sc_msr; - if (lsr != NULL) - *lsr = sc->sc_lsr; -} - -static int -moscom_cmd(struct moscom_softc *sc, int reg, int val) -{ - usb_device_request_t req; - usbd_status err; - - req.bmRequestType = UT_WRITE_VENDOR_DEVICE; - req.bRequest = MOSCOM_WRITE; - USETW(req.wValue, val + MOSCOM_UART_REG); - USETW(req.wIndex, reg); - USETW(req.wLength, 0); - err = usbd_do_request(sc->sc_ucom.sc_udev, &req, NULL); - if (err) - return (EIO); - else - return (0); -} diff --git a/sys/dev/usbmisc/uark/Makefile b/sys/dev/usbmisc/uark/Makefile deleted file mode 100644 index b7699c903a..0000000000 --- a/sys/dev/usbmisc/uark/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -# $DragonFly: src/sys/dev/usbmisc/uark/Makefile,v 1.2 2007/09/29 21:13:09 swildner Exp $ - -.PATH: ${.CURDIR}/../ucom - -KMOD= uark -SRCS= uark.c opt_usb.h device_if.h bus_if.h - -.include diff --git a/sys/dev/usbmisc/uark/uark.c b/sys/dev/usbmisc/uark/uark.c deleted file mode 100644 index 7186e1f954..0000000000 --- a/sys/dev/usbmisc/uark/uark.c +++ /dev/null @@ -1,371 +0,0 @@ -/* $OpenBSD: uark.c,v 1.9 2007/06/13 06:25:03 mbalmer Exp $ */ - -/* - * Copyright (c) 2006 Jonathan Gray - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include - -#ifdef UARK_DEBUG -#define DPRINTFN(n, x) do { if (uarkdebug > (n)) kprintf x; } while (0) -int uarkebug = 0; -#else -#define DPRINTFN(n, x) -#endif -#define DPRINTF(x) DPRINTFN(0, x) - -#define UARKBUFSZ 256 -#define UARK_CONFIG_NO 0 -#define UARK_IFACE_NO 0 - -#define UARK_SET_DATA_BITS(x) (x - 5) - -#define UARK_PARITY_NONE 0x00 -#define UARK_PARITY_ODD 0x08 -#define UARK_PARITY_EVEN 0x18 - -#define UARK_STOP_BITS_1 0x00 -#define UARK_STOP_BITS_2 0x04 - -#define UARK_BAUD_REF 3000000 - -#define UARK_WRITE 0x40 -#define UARK_READ 0xc0 - -#define UARK_REQUEST 0xfe - -struct uark_softc { - struct ucom_softc sc_ucom; - u_char sc_msr; - u_char sc_lsr; -}; - -static void uark_get_status(void *, int portno, u_char *lsr, u_char *msr); -static void uark_set(void *, int, int, int); -static int uark_param(void *, int, struct termios *); -static void uark_break(void *, int, int); -static int uark_cmd(struct uark_softc *, uint16_t, uint16_t); - -struct ucom_callback uark_callback = { - uark_get_status, - uark_set, - uark_param, - NULL, - NULL, - NULL, - NULL, - NULL, -}; - -static const struct usb_devno uark_devs[] = { - { USB_DEVICE(0x6547, 0x0232) } /* Arkmicro Technologies ARK3116 */ -}; - -static device_probe_t uark_match; -static device_attach_t uark_attach; -static device_detach_t uark_detach; - -static device_method_t uark_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, uark_match), - DEVMETHOD(device_attach, uark_attach), - DEVMETHOD(device_detach, uark_detach), - DEVMETHOD_END -}; - -static driver_t uark_driver = { - "ucom", - uark_methods, - sizeof (struct uark_softc) -}; - -DRIVER_MODULE(uark, uhub, uark_driver, ucom_devclass, usbd_driver_load, NULL); -MODULE_DEPEND(uark, usb, 1, 1, 1); -MODULE_DEPEND(uark, ucom, UCOM_MINVER, UCOM_PREFVER, UCOM_MAXVER); -MODULE_VERSION(uark, 1); - -static int -uark_match(device_t self) -{ - struct usb_attach_arg *uaa = device_get_ivars(self); - - if (uaa->iface != NULL) - return UMATCH_NONE; - - return (usb_lookup(uark_devs, uaa->vendor, uaa->product) != NULL) ? - UMATCH_VENDOR_PRODUCT : UMATCH_NONE; -} - -static int -uark_attach(device_t self) -{ - struct uark_softc *sc = device_get_softc(self); - struct usb_attach_arg *uaa = device_get_ivars(self); - struct ucom_softc *ucom; - usb_interface_descriptor_t *id; - usb_endpoint_descriptor_t *ed; - usbd_status error; - int i; - - ucom = &sc->sc_ucom; - bzero(sc, sizeof (struct uark_softc)); - - ucom->sc_dev = self; - ucom->sc_udev = uaa->device; - ucom->sc_iface = uaa->iface; - - if (usbd_set_config_index(ucom->sc_udev, UARK_CONFIG_NO, 1) != 0) { - device_printf(ucom->sc_dev, "could not set configuration no\n"); - goto error; - } - - /* get the first interface handle */ - error = usbd_device2interface_handle(ucom->sc_udev, UARK_IFACE_NO, - &ucom->sc_iface); - if (error != 0) { - device_printf(ucom->sc_dev, "could not get interface handle\n"); - goto error; - } - - id = usbd_get_interface_descriptor(ucom->sc_iface); - - ucom->sc_bulkin_no = ucom->sc_bulkout_no = -1; - for (i = 0; i < id->bNumEndpoints; i++) { - ed = usbd_interface2endpoint_descriptor(ucom->sc_iface, i); - if (ed == NULL) { - device_printf(ucom->sc_dev, "no endpoint descriptor " - "found for %d\n", i); - goto error; - } - - if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && - UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) - ucom->sc_bulkin_no = ed->bEndpointAddress; - else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT && - UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) - ucom->sc_bulkout_no = ed->bEndpointAddress; - } - - if (ucom->sc_bulkin_no == -1 || ucom->sc_bulkout_no == -1) { - device_printf(ucom->sc_dev, "missing endpoint\n"); - goto error; - } - - ucom->sc_parent = sc; - ucom->sc_portno = UCOM_UNK_PORTNO; - ucom->sc_ibufsize = UARKBUFSZ; - ucom->sc_obufsize = UARKBUFSZ; - ucom->sc_ibufsizepad = UARKBUFSZ; - ucom->sc_opkthdrlen = 0; - ucom->sc_callback = &uark_callback; - - usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, ucom->sc_udev, - ucom->sc_dev); - - DPRINTF(("uark: in = 0x%x, out = 0x%x, intr = 0x%x\n", - ucom->sc_bulkin_no, ucom->sc_bulkout_no, sc->sc_intr_number)); - - ucom_attach(&sc->sc_ucom); - - return 0; - -error: - ucom->sc_dying = 1; - return ENXIO; -} - -static int -uark_detach(device_t self) -{ - struct uark_softc *sc = device_get_softc(self); - int rv = 0; - - DPRINTF(("uark_detach: sc=%p\n", sc)); - sc->sc_ucom.sc_dying = 1; - rv = ucom_detach(&sc->sc_ucom); - usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_ucom.sc_udev, - sc->sc_ucom.sc_dev); - - return (rv); -} - -#if 0 /* not yet */ -int -uark_activate(struct device *self, enum devact act) -{ - struct uark_softc *sc = (struct uark_softc *)self; - int rv = 0; - - switch (act) { - case DVACT_ACTIVATE: - break; - - case DVACT_DEACTIVATE: - if (sc->sc_subdev != NULL) - rv = config_deactivate(sc->sc_subdev); - sc->sc_dying = 1; - break; - } - return (rv); -} -#endif - -static void -uark_set(void *vsc, int portno, int reg, int onoff) -{ - struct uark_softc *sc = vsc; - - switch (reg) { - case UCOM_SET_BREAK: - uark_break(sc, portno, onoff); - return; - case UCOM_SET_DTR: - case UCOM_SET_RTS: - default: - return; - } -} - -static int -uark_param(void *vsc, int portno, struct termios *t) -{ - struct uark_softc *sc = (struct uark_softc *)vsc; - int data; - - switch (t->c_ospeed) { - case 300: - case 600: - case 1200: - case 1800: - case 2400: - case 4800: - case 9600: - case 19200: - case 38400: - case 57600: - case 115200: - uark_cmd(sc, 3, 0x83); - uark_cmd(sc, 0, (UARK_BAUD_REF / t->c_ospeed) & 0xFF); - uark_cmd(sc, 1, (UARK_BAUD_REF / t->c_ospeed) >> 8); - uark_cmd(sc, 3, 0x03); - break; - default: - return (EINVAL); - } - - if (ISSET(t->c_cflag, CSTOPB)) - data = UARK_STOP_BITS_2; - else - data = UARK_STOP_BITS_1; - - if (ISSET(t->c_cflag, PARENB)) { - if (ISSET(t->c_cflag, PARODD)) - data |= UARK_PARITY_ODD; - else - data |= UARK_PARITY_EVEN; - } else - data |= UARK_PARITY_NONE; - - switch (ISSET(t->c_cflag, CSIZE)) { - case CS5: - data |= UARK_SET_DATA_BITS(5); - break; - case CS6: - data |= UARK_SET_DATA_BITS(6); - break; - case CS7: - data |= UARK_SET_DATA_BITS(7); - break; - case CS8: - data |= UARK_SET_DATA_BITS(8); - break; - } - - uark_cmd(sc, 3, 0x00); - uark_cmd(sc, 3, data); - -#if 0 - /* XXX flow control */ - if (ISSET(t->c_cflag, CRTSCTS)) - /* rts/cts flow ctl */ - } else if (ISSET(t->c_iflag, IXON|IXOFF)) { - /* xon/xoff flow ctl */ - } else { - /* disable flow ctl */ - } -#endif - - return (0); -} - -static void -uark_get_status(void *vsc, int portno, u_char *lsr, u_char *msr) -{ - struct uark_softc *sc = vsc; - - if (msr != NULL) - *msr = sc->sc_msr; - if (lsr != NULL) - *lsr = sc->sc_lsr; -} - -static void -uark_break(void *vsc, int portno, int onoff) -{ -#ifdef UARK_DEBUG - struct uark_softc *sc = vsc; - - device_printf(sc->sc_ucom.sc_dev, "break %s!\n", onoff ? "on" : "off"); - - if (onoff) - /* break on */ - uark_cmd(sc, 4, 0x01); - else - uark_cmd(sc, 4, 0x00); -#endif -} - -static int -uark_cmd(struct uark_softc *sc, uint16_t index, uint16_t value) -{ - usb_device_request_t req; - usbd_status err; - - req.bmRequestType = UARK_WRITE; - req.bRequest = UARK_REQUEST; - USETW(req.wValue, value); - USETW(req.wIndex, index); - USETW(req.wLength, 0); - err = usbd_do_request(sc->sc_ucom.sc_udev, &req, NULL); - - if (err) - return (EIO); - - return (0); -} diff --git a/sys/dev/usbmisc/ubsa/Makefile b/sys/dev/usbmisc/ubsa/Makefile deleted file mode 100644 index b0576e987b..0000000000 --- a/sys/dev/usbmisc/ubsa/Makefile +++ /dev/null @@ -1,9 +0,0 @@ -# $FreeBSD: src/sys/modules/ubsa/Makefile,v 1.1.2.2 2003/01/14 20:04:22 kan Exp $ -# $DragonFly: src/sys/dev/usbmisc/ubsa/Makefile,v 1.4 2004/08/13 17:51:06 dillon Exp $ - -.PATH: ${.CURDIR}/../ucom - -KMOD= ubsa -SRCS= ubsa.c ucomvar.h opt_usb.h device_if.h bus_if.h - -.include diff --git a/sys/dev/usbmisc/ubsa/ubsa.c b/sys/dev/usbmisc/ubsa/ubsa.c deleted file mode 100644 index 917d56f542..0000000000 --- a/sys/dev/usbmisc/ubsa/ubsa.c +++ /dev/null @@ -1,713 +0,0 @@ -/*- - * Copyright (c) 2002, Alexander Kabaev . - * 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. - */ - -/* - * Copyright (c) 2001 The NetBSD Foundation, Inc. - * All rights reserved. - * - * This code is derived from software contributed to The NetBSD Foundation - * by Ichiro FUKUHARA (ichiro@ichiro.org). - * - * 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. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the NetBSD - * Foundation, Inc. and its contributors. - * 4. Neither the name of The NetBSD Foundation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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: src/sys/dev/usb/ubsa.c,v 1.11 2003/11/16 12:13:39 akiyama Exp $ - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include -#include - -#include "../ucom/ucomvar.h" - -#ifdef USB_DEBUG -static int ubsadebug = 0; -SYSCTL_NODE(_hw_usb, OID_AUTO, ubsa, CTLFLAG_RW, 0, "USB ubsa"); -SYSCTL_INT(_hw_usb_ubsa, OID_AUTO, debug, CTLFLAG_RW, - &ubsadebug, 0, "ubsa debug level"); - -#define DPRINTFN(n, x) do { \ - if (ubsadebug > (n)) \ - kprintf x; \ - } while (0) -#else -#define DPRINTFN(n, x) -#endif -#define DPRINTF(x) DPRINTFN(0, x) - -#define UBSA_MODVER 1 /* module version */ - -#define UBSA_CONFIG_INDEX 1 -#define UBSA_IFACE_INDEX 0 - -#define UBSA_INTR_INTERVAL 100 /* ms */ - -#define UBSA_SET_BAUDRATE 0x00 -#define UBSA_SET_STOP_BITS 0x01 -#define UBSA_SET_DATA_BITS 0x02 -#define UBSA_SET_PARITY 0x03 -#define UBSA_SET_DTR 0x0A -#define UBSA_SET_RTS 0x0B -#define UBSA_SET_BREAK 0x0C -#define UBSA_SET_FLOW_CTRL 0x10 - -#define UBSA_PARITY_NONE 0x00 -#define UBSA_PARITY_EVEN 0x01 -#define UBSA_PARITY_ODD 0x02 -#define UBSA_PARITY_MARK 0x03 -#define UBSA_PARITY_SPACE 0x04 - -#define UBSA_FLOW_NONE 0x0000 -#define UBSA_FLOW_OCTS 0x0001 -#define UBSA_FLOW_ODSR 0x0002 -#define UBSA_FLOW_IDSR 0x0004 -#define UBSA_FLOW_IDTR 0x0008 -#define UBSA_FLOW_IRTS 0x0010 -#define UBSA_FLOW_ORTS 0x0020 -#define UBSA_FLOW_UNKNOWN 0x0040 -#define UBSA_FLOW_OXON 0x0080 -#define UBSA_FLOW_IXON 0x0100 - -/* line status register */ -#define UBSA_LSR_TSRE 0x40 /* Transmitter empty: byte sent */ -#define UBSA_LSR_TXRDY 0x20 /* Transmitter buffer empty */ -#define UBSA_LSR_BI 0x10 /* Break detected */ -#define UBSA_LSR_FE 0x08 /* Framing error: bad stop bit */ -#define UBSA_LSR_PE 0x04 /* Parity error */ -#define UBSA_LSR_OE 0x02 /* Overrun, lost incoming byte */ -#define UBSA_LSR_RXRDY 0x01 /* Byte ready in Receive Buffer */ -#define UBSA_LSR_RCV_MASK 0x1f /* Mask for incoming data or error */ - -/* modem status register */ -/* All deltas are from the last read of the MSR. */ -#define UBSA_MSR_DCD 0x80 /* Current Data Carrier Detect */ -#define UBSA_MSR_RI 0x40 /* Current Ring Indicator */ -#define UBSA_MSR_DSR 0x20 /* Current Data Set Ready */ -#define UBSA_MSR_CTS 0x10 /* Current Clear to Send */ -#define UBSA_MSR_DDCD 0x08 /* DCD has changed state */ -#define UBSA_MSR_TERI 0x04 /* RI has toggled low to high */ -#define UBSA_MSR_DDSR 0x02 /* DSR has changed state */ -#define UBSA_MSR_DCTS 0x01 /* CTS has changed state */ - -struct ubsa_softc { - struct ucom_softc sc_ucom; - - int sc_iface_number; /* interface number */ - - usbd_interface_handle sc_intr_iface; /* interrupt interface */ - int sc_intr_number; /* interrupt number */ - usbd_pipe_handle sc_intr_pipe; /* interrupt pipe */ - u_char *sc_intr_buf; /* interrupt buffer */ - int sc_isize; - - u_char sc_dtr; /* current DTR state */ - u_char sc_rts; /* current RTS state */ - - u_char sc_lsr; /* Local status register */ - u_char sc_msr; /* ubsa status register */ -}; - -static void ubsa_intr(usbd_xfer_handle, usbd_private_handle, usbd_status); -static void ubsa_notify(void *); - -static void ubsa_get_status(void *, int, u_char *, u_char *); -static void ubsa_set(void *, int, int, int); -static int ubsa_param(void *, int, struct termios *); -static int ubsa_open(void *, int); -static void ubsa_close(void *, int); - -static int ubsa_request(struct ubsa_softc *, u_int8_t, u_int16_t); -static void ubsa_dtr(struct ubsa_softc *, int); -static void ubsa_rts(struct ubsa_softc *, int); -static void ubsa_baudrate(struct ubsa_softc *, speed_t); -static void ubsa_parity(struct ubsa_softc *, tcflag_t); -static void ubsa_databits(struct ubsa_softc *, tcflag_t); -static void ubsa_stopbits(struct ubsa_softc *, tcflag_t); -static void ubsa_flow(struct ubsa_softc *, tcflag_t, tcflag_t); - -struct ucom_callback ubsa_callback = { - ubsa_get_status, - ubsa_set, - ubsa_param, - NULL, - ubsa_open, - ubsa_close, - NULL, - NULL -}; - -static const struct usb_devno ubsa_devs [] = { - { USB_DEVICE(0x050d, 0x0103) }, /* Belkin F5U103 serial adapter */ - { USB_DEVICE(0x050d, 0x1203) }, /* Belkin F5U120-PC hub */ - { USB_DEVICE(0x0565, 0x0001) }, /* Peracom serial converter */ - { USB_DEVICE(0x056c, 0x8007) }, /* e-TEK Labs serial port */ - { USB_DEVICE(0x0921, 0x1001) }, /* GoHubs GoCOM232 serial converter */ - { USB_DEVICE(0x0921, 0x1200) }, /* HandyTech's Braille displays */ -}; - -static device_probe_t ubsa_match; -static device_attach_t ubsa_attach; -static device_detach_t ubsa_detach; - -static device_method_t ubsa_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, ubsa_match), - DEVMETHOD(device_attach, ubsa_attach), - DEVMETHOD(device_detach, ubsa_detach), - DEVMETHOD_END -}; - -static driver_t ubsa_driver = { - "ucom", - ubsa_methods, - sizeof (struct ubsa_softc) -}; - -DRIVER_MODULE(ubsa, uhub, ubsa_driver, ucom_devclass, usbd_driver_load, NULL); -MODULE_DEPEND(ubsa, usb, 1, 1, 1); -MODULE_DEPEND(ubsa, ucom, UCOM_MINVER, UCOM_PREFVER, UCOM_MAXVER); -MODULE_VERSION(ubsa, UBSA_MODVER); - -static int -ubsa_match(device_t self) -{ - struct usb_attach_arg *uaa = device_get_ivars(self); - - if (uaa->iface != NULL) - return (UMATCH_NONE); - - return (usb_lookup(ubsa_devs, uaa->vendor, uaa->product) != NULL ? - UMATCH_VENDOR_PRODUCT : UMATCH_NONE); -} - -static int -ubsa_attach(device_t self) -{ - struct ubsa_softc *sc = device_get_softc(self); - struct usb_attach_arg *uaa = device_get_ivars(self); - usbd_device_handle dev; - struct ucom_softc *ucom; - usb_config_descriptor_t *cdesc; - usb_interface_descriptor_t *id; - usb_endpoint_descriptor_t *ed; - usbd_status err; - int i; - - dev = uaa->device; - ucom = &sc->sc_ucom; - bzero(sc, sizeof (struct ubsa_softc)); - - /* - * initialize rts, dtr variables to something - * different from boolean 0, 1 - */ - sc->sc_dtr = -1; - sc->sc_rts = -1; - - ucom->sc_dev = self; - ucom->sc_udev = dev; - ucom->sc_iface = uaa->iface; - - DPRINTF(("ubsa attach: sc = %p\n", sc)); - - /* initialize endpoints */ - ucom->sc_bulkin_no = ucom->sc_bulkout_no = -1; - sc->sc_intr_number = -1; - sc->sc_intr_pipe = NULL; - - /* Move the device into the configured state. */ - err = usbd_set_config_index(dev, UBSA_CONFIG_INDEX, 1); - if (err) { - device_printf(ucom->sc_dev, "failed to set configuration: %s\n", - usbd_errstr(err)); - ucom->sc_dying = 1; - goto error; - } - - /* get the config descriptor */ - cdesc = usbd_get_config_descriptor(ucom->sc_udev); - - if (cdesc == NULL) { - device_printf(ucom->sc_dev, "failed to get configuration " - "descriptor\n"); - ucom->sc_dying = 1; - goto error; - } - - /* get the first interface */ - err = usbd_device2interface_handle(dev, UBSA_IFACE_INDEX, - &ucom->sc_iface); - if (err) { - device_printf(ucom->sc_dev, "failed to get interface: %s\n", - usbd_errstr(err)); - ucom->sc_dying = 1; - goto error; - } - - /* Find the endpoints */ - - id = usbd_get_interface_descriptor(ucom->sc_iface); - sc->sc_iface_number = id->bInterfaceNumber; - - for (i = 0; i < id->bNumEndpoints; i++) { - ed = usbd_interface2endpoint_descriptor(ucom->sc_iface, i); - if (ed == NULL) { - device_printf(ucom->sc_dev, "no endpoint descriptor " - "for %d\n", i); - ucom->sc_dying = 1; - goto error; - } - - if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && - UE_GET_XFERTYPE(ed->bmAttributes) == UE_INTERRUPT) { - sc->sc_intr_number = ed->bEndpointAddress; - sc->sc_isize = UGETW(ed->wMaxPacketSize); - } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && - UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) { - ucom->sc_bulkin_no = ed->bEndpointAddress; - ucom->sc_ibufsize = UGETW(ed->wMaxPacketSize); - } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT && - UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) { - ucom->sc_bulkout_no = ed->bEndpointAddress; - ucom->sc_obufsize = UGETW(ed->wMaxPacketSize); - } - } - - if (sc->sc_intr_number == -1) { - device_printf(ucom->sc_dev, "could not find interrupt in\n"); - ucom->sc_dying = 1; - goto error; - } - - /* keep interface for interrupt */ - sc->sc_intr_iface = ucom->sc_iface; - - if (ucom->sc_bulkin_no == -1) { - device_printf(ucom->sc_dev, "could not find data bulk in\n"); - ucom->sc_dying = 1; - goto error; - } - - if (ucom->sc_bulkout_no == -1) { - device_printf(ucom->sc_dev, "could not find data bulk out\n"); - ucom->sc_dying = 1; - goto error; - } - - ucom->sc_parent = sc; - ucom->sc_portno = UCOM_UNK_PORTNO; - /* bulkin, bulkout set above */ - ucom->sc_ibufsizepad = ucom->sc_ibufsize; - ucom->sc_opkthdrlen = 0; - ucom->sc_callback = &ubsa_callback; - - DPRINTF(("ubsa: in = 0x%x, out = 0x%x, intr = 0x%x\n", - ucom->sc_bulkin_no, ucom->sc_bulkout_no, sc->sc_intr_number)); - - ucom_attach(ucom); - - return 0; - -error: - return ENXIO; -} - -static int -ubsa_detach(device_t self) -{ - struct ubsa_softc *sc = device_get_softc(self); - int rv; - - - DPRINTF(("ubsa_detach: sc = %p\n", sc)); - - if (sc->sc_intr_pipe != NULL) { - usbd_abort_pipe(sc->sc_intr_pipe); - usbd_close_pipe(sc->sc_intr_pipe); - kfree(sc->sc_intr_buf, M_USBDEV); - sc->sc_intr_pipe = NULL; - } - - sc->sc_ucom.sc_dying = 1; - - rv = ucom_detach(&sc->sc_ucom); - - return (rv); -} - -static int -ubsa_request(struct ubsa_softc *sc, u_int8_t request, u_int16_t value) -{ - usb_device_request_t req; - usbd_status err; - - req.bmRequestType = UT_WRITE_VENDOR_DEVICE; - req.bRequest = request; - USETW(req.wValue, value); - USETW(req.wIndex, sc->sc_iface_number); - USETW(req.wLength, 0); - - err = usbd_do_request(sc->sc_ucom.sc_udev, &req, 0); - if (err) - device_printf(sc->sc_ucom.sc_dev, "ubsa_request: %s\n", - usbd_errstr(err)); - return (err); -} - -static void -ubsa_dtr(struct ubsa_softc *sc, int onoff) -{ - - DPRINTF(("ubsa_dtr: onoff = %d\n", onoff)); - - if (sc->sc_dtr == onoff) - return; - sc->sc_dtr = onoff; - - ubsa_request(sc, UBSA_SET_DTR, onoff ? 1 : 0); -} - -static void -ubsa_rts(struct ubsa_softc *sc, int onoff) -{ - - DPRINTF(("ubsa_rts: onoff = %d\n", onoff)); - - if (sc->sc_rts == onoff) - return; - sc->sc_rts = onoff; - - ubsa_request(sc, UBSA_SET_RTS, onoff ? 1 : 0); -} - -static void -ubsa_break(struct ubsa_softc *sc, int onoff) -{ - - DPRINTF(("ubsa_rts: onoff = %d\n", onoff)); - - ubsa_request(sc, UBSA_SET_BREAK, onoff ? 1 : 0); -} - -static void -ubsa_set(void *addr, int portno, int reg, int onoff) -{ - struct ubsa_softc *sc; - - sc = addr; - switch (reg) { - case UCOM_SET_DTR: - ubsa_dtr(sc, onoff); - break; - case UCOM_SET_RTS: - ubsa_rts(sc, onoff); - break; - case UCOM_SET_BREAK: - ubsa_break(sc, onoff); - break; - default: - break; - } -} - -static void -ubsa_baudrate(struct ubsa_softc *sc, speed_t speed) -{ - u_int16_t value = 0; - - DPRINTF(("ubsa_baudrate: speed = %d\n", speed)); - - switch(speed) { - case B0: - break; - case B300: - case B600: - case B1200: - case B2400: - case B4800: - case B9600: - case B19200: - case B38400: - case B57600: - case B115200: - case B230400: - value = B230400 / speed; - break; - default: - device_printf(sc->sc_ucom.sc_dev, "ubsa_param: unsupported " - "baudrate, forcing default of 9600\n"); - value = B230400 / B9600; - break; - } - - if (speed == B0) { - ubsa_flow(sc, 0, 0); - ubsa_dtr(sc, 0); - ubsa_rts(sc, 0); - } else - ubsa_request(sc, UBSA_SET_BAUDRATE, value); -} - -static void -ubsa_parity(struct ubsa_softc *sc, tcflag_t cflag) -{ - int value; - - DPRINTF(("ubsa_parity: cflag = 0x%x\n", cflag)); - - if (cflag & PARENB) - value = (cflag & PARODD) ? UBSA_PARITY_ODD : UBSA_PARITY_EVEN; - else - value = UBSA_PARITY_NONE; - - ubsa_request(sc, UBSA_SET_PARITY, value); -} - -static void -ubsa_databits(struct ubsa_softc *sc, tcflag_t cflag) -{ - int value; - - DPRINTF(("ubsa_databits: cflag = 0x%x\n", cflag)); - - switch (cflag & CSIZE) { - case CS5: value = 0; break; - case CS6: value = 1; break; - case CS7: value = 2; break; - case CS8: value = 3; break; - default: - device_printf(sc->sc_ucom.sc_dev, "ubsa_param: unsupported " - "databits requested, forcing default of 8\n"); - value = 3; - } - - ubsa_request(sc, UBSA_SET_DATA_BITS, value); -} - -static void -ubsa_stopbits(struct ubsa_softc *sc, tcflag_t cflag) -{ - int value; - - DPRINTF(("ubsa_stopbits: cflag = 0x%x\n", cflag)); - - value = (cflag & CSTOPB) ? 1 : 0; - - ubsa_request(sc, UBSA_SET_STOP_BITS, value); -} - -static void -ubsa_flow(struct ubsa_softc *sc, tcflag_t cflag, tcflag_t iflag) -{ - int value; - - DPRINTF(("ubsa_flow: cflag = 0x%x, iflag = 0x%x\n", cflag, iflag)); - - value = 0; - if (cflag & CRTSCTS) - value |= UBSA_FLOW_OCTS | UBSA_FLOW_IRTS; - if (iflag & (IXON|IXOFF)) - value |= UBSA_FLOW_OXON | UBSA_FLOW_IXON; - - ubsa_request(sc, UBSA_SET_FLOW_CTRL, value); -} - -static int -ubsa_param(void *addr, int portno, struct termios *ti) -{ - struct ubsa_softc *sc; - - sc = addr; - - DPRINTF(("ubsa_param: sc = %p\n", sc)); - - ubsa_baudrate(sc, ti->c_ospeed); - ubsa_parity(sc, ti->c_cflag); - ubsa_databits(sc, ti->c_cflag); - ubsa_stopbits(sc, ti->c_cflag); - ubsa_flow(sc, ti->c_cflag, ti->c_iflag); - - return (0); -} - -static int -ubsa_open(void *addr, int portno) -{ - struct ubsa_softc *sc; - int err; - - sc = addr; - if (sc->sc_ucom.sc_dying) - return (ENXIO); - - DPRINTF(("ubsa_open: sc = %p\n", sc)); - - if (sc->sc_intr_number != -1 && sc->sc_intr_pipe == NULL) { - sc->sc_intr_buf = kmalloc(sc->sc_isize, M_USBDEV, M_WAITOK); - err = usbd_open_pipe_intr(sc->sc_intr_iface, - sc->sc_intr_number, - USBD_SHORT_XFER_OK, - &sc->sc_intr_pipe, - sc, - sc->sc_intr_buf, - sc->sc_isize, - ubsa_intr, - UBSA_INTR_INTERVAL); - if (err) { - device_printf(sc->sc_ucom.sc_dev, "cannot open " - "interrupt pipe (addr %d)\n", - sc->sc_intr_number); - return (EIO); - } - } - - return (0); -} - -static void -ubsa_close(void *addr, int portno) -{ - struct ubsa_softc *sc; - int err; - - sc = addr; - if (sc->sc_ucom.sc_dying) - return; - - DPRINTF(("ubsa_close: close\n")); - - if (sc->sc_intr_pipe != NULL) { - err = usbd_abort_pipe(sc->sc_intr_pipe); - if (err) - device_printf(sc->sc_ucom.sc_dev, "abort interrupt " - "pipe failed: %s\n", usbd_errstr(err)); - err = usbd_close_pipe(sc->sc_intr_pipe); - if (err) - device_printf(sc->sc_ucom.sc_dev, "close interrupt " - "pipe failed: %s\n", usbd_errstr(err)); - kfree(sc->sc_intr_buf, M_USBDEV); - sc->sc_intr_pipe = NULL; - } -} - -static void -ubsa_intr(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status) -{ - struct ubsa_softc *sc; - u_char *buf; - - sc = priv; - buf = sc->sc_intr_buf; - if (sc->sc_ucom.sc_dying) - return; - - if (status != USBD_NORMAL_COMPLETION) { - if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) - return; - - DPRINTF(("%s: ubsa_intr: abnormal status: %s\n", - device_get_nameunit(sc->sc_ucom.sc_dev), - usbd_errstr(status))); - usbd_clear_endpoint_stall_async(sc->sc_intr_pipe); - return; - } - - /* incidentally, Belkin adapter status bits match UART 16550 bits */ - sc->sc_lsr = buf[2]; - sc->sc_msr = buf[3]; - - DPRINTF(("%s: ubsa lsr = 0x%02x, msr = 0x%02x\n", - device_get_nameunit(sc->sc_ucom.sc_dev), sc->sc_lsr, sc->sc_msr)); - - ubsa_notify(sc); -} - -/* Handle delayed events. */ -static void -ubsa_notify(void *arg) -{ - struct ubsa_softc *sc; - - sc = arg; - ucom_status_change(&sc->sc_ucom); -} - -static void -ubsa_get_status(void *addr, int portno, u_char *lsr, u_char *msr) -{ - struct ubsa_softc *sc; - - DPRINTF(("ubsa_get_status\n")); - - sc = addr; - if (lsr != NULL) - *lsr = sc->sc_lsr; - if (msr != NULL) - *msr = sc->sc_msr; -} diff --git a/sys/dev/usbmisc/ubt/Makefile b/sys/dev/usbmisc/ubt/Makefile deleted file mode 100644 index c50d742b4d..0000000000 --- a/sys/dev/usbmisc/ubt/Makefile +++ /dev/null @@ -1,6 +0,0 @@ -# $DragonFly: src/sys/dev/usbmisc/ubt/Makefile,v 1.1 2007/12/30 20:02:56 hasso Exp $ - -KMOD= ubt -SRCS= ubt.c opt_usb.h bus_if.h device_if.h - -.include diff --git a/sys/dev/usbmisc/ubt/ubt.c b/sys/dev/usbmisc/ubt/ubt.c deleted file mode 100644 index e336babf93..0000000000 --- a/sys/dev/usbmisc/ubt/ubt.c +++ /dev/null @@ -1,1669 +0,0 @@ -/* $OpenBSD: src/sys/dev/usb/ubt.c,v 1.11 2008/02/24 21:34:48 uwe Exp $ */ -/* $NetBSD: ubt.c,v 1.30 2007/12/16 19:01:37 christos Exp $ */ - -/*- - * Copyright (c) 2006 Itronix Inc. - * All rights reserved. - * - * Written by Iain Hibbert for Itronix Inc. - * - * 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. - * 3. The name of Itronix Inc. may not be used to endorse - * or promote products derived from this software without specific - * prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY ITRONIX INC. ``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 ITRONIX INC. 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. - */ -/* - * Copyright (c) 2002, 2003 The NetBSD Foundation, Inc. - * All rights reserved. - * - * This code is derived from software contributed to The NetBSD Foundation - * by Lennart Augustsson (lennart@augustsson.net) and - * David Sainty (David.Sainty@dtsp.co.nz). - * - * 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. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the NetBSD - * Foundation, Inc. and its contributors. - * 4. Neither the name of The NetBSD Foundation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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. - */ -/* - * This driver originally written by Lennart Augustsson and David Sainty, - * but was mostly rewritten for the NetBSD Bluetooth protocol stack by - * Iain Hibbert for Itronix, Inc using the FreeBSD ng_ubt.c driver as a - * reference. - */ - -#include -#include -#include -#include - -#include -#include -#include -#include - -#include -#include - -/******************************************************************************* - * - * debugging stuff - */ -#undef DPRINTF -#undef DPRINTFN - -#ifdef UBT_DEBUG -int ubt_debug = UBT_DEBUG; - -#define DPRINTF(fmt, args...) do { \ - if (ubt_debug) \ - kprintf("%s: "fmt, __func__ , ##args); \ -} while (/* CONSTCOND */0) - -#define DPRINTFN(n, fmt, args...) do { \ - if (ubt_debug > (n)) \ - kprintf("%s: "fmt, __func__ , ##args); \ -} while (/* CONSTCOND */0) - -#else -#define DPRINTF(...) -#define DPRINTFN(...) -#endif - -/******************************************************************************* - * - * ubt softc structure - * - */ - -/* buffer sizes */ -/* - * NB: although ACL packets can extend to 65535 bytes, most devices - * have max_acl_size at much less (largest I have seen is 384) - */ -#define UBT_BUFSIZ_CMD (HCI_CMD_PKT_SIZE - 1) -#define UBT_BUFSIZ_ACL (2048 - 1) -#define UBT_BUFSIZ_EVENT (HCI_EVENT_PKT_SIZE - 1) - -/* Transmit timeouts */ - -#define UBT_CMD_TIMEOUT 100 -#define UBT_ACL_TIMEOUT 100 - -/* - * Specification says, that is must be 1ms, but it causes kernel panic. - * Setting interval to USBD_DEFAULT_INTERVAL is not working for some of - * us either. - * XXX: Make it sysctl. - */ -#define UBT_INTR_TIMEOUT USBD_DEFAULT_INTERVAL - -/* - * ISOC transfers - * - * xfer buffer size depends on the frame size, and the number - * of frames per transfer is fixed, as each frame should be - * 1ms worth of data. This keeps the rate that xfers complete - * fairly constant. We use multiple xfers to keep the hardware - * busy - */ -#define UBT_NXFERS 3 /* max xfers to queue */ -#define UBT_NFRAMES 10 /* frames per xfer */ - -struct ubt_isoc_xfer { - struct ubt_softc *softc; - usbd_xfer_handle xfer; - uint8_t *buf; - uint16_t size[UBT_NFRAMES]; - int busy; -}; - -struct ubt_softc { - device_t sc_dev; - usbd_device_handle sc_udev; - int sc_refcnt; - int sc_dying; - int sc_enabled; - - /* Control Interface */ - usbd_interface_handle sc_iface0; - - /* Commands (control) */ - usbd_xfer_handle sc_cmd_xfer; - u_char *sc_cmd_buf; - int sc_cmd_busy; /* write active */ - struct ifqueue sc_cmd_queue; /* output queue */ - - /* Events (interrupt) */ - int sc_evt_addr; /* endpoint address */ - usbd_pipe_handle sc_evt_pipe; - u_char *sc_evt_buf; - - - /* ACL data (in) */ - int sc_aclrd_addr; /* endpoint address */ - usbd_pipe_handle sc_aclrd_pipe; /* read pipe */ - usbd_xfer_handle sc_aclrd_xfer; /* read xfer */ - u_char *sc_aclrd_buf; /* read buffer */ - int sc_aclrd_busy; /* reading */ - - /* ACL data (out) */ - int sc_aclwr_addr; /* endpoint address */ - usbd_pipe_handle sc_aclwr_pipe; /* write pipe */ - usbd_xfer_handle sc_aclwr_xfer; /* write xfer */ - u_char *sc_aclwr_buf; /* write buffer */ - int sc_aclwr_busy; /* write active */ - struct ifqueue sc_aclwr_queue;/* output queue */ - - /* ISOC interface */ - usbd_interface_handle sc_iface1; /* ISOC interface */ - struct sysctllog *sc_log; /* sysctl log */ - int sc_config; /* current config no */ - int sc_alt_config; /* no of alternates */ - - /* SCO data (in) */ - int sc_scord_addr; /* endpoint address */ - usbd_pipe_handle sc_scord_pipe; /* read pipe */ - int sc_scord_size; /* frame length */ - struct ubt_isoc_xfer sc_scord[UBT_NXFERS]; - struct mbuf *sc_scord_mbuf; /* current packet */ - - /* SCO data (out) */ - int sc_scowr_addr; /* endpoint address */ - usbd_pipe_handle sc_scowr_pipe; /* write pipe */ - int sc_scowr_size; /* frame length */ - struct ubt_isoc_xfer sc_scowr[UBT_NXFERS]; - struct mbuf *sc_scowr_mbuf; /* current packet */ - int sc_scowr_busy; /* write active */ - struct ifqueue sc_scowr_queue;/* output queue */ - - /* Protocol structure */ - struct hci_unit *sc_unit; - struct bt_stats sc_stats; - - /* Successfully attached */ - int sc_ok; - - struct sysctl_ctx_list sysctl_ctx; - struct sysctl_oid *sysctl_tree; -}; - -/* - * Bluetooth unit/USB callback routines - */ -int ubt_enable(struct device *); -void ubt_disable(struct device *); - -void ubt_xmit_cmd(struct device *, struct mbuf *); -void ubt_xmit_cmd_start(struct ubt_softc *); -void ubt_xmit_cmd_complete(usbd_xfer_handle, - usbd_private_handle, usbd_status); - -void ubt_xmit_acl(struct device *, struct mbuf *); -void ubt_xmit_acl_start(struct ubt_softc *); -void ubt_xmit_acl_complete(usbd_xfer_handle, - usbd_private_handle, usbd_status); - -void ubt_xmit_sco(struct device *, struct mbuf *); -void ubt_xmit_sco_start(struct ubt_softc *); -void ubt_xmit_sco_start1(struct ubt_softc *, struct ubt_isoc_xfer *); -void ubt_xmit_sco_complete(usbd_xfer_handle, - usbd_private_handle, usbd_status); - -void ubt_recv_event(usbd_xfer_handle, - usbd_private_handle, usbd_status); - -void ubt_recv_acl_start(struct ubt_softc *); -void ubt_recv_acl_complete(usbd_xfer_handle, - usbd_private_handle, usbd_status); - -void ubt_recv_sco_start1(struct ubt_softc *, struct ubt_isoc_xfer *); -void ubt_recv_sco_complete(usbd_xfer_handle, - usbd_private_handle, usbd_status); - -void ubt_stats(struct device *, struct bt_stats *, int); - -static device_probe_t ubt_match; -static device_attach_t ubt_attach; -static device_detach_t ubt_detach; - -static devclass_t ubt_devclass; - -static device_method_t ubt_methods[] = { - DEVMETHOD(device_probe, ubt_match), - DEVMETHOD(device_attach, ubt_attach), - DEVMETHOD(device_detach, ubt_detach), - DEVMETHOD_END -}; - -static driver_t ubt_driver = { - "ubt", - ubt_methods, - sizeof(struct ubt_softc) -}; - -DRIVER_MODULE(ubt, uhub, ubt_driver, ubt_devclass, usbd_driver_load, NULL); -MODULE_DEPEND(ubt, netbt, 1, 1, 1); -#if 0 /* not yet */ -MODULE_DEPEND(ubt, bthub, 1, 1, 1); -#endif -MODULE_DEPEND(ubt, usb, 1, 1, 1); - -const struct hci_if ubt_hci = { - .enable = ubt_enable, - .disable = ubt_disable, - .output_cmd = ubt_xmit_cmd, - .output_acl = ubt_xmit_acl, - .output_sco = ubt_xmit_sco, - .get_stats = ubt_stats, -}; - -static int ubt_set_isoc_config(struct ubt_softc *); -static int ubt_sysctl_config(SYSCTL_HANDLER_ARGS); -static void ubt_abortdealloc(struct ubt_softc *); - -/* - * Match against the whole device, since we want to take - * both interfaces. If a device should be ignored then add - * - * { VendorID, ProductID } - * - * to the ubt_ignore list. - */ -static const struct usb_devno ubt_ignore[] = { - { USB_DEVICE(0x0a5c, 0x2033) }, /* Broadcom BCM2033 */ - { 0, 0 } /* end of list */ -}; - -static int -ubt_match(device_t self) -{ - struct usb_attach_arg *uaa = device_get_ivars(self); - usb_device_descriptor_t *dd = usbd_get_device_descriptor(uaa->device); - - DPRINTFN(50, "ubt_match\n"); - - if (usb_lookup(ubt_ignore, uaa->vendor, uaa->product)) - return UMATCH_NONE; - - if (dd->bDeviceClass == UDCLASS_WIRELESS - && dd->bDeviceSubClass == UDSUBCLASS_RF - && dd->bDeviceProtocol == UDPROTO_BLUETOOTH) - return UMATCH_DEVCLASS_DEVSUBCLASS_DEVPROTO; - return UMATCH_NONE; -} - -static int -ubt_attach(device_t self) -{ - struct ubt_softc *sc = device_get_softc(self); - struct usb_attach_arg *uaa = device_get_ivars(self); - - usb_config_descriptor_t *cd; - usb_endpoint_descriptor_t *ed; - int err; - uint8_t count, i; - - DPRINTFN(50, "ubt_attach: sc=%p\n", sc); - - sc->sc_udev = uaa->device; - sc->sc_dev = self; - - /* - * Move the device into the configured state - */ - err = usbd_set_config_index(sc->sc_udev, 0, 1); - if (err) { - kprintf("%s: failed to set configuration idx 0: %s\n", - device_get_nameunit(sc->sc_dev), usbd_errstr(err)); - - return ENXIO; - } - - /* - * Interface 0 must have 3 endpoints - * 1) Interrupt endpoint to receive HCI events - * 2) Bulk IN endpoint to receive ACL data - * 3) Bulk OUT endpoint to send ACL data - */ - err = usbd_device2interface_handle(sc->sc_udev, 0, &sc->sc_iface0); - if (err) { - kprintf("%s: Could not get interface 0 handle %s (%d)\n", - device_get_nameunit(sc->sc_dev), usbd_errstr(err), err); - - return ENXIO; - } - - sc->sc_evt_addr = -1; - sc->sc_aclrd_addr = -1; - sc->sc_aclwr_addr = -1; - - count = 0; - (void)usbd_endpoint_count(sc->sc_iface0, &count); - - for (i = 0 ; i < count ; i++) { - int dir, type; - - ed = usbd_interface2endpoint_descriptor(sc->sc_iface0, i); - if (ed == NULL) { - kprintf("%s: could not read endpoint descriptor %d\n", - device_get_nameunit(sc->sc_dev), i); - - return ENXIO; - } - - dir = UE_GET_DIR(ed->bEndpointAddress); - type = UE_GET_XFERTYPE(ed->bmAttributes); - - if (dir == UE_DIR_IN && type == UE_INTERRUPT) - sc->sc_evt_addr = ed->bEndpointAddress; - else if (dir == UE_DIR_IN && type == UE_BULK) - sc->sc_aclrd_addr = ed->bEndpointAddress; - else if (dir == UE_DIR_OUT && type == UE_BULK) - sc->sc_aclwr_addr = ed->bEndpointAddress; - } - - if (sc->sc_evt_addr == -1) { - kprintf("%s: missing INTERRUPT endpoint on interface 0\n", - device_get_nameunit(sc->sc_dev)); - - return ENXIO; - } - if (sc->sc_aclrd_addr == -1) { - kprintf("%s: missing BULK IN endpoint on interface 0\n", - device_get_nameunit(sc->sc_dev)); - - return ENXIO; - } - if (sc->sc_aclwr_addr == -1) { - kprintf("%s: missing BULK OUT endpoint on interface 0\n", - device_get_nameunit(sc->sc_dev)); - - return ENXIO; - } - - /* - * Interface 1 must have 2 endpoints - * 1) Isochronous IN endpoint to receive SCO data - * 2) Isochronous OUT endpoint to send SCO data - * - * and will have several configurations, which can be selected - * via a sysctl variable. We select config 0 to start, which - * means that no SCO data will be available. - */ - err = usbd_device2interface_handle(sc->sc_udev, 1, &sc->sc_iface1); - if (err) { - kprintf("%s: Could not get interface 1 handle %s (%d)\n", - device_get_nameunit(sc->sc_dev), usbd_errstr(err), err); - - return ENXIO; - } - - cd = usbd_get_config_descriptor(sc->sc_udev); - if (cd == NULL) { - kprintf("%s: could not get config descriptor\n", - device_get_nameunit(sc->sc_dev)); - - return ENXIO; - } - - sc->sc_alt_config = usbd_get_no_alts(cd, 1); - - /* set initial config */ - err = ubt_set_isoc_config(sc); - if (err) { - kprintf("%s: ISOC config failed\n", - device_get_nameunit(sc->sc_dev)); - - return ENXIO; - } - - /* Attach HCI */ - sc->sc_unit = hci_attach(&ubt_hci, sc->sc_dev, 0); - - usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev, - sc->sc_dev); - - sc->sc_ok = 1; - - sysctl_ctx_init(&sc->sysctl_ctx); - sc->sysctl_tree = SYSCTL_ADD_NODE(&sc->sysctl_ctx, - SYSCTL_STATIC_CHILDREN(_hw), - OID_AUTO, - device_get_nameunit(sc->sc_dev), - CTLFLAG_RD, 0, ""); - - if (sc->sysctl_tree == NULL) { - /* Failure isn't fatal */ - device_printf(sc->sc_dev, "Unable to create sysctl tree\n"); - return 0; - } - - SYSCTL_ADD_PROC(&sc->sysctl_ctx, SYSCTL_CHILDREN(sc->sysctl_tree), - OID_AUTO, "config", CTLTYPE_INT|CTLFLAG_RW, (void *)sc, - 0, ubt_sysctl_config, "I", "Configuration number"); - SYSCTL_ADD_INT(&sc->sysctl_ctx, SYSCTL_CHILDREN(sc->sysctl_tree), - OID_AUTO, "alt_config", CTLFLAG_RD, &sc->sc_alt_config, - 0, "Number of alternate configurations"); - SYSCTL_ADD_INT(&sc->sysctl_ctx, SYSCTL_CHILDREN(sc->sysctl_tree), - OID_AUTO, "sco_rxsize", CTLFLAG_RD, &sc->sc_scord_size, - 0, "Max SCO receive size"); - SYSCTL_ADD_INT(&sc->sysctl_ctx, SYSCTL_CHILDREN(sc->sysctl_tree), - OID_AUTO, "sco_wrsize", CTLFLAG_RD, &sc->sc_scowr_size, - 0, "Max SCO transmit size"); - - return 0; -} - -static int -ubt_detach(device_t self) -{ - - struct ubt_softc *sc = device_get_softc(self); - - DPRINTF("sc=%p \n", sc); - - sc->sc_dying = 1; - - if (!sc->sc_ok) - return 0; - - /* Detach HCI interface */ - if (sc->sc_unit) { - hci_detach(sc->sc_unit); - sc->sc_unit = NULL; - } - - /* - * Abort all pipes. Causes processes waiting for transfer to wake. - * - * Actually, hci_detach() above will call ubt_disable() which may - * call ubt_abortdealloc(), but lets be sure since doing it twice - * wont cause an error. - */ - ubt_abortdealloc(sc); - - /* wait for all processes to finish */ - if (sc->sc_refcnt-- > 0) - usb_detach_wait(sc->sc_dev); - - if (sc->sysctl_tree != NULL) { - sc->sysctl_tree = NULL; - sysctl_ctx_free(&sc->sysctl_ctx); - } - - usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev, - sc->sc_dev); - - DPRINTFN(1, "driver detached\n"); - - return 0; -} - -/* set ISOC configuration */ -int -ubt_set_isoc_config(struct ubt_softc *sc) -{ - usb_endpoint_descriptor_t *ed; - int rd_addr, wr_addr, rd_size, wr_size; - uint8_t count, i; - int err; - - err = usbd_set_interface(sc->sc_iface1, sc->sc_config); - if (err != USBD_NORMAL_COMPLETION) { - kprintf( - "%s: Could not set config %d on ISOC interface. %s (%d)\n", - device_get_nameunit(sc->sc_dev), sc->sc_config, usbd_errstr(err), err); - - return err == USBD_IN_USE ? EBUSY : EIO; - } - - /* - * We wont get past the above if there are any pipes open, so no - * need to worry about buf/xfer/pipe deallocation. If we get an - * error after this, the frame quantities will be 0 and no SCO - * data will be possible. - */ - - sc->sc_scord_size = rd_size = 0; - sc->sc_scord_addr = rd_addr = -1; - - sc->sc_scowr_size = wr_size = 0; - sc->sc_scowr_addr = wr_addr = -1; - - count = 0; - (void)usbd_endpoint_count(sc->sc_iface1, &count); - - for (i = 0 ; i < count ; i++) { - ed = usbd_interface2endpoint_descriptor(sc->sc_iface1, i); - if (ed == NULL) { - kprintf("%s: could not read endpoint descriptor %d\n", - device_get_nameunit(sc->sc_dev), i); - - return EIO; - } - - DPRINTFN(5, "%s: endpoint type %02x (%02x) addr %02x (%s)\n", - device_get_nameunit(sc->sc_dev), - UE_GET_XFERTYPE(ed->bmAttributes), - UE_GET_ISO_TYPE(ed->bmAttributes), - ed->bEndpointAddress, - UE_GET_DIR(ed->bEndpointAddress) ? "in" : "out"); - - if (UE_GET_XFERTYPE(ed->bmAttributes) != UE_ISOCHRONOUS) - continue; - - if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN) { - rd_addr = ed->bEndpointAddress; - rd_size = UGETW(ed->wMaxPacketSize); - } else { - wr_addr = ed->bEndpointAddress; - wr_size = UGETW(ed->wMaxPacketSize); - } - } - - if (rd_addr == -1) { - kprintf( - "%s: missing ISOC IN endpoint on interface config %d\n", - device_get_nameunit(sc->sc_dev), sc->sc_config); - - return ENOENT; - } - if (wr_addr == -1) { - kprintf( - "%s: missing ISOC OUT endpoint on interface config %d\n", - device_get_nameunit(sc->sc_dev), sc->sc_config); - - return ENOENT; - } - -#ifdef DIAGNOSTIC - if (rd_size > MLEN) { - kprintf("%s: rd_size=%d exceeds MLEN\n", - device_get_nameunit(sc->sc_dev), rd_size); - - return EOVERFLOW; - } - - if (wr_size > MLEN) { - kprintf("%s: wr_size=%d exceeds MLEN\n", - device_get_nameunit(sc->sc_dev), wr_size); - - return EOVERFLOW; - } -#endif - - sc->sc_scord_size = rd_size; - sc->sc_scord_addr = rd_addr; - - sc->sc_scowr_size = wr_size; - sc->sc_scowr_addr = wr_addr; - - return 0; -} - -static int -ubt_sysctl_config(SYSCTL_HANDLER_ARGS) -{ - struct ubt_softc *sc = (struct ubt_softc *)arg1; - int t, error; - - t = sc->sc_config; - error = sysctl_handle_int(oidp, &t, 0, req); - if (error || req->newptr == NULL) - return error; - - if (t < 0 || t >= sc->sc_alt_config) - return EINVAL; - - /* This may not change when the unit is enabled */ - if (sc->sc_enabled) - return EBUSY; - - sc->sc_config = t; - return ubt_set_isoc_config(sc); -} - -void -ubt_abortdealloc(struct ubt_softc *sc) -{ - int i; - - DPRINTFN(1, "sc=%p\n", sc); - - crit_enter(); - /* Abort all pipes */ - if (sc->sc_evt_pipe != NULL) { - usbd_abort_pipe(sc->sc_evt_pipe); - usbd_close_pipe(sc->sc_evt_pipe); - sc->sc_evt_pipe = NULL; - } - - if (sc->sc_aclrd_pipe != NULL) { - usbd_abort_pipe(sc->sc_aclrd_pipe); - usbd_close_pipe(sc->sc_aclrd_pipe); - sc->sc_aclrd_pipe = NULL; - } - - if (sc->sc_aclwr_pipe != NULL) { - usbd_abort_pipe(sc->sc_aclwr_pipe); - usbd_close_pipe(sc->sc_aclwr_pipe); - sc->sc_aclwr_pipe = NULL; - } - - if (sc->sc_scord_pipe != NULL) { - usbd_abort_pipe(sc->sc_scord_pipe); - usbd_close_pipe(sc->sc_scord_pipe); - sc->sc_scord_pipe = NULL; - } - - if (sc->sc_scowr_pipe != NULL) { - usbd_abort_pipe(sc->sc_scowr_pipe); - usbd_close_pipe(sc->sc_scowr_pipe); - sc->sc_scowr_pipe = NULL; - } - - /* Free event buffer */ - if (sc->sc_evt_buf != NULL) { - kfree(sc->sc_evt_buf, M_USBDEV); - sc->sc_evt_buf = NULL; - } - - /* Free all xfers and xfer buffers (implicit) */ - if (sc->sc_cmd_xfer != NULL) { - usbd_free_xfer(sc->sc_cmd_xfer); - sc->sc_cmd_xfer = NULL; - sc->sc_cmd_buf = NULL; - } - - if (sc->sc_aclrd_xfer != NULL) { - usbd_free_xfer(sc->sc_aclrd_xfer); - sc->sc_aclrd_xfer = NULL; - sc->sc_aclrd_buf = NULL; - } - - if (sc->sc_aclwr_xfer != NULL) { - usbd_free_xfer(sc->sc_aclwr_xfer); - sc->sc_aclwr_xfer = NULL; - sc->sc_aclwr_buf = NULL; - } - - for (i = 0 ; i < UBT_NXFERS ; i++) { - if (sc->sc_scord[i].xfer != NULL) { - usbd_free_xfer(sc->sc_scord[i].xfer); - sc->sc_scord[i].xfer = NULL; - sc->sc_scord[i].buf = NULL; - } - - if (sc->sc_scowr[i].xfer != NULL) { - usbd_free_xfer(sc->sc_scowr[i].xfer); - sc->sc_scowr[i].xfer = NULL; - sc->sc_scowr[i].buf = NULL; - } - } - - /* Free partial SCO packets */ - if (sc->sc_scord_mbuf != NULL) { - m_freem(sc->sc_scord_mbuf); - sc->sc_scord_mbuf = NULL; - } - - if (sc->sc_scowr_mbuf != NULL) { - m_freem(sc->sc_scowr_mbuf); - sc->sc_scowr_mbuf = NULL; - } - - /* Empty mbuf queues */ - IF_DRAIN(&sc->sc_cmd_queue); - IF_DRAIN(&sc->sc_aclwr_queue); - IF_DRAIN(&sc->sc_scowr_queue); - - crit_exit(); -} - -/******************************************************************************* - * - * Bluetooth Unit/USB callbacks - * - * All of this will be called at the IPL_ we specified above - */ -int -ubt_enable(struct device *self) -{ - struct ubt_softc *sc = device_get_softc(self); - usbd_status err; - int i, error; - - DPRINTFN(1, "%s: sc=%p\n", __func__, sc); - - if (sc->sc_enabled) - return 0; - - crit_enter(); - - /* Events */ - sc->sc_evt_buf = kmalloc(UBT_BUFSIZ_EVENT, M_USBDEV, M_NOWAIT); - if (sc->sc_evt_buf == NULL) { - error = ENOMEM; - goto bad; - } - - err = usbd_open_pipe_intr(sc->sc_iface0, - sc->sc_evt_addr, - USBD_SHORT_XFER_OK, - &sc->sc_evt_pipe, - sc, - sc->sc_evt_buf, - UBT_BUFSIZ_EVENT, - ubt_recv_event, - UBT_INTR_TIMEOUT); - if (err != USBD_NORMAL_COMPLETION) { - error = EIO; - kprintf("can't open events pipe_intr\n"); - goto bad; - } - - /* Commands */ - sc->sc_cmd_xfer = usbd_alloc_xfer(sc->sc_udev); - if (sc->sc_cmd_xfer == NULL) { - kprintf("can't allocate cmd_xfer\n"); - error = ENOMEM; - goto bad; - } - sc->sc_cmd_buf = usbd_alloc_buffer(sc->sc_cmd_xfer, UBT_BUFSIZ_CMD); - if (sc->sc_cmd_buf == NULL) { - kprintf("can't allocate cmd_buf\n"); - error = ENOMEM; - goto bad; - } - sc->sc_cmd_busy = 0; - - /* ACL read */ - err = usbd_open_pipe(sc->sc_iface0, sc->sc_aclrd_addr, - USBD_EXCLUSIVE_USE, &sc->sc_aclrd_pipe); - if (err != USBD_NORMAL_COMPLETION) { - kprintf("can't open aclrd pipe\n"); - error = EIO; - goto bad; - } - sc->sc_aclrd_xfer = usbd_alloc_xfer(sc->sc_udev); - if (sc->sc_aclrd_xfer == NULL) { - kprintf("can't allocate aclrd_xfer\n"); - error = ENOMEM; - goto bad; - } - sc->sc_aclrd_buf = usbd_alloc_buffer(sc->sc_aclrd_xfer, UBT_BUFSIZ_ACL); - if (sc->sc_aclrd_buf == NULL) { - kprintf("can't allocate aclrd_buf\n"); - error = ENOMEM; - goto bad; - } - sc->sc_aclrd_busy = 0; - ubt_recv_acl_start(sc); - - /* ACL write */ - err = usbd_open_pipe(sc->sc_iface0, sc->sc_aclwr_addr, - USBD_EXCLUSIVE_USE, &sc->sc_aclwr_pipe); - if (err != USBD_NORMAL_COMPLETION) { - kprintf("can't open aclwr pipe\n"); - error = EIO; - goto bad; - } - sc->sc_aclwr_xfer = usbd_alloc_xfer(sc->sc_udev); - if (sc->sc_aclwr_xfer == NULL) { - kprintf("can't allocate aclwr_xfer\n"); - error = ENOMEM; - goto bad; - } - sc->sc_aclwr_buf = usbd_alloc_buffer(sc->sc_aclwr_xfer, UBT_BUFSIZ_ACL); - if (sc->sc_aclwr_buf == NULL) { - kprintf("can't allocate aclwr_buf\n"); - error = ENOMEM; - goto bad; - } - sc->sc_aclwr_busy = 0; - - /* SCO read */ - if (sc->sc_scord_size > 0) { - err = usbd_open_pipe(sc->sc_iface1, sc->sc_scord_addr, - USBD_EXCLUSIVE_USE, &sc->sc_scord_pipe); - if (err != USBD_NORMAL_COMPLETION) { - error = EIO; - goto bad; - } - - for (i = 0 ; i < UBT_NXFERS ; i++) { - sc->sc_scord[i].xfer = usbd_alloc_xfer(sc->sc_udev); - if (sc->sc_scord[i].xfer == NULL) { - error = ENOMEM; - goto bad; - } - sc->sc_scord[i].buf = usbd_alloc_buffer(sc->sc_scord[i].xfer, - sc->sc_scord_size * UBT_NFRAMES); - if (sc->sc_scord[i].buf == NULL) { - error = ENOMEM; - goto bad; - } - sc->sc_scord[i].softc = sc; - sc->sc_scord[i].busy = 0; - ubt_recv_sco_start1(sc, &sc->sc_scord[i]); - } - } - - /* SCO write */ - if (sc->sc_scowr_size > 0) { - err = usbd_open_pipe(sc->sc_iface1, sc->sc_scowr_addr, - USBD_EXCLUSIVE_USE, &sc->sc_scowr_pipe); - if (err != USBD_NORMAL_COMPLETION) { - error = EIO; - goto bad; - } - - for (i = 0 ; i < UBT_NXFERS ; i++) { - sc->sc_scowr[i].xfer = usbd_alloc_xfer(sc->sc_udev); - if (sc->sc_scowr[i].xfer == NULL) { - error = ENOMEM; - goto bad; - } - sc->sc_scowr[i].buf = usbd_alloc_buffer(sc->sc_scowr[i].xfer, - sc->sc_scowr_size * UBT_NFRAMES); - if (sc->sc_scowr[i].buf == NULL) { - error = ENOMEM; - goto bad; - } - sc->sc_scowr[i].softc = sc; - sc->sc_scowr[i].busy = 0; - } - - sc->sc_scowr_busy = 0; - } - - sc->sc_enabled = 1; - crit_exit(); - return 0; - -bad: - ubt_abortdealloc(sc); - crit_exit(); - return error; -} - -void -ubt_disable(struct device *self) -{ - struct ubt_softc *sc = device_get_softc(self); - - DPRINTFN(1, "sc=%p\n", sc); - - if (sc->sc_enabled == 0) - return; - - ubt_abortdealloc(sc); - sc->sc_enabled = 0; -} - -void -ubt_xmit_cmd(struct device *self, struct mbuf *m) -{ - struct ubt_softc *sc = device_get_softc(self); - - KKASSERT(sc->sc_enabled); - - crit_enter(); - IF_ENQUEUE(&sc->sc_cmd_queue, m); - - if (sc->sc_cmd_busy == 0) - ubt_xmit_cmd_start(sc); - - crit_exit(); -} - -void -ubt_xmit_cmd_start(struct ubt_softc *sc) -{ - usb_device_request_t req; - usbd_status status; - struct mbuf *m; - int len; - - if (sc->sc_dying) - return; - - if (IF_QEMPTY(&sc->sc_cmd_queue)) - return; - - IF_DEQUEUE(&sc->sc_cmd_queue, m); - KKASSERT(m != NULL); - DPRINTFN(15, " %s: xmit CMD packet (%d bytes)\n", - device_get_nameunit(sc->sc_dev), m->m_pkthdr.len); - - sc->sc_refcnt++; - - sc->sc_cmd_busy = 1; - - len = m->m_pkthdr.len - 1; - m_copydata(m, 1, len, sc->sc_cmd_buf); - m_freem(m); - - memset(&req, 0, sizeof(req)); - req.bmRequestType = UT_WRITE_CLASS_DEVICE; - USETW(req.wLength, len); - - usbd_setup_default_xfer(sc->sc_cmd_xfer, - sc->sc_udev, - sc, - UBT_CMD_TIMEOUT, - &req, - sc->sc_cmd_buf, - len, - USBD_NO_COPY | USBD_FORCE_SHORT_XFER, - ubt_xmit_cmd_complete); - - status = usbd_transfer(sc->sc_cmd_xfer); - - KKASSERT(status != USBD_NORMAL_COMPLETION); - - if (status != USBD_IN_PROGRESS) { - DPRINTF("usbd_transfer status=%s (%d)\n", - usbd_errstr(status), status); - sc->sc_refcnt--; - sc->sc_cmd_busy = 0; - } - -} - -void -ubt_xmit_cmd_complete(usbd_xfer_handle xfer, - usbd_private_handle h, usbd_status status) -{ - struct ubt_softc *sc = h; - uint32_t count; - - DPRINTFN(15, " %s: CMD complete status=%s (%d)\n", - device_get_nameunit(sc->sc_dev), usbd_errstr(status), status); - - sc->sc_cmd_busy = 0; - - if (--sc->sc_refcnt < 0) { - DPRINTF("sc_refcnt=%d\n", sc->sc_refcnt); - usb_detach_wakeup(sc->sc_dev); - return; - } - - if (sc->sc_dying) { - DPRINTF("sc_dying\n"); - return; - } - - if (status != USBD_NORMAL_COMPLETION) { - DPRINTF("status=%s (%d)\n", - usbd_errstr(status), status); - sc->sc_stats.err_tx++; - return; - } - - usbd_get_xfer_status(xfer, NULL, NULL, &count, NULL); - sc->sc_stats.cmd_tx++; - sc->sc_stats.byte_tx += count; - - ubt_xmit_cmd_start(sc); -} - -void -ubt_xmit_acl(struct device *self, struct mbuf *m) -{ - struct ubt_softc *sc = device_get_softc(self); - - KKASSERT(sc->sc_enabled); - - crit_enter(); - IF_ENQUEUE(&sc->sc_aclwr_queue, m); - - if (sc->sc_aclwr_busy == 0) - ubt_xmit_acl_start(sc); - - crit_exit(); -} - -void -ubt_xmit_acl_start(struct ubt_softc *sc) -{ - struct mbuf *m; - usbd_status status; - int len; - - if (sc->sc_dying) - return; - - - if (IF_QEMPTY(&sc->sc_aclwr_queue)) - return; - - sc->sc_refcnt++; - sc->sc_aclwr_busy = 1; - - IF_DEQUEUE(&sc->sc_aclwr_queue, m); - KKASSERT(m != NULL); - - DPRINTFN(15, "%s: xmit ACL packet (%d bytes)\n", - device_get_nameunit(sc->sc_dev), m->m_pkthdr.len); - - len = m->m_pkthdr.len - 1; - if (len > UBT_BUFSIZ_ACL) { - DPRINTF("%s: truncating ACL packet (%d => %d)!\n", - device_get_nameunit(sc->sc_dev), len, UBT_BUFSIZ_ACL); - - len = UBT_BUFSIZ_ACL; - } - - m_copydata(m, 1, len, sc->sc_aclwr_buf); - m_freem(m); - - sc->sc_stats.acl_tx++; - sc->sc_stats.byte_tx += len; - - usbd_setup_xfer(sc->sc_aclwr_xfer, - sc->sc_aclwr_pipe, - sc, - sc->sc_aclwr_buf, - len, - USBD_NO_COPY | USBD_FORCE_SHORT_XFER, - UBT_ACL_TIMEOUT, - ubt_xmit_acl_complete); - - status = usbd_transfer(sc->sc_aclwr_xfer); - - KKASSERT(status != USBD_NORMAL_COMPLETION); - - if (status != USBD_IN_PROGRESS) { - DPRINTF("usbd_transfer status=%s (%d)\n", - usbd_errstr(status), status); - - sc->sc_refcnt--; - sc->sc_aclwr_busy = 0; - } - -} - -void -ubt_xmit_acl_complete(usbd_xfer_handle xfer, - usbd_private_handle h, usbd_status status) -{ - struct ubt_softc *sc = h; - - DPRINTFN(15, "%s: ACL complete status=%s (%d)\n", - device_get_nameunit(sc->sc_dev), usbd_errstr(status), status); - - sc->sc_aclwr_busy = 0; - - if (--sc->sc_refcnt < 0) { - usb_detach_wakeup(sc->sc_dev); - return; - } - - if (sc->sc_dying) - return; - - if (status != USBD_NORMAL_COMPLETION) { - DPRINTF("status=%s (%d)\n", - usbd_errstr(status), status); - - sc->sc_stats.err_tx++; - - if (status == USBD_STALLED) - usbd_clear_endpoint_stall_async(sc->sc_aclwr_pipe); - else - return; - } - - ubt_xmit_acl_start(sc); - -} - -void -ubt_xmit_sco(struct device *self, struct mbuf *m) -{ - struct ubt_softc *sc = device_get_softc(self); - - KKASSERT(sc->sc_enabled); - - crit_enter(); - IF_ENQUEUE(&sc->sc_scowr_queue, m); - - if (sc->sc_scowr_busy == 0) - ubt_xmit_sco_start(sc); - - crit_exit(); -} - -void -ubt_xmit_sco_start(struct ubt_softc *sc) -{ - int i; - - if (sc->sc_dying || sc->sc_scowr_size == 0) - return; - - for (i = 0 ; i < UBT_NXFERS ; i++) { - if (sc->sc_scowr[i].busy) - continue; - - ubt_xmit_sco_start1(sc, &sc->sc_scowr[i]); - } -} - -void -ubt_xmit_sco_start1(struct ubt_softc *sc, struct ubt_isoc_xfer *isoc) -{ - struct mbuf *m; - uint8_t *buf; - int num, len, size, space; - - if (sc->sc_dying) - return; - - space = sc->sc_scowr_size * UBT_NFRAMES; - buf = isoc->buf; - len = 0; - - /* - * Fill the request buffer with data from the queue, - * keeping any leftover packet on our private hook. - * - * Complete packets are passed back up to the stack - * for disposal, since we can't rely on the controller - * to tell us when it has finished with them. - */ - - m = sc->sc_scowr_mbuf; - while (space > 0) { - if (m == NULL) { - crit_enter(); - IF_DEQUEUE(&sc->sc_scowr_queue, m); - crit_exit(); - if (m == NULL) - break; - - m_adj(m, 1); /* packet type */ - - } - - if (m->m_pkthdr.len > 0) { - size = MIN(m->m_pkthdr.len, space); - - m_copydata(m, 0, size, buf); - m_adj(m, size); - - buf += size; - len += size; - space -= size; - } - - if (m->m_pkthdr.len == 0) { - sc->sc_stats.sco_tx++; - if (!hci_complete_sco(sc->sc_unit, m)) - sc->sc_stats.err_tx++; - - m = NULL; - } - } - sc->sc_scowr_mbuf = m; - - DPRINTFN(15, "isoc=%p, len=%d, space=%d\n", isoc, len, space); - - if (len == 0) /* nothing to send */ - - return; - - sc->sc_refcnt++; - sc->sc_scowr_busy = 1; - sc->sc_stats.byte_tx += len; - isoc->busy = 1; - - /* - * calculate number of isoc frames and sizes - */ - - for (num = 0 ; len > 0 ; num++) { - size = MIN(sc->sc_scowr_size, len); - - isoc->size[num] = size; - len -= size; - } - - usbd_setup_isoc_xfer(isoc->xfer, - sc->sc_scowr_pipe, - isoc, - isoc->size, - num, - USBD_NO_COPY | USBD_FORCE_SHORT_XFER, - ubt_xmit_sco_complete); - - usbd_transfer(isoc->xfer); -} - -void -ubt_xmit_sco_complete(usbd_xfer_handle xfer, - usbd_private_handle h, usbd_status status) -{ - struct ubt_isoc_xfer *isoc = h; - struct ubt_softc *sc; - int i; - - KKASSERT(xfer == isoc->xfer); - sc = isoc->softc; - - DPRINTFN(15, "isoc=%p, status=%s (%d)\n", - isoc, usbd_errstr(status), status); - - isoc->busy = 0; - - for (i = 0 ; ; i++) { - if (i == UBT_NXFERS) { - sc->sc_scowr_busy = 0; - break; - } - - if (sc->sc_scowr[i].busy) - break; - } - - if (--sc->sc_refcnt < 0) { - usb_detach_wakeup(sc->sc_dev); - return; - } - - if (sc->sc_dying) - return; - - if (status != USBD_NORMAL_COMPLETION) { - DPRINTF("status=%s (%d)\n", - usbd_errstr(status), status); - - sc->sc_stats.err_tx++; - - if (status == USBD_STALLED) - usbd_clear_endpoint_stall_async(sc->sc_scowr_pipe); - else - return; - } - - ubt_xmit_sco_start(sc); -} - -/* - * Load incoming data into an mbuf with leading type byte. - */ -static struct mbuf * -ubt_mbufload(uint8_t *buf, int count, uint8_t type) -{ - struct mbuf *m; - MGETHDR(m, MB_DONTWAIT, MT_DATA); - if (m == NULL) {kprintf(" MGETHDR return NULL\n"); - return NULL; } - *mtod(m, uint8_t *) = type; - m->m_pkthdr.len = m->m_len = MHLEN; - m_copyback(m, 1, count, buf); /* (extends if necessary)*/ - if (m->m_pkthdr.len != MAX(MHLEN, count + 1)) { - m_free(m); - kprintf(" m->m_pkthdr.len != MAX() \n"); - return NULL; - } - m->m_pkthdr.len = count + 1; - m->m_len = MIN(MHLEN, m->m_pkthdr.len); - return m; -} - -void -ubt_recv_event(usbd_xfer_handle xfer, usbd_private_handle h, usbd_status status) -{ - struct ubt_softc *sc = h; - struct mbuf *m; - uint32_t count; - void *buf; - - DPRINTFN(15, "sc=%p status=%s (%d)\n", - sc, usbd_errstr(status), status); - - if (status != USBD_NORMAL_COMPLETION || sc->sc_dying) - return; - - usbd_get_xfer_status(xfer, NULL, &buf, &count, NULL); - - if (count < sizeof(hci_event_hdr_t) - 1) { - DPRINTF("dumped undersized event (count = %d)\n", count); - sc->sc_stats.err_rx++; - return; - } - - sc->sc_stats.evt_rx++; - sc->sc_stats.byte_rx += count; - - m = ubt_mbufload(buf, count, HCI_EVENT_PKT); - if (m == NULL || !hci_input_event(sc->sc_unit, m)) - sc->sc_stats.err_rx++; -} - -void -ubt_recv_acl_start(struct ubt_softc *sc) -{ - usbd_status status; - - DPRINTFN(15, "sc=%p\n", sc); - - if (sc->sc_aclrd_busy || sc->sc_dying) { - DPRINTF("sc_aclrd_busy=%d, sc_dying=%d\n", - sc->sc_aclrd_busy, - sc->sc_dying); - - return; - } - - sc->sc_refcnt++; - sc->sc_aclrd_busy = 1; - - usbd_setup_xfer(sc->sc_aclrd_xfer, - sc->sc_aclrd_pipe, - sc, - sc->sc_aclrd_buf, - UBT_BUFSIZ_ACL, - USBD_NO_COPY | USBD_SHORT_XFER_OK, - USBD_NO_TIMEOUT, - ubt_recv_acl_complete); - - status = usbd_transfer(sc->sc_aclrd_xfer); - - KKASSERT(status != USBD_NORMAL_COMPLETION); - - if (status != USBD_IN_PROGRESS) { - DPRINTF("usbd_transfer status=%s (%d)\n", - usbd_errstr(status), status); - - sc->sc_refcnt--; - sc->sc_aclrd_busy = 0; - } -} - -void -ubt_recv_acl_complete(usbd_xfer_handle xfer, - usbd_private_handle h, usbd_status status) -{ - struct ubt_softc *sc = h; - struct mbuf *m; - uint32_t count; - void *buf; - - DPRINTFN(15, "sc=%p status=%s (%d)\n", - sc, usbd_errstr(status), status); - - sc->sc_aclrd_busy = 0; - - if (--sc->sc_refcnt < 0) { - DPRINTF("refcnt = %d\n", sc->sc_refcnt); - usb_detach_wakeup(sc->sc_dev); - return; - } - - if (sc->sc_dying) { - DPRINTF("sc_dying\n"); - return; - } - - if (status != USBD_NORMAL_COMPLETION) { - DPRINTF("status=%s (%d)\n", - usbd_errstr(status), status); - - sc->sc_stats.err_rx++; - - if (status == USBD_STALLED) - usbd_clear_endpoint_stall_async(sc->sc_aclrd_pipe); - else - return; - } else { - usbd_get_xfer_status(xfer, NULL, &buf, &count, NULL); - - if (count < sizeof(hci_acldata_hdr_t) - 1) { - DPRINTF("dumped undersized packet (%d)\n", count); - sc->sc_stats.err_rx++; - } else { - sc->sc_stats.acl_rx++; - sc->sc_stats.byte_rx += count; - - m = ubt_mbufload(buf, count, HCI_ACL_DATA_PKT); - if (m == NULL || !hci_input_acl(sc->sc_unit, m)) - sc->sc_stats.err_rx++; - } - } - - /* and restart */ - ubt_recv_acl_start(sc); -} - -void -ubt_recv_sco_start1(struct ubt_softc *sc, struct ubt_isoc_xfer *isoc) -{ - int i; - - DPRINTFN(15, "sc=%p, isoc=%p\n", sc, isoc); - - if (isoc->busy || sc->sc_dying || sc->sc_scord_size == 0) { - DPRINTF("%s%s%s\n", - isoc->busy ? " busy" : "", - sc->sc_dying ? " dying" : "", - sc->sc_scord_size == 0 ? " size=0" : ""); - - return; - } - - sc->sc_refcnt++; - isoc->busy = 1; - - for (i = 0 ; i < UBT_NFRAMES ; i++) - isoc->size[i] = sc->sc_scord_size; - - usbd_setup_isoc_xfer(isoc->xfer, - sc->sc_scord_pipe, - isoc, - isoc->size, - UBT_NFRAMES, - USBD_NO_COPY | USBD_SHORT_XFER_OK, - ubt_recv_sco_complete); - - usbd_transfer(isoc->xfer); -} - -void -ubt_recv_sco_complete(usbd_xfer_handle xfer, - usbd_private_handle h, usbd_status status) -{ - struct ubt_isoc_xfer *isoc = h; - struct ubt_softc *sc; - struct mbuf *m; - uint32_t count; - uint8_t *ptr, *frame; - int i, size, got, want; - - KKASSERT(isoc != NULL); - KKASSERT(isoc->xfer == xfer); - - sc = isoc->softc; - isoc->busy = 0; - - if (--sc->sc_refcnt < 0) { - DPRINTF("refcnt=%d\n", sc->sc_refcnt); - usb_detach_wakeup(sc->sc_dev); - return; - } - - if (sc->sc_dying) { - DPRINTF("sc_dying\n"); - return; - } - - if (status != USBD_NORMAL_COMPLETION) { - DPRINTF("status=%s (%d)\n", - usbd_errstr(status), status); - - sc->sc_stats.err_rx++; - - if (status == USBD_STALLED) { - usbd_clear_endpoint_stall_async(sc->sc_scord_pipe); - goto restart; - } - - return; - } - - usbd_get_xfer_status(xfer, NULL, NULL, &count, NULL); - if (count == 0) - goto restart; - - DPRINTFN(15, "sc=%p, isoc=%p, count=%u\n", - sc, isoc, count); - - sc->sc_stats.byte_rx += count; - - /* - * Extract SCO packets from ISOC frames. The way we have it, - * no SCO packet can be bigger than MHLEN. This is unlikely - * to actually happen, but if we ran out of mbufs and lost - * sync then we may get spurious data that makes it seem that - * way, so we discard data that wont fit. This doesnt really - * help with the lost sync situation alas. - */ - - m = sc->sc_scord_mbuf; - if (m != NULL) { - sc->sc_scord_mbuf = NULL; - ptr = mtod(m, uint8_t *) + m->m_pkthdr.len; - got = m->m_pkthdr.len; - want = sizeof(hci_scodata_hdr_t); - if (got >= want) - want += mtod(m, hci_scodata_hdr_t *)->length ; - } else { - ptr = NULL; - got = 0; - want = 0; - } - - for (i = 0 ; i < UBT_NFRAMES ; i++) { - frame = isoc->buf + (i * sc->sc_scord_size); - - while (isoc->size[i] > 0) { - size = isoc->size[i]; - - if (m == NULL) { - MGETHDR(m, MB_DONTWAIT, MT_DATA); - if (m == NULL) { - kprintf("%s: out of memory (xfer halted)\n", - device_get_nameunit(sc->sc_dev)); - - sc->sc_stats.err_rx++; - return; /* lost sync */ - } - - ptr = mtod(m, uint8_t *); - *ptr++ = HCI_SCO_DATA_PKT; - got = 1; - want = sizeof(hci_scodata_hdr_t); - } - - if (got + size > want) - size = want - got; - - if (got + size > MHLEN) - memcpy(ptr, frame, MHLEN - got); - else - memcpy(ptr, frame, size); - - ptr += size; - got += size; - frame += size; - - if (got == want) { - /* - * If we only got a header, add the packet - * length to our want count. Send complete - * packets up to protocol stack. - */ - if (want == sizeof(hci_scodata_hdr_t)) - want += mtod(m, hci_scodata_hdr_t *)->length; - - if (got == want) { - m->m_pkthdr.len = m->m_len = got; - sc->sc_stats.sco_rx++; - if (!hci_input_sco(sc->sc_unit, m)) - sc->sc_stats.err_rx++; - - m = NULL; - } - } - - isoc->size[i] -= size; - } - } - - if (m != NULL) { - m->m_pkthdr.len = m->m_len = got; - sc->sc_scord_mbuf = m; - } - -restart: /* and restart */ - ubt_recv_sco_start1(sc, isoc); -} - -void -ubt_stats(struct device *self, struct bt_stats *dest, int flush) -{ - struct ubt_softc *sc = device_get_softc(self); - - crit_enter(); - memcpy(dest, &sc->sc_stats, sizeof(struct bt_stats)); - - if (flush) - memset(&sc->sc_stats, 0, sizeof(struct bt_stats)); - - crit_exit(); -} diff --git a/sys/dev/usbmisc/uchcom/Makefile b/sys/dev/usbmisc/uchcom/Makefile deleted file mode 100644 index 37578bc8fc..0000000000 --- a/sys/dev/usbmisc/uchcom/Makefile +++ /dev/null @@ -1,9 +0,0 @@ -# $DragonFly: src/sys/dev/usbmisc/uchcom/Makefile,v 1.1 2007/11/07 09:07:44 hasso Exp $ - -S= ${.CURDIR}/../.. -.PATH: $S/dev/usb - -KMOD= uchcom -SRCS= uchcom.c opt_usb.h device_if.h bus_if.h - -.include diff --git a/sys/dev/usbmisc/uchcom/uchcom.c b/sys/dev/usbmisc/uchcom/uchcom.c deleted file mode 100644 index 4a055d389e..0000000000 --- a/sys/dev/usbmisc/uchcom/uchcom.c +++ /dev/null @@ -1,1028 +0,0 @@ -/* $NetBSD: uchcom.c,v 1.1 2007/09/03 17:57:37 tshiozak Exp $ */ - -/* - * Copyright (c) 2007 The NetBSD Foundation, Inc. - * All rights reserved. - * - * This code is derived from software contributed to The NetBSD Foundation - * by Takuya SHIOZAKI (tshiozak@netbsd.org). - * - * 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. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the NetBSD - * Foundation, Inc. and its contributors. - * 4. Neither the name of The NetBSD Foundation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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. - */ - -/* - * driver for WinChipHead CH341/340, the worst USB-serial chip in the world. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include - -#ifdef UCHCOM_DEBUG -#define DPRINTFN(n, x) do { if (uchcomdebug > (n)) kprintf x; } while (0) -int uchcomdebug = 0; -#else -#define DPRINTFN(n, x) -#endif -#define DPRINTF(x) DPRINTFN(0, x) - -#define UCHCOM_IFACE_INDEX 0 -#define UCHCOM_CONFIG_INDEX 0 - -#define UCHCOM_REV_CH340 0x0250 -#define UCHCOM_INPUT_BUF_SIZE 8 - -#define UCHCOM_REQ_GET_VERSION 0x5F -#define UCHCOM_REQ_READ_REG 0x95 -#define UCHCOM_REQ_WRITE_REG 0x9A -#define UCHCOM_REQ_RESET 0xA1 -#define UCHCOM_REQ_SET_DTRRTS 0xA4 - -#define UCHCOM_REG_STAT1 0x06 -#define UCHCOM_REG_STAT2 0x07 -#define UCHCOM_REG_BPS_PRE 0x12 -#define UCHCOM_REG_BPS_DIV 0x13 -#define UCHCOM_REG_BPS_MOD 0x14 -#define UCHCOM_REG_BPS_PAD 0x0F -#define UCHCOM_REG_BREAK1 0x05 -#define UCHCOM_REG_BREAK2 0x18 -#define UCHCOM_REG_LCR1 0x18 -#define UCHCOM_REG_LCR2 0x25 - -#define UCHCOM_VER_20 0x20 - -#define UCHCOM_BASE_UNKNOWN 0 -#define UCHCOM_BPS_MOD_BASE 20000000 -#define UCHCOM_BPS_MOD_BASE_OFS 1100 - -#define UCHCOM_DTR_MASK 0x20 -#define UCHCOM_RTS_MASK 0x40 - -#define UCHCOM_BRK1_MASK 0x01 -#define UCHCOM_BRK2_MASK 0x40 - -#define UCHCOM_LCR1_MASK 0xAF -#define UCHCOM_LCR2_MASK 0x07 -#define UCHCOM_LCR1_PARENB 0x80 -#define UCHCOM_LCR2_PAREVEN 0x07 -#define UCHCOM_LCR2_PARODD 0x06 -#define UCHCOM_LCR2_PARMARK 0x05 -#define UCHCOM_LCR2_PARSPACE 0x04 - -#define UCHCOM_INTR_STAT1 0x02 -#define UCHCOM_INTR_STAT2 0x03 -#define UCHCOM_INTR_LEAST 4 - -#define UCHCOMIBUFSIZE 256 -#define UCHCOMOBUFSIZE 256 - -struct uchcom_softc -{ - struct ucom_softc sc_ucom; - - int sc_intr_endpoint; - int sc_intr_size; - usbd_pipe_handle sc_intr_pipe; - u_char *sc_intr_buf; - - uint8_t sc_version; - int sc_dtr; - int sc_rts; - u_char sc_lsr; - u_char sc_msr; - int sc_lcr1; - int sc_lcr2; -}; - -struct uchcom_endpoints -{ - int ep_bulkin; - int ep_bulkout; - int ep_intr; - int ep_intr_size; -}; - -struct uchcom_divider -{ - uint8_t dv_prescaler; - uint8_t dv_div; - uint8_t dv_mod; -}; - -struct uchcom_divider_record -{ - uint32_t dvr_high; - uint32_t dvr_low; - uint32_t dvr_base_clock; - struct uchcom_divider dvr_divider; -}; - -static const struct uchcom_divider_record dividers[] = -{ - { 307200, 307200, UCHCOM_BASE_UNKNOWN, { 7, 0xD9, 0 } }, - { 921600, 921600, UCHCOM_BASE_UNKNOWN, { 7, 0xF3, 0 } }, - { 2999999, 23530, 6000000, { 3, 0, 0 } }, - { 23529, 2942, 750000, { 2, 0, 0 } }, - { 2941, 368, 93750, { 1, 0, 0 } }, - { 367, 1, 11719, { 0, 0, 0 } }, -}; -#define NUM_DIVIDERS NELEM(dividers) - -static void uchcom_get_status(void *, int, u_char *, u_char *); -static void uchcom_set(void *, int, int, int); -static int uchcom_param(void *, int, struct termios *); -static int uchcom_open(void *, int); -static void uchcom_close(void *, int); -static void uchcom_intr(usbd_xfer_handle, usbd_private_handle, - usbd_status); - -static int set_config(struct uchcom_softc *); -static int find_ifaces(struct uchcom_softc *, usbd_interface_handle *); -static int find_endpoints(struct uchcom_softc *, - struct uchcom_endpoints *); -static void close_intr_pipe(struct uchcom_softc *); - -static device_probe_t uchcom_match; -static device_attach_t uchcom_attach; -static device_detach_t uchcom_detach; - -static device_method_t uchcom_methods[] = { - DEVMETHOD(device_probe, uchcom_match), - DEVMETHOD(device_attach, uchcom_attach), - DEVMETHOD(device_detach, uchcom_detach), - DEVMETHOD_END -}; - -static driver_t uchcom_driver = { - "ucom", - uchcom_methods, - sizeof (struct uchcom_softc) -}; - -DRIVER_MODULE(uchcom, uhub, uchcom_driver, ucom_devclass, usbd_driver_load, NULL); -MODULE_DEPEND(uchcom, usb, 1, 1, 1); -MODULE_DEPEND(uchcom, ucom, UCOM_MINVER, UCOM_PREFVER, UCOM_MAXVER); -MODULE_VERSION(uchcom, 1); - -struct ucom_callback uchcom_callback = { - .ucom_get_status = uchcom_get_status, - .ucom_set = uchcom_set, - .ucom_param = uchcom_param, - .ucom_ioctl = NULL, - .ucom_open = uchcom_open, - .ucom_close = uchcom_close, - .ucom_read = NULL, - .ucom_write = NULL, -}; - -static const struct usb_devno uchcom_devs[] = { - { USB_DEVICE(0x4348, 0x5523) }, /* QinHeng Electronics CH341/340 */ -}; -#define uchcom_lookup(v, p) usb_lookup(uchcom_devs, v, p) - -/* ---------------------------------------------------------------------- - * driver entry points - */ - -static int -uchcom_match(device_t self) -{ - struct usb_attach_arg *uaa = device_get_ivars(self); - - if (uaa->iface != NULL) - return UMATCH_NONE; - - return (uchcom_lookup(uaa->vendor, uaa->product) != NULL ? - UMATCH_VENDOR_PRODUCT : UMATCH_NONE); -} - -static int -uchcom_attach(device_t self) -{ - struct uchcom_softc *sc = device_get_softc(self); - struct usb_attach_arg *uaa = device_get_ivars(self); - struct ucom_softc *ucom = &sc->sc_ucom; - usbd_device_handle dev = uaa->device; - struct uchcom_endpoints endpoints; - - bzero(sc, sizeof (struct uchcom_softc)); - ucom->sc_dev = self; - ucom->sc_udev = dev; - ucom->sc_dying = 0; - sc->sc_dtr = sc->sc_rts = -1; - sc->sc_lsr = sc->sc_msr = 0; - - DPRINTF(("\n\nuchcom attach: sc=%p\n", sc)); - - if (set_config(sc)) - goto failed; - - switch (uaa->release) { - case UCHCOM_REV_CH340: - device_printf(ucom->sc_dev, "CH340\n"); - break; - default: - device_printf(ucom->sc_dev, "CH341\n"); - break; - } - - if (find_ifaces(sc, &ucom->sc_iface)) - goto failed; - - if (find_endpoints(sc, &endpoints)) - goto failed; - - sc->sc_intr_endpoint = endpoints.ep_intr; - sc->sc_intr_size = endpoints.ep_intr_size; - - /* setup ucom layer */ - ucom->sc_parent = sc; - ucom->sc_portno = UCOM_UNK_PORTNO; - ucom->sc_bulkin_no = endpoints.ep_bulkin; - ucom->sc_bulkout_no = endpoints.ep_bulkout; - ucom->sc_ibufsize = UCHCOMIBUFSIZE; - ucom->sc_obufsize = UCHCOMOBUFSIZE; - ucom->sc_ibufsizepad = UCHCOMIBUFSIZE; - ucom->sc_opkthdrlen = 0; - ucom->sc_callback = &uchcom_callback; - - usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, ucom->sc_udev, - ucom->sc_dev); - ucom_attach(&sc->sc_ucom); - - return 0; - -failed: - ucom->sc_dying = 1; - return ENXIO; -} - -static int -uchcom_detach(device_t self) -{ - struct uchcom_softc *sc = device_get_softc(self); - int rv = 0; - - DPRINTF(("uchcom_detach: sc=%p flags=%d\n", sc, flags)); - - close_intr_pipe(sc); - sc->sc_ucom.sc_dying = 1; - rv = ucom_detach(&sc->sc_ucom); - usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_ucom.sc_udev, - sc->sc_ucom.sc_dev); - - return rv; -} - -#if 0 /* not yet */ -int -uchcom_activate(struct device *self, enum devact act) -{ - struct uchcom_softc *sc = (struct uchcom_softc *)self; - int rv = 0; - - switch (act) { - case DVACT_ACTIVATE: - rv = EOPNOTSUPP; - break; - case DVACT_DEACTIVATE: - uchcom_close_intr_pipe(sc); - sc->sc_dying = 1; - if (sc->sc_subdev != NULL) - rv = config_deactivate(sc->sc_subdev); - break; - } - return rv; -} -#endif - -int -set_config(struct uchcom_softc *sc) -{ - usbd_status err; - - err = usbd_set_config_index(sc->sc_ucom.sc_udev, - UCHCOM_CONFIG_INDEX, 1); - if (err) { - device_printf(sc->sc_ucom.sc_dev, "failed to set " - "configuration: %s\n", usbd_errstr(err)); - return -1; - } - - return 0; -} - -int -find_ifaces(struct uchcom_softc *sc, usbd_interface_handle *riface) -{ - usbd_status err; - - err = usbd_device2interface_handle(sc->sc_ucom.sc_udev, - UCHCOM_IFACE_INDEX, riface); - if (err) { - device_printf(sc->sc_ucom.sc_dev, "failed to get interface: " - "%s\n", usbd_errstr(err)); - return -1; - } - - return 0; -} - -int -find_endpoints(struct uchcom_softc *sc, - struct uchcom_endpoints *endpoints) -{ - int i, bin=-1, bout=-1, intr=-1, isize=0; - usb_interface_descriptor_t *id; - usb_endpoint_descriptor_t *ed; - - id = usbd_get_interface_descriptor(sc->sc_ucom.sc_iface); - - for (i = 0; i < id->bNumEndpoints; i++) { - ed = usbd_interface2endpoint_descriptor(sc->sc_ucom.sc_iface, - i); - if (ed == NULL) { - device_printf(sc->sc_ucom.sc_dev, - "no endpoint descriptor for %d\n", i); - return -1; - } - - if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && - UE_GET_XFERTYPE(ed->bmAttributes) == UE_INTERRUPT) { - intr = ed->bEndpointAddress; - isize = UGETW(ed->wMaxPacketSize); - } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && - UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) { - bin = ed->bEndpointAddress; - } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT && - UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) { - bout = ed->bEndpointAddress; - } - } - - if (intr == -1 || bin == -1 || bout == -1) { - if (intr == -1) { - device_printf(sc->sc_ucom.sc_dev, - "no interrupt end point\n"); - } - if (bin == -1) { - device_printf(sc->sc_ucom.sc_dev, - "no data bulk in end point\n"); - } - if (bout == -1) { - device_printf(sc->sc_ucom.sc_dev, - "no data bulk out end point\n"); - } - return -1; - } - if (isize < UCHCOM_INTR_LEAST) { - device_printf(sc->sc_ucom.sc_dev, "intr pipe is too short\n"); - return -1; - } - - DPRINTF(("%s: bulkin=%d, bulkout=%d, intr=%d, isize=%d\n", - device_get_nameunit(sc->sc_ucom.sc_dev), bin, bout, intr, - isize)); - - endpoints->ep_intr = intr; - endpoints->ep_intr_size = isize; - endpoints->ep_bulkin = bin; - endpoints->ep_bulkout = bout; - - return 0; -} - - -/* ---------------------------------------------------------------------- - * low level i/o - */ - -static __inline usbd_status -generic_control_out(struct uchcom_softc *sc, uint8_t reqno, - uint16_t value, uint16_t index) -{ - usb_device_request_t req; - - req.bmRequestType = UT_WRITE_VENDOR_DEVICE; - req.bRequest = reqno; - USETW(req.wValue, value); - USETW(req.wIndex, index); - USETW(req.wLength, 0); - - return usbd_do_request(sc->sc_ucom.sc_udev, &req, 0); -} - -static __inline usbd_status -generic_control_in(struct uchcom_softc *sc, uint8_t reqno, - uint16_t value, uint16_t index, void *buf, int buflen, int *actlen) -{ - usb_device_request_t req; - - req.bmRequestType = UT_READ_VENDOR_DEVICE; - req.bRequest = reqno; - USETW(req.wValue, value); - USETW(req.wIndex, index); - USETW(req.wLength, (uint16_t)buflen); - - return usbd_do_request_flags(sc->sc_ucom.sc_udev, &req, buf, - USBD_SHORT_XFER_OK, actlen, - USBD_DEFAULT_TIMEOUT); -} - -static __inline usbd_status -write_reg(struct uchcom_softc *sc, - uint8_t reg1, uint8_t val1, uint8_t reg2, uint8_t val2) -{ - DPRINTF(("uchcom: write reg 0x%02X<-0x%02X, 0x%02X<-0x%02X\n", - (unsigned)reg1, (unsigned)val1, - (unsigned)reg2, (unsigned)val2)); - return generic_control_out( - sc, UCHCOM_REQ_WRITE_REG, - reg1|((uint16_t)reg2<<8), val1|((uint16_t)val2<<8)); -} - -static __inline usbd_status -read_reg(struct uchcom_softc *sc, - uint8_t reg1, uint8_t *rval1, uint8_t reg2, uint8_t *rval2) -{ - uint8_t buf[UCHCOM_INPUT_BUF_SIZE]; - usbd_status err; - int actin; - - err = generic_control_in( - sc, UCHCOM_REQ_READ_REG, - reg1|((uint16_t)reg2<<8), 0, buf, sizeof buf, &actin); - if (err) - return err; - - DPRINTF(("uchcom: read reg 0x%02X->0x%02X, 0x%02X->0x%02X\n", - (unsigned)reg1, (unsigned)buf[0], - (unsigned)reg2, (unsigned)buf[1])); - - if (rval1) *rval1 = buf[0]; - if (rval2) *rval2 = buf[1]; - - return USBD_NORMAL_COMPLETION; -} - -static __inline usbd_status -get_version(struct uchcom_softc *sc, uint8_t *rver) -{ - uint8_t buf[UCHCOM_INPUT_BUF_SIZE]; - usbd_status err; - int actin; - - err = generic_control_in( - sc, UCHCOM_REQ_GET_VERSION, 0, 0, buf, sizeof buf, &actin); - if (err) - return err; - - if (rver) *rver = buf[0]; - - return USBD_NORMAL_COMPLETION; -} - -static __inline usbd_status -read_status(struct uchcom_softc *sc, uint8_t *rval) -{ - return read_reg(sc, UCHCOM_REG_STAT1, rval, UCHCOM_REG_STAT2, NULL); -} - -static __inline usbd_status -set_dtrrts_10(struct uchcom_softc *sc, uint8_t val) -{ - return write_reg(sc, UCHCOM_REG_STAT1, val, UCHCOM_REG_STAT1, val); -} - -static __inline usbd_status -set_dtrrts_20(struct uchcom_softc *sc, uint8_t val) -{ - return generic_control_out(sc, UCHCOM_REQ_SET_DTRRTS, val, 0); -} - - -/* ---------------------------------------------------------------------- - * middle layer - */ - -static int -update_version(struct uchcom_softc *sc) -{ - usbd_status err; - - err = get_version(sc, &sc->sc_version); - if (err) { - device_printf(sc->sc_ucom.sc_dev, "cannot get version: %s\n", - usbd_errstr(err)); - return EIO; - } - - return 0; -} - -static void -convert_status(struct uchcom_softc *sc, uint8_t cur) -{ - sc->sc_dtr = !(cur & UCHCOM_DTR_MASK); - sc->sc_rts = !(cur & UCHCOM_RTS_MASK); - - cur = ~cur & 0x0F; - sc->sc_msr = (cur << 4) | ((sc->sc_msr >> 4) ^ cur); -} - -static int -update_status(struct uchcom_softc *sc) -{ - usbd_status err; - uint8_t cur; - - err = read_status(sc, &cur); - if (err) { - device_printf(sc->sc_ucom.sc_dev, "cannot update status: %s\n", - usbd_errstr(err)); - return EIO; - } - convert_status(sc, cur); - - return 0; -} - - -static int -set_dtrrts(struct uchcom_softc *sc, int dtr, int rts) -{ - usbd_status err; - uint8_t val = 0; - - if (dtr) val |= UCHCOM_DTR_MASK; - if (rts) val |= UCHCOM_RTS_MASK; - - if (sc->sc_version < UCHCOM_VER_20) - err = set_dtrrts_10(sc, ~val); - else - err = set_dtrrts_20(sc, ~val); - - if (err) { - device_printf(sc->sc_ucom.sc_dev, "cannot set DTR/RTS: %s\n", - usbd_errstr(err)); - return EIO; - } - - return 0; -} - -static int -set_break(struct uchcom_softc *sc, int onoff) -{ - usbd_status err; - uint8_t brk1, brk2; - - err = read_reg(sc, UCHCOM_REG_BREAK1, &brk1, UCHCOM_REG_BREAK2, - &brk2); - if (err) - return EIO; - if (onoff) { - /* on - clear bits */ - brk1 &= ~UCHCOM_BRK1_MASK; - brk2 &= ~UCHCOM_BRK2_MASK; - } else { - /* off - set bits */ - brk1 |= UCHCOM_BRK1_MASK; - brk2 |= UCHCOM_BRK2_MASK; - } - err = write_reg(sc, UCHCOM_REG_BREAK1, brk1, UCHCOM_REG_BREAK2, - brk2); - if (err) - return EIO; - - return 0; -} - -static int -calc_divider_settings(struct uchcom_divider *dp, uint32_t rate) -{ - int i; - const struct uchcom_divider_record *rp; - uint32_t div, rem, mod; - - /* find record */ - for (i=0; i= rate && - dividers[i].dvr_low <= rate) { - rp = ÷rs[i]; - goto found; - } - } - return -1; - -found: - dp->dv_prescaler = rp->dvr_divider.dv_prescaler; - if (rp->dvr_base_clock == UCHCOM_BASE_UNKNOWN) - dp->dv_div = rp->dvr_divider.dv_div; - else { - div = rp->dvr_base_clock / rate; - rem = rp->dvr_base_clock % rate; - if (div==0 || div>=0xFF) - return -1; - if ((rem<<1) >= rate) - div += 1; - dp->dv_div = (uint8_t)-div; - } - - mod = UCHCOM_BPS_MOD_BASE/rate + UCHCOM_BPS_MOD_BASE_OFS; - mod = mod + mod/2; - - dp->dv_mod = mod / 0x100; - - return 0; -} - -static int -set_dte_rate(struct uchcom_softc *sc, uint32_t rate) -{ - usbd_status err; - struct uchcom_divider dv; - - if (calc_divider_settings(&dv, rate)) - return EINVAL; - - if ((err = write_reg(sc, - UCHCOM_REG_BPS_PRE, dv.dv_prescaler, - UCHCOM_REG_BPS_DIV, dv.dv_div)) || - (err = write_reg(sc, - UCHCOM_REG_BPS_MOD, dv.dv_mod, - UCHCOM_REG_BPS_PAD, 0))) { - device_printf(sc->sc_ucom.sc_dev, "cannot set DTE rate: %s\n", - usbd_errstr(err)); - return EIO; - } - - return 0; -} - -static int -set_line_control(struct uchcom_softc *sc, tcflag_t cflag) -{ - usbd_status err; - uint8_t lcr1 = 0, lcr2 = 0; - - err = read_reg(sc, UCHCOM_REG_LCR1, &lcr1, UCHCOM_REG_LCR2, &lcr2); - if (err) { - device_printf(sc->sc_ucom.sc_dev, "cannot get LCR: %s\n", - usbd_errstr(err)); - return EIO; - } - - lcr1 &= ~UCHCOM_LCR1_MASK; - lcr2 &= ~UCHCOM_LCR2_MASK; - - /* - * XXX: it is difficult to handle the line control appropriately: - * - CS8, !CSTOPB and any parity mode seems ok, but - * - the chip doesn't have the function to calculate parity - * in !CS8 mode. - * - it is unclear that the chip supports CS5,6 mode. - * - it is unclear how to handle stop bits. - */ - - switch (ISSET(cflag, CSIZE)) { - case CS5: - case CS6: - case CS7: - return EINVAL; - case CS8: - break; - } - - if (ISSET(cflag, PARENB)) { - lcr1 |= UCHCOM_LCR1_PARENB; - if (ISSET(cflag, PARODD)) - lcr2 |= UCHCOM_LCR2_PARODD; - else - lcr2 |= UCHCOM_LCR2_PAREVEN; - } - - err = write_reg(sc, UCHCOM_REG_LCR1, lcr1, UCHCOM_REG_LCR2, - lcr2); - if (err) { - device_printf(sc->sc_ucom.sc_dev, "cannot set LCR: %s\n", - usbd_errstr(err)); - return EIO; - } - - return 0; -} - -static int -clear_chip(struct uchcom_softc *sc) -{ - usbd_status err; - - DPRINTF(("%s: clear\n", sc->sc_dev.dv_xname)); - err = generic_control_out(sc, UCHCOM_REQ_RESET, 0, 0); - if (err) { - device_printf(sc->sc_ucom.sc_dev, "cannot clear: %s\n", - usbd_errstr(err)); - return EIO; - } - - return 0; -} - -static int -reset_chip(struct uchcom_softc *sc) -{ - usbd_status err; - uint8_t lcr1, lcr2, pre, div, mod; - uint16_t val=0, idx=0; - - err = read_reg(sc, UCHCOM_REG_LCR1, &lcr1, UCHCOM_REG_LCR2, &lcr2); - if (err) - goto failed; - - err = read_reg(sc, UCHCOM_REG_BPS_PRE, &pre, UCHCOM_REG_BPS_DIV, - &div); - if (err) - goto failed; - - err = read_reg(sc, UCHCOM_REG_BPS_MOD, &mod, UCHCOM_REG_BPS_PAD, - NULL); - if (err) - goto failed; - - val |= (uint16_t)(lcr1&0xF0) << 8; - val |= 0x01; - val |= (uint16_t)(lcr2&0x0F) << 8; - val |= 0x02; - idx |= pre & 0x07; - val |= 0x04; - idx |= (uint16_t)div << 8; - val |= 0x08; - idx |= mod & 0xF8; - val |= 0x10; - - DPRINTF(("%s: reset v=0x%04X, i=0x%04X\n", - device_get_nameunit(sc->sc_ucom.sc_dev), val, idx)); - - err = generic_control_out(sc, UCHCOM_REQ_RESET, val, idx); - if (err) - goto failed; - - return 0; - -failed: - device_printf(sc->sc_ucom.sc_dev, "cannot reset: %s\n", - usbd_errstr(err)); - return EIO; -} - -static int -setup_comm(struct uchcom_softc *sc) -{ - int ret; - - ret = update_version(sc); - if (ret) - return ret; - - ret = clear_chip(sc); - if (ret) - return ret; - - ret = set_dte_rate(sc, TTYDEF_SPEED); - if (ret) - return ret; - - ret = set_line_control(sc, CS8); - if (ret) - return ret; - - ret = update_status(sc); - if (ret) - return ret; - - ret = reset_chip(sc); - if (ret) - return ret; - - ret = set_dte_rate(sc, TTYDEF_SPEED); /* XXX */ - if (ret) - return ret; - - sc->sc_dtr = sc->sc_rts = 1; - ret = set_dtrrts(sc, sc->sc_dtr, sc->sc_rts); - if (ret) - return ret; - - return 0; -} - -static int -setup_intr_pipe(struct uchcom_softc *sc) -{ - usbd_status err; - - if (sc->sc_intr_endpoint != -1 && sc->sc_intr_pipe == NULL) { - sc->sc_intr_buf = kmalloc(sc->sc_intr_size, M_USBDEV, M_WAITOK); - err = usbd_open_pipe_intr(sc->sc_ucom.sc_iface, - sc->sc_intr_endpoint, - USBD_SHORT_XFER_OK, - &sc->sc_intr_pipe, sc, - sc->sc_intr_buf, - sc->sc_intr_size, - uchcom_intr, USBD_DEFAULT_INTERVAL); - if (err) { - device_printf(sc->sc_ucom.sc_dev, "cannot open " - "interrupt pipe: %s\n", usbd_errstr(err)); - return EIO; - } - } - return 0; -} - -static void -close_intr_pipe(struct uchcom_softc *sc) -{ - usbd_status err; - - if (sc->sc_ucom.sc_dying) - return; - - if (sc->sc_intr_pipe != NULL) { - err = usbd_abort_pipe(sc->sc_intr_pipe); - if (err) - device_printf(sc->sc_ucom.sc_dev, "abort interrupt " - "pipe failed: %s\n", usbd_errstr(err)); - err = usbd_close_pipe(sc->sc_intr_pipe); - if (err) - device_printf(sc->sc_ucom.sc_dev, "close interrupt " - "pipe failed: %s\n", usbd_errstr(err)); - kfree(sc->sc_intr_buf, M_USBDEV); - sc->sc_intr_pipe = NULL; - } -} - - -/* ---------------------------------------------------------------------- - * methods for ucom - */ -void -uchcom_get_status(void *arg, int portno, u_char *rlsr, u_char *rmsr) -{ - struct uchcom_softc *sc = arg; - - if (sc->sc_ucom.sc_dying) - return; - - *rlsr = sc->sc_lsr; - *rmsr = sc->sc_msr; -} - -void -uchcom_set(void *arg, int portno, int reg, int onoff) -{ - struct uchcom_softc *sc = arg; - - if (sc->sc_ucom.sc_dying) - return; - - switch (reg) { - case UCOM_SET_DTR: - sc->sc_dtr = !!onoff; - set_dtrrts(sc, sc->sc_dtr, sc->sc_rts); - break; - case UCOM_SET_RTS: - sc->sc_rts = !!onoff; - set_dtrrts(sc, sc->sc_dtr, sc->sc_rts); - break; - case UCOM_SET_BREAK: - set_break(sc, onoff); - break; - } -} - -int -uchcom_param(void *arg, int portno, struct termios *t) -{ - struct uchcom_softc *sc = arg; - int ret; - - if (sc->sc_ucom.sc_dying) - return 0; - - ret = set_line_control(sc, t->c_cflag); - if (ret) - return ret; - - ret = set_dte_rate(sc, t->c_ospeed); - if (ret) - return ret; - - return 0; -} - -int -uchcom_open(void *arg, int portno) -{ - int ret; - struct uchcom_softc *sc = arg; - - if (sc->sc_ucom.sc_dying) - return EIO; - - ret = setup_intr_pipe(sc); - if (ret) - return ret; - - ret = setup_comm(sc); - if (ret) - return ret; - - return 0; -} - -void -uchcom_close(void *arg, int portno) -{ - struct uchcom_softc *sc = arg; - - if (sc->sc_ucom.sc_dying) - return; - - close_intr_pipe(sc); -} - - -/* ---------------------------------------------------------------------- - * callback when the modem status is changed. - */ -void -uchcom_intr(usbd_xfer_handle xfer, usbd_private_handle priv, - usbd_status status) -{ - struct uchcom_softc *sc = priv; - u_char *buf = sc->sc_intr_buf; - - if (sc->sc_ucom.sc_dying) - return; - - if (status != USBD_NORMAL_COMPLETION) { - if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) - return; - - DPRINTF(("%s: abnormal status: %s\n", - device_get_nameunit(sc->sc_ucom.sc_dev), - usbd_errstr(status))); - usbd_clear_endpoint_stall_async(sc->sc_intr_pipe); - return; - } - DPRINTF(("%s: intr: 0x%02X 0x%02X 0x%02X 0x%02X " - "0x%02X 0x%02X 0x%02X 0x%02X\n", - device_get_nameunit(sc->sc_ucom.sc_dev), - (unsigned)buf[0], (unsigned)buf[1], - (unsigned)buf[2], (unsigned)buf[3], - (unsigned)buf[4], (unsigned)buf[5], - (unsigned)buf[6], (unsigned)buf[7])); - - convert_status(sc, buf[UCHCOM_INTR_STAT1]); - ucom_status_change(&sc->sc_ucom); -} diff --git a/sys/dev/usbmisc/ucom/Makefile b/sys/dev/usbmisc/ucom/Makefile deleted file mode 100644 index 6611a6e9ce..0000000000 --- a/sys/dev/usbmisc/ucom/Makefile +++ /dev/null @@ -1,10 +0,0 @@ -# $FreeBSD: src/sys/modules/ucom/Makefile,v 1.1.2.1 2002/08/08 18:45:05 joe Exp $ -# $DragonFly: src/sys/dev/usbmisc/ucom/Makefile,v 1.3 2004/08/13 17:51:06 dillon Exp $ - -S= ${.CURDIR}/../.. -.PATH: $S/dev/usb - -KMOD= ucom -SRCS= ucom.c ucomvar.h opt_usb.h device_if.h bus_if.h - -.include diff --git a/sys/dev/usbmisc/ucom/ucom.c b/sys/dev/usbmisc/ucom/ucom.c deleted file mode 100644 index 90c18b8e3d..0000000000 --- a/sys/dev/usbmisc/ucom/ucom.c +++ /dev/null @@ -1,1299 +0,0 @@ -/* - * (MPSAFE) - * - * $NetBSD: ucom.c,v 1.39 2001/08/16 22:31:24 augustss Exp $ - * $NetBSD: ucom.c,v 1.40 2001/11/13 06:24:54 lukem Exp $ - * $FreeBSD: src/sys/dev/usb/ucom.c,v 1.35 2003/11/16 11:58:21 akiyama Exp $ - */ -/*- - * Copyright (c) 2001-2002, Shunsuke Akiyama . - * 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. - */ - -/* - * Copyright (c) 1998, 2000 The NetBSD Foundation, Inc. - * All rights reserved. - * - * This code is derived from software contributed to The NetBSD Foundation - * by Lennart Augustsson (lennart@augustsson.net) at - * Carlstedt Research & Technology. - * - * 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. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the NetBSD - * Foundation, Inc. and its contributors. - * 4. Neither the name of The NetBSD Foundation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include -#include - -#include "ucomvar.h" - -#ifdef USB_DEBUG -static int ucomdebug = 0; -SYSCTL_NODE(_hw_usb, OID_AUTO, ucom, CTLFLAG_RW, 0, "USB ucom"); -SYSCTL_INT(_hw_usb_ucom, OID_AUTO, debug, CTLFLAG_RW, - &ucomdebug, 0, "ucom debug level"); -#define DPRINTF(x) do { \ - if (ucomdebug) \ - kprintf x; \ - } while (0) - -#define DPRINTFN(n, x) do { \ - if (ucomdebug > (n)) \ - kprintf x; \ - } while (0) -#else -#define DPRINTF(x) -#define DPRINTFN(n, x) -#endif - -static d_open_t ucomopen; -static d_close_t ucomclose; -static d_read_t ucomread; -static d_write_t ucomwrite; -static d_ioctl_t ucomioctl; - -static struct dev_ops ucom_ops = { - { "ucom", 0, D_TTY }, - .d_open = ucomopen, - .d_close = ucomclose, - .d_read = ucomread, - .d_write = ucomwrite, - .d_ioctl = ucomioctl, - .d_kqfilter = ttykqfilter, - .d_revoke = ttyrevoke -}; - -static void ucom_cleanup(struct ucom_softc *); -static int ucomctl(struct ucom_softc *, int, int); -static int ucomparam(struct tty *, struct termios *); -static void ucomstart(struct tty *); -static void ucomstop(struct tty *, int); -static void ucom_shutdown(struct ucom_softc *); -static void ucom_dtr(struct ucom_softc *, int); -static void ucom_rts(struct ucom_softc *, int); -static void ucom_break(struct ucom_softc *, int); -static usbd_status ucomstartread(struct ucom_softc *); -static void ucomreadcb(usbd_xfer_handle, usbd_private_handle, usbd_status); -static void ucomwritecb(usbd_xfer_handle, usbd_private_handle, usbd_status); -static void ucomstopread(struct ucom_softc *); -static void disc_optim(struct tty *, struct termios *, struct ucom_softc *); - -devclass_t ucom_devclass; - -static moduledata_t ucom_mod = { - "ucom", - NULL, - NULL -}; - -DECLARE_MODULE(ucom, ucom_mod, SI_SUB_DRIVERS, SI_ORDER_MIDDLE); -MODULE_DEPEND(ucom, usb, 1, 1, 1); -MODULE_VERSION(ucom, UCOM_MODVER); - -int -ucom_attach(struct ucom_softc *sc) -{ - struct tty *tp; - int unit; - cdev_t dev; - - lwkt_gettoken(&tty_token); - unit = device_get_unit(sc->sc_dev); - - sc->sc_tty = tp = ttymalloc(sc->sc_tty); - tp->t_oproc = ucomstart; - tp->t_param = ucomparam; - tp->t_stop = ucomstop; - - DPRINTF(("ucom_attach: tty_attach tp = %p\n", tp)); - - DPRINTF(("ucom_attach: make_dev: ucom%d\n", unit)); - - dev = make_dev(&ucom_ops, unit | UCOM_CALLOUT_MASK, - UID_UUCP, GID_DIALER, 0660, - "ucom%d", unit); - dev->si_tty = tp; - sc->dev = dev; - lwkt_reltoken(&tty_token); - - return (0); -} - -int -ucom_detach(struct ucom_softc *sc) -{ - struct tty *tp = sc->sc_tty; - int unit; - - DPRINTF(("ucom_detach: sc = %p, tp = %p\n", sc, sc->sc_tty)); - - destroy_dev(sc->dev); - lwkt_gettoken(&tty_token); - sc->sc_dying = 1; - - if (sc->sc_bulkin_pipe != NULL) - usbd_abort_pipe(sc->sc_bulkin_pipe); - if (sc->sc_bulkout_pipe != NULL) - usbd_abort_pipe(sc->sc_bulkout_pipe); - - if (tp != NULL) { - if (tp->t_state & TS_ISOPEN) { - device_printf(sc->sc_dev, - "still open, forcing close\n"); - (*linesw[tp->t_line].l_close)(tp, 0); - ttyclose(tp); - } - } else { - DPRINTF(("ucom_detach: no tty\n")); - lwkt_reltoken(&tty_token); - return (0); - } - - crit_enter(); - if (--sc->sc_refcnt >= 0) { - /* Wait for processes to go away. */ - usb_detach_wait(sc->sc_dev); - } - crit_exit(); - - unit = device_get_unit(sc->sc_dev); - dev_ops_remove_minor(&ucom_ops, /*UCOMUNIT_MASK, */unit); - - lwkt_reltoken(&tty_token); - return (0); -} - -static void -ucom_shutdown(struct ucom_softc *sc) -{ - struct tty *tp = sc->sc_tty; - - lwkt_gettoken(&tty_token); - DPRINTF(("ucom_shutdown\n")); - /* - * Hang up if necessary. Wait a bit, so the other side has time to - * notice even if we immediately open the port again. - */ - if (ISSET(tp->t_cflag, HUPCL)) { - (void)ucomctl(sc, TIOCM_DTR, DMBIC); - (void)tsleep(sc, 0, "ucomsd", hz); - } - lwkt_reltoken(&tty_token); -} - -static int -ucomopen(struct dev_open_args *ap) -{ - cdev_t dev = ap->a_head.a_dev; - int unit = UCOMUNIT(dev); - struct ucom_softc *sc; - usbd_status err; - struct tty *tp; - int error; - - sc = devclass_get_softc(ucom_devclass, unit); - if (sc == NULL) - return (ENXIO); - - if (sc->sc_dying) - return (ENXIO); - - lwkt_gettoken(&tty_token); - tp = sc->sc_tty; - - DPRINTF(("%s: ucomopen: tp = %p\n", device_get_nameunit(sc->sc_dev), tp)); - - if (ISSET(tp->t_state, TS_ISOPEN) && - ISSET(tp->t_state, TS_XCLUDE) && - priv_check_cred(ap->a_cred, PRIV_ROOT, 0) - ) { - lwkt_reltoken(&tty_token); - return (EBUSY); - } - - /* - * Do the following iff this is a first open. - */ - crit_enter(); - while (sc->sc_opening) - tsleep(&sc->sc_opening, 0, "ucomop", 0); - sc->sc_opening = 1; - - if (!ISSET(tp->t_state, TS_ISOPEN)) { - struct termios t; - - sc->sc_poll = 0; - sc->sc_lsr = sc->sc_msr = sc->sc_mcr = 0; - - tp->t_dev = reference_dev(dev); - - /* - * Initialize the termios status to the defaults. Add in the - * sticky bits from TIOCSFLAGS. - */ - t.c_ispeed = 0; - t.c_ospeed = TTYDEF_SPEED; - t.c_cflag = TTYDEF_CFLAG; - /* Make sure ucomparam() will do something. */ - tp->t_ospeed = 0; - (void)ucomparam(tp, &t); - tp->t_iflag = TTYDEF_IFLAG; - tp->t_oflag = TTYDEF_OFLAG; - tp->t_lflag = TTYDEF_LFLAG; - ttychars(tp); - ttsetwater(tp); - - /* - * Turn on DTR. We must always do this, even if carrier is not - * present, because otherwise we'd have to use TIOCSDTR - * immediately after setting CLOCAL, which applications do not - * expect. We always assert DTR while the device is open - * unless explicitly requested to deassert it. - */ - (void)ucomctl(sc, TIOCM_DTR | TIOCM_RTS, DMBIS); - - /* Device specific open */ - if (sc->sc_callback->ucom_open != NULL) { - error = sc->sc_callback->ucom_open(sc->sc_parent, - sc->sc_portno); - if (error) { - ucom_cleanup(sc); - sc->sc_opening = 0; - wakeup(&sc->sc_opening); - crit_exit(); - lwkt_reltoken(&tty_token); - return (error); - } - } - - DPRINTF(("ucomopen: open pipes in = %d out = %d\n", - sc->sc_bulkin_no, sc->sc_bulkout_no)); - - /* Open the bulk pipes */ - /* Bulk-in pipe */ - err = usbd_open_pipe(sc->sc_iface, sc->sc_bulkin_no, 0, - &sc->sc_bulkin_pipe); - if (err) { - kprintf("%s: open bulk in error (addr %d): %s\n", - device_get_nameunit(sc->sc_dev), sc->sc_bulkin_no, - usbd_errstr(err)); - error = EIO; - goto fail_0; - } - /* Bulk-out pipe */ - err = usbd_open_pipe(sc->sc_iface, sc->sc_bulkout_no, - USBD_EXCLUSIVE_USE, &sc->sc_bulkout_pipe); - if (err) { - kprintf("%s: open bulk out error (addr %d): %s\n", - device_get_nameunit(sc->sc_dev), sc->sc_bulkout_no, - usbd_errstr(err)); - error = EIO; - goto fail_1; - } - - /* Allocate a request and an input buffer and start reading. */ - sc->sc_ixfer = usbd_alloc_xfer(sc->sc_udev); - if (sc->sc_ixfer == NULL) { - error = ENOMEM; - goto fail_2; - } - - sc->sc_ibuf = usbd_alloc_buffer(sc->sc_ixfer, - sc->sc_ibufsizepad); - if (sc->sc_ibuf == NULL) { - error = ENOMEM; - goto fail_3; - } - - sc->sc_oxfer = usbd_alloc_xfer(sc->sc_udev); - if (sc->sc_oxfer == NULL) { - error = ENOMEM; - goto fail_3; - } - - sc->sc_obuf = usbd_alloc_buffer(sc->sc_oxfer, - sc->sc_obufsize + - sc->sc_opkthdrlen); - if (sc->sc_obuf == NULL) { - error = ENOMEM; - goto fail_4; - } - - /* - * Handle initial DCD. - */ - if (ISSET(sc->sc_msr, UMSR_DCD) || - (minor(dev) & UCOM_CALLOUT_MASK)) - (*linesw[tp->t_line].l_modem)(tp, 1); - - ucomstartread(sc); - } - - sc->sc_opening = 0; - wakeup(&sc->sc_opening); - crit_exit(); - - error = ttyopen(dev, tp); - if (error) - goto bad; - - error = (*linesw[tp->t_line].l_open)(dev, tp); - if (error) - goto bad; - - disc_optim(tp, &tp->t_termios, sc); - - DPRINTF(("%s: ucomopen: success\n", device_get_nameunit(sc->sc_dev))); - - sc->sc_poll = 1; - sc->sc_refcnt++; - - lwkt_reltoken(&tty_token); - return (0); - -fail_4: - usbd_free_xfer(sc->sc_oxfer); - sc->sc_oxfer = NULL; -fail_3: - usbd_free_xfer(sc->sc_ixfer); - sc->sc_ixfer = NULL; -fail_2: - usbd_close_pipe(sc->sc_bulkout_pipe); - sc->sc_bulkout_pipe = NULL; -fail_1: - usbd_close_pipe(sc->sc_bulkin_pipe); - sc->sc_bulkin_pipe = NULL; -fail_0: - sc->sc_opening = 0; - wakeup(&sc->sc_opening); - crit_exit(); - lwkt_reltoken(&tty_token); - return (error); - -bad: - if (!ISSET(tp->t_state, TS_ISOPEN)) { - /* - * We failed to open the device, and nobody else had it opened. - * Clean up the state as appropriate. - */ - ucom_cleanup(sc); - } - - DPRINTF(("%s: ucomopen: failed\n", device_get_nameunit(sc->sc_dev))); - - lwkt_reltoken(&tty_token); - return (error); -} - -static int -ucomclose(struct dev_close_args *ap) -{ - cdev_t dev = ap->a_head.a_dev; - struct ucom_softc *sc; - struct tty *tp; - - sc = devclass_get_softc(ucom_devclass, UCOMUNIT(dev)); - - lwkt_gettoken(&tty_token); - tp = sc->sc_tty; - - DPRINTF(("%s: ucomclose: unit = %d\n", - device_get_nameunit(sc->sc_dev), UCOMUNIT(dev))); - - if (!ISSET(tp->t_state, TS_ISOPEN)) - goto quit; - - crit_enter(); - (*linesw[tp->t_line].l_close)(tp, ap->a_fflag); - disc_optim(tp, &tp->t_termios, sc); - ttyclose(tp); - crit_exit(); - - if (sc->sc_dying) - goto quit; - - if (!ISSET(tp->t_state, TS_ISOPEN)) { - /* - * Although we got a last close, the device may still be in - * use; e.g. if this was the dialout node, and there are still - * processes waiting for carrier on the non-dialout node. - */ - ucom_cleanup(sc); - } - - if (sc->sc_callback->ucom_close != NULL) - sc->sc_callback->ucom_close(sc->sc_parent, sc->sc_portno); - -quit: - if (tp->t_dev) { - release_dev(tp->t_dev); - tp->t_dev = NULL; - } - - if (--sc->sc_refcnt < 0) - usb_detach_wakeup(sc->sc_dev); - - lwkt_reltoken(&tty_token); - return (0); -} - -static int -ucomread(struct dev_read_args *ap) -{ - cdev_t dev = ap->a_head.a_dev; - struct ucom_softc *sc; - struct tty *tp; - int error; - - sc = devclass_get_softc(ucom_devclass, UCOMUNIT(dev)); - lwkt_gettoken(&tty_token); - tp = sc->sc_tty; - - DPRINTF(("ucomread: tp = %p, flag = 0x%x\n", tp, ap->a_ioflag)); - - if (sc->sc_dying) { - lwkt_reltoken(&tty_token); - return (EIO); - } - - error = (*linesw[tp->t_line].l_read)(tp, ap->a_uio, ap->a_ioflag); - - DPRINTF(("ucomread: error = %d\n", error)); - - lwkt_reltoken(&tty_token); - return (error); -} - -static int -ucomwrite(struct dev_write_args *ap) -{ - cdev_t dev = ap->a_head.a_dev; - struct ucom_softc *sc; - struct tty *tp; - int error; - - sc = devclass_get_softc(ucom_devclass, UCOMUNIT(dev)); - lwkt_gettoken(&tty_token); - tp = sc->sc_tty; - - DPRINTF(("ucomwrite: tp = %p, flag = 0x%x\n", tp, ap->a_ioflag)); - - if (sc->sc_dying) { - lwkt_reltoken(&tty_token); - return (EIO); - } - - error = (*linesw[tp->t_line].l_write)(tp, ap->a_uio, ap->a_ioflag); - - DPRINTF(("ucomwrite: error = %d\n", error)); - - lwkt_reltoken(&tty_token); - return (error); -} - -static int -ucomioctl(struct dev_ioctl_args *ap) -{ - cdev_t dev = ap->a_head.a_dev; - struct ucom_softc *sc; - struct tty *tp; - int error; - int d; - - sc = devclass_get_softc(ucom_devclass, UCOMUNIT(dev)); - lwkt_gettoken(&tty_token); - tp = sc->sc_tty; - - if (sc->sc_dying) { - lwkt_reltoken(&tty_token); - return (EIO); - } - - DPRINTF(("ucomioctl: cmd = 0x%08lx\n", ap->a_cmd)); - - error = (*linesw[tp->t_line].l_ioctl)(tp, ap->a_cmd, ap->a_data, - ap->a_fflag, ap->a_cred); - if (error != ENOIOCTL) { - DPRINTF(("ucomioctl: l_ioctl: error = %d\n", error)); - lwkt_reltoken(&tty_token); - return (error); - } - - crit_enter(); - - error = ttioctl(tp, ap->a_cmd, ap->a_data, ap->a_fflag); - disc_optim(tp, &tp->t_termios, sc); - if (error != ENOIOCTL) { - crit_exit(); - DPRINTF(("ucomioctl: ttioctl: error = %d\n", error)); - lwkt_reltoken(&tty_token); - return (error); - } - - if (sc->sc_callback->ucom_ioctl != NULL) { - error = sc->sc_callback->ucom_ioctl(sc->sc_parent, - sc->sc_portno, - ap->a_cmd, ap->a_data, - ap->a_fflag, curthread); - if (error >= 0) { - crit_exit(); - lwkt_reltoken(&tty_token); - return (error); - } - } - - error = 0; - - DPRINTF(("ucomioctl: our cmd = 0x%08lx\n", ap->a_cmd)); - - switch (ap->a_cmd) { - case TIOCSBRK: - DPRINTF(("ucomioctl: TIOCSBRK\n")); - ucom_break(sc, 1); - break; - case TIOCCBRK: - DPRINTF(("ucomioctl: TIOCCBRK\n")); - ucom_break(sc, 0); - break; - - case TIOCSDTR: - DPRINTF(("ucomioctl: TIOCSDTR\n")); - (void)ucomctl(sc, TIOCM_DTR, DMBIS); - break; - case TIOCCDTR: - DPRINTF(("ucomioctl: TIOCCDTR\n")); - (void)ucomctl(sc, TIOCM_DTR, DMBIC); - break; - - case TIOCMSET: - d = *(int *)ap->a_data; - DPRINTF(("ucomioctl: TIOCMSET, 0x%x\n", d)); - (void)ucomctl(sc, d, DMSET); - break; - case TIOCMBIS: - d = *(int *)ap->a_data; - DPRINTF(("ucomioctl: TIOCMBIS, 0x%x\n", d)); - (void)ucomctl(sc, d, DMBIS); - break; - case TIOCMBIC: - d = *(int *)ap->a_data; - DPRINTF(("ucomioctl: TIOCMBIC, 0x%x\n", d)); - (void)ucomctl(sc, d, DMBIC); - break; - case TIOCMGET: - d = ucomctl(sc, 0, DMGET); - DPRINTF(("ucomioctl: TIOCMGET, 0x%x\n", d)); - *(int *)ap->a_data = d; - break; - - default: - DPRINTF(("ucomioctl: error: our cmd = 0x%08lx\n", ap->a_cmd)); - error = ENOTTY; - break; - } - - crit_exit(); - - lwkt_reltoken(&tty_token); - return (error); -} - -/* - * NOTE: Must be called with tty_token held. - */ -static int -ucomctl(struct ucom_softc *sc, int bits, int how) -{ - int mcr; - int msr; - int onoff; - - ASSERT_LWKT_TOKEN_HELD(&tty_token); - DPRINTF(("ucomctl: bits = 0x%x, how = %d\n", bits, how)); - - if (how == DMGET) { - SET(bits, TIOCM_LE); /* always set TIOCM_LE bit */ - DPRINTF(("ucomctl: DMGET: LE")); - - mcr = sc->sc_mcr; - if (ISSET(mcr, UMCR_DTR)) { - SET(bits, TIOCM_DTR); - DPRINTF((" DTR")); - } - if (ISSET(mcr, UMCR_RTS)) { - SET(bits, TIOCM_RTS); - DPRINTF((" RTS")); - } - - msr = sc->sc_msr; - if (ISSET(msr, UMSR_CTS)) { - SET(bits, TIOCM_CTS); - DPRINTF((" CTS")); - } - if (ISSET(msr, UMSR_DCD)) { - SET(bits, TIOCM_CD); - DPRINTF((" CD")); - } - if (ISSET(msr, UMSR_DSR)) { - SET(bits, TIOCM_DSR); - DPRINTF((" DSR")); - } - if (ISSET(msr, UMSR_RI)) { - SET(bits, TIOCM_RI); - DPRINTF((" RI")); - } - - DPRINTF(("\n")); - - return (bits); - } - - mcr = 0; - if (ISSET(bits, TIOCM_DTR)) - SET(mcr, UMCR_DTR); - if (ISSET(bits, TIOCM_RTS)) - SET(mcr, UMCR_RTS); - - switch (how) { - case DMSET: - sc->sc_mcr = mcr; - break; - case DMBIS: - sc->sc_mcr |= mcr; - break; - case DMBIC: - sc->sc_mcr &= ~mcr; - break; - } - - onoff = ISSET(sc->sc_mcr, UMCR_DTR) ? 1 : 0; - ucom_dtr(sc, onoff); - - onoff = ISSET(sc->sc_mcr, UMCR_RTS) ? 1 : 0; - ucom_rts(sc, onoff); - - return (0); -} - -/* - * NOTE: Must be called with tty_token held. - */ -static void -ucom_break(struct ucom_softc *sc, int onoff) -{ - ASSERT_LWKT_TOKEN_HELD(&tty_token); - DPRINTF(("ucom_break: onoff = %d\n", onoff)); - - if (sc->sc_callback->ucom_set == NULL) - return; - sc->sc_callback->ucom_set(sc->sc_parent, sc->sc_portno, - UCOM_SET_BREAK, onoff); -} - -/* - * NOTE: Must be called with tty_token held. - */ -static void -ucom_dtr(struct ucom_softc *sc, int onoff) -{ - ASSERT_LWKT_TOKEN_HELD(&tty_token); - DPRINTF(("ucom_dtr: onoff = %d\n", onoff)); - - if (sc->sc_callback->ucom_set == NULL) - return; - sc->sc_callback->ucom_set(sc->sc_parent, sc->sc_portno, - UCOM_SET_DTR, onoff); -} - -/* - * NOTE: Must be called with tty_token held. - */ -static void -ucom_rts(struct ucom_softc *sc, int onoff) -{ - ASSERT_LWKT_TOKEN_HELD(&tty_token); - DPRINTF(("ucom_rts: onoff = %d\n", onoff)); - - if (sc->sc_callback->ucom_set == NULL) - return; - sc->sc_callback->ucom_set(sc->sc_parent, sc->sc_portno, - UCOM_SET_RTS, onoff); -} - -void -ucom_status_change(struct ucom_softc *sc) -{ - struct tty *tp = sc->sc_tty; - u_char old_msr; - int onoff; - - lwkt_gettoken(&tty_token); - if (sc->sc_callback->ucom_get_status == NULL) { - sc->sc_lsr = 0; - sc->sc_msr = 0; - lwkt_reltoken(&tty_token); - return; - } - - old_msr = sc->sc_msr; - sc->sc_callback->ucom_get_status(sc->sc_parent, sc->sc_portno, - &sc->sc_lsr, &sc->sc_msr); - if (ISSET((sc->sc_msr ^ old_msr), UMSR_DCD)) { - if (sc->sc_poll == 0) { - lwkt_reltoken(&tty_token); - return; - } - onoff = ISSET(sc->sc_msr, UMSR_DCD) ? 1 : 0; - DPRINTF(("ucom_status_change: DCD changed to %d\n", onoff)); - (*linesw[tp->t_line].l_modem)(tp, onoff); - } - lwkt_reltoken(&tty_token); -} - -static int -ucomparam(struct tty *tp, struct termios *t) -{ - struct ucom_softc *sc; - int error; - usbd_status uerr; - - sc = devclass_get_softc(ucom_devclass, UCOMUNIT(tp->t_dev)); - - lwkt_gettoken(&tty_token); - if (sc->sc_dying) { - lwkt_reltoken(&tty_token); - return (EIO); - } - - DPRINTF(("ucomparam: sc = %p\n", sc)); - - /* Check requested parameters. */ - if (t->c_ospeed < 0) { - DPRINTF(("ucomparam: negative ospeed\n")); - lwkt_reltoken(&tty_token); - return (EINVAL); - } - if (t->c_ispeed && t->c_ispeed != t->c_ospeed) { - DPRINTF(("ucomparam: mismatch ispeed and ospeed\n")); - lwkt_reltoken(&tty_token); - return (EINVAL); - } - - /* - * If there were no changes, don't do anything. This avoids dropping - * input and improves performance when all we did was frob things like - * VMIN and VTIME. - */ - if (tp->t_ospeed == t->c_ospeed && - tp->t_cflag == t->c_cflag) { - lwkt_reltoken(&tty_token); - return (0); - } - - /* And copy to tty. */ - tp->t_ispeed = 0; - tp->t_ospeed = t->c_ospeed; - tp->t_cflag = t->c_cflag; - - if (sc->sc_callback->ucom_param == NULL) { - lwkt_reltoken(&tty_token); - return (0); - } - - ucomstopread(sc); - - error = sc->sc_callback->ucom_param(sc->sc_parent, sc->sc_portno, t); - if (error) { - DPRINTF(("ucomparam: callback: error = %d\n", error)); - lwkt_reltoken(&tty_token); - return (error); - } - - ttsetwater(tp); - - if (t->c_cflag & CRTS_IFLOW) { - sc->sc_state |= UCS_RTS_IFLOW; - } else if (sc->sc_state & UCS_RTS_IFLOW) { - sc->sc_state &= ~UCS_RTS_IFLOW; - (void)ucomctl(sc, UMCR_RTS, DMBIS); - } - - disc_optim(tp, t, sc); - - uerr = ucomstartread(sc); - if (uerr != USBD_NORMAL_COMPLETION) { - lwkt_reltoken(&tty_token); - return (EIO); - } - - lwkt_reltoken(&tty_token); - return (0); -} - -static void -ucomstart(struct tty *tp) -{ - struct ucom_softc *sc; - struct cblock *cbp; - usbd_status err; - u_char *data; - int cnt; - - sc = devclass_get_softc(ucom_devclass, UCOMUNIT(tp->t_dev)); - DPRINTF(("ucomstart: sc = %p\n", sc)); - - lwkt_gettoken(&tty_token); - - if (sc->sc_dying) { - lwkt_reltoken(&tty_token); - return; - } - - crit_enter(); - - if (tp->t_state & TS_TBLOCK) { - if (ISSET(sc->sc_mcr, UMCR_RTS) && - ISSET(sc->sc_state, UCS_RTS_IFLOW)) { - DPRINTF(("ucomstart: clear RTS\n")); - (void)ucomctl(sc, UMCR_RTS, DMBIC); - } - } else { - if (!ISSET(sc->sc_mcr, UMCR_RTS) && - tp->t_rawq.c_cc <= tp->t_ilowat && - ISSET(sc->sc_state, UCS_RTS_IFLOW)) { - DPRINTF(("ucomstart: set RTS\n")); - (void)ucomctl(sc, UMCR_RTS, DMBIS); - } - } - - if (ISSET(tp->t_state, TS_BUSY | TS_TIMEOUT | TS_TTSTOP)) { - ttwwakeup(tp); - DPRINTF(("ucomstart: stopped\n")); - goto out; - } - - if (tp->t_outq.c_cc <= tp->t_olowat) { - if (ISSET(tp->t_state, TS_SO_OLOWAT)) { - CLR(tp->t_state, TS_SO_OLOWAT); - wakeup(TSA_OLOWAT(tp)); - } - KNOTE(&tp->t_wkq.ki_note, 0); - if (tp->t_outq.c_cc == 0) { - if (ISSET(tp->t_state, TS_BUSY | TS_SO_OCOMPLETE) == - TS_SO_OCOMPLETE && tp->t_outq.c_cc == 0) { - CLR(tp->t_state, TS_SO_OCOMPLETE); - wakeup(TSA_OCOMPLETE(tp)); - } - goto out; - } - } - - /* Grab the first contiguous region of buffer space. */ - data = tp->t_outq.c_cf; - cbp = (struct cblock *) ((intptr_t) tp->t_outq.c_cf & ~CROUND); - cnt = min((char *) (cbp+1) - tp->t_outq.c_cf, tp->t_outq.c_cc); - - if (cnt == 0) { - DPRINTF(("ucomstart: cnt == 0\n")); - goto out; - } - - SET(tp->t_state, TS_BUSY); - - if (cnt > sc->sc_obufsize) { - DPRINTF(("ucomstart: big buffer %d chars\n", cnt)); - cnt = sc->sc_obufsize; - } - if (sc->sc_callback->ucom_write != NULL) - sc->sc_callback->ucom_write(sc->sc_parent, sc->sc_portno, - sc->sc_obuf, data, &cnt); - else - memcpy(sc->sc_obuf, data, cnt); - - DPRINTF(("ucomstart: %d chars\n", cnt)); - usbd_setup_xfer(sc->sc_oxfer, sc->sc_bulkout_pipe, - (usbd_private_handle)sc, sc->sc_obuf, cnt, - USBD_NO_COPY, USBD_NO_TIMEOUT, ucomwritecb); - /* What can we do on error? */ - err = usbd_transfer(sc->sc_oxfer); - if (err != USBD_IN_PROGRESS) - kprintf("ucomstart: err=%s\n", usbd_errstr(err)); - - ttwwakeup(tp); - - out: - crit_exit(); - lwkt_reltoken(&tty_token); -} - -static void -ucomstop(struct tty *tp, int flag) -{ - struct ucom_softc *sc; - - sc = devclass_get_softc(ucom_devclass, UCOMUNIT(tp->t_dev)); - - DPRINTF(("ucomstop: %d\n", flag)); - - lwkt_gettoken(&tty_token); - if (flag & FREAD) { - /* - * This is just supposed to flush pending receive data, - * not stop the reception of data entirely! - */ - DPRINTF(("ucomstop: read\n")); - ucomstopread(sc); - ucomstartread(sc); - } - - if (flag & FWRITE) { - DPRINTF(("ucomstop: write\n")); - crit_enter(); - if (ISSET(tp->t_state, TS_BUSY)) { - /* XXX do what? */ - if (!ISSET(tp->t_state, TS_TTSTOP)) - SET(tp->t_state, TS_FLUSH); - } - crit_exit(); - } - - DPRINTF(("ucomstop: done\n")); - lwkt_reltoken(&tty_token); -} - -static void -ucomwritecb(usbd_xfer_handle xfer, usbd_private_handle p, usbd_status status) -{ - struct ucom_softc *sc = (struct ucom_softc *)p; - struct tty *tp = sc->sc_tty; - u_int32_t cc; - - lwkt_gettoken(&tty_token); - DPRINTF(("ucomwritecb: status = %d\n", status)); - - if (status == USBD_CANCELLED || sc->sc_dying) - goto error; - - if (status != USBD_NORMAL_COMPLETION) { - kprintf("%s: ucomwritecb: %s\n", - device_get_nameunit(sc->sc_dev), usbd_errstr(status)); - if (status == USBD_STALLED) - usbd_clear_endpoint_stall_async(sc->sc_bulkin_pipe); - /* - * XXX. We may need a flag to sequence ucomstopread() and - * ucomstartread() to handle the case where ucomstartread() - * is called after ucomstopread() but before the request has - * been properly canceled? - */ - goto error; - } - - usbd_get_xfer_status(xfer, NULL, NULL, &cc, NULL); - DPRINTF(("ucomwritecb: cc = %d\n", cc)); - if (cc <= sc->sc_opkthdrlen) { - kprintf("%s: sent size too small, cc = %d\n", - device_get_nameunit(sc->sc_dev), cc); - goto error; - } - - /* convert from USB bytes to tty bytes */ - cc -= sc->sc_opkthdrlen; - - crit_enter(); - CLR(tp->t_state, TS_BUSY); - if (ISSET(tp->t_state, TS_FLUSH)) - CLR(tp->t_state, TS_FLUSH); - else - ndflush(&tp->t_outq, cc); - (*linesw[tp->t_line].l_start)(tp); - crit_exit(); - - lwkt_reltoken(&tty_token); - return; - - error: - crit_enter(); - CLR(tp->t_state, TS_BUSY); - crit_exit(); - lwkt_reltoken(&tty_token); - return; -} - -/* - * NOTE: Must be called with tty_token held - */ -static usbd_status -ucomstartread(struct ucom_softc *sc) -{ - usbd_status err; - - ASSERT_LWKT_TOKEN_HELD(&tty_token); - DPRINTF(("ucomstartread: start\n")); - - sc->sc_state &= ~UCS_RXSTOP; - - if (sc->sc_bulkin_pipe == NULL) - return (USBD_NORMAL_COMPLETION); - - usbd_setup_xfer(sc->sc_ixfer, sc->sc_bulkin_pipe, - (usbd_private_handle)sc, - sc->sc_ibuf, sc->sc_ibufsize, - USBD_SHORT_XFER_OK | USBD_NO_COPY, - USBD_NO_TIMEOUT, ucomreadcb); - - err = usbd_transfer(sc->sc_ixfer); - if (err != USBD_IN_PROGRESS) { - DPRINTF(("ucomstartread: err = %s\n", usbd_errstr(err))); - return (err); - } - - return (USBD_NORMAL_COMPLETION); -} - -static void -ucomreadcb(usbd_xfer_handle xfer, usbd_private_handle p, usbd_status status) -{ - lwkt_gettoken(&tty_token); - - struct ucom_softc *sc = (struct ucom_softc *)p; - struct tty *tp = sc->sc_tty; - int (*rint) (int c, struct tty *tp) = linesw[tp->t_line].l_rint; - usbd_status err; - u_int32_t cc; - u_char *cp; - int lostcc; - - DPRINTF(("ucomreadcb: status = %d\n", status)); - - if (status != USBD_NORMAL_COMPLETION) { - if (!(sc->sc_state & UCS_RXSTOP)) - kprintf("%s: ucomreadcb: %s\n", - device_get_nameunit(sc->sc_dev), usbd_errstr(status)); - if (status == USBD_STALLED) - usbd_clear_endpoint_stall_async(sc->sc_bulkin_pipe); - /* XXX we should restart after some delay. */ - lwkt_reltoken(&tty_token); - return; - } - - usbd_get_xfer_status(xfer, NULL, (void **)&cp, &cc, NULL); - DPRINTF(("ucomreadcb: got %d chars, tp = %p\n", cc, tp)); - if (cc == 0) - goto resubmit; - - if (sc->sc_callback->ucom_read != NULL) { - sc->sc_callback->ucom_read(sc->sc_parent, sc->sc_portno, - &cp, &cc); - } - - if (cc > sc->sc_ibufsize) { - kprintf("%s: invalid receive data size, %d chars\n", - device_get_nameunit(sc->sc_dev), cc); - goto resubmit; - } - if (cc < 1) - goto resubmit; - - crit_enter(); - if (tp->t_state & TS_CAN_BYPASS_L_RINT) { - if (tp->t_rawq.c_cc + cc > tp->t_ihiwat - && (sc->sc_state & UCS_RTS_IFLOW - || tp->t_iflag & IXOFF) - && !(tp->t_state & TS_TBLOCK)) - ttyblock(tp); - lostcc = b_to_q((char *)cp, cc, &tp->t_rawq); - tp->t_rawcc += cc; - if (sc->hotchar) { - while (cc) { - if (*cp == sc->hotchar) - break; - --cc; - ++cp; - } - if (cc) - setsofttty(); - } - ttwakeup(tp); - if (tp->t_state & TS_TTSTOP - && (tp->t_iflag & IXANY - || tp->t_cc[VSTART] == tp->t_cc[VSTOP])) { - tp->t_state &= ~TS_TTSTOP; - tp->t_lflag &= ~FLUSHO; - ucomstart(tp); - } - if (lostcc > 0) - kprintf("%s: lost %d chars\n", device_get_nameunit(sc->sc_dev), - lostcc); - } else { - /* Give characters to tty layer. */ - while (cc > 0) { - DPRINTFN(7, ("ucomreadcb: char = 0x%02x\n", *cp)); - if ((*rint)(*cp, tp) == -1) { - /* XXX what should we do? */ - kprintf("%s: lost %d chars\n", - device_get_nameunit(sc->sc_dev), cc); - break; - } - cc--; - cp++; - } - } - crit_exit(); - -resubmit: - err = ucomstartread(sc); - if (err) { - kprintf("%s: read start failed\n", device_get_nameunit(sc->sc_dev)); - /* XXX what should we dow now? */ - } - - if ((sc->sc_state & UCS_RTS_IFLOW) && !ISSET(sc->sc_mcr, UMCR_RTS) - && !(tp->t_state & TS_TBLOCK)) - ucomctl(sc, UMCR_RTS, DMBIS); - - lwkt_reltoken(&tty_token); -} - -/* - * NOTE: Must be called with tty_token held. - */ -static void -ucom_cleanup(struct ucom_softc *sc) -{ - ASSERT_LWKT_TOKEN_HELD(&tty_token); - DPRINTF(("ucom_cleanup: closing pipes\n")); - - ucom_shutdown(sc); - if (sc->sc_bulkin_pipe != NULL) { - usbd_abort_pipe(sc->sc_bulkin_pipe); - usbd_close_pipe(sc->sc_bulkin_pipe); - sc->sc_bulkin_pipe = NULL; - } - if (sc->sc_bulkout_pipe != NULL) { - usbd_abort_pipe(sc->sc_bulkout_pipe); - usbd_close_pipe(sc->sc_bulkout_pipe); - sc->sc_bulkout_pipe = NULL; - } - if (sc->sc_ixfer != NULL) { - usbd_free_xfer(sc->sc_ixfer); - sc->sc_ixfer = NULL; - } - if (sc->sc_oxfer != NULL) { - usbd_free_xfer(sc->sc_oxfer); - sc->sc_oxfer = NULL; - } -} - -/* - * NOTE: Must be called with tty_token held. - */ -static void -ucomstopread(struct ucom_softc *sc) -{ - usbd_status err; - - ASSERT_LWKT_TOKEN_HELD(&tty_token); - DPRINTF(("ucomstopread: enter\n")); - - if (!(sc->sc_state & UCS_RXSTOP)) { - sc->sc_state |= UCS_RXSTOP; - if (sc->sc_bulkin_pipe == NULL) { - DPRINTF(("ucomstopread: bulkin pipe NULL\n")); - return; - } - err = usbd_abort_pipe(sc->sc_bulkin_pipe); - if (err) { - DPRINTF(("ucomstopread: err = %s\n", - usbd_errstr(err))); - } - } - - DPRINTF(("ucomstopread: leave\n")); -} - -/* - * NOTE: Must be called with tty_token held. - */ -static void -disc_optim(struct tty *tp, struct termios *t, struct ucom_softc *sc) -{ - ASSERT_LWKT_TOKEN_HELD(&tty_token); - if (!(t->c_iflag & (ICRNL | IGNCR | IMAXBEL | INLCR | ISTRIP | IXON)) - && (!(t->c_iflag & BRKINT) || (t->c_iflag & IGNBRK)) - && (!(t->c_iflag & PARMRK) - || (t->c_iflag & (IGNPAR | IGNBRK)) == (IGNPAR | IGNBRK)) - && !(t->c_lflag & (ECHO | ICANON | IEXTEN | ISIG | PENDIN)) - && linesw[tp->t_line].l_rint == ttyinput) { - DPRINTF(("disc_optim: bypass l_rint\n")); - tp->t_state |= TS_CAN_BYPASS_L_RINT; - } else { - DPRINTF(("disc_optim: can't bypass l_rint\n")); - tp->t_state &= ~TS_CAN_BYPASS_L_RINT; - } - sc->hotchar = linesw[tp->t_line].l_hotchar; -} diff --git a/sys/dev/usbmisc/ucom/ucomvar.h b/sys/dev/usbmisc/ucom/ucomvar.h deleted file mode 100644 index 4e0f17bd8e..0000000000 --- a/sys/dev/usbmisc/ucom/ucomvar.h +++ /dev/null @@ -1,186 +0,0 @@ -/* - * $NetBSD: ucomvar.h,v 1.9 2001/01/23 21:56:17 augustss Exp $ - * $FreeBSD: src/sys/dev/usb/ucomvar.h,v 1.2 2002/07/31 14:34:35 joe Exp $ - * $DragonFly: src/sys/dev/usbmisc/ucom/ucomvar.h,v 1.6 2007/07/03 19:28:16 hasso Exp $ - */ - -/*- - * Copyright (c) 2001-2002, Shunsuke Akiyama . - * 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. - */ - -/* - * Copyright (c) 1999 The NetBSD Foundation, Inc. - * All rights reserved. - * - * This code is derived from software contributed to The NetBSD Foundation - * by Lennart Augustsson (lennart@augustsson.net) at - * Carlstedt Research & Technology. - * - * 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. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the NetBSD - * Foundation, Inc. and its contributors. - * 4. Neither the name of The NetBSD Foundation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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. - */ - -/* Module interface related macros */ -#define UCOM_MODVER 1 - -#define UCOM_MINVER 1 -#define UCOM_PREFVER UCOM_MODVER -#define UCOM_MAXVER 1 - -/* Macros to clear/set/test flags. */ -#define SET(t, f) (t) |= (f) -#define CLR(t, f) (t) &= ~((unsigned)(f)) -#define ISSET(t, f) ((t) & (f)) - -#define UCOM_CALLOUT_MASK 0x80 - -#define UCOMUNIT_MASK 0x3ff7f -#define UCOMDIALOUT_MASK 0x80000 -#define UCOMCALLUNIT_MASK 0x40000 - -#define UCOMUNIT(x) (minor(x) & UCOMUNIT_MASK) -#define UCOMDIALOUT(x) (minor(x) & UCOMDIALOUT_MASK) -#define UCOMCALLUNIT(x) (minor(x) & UCOMCALLUNIT_MASK) - -#define UCOM_UNK_PORTNO -1 /* XXX */ - -struct ucom_softc; - -struct ucom_callback { - void (*ucom_get_status)(void *, int, u_char *, u_char *); - void (*ucom_set)(void *, int, int, int); -#define UCOM_SET_DTR 1 -#define UCOM_SET_RTS 2 -#define UCOM_SET_BREAK 3 - int (*ucom_param)(void *, int, struct termios *); - int (*ucom_ioctl)(void *, int, u_long, caddr_t, int, struct thread *); - int (*ucom_open)(void *, int); - void (*ucom_close)(void *, int); - void (*ucom_read)(void *, int, u_char **, u_int32_t *); - void (*ucom_write)(void *, int, u_char *, u_char *, u_int32_t *); -}; - -/* modem control register */ -#define UMCR_RTS 0x02 /* Request To Send */ -#define UMCR_DTR 0x01 /* Data Terminal Ready */ - -/* line status register */ -#define ULSR_RCV_FIFO 0x80 -#define ULSR_TSRE 0x40 /* Transmitter empty: byte sent */ -#define ULSR_TXRDY 0x20 /* Transmitter buffer empty */ -#define ULSR_BI 0x10 /* Break detected */ -#define ULSR_FE 0x08 /* Framing error: bad stop bit */ -#define ULSR_PE 0x04 /* Parity error */ -#define ULSR_OE 0x02 /* Overrun, lost incoming byte */ -#define ULSR_RXRDY 0x01 /* Byte ready in Receive Buffer */ -#define ULSR_RCV_MASK 0x1f /* Mask for incoming data or error */ - -/* modem status register */ -/* All deltas are from the last read of the MSR. */ -#define UMSR_DCD 0x80 /* Current Data Carrier Detect */ -#define UMSR_RI 0x40 /* Current Ring Indicator */ -#define UMSR_DSR 0x20 /* Current Data Set Ready */ -#define UMSR_CTS 0x10 /* Current Clear to Send */ -#define UMSR_DDCD 0x08 /* DCD has changed state */ -#define UMSR_TERI 0x04 /* RI has toggled low to high */ -#define UMSR_DDSR 0x02 /* DSR has changed state */ -#define UMSR_DCTS 0x01 /* CTS has changed state */ - -/* ucom state declarations */ -#define UCS_RXSTOP 0x0001 /* Rx stopped */ -#define UCS_RTS_IFLOW 0x0008 /* use RTS input flow control */ - -struct ucom_softc { - device_t sc_dev; /* base device */ - usbd_device_handle sc_udev; /* USB device */ - usbd_interface_handle sc_iface; /* data interface */ - - int sc_bulkin_no; /* bulk in endpoint address */ - usbd_pipe_handle sc_bulkin_pipe; /* bulk in pipe */ - usbd_xfer_handle sc_ixfer; /* read request */ - u_char *sc_ibuf; /* read buffer */ - u_int sc_ibufsize; /* read buffer size */ - u_int sc_ibufsizepad; /* read buffer size padded */ - - int sc_bulkout_no; /* bulk out endpoint address */ - usbd_pipe_handle sc_bulkout_pipe;/* bulk out pipe */ - usbd_xfer_handle sc_oxfer; /* write request */ - u_char *sc_obuf; /* write buffer */ - u_int sc_obufsize; /* write buffer size */ - u_int sc_opkthdrlen; /* header length of - output packet */ - - struct ucom_callback *sc_callback; - void *sc_parent; - int sc_portno; - - struct tty *sc_tty; /* our tty */ - - int sc_state; - - int sc_poll; - u_char hotchar; - - u_char sc_lsr; - u_char sc_msr; - u_char sc_mcr; - - u_char sc_opening; /* lock during open */ - int sc_refcnt; - u_char sc_dying; /* disconnecting */ - - cdev_t dev; /* special device node */ -}; - -extern devclass_t ucom_devclass; - -int ucom_attach(struct ucom_softc *); -int ucom_detach(struct ucom_softc *); -void ucom_status_change(struct ucom_softc *); diff --git a/sys/dev/usbmisc/ufm/Makefile b/sys/dev/usbmisc/ufm/Makefile deleted file mode 100644 index 5e5cf395e8..0000000000 --- a/sys/dev/usbmisc/ufm/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -# $FreeBSD: src/sys/modules/ufm/Makefile,v 1.1.2.1 2002/03/04 04:01:36 alfred Exp $ -# $DragonFly: src/sys/dev/usbmisc/ufm/Makefile,v 1.4 2004/08/13 17:51:06 dillon Exp $ - -.PATH: ${.CURDIR}/../../dev/usb ${.CURDIR}/../../../bus/usb -KMOD= ufm -SRCS= bus_if.h device_if.h opt_usb.h ufm.c dsbr100io.h - -.include diff --git a/sys/dev/usbmisc/ufm/ufm.c b/sys/dev/usbmisc/ufm/ufm.c deleted file mode 100644 index 962788e3c4..0000000000 --- a/sys/dev/usbmisc/ufm/ufm.c +++ /dev/null @@ -1,380 +0,0 @@ -/* - * Copyright (c) 2001 M. Warner Losh - * 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. - * - * This code is based on ugen.c and ulpt.c developed by Lennart Augustsson. - * This code includes software developed by the NetBSD Foundation, Inc. and - * its contributors. - */ - -/* - * $FreeBSD: src/sys/dev/usb/ufm.c,v 1.16 2003/10/04 21:41:01 joe Exp $ - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include - -#ifdef USB_DEBUG -#define DPRINTF(x) if (ufmdebug) kprintf x -#define DPRINTFN(n,x) if (ufmdebug>(n)) kprintf x -int ufmdebug = 0; -SYSCTL_NODE(_hw_usb, OID_AUTO, ufm, CTLFLAG_RW, 0, "USB ufm"); -SYSCTL_INT(_hw_usb_ufm, OID_AUTO, debug, CTLFLAG_RW, - &ufmdebug, 0, "ufm debug level"); -#else -#define DPRINTF(x) -#define DPRINTFN(n,x) -#endif - -d_open_t ufmopen; -d_close_t ufmclose; -d_ioctl_t ufmioctl; - -static struct dev_ops ufm_ops = { - { "ufm", 0, 0 }, - .d_open = ufmopen, - .d_close = ufmclose, - .d_ioctl = ufmioctl, -}; - -#define FM_CMD0 0x00 -#define FM_CMD_SET_FREQ 0x01 -#define FM_CMD2 0x02 - -struct ufm_softc { - device_t sc_dev; - usbd_device_handle sc_udev; - usbd_interface_handle sc_iface; - - int sc_opened; - int sc_epaddr; - int sc_freq; - - int sc_refcnt; -}; - -#define UFMUNIT(n) (minor(n)) - -static device_probe_t ufm_match; -static device_attach_t ufm_attach; -static device_detach_t ufm_detach; - -static devclass_t ufm_devclass; - -static kobj_method_t ufm_methods[] = { - DEVMETHOD(device_probe, ufm_match), - DEVMETHOD(device_attach, ufm_attach), - DEVMETHOD(device_detach, ufm_detach), - DEVMETHOD_END -}; - -static driver_t ufm_driver = { - "ufm", - ufm_methods, - sizeof(struct ufm_softc) -}; - -MODULE_DEPEND(ufm, usb, 1, 1, 1); - -static int -ufm_match(device_t self) -{ - struct usb_attach_arg *uaa = device_get_ivars(self); - usb_device_descriptor_t *dd; - - DPRINTFN(10,("ufm_match\n")); - if (!uaa->iface) - return UMATCH_NONE; - - dd = usbd_get_device_descriptor(uaa->device); - - if (dd && - ((UGETW(dd->idVendor) == 0x04b4 && UGETW(dd->idProduct) == 0x1002))) - return UMATCH_VENDOR_PRODUCT; - else - return UMATCH_NONE; -} - -static int -ufm_attach(device_t self) -{ - struct ufm_softc *sc = device_get_softc(self); - struct usb_attach_arg *uaa = device_get_ivars(self); - usb_endpoint_descriptor_t *edesc; - usbd_interface_handle iface; - u_int8_t epcount; - usbd_status r; - char * ermsg = ""; - - DPRINTFN(10,("ufm_attach: sc=%p\n", sc)); - sc->sc_dev = self; - sc->sc_udev = uaa->device; - - if ((!uaa->device) || (!uaa->iface)) { - ermsg = "device or iface"; - goto nobulk; - } - sc->sc_iface = iface = uaa->iface; - sc->sc_opened = 0; - sc->sc_refcnt = 0; - - r = usbd_endpoint_count(iface, &epcount); - if (r != USBD_NORMAL_COMPLETION) { - ermsg = "endpoints"; - goto nobulk; - } - - edesc = usbd_interface2endpoint_descriptor(iface, 0); - if (!edesc) { - ermsg = "interface endpoint"; - goto nobulk; - } - sc->sc_epaddr = edesc->bEndpointAddress; - - /* XXX no error trapping, no storing of cdev_t */ - make_dev(&ufm_ops, device_get_unit(self), - UID_ROOT, GID_OPERATOR, - 0644, "ufm%d", device_get_unit(self)); - - DPRINTFN(10, ("ufm_attach: %p\n", sc->sc_udev)); - - return 0; - - nobulk: - kprintf("%s: could not find %s\n", device_get_nameunit(sc->sc_dev),ermsg); - return ENXIO; -} - - -int -ufmopen(struct dev_open_args *ap) -{ - cdev_t dev = ap->a_head.a_dev; - struct ufm_softc *sc; - - int unit = UFMUNIT(dev); - sc = devclass_get_softc(ufm_devclass, unit); - if (sc == NULL) - return (ENXIO); - - DPRINTFN(5, ("ufmopen: flag=%d, mode=%d, unit=%d\n", - ap->a_oflags, ap->a_devtype, unit)); - - if (sc->sc_opened) - return (EBUSY); - - if ((ap->a_oflags & (FWRITE|FREAD)) != (FWRITE|FREAD)) - return (EACCES); - - sc->sc_opened = 1; - return (0); -} - -int -ufmclose(struct dev_close_args *ap) -{ - cdev_t dev = ap->a_head.a_dev; - struct ufm_softc *sc; - - int unit = UFMUNIT(dev); - sc = devclass_get_softc(ufm_devclass, unit); - - DPRINTFN(5, ("ufmclose: flag=%d, mode=%d, unit=%d\n", - ap->a_fflag, ap->a_devtype, unit)); - sc->sc_opened = 0; - sc->sc_refcnt = 0; - return 0; -} - -static int -ufm_do_req(struct ufm_softc *sc, u_int8_t reqtype, u_int8_t request, - u_int16_t value, u_int16_t index, u_int8_t len, void *retbuf) -{ - usb_device_request_t req; - usbd_status err; - - crit_enter(); - req.bmRequestType = reqtype; - req.bRequest = request; - USETW(req.wValue, value); - USETW(req.wIndex, index); - USETW(req.wLength, len); - err = usbd_do_request_flags(sc->sc_udev, &req, retbuf, 0, NULL, - USBD_DEFAULT_TIMEOUT); - crit_exit(); - if (err) { - kprintf("usbd_do_request_flags returned %#x\n", err); - return (EIO); - } - return (0); -} - -static int -ufm_set_freq(struct ufm_softc *sc, caddr_t addr) -{ - int freq = *(int *)addr; - u_int8_t ret; - - /* - * Freq now is in Hz. We need to convert it to the frequency - * that the radio wants. This frequency is 10.7MHz above - * the actual frequency. We then need to convert to - * units of 12.5kHz. We add one to the IFM to make rounding - * easier. - */ - sc->sc_freq = freq; - freq = (freq + 10700001) / 12500; - /* This appears to set the frequency */ - if (ufm_do_req(sc, UT_READ_VENDOR_DEVICE, FM_CMD_SET_FREQ, freq >> 8, - freq, 1, &ret) != 0) - return (EIO); - /* Not sure what this does */ - if (ufm_do_req(sc, UT_READ_VENDOR_DEVICE, FM_CMD0, 0x96, 0xb7, 1, - &ret) != 0) - return (EIO); - return (0); -} - -static int -ufm_get_freq(struct ufm_softc *sc, caddr_t addr) -{ - int *valp = (int *)addr; - *valp = sc->sc_freq; - return (0); -} - -static int -ufm_start(struct ufm_softc *sc, caddr_t addr) -{ - u_int8_t ret; - - if (ufm_do_req(sc, UT_READ_VENDOR_DEVICE, FM_CMD0, 0x00, 0xc7, - 1, &ret)) - return (EIO); - if (ufm_do_req(sc, UT_READ_VENDOR_DEVICE, FM_CMD2, 0x01, 0x00, - 1, &ret)) - return (EIO); - if (ret & 0x1) - return (EIO); - return (0); -} - -static int -ufm_stop(struct ufm_softc *sc, caddr_t addr) -{ - u_int8_t ret; - - if (ufm_do_req(sc, UT_READ_VENDOR_DEVICE, FM_CMD0, 0x16, 0x1C, - 1, &ret)) - return (EIO); - if (ufm_do_req(sc, UT_READ_VENDOR_DEVICE, FM_CMD2, 0x00, 0x00, - 1, &ret)) - return (EIO); - return (0); -} - -static int -ufm_get_stat(struct ufm_softc *sc, caddr_t addr) -{ - u_int8_t ret; - - /* - * Note, there's a 240ms settle time before the status - * will be valid, so tsleep that amount. hz/4 is a good - * approximation of that. Since this is a short sleep - * we don't try to catch any signals to keep things - * simple. - */ - tsleep(sc, 0, "ufmwait", hz/4); - if (ufm_do_req(sc, UT_READ_VENDOR_DEVICE, FM_CMD0, 0x00, 0x24, - 1, &ret)) - return (EIO); - *(int *)addr = ret; - - return (0); -} - -int -ufmioctl(struct dev_ioctl_args *ap) -{ - cdev_t dev = ap->a_head.a_dev; - caddr_t addr = ap->a_data; - struct ufm_softc *sc; - - int unit = UFMUNIT(dev); - int error = 0; - - sc = devclass_get_softc(ufm_devclass, unit); - - switch (ap->a_cmd) { - case FM_SET_FREQ: - error = ufm_set_freq(sc, addr); - break; - case FM_GET_FREQ: - error = ufm_get_freq(sc, addr); - break; - case FM_START: - error = ufm_start(sc, addr); - break; - case FM_STOP: - error = ufm_stop(sc, addr); - break; - case FM_GET_STAT: - error = ufm_get_stat(sc, addr); - break; - default: - return ENOTTY; - break; - } - return error; -} - -static int -ufm_detach(device_t self) -{ - DPRINTF(("%s: disconnected\n", device_get_nameunit(self))); - return 0; -} - -DRIVER_MODULE(ufm, uhub, ufm_driver, ufm_devclass, usbd_driver_load, NULL); diff --git a/sys/dev/usbmisc/uftdi/Makefile b/sys/dev/usbmisc/uftdi/Makefile deleted file mode 100644 index cf9c61d7d6..0000000000 --- a/sys/dev/usbmisc/uftdi/Makefile +++ /dev/null @@ -1,10 +0,0 @@ -# $FreeBSD: src/sys/modules/uftdi/Makefile,v 1.1.2.1 2002/11/21 01:28:18 ticso Exp $ -# $DragonFly: src/sys/dev/usbmisc/uftdi/Makefile,v 1.3 2004/08/13 17:51:06 dillon Exp $ - -S= ${.CURDIR}/../.. -.PATH: $S/dev/usb - -KMOD= uftdi -SRCS= uftdi.c uftdireg.h opt_usb.h device_if.h bus_if.h - -.include diff --git a/sys/dev/usbmisc/uftdi/uftdi.c b/sys/dev/usbmisc/uftdi/uftdi.c deleted file mode 100644 index 83fb09dfd7..0000000000 --- a/sys/dev/usbmisc/uftdi/uftdi.c +++ /dev/null @@ -1,999 +0,0 @@ -/* - * $NetBSD: uftdi.c,v 1.13 2002/09/23 05:51:23 simonb Exp $ - * $FreeBSD: src/sys/dev/usb/uftdi.c,v 1.37 2007/06/22 05:53:05 imp Exp $ - */ - -/*- - * Copyright (c) 2000 The NetBSD Foundation, Inc. - * All rights reserved. - * - * This code is derived from software contributed to The NetBSD Foundation - * by Lennart Augustsson (lennart@augustsson.net). - * - * 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. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the NetBSD - * Foundation, Inc. and its contributors. - * 4. Neither the name of The NetBSD Foundation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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. - */ - -/* - * FTDI FT8U100AX serial adapter driver - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include - -#include -#include - -#include -#include - -#include "../ucom/ucomvar.h" - -#include "uftdireg.h" - -#ifdef USB_DEBUG -static int uftdidebug = 0; -SYSCTL_NODE(_hw_usb, OID_AUTO, uftdi, CTLFLAG_RW, 0, "USB uftdi"); -SYSCTL_INT(_hw_usb_uftdi, OID_AUTO, debug, CTLFLAG_RW, - &uftdidebug, 0, "uftdi debug level"); -#define DPRINTF(x) do { \ - if (uftdidebug) \ - kprintf x; \ - } while (0) - -#define DPRINTFN(n, x) do { \ - if (uftdidebug > (n)) \ - kprintf x; \ - } while (0) - -#else -#define DPRINTF(x) -#define DPRINTFN(n,x) -#endif - -#define UFTDI_CONFIG_INDEX 0 -#define UFTDI_IFACE_INDEX 0 - -/* - * These are the maximum number of bytes transferred per frame. - * The output buffer size cannot be increased due to the size encoding. - */ -#define UFTDIIBUFSIZE 64 -#define UFTDIOBUFSIZE 64 - -struct uftdi_softc { - struct ucom_softc sc_ucom; - usbd_interface_handle sc_iface; /* interface */ - enum uftdi_type sc_type; - u_int sc_hdrlen; - u_char sc_msr; - u_char sc_lsr; - u_int last_lcr; -}; - -static void uftdi_get_status(void *, int portno, u_char *lsr, u_char *msr); -static void uftdi_set(void *, int, int, int); -static int uftdi_param(void *, int, struct termios *); -static int uftdi_open(void *sc, int portno); -static void uftdi_read(void *sc, int portno, u_char **ptr,u_int32_t *count); -static void uftdi_write(void *sc, int portno, u_char *to, u_char *from, - u_int32_t *count); -static void uftdi_break(void *sc, int portno, int onoff); -static int uftdi_8u232am_getrate(speed_t speed, int *rate); - -struct ucom_callback uftdi_callback = { - uftdi_get_status, - uftdi_set, - uftdi_param, - NULL, - uftdi_open, - NULL, - uftdi_read, - uftdi_write, -}; - -static const struct usb_devno uftdi_devs[] = { - /* FTDI chips defaults */ - { USB_DEVICE(0x0403, 0x0232) }, /* FT232 serial converter */ - { USB_DEVICE(0x0403, 0x6001) }, /* FT232 serial converter */ - { USB_DEVICE(0x0403, 0x6006) }, /* FT232 serial converter */ - { USB_DEVICE(0x0403, 0x6007) }, /* FT232 serial converter */ - { USB_DEVICE(0x0403, 0x6008) }, /* FT232 serial converter */ - { USB_DEVICE(0x0403, 0x6009) }, /* FT232 serial converter */ - { USB_DEVICE(0x0403, 0x6010) }, /* FT2232 dual port serial converter */ - { USB_DEVICE(0x0403, 0x8372) }, /* FTDI 8U100AX USB hub controller */ - - /* RR-CirKits products */ - { USB_DEVICE(0x0403, 0xc7d0) }, /* LocoBuffer USB */ - - /* DMX4ALL products */ - { USB_DEVICE(0x0403, 0xc850) }, /* DMX interface */ - - /* ASK products */ - { USB_DEVICE(0x0403, 0xc990) }, /* RDR 4X7 series card reader */ - { USB_DEVICE(0x0403, 0xc991) }, /* RDR 4X7 series card reader */ - { USB_DEVICE(0x0403, 0xc992) }, /* RDR 4X7 series card reader */ - { USB_DEVICE(0x0403, 0xc993) }, /* RDR 4X7 series card reader */ - { USB_DEVICE(0x0403, 0xc994) }, /* RDR 4X7 series card reader */ - { USB_DEVICE(0x0403, 0xc995) }, /* RDR 4X7 series card reader */ - { USB_DEVICE(0x0403, 0xc996) }, /* RDR 4X7 series card reader */ - { USB_DEVICE(0x0403, 0xc997) }, /* RDR 4X7 series card reader */ - - /* MJS products */ - { USB_DEVICE(0x0403, 0xca81) }, /* Sirius To PC Interface */ - - /* Starting Point Systems products */ - { USB_DEVICE(0x0403, 0xcaa0) }, /* µChameleon */ - - /* Tactrix products */ - { USB_DEVICE(0x0403, 0xcc48) }, /* OpenPort 1.3 Mitsubishi */ - { USB_DEVICE(0x0403, 0xcc49) }, /* OpenPort 1.3 Subaru */ - { USB_DEVICE(0x0403, 0xcc4a) }, /* OpenPort 1.3 Universal */ - - /* Plus GSM products */ - { USB_DEVICE(0x0403, 0xd070) }, /* Plus GSM iPlus */ - - /* Xsens Technologies BV products */ - { USB_DEVICE(0x0403, 0xd388) }, /* Serial interface */ - { USB_DEVICE(0x0403, 0xd389) }, /* Serial interface */ - { USB_DEVICE(0x0403, 0xd38a) }, /* Serial interface */ - { USB_DEVICE(0x0403, 0xd38b) }, /* Serial interface */ - { USB_DEVICE(0x0403, 0xd38c) }, /* Serial interface */ - { USB_DEVICE(0x0403, 0xd38d) }, /* Serial interface */ - { USB_DEVICE(0x0403, 0xd38e) }, /* Serial interface */ - { USB_DEVICE(0x0403, 0xd38f) }, /* Serial interface */ - - /* Eurami Group products */ - { USB_DEVICE(0x0403, 0xd678) }, /* Gamma Scout Online */ - - /* Westrex International products */ - { USB_DEVICE(0x0403, 0xdc00) }, /* Model 777 */ - { USB_DEVICE(0x0403, 0xdc01) }, /* Model 8900F */ - - /* ACG Identification GmbH products */ - { USB_DEVICE(0x0403, 0xdd20) }, /* HF Dual ISO Reader (RFID) */ - - /* Artemis products */ - { USB_DEVICE(0x0403, 0xdf28) }, /* CCD camera */ - - /* ATIK Instruments products */ - { USB_DEVICE(0x0403, 0xdf30) }, /* ATK-16 Grayscale Camera */ - { USB_DEVICE(0x0403, 0xdf31) }, /* ATK-16HR Grayscale Camera */ - { USB_DEVICE(0x0403, 0xdf32) }, /* ATK-16C Colour Camera */ - { USB_DEVICE(0x0403, 0xdf33) }, /* ATK-16HRC Colour Camera */ - - /* Yost Engineering, Inc. products */ - { USB_DEVICE(0x0403, 0xe050) }, /* ServoCenter3.1 USB */ - - /* EVER Sp. products */ - { USB_DEVICE(0x0403, 0xe520) }, /* Eco Pro UPS */ - - /* Active Robots products */ - { USB_DEVICE(0x0403, 0xe548) }, /* Active Robots comms board */ - - /* Pyramid Computer GmbH products */ - { USB_DEVICE(0x0403, 0xe6c8) }, /* Pyramid Appliance Display */ - - /* Gude Analog- und Digitalsysteme GmbH products */ - { USB_DEVICE(0x0403, 0xe808) }, /* USB to serial */ - { USB_DEVICE(0x0403, 0xe809) }, /* USB to serial */ - { USB_DEVICE(0x0403, 0xe80a) }, /* USB to serial */ - { USB_DEVICE(0x0403, 0xe80b) }, /* USB to serial */ - { USB_DEVICE(0x0403, 0xe80c) }, /* USB to serial */ - { USB_DEVICE(0x0403, 0xe80d) }, /* USB to serial */ - { USB_DEVICE(0x0403, 0xe80e) }, /* USB to serial */ - { USB_DEVICE(0x0403, 0xe80f) }, /* USB to serial */ - { USB_DEVICE(0x0403, 0xe888) }, /* Expert ISDN Control USB */ - { USB_DEVICE(0x0403, 0xe889) }, /* USB-RS232 OptoBridge */ - { USB_DEVICE(0x0403, 0xe88a) }, /* Expert mouseCLOCK USB II */ - { USB_DEVICE(0x0403, 0xe88b) }, /* Precision Clock MSF USB */ - { USB_DEVICE(0x0403, 0xe88c) }, /* Expert mouseCLOCK USB II HBG */ - { USB_DEVICE(0x0403, 0xe88d) }, /* USB to serial */ - { USB_DEVICE(0x0403, 0xe88e) }, /* USB to serial */ - { USB_DEVICE(0x0403, 0xe88f) }, /* USB to serial */ - - /* Eclo, Lda. products */ - { USB_DEVICE(0x0403, 0xea90) }, /* COM to 1-Wire USB adaptor */ - - /* Coastal ChipWorks products */ - { USB_DEVICE(0x0403, 0xebe0) }, /* TNC-X USB to packet-radio adapter */ - - /* Teratronik products */ - { USB_DEVICE(0x0403, 0xec88) }, /* Teratronik VCP device */ - - /* MaxStream products */ - { USB_DEVICE(0x0403, 0xee18) }, /* PKG-U RF modem */ - - /* microHAM products */ - { USB_DEVICE(0x0403, 0xeee8) }, /* USB-KW interface */ - { USB_DEVICE(0x0403, 0xeee9) }, /* USB-YS interface */ - { USB_DEVICE(0x0403, 0xeeea) }, /* USB-Y6 interface */ - { USB_DEVICE(0x0403, 0xeeeb) }, /* USB-Y8 interface */ - { USB_DEVICE(0x0403, 0xeeec) }, /* USB-IC interface */ - { USB_DEVICE(0x0403, 0xeeed) }, /* USB-DB9 interface */ - { USB_DEVICE(0x0403, 0xeeee) }, /* USB-RS232 interface */ - { USB_DEVICE(0x0403, 0xeeef) }, /* USB-Y9 interface */ - - /* ELV products */ - { USB_DEVICE(0x0403, 0xf06e) }, /* ALC 8500 Expert */ - { USB_DEVICE(0x0403, 0xf06f) }, /* FHZ 1000 PC */ - - /* Perle Systems products */ - { USB_DEVICE(0x0403, 0xf0c0) }, /* UltraPort USB */ - - /* ACT Solutions products */ - { USB_DEVICE(0x0403, 0xf2d0) }, /* HomePro ZWave */ - - /* 4n-galaxy.de products */ - { USB_DEVICE(0x0403, 0xf3c0) }, /* Galaxy USB to serial */ - { USB_DEVICE(0x0403, 0xf3c1) }, /* Galaxy USB to serial */ - - /* Linx Technologies products */ - { USB_DEVICE(0x0403, 0xf448) }, /* Linx SDM-USB-QS-S */ - { USB_DEVICE(0x0403, 0xf449) }, /* Linx Master Development 2.0 */ - { USB_DEVICE(0x0403, 0xf44a) }, /* Linx USB to serial */ - { USB_DEVICE(0x0403, 0xf44b) }, /* Linx USB to serial */ - { USB_DEVICE(0x0403, 0xf44c) }, /* Linx USB to serial */ - - /* Suunto Oy products */ - { USB_DEVICE(0x0403, 0xf680) }, /* Suunto Sports instrument */ - - /* USB-UIRT */ - { USB_DEVICE(0x0403, 0xf850) }, /* USB-UIRT */ - - /* CCS Inc. products */ - { USB_DEVICE(0x0403, 0xf9d0) }, /* ICD-U20 */ - { USB_DEVICE(0x0403, 0xf9d1) }, /* ICD-U40 */ - { USB_DEVICE(0x0403, 0xf9d2) }, /* MACH-X */ - - /* Matrix Orbital LCD displays */ - { USB_DEVICE(0x0403, 0xfa00) }, /* USB Serial */ - { USB_DEVICE(0x0403, 0xfa01) }, /* MX2 or MX3 LCD */ - { USB_DEVICE(0x0403, 0xfa02) }, /* MX4 or MX5 LCD */ - { USB_DEVICE(0x0403, 0xfa03) }, /* LK202-24 LCD */ - { USB_DEVICE(0x0403, 0xfa04) }, /* LK204-24 LCD */ - { USB_DEVICE(0x0403, 0xfa05) }, /* USB Serial */ - { USB_DEVICE(0x0403, 0xfa06) }, /* USB Serial */ - - /* Home Electronics products */ - { USB_DEVICE(0x0403, 0xfa78) }, /* Tira-1 */ - - /* PCDJ products */ - { USB_DEVICE(0x0403, 0xfa88) }, /* DAC-2 */ - - /* Inside.fr products */ - { USB_DEVICE(0x0403, 0xfad0) }, /* Accesso contactless reader */ - - /* Thorlabs GmbH products */ - { USB_DEVICE(0x0403, 0xfaf0) }, /* Motors controller */ - - /* ELV products */ - { USB_DEVICE(0x0403, 0xfb58) }, /* UR 100 */ - { USB_DEVICE(0x0403, 0xfb5a) }, /* UM 100 */ - { USB_DEVICE(0x0403, 0xfb5b) }, /* UO 100 */ - - /* Crystalfontz products */ - { USB_DEVICE(0x0403, 0xfc08) }, /* CFA-632 LCD */ - { USB_DEVICE(0x0403, 0xfc09) }, /* CFA-634 LCD */ - { USB_DEVICE(0x0403, 0xfc0a) }, /* CFA-547 LCD */ - { USB_DEVICE(0x0403, 0xfc0b) }, /* CFA-633 LCD */ - { USB_DEVICE(0x0403, 0xfc0c) }, /* CFA-631 LCD */ - { USB_DEVICE(0x0403, 0xfc0d) }, /* CFA-635 LCD */ - { USB_DEVICE(0x0403, 0xfc0e) }, /* CFA-640 LCD */ - { USB_DEVICE(0x0403, 0xfc0f) }, /* CFA-642 LCD */ - - /* IRTrans GmbH products */ - { USB_DEVICE(0x0403, 0xfc60) }, /* Irtrans device */ - - /* Sony Ericsson products */ - { USB_DEVICE(0x0403, 0xfc82) }, /* DSS-20 SyncStation */ - - /* RM Michaelides Software & Elektronik GmbH products */ - { USB_DEVICE(0x0403, 0xfd60) }, /* CANview USB */ - - /* Video Networks Limited / Homechoice products */ - { USB_DEVICE(0x0403, 0xfe38) }, /* Homechoice broadband modem */ - - /* AlphaMicro Components products */ - { USB_DEVICE(0x0403, 0xff00) }, /* AMC-232USB01 */ - - /* Thought Technology Ltd. products */ - { USB_DEVICE(0x0403, 0xff20) }, /* TT-USB */ - - /* IBS elektronik products */ - { USB_DEVICE(0x0403, 0xff38) }, /* US485 interface */ - { USB_DEVICE(0x0403, 0xff39) }, /* PIC-Programmer */ - { USB_DEVICE(0x0403, 0xff3a) }, /* PCMCIA SRAM-cards reader */ - { USB_DEVICE(0x0403, 0xff3b) }, /* Particel counter PK1 */ - { USB_DEVICE(0x0403, 0xff3c) }, /* RS232 - Monitor */ - { USB_DEVICE(0x0403, 0xff3d) }, /* APP 70 dust monitoring */ - { USB_DEVICE(0x0403, 0xff3e) }, /* PEDO-Modem */ - { USB_DEVICE(0x0403, 0xff3f) }, /* Future device */ - - /* Lawicel products */ - { USB_DEVICE(0x0403, 0xffa8) }, /* CANUSB device */ - - /* Melco, Inc products */ - { USB_DEVICE(0x0411, 0x00b3) }, /* PC-OP-RS1 RemoteStation */ - - /* B&B Electronics products */ - { USB_DEVICE(0x0856, 0xac01) }, /* USOTL4 */ - { USB_DEVICE(0x0856, 0xac02) }, /* USTL4 */ - { USB_DEVICE(0x0856, 0xac03) }, /* USO9ML2 */ - { USB_DEVICE(0x0856, 0xac11) }, /* USOPTL4 */ - { USB_DEVICE(0x0856, 0xac12) }, /* USPTL4 */ - { USB_DEVICE(0x0856, 0xac16) }, /* USO9ML2DR-2 */ - { USB_DEVICE(0x0856, 0xac17) }, /* USO9ML2DR */ - { USB_DEVICE(0x0856, 0xac18) }, /* USOPTL4DR-2 */ - { USB_DEVICE(0x0856, 0xac19) }, /* USOPTL4DR */ - { USB_DEVICE(0x0856, 0xac25) }, /* 485USB9F-2W */ - { USB_DEVICE(0x0856, 0xac26) }, /* 485USB9F-4W */ - { USB_DEVICE(0x0856, 0xac27) }, /* 232USB9M */ - - /* Interpid Control Systems products */ - { USB_DEVICE(0x093c, 0x0601) }, /* ValueCAN */ - { USB_DEVICE(0x093c, 0x0701) }, /* NeoVI Blue */ - - /* ID TECH products */ - { USB_DEVICE(0x0acd, 0x0300) }, /* USB to serial adapter */ - - /* Omnidirectional Control Technology products */ - { USB_DEVICE(0x0b39, 0x0421) }, /* USB to serial */ - - /* Icom, Inc. products */ - { USB_DEVICE(0x0c26, 0x0004) }, /* ID-1 */ - { USB_DEVICE(0x0c26, 0x0009) }, /* ID-RP2C service 1 */ - { USB_DEVICE(0x0c26, 0x000a) }, /* ID-RP2C service 2 */ - { USB_DEVICE(0x0c26, 0x000b) }, /* ID-RP2D */ - { USB_DEVICE(0x0c26, 0x000c) }, /* ID-RP2V service T */ - { USB_DEVICE(0x0c26, 0x000d) }, /* ID-RP2V service R */ - { USB_DEVICE(0x0c26, 0x0011) }, /* ID-RP4000V service R */ - { USB_DEVICE(0x0c26, 0x0011) }, /* ID-RP4000V service T */ - { USB_DEVICE(0x0c26, 0x0012) }, /* ID-RP2000V service T */ - { USB_DEVICE(0x0c26, 0x0013) }, /* ID-RP2000V service R */ - - /* Sealevel products */ - { USB_DEVICE(0x0c52, 0X2811) }, /* SeaLINK+8/232 (2801) Port 1 */ - { USB_DEVICE(0x0c52, 0X2812) }, /* SeaLINK+8/485 (2802) Port 1 */ - { USB_DEVICE(0x0c52, 0X2813) }, /* SeaLINK+8 (2803) Port 1 */ - { USB_DEVICE(0x0c52, 0X2821) }, /* SeaLINK+8/232 (2801) Port 2 */ - { USB_DEVICE(0x0c52, 0X2822) }, /* SeaLINK+8/485 (2802) Port 2 */ - { USB_DEVICE(0x0c52, 0X2823) }, /* SeaLINK+8 (2803) Port 2 */ - { USB_DEVICE(0x0c52, 0X2831) }, /* SeaLINK+8/232 (2801) Port 3 */ - { USB_DEVICE(0x0c52, 0X2832) }, /* SeaLINK+8/485 (2802) Port 3 */ - { USB_DEVICE(0x0c52, 0X2833) }, /* SeaLINK+8 (2803) Port 3 */ - { USB_DEVICE(0x0c52, 0X2841) }, /* SeaLINK+8/232 (2801) Port 4 */ - { USB_DEVICE(0x0c52, 0X2842) }, /* SeaLINK+8/485 (2802) Port 4 */ - { USB_DEVICE(0x0c52, 0X2843) }, /* SeaLINK+8 (2803) Port 4 */ - { USB_DEVICE(0x0c52, 0X2851) }, /* SeaLINK+8/232 (2801) Port 5 */ - { USB_DEVICE(0x0c52, 0X2852) }, /* SeaLINK+8/485 (2802) Port 5 */ - { USB_DEVICE(0x0c52, 0X2853) }, /* SeaLINK+8 (2803) Port 5 */ - { USB_DEVICE(0x0c52, 0X2861) }, /* SeaLINK+8/232 (2801) Port 6 */ - { USB_DEVICE(0x0c52, 0X2862) }, /* SeaLINK+8/485 (2802) Port 6 */ - { USB_DEVICE(0x0c52, 0X2863) }, /* SeaLINK+8 (2803) Port 6 */ - { USB_DEVICE(0x0c52, 0X2871) }, /* SeaLINK+8/232 (2801) Port 7 */ - { USB_DEVICE(0x0c52, 0X2872) }, /* SeaLINK+8/485 (2802) Port 7 */ - { USB_DEVICE(0x0c52, 0X2873) }, /* SeaLINK+8 (2803) Port 7 */ - { USB_DEVICE(0x0c52, 0X2881) }, /* SeaLINK+8/232 (2801) Port 8 */ - { USB_DEVICE(0x0c52, 0X2882) }, /* SeaLINK+8/485 (2802) Port 8 */ - { USB_DEVICE(0x0c52, 0X2883) }, /* SeaLINK+8 (2803) Port 8 */ - { USB_DEVICE(0x0c52, 0x2101) }, /* SeaLINK+232 (2101/2105) */ - { USB_DEVICE(0x0c52, 0x2102) }, /* SeaLINK+485 (2102) */ - { USB_DEVICE(0x0c52, 0x2103) }, /* SeaLINK+232I (2103) */ - { USB_DEVICE(0x0c52, 0x2104) }, /* SeaLINK+485I (2104) */ - { USB_DEVICE(0x0c52, 0x2211) }, /* SeaPORT+2/232 (2201) Port 1 */ - { USB_DEVICE(0x0c52, 0x2212) }, /* SeaPORT+2/485 (2202) Port 1 */ - { USB_DEVICE(0x0c52, 0x2213) }, /* SeaPORT+2 (2203) Port 1 */ - { USB_DEVICE(0x0c52, 0x2221) }, /* SeaPORT+2/232 (2201) Port 2 */ - { USB_DEVICE(0x0c52, 0x2222) }, /* SeaPORT+2/485 (2202) Port 2 */ - { USB_DEVICE(0x0c52, 0x2223) }, /* SeaPORT+2 (2203) Port 2 */ - { USB_DEVICE(0x0c52, 0x2411) }, /* SeaPORT+4/232 (2401) Port 1 */ - { USB_DEVICE(0x0c52, 0x2412) }, /* SeaPORT+4/485 (2402) Port 1 */ - { USB_DEVICE(0x0c52, 0x2413) }, /* SeaPORT+4 (2403) Port 1 */ - { USB_DEVICE(0x0c52, 0x2421) }, /* SeaPORT+4/232 (2401) Port 2 */ - { USB_DEVICE(0x0c52, 0x2422) }, /* SeaPORT+4/485 (2402) Port 2 */ - { USB_DEVICE(0x0c52, 0x2423) }, /* SeaPORT+4 (2403) Port 2 */ - { USB_DEVICE(0x0c52, 0x2431) }, /* SeaPORT+4/232 (2401) Port 3 */ - { USB_DEVICE(0x0c52, 0x2432) }, /* SeaPORT+4/485 (2402) Port 3 */ - { USB_DEVICE(0x0c52, 0x2433) }, /* SeaPORT+4 (2403) Port 3 */ - { USB_DEVICE(0x0c52, 0x2441) }, /* SeaPORT+4/232 (2401) Port 4 */ - { USB_DEVICE(0x0c52, 0x2442) }, /* SeaPORT+4/485 (2402) Port 4 */ - { USB_DEVICE(0x0c52, 0x2443) }, /* SeaPORT+4 (2403) Port 4 */ - { USB_DEVICE(0x0c52, 0x9020) }, /* SeaLINK+422 (2106) */ - - /* Posiflex Technologies products */ - { USB_DEVICE(0x0d3a, 0x0300) }, /* PP7000 series printer */ - { USB_DEVICE(0x0d3a, 0x0400) }, /* PP7000 series printer */ - - /* Kobil Systems products */ - { USB_DEVICE(0x0d46, 0x2020) }, /* Konverter for B1 */ - { USB_DEVICE(0x0d46, 0x2021) }, /* Konverter for KAAN */ - - /* Falcom Wireless Communications products */ - { USB_DEVICE(0x0f94, 0x0001) }, /* Twist USB GPRS modem */ - { USB_DEVICE(0x0f94, 0x0005) }, /* Samba USB GPRS modem */ - - /* Thurlby Thandar Instruments products */ - { USB_DEVICE(0x103e, 0x03e8) }, /* QL355P power supply */ - - /* InterBiometrics products */ - { USB_DEVICE(0x1209, 0x1002) }, /* IO Board */ - { USB_DEVICE(0x1209, 0x1006) }, /* Mini IO Board */ - - /* Testo AG products */ - { USB_DEVICE(0x128d, 0x0001) }, /* 175/177 USB interface */ - { USB_DEVICE(0x128d, 0x0002) }, /* 330 USB interface */ - { USB_DEVICE(0x128d, 0x0003) }, /* 435/635/735 USB interface */ - { USB_DEVICE(0x128d, 0x0004) }, /* 845 USB interface */ - { USB_DEVICE(0x128d, 0x0005) }, /* Service adapter */ - { USB_DEVICE(0x128d, 0x0006) }, /* 580 USB interface */ - { USB_DEVICE(0x128d, 0x0007) }, /* 174 USB interface */ - { USB_DEVICE(0x128d, 0x0009) }, /* 556/560 USB interface */ - { USB_DEVICE(0x128d, 0x000a) }, /* USB adapter */ - { USB_DEVICE(0x128d, 0xf001) }, /* USB to serial converter */ - - /* Mobility products */ - { USB_DEVICE(0x1342, 0x0202) }, /* EasiDock 200 serial port */ - - /* Papouch s.r.o. products */ - { USB_DEVICE(0x5050, 0x0100) }, /* SB485 USB-485/422 Converter */ - { USB_DEVICE(0x5050, 0x0101) }, /* AP485 USB-RS485 Converter */ - { USB_DEVICE(0x5050, 0x0102) }, /* SB422 USB-RS422 Converter */ - { USB_DEVICE(0x5050, 0x0103) }, /* SB485 USB-485/422 Converter */ - { USB_DEVICE(0x5050, 0x0104) }, /* AP485 USB-RS485 Converter */ - { USB_DEVICE(0x5050, 0x0105) }, /* SB422 USB-RS422 Converter */ - { USB_DEVICE(0x5050, 0x0106) }, /* SB485S USB-485/422 Converter */ - { USB_DEVICE(0x5050, 0x0107) }, /* SB485C USB-485/422 Converter */ - { USB_DEVICE(0x5050, 0x0200) }, /* USB Device */ - { USB_DEVICE(0x5050, 0x0300) }, /* LEC USB Converter */ - { USB_DEVICE(0x5050, 0x0301) }, /* SB232 USB-RS232 Converter */ - { USB_DEVICE(0x5050, 0x0400) }, /* TMU Thermometer */ - { USB_DEVICE(0x5050, 0x0500) }, /* IRAmp Duplex */ - { USB_DEVICE(0x5050, 0x0700) }, /* DRAK5 */ - { USB_DEVICE(0x5050, 0x0800) }, /* QUIDO USB 8/8 */ - { USB_DEVICE(0x5050, 0x0900) }, /* QUIDO USB 4/4 */ - { USB_DEVICE(0x5050, 0x0A00) }, /* QUIDO USB 2/2 */ - { USB_DEVICE(0x5050, 0x0B00) }, /* QUIDO USB 10/1 */ - { USB_DEVICE(0x5050, 0x0C00) }, /* QUIDO USB 30/3 */ - { USB_DEVICE(0x5050, 0x0D00) }, /* QUIDO USB 60(100)/3 */ - { USB_DEVICE(0x5050, 0x0E00) }, /* QUIDO USB 2/16 */ - { USB_DEVICE(0x5050, 0x0F00) }, /* QUIDO USB 3/32 */ - { USB_DEVICE(0x5050, 0x1000) }, /* DRAK6 USB */ - { USB_DEVICE(0x5050, 0x8000) }, /* UPS-USB Stavovy Adapter */ - { USB_DEVICE(0x5050, 0x8001) }, /* MU Controller */ - { USB_DEVICE(0x5050, 0x8002) }, /* SimuKey */ - { USB_DEVICE(0x5050, 0x8003) }, /* AD4USB */ - { USB_DEVICE(0x5050, 0x8004) }, /* GOLIATH MUX */ - { USB_DEVICE(0x5050, 0x8005) }, /* GOLIATH MSR */ - - /* Evolution Robotics, Inc. products */ - { USB_DEVICE(0xdeee, 0x0300) }, /* ER1 Control Module */ - { USB_DEVICE(0xdeee, 0x0302) }, /* RCM4 interface */ - { USB_DEVICE(0xdeee, 0x0303) }, /* RCM4 interface */ -}; - -static int -uftdi_match(device_t self) -{ - struct usb_attach_arg *uaa = device_get_ivars(self); - - if (uaa->iface == NULL) - return (UMATCH_NONE); - - if (usb_lookup(uftdi_devs, uaa->vendor, uaa->product) != NULL) - return (UMATCH_VENDOR_IFACESUBCLASS); - - return (UMATCH_NONE); -} - -static int -uftdi_attach(device_t self) -{ - struct uftdi_softc *sc = device_get_softc(self); - struct usb_attach_arg *uaa = device_get_ivars(self); - usbd_device_handle dev = uaa->device; - usbd_interface_handle iface; - usb_interface_descriptor_t *id; - usb_endpoint_descriptor_t *ed; - int i; - struct ucom_softc *ucom = &sc->sc_ucom; - DPRINTFN(10,("\nuftdi_attach: sc=%p\n", sc)); - - ucom->sc_dev = self; - ucom->sc_udev = dev; - - iface = uaa->iface; - id = usbd_get_interface_descriptor(iface); - ucom->sc_iface = iface; - - if (uaa->release < 0x0200) { - sc->sc_type = UFTDI_TYPE_SIO; - sc->sc_hdrlen = 1; - } else { - sc->sc_type = UFTDI_TYPE_8U232AM; - sc->sc_hdrlen = 0; - } - - ucom->sc_bulkin_no = ucom->sc_bulkout_no = -1; - - for (i = 0; i < id->bNumEndpoints; i++) { - int addr, dir, attr; - ed = usbd_interface2endpoint_descriptor(iface, i); - if (ed == NULL) { - device_printf(ucom->sc_dev, - "could not read endpoint descriptor\n"); - goto bad; - } - - addr = ed->bEndpointAddress; - dir = UE_GET_DIR(ed->bEndpointAddress); - attr = ed->bmAttributes & UE_XFERTYPE; - if (dir == UE_DIR_IN && attr == UE_BULK) - ucom->sc_bulkin_no = addr; - else if (dir == UE_DIR_OUT && attr == UE_BULK) - ucom->sc_bulkout_no = addr; - else { - device_printf(ucom->sc_dev, "unexpected endpoint\n"); - goto bad; - } - } - if (ucom->sc_bulkin_no == -1) { - device_printf(ucom->sc_dev, "Could not find data bulk in\n"); - goto bad; - } - if (ucom->sc_bulkout_no == -1) { - device_printf(ucom->sc_dev, "Could not find data bulk out\n"); - goto bad; - } - ucom->sc_parent = sc; - ucom->sc_portno = FTDI_PIT_SIOA + id->bInterfaceNumber; - /* bulkin, bulkout set above */ - - ucom->sc_ibufsize = UFTDIIBUFSIZE; - ucom->sc_obufsize = UFTDIOBUFSIZE - sc->sc_hdrlen; - ucom->sc_ibufsizepad = UFTDIIBUFSIZE; - ucom->sc_opkthdrlen = sc->sc_hdrlen; - - - ucom->sc_callback = &uftdi_callback; -#if 0 - usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, ucom->sc_udev, - ucom->sc_dev); -#endif - DPRINTF(("uftdi: in=0x%x out=0x%x\n", ucom->sc_bulkin_no, ucom->sc_bulkout_no)); - ucom_attach(&sc->sc_ucom); - return 0; - -bad: - DPRINTF(("uftdi_attach: ATTACH ERROR\n")); - ucom->sc_dying = 1; - return ENXIO; -} -#if 0 -int -uftdi_activate(device_t self, enum devact act) -{ - struct uftdi_softc *sc = (struct uftdi_softc *)self; - int rv = 0; - - switch (act) { - case DVACT_ACTIVATE: - return (EOPNOTSUPP); - - case DVACT_DEACTIVATE: - if (sc->sc_subdev != NULL) - rv = config_deactivate(sc->sc_subdev); - sc->sc_ucom.sc_dying = 1; - break; - } - return (rv); -} -#endif - -static int -uftdi_detach(device_t self) -{ - struct uftdi_softc *sc = device_get_softc(self); - - int rv = 0; - - DPRINTF(("uftdi_detach: sc=%p\n", sc)); - sc->sc_ucom.sc_dying = 1; - rv = ucom_detach(&sc->sc_ucom); - - return rv; -} - -static int -uftdi_open(void *vsc, int portno) -{ - struct uftdi_softc *sc = vsc; - struct ucom_softc *ucom = &sc->sc_ucom; - usb_device_request_t req; - usbd_status err; - struct termios t; - - DPRINTF(("uftdi_open: sc=%p\n", sc)); - - if (ucom->sc_dying) - return (EIO); - - /* Perform a full reset on the device */ - req.bmRequestType = UT_WRITE_VENDOR_DEVICE; - req.bRequest = FTDI_SIO_RESET; - USETW(req.wValue, FTDI_SIO_RESET_SIO); - USETW(req.wIndex, portno); - USETW(req.wLength, 0); - err = usbd_do_request(ucom->sc_udev, &req, NULL); - if (err) - return (EIO); - - /* Set 9600 baud, 2 stop bits, no parity, 8 bits */ - t.c_ospeed = 9600; - t.c_cflag = CSTOPB | CS8; - (void)uftdi_param(sc, portno, &t); - - /* Turn on RTS/CTS flow control */ - req.bmRequestType = UT_WRITE_VENDOR_DEVICE; - req.bRequest = FTDI_SIO_SET_FLOW_CTRL; - USETW(req.wValue, 0); - USETW2(req.wIndex, FTDI_SIO_RTS_CTS_HS, portno); - USETW(req.wLength, 0); - err = usbd_do_request(ucom->sc_udev, &req, NULL); - if (err) - return (EIO); - - return (0); -} - -static void -uftdi_read(void *vsc, int portno, u_char **ptr, u_int32_t *count) -{ - struct uftdi_softc *sc = vsc; - u_char msr, lsr; - - DPRINTFN(15,("uftdi_read: sc=%p, port=%d count=%d\n", sc, portno, - *count)); - - msr = FTDI_GET_MSR(*ptr); - lsr = FTDI_GET_LSR(*ptr); - -#ifdef USB_DEBUG - if (*count != 2) - DPRINTFN(10,("uftdi_read: sc=%p, port=%d count=%d data[0]=" - "0x%02x\n", sc, portno, *count, (*ptr)[2])); -#endif - - if (sc->sc_msr != msr || - (sc->sc_lsr & FTDI_LSR_MASK) != (lsr & FTDI_LSR_MASK)) { - DPRINTF(("uftdi_read: status change msr=0x%02x(0x%02x) " - "lsr=0x%02x(0x%02x)\n", msr, sc->sc_msr, - lsr, sc->sc_lsr)); - sc->sc_msr = msr; - sc->sc_lsr = lsr; - ucom_status_change(&sc->sc_ucom); - } - - /* Pick up status and adjust data part. */ - *ptr += 2; - *count -= 2; -} - -static void -uftdi_write(void *vsc, int portno, u_char *to, u_char *from, u_int32_t *count) -{ - struct uftdi_softc *sc = vsc; - - DPRINTFN(10,("uftdi_write: sc=%p, port=%d count=%u data[0]=0x%02x\n", - vsc, portno, *count, from[0])); - - /* Make length tag and copy data */ - if (sc->sc_hdrlen > 0) - *to = FTDI_OUT_TAG(*count, portno); - - memcpy(to + sc->sc_hdrlen, from, *count); - *count += sc->sc_hdrlen; -} - -static void -uftdi_set(void *vsc, int portno, int reg, int onoff) -{ - struct uftdi_softc *sc = vsc; - struct ucom_softc *ucom = vsc; - usb_device_request_t req; - int ctl; - - DPRINTF(("uftdi_set: sc=%p, port=%d reg=%d onoff=%d\n", vsc, portno, - reg, onoff)); - - switch (reg) { - case UCOM_SET_DTR: - ctl = onoff ? FTDI_SIO_SET_DTR_HIGH : FTDI_SIO_SET_DTR_LOW; - break; - case UCOM_SET_RTS: - ctl = onoff ? FTDI_SIO_SET_RTS_HIGH : FTDI_SIO_SET_RTS_LOW; - break; - case UCOM_SET_BREAK: - uftdi_break(sc, portno, onoff); - return; - default: - return; - } - req.bmRequestType = UT_WRITE_VENDOR_DEVICE; - req.bRequest = FTDI_SIO_MODEM_CTRL; - USETW(req.wValue, ctl); - USETW(req.wIndex, portno); - USETW(req.wLength, 0); - DPRINTFN(2,("uftdi_set: reqtype=0x%02x req=0x%02x value=0x%04x " - "index=0x%04x len=%d\n", req.bmRequestType, req.bRequest, - UGETW(req.wValue), UGETW(req.wIndex), UGETW(req.wLength))); - (void)usbd_do_request(ucom->sc_udev, &req, NULL); -} - -static int -uftdi_param(void *vsc, int portno, struct termios *t) -{ - struct uftdi_softc *sc = vsc; - struct ucom_softc *ucom = &sc->sc_ucom; - usb_device_request_t req; - usbd_status err; - int rate=0, data, flow; - - DPRINTF(("uftdi_param: sc=%p\n", sc)); - - if (ucom->sc_dying) - return (EIO); - - switch (sc->sc_type) { - case UFTDI_TYPE_SIO: - switch (t->c_ospeed) { - case 300: rate = ftdi_sio_b300; break; - case 600: rate = ftdi_sio_b600; break; - case 1200: rate = ftdi_sio_b1200; break; - case 2400: rate = ftdi_sio_b2400; break; - case 4800: rate = ftdi_sio_b4800; break; - case 9600: rate = ftdi_sio_b9600; break; - case 19200: rate = ftdi_sio_b19200; break; - case 38400: rate = ftdi_sio_b38400; break; - case 57600: rate = ftdi_sio_b57600; break; - case 115200: rate = ftdi_sio_b115200; break; - default: - return (EINVAL); - } - break; - - case UFTDI_TYPE_8U232AM: - if (uftdi_8u232am_getrate(t->c_ospeed, &rate) == -1) - return (EINVAL); - break; - } - req.bmRequestType = UT_WRITE_VENDOR_DEVICE; - req.bRequest = FTDI_SIO_SET_BAUD_RATE; - USETW(req.wValue, rate); - USETW(req.wIndex, portno); - USETW(req.wLength, 0); - DPRINTFN(2,("uftdi_param: reqtype=0x%02x req=0x%02x value=0x%04x " - "index=0x%04x len=%d\n", req.bmRequestType, req.bRequest, - UGETW(req.wValue), UGETW(req.wIndex), UGETW(req.wLength))); - err = usbd_do_request(ucom->sc_udev, &req, NULL); - if (err) - return (EIO); - - if (ISSET(t->c_cflag, CSTOPB)) - data = FTDI_SIO_SET_DATA_STOP_BITS_2; - else - data = FTDI_SIO_SET_DATA_STOP_BITS_1; - if (ISSET(t->c_cflag, PARENB)) { - if (ISSET(t->c_cflag, PARODD)) - data |= FTDI_SIO_SET_DATA_PARITY_ODD; - else - data |= FTDI_SIO_SET_DATA_PARITY_EVEN; - } else - data |= FTDI_SIO_SET_DATA_PARITY_NONE; - switch (ISSET(t->c_cflag, CSIZE)) { - case CS5: - data |= FTDI_SIO_SET_DATA_BITS(5); - break; - case CS6: - data |= FTDI_SIO_SET_DATA_BITS(6); - break; - case CS7: - data |= FTDI_SIO_SET_DATA_BITS(7); - break; - case CS8: - data |= FTDI_SIO_SET_DATA_BITS(8); - break; - } - sc->last_lcr = data; - - req.bmRequestType = UT_WRITE_VENDOR_DEVICE; - req.bRequest = FTDI_SIO_SET_DATA; - USETW(req.wValue, data); - USETW(req.wIndex, portno); - USETW(req.wLength, 0); - DPRINTFN(2,("uftdi_param: reqtype=0x%02x req=0x%02x value=0x%04x " - "index=0x%04x len=%d\n", req.bmRequestType, req.bRequest, - UGETW(req.wValue), UGETW(req.wIndex), UGETW(req.wLength))); - err = usbd_do_request(ucom->sc_udev, &req, NULL); - if (err) - return (EIO); - - if (ISSET(t->c_cflag, CRTSCTS)) { - flow = FTDI_SIO_RTS_CTS_HS; - USETW(req.wValue, 0); - } else if (ISSET(t->c_iflag, IXON|IXOFF)) { - flow = FTDI_SIO_XON_XOFF_HS; - USETW2(req.wValue, t->c_cc[VSTOP], t->c_cc[VSTART]); - } else { - flow = FTDI_SIO_DISABLE_FLOW_CTRL; - USETW(req.wValue, 0); - } - req.bmRequestType = UT_WRITE_VENDOR_DEVICE; - req.bRequest = FTDI_SIO_SET_FLOW_CTRL; - USETW2(req.wIndex, flow, portno); - USETW(req.wLength, 0); - err = usbd_do_request(ucom->sc_udev, &req, NULL); - if (err) - return (EIO); - - return (0); -} - -void -uftdi_get_status(void *vsc, int portno, u_char *lsr, u_char *msr) -{ - struct uftdi_softc *sc = vsc; - - DPRINTF(("uftdi_status: msr=0x%02x lsr=0x%02x\n", - sc->sc_msr, sc->sc_lsr)); - - if (msr != NULL) - *msr = sc->sc_msr; - if (lsr != NULL) - *lsr = sc->sc_lsr; -} - -void -uftdi_break(void *vsc, int portno, int onoff) -{ - struct uftdi_softc *sc = vsc; - struct ucom_softc *ucom = vsc; - - usb_device_request_t req; - int data; - - DPRINTF(("uftdi_break: sc=%p, port=%d onoff=%d\n", vsc, portno, - onoff)); - - if (onoff) { - data = sc->last_lcr | FTDI_SIO_SET_BREAK; - } else { - data = sc->last_lcr; - } - - req.bmRequestType = UT_WRITE_VENDOR_DEVICE; - req.bRequest = FTDI_SIO_SET_DATA; - USETW(req.wValue, data); - USETW(req.wIndex, portno); - USETW(req.wLength, 0); - (void)usbd_do_request(ucom->sc_udev, &req, NULL); -} - -static int -uftdi_8u232am_getrate(speed_t speed, int *rate) -{ - /* Table of the nearest even powers-of-2 for values 0..15. */ - static const unsigned char roundoff[16] = { - 0, 2, 2, 4, 4, 4, 8, 8, - 8, 8, 8, 8, 16, 16, 16, 16, - }; - - unsigned int d, freq; - int result; - - if (speed <= 0) - return (-1); - - /* Special cases for 2M and 3M. */ - if (speed >= 3000000 * 100 / 103 && - speed <= 3000000 * 100 / 97) { - result = 0; - goto done; - } - if (speed >= 2000000 * 100 / 103 && - speed <= 2000000 * 100 / 97) { - result = 1; - goto done; - } - - d = (FTDI_8U232AM_FREQ << 4) / speed; - d = (d & ~15) + roundoff[d & 15]; - - if (d < FTDI_8U232AM_MIN_DIV) - d = FTDI_8U232AM_MIN_DIV; - else if (d > FTDI_8U232AM_MAX_DIV) - d = FTDI_8U232AM_MAX_DIV; - - /* - * Calculate the frequency needed for d to exactly divide down - * to our target speed, and check that the actual frequency is - * within 3% of this. - */ - freq = speed * d; - if (freq < (quad_t)(FTDI_8U232AM_FREQ << 4) * 100 / 103 || - freq > (quad_t)(FTDI_8U232AM_FREQ << 4) * 100 / 97) - return (-1); - - /* - * Pack the divisor into the resultant value. The lower - * 14-bits hold the integral part, while the upper 2 bits - * encode the fractional component: either 0, 0.5, 0.25, or - * 0.125. - */ - result = d >> 4; - if (d & 8) - result |= 0x4000; - else if (d & 4) - result |= 0x8000; - else if (d & 2) - result |= 0xc000; - -done: - *rate = result; - return (0); -} -static device_method_t uftdi_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, uftdi_match), - DEVMETHOD(device_attach, uftdi_attach), - DEVMETHOD(device_detach, uftdi_detach), - - DEVMETHOD_END -}; - -static driver_t uftdi_driver = { - "ucom", - uftdi_methods, - sizeof (struct uftdi_softc) -}; - -DRIVER_MODULE(uftdi, uhub, uftdi_driver, ucom_devclass, usbd_driver_load, NULL); -MODULE_DEPEND(uftdi, usb, 1, 1, 1); -MODULE_DEPEND(uftdi, ucom,UCOM_MINVER, UCOM_PREFVER, UCOM_MAXVER); diff --git a/sys/dev/usbmisc/uftdi/uftdireg.h b/sys/dev/usbmisc/uftdi/uftdireg.h deleted file mode 100644 index 411abb04ec..0000000000 --- a/sys/dev/usbmisc/uftdi/uftdireg.h +++ /dev/null @@ -1,341 +0,0 @@ -/* - * $NetBSD: uftdireg.h,v 1.6 2002/07/11 21:14:28 augustss Exp $ - * $FreeBSD: src/sys/dev/usb/uftdireg.h,v 1.2 2004/07/01 17:16:20 brooks Exp $ - * $DragonFly: src/sys/dev/usbmisc/uftdi/uftdireg.h,v 1.5 2007/08/31 13:39:35 hasso Exp $ - */ - -/* - * Definitions for the FTDI USB Single Port Serial Converter - - * known as FTDI_SIO (Serial Input/Output application of the chipset) - * - * The device is based on the FTDI FT8U100AX chip. It has a DB25 on one side, - * USB on the other. - * - * Thanx to FTDI (http://www.ftdi.co.uk) for so kindly providing details - * of the protocol required to talk to the device and ongoing assistence - * during development. - * - * Bill Ryder - bryder@sgi.com of Silicon Graphics, Inc. is the original - * author of this file. - */ -/* Modified by Lennart Augustsson */ - -/* Vendor Request Interface */ -#define FTDI_SIO_RESET 0 /* Reset the port */ -#define FTDI_SIO_MODEM_CTRL 1 /* Set the modem control register */ -#define FTDI_SIO_SET_FLOW_CTRL 2 /* Set flow control register */ -#define FTDI_SIO_SET_BAUD_RATE 3 /* Set baud rate */ -#define FTDI_SIO_SET_DATA 4 /* Set the data characteristics of the port */ -#define FTDI_SIO_GET_STATUS 5 /* Retrieve current value of status reg */ -#define FTDI_SIO_SET_EVENT_CHAR 6 /* Set the event character */ -#define FTDI_SIO_SET_ERROR_CHAR 7 /* Set the error character */ - -/* Port Identifier Table */ -#define FTDI_PIT_DEFAULT 0 /* SIOA */ -#define FTDI_PIT_SIOA 1 /* SIOA */ -#define FTDI_PIT_SIOB 2 /* SIOB */ -#define FTDI_PIT_PARALLEL 3 /* Parallel */ - -enum uftdi_type { - UFTDI_TYPE_SIO, - UFTDI_TYPE_8U232AM -}; - -/* - * BmRequestType: 0100 0000B - * bRequest: FTDI_SIO_RESET - * wValue: Control Value - * 0 = Reset SIO - * 1 = Purge RX buffer - * 2 = Purge TX buffer - * wIndex: Port - * wLength: 0 - * Data: None - * - * The Reset SIO command has this effect: - * - * Sets flow control set to 'none' - * Event char = 0x0d - * Event trigger = disabled - * Purge RX buffer - * Purge TX buffer - * Clear DTR - * Clear RTS - * baud and data format not reset - * - * The Purge RX and TX buffer commands affect nothing except the buffers - * - */ -/* FTDI_SIO_RESET */ -#define FTDI_SIO_RESET_SIO 0 -#define FTDI_SIO_RESET_PURGE_RX 1 -#define FTDI_SIO_RESET_PURGE_TX 2 - - -/* - * BmRequestType: 0100 0000B - * bRequest: FTDI_SIO_SET_BAUDRATE - * wValue: BaudRate value - see below - * wIndex: Port - * wLength: 0 - * Data: None - */ -/* FTDI_SIO_SET_BAUDRATE */ -enum { - ftdi_sio_b300 = 0, - ftdi_sio_b600 = 1, - ftdi_sio_b1200 = 2, - ftdi_sio_b2400 = 3, - ftdi_sio_b4800 = 4, - ftdi_sio_b9600 = 5, - ftdi_sio_b19200 = 6, - ftdi_sio_b38400 = 7, - ftdi_sio_b57600 = 8, - ftdi_sio_b115200 = 9 -}; - -#define FTDI_8U232AM_FREQ 3000000 - -/* Bounds for normal divisors as 4-bit fixed precision ints. */ -#define FTDI_8U232AM_MIN_DIV 0x20 -#define FTDI_8U232AM_MAX_DIV 0x3fff8 - -/* - * BmRequestType: 0100 0000B - * bRequest: FTDI_SIO_SET_DATA - * wValue: Data characteristics (see below) - * wIndex: Port - * wLength: 0 - * Data: No - * - * Data characteristics - * - * B0..7 Number of data bits - * B8..10 Parity - * 0 = None - * 1 = Odd - * 2 = Even - * 3 = Mark - * 4 = Space - * B11..13 Stop Bits - * 0 = 1 - * 1 = 1.5 - * 2 = 2 - * B14..15 Reserved - * - */ -/* FTDI_SIO_SET_DATA */ -#define FTDI_SIO_SET_DATA_BITS(n) (n) -#define FTDI_SIO_SET_DATA_PARITY_NONE (0x0 << 8) -#define FTDI_SIO_SET_DATA_PARITY_ODD (0x1 << 8) -#define FTDI_SIO_SET_DATA_PARITY_EVEN (0x2 << 8) -#define FTDI_SIO_SET_DATA_PARITY_MARK (0x3 << 8) -#define FTDI_SIO_SET_DATA_PARITY_SPACE (0x4 << 8) -#define FTDI_SIO_SET_DATA_STOP_BITS_1 (0x0 << 11) -#define FTDI_SIO_SET_DATA_STOP_BITS_15 (0x1 << 11) -#define FTDI_SIO_SET_DATA_STOP_BITS_2 (0x2 << 11) -#define FTDI_SIO_SET_BREAK (0x1 << 14) - - -/* - * BmRequestType: 0100 0000B - * bRequest: FTDI_SIO_MODEM_CTRL - * wValue: ControlValue (see below) - * wIndex: Port - * wLength: 0 - * Data: None - * - * NOTE: If the device is in RTS/CTS flow control, the RTS set by this - * command will be IGNORED without an error being returned - * Also - you can not set DTR and RTS with one control message - * - * ControlValue - * B0 DTR state - * 0 = reset - * 1 = set - * B1 RTS state - * 0 = reset - * 1 = set - * B2..7 Reserved - * B8 DTR state enable - * 0 = ignore - * 1 = use DTR state - * B9 RTS state enable - * 0 = ignore - * 1 = use RTS state - * B10..15 Reserved - */ -/* FTDI_SIO_MODEM_CTRL */ -#define FTDI_SIO_SET_DTR_MASK 0x1 -#define FTDI_SIO_SET_DTR_HIGH (1 | ( FTDI_SIO_SET_DTR_MASK << 8)) -#define FTDI_SIO_SET_DTR_LOW (0 | ( FTDI_SIO_SET_DTR_MASK << 8)) -#define FTDI_SIO_SET_RTS_MASK 0x2 -#define FTDI_SIO_SET_RTS_HIGH (2 | ( FTDI_SIO_SET_RTS_MASK << 8)) -#define FTDI_SIO_SET_RTS_LOW (0 | ( FTDI_SIO_SET_RTS_MASK << 8)) - - -/* - * BmRequestType: 0100 0000b - * bRequest: FTDI_SIO_SET_FLOW_CTRL - * wValue: Xoff/Xon - * wIndex: Protocol/Port - hIndex is protocl / lIndex is port - * wLength: 0 - * Data: None - * - * hIndex protocol is: - * B0 Output handshaking using RTS/CTS - * 0 = disabled - * 1 = enabled - * B1 Output handshaking using DTR/DSR - * 0 = disabled - * 1 = enabled - * B2 Xon/Xoff handshaking - * 0 = disabled - * 1 = enabled - * - * A value of zero in the hIndex field disables handshaking - * - * If Xon/Xoff handshaking is specified, the hValue field should contain the - * XOFF character and the lValue field contains the XON character. - */ -/* FTDI_SIO_SET_FLOW_CTRL */ -#define FTDI_SIO_DISABLE_FLOW_CTRL 0x0 -#define FTDI_SIO_RTS_CTS_HS 0x1 -#define FTDI_SIO_DTR_DSR_HS 0x2 -#define FTDI_SIO_XON_XOFF_HS 0x4 - - -/* - * BmRequestType: 0100 0000b - * bRequest: FTDI_SIO_SET_EVENT_CHAR - * wValue: Event Char - * wIndex: Port - * wLength: 0 - * Data: None - * - * wValue: - * B0..7 Event Character - * B8 Event Character Processing - * 0 = disabled - * 1 = enabled - * B9..15 Reserved - * - * FTDI_SIO_SET_EVENT_CHAR - * - * Set the special event character for the specified communications port. - * If the device sees this character it will immediately return the - * data read so far - rather than wait 40ms or until 62 bytes are read - * which is what normally happens. - */ - - - -/* - * BmRequestType: 0100 0000b - * bRequest: FTDI_SIO_SET_ERROR_CHAR - * wValue: Error Char - * wIndex: Port - * wLength: 0 - * Data: None - * - * Error Char - * B0..7 Error Character - * B8 Error Character Processing - * 0 = disabled - * 1 = enabled - * B9..15 Reserved - * - * - * FTDI_SIO_SET_ERROR_CHAR - * Set the parity error replacement character for the specified communications - * port. - */ - - -/* - * BmRequestType: 1100 0000b - * bRequest: FTDI_SIO_GET_MODEM_STATUS - * wValue: zero - * wIndex: Port - * wLength: 1 - * Data: Status - * - * One byte of data is returned - * B0..3 0 - * B4 CTS - * 0 = inactive - * 1 = active - * B5 DSR - * 0 = inactive - * 1 = active - * B6 Ring Indicator (RI) - * 0 = inactive - * 1 = active - * B7 Receive Line Signal Detect (RLSD) - * 0 = inactive - * 1 = active - * - * FTDI_SIO_GET_MODEM_STATUS - * Retrieve the current value of the modem status register. - */ -#define FTDI_SIO_CTS_MASK 0x10 -#define FTDI_SIO_DSR_MASK 0x20 -#define FTDI_SIO_RI_MASK 0x40 -#define FTDI_SIO_RLSD_MASK 0x80 - - - -/* - * - * DATA FORMAT - * - * IN Endpoint - * - * The device reserves the first two bytes of data on this endpoint to contain - * the current values of the modem and line status registers. In the absence of - * data, the device generates a message consisting of these two status bytes - * every 40 ms. - * - * Byte 0: Modem Status - * NOTE: 4 upper bits have same layout as the MSR register in a 16550 - * - * Offset Description - * B0..3 Port - * B4 Clear to Send (CTS) - * B5 Data Set Ready (DSR) - * B6 Ring Indicator (RI) - * B7 Receive Line Signal Detect (RLSD) - * - * Byte 1: Line Status - * NOTE: same layout as the LSR register in a 16550 - * - * Offset Description - * B0 Data Ready (DR) - * B1 Overrun Error (OE) - * B2 Parity Error (PE) - * B3 Framing Error (FE) - * B4 Break Interrupt (BI) - * B5 Transmitter Holding Register (THRE) - * B6 Transmitter Empty (TEMT) - * B7 Error in RCVR FIFO - * - * - * OUT Endpoint - * - * This device reserves the first bytes of data on this endpoint contain the - * length and port identifier of the message. For the FTDI USB Serial converter - * the port identifier is always 1. - * - * Byte 0: Port & length - * - * Offset Description - * B0..1 Port - * B2..7 Length of message - (not including Byte 0) - * - */ -#define FTDI_PORT_MASK 0x0f -#define FTDI_MSR_MASK 0xf0 -#define FTDI_GET_MSR(p) (((p)[0]) & FTDI_MSR_MASK) -#define FTDI_GET_LSR(p) ((p)[1]) -#define FTDI_LSR_MASK (~0x60) /* interesting bits */ -#define FTDI_OUT_TAG(len, port) (((len) << 2) | (port)) diff --git a/sys/dev/usbmisc/ugen/Makefile b/sys/dev/usbmisc/ugen/Makefile deleted file mode 100644 index 56736a69a5..0000000000 --- a/sys/dev/usbmisc/ugen/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -# $FreeBSD: src/sys/modules/ugen/Makefile,v 1.7 1999/11/28 18:53:28 bde Exp $ -# $DragonFly: src/sys/dev/usbmisc/ugen/Makefile,v 1.5 2004/08/13 17:51:07 dillon Exp $ - -.PATH: ${.CURDIR}/../../dev/usb -KMOD = ugen -SRCS = bus_if.h device_if.h opt_usb.h ugen.c ugenbuf.c - -.include diff --git a/sys/dev/usbmisc/ugen/ugen.c b/sys/dev/usbmisc/ugen/ugen.c deleted file mode 100644 index 1b774ac60a..0000000000 --- a/sys/dev/usbmisc/ugen/ugen.c +++ /dev/null @@ -1,1564 +0,0 @@ -/* - * $NetBSD: ugen.c,v 1.27 1999/10/28 12:08:38 augustss Exp $ - * $NetBSD: ugen.c,v 1.59 2002/07/11 21:14:28 augustss Exp $ - * $FreeBSD: src/sys/dev/usb/ugen.c,v 1.81 2003/11/09 09:17:22 tanimura Exp $ - */ - -/* - * Also already merged from NetBSD: - * $NetBSD: ugen.c,v 1.61 2002/09/23 05:51:20 simonb Exp $ - * $NetBSD: ugen.c,v 1.64 2003/06/28 14:21:46 darrenr Exp $ - * $NetBSD: ugen.c,v 1.65 2003/06/29 22:30:56 fvdl Exp $ - */ - -/* - * Copyright (c) 1998 The NetBSD Foundation, Inc. - * All rights reserved. - * - * This code is derived from software contributed to The NetBSD Foundation - * by Lennart Augustsson (lennart@augustsson.net) at - * Carlstedt Research & Technology. - * - * 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. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the NetBSD - * Foundation, Inc. and its contributors. - * 4. Neither the name of The NetBSD Foundation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "ugenbuf.h" - -SYSCTL_NODE(_hw_usb, OID_AUTO, ugen, CTLFLAG_RW, 0, "USB ugen"); - -#ifdef USB_DEBUG -#define DPRINTF(x) if (ugendebug) kprintf x -#define DPRINTFN(n,x) if (ugendebug>(n)) kprintf x -int ugendebug = 0; -SYSCTL_INT(_hw_usb_ugen, OID_AUTO, debug, CTLFLAG_RW, - &ugendebug, 0, "ugen debug level"); -#else -#define DPRINTF(x) -#define DPRINTFN(n,x) -#endif - -static int ugen_bufsize = 16384; -SYSCTL_INT(_hw_usb_ugen, OID_AUTO, bufsize, CTLFLAG_RW, - &ugen_bufsize, 0, "ugen temporary buffer size"); - -#define UGEN_CHUNK 128 /* chunk size for read */ -#define UGEN_IBSIZE 1020 /* buffer size */ - -#define UGEN_NISOFRAMES 500 /* 0.5 seconds worth */ -#define UGEN_NISOREQS 6 /* number of outstanding xfer requests */ -#define UGEN_NISORFRMS 4 /* number of frames (miliseconds) per req */ - -struct ugen_endpoint { - struct ugen_softc *sc; - cdev_t dev; - usb_endpoint_descriptor_t *edesc; - usbd_interface_handle iface; - int state; -#define UGEN_ASLP 0x02 /* waiting for data */ -#define UGEN_SHORT_OK 0x04 /* short xfers are OK */ - usbd_pipe_handle pipeh; - struct clist q; - struct kqinfo rkq; - u_char *ibuf; /* start of buffer (circular for isoc) */ - u_char *fill; /* location for input (isoc) */ - u_char *limit; /* end of circular buffer (isoc) */ - u_char *cur; /* current read location (isoc) */ - u_int32_t timeout; - struct isoreq { - struct ugen_endpoint *sce; - usbd_xfer_handle xfer; - void *dmabuf; - u_int16_t sizes[UGEN_NISORFRMS]; - } isoreqs[UGEN_NISOREQS]; -}; - -struct ugen_softc { - device_t sc_dev; /* base device */ - usbd_device_handle sc_udev; - - char sc_is_open[USB_MAX_ENDPOINTS]; - struct ugen_endpoint sc_endpoints[USB_MAX_ENDPOINTS][2]; -#define OUT 0 -#define IN 1 - - int sc_refcnt; - u_char sc_dying; -}; - -d_open_t ugenopen; -d_close_t ugenclose; -d_read_t ugenread; -d_write_t ugenwrite; -d_ioctl_t ugenioctl; -d_kqfilter_t ugenkqfilter; - -static void ugen_filt_detach(struct knote *); -static int ugen_filt_read(struct knote *, long); -static int ugen_filt_write(struct knote *, long); - -static struct dev_ops ugen_ops = { - { "ugen", 0, 0 }, - .d_open = ugenopen, - .d_close = ugenclose, - .d_read = ugenread, - .d_write = ugenwrite, - .d_ioctl = ugenioctl, - .d_kqfilter = ugenkqfilter -}; - -static void ugenintr(usbd_xfer_handle xfer, usbd_private_handle addr, - usbd_status status); -static void ugen_isoc_rintr(usbd_xfer_handle xfer, usbd_private_handle addr, - usbd_status status); -static int ugen_do_read(struct ugen_softc *, int, struct uio *, int); -static int ugen_do_write(struct ugen_softc *, int, struct uio *, int); -static int ugen_do_ioctl(struct ugen_softc *, int, u_long, - caddr_t, int); -static void ugen_make_devnodes(struct ugen_softc *sc); -static void ugen_destroy_devnodes(struct ugen_softc *sc); -static int ugen_set_config(struct ugen_softc *sc, int configno); -static usb_config_descriptor_t *ugen_get_cdesc(struct ugen_softc *sc, - int index, int *lenp); -static usbd_status ugen_set_interface(struct ugen_softc *, int, int); -static int ugen_get_alt_index(struct ugen_softc *sc, int ifaceidx); - -#define UGENUNIT(n) ((lminor(n) >> 4) & 0xff) -#define UGENENDPOINT(n) (minor(n) & 0xf) -#define UGENMINOR(u, e) (((u & 0xf) << 4) | ((u & 0xf0) << 12) | (e)) -#define UGENUNITMASK 0xffff00f0 - -static device_probe_t ugen_match; -static device_attach_t ugen_attach; -static device_detach_t ugen_detach; - -static devclass_t ugen_devclass; - -static kobj_method_t ugen_methods[] = { - DEVMETHOD(device_probe, ugen_match), - DEVMETHOD(device_attach, ugen_attach), - DEVMETHOD(device_detach, ugen_detach), - DEVMETHOD_END -}; - -static driver_t ugen_driver = { - "ugen", - ugen_methods, - sizeof(struct ugen_softc) -}; - -MODULE_DEPEND(ugen, usb, 1, 1, 1); - -static int -ugen_match(device_t self) -{ - struct usb_attach_arg *uaa = device_get_ivars(self); - -#if 0 - if (uaa->matchlvl) - return (uaa->matchlvl); -#endif - if (uaa->usegeneric) - return (UMATCH_GENERIC); - else - return (UMATCH_NONE); -} - -static int -ugen_attach(device_t self) -{ - struct ugen_softc *sc = device_get_softc(self); - struct usb_attach_arg *uaa = device_get_ivars(self); - usbd_device_handle udev; - usbd_status err; - int conf; - - sc->sc_dev = self; - sc->sc_udev = udev = uaa->device; - - memset(sc->sc_endpoints, 0, sizeof sc->sc_endpoints); - - /* First set configuration index 0, the default one for ugen. */ - err = usbd_set_config_index(udev, 0, 0); - if (err) { - kprintf("%s: setting configuration index 0 failed\n", - device_get_nameunit(sc->sc_dev)); - sc->sc_dying = 1; - return ENXIO; - } - conf = usbd_get_config_descriptor(udev)->bConfigurationValue; - - /* Set up all the local state for this configuration. */ - err = ugen_set_config(sc, conf); - if (err) { - kprintf("%s: setting configuration %d failed\n", - device_get_nameunit(sc->sc_dev), conf); - sc->sc_dying = 1; - return ENXIO; - } - - /* the main device, ctrl endpoint */ - make_dev(&ugen_ops, UGENMINOR(device_get_unit(sc->sc_dev), 0), - UID_ROOT, GID_OPERATOR, 0644, - "%s", device_get_nameunit(sc->sc_dev)); - - usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev, sc->sc_dev); - return 0; -} - -static void -ugen_make_devnodes(struct ugen_softc *sc) -{ - int endptno; - cdev_t dev; - - for (endptno = 1; endptno < USB_MAX_ENDPOINTS; endptno++) { - if (sc->sc_endpoints[endptno][IN].sc != NULL || - sc->sc_endpoints[endptno][OUT].sc != NULL ) { - /* endpt can be 0x81 and 0x01, representing - * endpoint address 0x01 and IN/OUT directions. - * We map both endpts to the same device, - * IN is reading from it, OUT is writing to it. - * - * In the if clause above we check whether one - * of the structs is populated. - */ - dev = make_dev(&ugen_ops, - UGENMINOR(device_get_unit(sc->sc_dev), endptno), - UID_ROOT, GID_OPERATOR, 0644, - "%s.%d", - device_get_nameunit(sc->sc_dev), endptno); - if (sc->sc_endpoints[endptno][IN].sc != NULL) { - reference_dev(dev); - if (sc->sc_endpoints[endptno][IN].dev) - release_dev(sc->sc_endpoints[endptno][IN].dev); - sc->sc_endpoints[endptno][IN].dev = dev; - } - if (sc->sc_endpoints[endptno][OUT].sc != NULL) { - reference_dev(dev); - if (sc->sc_endpoints[endptno][OUT].dev) - release_dev(sc->sc_endpoints[endptno][OUT].dev); - sc->sc_endpoints[endptno][OUT].dev = dev; - } - } - } -} - -static void -ugen_destroy_devnodes(struct ugen_softc *sc) -{ - int endptno, prev_sc_dying; - cdev_t dev; - - prev_sc_dying = sc->sc_dying; - sc->sc_dying = 1; - - /* destroy all devices for the other (existing) endpoints as well */ - for (endptno = 1; endptno < USB_MAX_ENDPOINTS; endptno++) { - if (sc->sc_endpoints[endptno][IN].sc != NULL || - sc->sc_endpoints[endptno][OUT].sc != NULL ) { - /* endpt can be 0x81 and 0x01, representing - * endpoint address 0x01 and IN/OUT directions. - * We map both endpoint addresses to the same device, - * IN is reading from it, OUT is writing to it. - * - * In the if clause above we check whether one - * of the structs is populated. - */ - dev = sc->sc_endpoints[endptno][IN].dev; - if (dev != NULL) { - destroy_dev(dev); - sc->sc_endpoints[endptno][IN].dev = NULL; - } - dev = sc->sc_endpoints[endptno][OUT].dev; - if (dev != NULL) { - destroy_dev(dev); - sc->sc_endpoints[endptno][OUT].dev = NULL; - } - } - } - sc->sc_dying = prev_sc_dying; -} - -static int -ugen_set_config(struct ugen_softc *sc, int configno) -{ - usbd_device_handle dev = sc->sc_udev; - usbd_interface_handle iface; - usb_endpoint_descriptor_t *ed; - struct ugen_endpoint *sce; - u_int8_t niface, nendpt; - int ifaceno, endptno, endpt; - usbd_status err; - int dir; - - DPRINTFN(1,("ugen_set_config: %s to configno %d, sc=%p\n", - device_get_nameunit(sc->sc_dev), configno, sc)); - - ugen_destroy_devnodes(sc); - - /* We start at 1, not 0, because we don't care whether the - * control endpoint is open or not. It is always present. - */ - for (endptno = 1; endptno < USB_MAX_ENDPOINTS; endptno++) { - if (sc->sc_is_open[endptno]) { - DPRINTFN(1, - ("ugen_set_config: %s - endpoint %d is open\n", - device_get_nameunit(sc->sc_dev), endptno)); - return (USBD_IN_USE); - } - } - - /* Avoid setting the current value. */ - if (usbd_get_config_descriptor(dev)->bConfigurationValue != configno) { - err = usbd_set_config_no(dev, configno, 1); - if (err) - return (err); - } - - err = usbd_interface_count(dev, &niface); - if (err) - return (err); - memset(sc->sc_endpoints, 0, sizeof sc->sc_endpoints); - for (ifaceno = 0; ifaceno < niface; ifaceno++) { - DPRINTFN(1,("ugen_set_config: ifaceno %d\n", ifaceno)); - err = usbd_device2interface_handle(dev, ifaceno, &iface); - if (err) - return (err); - err = usbd_endpoint_count(iface, &nendpt); - if (err) - return (err); - for (endptno = 0; endptno < nendpt; endptno++) { - ed = usbd_interface2endpoint_descriptor(iface,endptno); - endpt = ed->bEndpointAddress; - dir = UE_GET_DIR(endpt) == UE_DIR_IN ? IN : OUT; - sce = &sc->sc_endpoints[UE_GET_ADDR(endpt)][dir]; - DPRINTFN(1,("ugen_set_config: endptno %d, endpt=0x%02x" - "(%d,%d), sce=%p\n", - endptno, endpt, UE_GET_ADDR(endpt), - UE_GET_DIR(endpt), sce)); - sce->sc = sc; - sce->edesc = ed; - sce->iface = iface; - } - } - - ugen_make_devnodes(sc); - - return (USBD_NORMAL_COMPLETION); -} - -int -ugenopen(struct dev_open_args *ap) -{ - cdev_t dev = ap->a_head.a_dev; - struct ugen_softc *sc; - int unit = UGENUNIT(dev); - int endpt = UGENENDPOINT(dev); - usb_endpoint_descriptor_t *edesc; - struct ugen_endpoint *sce; - int dir, isize; - usbd_status err; - usbd_xfer_handle xfer; - void *buf; - int i, j; - - sc = devclass_get_softc(ugen_devclass, unit); - if (sc == NULL) - return (ENXIO); - - DPRINTFN(5, ("ugenopen: flag=%d, mode=%d, unit=%d endpt=%d\n", - ap->a_oflags, ap->a_devtype, unit, endpt)); - - if (sc->sc_dying) - return (ENXIO); - - if (sc->sc_is_open[endpt]) - return (EBUSY); - - if (endpt == USB_CONTROL_ENDPOINT) { - sc->sc_is_open[USB_CONTROL_ENDPOINT] = 1; - return (0); - } - - /* Make sure there are pipes for all directions. */ - for (dir = OUT; dir <= IN; dir++) { - if (ap->a_oflags & (dir == OUT ? FWRITE : FREAD)) { - sce = &sc->sc_endpoints[endpt][dir]; - if (sce == NULL || sce->edesc == NULL) - return (ENXIO); - } - } - - /* Actually open the pipes. */ - /* XXX Should back out properly if it fails. */ - for (dir = OUT; dir <= IN; dir++) { - if (!(ap->a_oflags & (dir == OUT ? FWRITE : FREAD))) - continue; - sce = &sc->sc_endpoints[endpt][dir]; - sce->state = 0; - sce->timeout = USBD_NO_TIMEOUT; - DPRINTFN(5, ("ugenopen: sc=%p, endpt=%d, dir=%d, sce=%p\n", - sc, endpt, dir, sce)); - edesc = sce->edesc; - switch (edesc->bmAttributes & UE_XFERTYPE) { - case UE_INTERRUPT: - if (dir == OUT) { - err = usbd_open_pipe(sce->iface, - edesc->bEndpointAddress, 0, &sce->pipeh); - if (err) - return (EIO); - break; - } - isize = UGETW(edesc->wMaxPacketSize); - if (isize == 0) /* shouldn't happen */ - return (EINVAL); - sce->ibuf = kmalloc(isize, M_USBDEV, M_WAITOK); - DPRINTFN(5, ("ugenopen: intr endpt=%d,isize=%d\n", - endpt, isize)); - if ((clist_alloc_cblocks(&sce->q, UGEN_IBSIZE, - UGEN_IBSIZE), 0) == -1) - return (ENOMEM); - err = usbd_open_pipe_intr(sce->iface, - edesc->bEndpointAddress, - USBD_SHORT_XFER_OK, &sce->pipeh, sce, - sce->ibuf, isize, ugenintr, - USBD_DEFAULT_INTERVAL); - if (err) { - kfree(sce->ibuf, M_USBDEV); - clist_free_cblocks(&sce->q); - return (EIO); - } - DPRINTFN(5, ("ugenopen: interrupt open done\n")); - break; - case UE_BULK: - err = usbd_open_pipe(sce->iface, - edesc->bEndpointAddress, 0, &sce->pipeh); - if (err) - return (EIO); - break; - case UE_ISOCHRONOUS: - if (dir == OUT) - return (EINVAL); - isize = UGETW(edesc->wMaxPacketSize); - if (isize == 0) /* shouldn't happen */ - return (EINVAL); - sce->ibuf = kmalloc(isize * UGEN_NISOFRAMES, - M_USBDEV, M_WAITOK); - sce->cur = sce->fill = sce->ibuf; - sce->limit = sce->ibuf + isize * UGEN_NISOFRAMES; - DPRINTFN(5, ("ugenopen: isoc endpt=%d, isize=%d\n", - endpt, isize)); - err = usbd_open_pipe(sce->iface, - edesc->bEndpointAddress, 0, &sce->pipeh); - if (err) { - kfree(sce->ibuf, M_USBDEV); - return (EIO); - } - for(i = 0; i < UGEN_NISOREQS; ++i) { - sce->isoreqs[i].sce = sce; - xfer = usbd_alloc_xfer(sc->sc_udev); - if (xfer == 0) - goto bad; - sce->isoreqs[i].xfer = xfer; - buf = usbd_alloc_buffer - (xfer, isize * UGEN_NISORFRMS); - if (buf == NULL) { - i++; - goto bad; - } - sce->isoreqs[i].dmabuf = buf; - for(j = 0; j < UGEN_NISORFRMS; ++j) - sce->isoreqs[i].sizes[j] = isize; - usbd_setup_isoc_xfer - (xfer, sce->pipeh, &sce->isoreqs[i], - sce->isoreqs[i].sizes, - UGEN_NISORFRMS, USBD_NO_COPY, - ugen_isoc_rintr); - (void)usbd_transfer(xfer); - } - DPRINTFN(5, ("ugenopen: isoc open done\n")); - break; - bad: - while (--i >= 0) /* implicit buffer free */ - usbd_free_xfer(sce->isoreqs[i].xfer); - return (ENOMEM); - case UE_CONTROL: - sce->timeout = USBD_DEFAULT_TIMEOUT; - return (EINVAL); - } - } - sc->sc_is_open[endpt] = 1; - return (0); -} - -int -ugenclose(struct dev_close_args *ap) -{ - cdev_t dev = ap->a_head.a_dev; - int endpt = UGENENDPOINT(dev); - struct ugen_softc *sc; - struct ugen_endpoint *sce; - int dir; - int i; - - sc = devclass_get_softc(ugen_devclass, UGENUNIT(dev)); - - DPRINTFN(5, ("ugenclose: flag=%d, mode=%d, unit=%d, endpt=%d\n", - ap->a_fflag, ap->a_devtype, UGENUNIT(dev), endpt)); - -#ifdef DIAGNOSTIC - if (!sc->sc_is_open[endpt]) { - kprintf("ugenclose: not open\n"); - return (EINVAL); - } -#endif - - if (endpt == USB_CONTROL_ENDPOINT) { - DPRINTFN(5, ("ugenclose: close control\n")); - sc->sc_is_open[endpt] = 0; - return (0); - } - - for (dir = OUT; dir <= IN; dir++) { - if (!(ap->a_fflag & (dir == OUT ? FWRITE : FREAD))) - continue; - sce = &sc->sc_endpoints[endpt][dir]; - if (sce->pipeh == NULL) - continue; - DPRINTFN(5, ("ugenclose: endpt=%d dir=%d sce=%p\n", - endpt, dir, sce)); - - usbd_abort_pipe(sce->pipeh); - usbd_close_pipe(sce->pipeh); - sce->pipeh = NULL; - - switch (sce->edesc->bmAttributes & UE_XFERTYPE) { - case UE_INTERRUPT: - ndflush(&sce->q, sce->q.c_cc); - clist_free_cblocks(&sce->q); - break; - case UE_ISOCHRONOUS: - for (i = 0; i < UGEN_NISOREQS; ++i) - usbd_free_xfer(sce->isoreqs[i].xfer); - default: - break; - } - - if (sce->ibuf != NULL) { - kfree(sce->ibuf, M_USBDEV); - sce->ibuf = NULL; - clist_free_cblocks(&sce->q); - } - } - sc->sc_is_open[endpt] = 0; - - return (0); -} - -static int -ugen_do_read(struct ugen_softc *sc, int endpt, struct uio *uio, int flag) -{ - struct ugen_endpoint *sce = &sc->sc_endpoints[endpt][IN]; - u_int32_t n, tn; - char *buf; - usbd_xfer_handle xfer; - usbd_status err; - int error = 0; - int ugen_bbsize; - u_char buffer[UGEN_CHUNK]; - - DPRINTFN(5, ("%s: ugenread: %d\n", device_get_nameunit(sc->sc_dev), endpt)); - - if (sc->sc_dying) - return (EIO); - - if (endpt == USB_CONTROL_ENDPOINT) - return (ENODEV); - -#ifdef DIAGNOSTIC - if (sce->edesc == NULL) { - kprintf("ugenread: no edesc\n"); - return (EIO); - } - if (sce->pipeh == NULL) { - kprintf("ugenread: no pipe\n"); - return (EIO); - } -#endif - - buf = getugenbuf(ugen_bufsize, &ugen_bbsize); - - switch (sce->edesc->bmAttributes & UE_XFERTYPE) { - case UE_INTERRUPT: - /* Block until activity occurred. */ - crit_enter(); - while (sce->q.c_cc == 0) { - if (flag & IO_NDELAY) { - crit_exit(); - error = EWOULDBLOCK; - goto done; - } - sce->state |= UGEN_ASLP; - DPRINTFN(5, ("ugenread: sleep on %p\n", sce)); - error = tsleep(sce, PCATCH, "ugenri", - (sce->timeout * hz + 999) / 1000); - sce->state &= ~UGEN_ASLP; - DPRINTFN(5, ("ugenread: woke, error=%d\n", error)); - if (sc->sc_dying) - error = EIO; - if (error == EAGAIN) { - error = 0; /* timeout, return 0 bytes */ - break; - } - if (error) - break; - } - crit_exit(); - - /* Transfer as many chunks as possible. */ - while (sce->q.c_cc > 0 && uio->uio_resid > 0 && !error) { - n = szmin(sce->q.c_cc, uio->uio_resid); - if (n > sizeof(buffer)) - n = sizeof(buffer); - - /* Remove a small chunk from the input queue. */ - q_to_b(&sce->q, buffer, n); - DPRINTFN(5, ("ugenread: got %d chars\n", n)); - - /* Copy the data to the user process. */ - error = uiomove(buffer, n, uio); - if (error) - break; - } - break; - case UE_BULK: - xfer = usbd_alloc_xfer(sc->sc_udev); - if (xfer == 0) { - error = ENOMEM; - goto done; - } - while ((n = szmin(ugen_bbsize, uio->uio_resid)) != 0) { - DPRINTFN(1, ("ugenread: start transfer %d bytes\n",n)); - tn = n; - err = usbd_bulk_transfer( - xfer, sce->pipeh, - sce->state & UGEN_SHORT_OK ? - USBD_SHORT_XFER_OK : 0, - sce->timeout, buf, &tn, "ugenrb"); - if (err) { - if (err == USBD_INTERRUPTED) - error = EINTR; - else if (err == USBD_TIMEOUT) - error = ETIMEDOUT; - else - error = EIO; - break; - } - DPRINTFN(1, ("ugenread: got %d bytes\n", tn)); - error = uiomove(buf, tn, uio); - if (error || tn < n) - break; - } - usbd_free_xfer(xfer); - break; - case UE_ISOCHRONOUS: - crit_enter(); - while (sce->cur == sce->fill) { - if (flag & IO_NDELAY) { - crit_exit(); - error = EWOULDBLOCK; - goto done; - } - sce->state |= UGEN_ASLP; - DPRINTFN(5, ("ugenread: sleep on %p\n", sce)); - error = tsleep(sce, PCATCH, "ugenri", - (sce->timeout * hz + 999) / 1000); - sce->state &= ~UGEN_ASLP; - DPRINTFN(5, ("ugenread: woke, error=%d\n", error)); - if (sc->sc_dying) - error = EIO; - if (error == EAGAIN) { - error = 0; /* timeout, return 0 bytes */ - break; - } - if (error) - break; - } - - while (sce->cur != sce->fill && uio->uio_resid > 0 && !error) { - if (sce->fill > sce->cur) - n = szmin(sce->fill - sce->cur, uio->uio_resid); - else - n = szmin(sce->limit- sce->cur, uio->uio_resid); - - DPRINTFN(5, ("ugenread: isoc got %d chars\n", n)); - - /* Copy the data to the user process. */ - error = uiomove(sce->cur, n, uio); - if (error) - break; - sce->cur += n; - if(sce->cur >= sce->limit) - sce->cur = sce->ibuf; - } - crit_exit(); - break; - - - default: - error = ENXIO; - break; - } -done: - relugenbuf(buf, ugen_bbsize); - return (error); -} - -int -ugenread(struct dev_read_args *ap) -{ - cdev_t dev = ap->a_head.a_dev; - int endpt = UGENENDPOINT(dev); - struct ugen_softc *sc; - int error; - - sc = devclass_get_softc(ugen_devclass, UGENUNIT(dev)); - - if (sc->sc_dying) - return (EIO); - - sc->sc_refcnt++; - error = ugen_do_read(sc, endpt, ap->a_uio, ap->a_ioflag); - if (--sc->sc_refcnt < 0) - usb_detach_wakeup(sc->sc_dev); - return (error); -} - -static int -ugen_do_write(struct ugen_softc *sc, int endpt, struct uio *uio, int flag) -{ - struct ugen_endpoint *sce = &sc->sc_endpoints[endpt][OUT]; - u_int32_t n; - int error = 0; - int ugen_bbsize; - char *buf; - usbd_xfer_handle xfer; - usbd_status err; - - DPRINTFN(5, ("%s: ugenwrite: %d\n", device_get_nameunit(sc->sc_dev), endpt)); - - if (sc->sc_dying) - return (EIO); - - if (endpt == USB_CONTROL_ENDPOINT) - return (ENODEV); - -#ifdef DIAGNOSTIC - if (sce->edesc == NULL) { - kprintf("ugenwrite: no edesc\n"); - return (EIO); - } - if (sce->pipeh == NULL) { - kprintf("ugenwrite: no pipe\n"); - return (EIO); - } -#endif - - buf = getugenbuf(ugen_bufsize, &ugen_bbsize); - - switch (sce->edesc->bmAttributes & UE_XFERTYPE) { - case UE_BULK: - xfer = usbd_alloc_xfer(sc->sc_udev); - if (xfer == 0) { - error = EIO; - goto done; - } - while ((n = szmin(ugen_bbsize, uio->uio_resid)) != 0) { - error = uiomove(buf, n, uio); - if (error) - break; - DPRINTFN(1, ("ugenwrite: transfer %d bytes\n", n)); - err = usbd_bulk_transfer(xfer, sce->pipeh, 0, - sce->timeout, buf, &n,"ugenwb"); - if (err) { - if (err == USBD_INTERRUPTED) - error = EINTR; - else if (err == USBD_TIMEOUT) - error = ETIMEDOUT; - else - error = EIO; - break; - } - } - usbd_free_xfer(xfer); - break; - case UE_INTERRUPT: - xfer = usbd_alloc_xfer(sc->sc_udev); - if (xfer == 0) { - error = EIO; - goto done; - } - while ((n = szmin(UGETW(sce->edesc->wMaxPacketSize), - uio->uio_resid)) != 0) { - error = uiomove(buf, n, uio); - if (error) - break; - DPRINTFN(1, ("ugenwrite: transfer %d bytes\n", n)); - err = usbd_intr_transfer(xfer, sce->pipeh, 0, - sce->timeout, buf, &n,"ugenwi"); - if (err) { - if (err == USBD_INTERRUPTED) - error = EINTR; - else if (err == USBD_TIMEOUT) - error = ETIMEDOUT; - else - error = EIO; - break; - } - } - usbd_free_xfer(xfer); - break; - default: - error = ENXIO; - break; - } -done: - relugenbuf(buf, ugen_bbsize); - return (error); -} - -int -ugenwrite(struct dev_write_args *ap) -{ - cdev_t dev = ap->a_head.a_dev; - int endpt = UGENENDPOINT(dev); - struct ugen_softc *sc; - int error; - - sc = devclass_get_softc(ugen_devclass, UGENUNIT(dev)); - - if (sc->sc_dying) - return (EIO); - - sc->sc_refcnt++; - error = ugen_do_write(sc, endpt, ap->a_uio, ap->a_ioflag); - if (--sc->sc_refcnt < 0) - usb_detach_wakeup(sc->sc_dev); - return (error); -} - -static int -ugen_detach(device_t self) -{ - struct ugen_softc *sc = device_get_softc(self); - struct ugen_endpoint *sce; - int i, dir; - - DPRINTF(("ugen_detach: sc=%p\n", sc)); - - sc->sc_dying = 1; - /* Abort all pipes. Causes processes waiting for transfer to wake. */ - for (i = 0; i < USB_MAX_ENDPOINTS; i++) { - for (dir = OUT; dir <= IN; dir++) { - sce = &sc->sc_endpoints[i][dir]; - if (sce && sce->pipeh) - usbd_abort_pipe(sce->pipeh); - KNOTE(&sce->rkq.ki_note, 0); - } - } - crit_enter(); - if (--sc->sc_refcnt >= 0) { - /* Wake everyone */ - for (i = 0; i < USB_MAX_ENDPOINTS; i++) - wakeup(&sc->sc_endpoints[i][IN]); - /* Wait for processes to go away. */ - usb_detach_wait(sc->sc_dev); - } - crit_exit(); - - /* destroy the device for the control endpoint */ - ugen_destroy_devnodes(sc); - dev_ops_remove_minor(&ugen_ops, - /*UGENUNITMASK,*/ UGENMINOR(device_get_unit(sc->sc_dev), 0)); - usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev, sc->sc_dev); - return (0); -} - -static void -ugenintr(usbd_xfer_handle xfer, usbd_private_handle addr, usbd_status status) -{ - struct ugen_endpoint *sce = addr; - /*struct ugen_softc *sc = sce->sc;*/ - u_int32_t count; - u_char *ibuf; - - if (status == USBD_CANCELLED) - return; - - if (status != USBD_NORMAL_COMPLETION) { - DPRINTF(("ugenintr: status=%d\n", status)); - if (status == USBD_STALLED) - usbd_clear_endpoint_stall_async(sce->pipeh); - return; - } - - usbd_get_xfer_status(xfer, NULL, NULL, &count, NULL); - ibuf = sce->ibuf; - - DPRINTFN(5, ("ugenintr: xfer=%p status=%d count=%d\n", - xfer, status, count)); - DPRINTFN(5, (" data = %02x %02x %02x\n", - ibuf[0], ibuf[1], ibuf[2])); - - (void)b_to_q(ibuf, count, &sce->q); - - if (sce->state & UGEN_ASLP) { - sce->state &= ~UGEN_ASLP; - DPRINTFN(5, ("ugen_intr: waking %p\n", sce)); - wakeup(sce); - } - KNOTE(&sce->rkq.ki_note, 0); -} - -static void -ugen_isoc_rintr(usbd_xfer_handle xfer, usbd_private_handle addr, - usbd_status status) -{ - struct isoreq *req = addr; - struct ugen_endpoint *sce = req->sce; - u_int32_t count, n; - int i, isize; - - /* Return if we are aborting. */ - if (status == USBD_CANCELLED) - return; - - usbd_get_xfer_status(xfer, NULL, NULL, &count, NULL); - DPRINTFN(5,("ugen_isoc_rintr: xfer %d, count=%d\n", - (int)(req - sce->isoreqs), - count)); - - /* throw away oldest input if the buffer is full */ - if(sce->fill < sce->cur && sce->cur <= sce->fill + count) { - sce->cur += count; - if(sce->cur >= sce->limit) - sce->cur = sce->ibuf + (sce->limit - sce->cur); - DPRINTFN(5, ("ugen_isoc_rintr: throwing away %d bytes\n", - count)); - } - - isize = UGETW(sce->edesc->wMaxPacketSize); - for (i = 0; i < UGEN_NISORFRMS; i++) { - u_int32_t actlen = req->sizes[i]; - char const *buf = (char const *)req->dmabuf + isize * i; - - /* copy data to buffer */ - while (actlen > 0) { - n = min(actlen, sce->limit - sce->fill); - memcpy(sce->fill, buf, n); - - buf += n; - actlen -= n; - sce->fill += n; - if(sce->fill == sce->limit) - sce->fill = sce->ibuf; - } - - /* setup size for next transfer */ - req->sizes[i] = isize; - } - - usbd_setup_isoc_xfer(xfer, sce->pipeh, req, req->sizes, UGEN_NISORFRMS, - USBD_NO_COPY, ugen_isoc_rintr); - (void)usbd_transfer(xfer); - - if (sce->state & UGEN_ASLP) { - sce->state &= ~UGEN_ASLP; - DPRINTFN(5, ("ugen_isoc_rintr: waking %p\n", sce)); - wakeup(sce); - } - KNOTE(&sce->rkq.ki_note, 0); -} - -static usbd_status -ugen_set_interface(struct ugen_softc *sc, int ifaceidx, int altno) -{ - usbd_interface_handle iface; - usb_endpoint_descriptor_t *ed; - usbd_status err; - struct ugen_endpoint *sce; - u_int8_t niface, nendpt, endptno, endpt; - int dir; - - DPRINTFN(15, ("ugen_set_interface %d %d\n", ifaceidx, altno)); - - err = usbd_interface_count(sc->sc_udev, &niface); - if (err) - return (err); - if (ifaceidx < 0 || ifaceidx >= niface) - return (USBD_INVAL); - - err = usbd_device2interface_handle(sc->sc_udev, ifaceidx, &iface); - if (err) - return (err); - err = usbd_endpoint_count(iface, &nendpt); - if (err) - return (err); - - /* destroy the existing devices, we remake the new ones in a moment */ - ugen_destroy_devnodes(sc); - - /* XXX should only do this after setting new altno has succeeded */ - for (endptno = 0; endptno < nendpt; endptno++) { - ed = usbd_interface2endpoint_descriptor(iface,endptno); - endpt = ed->bEndpointAddress; - dir = UE_GET_DIR(endpt) == UE_DIR_IN ? IN : OUT; - sce = &sc->sc_endpoints[UE_GET_ADDR(endpt)][dir]; - sce->sc = NULL; - sce->edesc = NULL; - sce->iface = 0; - } - - /* change setting */ - err = usbd_set_interface(iface, altno); - if (err) - return (err); - - err = usbd_endpoint_count(iface, &nendpt); - if (err) - return (err); - for (endptno = 0; endptno < nendpt; endptno++) { - ed = usbd_interface2endpoint_descriptor(iface,endptno); - endpt = ed->bEndpointAddress; - dir = UE_GET_DIR(endpt) == UE_DIR_IN ? IN : OUT; - sce = &sc->sc_endpoints[UE_GET_ADDR(endpt)][dir]; - sce->sc = sc; - sce->edesc = ed; - sce->iface = iface; - } - - /* make the new devices */ - ugen_make_devnodes(sc); - - return (0); -} - -/* Retrieve a complete descriptor for a certain device and index. */ -static usb_config_descriptor_t * -ugen_get_cdesc(struct ugen_softc *sc, int index, int *lenp) -{ - usb_config_descriptor_t *cdesc, *tdesc, cdescr; - int len; - usbd_status err; - - if (index == USB_CURRENT_CONFIG_INDEX) { - tdesc = usbd_get_config_descriptor(sc->sc_udev); - len = UGETW(tdesc->wTotalLength); - if (lenp) - *lenp = len; - cdesc = kmalloc(len, M_TEMP, M_INTWAIT); - memcpy(cdesc, tdesc, len); - DPRINTFN(5,("ugen_get_cdesc: current, len=%d\n", len)); - } else { - err = usbd_get_config_desc(sc->sc_udev, index, &cdescr); - if (err) - return (0); - len = UGETW(cdescr.wTotalLength); - DPRINTFN(5,("ugen_get_cdesc: index=%d, len=%d\n", index, len)); - if (lenp) - *lenp = len; - cdesc = kmalloc(len, M_TEMP, M_INTWAIT); - err = usbd_get_config_desc_full(sc->sc_udev, index, cdesc, len); - if (err) { - kfree(cdesc, M_TEMP); - return (0); - } - } - return (cdesc); -} - -static int -ugen_get_alt_index(struct ugen_softc *sc, int ifaceidx) -{ - usbd_interface_handle iface; - usbd_status err; - - err = usbd_device2interface_handle(sc->sc_udev, ifaceidx, &iface); - if (err) - return (-1); - return (usbd_get_interface_altindex(iface)); -} - -static int -ugen_do_ioctl(struct ugen_softc *sc, int endpt, u_long cmd, - caddr_t addr, int flag) -{ - struct ugen_endpoint *sce; - usbd_status err; - usbd_interface_handle iface; - struct usb_config_desc *cd; - usb_config_descriptor_t *cdesc; - struct usb_interface_desc *id; - usb_interface_descriptor_t *idesc; - struct usb_endpoint_desc *ed; - usb_endpoint_descriptor_t *edesc; - struct usb_alt_interface *ai; - struct usb_string_desc *si; - u_int8_t conf, alt; - - DPRINTFN(5, ("ugenioctl: cmd=%08lx\n", cmd)); - if (sc->sc_dying) - return (EIO); - - switch (cmd) { - case USB_SET_SHORT_XFER: - /* This flag only affects read */ - if (endpt == USB_CONTROL_ENDPOINT) - return (EINVAL); - sce = &sc->sc_endpoints[endpt][IN]; - - if (sce->pipeh == NULL) { - kprintf("ugenioctl: USB_SET_SHORT_XFER, no pipe\n"); - return (EIO); - } - - if (*(int *)addr) - sce->state |= UGEN_SHORT_OK; - else - sce->state &= ~UGEN_SHORT_OK; - return (0); - case USB_SET_TIMEOUT: - sce = &sc->sc_endpoints[endpt][IN]; - sce->timeout = *(int *)addr; - sce = &sc->sc_endpoints[endpt][OUT]; - sce->timeout = *(int *)addr; - return (0); - default: - break; - } - - if (endpt != USB_CONTROL_ENDPOINT) - return (EINVAL); - - switch (cmd) { -#ifdef USB_DEBUG - case USB_SETDEBUG: - ugendebug = *(int *)addr; - break; -#endif - case USB_GET_CONFIG: - err = usbd_get_config(sc->sc_udev, &conf); - if (err) - return (EIO); - *(int *)addr = conf; - break; - case USB_SET_CONFIG: - if (!(flag & FWRITE)) - return (EPERM); - err = ugen_set_config(sc, *(int *)addr); - switch (err) { - case USBD_NORMAL_COMPLETION: - break; - case USBD_IN_USE: - return (EBUSY); - default: - return (EIO); - } - break; - case USB_GET_ALTINTERFACE: - ai = (struct usb_alt_interface *)addr; - err = usbd_device2interface_handle(sc->sc_udev, - ai->uai_interface_index, &iface); - if (err) - return (EINVAL); - idesc = usbd_get_interface_descriptor(iface); - if (idesc == NULL) - return (EIO); - ai->uai_alt_no = idesc->bAlternateSetting; - break; - case USB_SET_ALTINTERFACE: - if (!(flag & FWRITE)) - return (EPERM); - ai = (struct usb_alt_interface *)addr; - err = usbd_device2interface_handle(sc->sc_udev, - ai->uai_interface_index, &iface); - if (err) - return (EINVAL); - err = ugen_set_interface(sc, ai->uai_interface_index, ai->uai_alt_no); - if (err) - return (EINVAL); - break; - case USB_GET_NO_ALT: - ai = (struct usb_alt_interface *)addr; - cdesc = ugen_get_cdesc(sc, ai->uai_config_index, 0); - if (cdesc == NULL) - return (EINVAL); - idesc = usbd_find_idesc(cdesc, ai->uai_interface_index, 0); - if (idesc == NULL) { - kfree(cdesc, M_TEMP); - return (EINVAL); - } - ai->uai_alt_no = usbd_get_no_alts(cdesc, idesc->bInterfaceNumber); - kfree(cdesc, M_TEMP); - break; - case USB_GET_DEVICE_DESC: - *(usb_device_descriptor_t *)addr = - *usbd_get_device_descriptor(sc->sc_udev); - break; - case USB_GET_CONFIG_DESC: - cd = (struct usb_config_desc *)addr; - cdesc = ugen_get_cdesc(sc, cd->ucd_config_index, 0); - if (cdesc == NULL) - return (EINVAL); - cd->ucd_desc = *cdesc; - kfree(cdesc, M_TEMP); - break; - case USB_GET_INTERFACE_DESC: - id = (struct usb_interface_desc *)addr; - cdesc = ugen_get_cdesc(sc, id->uid_config_index, 0); - if (cdesc == NULL) - return (EINVAL); - if (id->uid_config_index == USB_CURRENT_CONFIG_INDEX && - id->uid_alt_index == USB_CURRENT_ALT_INDEX) - alt = ugen_get_alt_index(sc, id->uid_interface_index); - else - alt = id->uid_alt_index; - idesc = usbd_find_idesc(cdesc, id->uid_interface_index, alt); - if (idesc == NULL) { - kfree(cdesc, M_TEMP); - return (EINVAL); - } - id->uid_desc = *idesc; - kfree(cdesc, M_TEMP); - break; - case USB_GET_ENDPOINT_DESC: - ed = (struct usb_endpoint_desc *)addr; - cdesc = ugen_get_cdesc(sc, ed->ued_config_index, 0); - if (cdesc == NULL) - return (EINVAL); - if (ed->ued_config_index == USB_CURRENT_CONFIG_INDEX && - ed->ued_alt_index == USB_CURRENT_ALT_INDEX) - alt = ugen_get_alt_index(sc, ed->ued_interface_index); - else - alt = ed->ued_alt_index; - edesc = usbd_find_edesc(cdesc, ed->ued_interface_index, - alt, ed->ued_endpoint_index); - if (edesc == NULL) { - kfree(cdesc, M_TEMP); - return (EINVAL); - } - ed->ued_desc = *edesc; - kfree(cdesc, M_TEMP); - break; - case USB_GET_FULL_DESC: - { - int len; - struct iovec iov; - struct uio uio; - struct usb_full_desc *fd = (struct usb_full_desc *)addr; - int error; - - cdesc = ugen_get_cdesc(sc, fd->ufd_config_index, &len); - if (len > fd->ufd_size) - len = fd->ufd_size; - iov.iov_base = (caddr_t)fd->ufd_data; - iov.iov_len = len; - uio.uio_iov = &iov; - uio.uio_iovcnt = 1; - uio.uio_resid = len; - uio.uio_offset = 0; - uio.uio_segflg = UIO_USERSPACE; - uio.uio_rw = UIO_READ; - uio.uio_td = curthread; - error = uiomove((void *)cdesc, len, &uio); - kfree(cdesc, M_TEMP); - return (error); - } - case USB_GET_STRING_DESC: - { - int size; - - si = (struct usb_string_desc *)addr; - err = usbd_get_string_desc(sc->sc_udev, si->usd_string_index, - si->usd_language_id, &si->usd_desc, &size); - if (err) - return (EINVAL); - break; - } - case USB_DO_REQUEST: - { - struct usb_ctl_request *ur = (void *)addr; - int len = UGETW(ur->ucr_request.wLength); - struct iovec iov; - struct uio uio; - void *ptr = NULL; - usbd_status err; - int error = 0; - - if (!(flag & FWRITE)) - return (EPERM); - /* Avoid requests that would damage the bus integrity. */ - if ((ur->ucr_request.bmRequestType == UT_WRITE_DEVICE && - ur->ucr_request.bRequest == UR_SET_ADDRESS) || - (ur->ucr_request.bmRequestType == UT_WRITE_DEVICE && - ur->ucr_request.bRequest == UR_SET_CONFIG) || - (ur->ucr_request.bmRequestType == UT_WRITE_INTERFACE && - ur->ucr_request.bRequest == UR_SET_INTERFACE)) - return (EINVAL); - - if (len < 0 || len > 32767) - return (EINVAL); - if (len != 0) { - iov.iov_base = (caddr_t)ur->ucr_data; - iov.iov_len = len; - uio.uio_iov = &iov; - uio.uio_iovcnt = 1; - uio.uio_resid = len; - uio.uio_offset = 0; - uio.uio_segflg = UIO_USERSPACE; - uio.uio_rw = - ur->ucr_request.bmRequestType & UT_READ ? - UIO_READ : UIO_WRITE; - uio.uio_td = curthread; - ptr = kmalloc(len, M_TEMP, M_WAITOK); - if (uio.uio_rw == UIO_WRITE) { - error = uiomove(ptr, len, &uio); - if (error) - goto ret; - } - } - sce = &sc->sc_endpoints[endpt][IN]; - err = usbd_do_request_flags(sc->sc_udev, &ur->ucr_request, - ptr, ur->ucr_flags, &ur->ucr_actlen, sce->timeout); - if (err) { - error = EIO; - goto ret; - } - if (len != 0) { - if (uio.uio_rw == UIO_READ) { - error = uiomove(ptr, len, &uio); - if (error) - goto ret; - } - } - ret: - if (ptr) - kfree(ptr, M_TEMP); - return (error); - } - case USB_GET_DEVICEINFO: - usbd_fill_deviceinfo(sc->sc_udev, - (struct usb_device_info *)addr, 1); - break; - default: - return (EINVAL); - } - return (0); -} - -int -ugenioctl(struct dev_ioctl_args *ap) -{ - cdev_t dev = ap->a_head.a_dev; - int endpt = UGENENDPOINT(dev); - struct ugen_softc *sc; - int error; - - sc = devclass_get_softc(ugen_devclass, UGENUNIT(dev)); - if (sc->sc_dying) - return (EIO); - - sc->sc_refcnt++; - error = ugen_do_ioctl(sc, endpt, ap->a_cmd, ap->a_data, ap->a_fflag); - if (--sc->sc_refcnt < 0) - usb_detach_wakeup(sc->sc_dev); - return (error); -} - -static struct filterops ugen_filtops_read = - { FILTEROP_ISFD, NULL, ugen_filt_detach, ugen_filt_read }; -static struct filterops ugen_filtops_write = - { FILTEROP_ISFD, NULL, ugen_filt_detach, ugen_filt_write }; - -int -ugenkqfilter(struct dev_kqfilter_args *ap) -{ - cdev_t dev = ap->a_head.a_dev; - struct knote *kn = ap->a_kn; - struct klist *klist; - struct ugen_softc *sc; - struct ugen_endpoint *sce; - - sc = devclass_get_softc(ugen_devclass, UGENUNIT(dev)); - - ap->a_result = 1; - - if (sc->sc_dying) - return (0); - - /* Do not allow filter on a control endpoint */ - if (UGENENDPOINT(dev) == USB_CONTROL_ENDPOINT) - return (0); - - ap->a_result = 0; - - switch (kn->kn_filter) { - case EVFILT_READ: - sce = &sc->sc_endpoints[UGENENDPOINT(dev)][IN]; - kn->kn_fop = &ugen_filtops_read; - kn->kn_hook = (caddr_t)dev; - break; - case EVFILT_WRITE: - sce = &sc->sc_endpoints[UGENENDPOINT(dev)][OUT]; - kn->kn_fop = &ugen_filtops_write; - kn->kn_hook = (caddr_t)dev; - break; - default: - ap->a_result = EOPNOTSUPP; - return (0); - } - - if (sce->edesc != NULL || sce->pipeh != NULL) { - klist = &sce->rkq.ki_note; - knote_insert(klist, kn); - } - - return (0); -} - -static void -ugen_filt_detach(struct knote *kn) -{ - cdev_t dev = (cdev_t)kn->kn_hook; - struct ugen_softc *sc; - struct ugen_endpoint *sce; - struct klist *klist; - - sc = devclass_get_softc(ugen_devclass, UGENUNIT(dev)); - - switch (kn->kn_filter) { - case EVFILT_READ: - sce = &sc->sc_endpoints[UGENENDPOINT(dev)][IN]; - break; - case EVFILT_WRITE: - sce = &sc->sc_endpoints[UGENENDPOINT(dev)][OUT]; - break; - default: - return; - } - - if (sce->edesc != NULL || sce->pipeh != NULL) { - klist = &sce->rkq.ki_note; - knote_remove(klist, kn); - } -} - -static int -ugen_filt_read(struct knote *kn, long hint) -{ - cdev_t dev = (cdev_t)kn->kn_hook; - struct ugen_softc *sc; - struct ugen_endpoint *sce; - int ready = 0; - - sc = devclass_get_softc(ugen_devclass, UGENUNIT(dev)); - sce = &sc->sc_endpoints[UGENENDPOINT(dev)][IN]; - - switch (sce->edesc->bmAttributes & UE_XFERTYPE) { - case UE_INTERRUPT: - if (sce->q.c_cc > 0) - ready = 1; - break; - case UE_ISOCHRONOUS: - if (sce->cur != sce->fill) - ready = 1; - break; - case UE_BULK: - ready = 1; - break; - default: - break; - } - - return (ready); -} - -static int -ugen_filt_write(struct knote *kn, long hint) -{ - cdev_t dev = (cdev_t)kn->kn_hook; - struct ugen_softc *sc; - struct ugen_endpoint *sce; - int ready = 0; - - sc = devclass_get_softc(ugen_devclass, UGENUNIT(dev)); - sce = &sc->sc_endpoints[UGENENDPOINT(dev)][OUT]; - - switch (sce->edesc->bmAttributes & UE_XFERTYPE) { - case UE_INTERRUPT: - if (sce->q.c_cc > 0) - ready = 1; - break; - case UE_ISOCHRONOUS: - if (sce->cur != sce->fill) - ready = 1; - break; - case UE_BULK: - ready = 1; - break; - default: - break; - } - - return (ready); -} - -DRIVER_MODULE(ugen, uhub, ugen_driver, ugen_devclass, usbd_driver_load, NULL); - diff --git a/sys/dev/usbmisc/ugen/ugenbuf.c b/sys/dev/usbmisc/ugen/ugenbuf.c deleted file mode 100644 index c4ab2f8123..0000000000 --- a/sys/dev/usbmisc/ugen/ugenbuf.c +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright (c) 2004 The DragonFly Project. - * All rights reserved. - * - * This code is derived from software contributed to The DragonFly Project - * by Matthew Dillon . - * - * 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. - * 3. Neither the name of The DragonFly Project nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific, prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 - * COPYRIGHT HOLDERS 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. - * - * $DragonFly: src/sys/dev/usbmisc/ugen/ugenbuf.c,v 1.3 2006/09/05 00:55:43 dillon Exp $ - */ - -#include -#include -#include -#include -#include -#include "ugenbuf.h" - -static MALLOC_DEFINE(M_UGENBUF, "ugenbufs", "Temporary buffer space"); -static void *ugencache_buf; -static int ugencache_size; - -/* - * getugenbuf() - * - * Allocate a temporary buffer for UGEN. This routine is called from - * mainline code only and the BGL is held. - */ -void * -getugenbuf(int reqsize, int *bsize) -{ - void *buf; - - if (reqsize < 256) - reqsize = 256; - if (reqsize > 262144) - reqsize = 262144; - *bsize = reqsize; - - buf = ugencache_buf; - if (buf == NULL) { - buf = kmalloc(reqsize, M_UGENBUF, M_WAITOK); - } else if (ugencache_size != reqsize) { - ugencache_buf = NULL; - kfree(buf, M_UGENBUF); - buf = kmalloc(reqsize, M_UGENBUF, M_WAITOK); - } else { - buf = ugencache_buf; - ugencache_buf = NULL; - } - return(buf); -} - -/* - * relugenbuf() - * - * Release a temporary buffer for UGEN. This routine is called from - * mainline code only and the BGL is held. - */ -void -relugenbuf(void *buf, int bsize) -{ - if (ugencache_buf == NULL) { - ugencache_buf = buf; - ugencache_size = bsize; - } else { - kfree(buf, M_UGENBUF); - } -} - diff --git a/sys/dev/usbmisc/ugen/ugenbuf.h b/sys/dev/usbmisc/ugen/ugenbuf.h deleted file mode 100644 index 538115d0a4..0000000000 --- a/sys/dev/usbmisc/ugen/ugenbuf.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (c) 2004 The DragonFly Project. - * All rights reserved. - * - * This code is derived from software contributed to The DragonFly Project - * by Hiten Pandya and Matthew Dillon - * . - * - * 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. - * 3. Neither the name of The DragonFly Project nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific, prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 - * COPYRIGHT HOLDERS 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. - * - * $DragonFly: src/sys/dev/usbmisc/ugen/ugenbuf.h,v 1.2 2004/07/08 16:18:50 dillon Exp $ - */ - -extern void *getugenbuf(int reqsize, int *bsize); -extern void relugenbuf(void *buf, int bsize); diff --git a/sys/dev/usbmisc/ugensa/Makefile b/sys/dev/usbmisc/ugensa/Makefile deleted file mode 100644 index 9dd206e8c0..0000000000 --- a/sys/dev/usbmisc/ugensa/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -# $DragonFly: src/sys/dev/usbmisc/ugensa/Makefile,v 1.1 2008/02/11 18:13:58 hasso Exp $ - -.PATH: ${.CURDIR}/../ucom - -KMOD= ugensa -SRCS= ugensa.c opt_usb.h device_if.h bus_if.h - -.include diff --git a/sys/dev/usbmisc/ugensa/ugensa.c b/sys/dev/usbmisc/ugensa/ugensa.c deleted file mode 100644 index f5db5d12db..0000000000 --- a/sys/dev/usbmisc/ugensa/ugensa.c +++ /dev/null @@ -1,477 +0,0 @@ -/* $OpenBSD: umsm.c,v 1.15 2007/06/14 10:11:16 mbalmer Exp $ */ - -/* - * Copyright (c) 2006 Jonathan Gray - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -/* - * Generic USB serial driver used for devices where hardware specific - * don't apply or doesn't make sense (for example Qualcomm MSM EVDO, UMTS - * and other similar communication devices). - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#ifdef UGENSA_DEBUG -static int ugensadebug = 1; -#define DPRINTFN(n, x) do { if (ugensadebug > (n)) kprintf x; } while (0) -#else -#define DPRINTFN(n, x) -#endif -#define DPRINTF(x) DPRINTFN(0, x) - -#define UGENSABUFSZ 4096 -#define UGENSA_INTR_INTERVAL 100 /* ms */ - -struct ugensa_softc { - struct ucom_softc sc_ucom; - int sc_iface_no; - - /* interrupt ep */ - int sc_intr_number; - usbd_pipe_handle sc_intr_pipe; - u_char *sc_intr_buf; - int sc_isize; - - u_char sc_lsr; /* Local status register */ - u_char sc_msr; /* Status register */ - u_char sc_dtr; /* Current DTR state */ - u_char sc_rts; /* Current RTS state */ -}; - -static device_probe_t ugensa_match; -static device_attach_t ugensa_attach; -static device_detach_t ugensa_detach; - -static int ugensa_open(void *, int); -static void ugensa_close(void *, int); -static void ugensa_intr(usbd_xfer_handle, usbd_private_handle, usbd_status); -static void ugensa_get_status(void *, int, u_char *, u_char *); -static void ugensa_set(void *, int, int, int); - -static void ugensa_e220_changemode(usbd_device_handle); - -static device_method_t ugensa_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, ugensa_match), - DEVMETHOD(device_attach, ugensa_attach), - DEVMETHOD(device_detach, ugensa_detach), - DEVMETHOD_END -}; - -static driver_t ugensa_driver = { - "ucom", - ugensa_methods, - sizeof (struct ugensa_softc) -}; - -struct ucom_callback ugensa_callback = { - ugensa_get_status, - ugensa_set, - NULL, - NULL, - ugensa_open, - ugensa_close, - NULL, - NULL -}; - -static const struct usb_devno ugensa_devs[] = { - { USB_DEVICE(0x05c6, 0x6000) }, /* Qualcomm HSDPA MSM */ - { USB_DEVICE(0x05c6, 0x6613) }, /* Qualcomm HSDPA MSM */ - { USB_DEVICE(0x0c88, 0x17da) }, /* Kyocera KPC650 */ - { USB_DEVICE(0x0f3d, 0x0112) }, /* AirPrime PC5220 */ - { USB_DEVICE(0x1199, 0x0017) }, /* Sierra Wireless EM5625 */ - { USB_DEVICE(0x1199, 0x0018) }, /* Sierra Wireless MC5720 */ - { USB_DEVICE(0x1199, 0x0019) }, /* Sierra Wireless AirCard 595 */ - { USB_DEVICE(0x1199, 0x0020) }, /* Sierra Wireless MC5725 */ - { USB_DEVICE(0x1199, 0x0021) }, /* Sierra Wireless AirCard 597E */ - { USB_DEVICE(0x1199, 0x0112) }, /* Sierra Wireless AirCard 580 */ - { USB_DEVICE(0x1199, 0x0120) }, /* Sierra Wireless AirCard 595U */ - { USB_DEVICE(0x1199, 0x0218) }, /* Sierra Wireless MC5720 */ - { USB_DEVICE(0x1199, 0x0220) }, /* Sierra Wireless MC5725 */ - { USB_DEVICE(0x1199, 0x6802) }, /* Sierra Wireless MC8755 */ - { USB_DEVICE(0x1199, 0x6803) }, /* Sierra Wireless MC8765 */ - { USB_DEVICE(0x1199, 0x6804) }, /* Sierra Wireless MC8755 */ - { USB_DEVICE(0x1199, 0x6812) }, /* Sierra Wireless MC8775 */ - { USB_DEVICE(0x1199, 0x6813) }, /* Sierra Wireless MC8755 */ - { USB_DEVICE(0x1199, 0x6820) }, /* Sierra Wireless AirCard 875 */ - { USB_DEVICE(0x1199, 0x6832) }, /* Sierra Wireless MC8780 */ - { USB_DEVICE(0x1199, 0x6833) }, /* Sierra Wireless MC8781 */ - { USB_DEVICE(0x1199, 0x6850) }, /* Sierra Wireless AirCard 880 */ - { USB_DEVICE(0x1199, 0x6851) }, /* Sierra Wireless AirCard 881 */ - { USB_DEVICE(0x1199, 0x6852) }, /* Sierra Wireless AirCard 880E */ - { USB_DEVICE(0x1199, 0x6853) }, /* Sierra Wireless AirCard 881E */ - { USB_DEVICE(0x1199, 0x6855) }, /* Sierra Wireless AirCard 880U */ - { USB_DEVICE(0x1199, 0x6856) }, /* Sierra Wireless AirCard 881U */ - { USB_DEVICE(0x12d1, 0x1001) }, /* Huawei Mobile Connect */ - { USB_DEVICE(0x12d1, 0x1003) }, /* Huawei Mobile E220 */ - { USB_DEVICE(0x12d1, 0x1004) }, /* Huawei Mobile E220 */ - { USB_DEVICE(0x1410, 0x1100) }, /* Novatel Wireless Merlin XS620/S640 */ - { USB_DEVICE(0x1410, 0x1110) }, /* Novatel Wireless Merlin S620/V620 */ - { USB_DEVICE(0x1410, 0x1120) }, /* Novatel Wireless Merlin EX720 */ - { USB_DEVICE(0x1410, 0x1130) }, /* Novatel Wireless Merlin S720 */ - { USB_DEVICE(0x1410, 0x1400) }, /* Novatel Wireless Merlin U730 */ - { USB_DEVICE(0x1410, 0x1410) }, /* Novatel Wireless Merlin U740 */ - { USB_DEVICE(0x1410, 0x1420) }, /* Novatel Wireless Expedite EU870D */ - { USB_DEVICE(0x1410, 0x1430) }, /* Novatel Wireless Merlin XU870 */ - { USB_DEVICE(0x1410, 0x2100) }, /* Novatel Wireless Expedite EV620 */ - { USB_DEVICE(0x1410, 0x2110) }, /* Novatel Wireless Merlin ES620, - Merlin ES720, Ovation U720 */ - { USB_DEVICE(0x1410, 0x2130) }, /* Novatel Wireless Merlin ES620 */ - { USB_DEVICE(0x1410, 0x2410) }, /* Novatel Wireless Expedite EU740 */ - { USB_DEVICE(0x1410, 0x4100) }, /* Novatel Wireless Ovation MC727 */ - { USB_DEVICE(0x1410, 0x4400) }, /* Novatel Wireless Ovation MC950D */ - { USB_DEVICE(0x16d5, 0x6501) }, /* AnyDATA ADU-E100A/D/H */ - { USB_DEVICE(0x413c, 0x8114) }, /* Dell Wireless 5700 */ - { USB_DEVICE(0x413c, 0x8115) }, /* Dell Wireless 5500 */ - { USB_DEVICE(0x413c, 0x8116) }, /* Dell Wireless 5505 */ - { USB_DEVICE(0x413c, 0x8117) }, /* Dell Wireless 5700 */ - { USB_DEVICE(0x413c, 0x8118) }, /* Dell Wireless 5510 */ - { USB_DEVICE(0x413c, 0x8128) }, /* Dell Wireless 5700 */ - { USB_DEVICE(0x413c, 0x8136) }, /* Dell Wireless 5520 */ - { USB_DEVICE(0x413c, 0x8137) }, /* Dell Wireless 5520 */ -}; - -DRIVER_MODULE(ugensa, uhub, ugensa_driver, ucom_devclass, usbd_driver_load, NULL); -MODULE_DEPEND(ugensa, usb, 1, 1, 1); -MODULE_DEPEND(ugensa, ucom, UCOM_MINVER, UCOM_PREFVER, UCOM_MAXVER); -MODULE_VERSION(ugensa, 1); - -static int -ugensa_match(device_t self) -{ - struct usb_attach_arg *uaa = device_get_ivars(self); - - if (uaa->iface == NULL) - return UMATCH_NONE; - - /* - * Some devices have mass storage interfaces. What we do with these - * is telling them that we don't need the mass storage and then - * just treat them the way we should. - * - * These devices, most notably Huawei (vendor id 0x12d1) have only - * one interface in mass storage, and after sending them magic, - * they have more than one and are in the correct operating mode. - */ - - if (uaa->vendor == 0x12d1) { - if (uaa->nifaces > 1) { - /* - * XXX: we might want to let the normal lookup handle - * these cases. Right now we just claim we know the - * device if it isn't in mass storage mode anymore. - */ - return UMATCH_VENDOR_IFACESUBCLASS; - } else { - ugensa_e220_changemode(uaa->device); - return -1; // avoid umass to reattach (UMATCH_HIGHEST) - } - } - - return (usb_lookup(ugensa_devs, uaa->vendor, uaa->product) != NULL) ? - UMATCH_VENDOR_IFACESUBCLASS : UMATCH_NONE; -} - -static int -ugensa_attach(device_t self) -{ - struct ugensa_softc *sc = device_get_softc(self); - struct usb_attach_arg *uaa = device_get_ivars(self); - struct ucom_softc *ucom; - usb_interface_descriptor_t *id; - usb_endpoint_descriptor_t *ed; - int i; - - ucom = &sc->sc_ucom; - bzero(sc, sizeof (struct ugensa_softc)); - - ucom->sc_dev = self; - ucom->sc_udev = uaa->device; - ucom->sc_iface = uaa->iface; - - id = usbd_get_interface_descriptor(ucom->sc_iface); - - sc->sc_iface_no = id->bInterfaceNumber; - ucom->sc_bulkin_no = ucom->sc_bulkout_no = -1; - for (i = 0; i < id->bNumEndpoints; i++) { - ed = usbd_interface2endpoint_descriptor(ucom->sc_iface, i); - if (ed == NULL) { - device_printf(ucom->sc_dev, "no endpoint descriptor " - "found for %d\n", i); - goto error; - } - - if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && - UE_GET_XFERTYPE(ed->bmAttributes) == UE_INTERRUPT) { - sc->sc_intr_number = ed->bEndpointAddress; - sc->sc_isize = UGETW(ed->wMaxPacketSize); - } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && - UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) - ucom->sc_bulkin_no = ed->bEndpointAddress; - else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT && - UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) - ucom->sc_bulkout_no = ed->bEndpointAddress; - } - if (ucom->sc_bulkin_no == -1 || ucom->sc_bulkout_no == -1) { - device_printf(ucom->sc_dev, "missing endpoint\n"); - goto error; - } - - sc->sc_dtr = sc->sc_rts = -1; - - ucom->sc_parent = sc; - ucom->sc_portno = UCOM_UNK_PORTNO; - ucom->sc_ibufsize = UGENSABUFSZ; - ucom->sc_obufsize = UGENSABUFSZ; - ucom->sc_ibufsizepad = UGENSABUFSZ; - ucom->sc_opkthdrlen = 0; - ucom->sc_callback = &ugensa_callback; - - usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, ucom->sc_udev, - ucom->sc_dev); - - DPRINTF(("%s: in = 0x%x, out = 0x%x\n", - device_get_nameunit(ucom->sc_dev), ucom->sc_bulkin_no, - ucom->sc_bulkout_no)); - - ucom_attach(&sc->sc_ucom); - - return 0; - -error: - ucom->sc_dying = 1; - return ENXIO; -} - -static int -ugensa_detach(device_t self) -{ - struct ugensa_softc *sc = device_get_softc(self); - int rv = 0; - - /* close the interrupt endpoint if that is opened */ - if (sc->sc_intr_pipe != NULL) { - usbd_abort_pipe(sc->sc_intr_pipe); - usbd_close_pipe(sc->sc_intr_pipe); - kfree(sc->sc_intr_buf, M_USBDEV); - sc->sc_intr_pipe = NULL; - } - - DPRINTF(("ugensa_detach: sc=%p\n", sc)); - sc->sc_ucom.sc_dying = 1; - rv = ucom_detach(&sc->sc_ucom); - usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_ucom.sc_udev, - sc->sc_ucom.sc_dev); - - return (rv); -} - -#if 0 /* not yet */ -int -ugensa_activate(struct device *self, enum devact act) -{ - struct ugensa_softc *sc = (struct ugensa_softc *)self; - int rv = 0; - - switch (act) { - case DVACT_ACTIVATE: - break; - - case DVACT_DEACTIVATE: - if (sc->sc_subdev != NULL) - rv = config_deactivate(sc->sc_subdev); - sc->sc_dying = 1; - break; - } - return (rv); -} -#endif - -static int -ugensa_open(void *addr, int portno) -{ - struct ugensa_softc *sc = addr; - int err; - - if (sc->sc_ucom.sc_dying) - return (ENXIO); - - if (sc->sc_intr_number != -1 && sc->sc_intr_pipe == NULL) { - sc->sc_intr_buf = kmalloc(sc->sc_isize, M_USBDEV, M_WAITOK); - err = usbd_open_pipe_intr(sc->sc_ucom.sc_iface, - sc->sc_intr_number, USBD_SHORT_XFER_OK, &sc->sc_intr_pipe, - sc, sc->sc_intr_buf, sc->sc_isize, ugensa_intr, - UGENSA_INTR_INTERVAL); - if (err) { - device_printf(sc->sc_ucom.sc_dev, - "cannot open interrupt pipe (addr %d)\n", - sc->sc_intr_number); - return (EIO); - } - } - - return (0); -} - -static void -ugensa_close(void *addr, int portno) -{ - struct ugensa_softc *sc = addr; - int err; - - if (sc->sc_ucom.sc_dying) - return; - - if (sc->sc_intr_pipe != NULL) { - err = usbd_abort_pipe(sc->sc_intr_pipe); - if (err) - device_printf(sc->sc_ucom.sc_dev, - "abort interrupt pipe failed: %s\n", - usbd_errstr(err)); - err = usbd_close_pipe(sc->sc_intr_pipe); - if (err) - device_printf(sc->sc_ucom.sc_dev, - "close interrupt pipe failed: %s\n", - usbd_errstr(err)); - kfree(sc->sc_intr_buf, M_USBDEV); - sc->sc_intr_pipe = NULL; - } - -} - -static void -ugensa_intr(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status) -{ - struct ugensa_softc *sc = priv; - usb_cdc_notification_t *buf; - u_char mstatus; - - buf = (usb_cdc_notification_t *)sc->sc_intr_buf; - if (sc->sc_ucom.sc_dying) - return; - - if (status != USBD_NORMAL_COMPLETION) { - if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) - return; - - device_printf(sc->sc_ucom.sc_dev, - "ugensa_intr: abnormal status: %s\n", usbd_errstr(status)); - usbd_clear_endpoint_stall_async(sc->sc_intr_pipe); - return; - } - - if (buf->bmRequestType != UCDC_NOTIFICATION) { - DPRINTF(("%s: umsm_intr: unknown message type(0x%02x)\n", - sc->sc_dev.dv_xname, buf->bmRequestType)); - return; - } - - if (buf->bNotification == UCDC_N_SERIAL_STATE) { - /* invalid message length, discard it */ - if (UGETW(buf->wLength) != 2) - return; - /* XXX: sc_lsr is always 0 */ - sc->sc_lsr = sc->sc_msr = 0; - mstatus = buf->data[0]; - if (ISSET(mstatus, UCDC_N_SERIAL_RI)) - sc->sc_msr |= UMSR_RI; - if (ISSET(mstatus, UCDC_N_SERIAL_DSR)) - sc->sc_msr |= UMSR_DSR; - if (ISSET(mstatus, UCDC_N_SERIAL_DCD)) - sc->sc_msr |= UMSR_DCD; - } else if (buf->bNotification != UCDC_N_CONNECTION_SPEED_CHANGE) { - DPRINTF(("%s: umsm_intr: unknown notify message (0x%02x)\n", - sc->sc_dev.dv_xname, buf->bNotification)); - return; - } - - ucom_status_change(&sc->sc_ucom); -} - -static void -ugensa_get_status(void *addr, int portno, u_char *lsr, u_char *msr) -{ - struct ugensa_softc *sc = addr; - - if (lsr != NULL) - *lsr = sc->sc_lsr; - if (msr != NULL) - *msr = sc->sc_msr; -} - -static void -ugensa_set(void *addr, int portno, int reg, int onoff) -{ - struct ugensa_softc *sc = addr; - usb_device_request_t req; - int ls; - - switch (reg) { - case UCOM_SET_DTR: - if (sc->sc_dtr == onoff) - return; - sc->sc_dtr = onoff; - break; - case UCOM_SET_RTS: - if (sc->sc_rts == onoff) - return; - sc->sc_rts = onoff; - break; - default: - return; - } - - /* build an usb request */ - ls = (sc->sc_dtr ? UCDC_LINE_DTR : 0) | - (sc->sc_rts ? UCDC_LINE_RTS : 0); - req.bmRequestType = UT_WRITE_CLASS_INTERFACE; - req.bRequest = UCDC_SET_CONTROL_LINE_STATE; - USETW(req.wValue, ls); - USETW(req.wIndex, sc->sc_iface_no); - USETW(req.wLength, 0); - - (void)usbd_do_request(sc->sc_ucom.sc_udev, &req, 0); -} - -static void -ugensa_e220_changemode(usbd_device_handle dev) -{ - usb_device_request_t req; - - req.bmRequestType = UT_WRITE_DEVICE; - req.bRequest = UR_SET_FEATURE; - USETW(req.wValue, UF_DEVICE_REMOTE_WAKEUP); - USETW(req.wIndex, 0x2); - USETW(req.wLength, 0); - - usbd_do_request(dev, &req, 0); -} - diff --git a/sys/dev/usbmisc/uhid/Makefile b/sys/dev/usbmisc/uhid/Makefile deleted file mode 100644 index 8a8b584502..0000000000 --- a/sys/dev/usbmisc/uhid/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -# $FreeBSD: src/sys/modules/uhid/Makefile,v 1.7 1999/11/28 18:53:30 bde Exp $ -# $DragonFly: src/sys/dev/usbmisc/uhid/Makefile,v 1.4 2004/08/13 17:51:07 dillon Exp $ - -.PATH: ${.CURDIR}/../../dev/usb -KMOD = uhid -SRCS = bus_if.h device_if.h opt_usb.h uhid.c - -.include diff --git a/sys/dev/usbmisc/uhid/uhid.c b/sys/dev/usbmisc/uhid/uhid.c deleted file mode 100644 index 8086b8da58..0000000000 --- a/sys/dev/usbmisc/uhid/uhid.c +++ /dev/null @@ -1,747 +0,0 @@ -/* - * $NetBSD: uhid.c,v 1.46 2001/11/13 06:24:55 lukem Exp $ - * $FreeBSD: src/sys/dev/usb/uhid.c,v 1.65 2003/11/09 09:17:22 tanimura Exp $ - */ - -/* Also already merged from NetBSD: - * $NetBSD: uhid.c,v 1.54 2002/09/23 05:51:21 simonb Exp $ - */ - -/* - * Copyright (c) 1998 The NetBSD Foundation, Inc. - * All rights reserved. - * - * This code is derived from software contributed to The NetBSD Foundation - * by Lennart Augustsson (lennart@augustsson.net) at - * Carlstedt Research & Technology. - * - * 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. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the NetBSD - * Foundation, Inc. and its contributors. - * 4. Neither the name of The NetBSD Foundation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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. - */ - -/* - * HID spec: http://www.usb.org/developers/data/usbhid10.pdf - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include -#include - -/* Report descriptor for broken Wacom Graphire */ -#include - -#ifdef USB_DEBUG -#define DPRINTF(x) if (uhiddebug) kprintf x -#define DPRINTFN(n,x) if (uhiddebug>(n)) kprintf x -int uhiddebug = 0; -SYSCTL_NODE(_hw_usb, OID_AUTO, uhid, CTLFLAG_RW, 0, "USB uhid"); -SYSCTL_INT(_hw_usb_uhid, OID_AUTO, debug, CTLFLAG_RW, - &uhiddebug, 0, "uhid debug level"); -#else -#define DPRINTF(x) -#define DPRINTFN(n,x) -#endif - -struct uhid_softc { - device_t sc_dev; /* base device */ - usbd_device_handle sc_udev; - usbd_interface_handle sc_iface; /* interface */ - usbd_pipe_handle sc_intrpipe; /* interrupt pipe */ - int sc_ep_addr; - - int sc_isize; - int sc_osize; - int sc_fsize; - u_int8_t sc_iid; - u_int8_t sc_oid; - u_int8_t sc_fid; - - u_char *sc_ibuf; - u_char *sc_obuf; - - void *sc_repdesc; - int sc_repdesc_size; - - struct clist sc_q; - struct kqinfo sc_rkq; - struct proc *sc_async; /* process that wants SIGIO */ - u_char sc_state; /* driver state */ -#define UHID_OPEN 0x01 /* device is open */ -#define UHID_ASLP 0x02 /* waiting for device data */ -#define UHID_NEEDCLEAR 0x04 /* needs clearing endpoint stall */ -#define UHID_IMMED 0x08 /* return read data immediately */ - - int sc_refcnt; - u_char sc_dying; -}; - -#define UHIDUNIT(dev) (minor(dev)) -#define UHID_CHUNK 128 /* chunk size for read */ -#define UHID_BSIZE 1020 /* buffer size */ - -d_open_t uhidopen; -d_close_t uhidclose; -d_read_t uhidread; -d_write_t uhidwrite; -d_ioctl_t uhidioctl; -d_kqfilter_t uhidkqfilter; - -static void uhidfilt_detach(struct knote *); -static int uhidfilt_read(struct knote *, long); -static int uhidfilt_write(struct knote *, long); - -static struct dev_ops uhid_ops = { - { "uhid", 0, 0 }, - .d_open = uhidopen, - .d_close = uhidclose, - .d_read = uhidread, - .d_write = uhidwrite, - .d_ioctl = uhidioctl, - .d_kqfilter = uhidkqfilter -}; - -static void uhid_intr(usbd_xfer_handle, usbd_private_handle, - usbd_status); - -static int uhid_do_read(struct uhid_softc *, struct uio *uio, int); -static int uhid_do_write(struct uhid_softc *, struct uio *uio, int); -static int uhid_do_ioctl(struct uhid_softc *, u_long, caddr_t, int); - -static device_probe_t uhid_match; -static device_attach_t uhid_attach; -static device_detach_t uhid_detach; - -static devclass_t uhid_devclass; - -static kobj_method_t uhid_methods[] = { - DEVMETHOD(device_probe, uhid_match), - DEVMETHOD(device_attach, uhid_attach), - DEVMETHOD(device_detach, uhid_detach), - DEVMETHOD_END -}; - -static driver_t uhid_driver = { - "uhid", - uhid_methods, - sizeof(struct uhid_softc) -}; - -MODULE_DEPEND(uhid, usb, 1, 1, 1); - -static int -uhid_match(device_t self) -{ - struct usb_attach_arg *uaa = device_get_ivars(self); - usb_interface_descriptor_t *id; - - if (uaa->iface == NULL) - return (UMATCH_NONE); - id = usbd_get_interface_descriptor(uaa->iface); - if (id == NULL || id->bInterfaceClass != UICLASS_HID) - return (UMATCH_NONE); - if (uaa->matchlvl) - return (uaa->matchlvl); - return (UMATCH_IFACECLASS_GENERIC); -} - -static int -uhid_attach(device_t self) -{ - struct uhid_softc *sc = device_get_softc(self); - struct usb_attach_arg *uaa = device_get_ivars(self); - usbd_interface_handle iface = uaa->iface; - usb_endpoint_descriptor_t *ed; - int size; - void *desc; - usbd_status err; - - sc->sc_udev = uaa->device; - sc->sc_iface = iface; - sc->sc_dev = self; - - ed = usbd_interface2endpoint_descriptor(iface, 0); - if (ed == NULL) { - kprintf("%s: could not read endpoint descriptor\n", - device_get_nameunit(sc->sc_dev)); - sc->sc_dying = 1; - return ENXIO; - } - - DPRINTFN(10,("uhid_attach: bLength=%d bDescriptorType=%d " - "bEndpointAddress=%d-%s bmAttributes=%d wMaxPacketSize=%d" - " bInterval=%d\n", - ed->bLength, ed->bDescriptorType, - ed->bEndpointAddress & UE_ADDR, - UE_GET_DIR(ed->bEndpointAddress)==UE_DIR_IN? "in" : "out", - ed->bmAttributes & UE_XFERTYPE, - UGETW(ed->wMaxPacketSize), ed->bInterval)); - - if (UE_GET_DIR(ed->bEndpointAddress) != UE_DIR_IN || - (ed->bmAttributes & UE_XFERTYPE) != UE_INTERRUPT) { - kprintf("%s: unexpected endpoint\n", device_get_nameunit(sc->sc_dev)); - sc->sc_dying = 1; - return ENXIO; - } - - sc->sc_ep_addr = ed->bEndpointAddress; - - /* The report descriptor for the Wacom Graphire is broken. */ - if (uaa->vendor == 0x056a && uaa->product == 0x0010 /* && - uaa->revision == 0x???? */) { /* XXX should use revision */ - size = sizeof uhid_graphire_report_descr; - desc = kmalloc(size, M_USBDEV, M_INTWAIT); - err = USBD_NORMAL_COMPLETION; - memcpy(desc, uhid_graphire_report_descr, size); - } else { - desc = NULL; - err = usbd_read_report_desc(uaa->iface, &desc, &size,M_USBDEV); - } - - if (err) { - kprintf("%s: no report descriptor\n", device_get_nameunit(sc->sc_dev)); - sc->sc_dying = 1; - return ENXIO; - } - - (void)usbd_set_idle(iface, 0, 0); - - sc->sc_isize = hid_report_size(desc, size, hid_input, &sc->sc_iid); - sc->sc_osize = hid_report_size(desc, size, hid_output, &sc->sc_oid); - sc->sc_fsize = hid_report_size(desc, size, hid_feature, &sc->sc_fid); - - sc->sc_repdesc = desc; - sc->sc_repdesc_size = size; - - make_dev(&uhid_ops, device_get_unit(self), - UID_ROOT, GID_OPERATOR, - 0644, "uhid%d", device_get_unit(self)); - - return 0; -} - -static int -uhid_detach(device_t self) -{ - struct uhid_softc *sc = device_get_softc(self); - - DPRINTF(("uhid_detach: sc=%p\n", sc)); - - sc->sc_dying = 1; - if (sc->sc_intrpipe != NULL) - usbd_abort_pipe(sc->sc_intrpipe); - - if (sc->sc_state & UHID_OPEN) { - crit_enter(); - if (--sc->sc_refcnt >= 0) { - /* Wake everyone */ - wakeup(&sc->sc_q); - /* Wait for processes to go away. */ - usb_detach_wait(sc->sc_dev); - } - crit_exit(); - } - - dev_ops_remove_minor(&uhid_ops, device_get_unit(self)); - - if (sc->sc_repdesc) - kfree(sc->sc_repdesc, M_USBDEV); - - return (0); -} - -void -uhid_intr(usbd_xfer_handle xfer, usbd_private_handle addr, usbd_status status) -{ - struct uhid_softc *sc = addr; - -#ifdef USB_DEBUG - if (uhiddebug > 5) { - u_int32_t cc, i; - - usbd_get_xfer_status(xfer, NULL, NULL, &cc, NULL); - DPRINTF(("uhid_intr: status=%d cc=%d\n", status, cc)); - DPRINTF(("uhid_intr: data =")); - for (i = 0; i < cc; i++) - DPRINTF((" %02x", sc->sc_ibuf[i])); - DPRINTF(("\n")); - } -#endif - - if (status == USBD_CANCELLED) - return; - - if (status != USBD_NORMAL_COMPLETION) { - DPRINTF(("uhid_intr: status=%d\n", status)); - if (status == USBD_STALLED) - sc->sc_state |= UHID_NEEDCLEAR; - return; - } - - (void) b_to_q(sc->sc_ibuf, sc->sc_isize, &sc->sc_q); - - if (sc->sc_state & UHID_ASLP) { - sc->sc_state &= ~UHID_ASLP; - DPRINTFN(5, ("uhid_intr: waking %p\n", &sc->sc_q)); - wakeup(&sc->sc_q); - } - KNOTE(&sc->sc_rkq.ki_note, 0); - if (sc->sc_async != NULL) { - DPRINTFN(3, ("uhid_intr: sending SIGIO %p\n", sc->sc_async)); - ksignal(sc->sc_async, SIGIO); - } -} - -int -uhidopen(struct dev_open_args *ap) -{ - cdev_t dev = ap->a_head.a_dev; - struct uhid_softc *sc; - usbd_status err; - - sc = devclass_get_softc(uhid_devclass, UHIDUNIT(dev)); - if (sc == NULL) - return (ENXIO); - - DPRINTF(("uhidopen: sc=%p\n", sc)); - - if (sc->sc_dying) - return (ENXIO); - - if (sc->sc_state & UHID_OPEN) - return (EBUSY); - sc->sc_state |= UHID_OPEN; - - if ((clist_alloc_cblocks(&sc->sc_q, UHID_BSIZE, - UHID_BSIZE), 0) == -1) { - sc->sc_state &= ~UHID_OPEN; - return (ENOMEM); - } - - sc->sc_ibuf = kmalloc(sc->sc_isize, M_USBDEV, M_WAITOK); - sc->sc_obuf = kmalloc(sc->sc_osize, M_USBDEV, M_WAITOK); - - /* Set up interrupt pipe. */ - err = usbd_open_pipe_intr(sc->sc_iface, sc->sc_ep_addr, - USBD_SHORT_XFER_OK, &sc->sc_intrpipe, sc, sc->sc_ibuf, - sc->sc_isize, uhid_intr, USBD_DEFAULT_INTERVAL); - if (err) { - DPRINTF(("uhidopen: usbd_open_pipe_intr failed, " - "error=%d\n",err)); - kfree(sc->sc_ibuf, M_USBDEV); - kfree(sc->sc_obuf, M_USBDEV); - sc->sc_ibuf = sc->sc_obuf = NULL; - - sc->sc_state &= ~UHID_OPEN; - return (EIO); - } - - sc->sc_state &= ~UHID_IMMED; - - sc->sc_async = NULL; - - return (0); -} - -int -uhidclose(struct dev_close_args *ap) -{ - cdev_t dev = ap->a_head.a_dev; - struct uhid_softc *sc; - - sc = devclass_get_softc(uhid_devclass, UHIDUNIT(dev)); - - DPRINTF(("uhidclose: sc=%p\n", sc)); - - /* Disable interrupts. */ - usbd_abort_pipe(sc->sc_intrpipe); - usbd_close_pipe(sc->sc_intrpipe); - sc->sc_intrpipe = 0; - - ndflush(&sc->sc_q, sc->sc_q.c_cc); - clist_free_cblocks(&sc->sc_q); - - kfree(sc->sc_ibuf, M_USBDEV); - kfree(sc->sc_obuf, M_USBDEV); - sc->sc_ibuf = sc->sc_obuf = NULL; - - sc->sc_state &= ~UHID_OPEN; - - sc->sc_async = NULL; - - return (0); -} - -int -uhid_do_read(struct uhid_softc *sc, struct uio *uio, int flag) -{ - int error = 0; - size_t length; - u_char buffer[UHID_CHUNK]; - usbd_status err; - - DPRINTFN(1, ("uhidread\n")); - if (sc->sc_state & UHID_IMMED) { - DPRINTFN(1, ("uhidread immed\n")); - - err = usbd_get_report(sc->sc_iface, UHID_INPUT_REPORT, - sc->sc_iid, buffer, sc->sc_isize); - if (err) - return (EIO); - return (uiomove(buffer, sc->sc_isize, uio)); - } - - crit_enter(); - while (sc->sc_q.c_cc == 0) { - if (flag & IO_NDELAY) { - crit_exit(); - return (EWOULDBLOCK); - } - sc->sc_state |= UHID_ASLP; - DPRINTFN(5, ("uhidread: sleep on %p\n", &sc->sc_q)); - error = tsleep(&sc->sc_q, PCATCH, "uhidrea", 0); - DPRINTFN(5, ("uhidread: woke, error=%d\n", error)); - if (sc->sc_dying) - error = EIO; - if (error) { - sc->sc_state &= ~UHID_ASLP; - break; - } - if (sc->sc_state & UHID_NEEDCLEAR) { - DPRINTFN(-1,("uhidread: clearing stall\n")); - sc->sc_state &= ~UHID_NEEDCLEAR; - usbd_clear_endpoint_stall(sc->sc_intrpipe); - } - } - crit_exit(); - - /* Transfer as many chunks as possible. */ - while (sc->sc_q.c_cc > 0 && uio->uio_resid > 0 && !error) { - length = szmin(sc->sc_q.c_cc, uio->uio_resid); - if (length > sizeof(buffer)) - length = sizeof(buffer); - - /* Remove a small chunk from the input queue. */ - (void) q_to_b(&sc->sc_q, buffer, length); - DPRINTFN(5, ("uhidread: got %lu chars\n", (u_long)length)); - - /* Copy the data to the user process. */ - if ((error = uiomove(buffer, length, uio)) != 0) - break; - } - - return (error); -} - -int -uhidread(struct dev_read_args *ap) -{ - cdev_t dev = ap->a_head.a_dev; - struct uhid_softc *sc; - int error; - - sc = devclass_get_softc(uhid_devclass, UHIDUNIT(dev)); - - sc->sc_refcnt++; - error = uhid_do_read(sc, ap->a_uio, ap->a_ioflag); - if (--sc->sc_refcnt < 0) - usb_detach_wakeup(sc->sc_dev); - return (error); -} - -int -uhid_do_write(struct uhid_softc *sc, struct uio *uio, int flag) -{ - int error; - int size; - usbd_status err; - - DPRINTFN(1, ("uhidwrite\n")); - - if (sc->sc_dying) - return (EIO); - - size = sc->sc_osize; - if (uio->uio_resid != size) - return (EINVAL); - error = uiomove(sc->sc_obuf, size, uio); - if (!error) { - if (sc->sc_oid) - err = usbd_set_report(sc->sc_iface, UHID_OUTPUT_REPORT, - sc->sc_obuf[0], sc->sc_obuf+1, size-1); - else - err = usbd_set_report(sc->sc_iface, UHID_OUTPUT_REPORT, - 0, sc->sc_obuf, size); - if (err) - error = EIO; - } - - return (error); -} - -int -uhidwrite(struct dev_write_args *ap) -{ - cdev_t dev = ap->a_head.a_dev; - struct uhid_softc *sc; - int error; - - sc = devclass_get_softc(uhid_devclass, UHIDUNIT(dev)); - - sc->sc_refcnt++; - error = uhid_do_write(sc, ap->a_uio, ap->a_ioflag); - if (--sc->sc_refcnt < 0) - usb_detach_wakeup(sc->sc_dev); - return (error); -} - -int -uhid_do_ioctl(struct uhid_softc *sc, u_long cmd, caddr_t addr, int flag) -{ - struct usb_ctl_report_desc *rd; - struct usb_ctl_report *re; - int size, id; - usbd_status err; - - DPRINTFN(2, ("uhidioctl: cmd=%lx\n", cmd)); - - if (sc->sc_dying) - return (EIO); - - switch (cmd) { - case FIOASYNC: - if (*(int *)addr) { - if (sc->sc_async != NULL) - return (EBUSY); - sc->sc_async = curproc; - DPRINTF(("uhid_do_ioctl: FIOASYNC %p\n", sc->sc_async)); - } else - sc->sc_async = NULL; - break; - - /* XXX this is not the most general solution. */ - case TIOCSPGRP: - if (sc->sc_async == NULL) - return (EINVAL); - if (*(int *)addr != sc->sc_async->p_pgid) - return (EPERM); - break; - - case USB_GET_REPORT_DESC: - rd = (struct usb_ctl_report_desc *)addr; - size = min(sc->sc_repdesc_size, sizeof rd->ucrd_data); - rd->ucrd_size = size; - memcpy(rd->ucrd_data, sc->sc_repdesc, size); - break; - - case USB_SET_IMMED: - if (*(int *)addr) { - /* XXX should read into ibuf, but does it matter? */ - err = usbd_get_report(sc->sc_iface, UHID_INPUT_REPORT, - sc->sc_iid, sc->sc_ibuf, sc->sc_isize); - if (err) - return (EOPNOTSUPP); - - sc->sc_state |= UHID_IMMED; - } else - sc->sc_state &= ~UHID_IMMED; - break; - - case USB_GET_REPORT: - re = (struct usb_ctl_report *)addr; - switch (re->ucr_report) { - case UHID_INPUT_REPORT: - size = sc->sc_isize; - id = sc->sc_iid; - break; - case UHID_OUTPUT_REPORT: - size = sc->sc_osize; - id = sc->sc_oid; - break; - case UHID_FEATURE_REPORT: - size = sc->sc_fsize; - id = sc->sc_fid; - break; - default: - return (EINVAL); - } - err = usbd_get_report(sc->sc_iface, re->ucr_report, id, re->ucr_data, - size); - if (err) - return (EIO); - break; - - case USB_SET_REPORT: - re = (struct usb_ctl_report *)addr; - switch (re->ucr_report) { - case UHID_INPUT_REPORT: - size = sc->sc_isize; - id = sc->sc_iid; - break; - case UHID_OUTPUT_REPORT: - size = sc->sc_osize; - id = sc->sc_oid; - break; - case UHID_FEATURE_REPORT: - size = sc->sc_fsize; - id = sc->sc_fid; - break; - default: - return (EINVAL); - } - err = usbd_set_report(sc->sc_iface, re->ucr_report, id, re->ucr_data, - size); - if (err) - return (EIO); - break; - - case USB_GET_REPORT_ID: - *(int *)addr = 0; /* XXX: we only support reportid 0? */ - break; - - default: - return (EINVAL); - } - return (0); -} - -int -uhidioctl(struct dev_ioctl_args *ap) -{ - cdev_t dev = ap->a_head.a_dev; - struct uhid_softc *sc; - int error; - - sc = devclass_get_softc(uhid_devclass, UHIDUNIT(dev)); - - sc->sc_refcnt++; - error = uhid_do_ioctl(sc, ap->a_cmd, ap->a_data, ap->a_fflag); - if (--sc->sc_refcnt < 0) - usb_detach_wakeup(sc->sc_dev); - return (error); -} - -static struct filterops uhidfiltops_read = - { FILTEROP_ISFD, NULL, uhidfilt_detach, uhidfilt_read }; -static struct filterops uhidfiltops_write = - { FILTEROP_ISFD, NULL, uhidfilt_detach, uhidfilt_write }; - -int -uhidkqfilter(struct dev_kqfilter_args *ap) -{ - cdev_t dev = ap->a_head.a_dev; - struct knote *kn = ap->a_kn; - struct uhid_softc *sc; - struct klist *klist; - - sc = devclass_get_softc(uhid_devclass, UHIDUNIT(dev)); - - if (sc->sc_dying) { - ap->a_result = 1; - return (0); - } - - ap->a_result = 0; - - switch (kn->kn_filter) { - case EVFILT_READ: - kn->kn_fop = &uhidfiltops_read; - kn->kn_hook = (caddr_t)sc; - break; - case EVFILT_WRITE: - kn->kn_fop = &uhidfiltops_write; - kn->kn_hook = (caddr_t)sc; - break; - default: - ap->a_result = EOPNOTSUPP; - return (0); - } - - klist = &sc->sc_rkq.ki_note; - knote_insert(klist, kn); - - return (0); -} - -static void -uhidfilt_detach(struct knote *kn) -{ - cdev_t dev = (cdev_t)kn->kn_hook; - struct uhid_softc *sc; - struct klist *klist; - - sc = devclass_get_softc(uhid_devclass, UHIDUNIT(dev)); - - klist = &sc->sc_rkq.ki_note; - knote_remove(klist, kn); -} - -static int -uhidfilt_read(struct knote *kn, long hint) -{ - cdev_t dev = (cdev_t)kn->kn_hook; - struct uhid_softc *sc; - int ready = 0; - - sc = devclass_get_softc(uhid_devclass, UHIDUNIT(dev)); - - crit_enter(); - if (sc->sc_q.c_cc > 0) - ready = 1; - crit_exit(); - - return (ready); -} - -static int -uhidfilt_write(struct knote *kn, long hint) -{ - return (1); -} - -DRIVER_MODULE(uhid, uhub, uhid_driver, uhid_devclass, usbd_driver_load, NULL); - diff --git a/sys/dev/usbmisc/ukbd/Makefile b/sys/dev/usbmisc/ukbd/Makefile deleted file mode 100644 index b9851ac1cf..0000000000 --- a/sys/dev/usbmisc/ukbd/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -# $FreeBSD: src/sys/modules/ukbd/Makefile,v 1.10 2000/01/20 13:25:18 yokota Exp $ - -.PATH: ${.CURDIR}/../../dev/usb -KMOD = ukbd -SRCS = bus_if.h device_if.h \ - opt_usb.h opt_kbd.h opt_ukbd.h \ - ukbd.c - -.if !defined(BUILDING_WITH_KERNEL) -opt_kbd.h: - echo '#define KBD_INSTALL_CDEV 1' > ${.TARGET} -.endif - -.include diff --git a/sys/dev/usbmisc/ukbd/ukbd.c b/sys/dev/usbmisc/ukbd/ukbd.c deleted file mode 100644 index 63218156c0..0000000000 --- a/sys/dev/usbmisc/ukbd/ukbd.c +++ /dev/null @@ -1,1540 +0,0 @@ -/* - * $FreeBSD: src/sys/dev/usb/ukbd.c,v 1.45 2003/10/04 21:41:01 joe Exp $ - */ - -/* - * (MPSAFE) - * - * Copyright (c) 1998 The NetBSD Foundation, Inc. - * All rights reserved. - * - * This code is derived from software contributed to The NetBSD Foundation - * by Lennart Augustsson (lennart@augustsson.net) at - * Carlstedt Research & Technology. - * - * 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. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the NetBSD - * Foundation, Inc. and its contributors. - * 4. Neither the name of The NetBSD Foundation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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. - */ - -/* - * HID spec: http://www.usb.org/developers/devclass_docs/HID1_11.pdf - * - * NOTE: All locks are handled by the kbd wrappers. - */ - -#include "opt_kbd.h" -#include "opt_ukbd.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include -#include - -#define UKBD_EMULATE_ATSCANCODE 1 - -#define DRIVER_NAME "ukbd" - -#define delay(d) DELAY(d) - -#ifdef USB_DEBUG -#define DPRINTF(x) if (ukbddebug) kprintf x -#define DPRINTFN(n,x) if (ukbddebug>(n)) kprintf x -int ukbddebug = 0; -SYSCTL_NODE(_hw_usb, OID_AUTO, ukbd, CTLFLAG_RW, 0, "USB ukbd"); -SYSCTL_INT(_hw_usb_ukbd, OID_AUTO, debug, CTLFLAG_RW, - &ukbddebug, 0, "ukbd debug level"); -#else -#define DPRINTF(x) -#define DPRINTFN(n,x) -#endif - -#define NKEYCODE 6 - -struct ukbd_data { - u_int8_t modifiers; -#define MOD_CONTROL_L 0x01 -#define MOD_CONTROL_R 0x10 -#define MOD_SHIFT_L 0x02 -#define MOD_SHIFT_R 0x20 -#define MOD_ALT_L 0x04 -#define MOD_ALT_R 0x40 -#define MOD_WIN_L 0x08 -#define MOD_WIN_R 0x80 - u_int8_t reserved; - u_int8_t keycode[NKEYCODE]; -}; - -#define MAXKEYS (NMOD+2*NKEYCODE) - -typedef struct ukbd_softc { - device_t sc_dev; /* base device */ -} ukbd_softc_t; - -#define UKBD_CHUNK 128 /* chunk size for read */ -#define UKBD_BSIZE 1020 /* buffer size */ - -typedef void usbd_intr_t(usbd_xfer_handle, usbd_private_handle, usbd_status); -typedef void usbd_disco_t(void *); - -static int ukbd_resume(device_t self); -static usbd_intr_t ukbd_intr; -static int ukbd_driver_load(module_t mod, int what, void *arg); - -static keyboard_t default_kbd; - -static device_probe_t ukbd_match; -static device_attach_t ukbd_attach; -static device_detach_t ukbd_detach; - -static devclass_t ukbd_devclass; - -static kobj_method_t ukbd_methods[] = { - DEVMETHOD(device_probe, ukbd_match), - DEVMETHOD(device_attach, ukbd_attach), - DEVMETHOD(device_detach, ukbd_detach), - DEVMETHOD(device_resume, ukbd_resume), - DEVMETHOD_END -}; - -static driver_t ukbd_driver = { - "ukbd", - ukbd_methods, - sizeof(struct ukbd_softc) -}; - -MODULE_DEPEND(ukbd, usb, 1, 1, 1); - -static int -ukbd_match(device_t self) -{ - struct usb_attach_arg *uaa = device_get_ivars(self); - - keyboard_switch_t *sw; - void *arg[2]; - int unit = device_get_unit(self); - - sw = kbd_get_switch(DRIVER_NAME); - if (sw == NULL) - return (UMATCH_NONE); - - arg[0] = (void *)uaa; - arg[1] = (void *)ukbd_intr; - if ((*sw->probe)(unit, (void *)arg, 0)) - return (UMATCH_NONE); - - return (UMATCH_IFACECLASS_IFACESUBCLASS_IFACEPROTO); -} - -static int -ukbd_attach(device_t self) -{ - struct ukbd_softc *sc = device_get_softc(self); - struct usb_attach_arg *uaa = device_get_ivars(self); - - keyboard_switch_t *sw; - keyboard_t *kbd; - void *arg[2]; - int unit = device_get_unit(self); - - sc->sc_dev = self; - - sw = kbd_get_switch(DRIVER_NAME); - if (sw == NULL) - return ENXIO; - - arg[0] = (void *)uaa; - arg[1] = (void *)ukbd_intr; - kbd = NULL; - if ((*sw->probe)(unit, (void *)arg, 0)) - return ENXIO; - if ((*sw->init)(unit, &kbd, (void *)arg, 0)) - return ENXIO; - (*sw->enable)(kbd); - -#ifdef KBD_INSTALL_CDEV - if (kbd_attach(kbd)) - return ENXIO; -#endif - if (bootverbose) - (*sw->diag)(kbd, bootverbose); - return 0; -} - -int -ukbd_detach(device_t self) -{ - keyboard_t *kbd; - int error; - - kbd = kbd_get_keyboard(kbd_find_keyboard(DRIVER_NAME, - device_get_unit(self))); - if (kbd == NULL) { - DPRINTF(("%s: keyboard not attached!?\n", device_get_nameunit(self))); - return ENXIO; - } - kbd_disable(kbd); - -#ifdef KBD_INSTALL_CDEV - error = kbd_detach(kbd); - if (error) - return error; -#endif - error = kbd_term(kbd); - if (error) - return error; - - DPRINTF(("%s: disconnected\n", device_get_nameunit(self))); - - return (0); -} - -static int -ukbd_resume(device_t self) -{ - keyboard_t *kbd; - - kbd = kbd_get_keyboard(kbd_find_keyboard(DRIVER_NAME, - device_get_unit(self))); - if (kbd) - kbd_clear_state(kbd); - - return (0); -} - -void -ukbd_intr(usbd_xfer_handle xfer, usbd_private_handle addr, usbd_status status) -{ - keyboard_t *kbd = (keyboard_t *)addr; - - kbd_intr(kbd, (void *)status); -} - -DRIVER_MODULE(ukbd, uhub, ukbd_driver, ukbd_devclass, ukbd_driver_load, NULL); - - -#define UKBD_DEFAULT 0 - -#define KEY_ERROR 0x01 - -#define KEY_PRESS 0 -#define KEY_RELEASE 0x400 -#define KEY_INDEX(c) ((c) & ~KEY_RELEASE) - -#define SCAN_PRESS 0 -#define SCAN_RELEASE 0x80 -#define SCAN_PREFIX_E0 0x100 -#define SCAN_PREFIX_E1 0x200 -#define SCAN_PREFIX_CTL 0x400 -#define SCAN_PREFIX_SHIFT 0x800 -#define SCAN_PREFIX (SCAN_PREFIX_E0 | SCAN_PREFIX_E1 | SCAN_PREFIX_CTL \ - | SCAN_PREFIX_SHIFT) -#define SCAN_CHAR(c) ((c) & 0x7f) - -#define NMOD 8 -static struct { - int mask, key; -} ukbd_mods[NMOD] = { - { MOD_CONTROL_L, 0xe0 }, - { MOD_CONTROL_R, 0xe4 }, - { MOD_SHIFT_L, 0xe1 }, - { MOD_SHIFT_R, 0xe5 }, - { MOD_ALT_L, 0xe2 }, - { MOD_ALT_R, 0xe6 }, - { MOD_WIN_L, 0xe3 }, - { MOD_WIN_R, 0xe7 }, -}; - -#define NN 0 /* no translation */ -/* - * Translate USB keycodes to AT keyboard scancodes. - */ -/* - * FIXME: Mac USB keyboard generates: - * 0x53: keypad NumLock/Clear - * 0x66: Power - * 0x67: keypad = - * 0x68: F13 - * 0x69: F14 - * 0x6a: F15 - */ -static u_int8_t ukbd_trtab[256] = { - 0, 0, 0, 0, 30, 48, 46, 32, /* 00 - 07 */ - 18, 33, 34, 35, 23, 36, 37, 38, /* 08 - 0F */ - 50, 49, 24, 25, 16, 19, 31, 20, /* 10 - 17 */ - 22, 47, 17, 45, 21, 44, 2, 3, /* 18 - 1F */ - 4, 5, 6, 7, 8, 9, 10, 11, /* 20 - 27 */ - 28, 1, 14, 15, 57, 12, 13, 26, /* 28 - 2F */ - 27, 43, 43, 39, 40, 41, 51, 52, /* 30 - 37 */ - 53, 58, 59, 60, 61, 62, 63, 64, /* 38 - 3F */ - 65, 66, 67, 68, 87, 88, 92, 70, /* 40 - 47 */ - 104, 102, 94, 96, 103, 99, 101, 98, /* 48 - 4F */ - 97, 100, 95, 69, 91, 55, 74, 78, /* 50 - 57 */ - 89, 79, 80, 81, 75, 76, 77, 71, /* 58 - 5F */ - 72, 73, 82, 83, 86, 107, 122, NN, /* 60 - 67 */ - NN, NN, NN, NN, NN, NN, NN, NN, /* 68 - 6F */ - NN, NN, NN, NN, 115, 108, 111, 113, /* 70 - 77 */ - 109, 110, 112, 118, 114, 116, 117, 119, /* 78 - 7F */ - 121, 120, NN, NN, NN, NN, NN, 115, /* 80 - 87 */ - 112, 125, 121, 123, NN, NN, NN, NN, /* 88 - 8F */ - NN, NN, NN, NN, NN, NN, NN, NN, /* 90 - 97 */ - NN, NN, NN, NN, NN, NN, NN, NN, /* 98 - 9F */ - NN, NN, NN, NN, NN, NN, NN, NN, /* A0 - A7 */ - NN, NN, NN, NN, NN, NN, NN, NN, /* A8 - AF */ - NN, NN, NN, NN, NN, NN, NN, NN, /* B0 - B7 */ - NN, NN, NN, NN, NN, NN, NN, NN, /* B8 - BF */ - NN, NN, NN, NN, NN, NN, NN, NN, /* C0 - C7 */ - NN, NN, NN, NN, NN, NN, NN, NN, /* C8 - CF */ - NN, NN, NN, NN, NN, NN, NN, NN, /* D0 - D7 */ - NN, NN, NN, NN, NN, NN, NN, NN, /* D8 - DF */ - 29, 42, 56, 105, 90, 54, 93, 106, /* E0 - E7 */ - NN, NN, NN, NN, NN, NN, NN, NN, /* E8 - EF */ - NN, NN, NN, NN, NN, NN, NN, NN, /* F0 - F7 */ - NN, NN, NN, NN, NN, NN, NN, NN, /* F8 - FF */ -}; - -typedef struct ukbd_state { - usbd_interface_handle ks_iface; /* interface */ - usbd_pipe_handle ks_intrpipe; /* interrupt pipe */ - struct usb_attach_arg *ks_uaa; - int ks_ep_addr; - - struct ukbd_data ks_ndata; - struct ukbd_data ks_odata; - u_long ks_ntime[NKEYCODE]; - u_long ks_otime[NKEYCODE]; - -#define INPUTBUFSIZE (NMOD + 2*NKEYCODE) - u_int ks_input[INPUTBUFSIZE]; /* input buffer */ - int ks_inputs; - int ks_inputhead; - int ks_inputtail; - - int ks_ifstate; -#define INTRENABLED (1 << 0) -#define DISCONNECTED (1 << 1) - - struct callout ks_timeout; - - int ks_mode; /* input mode (K_XLATE,K_RAW,K_CODE) */ - int ks_flags; /* flags */ -#define COMPOSE (1 << 0) - int ks_polling; - int ks_state; /* shift/lock key state */ - int ks_accents; /* accent key index (> 0) */ - u_int ks_composed_char; /* composed char code (> 0) */ -#ifdef UKBD_EMULATE_ATSCANCODE - u_int ks_buffered_char[2]; -#endif -} ukbd_state_t; - -/* keyboard driver declaration */ -static int ukbd_configure(int flags); -static kbd_probe_t ukbd_probe; -static kbd_init_t ukbd_init; -static kbd_term_t ukbd_term; -static kbd_intr_t ukbd_interrupt; -static kbd_test_if_t ukbd_test_if; -static kbd_enable_t ukbd_enable; -static kbd_disable_t ukbd_disable; -static kbd_read_t ukbd_read; -static kbd_check_t ukbd_check; -static kbd_read_char_t ukbd_read_char; -static kbd_check_char_t ukbd_check_char; -static kbd_ioctl_t ukbd_ioctl; -static kbd_lock_t ukbd_lock; -static kbd_clear_state_t ukbd_clear_state; -static kbd_get_state_t ukbd_get_state; -static kbd_set_state_t ukbd_set_state; -static kbd_poll_mode_t ukbd_poll; - -keyboard_switch_t ukbdsw = { - ukbd_probe, - ukbd_init, - ukbd_term, - ukbd_interrupt, - ukbd_test_if, - ukbd_enable, - ukbd_disable, - ukbd_read, - ukbd_check, - ukbd_read_char, - ukbd_check_char, - ukbd_ioctl, - ukbd_lock, - ukbd_clear_state, - ukbd_get_state, - ukbd_set_state, - genkbd_get_fkeystr, - ukbd_poll, - genkbd_diag, -}; - -KEYBOARD_DRIVER(ukbd, ukbdsw, ukbd_configure); - -/* local functions */ -static int ukbd_enable_intr(keyboard_t *kbd, int on, - usbd_intr_t *func); -static timeout_t ukbd_timeout; - -static int ukbd_getc(ukbd_state_t *state, int wait); -static int probe_keyboard(struct usb_attach_arg *uaa, int flags); -static int init_keyboard(ukbd_state_t *state, int *type, - int flags); -static void set_leds(ukbd_state_t *state, int leds); -static int set_typematic(keyboard_t *kbd, int code); -#ifdef UKBD_EMULATE_ATSCANCODE -static int keycode2scancode(int keycode, int shift, int up); -#endif - -/* local variables */ - -/* the initial key map, accent map and fkey strings */ -#if defined(UKBD_DFLT_KEYMAP) && !defined(KLD_MODULE) -#define KBD_DFLT_KEYMAP -#include "ukbdmap.h" -#endif -#include - -/* structures for the default keyboard */ -static ukbd_state_t default_kbd_state; -static keymap_t default_keymap; -static accentmap_t default_accentmap; -static fkeytab_t default_fkeytab[NUM_FKEYS]; - -/* - * The back door to the keyboard driver! - * This function is called by the console driver, via the kbdio module, - * to tickle keyboard drivers when the low-level console is being initialized. - * Almost nothing in the kernel has been initialied yet. Try to probe - * keyboards if possible. - * NOTE: because of the way the low-level conole is initialized, this routine - * may be called more than once!! - */ -static int -ukbd_configure(int flags) -{ - return 0; - -#if 0 /* not yet */ - keyboard_t *kbd; - device_t device; - struct usb_attach_arg *uaa; - void *arg[2]; - - device = devclass_get_device(ukbd_devclass, UKBD_DEFAULT); - if (device == NULL) - return 0; - uaa = (struct usb_attach_arg *)device_get_ivars(device); - if (uaa == NULL) - return 0; - - /* probe the default keyboard */ - arg[0] = (void *)uaa; - arg[1] = (void *)ukbd_intr; - kbd = NULL; - if (ukbd_probe(UKBD_DEFAULT, arg, flags)) - return 0; - if (ukbd_init(UKBD_DEFAULT, &kbd, arg, flags)) - return 0; - - /* return the number of found keyboards */ - return 1; -#endif -} - -/* low-level functions */ - -/* detect a keyboard */ -static int -ukbd_probe(int unit, void *arg, int flags) -{ - void **data; - struct usb_attach_arg *uaa; - - data = (void **)arg; - uaa = (struct usb_attach_arg *)data[0]; - - if (unit == UKBD_DEFAULT) { - if (KBD_IS_PROBED(&default_kbd)) - return 0; - } - if (probe_keyboard(uaa, flags)) - return ENXIO; - return 0; -} - -/* - * Reset and initialize the device. Note that unit 0 (UKBD_DEFAULT) is an - * always-connected device once it has been initially detected. We do not - * deregister it if the usb keyboard is unplugged to avoid losing the - * connection to the console. This feature also handles the USB bus reset - * which detaches and reattaches USB devices during boot. - */ -static int -ukbd_init(int unit, keyboard_t **kbdp, void *arg, int flags) -{ - keyboard_t *kbd; - ukbd_state_t *state; - keymap_t *keymap; - accentmap_t *accmap; - fkeytab_t *fkeymap; - int fkeymap_size; - void **data = (void **)arg; - struct usb_attach_arg *uaa = (struct usb_attach_arg *)data[0]; - - if (unit == UKBD_DEFAULT) { - *kbdp = kbd = &default_kbd; - if (KBD_IS_INITIALIZED(kbd) && KBD_IS_CONFIGURED(kbd)) { - return 0; - } - state = &default_kbd_state; - keymap = &default_keymap; - accmap = &default_accentmap; - fkeymap = default_fkeytab; - fkeymap_size = NELEM(default_fkeytab); - } else if (*kbdp == NULL) { - *kbdp = kbd = kmalloc(sizeof(*kbd), M_DEVBUF, M_INTWAIT | M_ZERO); - state = kmalloc(sizeof(*state), M_DEVBUF, M_INTWAIT); - keymap = kmalloc(sizeof(key_map), M_DEVBUF, M_INTWAIT); - accmap = kmalloc(sizeof(accent_map), M_DEVBUF, M_INTWAIT); - fkeymap = kmalloc(sizeof(fkey_tab), M_DEVBUF, M_INTWAIT); - fkeymap_size = NELEM(fkey_tab); - if ((state == NULL) || (keymap == NULL) || (accmap == NULL) - || (fkeymap == NULL)) { - if (state != NULL) - kfree(state, M_DEVBUF); - if (keymap != NULL) - kfree(keymap, M_DEVBUF); - if (accmap != NULL) - kfree(accmap, M_DEVBUF); - if (fkeymap != NULL) - kfree(fkeymap, M_DEVBUF); - kfree(kbd, M_DEVBUF); - return ENOMEM; - } - } else if (KBD_IS_INITIALIZED(*kbdp) && KBD_IS_CONFIGURED(*kbdp)) { - return 0; - } else { - kbd = *kbdp; - state = (ukbd_state_t *)kbd->kb_data; - keymap = kbd->kb_keymap; - accmap = kbd->kb_accentmap; - fkeymap = kbd->kb_fkeytab; - fkeymap_size = kbd->kb_fkeytab_size; - } - - if (!KBD_IS_PROBED(kbd)) { - kbd_init_struct(kbd, DRIVER_NAME, KB_OTHER, - unit, flags, KB_PRI_USB, - 0, 0); - bzero(state, sizeof(*state)); - bcopy(&key_map, keymap, sizeof(key_map)); - bcopy(&accent_map, accmap, sizeof(accent_map)); - bcopy(fkey_tab, fkeymap, - imin(fkeymap_size*sizeof(fkeymap[0]), sizeof(fkey_tab))); - kbd_set_maps(kbd, keymap, accmap, fkeymap, fkeymap_size); - kbd->kb_data = (void *)state; - - if (probe_keyboard(uaa, flags)) { - return ENXIO; - } else { - KBD_FOUND_DEVICE(kbd); - } - ukbd_clear_state(kbd); - - /* - * If reattatching to an already open keyboard (e.g. console), - * try to restore the translation mode. Otherwise set the - * translation mode to, well, translation mode so we don't - * get garbage. - */ - state->ks_mode = K_XLATE; - state->ks_iface = uaa->iface; - state->ks_uaa = uaa; - state->ks_ifstate = 0; - callout_init_mp(&state->ks_timeout); - /* - * FIXME: set the initial value for lock keys in ks_state - * according to the BIOS data? - */ - KBD_PROBE_DONE(kbd); - } - if (!KBD_IS_INITIALIZED(kbd) && !(flags & KB_CONF_PROBE_ONLY)) { - if (KBD_HAS_DEVICE(kbd) - && init_keyboard((ukbd_state_t *)kbd->kb_data, - &kbd->kb_type, kbd->kb_flags)) { - return ENXIO; - } - ukbd_ioctl(kbd, KDSETLED, (caddr_t)&(state->ks_state)); - } - if (!KBD_IS_CONFIGURED(kbd)) { - if (kbd_register(kbd) < 0) { - kbd->kb_flags = 0; - /* XXX: Missing free()'s */ - return ENXIO; - } - if (ukbd_enable_intr(kbd, TRUE, (usbd_intr_t *)data[1]) == 0) - ukbd_timeout(kbd); - KBD_CONFIG_DONE(kbd); - } - - return 0; -} - -static int -ukbd_enable_intr(keyboard_t *kbd, int on, usbd_intr_t *func) -{ - ukbd_state_t *state = (ukbd_state_t *)kbd->kb_data; - usbd_status err; - - if (on) { - /* Set up interrupt pipe. */ - if (state->ks_ifstate & INTRENABLED) { - return EBUSY; - } - - state->ks_ifstate |= INTRENABLED; - err = usbd_open_pipe_intr(state->ks_iface, state->ks_ep_addr, - USBD_SHORT_XFER_OK | USBD_CALLBACK_LAST, - &state->ks_intrpipe, kbd, - &state->ks_ndata, - sizeof(state->ks_ndata), func, - USBD_DEFAULT_INTERVAL); - if (err) { - return (EIO); - } - } else { - /* Disable interrupts. */ - usbd_abort_pipe(state->ks_intrpipe); - usbd_close_pipe(state->ks_intrpipe); - - state->ks_ifstate &= ~INTRENABLED; - } - - return (0); -} - -/* finish using this keyboard */ -static int -ukbd_term(keyboard_t *kbd) -{ - ukbd_state_t *state; - int error; - - crit_enter(); - state = (ukbd_state_t *)kbd->kb_data; - DPRINTF(("ukbd_term: ks_ifstate=0x%x\n", state->ks_ifstate)); - - callout_stop(&state->ks_timeout); - - if (state->ks_ifstate & INTRENABLED) - ukbd_enable_intr(kbd, FALSE, NULL); - if (state->ks_ifstate & INTRENABLED) { - crit_exit(); - DPRINTF(("ukbd_term: INTRENABLED!\n")); - return ENXIO; - } - - error = kbd_unregister(kbd); - - DPRINTF(("ukbd_term: kbd_unregister() %d\n", error)); - if (error == 0) { - kbd->kb_flags = 0; - if (kbd != &default_kbd) { - kfree(kbd->kb_keymap, M_DEVBUF); - kfree(kbd->kb_accentmap, M_DEVBUF); - kfree(kbd->kb_fkeytab, M_DEVBUF); - kfree(state, M_DEVBUF); - kfree(kbd, M_DEVBUF); - } - } - crit_exit(); - return error; -} - -/* keyboard interrupt routine */ - -static void -ukbd_timeout(void *arg) -{ - keyboard_t *kbd; - ukbd_state_t *state; - - kbd = (keyboard_t *)arg; - state = (ukbd_state_t *)kbd->kb_data; - crit_enter(); - kbd_intr(kbd, (void *)USBD_NORMAL_COMPLETION); - callout_reset(&state->ks_timeout, hz / 40, ukbd_timeout, arg); - crit_exit(); -} - -static int -ukbd_interrupt(keyboard_t *kbd, void *arg) -{ - usbd_status status = (usbd_status)arg; - ukbd_state_t *state; - struct ukbd_data *ud; - struct timeval tv; - u_long now; - int mod, omod; - int key, c; - int i, j; - - DPRINTFN(5, ("ukbd_intr: status=%d\n", status)); - if (status == USBD_CANCELLED) - return 0; - - state = (ukbd_state_t *)kbd->kb_data; - ud = &state->ks_ndata; - - if (status != USBD_NORMAL_COMPLETION) { - DPRINTF(("ukbd_intr: status=%d\n", status)); - if (status == USBD_STALLED) - usbd_clear_endpoint_stall_async(state->ks_intrpipe); - return 0; - } - - if (ud->keycode[0] == KEY_ERROR) { - return 0; /* ignore */ - } - - getmicrouptime(&tv); - now = (u_long)tv.tv_sec*1000 + (u_long)tv.tv_usec/1000; - -#define ADDKEY1(c) \ - if (state->ks_inputs < INPUTBUFSIZE) { \ - state->ks_input[state->ks_inputtail] = (c); \ - ++state->ks_inputs; \ - state->ks_inputtail = (state->ks_inputtail + 1)%INPUTBUFSIZE; \ - } - - mod = ud->modifiers; - omod = state->ks_odata.modifiers; - if (mod != omod) { - for (i = 0; i < NMOD; i++) - if (( mod & ukbd_mods[i].mask) != - (omod & ukbd_mods[i].mask)) - ADDKEY1(ukbd_mods[i].key | - (mod & ukbd_mods[i].mask - ? KEY_PRESS : KEY_RELEASE)); - } - - /* Check for released keys. */ - for (i = 0; i < NKEYCODE; i++) { - key = state->ks_odata.keycode[i]; - if (key == 0) - continue; - for (j = 0; j < NKEYCODE; j++) { - if (ud->keycode[j] == 0) - continue; - if (key == ud->keycode[j]) - goto rfound; - } - ADDKEY1(key | KEY_RELEASE); - rfound: - ; - } - - /* Check for pressed keys. */ - for (i = 0; i < NKEYCODE; i++) { - key = ud->keycode[i]; - if (key == 0) - continue; - state->ks_ntime[i] = now + kbd->kb_delay1; - for (j = 0; j < NKEYCODE; j++) { - if (state->ks_odata.keycode[j] == 0) - continue; - if (key == state->ks_odata.keycode[j]) { - state->ks_ntime[i] = state->ks_otime[j]; - if (state->ks_otime[j] > now) - goto pfound; - state->ks_ntime[i] = now + kbd->kb_delay2; - break; - } - } - ADDKEY1(key | KEY_PRESS); - /* - * If any other key is presently down, force its repeat to be - * well in the future (100s). This makes the last key to be - * pressed do the autorepeat. - */ - for (j = 0; j < NKEYCODE; j++) { - if (j != i) - state->ks_ntime[j] = now + 100 * 1000; - } - pfound: - ; - } - - state->ks_odata = *ud; - bcopy(state->ks_ntime, state->ks_otime, sizeof(state->ks_ntime)); - if (state->ks_inputs <= 0) { - return 0; - } - -#ifdef USB_DEBUG - for (i = state->ks_inputhead, j = 0; j < state->ks_inputs; ++j, - i = (i + 1)%INPUTBUFSIZE) { - c = state->ks_input[i]; - DPRINTF(("0x%x (%d) %s\n", c, c, - (c & KEY_RELEASE) ? "released":"pressed")); - } - if (ud->modifiers) - DPRINTF(("mod:0x%04x ", ud->modifiers)); - for (i = 0; i < NKEYCODE; i++) { - if (ud->keycode[i]) - DPRINTF(("%d ", ud->keycode[i])); - } - DPRINTF(("\n")); -#endif /* USB_DEBUG */ - - if (state->ks_polling) { - return 0; - } - - if (KBD_IS_ACTIVE(kbd) && KBD_IS_BUSY(kbd)) { - /* let the callback function to process the input */ - (*kbd->kb_callback.kc_func)(kbd, KBDIO_KEYINPUT, - kbd->kb_callback.kc_arg); - } else { - /* read and discard the input; no one is waiting for it */ - do { - c = ukbd_read_char(kbd, FALSE); - } while (c != NOKEY); - } - - return 0; -} - -static int -ukbd_getc(ukbd_state_t *state, int wait) -{ - int c; - - if (state->ks_polling) { - DPRINTFN(1,("ukbd_getc: polling\n")); - crit_enter(); - while (state->ks_inputs <= 0) { - usbd_dopoll(state->ks_iface); - if (wait == 0) - break; - } - crit_exit(); - } - crit_enter(); - if (state->ks_inputs <= 0) { - c = -1; - } else { - c = state->ks_input[state->ks_inputhead]; - --state->ks_inputs; - state->ks_inputhead = (state->ks_inputhead + 1)%INPUTBUFSIZE; - } - crit_exit(); - - return c; -} - -/* test the interface to the device */ -static int -ukbd_test_if(keyboard_t *kbd) -{ - return 0; -} - -/* - * Enable the access to the device; until this function is called, - * the client cannot read from the keyboard. - */ -static int -ukbd_enable(keyboard_t *kbd) -{ - crit_enter(); - KBD_ACTIVATE(kbd); - crit_exit(); - return 0; -} - -/* disallow the access to the device */ -static int -ukbd_disable(keyboard_t *kbd) -{ - crit_enter(); - KBD_DEACTIVATE(kbd); - crit_exit(); - return 0; -} - -/* read one byte from the keyboard if it's allowed */ -static int -ukbd_read(keyboard_t *kbd, int wait) -{ - ukbd_state_t *state; - int usbcode; -#ifdef UKBD_EMULATE_ATSCANCODE - int keycode; - int scancode; -#endif - - state = (ukbd_state_t *)kbd->kb_data; -#ifdef UKBD_EMULATE_ATSCANCODE - if (state->ks_buffered_char[0]) { - scancode = state->ks_buffered_char[0]; - if (scancode & SCAN_PREFIX) { - state->ks_buffered_char[0] = scancode & ~SCAN_PREFIX; - return ((scancode & SCAN_PREFIX_E0) ? 0xe0 : 0xe1); - } else { - state->ks_buffered_char[0] = state->ks_buffered_char[1]; - state->ks_buffered_char[1] = 0; - return scancode; - } - } -#endif /* UKBD_EMULATE_ATSCANCODE */ - - usbcode = ukbd_getc(state, wait); - if (!KBD_IS_ACTIVE(kbd) || (usbcode == -1)) { - return -1; - } - ++kbd->kb_count; -#ifdef UKBD_EMULATE_ATSCANCODE - keycode = ukbd_trtab[KEY_INDEX(usbcode)]; - if (keycode == NN) { - return -1; - } - - scancode = keycode2scancode(keycode, state->ks_ndata.modifiers, - usbcode & KEY_RELEASE); - if (scancode & SCAN_PREFIX) { - if (scancode & SCAN_PREFIX_CTL) { - state->ks_buffered_char[0] = - 0x1d | (scancode & SCAN_RELEASE); /* Ctrl */ - state->ks_buffered_char[1] = scancode & ~SCAN_PREFIX; - } else if (scancode & SCAN_PREFIX_SHIFT) { - state->ks_buffered_char[0] = - 0x2a | (scancode & SCAN_RELEASE); /* Shift */ - state->ks_buffered_char[1] = - scancode & ~SCAN_PREFIX_SHIFT; - } else { - state->ks_buffered_char[0] = scancode & ~SCAN_PREFIX; - state->ks_buffered_char[1] = 0; - } - return ((scancode & SCAN_PREFIX_E0) ? 0xe0 : 0xe1); - } - return scancode; -#else /* !UKBD_EMULATE_ATSCANCODE */ - return usbcode; -#endif /* UKBD_EMULATE_ATSCANCODE */ -} - -/* check if data is waiting */ -static int -ukbd_check(keyboard_t *kbd) -{ - ukbd_state_t *state; - - if (!KBD_IS_ACTIVE(kbd)) { - return FALSE; - } - state = (ukbd_state_t *)kbd->kb_data; - if (state->ks_polling) { - crit_enter(); - usbd_dopoll(state->ks_iface); - crit_exit(); - } -#ifdef UKBD_EMULATE_ATSCANCODE - if (((ukbd_state_t *)kbd->kb_data)->ks_buffered_char[0]) { - return TRUE; - } -#endif - if (((ukbd_state_t *)kbd->kb_data)->ks_inputs > 0) { - return TRUE; - } - - return FALSE; -} - -/* read char from the keyboard */ -static u_int -ukbd_read_char(keyboard_t *kbd, int wait) -{ - ukbd_state_t *state; - u_int action; - int usbcode; - int keycode; -#ifdef UKBD_EMULATE_ATSCANCODE - int scancode; -#endif - - state = (ukbd_state_t *)kbd->kb_data; -next_code: - /* do we have a composed char to return? */ - if (!(state->ks_flags & COMPOSE) && (state->ks_composed_char > 0)) { - action = state->ks_composed_char; - state->ks_composed_char = 0; - if (action > UCHAR_MAX) { - return ERRKEY; - } - return action; - } - -#ifdef UKBD_EMULATE_ATSCANCODE - /* do we have a pending raw scan code? */ - if (state->ks_mode == K_RAW) { - if (state->ks_buffered_char[0]) { - scancode = state->ks_buffered_char[0]; - if (scancode & SCAN_PREFIX) { - state->ks_buffered_char[0] = - scancode & ~SCAN_PREFIX; - return ((scancode & SCAN_PREFIX_E0) ? 0xe0 : 0xe1); - } else { - state->ks_buffered_char[0] = - state->ks_buffered_char[1]; - state->ks_buffered_char[1] = 0; - return scancode; - } - } - } -#endif /* UKBD_EMULATE_ATSCANCODE */ - - /* see if there is something in the keyboard port */ - /* XXX */ - usbcode = ukbd_getc(state, wait); - if (usbcode == -1) { - return NOKEY; - } - ++kbd->kb_count; - -#ifdef UKBD_EMULATE_ATSCANCODE - /* USB key index -> key code -> AT scan code */ - keycode = ukbd_trtab[KEY_INDEX(usbcode)]; - if (keycode == NN) { - return NOKEY; - } - - /* return an AT scan code for the K_RAW mode */ - if (state->ks_mode == K_RAW) { - scancode = keycode2scancode(keycode, state->ks_ndata.modifiers, - usbcode & KEY_RELEASE); - if (scancode & SCAN_PREFIX) { - if (scancode & SCAN_PREFIX_CTL) { - state->ks_buffered_char[0] = - 0x1d | (scancode & SCAN_RELEASE); - state->ks_buffered_char[1] = - scancode & ~SCAN_PREFIX; - } else if (scancode & SCAN_PREFIX_SHIFT) { - state->ks_buffered_char[0] = - 0x2a | (scancode & SCAN_RELEASE); - state->ks_buffered_char[1] = - scancode & ~SCAN_PREFIX_SHIFT; - } else { - state->ks_buffered_char[0] = - scancode & ~SCAN_PREFIX; - state->ks_buffered_char[1] = 0; - } - return ((scancode & SCAN_PREFIX_E0) ? 0xe0 : 0xe1); - } - return scancode; - } -#else /* !UKBD_EMULATE_ATSCANCODE */ - /* return the byte as is for the K_RAW mode */ - if (state->ks_mode == K_RAW) { - return usbcode; - } - - /* USB key index -> key code */ - keycode = ukbd_trtab[KEY_INDEX(usbcode)]; - if (keycode == NN) { - return NOKEY; - } -#endif /* UKBD_EMULATE_ATSCANCODE */ - - switch (keycode) { - case 0x38: /* left alt (compose key) */ - if (usbcode & KEY_RELEASE) { - if (state->ks_flags & COMPOSE) { - state->ks_flags &= ~COMPOSE; - if (state->ks_composed_char > UCHAR_MAX) - state->ks_composed_char = 0; - } - } else { - if (!(state->ks_flags & COMPOSE)) { - state->ks_flags |= COMPOSE; - state->ks_composed_char = 0; - } - } - break; - /* XXX: I don't like these... */ - case 0x5c: /* print screen */ - if (state->ks_flags & ALTS) - keycode = 0x54; /* sysrq */ - break; - case 0x68: /* pause/break */ - if (state->ks_flags & CTLS) - keycode = 0x6c; /* break */ - break; - } - - /* return the key code in the K_CODE mode */ - if (usbcode & KEY_RELEASE) - keycode |= SCAN_RELEASE; - if (state->ks_mode == K_CODE) { - return keycode; - } - - /* compose a character code */ - if (state->ks_flags & COMPOSE) { - switch (keycode) { - /* key pressed, process it */ - case 0x47: case 0x48: case 0x49: /* keypad 7,8,9 */ - state->ks_composed_char *= 10; - state->ks_composed_char += keycode - 0x40; - if (state->ks_composed_char > UCHAR_MAX) { - return ERRKEY; - } - goto next_code; - case 0x4B: case 0x4C: case 0x4D: /* keypad 4,5,6 */ - state->ks_composed_char *= 10; - state->ks_composed_char += keycode - 0x47; - if (state->ks_composed_char > UCHAR_MAX) { - return ERRKEY; - } - goto next_code; - case 0x4F: case 0x50: case 0x51: /* keypad 1,2,3 */ - state->ks_composed_char *= 10; - state->ks_composed_char += keycode - 0x4E; - if (state->ks_composed_char > UCHAR_MAX) { - return ERRKEY; - } - goto next_code; - case 0x52: /* keypad 0 */ - state->ks_composed_char *= 10; - if (state->ks_composed_char > UCHAR_MAX) { - return ERRKEY; - } - goto next_code; - - /* key released, no interest here */ - case SCAN_RELEASE | 0x47: - case SCAN_RELEASE | 0x48: - case SCAN_RELEASE | 0x49: /* keypad 7,8,9 */ - case SCAN_RELEASE | 0x4B: - case SCAN_RELEASE | 0x4C: - case SCAN_RELEASE | 0x4D: /* keypad 4,5,6 */ - case SCAN_RELEASE | 0x4F: - case SCAN_RELEASE | 0x50: - case SCAN_RELEASE | 0x51: /* keypad 1,2,3 */ - case SCAN_RELEASE | 0x52: /* keypad 0 */ - goto next_code; - - case 0x38: /* left alt key */ - break; - - default: - if (state->ks_composed_char > 0) { - state->ks_flags &= ~COMPOSE; - state->ks_composed_char = 0; - return ERRKEY; - } - break; - } - } - - /* keycode to key action */ - action = genkbd_keyaction(kbd, SCAN_CHAR(keycode), - keycode & SCAN_RELEASE, &state->ks_state, - &state->ks_accents); - if (action == NOKEY) { - goto next_code; - } else { - return action; - } - /* NOTREACHED */ -} - -/* check if char is waiting */ -static int -ukbd_check_char(keyboard_t *kbd) -{ - ukbd_state_t *state; - int ret; - - if (!KBD_IS_ACTIVE(kbd)) { - return FALSE; - } - state = (ukbd_state_t *)kbd->kb_data; - if (!(state->ks_flags & COMPOSE) && (state->ks_composed_char > 0)) { - return TRUE; - } - ret = (ukbd_check(kbd)); - - return ret; -} - -/* some useful control functions */ -static int -ukbd_ioctl(keyboard_t *kbd, u_long cmd, caddr_t arg) -{ - /* translate LED_XXX bits into the device specific bits */ - static u_char ledmap[8] = { - 0, 2, 1, 3, 4, 6, 5, 7, - }; - ukbd_state_t *state = kbd->kb_data; - int i; - - crit_enter(); - switch (cmd) { - case KDGKBMODE: /* get keyboard mode */ - *(int *)arg = state->ks_mode; - break; - case KDSKBMODE: /* set keyboard mode */ - switch (*(int *)arg) { - case K_XLATE: - if (state->ks_mode != K_XLATE) { - /* make lock key state and LED state match */ - state->ks_state &= ~LOCK_MASK; - state->ks_state |= KBD_LED_VAL(kbd); - } - /* FALLTHROUGH */ - case K_RAW: - case K_CODE: - if (state->ks_mode != *(int *)arg) { - ukbd_clear_state(kbd); - state->ks_mode = *(int *)arg; - kbd->kb_savemode = state->ks_mode; - } - break; - default: - crit_exit(); - return EINVAL; - } - break; - - case KDGETLED: /* get keyboard LED */ - *(int *)arg = KBD_LED_VAL(kbd); - break; - case KDSETLED: /* set keyboard LED */ - /* NOTE: lock key state in ks_state won't be changed */ - if (*(int *)arg & ~LOCK_MASK) { - crit_exit(); - return EINVAL; - } - i = *(int *)arg; - /* replace CAPS LED with ALTGR LED for ALTGR keyboards */ - if (state->ks_mode == K_XLATE && - kbd->kb_keymap->n_keys > ALTGR_OFFSET) { - if (i & ALKED) - i |= CLKED; - else - i &= ~CLKED; - } - if (KBD_HAS_DEVICE(kbd)) { - set_leds(state, ledmap[i & LED_MASK]); - /* XXX: error check? */ - } - KBD_LED_VAL(kbd) = *(int *)arg; - break; - - case KDGKBSTATE: /* get lock key state */ - *(int *)arg = state->ks_state & LOCK_MASK; - break; - case KDSKBSTATE: /* set lock key state */ - if (*(int *)arg & ~LOCK_MASK) { - crit_exit(); - return EINVAL; - } - state->ks_state &= ~LOCK_MASK; - state->ks_state |= *(int *)arg; - crit_exit(); - /* set LEDs and quit */ - return ukbd_ioctl(kbd, KDSETLED, arg); - - case KDSETREPEAT: /* set keyboard repeat rate (new interface) */ - crit_exit(); - if (!KBD_HAS_DEVICE(kbd)) { - return 0; - } - if (((int *)arg)[1] < 0) { - return EINVAL; - } - if (((int *)arg)[0] < 0) { - return EINVAL; - } - else if (((int *)arg)[0] == 0) /* fastest possible value */ - kbd->kb_delay1 = 200; - else - kbd->kb_delay1 = ((int *)arg)[0]; - kbd->kb_delay2 = ((int *)arg)[1]; - return 0; - - case KDSETRAD: /* set keyboard repeat rate (old interface) */ - crit_exit(); - return set_typematic(kbd, *(int *)arg); - - case PIO_KEYMAP: /* set keyboard translation table */ - case PIO_KEYMAPENT: /* set keyboard translation table entry */ - case PIO_DEADKEYMAP: /* set accent key translation table */ - state->ks_accents = 0; - /* FALLTHROUGH */ - default: - crit_exit(); - return genkbd_commonioctl(kbd, cmd, arg); - -#ifdef USB_DEBUG - case USB_SETDEBUG: - ukbddebug = *(int *)arg; - break; -#endif - } - - crit_exit(); - return 0; -} - -/* lock the access to the keyboard */ -static int -ukbd_lock(keyboard_t *kbd, int lock) -{ - /* XXX ? */ - return TRUE; -} - -/* clear the internal state of the keyboard */ -static void -ukbd_clear_state(keyboard_t *kbd) -{ - ukbd_state_t *state; - - state = (ukbd_state_t *)kbd->kb_data; - state->ks_flags = 0; - state->ks_polling = 0; - state->ks_state &= LOCK_MASK; /* preserve locking key state */ - state->ks_accents = 0; - state->ks_composed_char = 0; -#ifdef UKBD_EMULATE_ATSCANCODE - state->ks_buffered_char[0] = 0; - state->ks_buffered_char[1] = 0; -#endif - bzero(&state->ks_ndata, sizeof(state->ks_ndata)); - bzero(&state->ks_odata, sizeof(state->ks_odata)); - bzero(&state->ks_ntime, sizeof(state->ks_ntime)); - bzero(&state->ks_otime, sizeof(state->ks_otime)); -} - -/* save the internal state */ -static int -ukbd_get_state(keyboard_t *kbd, void *buf, size_t len) -{ - if (len == 0) - return sizeof(ukbd_state_t); - if (len < sizeof(ukbd_state_t)) - return -1; - bcopy(kbd->kb_data, buf, sizeof(ukbd_state_t)); - return 0; -} - -/* set the internal state */ -static int -ukbd_set_state(keyboard_t *kbd, void *buf, size_t len) -{ - if (len < sizeof(ukbd_state_t)) - return ENOMEM; - bcopy(buf, kbd->kb_data, sizeof(ukbd_state_t)); - return 0; -} - -static int -ukbd_poll(keyboard_t *kbd, int on) -{ - ukbd_state_t *state; - usbd_device_handle dev; - - state = (ukbd_state_t *)kbd->kb_data; - usbd_interface2device_handle(state->ks_iface, &dev); - - crit_enter(); - if (on) { - ++state->ks_polling; - if (state->ks_polling == 1) - usbd_set_polling(dev, on); - } else { - --state->ks_polling; - if (state->ks_polling == 0) - usbd_set_polling(dev, on); - } - crit_exit(); - return 0; -} - -/* local functions */ - -static int -probe_keyboard(struct usb_attach_arg *uaa, int flags) -{ - usb_interface_descriptor_t *id; - - if (!uaa->iface) /* we attach to ifaces only */ - return EINVAL; - - /* Check that this is a keyboard that speaks the boot protocol. */ - id = usbd_get_interface_descriptor(uaa->iface); - if (id - && id->bInterfaceClass == UICLASS_HID - && id->bInterfaceSubClass == UISUBCLASS_BOOT - && id->bInterfaceProtocol == UIPROTO_BOOT_KEYBOARD) - return 0; /* found it */ - - return EINVAL; -} - -static int -init_keyboard(ukbd_state_t *state, int *type, int flags) -{ - usb_endpoint_descriptor_t *ed; - usbd_status err; - - *type = KB_OTHER; - - state->ks_ifstate |= DISCONNECTED; - - ed = usbd_interface2endpoint_descriptor(state->ks_iface, 0); - if (!ed) { - kprintf("ukbd: could not read endpoint descriptor\n"); - return EIO; - } - - DPRINTFN(10,("ukbd:init_keyboard: \ -bLength=%d bDescriptorType=%d bEndpointAddress=%d-%s bmAttributes=%d wMaxPacketSize=%d bInterval=%d\n", - ed->bLength, ed->bDescriptorType, - UE_GET_ADDR(ed->bEndpointAddress), - UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN ? "in":"out", - UE_GET_XFERTYPE(ed->bmAttributes), - UGETW(ed->wMaxPacketSize), ed->bInterval)); - - if (UE_GET_DIR(ed->bEndpointAddress) != UE_DIR_IN || - UE_GET_XFERTYPE(ed->bmAttributes) != UE_INTERRUPT) { - kprintf("ukbd: unexpected endpoint\n"); - return EINVAL; - } - - if ((usbd_get_quirks(state->ks_uaa->device)->uq_flags & UQ_NO_SET_PROTO) == 0) { - err = usbd_set_protocol(state->ks_iface, 0); - DPRINTFN(5, ("ukbd:init_keyboard: protocol set\n")); - if (err) { - kprintf("ukbd: set protocol failed\n"); - return EIO; - } - } - /* Ignore if SETIDLE fails since it is not crucial. */ - usbd_set_idle(state->ks_iface, 0, 0); - - state->ks_ep_addr = ed->bEndpointAddress; - state->ks_ifstate &= ~DISCONNECTED; - - return 0; -} - -static void -set_leds(ukbd_state_t *state, int leds) -{ - u_int8_t res = leds; - - DPRINTF(("ukbd:set_leds: state=%p leds=%d\n", state, leds)); - - usbd_set_report_async(state->ks_iface, UHID_OUTPUT_REPORT, 0, &res, 1); -} - -static int -set_typematic(keyboard_t *kbd, int code) -{ - static int delays[] = { 250, 500, 750, 1000 }; - static int rates[] = { 34, 38, 42, 46, 50, 55, 59, 63, - 68, 76, 84, 92, 100, 110, 118, 126, - 136, 152, 168, 184, 200, 220, 236, 252, - 272, 304, 336, 368, 400, 440, 472, 504 }; - - if (code & ~0x7f) - return EINVAL; - kbd->kb_delay1 = delays[(code >> 5) & 3]; - kbd->kb_delay2 = rates[code & 0x1f]; - return 0; -} - -#ifdef UKBD_EMULATE_ATSCANCODE -static int -keycode2scancode(int keycode, int shift, int up) -{ - static int scan[] = { - 0x1c, 0x1d, 0x35, - 0x37 | SCAN_PREFIX_SHIFT, /* PrintScreen */ - 0x38, 0x47, 0x48, 0x49, 0x4b, 0x4d, 0x4f, - 0x50, 0x51, 0x52, 0x53, - 0x46, /* XXX Pause/Break */ - 0x5b, 0x5c, 0x5d, - }; - int scancode; - - scancode = keycode; - if ((keycode >= 89) && (keycode < 89 + NELEM(scan))) - scancode = scan[keycode - 89] | SCAN_PREFIX_E0; - /* Pause/Break */ - if ((keycode == 104) && !(shift & (MOD_CONTROL_L | MOD_CONTROL_R))) - scancode = 0x45 | SCAN_PREFIX_E1 | SCAN_PREFIX_CTL; - if (shift & (MOD_SHIFT_L | MOD_SHIFT_R)) - scancode &= ~SCAN_PREFIX_SHIFT; - return (scancode | (up ? SCAN_RELEASE : SCAN_PRESS)); -} -#endif /* UKBD_EMULATE_ATSCANCODE */ - -static int -ukbd_driver_load(module_t mod, int what, void *arg) -{ - switch (what) { - case MOD_LOAD: - kbd_add_driver(&ukbd_kbd_driver); - break; - case MOD_UNLOAD: - kbd_delete_driver(&ukbd_kbd_driver); - break; - } - return usbd_driver_load(mod, what, 0); -} diff --git a/sys/dev/usbmisc/ulpt/Makefile b/sys/dev/usbmisc/ulpt/Makefile deleted file mode 100644 index 31545dab90..0000000000 --- a/sys/dev/usbmisc/ulpt/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -# $FreeBSD: src/sys/modules/ulpt/Makefile,v 1.7 1999/11/28 18:53:32 bde Exp $ -# $DragonFly: src/sys/dev/usbmisc/ulpt/Makefile,v 1.4 2004/08/13 17:51:07 dillon Exp $ - -.PATH: ${.CURDIR}/../../dev/usb -KMOD = ulpt -SRCS = bus_if.h device_if.h opt_usb.h ulpt.c - -.include diff --git a/sys/dev/usbmisc/ulpt/ulpt.c b/sys/dev/usbmisc/ulpt/ulpt.c deleted file mode 100644 index 92d4c6710f..0000000000 --- a/sys/dev/usbmisc/ulpt/ulpt.c +++ /dev/null @@ -1,758 +0,0 @@ -/* - * $NetBSD: ulpt.c,v 1.55 2002/10/23 09:14:01 jdolecek Exp $ - * $FreeBSD: src/sys/dev/usb/ulpt.c,v 1.59 2003/09/28 20:48:13 phk Exp $ - */ - -/* - * Copyright (c) 1998 The NetBSD Foundation, Inc. - * All rights reserved. - * - * This code is derived from software contributed to The NetBSD Foundation - * by Lennart Augustsson (lennart@augustsson.net) at - * Carlstedt Research & Technology. - * - * 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. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the NetBSD - * Foundation, Inc. and its contributors. - * 4. Neither the name of The NetBSD Foundation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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. - */ - -/* - * Printer Class spec: http://www.usb.org/developers/data/devclass/usbprint109.PDF - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#define TIMEOUT hz*16 /* wait up to 16 seconds for a ready */ -#define STEP hz/4 - -#define ULPT_BSIZE 16384 -#define ULPT_JUNK_SIZE 512 - -#ifdef USB_DEBUG -#define DPRINTF(x) if (ulptdebug) kprintf x -#define DPRINTFN(n,x) if (ulptdebug>=(n)) kprintf x -int ulptdebug = 0; -SYSCTL_NODE(_hw_usb, OID_AUTO, ulpt, CTLFLAG_RW, 0, "USB ulpt"); -SYSCTL_INT(_hw_usb_ulpt, OID_AUTO, debug, CTLFLAG_RW, - &ulptdebug, 0, "ulpt debug level"); -#else -#define DPRINTF(x) -#define DPRINTFN(n,x) -#endif - -#define UR_GET_DEVICE_ID 0 -#define UR_GET_PORT_STATUS 1 -#define UR_SOFT_RESET 2 - -#define LPS_NERR 0x08 /* printer no error */ -#define LPS_SELECT 0x10 /* printer selected */ -#define LPS_NOPAPER 0x20 /* printer out of paper */ -#define LPS_INVERT (LPS_SELECT|LPS_NERR) -#define LPS_MASK (LPS_SELECT|LPS_NERR|LPS_NOPAPER) - -struct ulpt_softc { - device_t sc_dev; - usbd_device_handle sc_udev; /* device */ - usbd_interface_handle sc_iface; /* interface */ - int sc_ifaceno; - cdev_t sc_cdev1; - cdev_t sc_cdev2; - - int sc_out; - usbd_pipe_handle sc_out_pipe; /* bulk out pipe */ - - int sc_in; - usbd_pipe_handle sc_in_pipe; /* bulk in pipe */ - usbd_xfer_handle sc_in_xfer1; - usbd_xfer_handle sc_in_xfer2; - u_char *sc_junk1; /* somewhere to dump input */ - u_char *sc_junk2; /* somewhere to dump input */ - - u_char sc_state; -#define ULPT_OPEN 0x01 /* device is open */ -#define ULPT_OBUSY 0x02 /* printer is busy doing output */ -#define ULPT_INIT 0x04 /* waiting to initialize for open */ - u_char sc_flags; -#define ULPT_NOPRIME 0x40 /* don't prime on open */ - u_char sc_laststatus; - - int sc_refcnt; - u_char sc_dying; - struct kqinfo sc_wkq; - int vendor; - int product; -}; - -static d_open_t ulptopen; -static d_close_t ulptclose; -static d_write_t ulptwrite; -static d_ioctl_t ulptioctl; -static d_kqfilter_t ulptkqfilter; - -static void ulpt_filt_detach(struct knote *); -static int ulpt_filt(struct knote *, long); - -static struct dev_ops ulpt_ops = { - { "ulpt", 0, 0 }, - .d_open = ulptopen, - .d_close = ulptclose, - .d_write = ulptwrite, - .d_ioctl = ulptioctl, - .d_kqfilter = ulptkqfilter -}; - -void ulpt_disco(void *); - -int ulpt_do_write(struct ulpt_softc *, struct uio *uio, int); -int ulpt_status(struct ulpt_softc *); -void ulpt_reset(struct ulpt_softc *); -int ulpt_statusmsg(u_char, struct ulpt_softc *); - -#if 0 -void ieee1284_print_id(char *); -#endif - -#define ULPTUNIT(s) (minor(s) & 0x1f) -#define ULPTFLAGS(s) (minor(s) & 0xe0) - - -static device_probe_t ulpt_match; -static device_attach_t ulpt_attach; -static device_detach_t ulpt_detach; - -static devclass_t ulpt_devclass; - -static kobj_method_t ulpt_methods[] = { - DEVMETHOD(device_probe, ulpt_match), - DEVMETHOD(device_attach, ulpt_attach), - DEVMETHOD(device_detach, ulpt_detach), - DEVMETHOD_END -}; - -static driver_t ulpt_driver = { - "ulpt", - ulpt_methods, - sizeof(struct ulpt_softc) -}; - -MODULE_DEPEND(ulpt, usb, 1, 1, 1); - -static int -ulpt_match(device_t self) -{ - struct usb_attach_arg *uaa = device_get_ivars(self); - usb_interface_descriptor_t *id; - - DPRINTFN(10,("ulpt_match\n")); - if (uaa->iface == NULL) - return (UMATCH_NONE); - id = usbd_get_interface_descriptor(uaa->iface); - if (id != NULL && - id->bInterfaceClass == UICLASS_PRINTER && - id->bInterfaceSubClass == UISUBCLASS_PRINTER && - (id->bInterfaceProtocol == UIPROTO_PRINTER_UNI || - id->bInterfaceProtocol == UIPROTO_PRINTER_BI || - id->bInterfaceProtocol == UIPROTO_PRINTER_1284)) - return (UMATCH_IFACECLASS_IFACESUBCLASS_IFACEPROTO); - return (UMATCH_NONE); -} - -static int -ulpt_attach(device_t self) -{ - struct ulpt_softc *sc = device_get_softc(self); - struct usb_attach_arg *uaa = device_get_ivars(self); - usbd_device_handle dev = uaa->device; - usbd_interface_handle iface = uaa->iface; - usb_interface_descriptor_t *ifcd = usbd_get_interface_descriptor(iface); - usb_interface_descriptor_t *id, *iend; - usb_config_descriptor_t *cdesc; - usbd_status err; - usb_endpoint_descriptor_t *ed; - u_int8_t epcount; - int i, altno; - - DPRINTFN(10,("ulpt_attach: sc=%p\n", sc)); - sc->sc_dev = self; - - /* XXX - * Stepping through the alternate settings needs to be abstracted out. - */ - cdesc = usbd_get_config_descriptor(dev); - if (cdesc == NULL) { - kprintf("%s: failed to get configuration descriptor\n", - device_get_nameunit(sc->sc_dev)); - return ENXIO; - } - iend = (usb_interface_descriptor_t *) - ((char *)cdesc + UGETW(cdesc->wTotalLength)); -#ifdef DIAGNOSTIC - if (ifcd < (usb_interface_descriptor_t *)cdesc || - ifcd >= iend) - panic("ulpt: iface desc out of range"); -#endif - /* Step through all the descriptors looking for bidir mode */ - for (id = ifcd, altno = 0; - id < iend; - id = (void *)((char *)id + id->bLength)) { - if (id->bDescriptorType == UDESC_INTERFACE && - id->bInterfaceNumber == ifcd->bInterfaceNumber) { - if (id->bInterfaceClass == UICLASS_PRINTER && - id->bInterfaceSubClass == UISUBCLASS_PRINTER && - (id->bInterfaceProtocol == UIPROTO_PRINTER_BI /* || - id->bInterfaceProtocol == UIPROTO_PRINTER_1284 */)) - goto found; - altno++; - } - } - id = ifcd; /* not found, use original */ - found: - if (id != ifcd) { - /* Found a new bidir setting */ - DPRINTF(("ulpt_attach: set altno = %d\n", altno)); - err = usbd_set_interface(iface, altno); - if (err) { - kprintf("%s: setting alternate interface failed\n", - device_get_nameunit(sc->sc_dev)); - sc->sc_dying = 1; - return ENXIO; - } - } - - epcount = 0; - (void)usbd_endpoint_count(iface, &epcount); - - sc->sc_in = -1; - sc->sc_out = -1; - sc->vendor = uaa->vendor; - sc->product = uaa->product; - for (i = 0; i < epcount; i++) { - ed = usbd_interface2endpoint_descriptor(iface, i); - if (ed == NULL) { - kprintf("%s: couldn't get ep %d\n", - device_get_nameunit(sc->sc_dev), i); - return ENXIO; - } - if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && - UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) { - sc->sc_in = ed->bEndpointAddress; - } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT && - UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) { - sc->sc_out = ed->bEndpointAddress; - } - } - if (sc->sc_out == -1) { - kprintf("%s: could not find bulk out endpoint\n", - device_get_nameunit(sc->sc_dev)); - sc->sc_dying = 1; - return ENXIO; - } - - if (usbd_get_quirks(dev)->uq_flags & UQ_BROKEN_BIDIR) { - /* This device doesn't handle reading properly. */ - sc->sc_in = -1; - } - - kprintf("%s: using %s-directional mode\n", device_get_nameunit(sc->sc_dev), - sc->sc_in >= 0 ? "bi" : "uni"); - - DPRINTFN(10, ("ulpt_attach: bulk=%d\n", sc->sc_out)); - - sc->sc_iface = iface; - sc->sc_ifaceno = id->bInterfaceNumber; - sc->sc_udev = dev; - sc->sc_junk1 = NULL; - sc->sc_junk2 = NULL; - - sc->sc_cdev1 = make_dev(&ulpt_ops, device_get_unit(self), - UID_ROOT, GID_OPERATOR, 0644, - "ulpt%d", device_get_unit(self)); - sc->sc_cdev2 = make_dev(&ulpt_ops, device_get_unit(self)|ULPT_NOPRIME, - UID_ROOT, GID_OPERATOR, 0644, - "unlpt%d", device_get_unit(self)); - - usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev, - sc->sc_dev); - - return 0; -} - -static int -ulpt_detach(device_t self) -{ - struct ulpt_softc *sc = device_get_softc(self); - - DPRINTF(("ulpt_detach: sc=%p\n", sc)); - - sc->sc_dying = 1; - if (sc->sc_out_pipe != NULL) - usbd_abort_pipe(sc->sc_out_pipe); - if (sc->sc_in_pipe != NULL) - usbd_abort_pipe(sc->sc_in_pipe); - - /* - * Wait for any ongoing operations to complete before we actually - * close things down. - */ - - crit_enter(); - --sc->sc_refcnt; - if (sc->sc_refcnt >= 0) { - kprintf("%s: waiting for idle\n", device_get_nameunit(sc->sc_dev)); - while (sc->sc_refcnt >= 0) - usb_detach_wait(sc->sc_dev); - kprintf("%s: idle wait done\n", device_get_nameunit(sc->sc_dev)); - } - crit_exit(); - - dev_ops_remove_minor(&ulpt_ops, /*-1, */device_get_unit(self)); - devfs_assume_knotes(sc->sc_cdev1, &sc->sc_wkq); - devfs_assume_knotes(sc->sc_cdev2, &sc->sc_wkq); - - usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev, sc->sc_dev); - - return (0); -} - -int -ulpt_status(struct ulpt_softc *sc) -{ - usb_device_request_t req; - usbd_status err; - u_char status; - - req.bmRequestType = UT_READ_CLASS_INTERFACE; - req.bRequest = UR_GET_PORT_STATUS; - USETW(req.wValue, 0); - USETW(req.wIndex, sc->sc_ifaceno); - USETW(req.wLength, 1); - err = usbd_do_request(sc->sc_udev, &req, &status); - DPRINTFN(1, ("ulpt_status: status=0x%02x err=%d\n", status, err)); - if (!err) - return (status); - else - return (0); -} - -void -ulpt_reset(struct ulpt_softc *sc) -{ - usb_device_request_t req; - int other_fails; - - /* The Brother HL1240 doesn't handle UT_WRITE_CLASS_OTHER */ - other_fails = (sc->vendor == 0x04f9 && sc->product == 0x0006); - - DPRINTFN(1, ("ulpt_reset\n")); - req.bRequest = UR_SOFT_RESET; - USETW(req.wValue, 0); - USETW(req.wIndex, sc->sc_ifaceno); - USETW(req.wLength, 0); - - /* - * There was a mistake in the USB printer 1.0 spec that gave the - * request type as UT_WRITE_CLASS_OTHER; it should have been - * UT_WRITE_CLASS_INTERFACE. Many printers use the old one, - * so we try both. - */ - req.bmRequestType = UT_WRITE_CLASS_OTHER; - /* Some printers don't handle UT_WRITE_CLASS_OTHER */ - if (other_fails || usbd_do_request(sc->sc_udev, &req, 0)) {/* 1.0 */ - req.bmRequestType = UT_WRITE_CLASS_INTERFACE; - (void)usbd_do_request(sc->sc_udev, &req, 0); /* 1.1 */ - } -} - -static void -ulpt_input(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status) -{ - struct ulpt_softc *sc = priv; - u_int32_t count; - - /* Don't loop on errors or 0-length input. */ - usbd_get_xfer_status(xfer, NULL, NULL, &count, NULL); - if (status != USBD_NORMAL_COMPLETION || count == 0) - return; - - DPRINTFN(2,("ulpt_input: got some data\n")); - /* Do it again. */ - if (xfer == sc->sc_in_xfer1) - usbd_transfer(sc->sc_in_xfer2); - else - usbd_transfer(sc->sc_in_xfer1); -} - -int ulptusein = 1; - -/* - * Reset the printer, then wait until it's selected and not busy. - */ -int -ulptopen(struct dev_open_args *ap) -{ - cdev_t dev = ap->a_head.a_dev; - u_char flags = ULPTFLAGS(dev); - struct ulpt_softc *sc; - usbd_status err; - int spin, error; - - sc = devclass_get_softc(ulpt_devclass, ULPTUNIT(dev)); - if (sc == NULL) - return (ENXIO); - - if (sc == NULL || sc->sc_iface == NULL || sc->sc_dying) - return (ENXIO); - - if (sc->sc_state) - return (EBUSY); - - sc->sc_state = ULPT_INIT; - sc->sc_flags = flags; - DPRINTF(("ulptopen: flags=0x%x\n", (unsigned)flags)); - -#if defined(USB_DEBUG) - /* Ignoring these flags might not be a good idea */ - if ((flags & ~ULPT_NOPRIME) != 0) - kprintf("ulptopen: flags ignored: %b\n", flags, - "\20\3POS_INIT\4POS_ACK\6PRIME_OPEN\7AUTOLF\10BYPASS"); -#endif - - error = 0; - sc->sc_refcnt++; - - if ((flags & ULPT_NOPRIME) == 0) { - ulpt_reset(sc); - if (sc->sc_dying) { - error = ENXIO; - sc->sc_state = 0; - goto done; - } - } - - for (spin = 0; (ulpt_status(sc) & LPS_SELECT) == 0; spin += STEP) { - DPRINTF(("ulpt_open: waiting a while\n")); - if (spin >= TIMEOUT) { - error = EBUSY; - sc->sc_state = 0; - goto done; - } - - /* wait 1/4 second, give up if we get a signal */ - error = tsleep((caddr_t)sc, PCATCH, "ulptop", STEP); - if (error != EWOULDBLOCK) { - sc->sc_state = 0; - goto done; - } - - if (sc->sc_dying) { - error = ENXIO; - sc->sc_state = 0; - goto done; - } - } - - err = usbd_open_pipe(sc->sc_iface, sc->sc_out, 0, &sc->sc_out_pipe); - if (err) { - sc->sc_state = 0; - error = EIO; - goto done; - } - - if (ulptusein && sc->sc_in != -1) { - DPRINTF(("ulpt_open: open input pipe\n")); - err = usbd_open_pipe(sc->sc_iface, sc->sc_in,0,&sc->sc_in_pipe); - if (err) { - error = EIO; - usbd_close_pipe(sc->sc_out_pipe); - sc->sc_out_pipe = NULL; - sc->sc_state = 0; - goto done; - } - sc->sc_in_xfer1 = usbd_alloc_xfer(sc->sc_udev); - sc->sc_in_xfer2 = usbd_alloc_xfer(sc->sc_udev); - if (sc->sc_in_xfer1 == NULL || sc->sc_in_xfer2 == NULL) { - error = ENOMEM; - if (sc->sc_in_xfer1 != NULL) { - usbd_free_xfer(sc->sc_in_xfer1); - sc->sc_in_xfer1 = NULL; - } - if (sc->sc_in_xfer2 != NULL) { - usbd_free_xfer(sc->sc_in_xfer2); - sc->sc_in_xfer2 = NULL; - } - usbd_close_pipe(sc->sc_out_pipe); - sc->sc_out_pipe = NULL; - usbd_close_pipe(sc->sc_in_pipe); - sc->sc_in_pipe = NULL; - sc->sc_state = 0; - goto done; - } - sc->sc_junk1 = usbd_alloc_buffer(sc->sc_in_xfer1, - ULPT_JUNK_SIZE); - sc->sc_junk2 = usbd_alloc_buffer(sc->sc_in_xfer2, - ULPT_JUNK_SIZE); - usbd_setup_xfer(sc->sc_in_xfer1, sc->sc_in_pipe, sc, - sc->sc_junk1, ULPT_JUNK_SIZE, USBD_SHORT_XFER_OK, - USBD_NO_TIMEOUT, ulpt_input); - usbd_setup_xfer(sc->sc_in_xfer2, sc->sc_in_pipe, sc, - sc->sc_junk2, ULPT_JUNK_SIZE, USBD_SHORT_XFER_OK, - USBD_NO_TIMEOUT, ulpt_input); - usbd_transfer(sc->sc_in_xfer1); /* ignore failed start */ - } - - sc->sc_state = ULPT_OPEN; - -done: - if (--sc->sc_refcnt < 0) - usb_detach_wakeup(sc->sc_dev); - - DPRINTF(("ulptopen: done, error=%d\n", error)); - return (error); -} - -int -ulpt_statusmsg(u_char status, struct ulpt_softc *sc) -{ - u_char new; - - status = (status ^ LPS_INVERT) & LPS_MASK; - new = status & ~sc->sc_laststatus; - sc->sc_laststatus = status; - - if (new & LPS_SELECT) - log(LOG_NOTICE, "%s: offline\n", device_get_nameunit(sc->sc_dev)); - else if (new & LPS_NOPAPER) - log(LOG_NOTICE, "%s: out of paper\n", device_get_nameunit(sc->sc_dev)); - else if (new & LPS_NERR) - log(LOG_NOTICE, "%s: output error\n", device_get_nameunit(sc->sc_dev)); - - return (status); -} - -int -ulptclose(struct dev_close_args *ap) -{ - cdev_t dev = ap->a_head.a_dev; - struct ulpt_softc *sc; - - sc = devclass_get_softc(ulpt_devclass, ULPTUNIT(dev)); - - if (sc == NULL) - return (0); - - if (sc->sc_state != ULPT_OPEN) - /* We are being forced to close before the open completed. */ - return (0); - - if (sc->sc_out_pipe != NULL) { - usbd_close_pipe(sc->sc_out_pipe); - sc->sc_out_pipe = NULL; - } - if (sc->sc_in_pipe != NULL) { - usbd_abort_pipe(sc->sc_in_pipe); - usbd_close_pipe(sc->sc_in_pipe); - sc->sc_in_pipe = NULL; - if (sc->sc_in_xfer1 != NULL) { - usbd_free_xfer(sc->sc_in_xfer1); - sc->sc_in_xfer1 = NULL; - } - if (sc->sc_in_xfer2 != NULL) { - usbd_free_xfer(sc->sc_in_xfer2); - sc->sc_in_xfer2 = NULL; - } - } - - sc->sc_state = 0; - - DPRINTF(("ulptclose: closed\n")); - return (0); -} - -int -ulpt_do_write(struct ulpt_softc *sc, struct uio *uio, int flags) -{ - u_int32_t n; - int error = 0; - void *bufp; - usbd_xfer_handle xfer; - usbd_status err; - - DPRINTF(("ulptwrite\n")); - xfer = usbd_alloc_xfer(sc->sc_udev); - if (xfer == NULL) - return (ENOMEM); - bufp = usbd_alloc_buffer(xfer, ULPT_BSIZE); - if (bufp == NULL) { - usbd_free_xfer(xfer); - return (ENOMEM); - } - while ((n = szmin(ULPT_BSIZE, uio->uio_resid)) != 0) { - ulpt_statusmsg(ulpt_status(sc), sc); - error = uiomove(bufp, n, uio); - if (error) { - DPRINTF(("ulpt_do_write: uiomove error = %d\n", error)); - break; - } - DPRINTFN(1, ("ulptwrite: transfer %d bytes\n", n)); - err = usbd_bulk_transfer(xfer, sc->sc_out_pipe, USBD_NO_COPY, - USBD_NO_TIMEOUT, bufp, &n, "ulptwr"); - if (err) { - DPRINTF(("ulptwrite: error=%d\n", err)); - error = EIO; - break; - } - } - usbd_free_xfer(xfer); - - return (error); -} - -int -ulptwrite(struct dev_write_args *ap) -{ - cdev_t dev = ap->a_head.a_dev; - struct ulpt_softc *sc; - int error; - - sc = devclass_get_softc(ulpt_devclass, ULPTUNIT(dev)); - - if (sc == NULL || sc->sc_dying) - return (EIO); - - sc->sc_refcnt++; - error = ulpt_do_write(sc, ap->a_uio, ap->a_ioflag); - DPRINTF(("ulpt_write: error = %d\n", error)); - if (--sc->sc_refcnt < 0) - usb_detach_wakeup(sc->sc_dev); - return (error); -} - -int -ulptioctl(struct dev_ioctl_args *ap) -{ - int error = 0; - - switch (ap->a_cmd) { - default: - error = ENODEV; - } - - return (error); -} - -static struct filterops ulpt_filtops = - { FILTEROP_ISFD, NULL, ulpt_filt_detach, ulpt_filt }; - -static int -ulptkqfilter(struct dev_kqfilter_args *ap) -{ - cdev_t dev = ap->a_head.a_dev; - struct knote *kn = ap->a_kn; - struct ulpt_softc *sc; - struct klist *klist; - - ap->a_result = 0; - - switch(kn->kn_filter) { - case EVFILT_WRITE: - sc = devclass_get_softc(ulpt_devclass, ULPTUNIT(dev)); - kn->kn_fop = &ulpt_filtops; - kn->kn_hook = (caddr_t)sc; - break; - default: - ap->a_result = EOPNOTSUPP; - return (0); - } - - klist = &sc->sc_wkq.ki_note; - knote_insert(klist, kn); - - return(0); -} - -static void -ulpt_filt_detach(struct knote *kn) -{ - struct ulpt_softc *sc = (struct ulpt_softc *)kn->kn_hook; - struct klist *klist; - - klist = &sc->sc_wkq.ki_note; - knote_remove(klist, kn); -} - -static int -ulpt_filt(struct knote *kn, long hint) -{ -/* struct ulpt_softc *sc = (struct ulpt_softc *)kn->kn_hook;*/ - - return 1; -} - -#if 0 -/* XXX This does not belong here. */ -/* - * Print select parts of an IEEE 1284 device ID. - */ -void -ieee1284_print_id(char *str) -{ - char *p, *q; - - for (p = str-1; p; p = strchr(p, ';')) { - p++; /* skip ';' */ - if (strncmp(p, "MFG:", 4) == 0 || - strncmp(p, "MANUFACTURER:", 14) == 0 || - strncmp(p, "MDL:", 4) == 0 || - strncmp(p, "MODEL:", 6) == 0) { - q = strchr(p, ';'); - if (q) - kprintf("%.*s", (int)(q - p + 1), p); - } - } -} -#endif - -DRIVER_MODULE(ulpt, uhub, ulpt_driver, ulpt_devclass, usbd_driver_load, NULL); - diff --git a/sys/dev/usbmisc/umass/Makefile b/sys/dev/usbmisc/umass/Makefile deleted file mode 100644 index 8a2d71020a..0000000000 --- a/sys/dev/usbmisc/umass/Makefile +++ /dev/null @@ -1,11 +0,0 @@ -# $FreeBSD: src/sys/modules/umass/Makefile,v 1.7.2.1 2000/04/01 19:33:33 n_hibma Exp $ -# $DragonFly: src/sys/dev/usbmisc/umass/Makefile,v 1.3 2004/01/31 06:56:33 dillon Exp $ - -.PATH: ${.CURDIR}/../../dev/usb -KMOD = umass -KMODDEP = cam -SRCS = bus_if.h device_if.h \ - opt_usb.h opt_cam.h opt_scsi.h \ - umass.c - -.include diff --git a/sys/dev/usbmisc/umass/umass.c b/sys/dev/usbmisc/umass/umass.c deleted file mode 100644 index 301466a02a..0000000000 --- a/sys/dev/usbmisc/umass/umass.c +++ /dev/null @@ -1,3636 +0,0 @@ -/*- - * Copyright (c) 1999 MAEKAWA Masahide , - * Nick Hibma - * 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. - * - * $NetBSD: umass.c,v 1.28 2000/04/02 23:46:53 augustss Exp $ - * $FreeBSD: src/sys/dev/usb/umass.c,v 1.96 2003/12/19 12:19:11 sanpei Exp $ - */ - -/* - * Universal Serial Bus Mass Storage Class specs: - * http://www.usb.org/developers/data/devclass/usbmassover_11.pdf - * http://www.usb.org/developers/data/devclass/usbmassbulk_10.pdf - * http://www.usb.org/developers/data/devclass/usbmass-cbi10.pdf - * http://www.usb.org/developers/data/devclass/usbmass-ufi10.pdf - */ - -/* - * Ported to NetBSD by Lennart Augustsson . - * Parts of the code written my Jason R. Thorpe . - */ - -/* - * The driver handles 3 Wire Protocols - * - Command/Bulk/Interrupt (CBI) - * - Command/Bulk/Interrupt with Command Completion Interrupt (CBI with CCI) - * - Mass Storage Bulk-Only (BBB) - * (BBB refers Bulk/Bulk/Bulk for Command/Data/Status phases) - * - * Over these wire protocols it handles the following command protocols - * - SCSI - * - UFI (floppy command set) - * - 8070i (ATAPI) - * - * UFI and 8070i (ATAPI) are transformed versions of the SCSI command set. The - * sc->transform method is used to convert the commands into the appropriate - * format (if at all necessary). For example, UFI requires all commands to be - * 12 bytes in length amongst other things. - * - * The source code below is marked and can be split into a number of pieces - * (in this order): - * - * - probe/attach/detach - * - generic transfer routines - * - BBB - * - CBI - * - CBI_I (in addition to functions from CBI) - * - CAM (Common Access Method) - * - SCSI - * - UFI - * - 8070i (ATAPI) - * - * The protocols are implemented using a state machine, for the transfers as - * well as for the resets. The state machine is contained in umass_*_state. - * The state machine is started through either umass_*_transfer or - * umass_*_reset. - * - * The reason for doing this is a) CAM performs a lot better this way and b) it - * avoids using tsleep from interrupt context (for example after a failed - * transfer). - */ - -/* - * The SCSI related part of this driver has been derived from the - * dev/ppbus/vpo.c driver, by Nicolas Souchu (nsouch@freebsd.org). - * - * The CAM layer uses so called actions which are messages sent to the host - * adapter for completion. The actions come in through umass_cam_action. The - * appropriate block of routines is called depending on the transport protocol - * in use. When the transfer has finished, these routines call - * umass_cam_cb again to complete the CAM command. - */ - -/* - * XXX Currently CBI with CCI is not supported because it bombs the system - * when the device is detached (low frequency interrupts are detached - * too late. - */ -#undef CBI_I - -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#ifdef USB_DEBUG -#define DIF(m, x) if (umassdebug & (m)) do { x ; } while (0) -#define DPRINTF(m, x) if (umassdebug & (m)) kprintf x -#define UDMASS_GEN 0x00010000 /* general */ -#define UDMASS_SCSI 0x00020000 /* scsi */ -#define UDMASS_UFI 0x00040000 /* ufi command set */ -#define UDMASS_ATAPI 0x00080000 /* 8070i command set */ -#define UDMASS_CMD (UDMASS_SCSI|UDMASS_UFI|UDMASS_ATAPI) -#define UDMASS_USB 0x00100000 /* USB general */ -#define UDMASS_BBB 0x00200000 /* Bulk-Only transfers */ -#define UDMASS_CBI 0x00400000 /* CBI transfers */ -#define UDMASS_WIRE (UDMASS_BBB|UDMASS_CBI) -#define UDMASS_ALL 0xffff0000 /* all of the above */ -int umassdebug = 0; -SYSCTL_NODE(_hw_usb, OID_AUTO, umass, CTLFLAG_RW, 0, "USB umass"); -SYSCTL_INT(_hw_usb_umass, OID_AUTO, debug, CTLFLAG_RW, - &umassdebug, 0, "umass debug level"); -#else -#define DIF(m, x) /* nop */ -#define DPRINTF(m, x) /* nop */ -#endif - - -/* Generic definitions */ - -/* Direction for umass_*_transfer */ -#define DIR_NONE 0 -#define DIR_IN 1 -#define DIR_OUT 2 - -/* device name */ -#define DEVNAME "umass" -#define DEVNAME_SIM "umass-sim" - -#define UMASS_MAX_TRANSFER_SIZE 65536 -/* Approximate maximum transfer speeds (assumes 33% overhead). */ -#define UMASS_FULL_TRANSFER_SPEED 1000 -#define UMASS_HIGH_TRANSFER_SPEED 40000 -#define UMASS_FLOPPY_TRANSFER_SPEED 20 - -#define UMASS_TIMEOUT 5000 /* msecs */ - -/* CAM specific definitions */ - -#define UMASS_SCSIID_MAX 1 /* maximum number of drives expected */ -#define UMASS_SCSIID_HOST UMASS_SCSIID_MAX - -#define MS_TO_TICKS(ms) ((ms) * hz / 1000) - - -/* Bulk-Only features */ - -#define UR_BBB_RESET 0xff /* Bulk-Only reset */ -#define UR_BBB_GET_MAX_LUN 0xfe /* Get maximum lun */ - -/* Command Block Wrapper */ -typedef struct { - uDWord dCBWSignature; -# define CBWSIGNATURE 0x43425355 - uDWord dCBWTag; - uDWord dCBWDataTransferLength; - uByte bCBWFlags; -# define CBWFLAGS_OUT 0x00 -# define CBWFLAGS_IN 0x80 - uByte bCBWLUN; - uByte bCDBLength; -# define CBWCDBLENGTH 16 - uByte CBWCDB[CBWCDBLENGTH]; -} umass_bbb_cbw_t; -#define UMASS_BBB_CBW_SIZE 31 - -/* Command Status Wrapper */ -typedef struct { - uDWord dCSWSignature; -# define CSWSIGNATURE 0x53425355 -# define CSWSIGNATURE_OLYMPUS_C1 0x55425355 - uDWord dCSWTag; - uDWord dCSWDataResidue; - uByte bCSWStatus; -# define CSWSTATUS_GOOD 0x0 -# define CSWSTATUS_FAILED 0x1 -# define CSWSTATUS_PHASE 0x2 -} umass_bbb_csw_t; -#define UMASS_BBB_CSW_SIZE 13 - -/* CBI features */ - -#define UR_CBI_ADSC 0x00 - -typedef unsigned char umass_cbi_cbl_t[16]; /* Command block */ - -typedef union { - struct { - unsigned char type; - #define IDB_TYPE_CCI 0x00 - unsigned char value; - #define IDB_VALUE_PASS 0x00 - #define IDB_VALUE_FAIL 0x01 - #define IDB_VALUE_PHASE 0x02 - #define IDB_VALUE_PERSISTENT 0x03 - #define IDB_VALUE_STATUS_MASK 0x03 - } common; - - struct { - unsigned char asc; - unsigned char ascq; - } ufi; -} umass_cbi_sbl_t; - - - -struct umass_softc; /* see below */ - -typedef void (*transfer_cb_f) (struct umass_softc *sc, void *priv, - int residue, int status); -#define STATUS_CMD_OK 0 /* everything ok */ -#define STATUS_CMD_UNKNOWN 1 /* will have to fetch sense */ -#define STATUS_CMD_FAILED 2 /* transfer was ok, command failed */ -#define STATUS_WIRE_FAILED 3 /* couldn't even get command across */ - -typedef void (*wire_reset_f) (struct umass_softc *sc, int status); -typedef void (*wire_transfer_f) (struct umass_softc *sc, int lun, - void *cmd, int cmdlen, void *data, int datalen, - int dir, u_int timeout, transfer_cb_f cb, void *priv); -typedef void (*wire_state_f) (usbd_xfer_handle xfer, - usbd_private_handle priv, usbd_status err); - -typedef int (*command_transform_f) (struct umass_softc *sc, - unsigned char *cmd, int cmdlen, - unsigned char **rcmd, int *rcmdlen); - - -struct umass_devdescr_t { - u_int32_t vendor; - u_int32_t product; - u_int32_t release; -# define WILDCARD_ID 0xffffffff -# define EOT_ID 0xfffffffe - - /* wire and command protocol */ - u_int16_t proto; -# define UMASS_PROTO_BBB 0x0001 /* USB wire protocol */ -# define UMASS_PROTO_CBI 0x0002 -# define UMASS_PROTO_CBI_I 0x0004 -# define UMASS_PROTO_WIRE 0x00ff /* USB wire protocol mask */ -# define UMASS_PROTO_SCSI 0x0100 /* command protocol */ -# define UMASS_PROTO_ATAPI 0x0200 -# define UMASS_PROTO_UFI 0x0400 -# define UMASS_PROTO_RBC 0x0800 -# define UMASS_PROTO_COMMAND 0xff00 /* command protocol mask */ - - /* Device specific quirks */ - u_int16_t quirks; -# define NO_QUIRKS 0x0000 - /* The drive does not support Test Unit Ready. Convert to Start Unit - */ -# define NO_TEST_UNIT_READY 0x0001 - /* The drive does not reset the Unit Attention state after REQUEST - * SENSE has been sent. The INQUIRY command does not reset the UA - * either, and so CAM runs in circles trying to retrieve the initial - * INQUIRY data. - */ -# define RS_NO_CLEAR_UA 0x0002 - /* The drive does not support START STOP. */ -# define NO_START_STOP 0x0004 - /* Don't ask for full inquiry data (255b). */ -# define FORCE_SHORT_INQUIRY 0x0008 - /* Needs to be initialised the Shuttle way */ -# define SHUTTLE_INIT 0x0010 - /* Drive needs to be switched to alternate iface 1 */ -# define ALT_IFACE_1 0x0020 - /* Drive does not do 1Mb/s, but just floppy speeds (20kb/s) */ -# define FLOPPY_SPEED 0x0040 - /* The device can't count and gets the residue of transfers wrong */ -# define IGNORE_RESIDUE 0x0080 - /* No GetMaxLun call */ -# define NO_GETMAXLUN 0x0100 - /* The device uses a weird CSWSIGNATURE. */ -# define WRONG_CSWSIG 0x0200 - /* Device cannot handle INQUIRY so fake a generic response */ -# define NO_INQUIRY 0x0400 - /* Device cannot handle INQUIRY EVPD, return CHECK CONDITION */ -# define NO_INQUIRY_EVPD 0x0800 -# define READ_CAPACITY_OFFBY1 0x2000 -}; - -static struct umass_devdescr_t umass_devdescrs[] = { - /* Addonics Cable 205 */ - { .vendor = 0x0bf6, .product = 0xa001, .release = WILDCARD_ID, - .proto = UMASS_PROTO_SCSI | UMASS_PROTO_BBB, - .quirks = NO_QUIRKS - }, - /* Addonics USB 2.0 Flash */ - { .vendor = 0x09df, .product = 0x1300, .release = WILDCARD_ID, - .proto = UMASS_PROTO_SCSI | UMASS_PROTO_BBB, - .quirks = IGNORE_RESIDUE - }, - /* Addonics Attache 256MB USB */ - { .vendor = 0x09df, .product = 0x1400, .release = WILDCARD_ID, - .proto = UMASS_PROTO_SCSI | UMASS_PROTO_BBB, - .quirks = IGNORE_RESIDUE - }, - /* Addonics USB 2.0 Flash */ - { .vendor = 0x09df, .product = 0x1420, .release = WILDCARD_ID, - .proto = UMASS_PROTO_SCSI | UMASS_PROTO_BBB, - .quirks = IGNORE_RESIDUE - }, - /* AIPTEK PocketCAM 3Mega */ - { .vendor = 0x08ca, .product = 0x2011, .release = WILDCARD_ID, - .proto = UMASS_PROTO_SCSI | UMASS_PROTO_BBB, - .quirks = NO_QUIRKS - }, - /* All Asahi Optical products */ - { .vendor = 0x0a17, .product = WILDCARD_ID, .release = WILDCARD_ID, - .proto = UMASS_PROTO_ATAPI | UMASS_PROTO_CBI_I, - .quirks = RS_NO_CLEAR_UA - }, - /* Belkin USB to SCSI */ - { .vendor = 0x050d, .product = 0x0115, .release = WILDCARD_ID, - .proto = UMASS_PROTO_SCSI | UMASS_PROTO_BBB, - .quirks = NO_QUIRKS - }, - /* CASIO QV DigiCam */ - { .vendor = 0x07cf, .product = 0x1001, .release = WILDCARD_ID, - .proto = UMASS_PROTO_SCSI | UMASS_PROTO_CBI, - .quirks = NO_INQUIRY - }, - /* CCYU EasyDisk ED1064 */ - { .vendor = 0x1065, .product = 0x2136, .release = WILDCARD_ID, - .proto = UMASS_PROTO_SCSI | UMASS_PROTO_BBB, - .quirks = NO_QUIRKS - }, - /* Century Century USB Disk */ - { .vendor = 0x07f7, .product = 0x011e, .release = WILDCARD_ID, - .proto = UMASS_PROTO_SCSI | UMASS_PROTO_BBB, - .quirks = FORCE_SHORT_INQUIRY | NO_START_STOP | IGNORE_RESIDUE - }, - /* Desknote UCR-61S2B */ - { .vendor = 0x1019, .product = 0x0c55, .release = WILDCARD_ID, - .proto = UMASS_PROTO_SCSI | UMASS_PROTO_BBB, - .quirks = NO_QUIRKS - }, - /* DMI CF/SM Reader/Writer */ - { .vendor = 0x0c0b, .product = 0xa109, .release = WILDCARD_ID, - .proto = UMASS_PROTO_SCSI, - .quirks = NO_GETMAXLUN - }, - /* Epson Stylus Photo 875DC */ - { .vendor = 0x03f8, .product = 0x0601, .release = WILDCARD_ID, - .proto = UMASS_PROTO_SCSI | UMASS_PROTO_CBI, - .quirks = NO_INQUIRY - }, - /* Epson Stylus Photo 895 */ - { .vendor = 0x03f8, .product = 0x0602, .release = WILDCARD_ID, - .proto = UMASS_PROTO_SCSI | UMASS_PROTO_BBB, - .quirks = NO_GETMAXLUN - }, - /* Feiya 5-in-1 Card Reader */ - { .vendor = 0x090c, .product = 0x1132, .release = WILDCARD_ID, - .proto = UMASS_PROTO_SCSI | UMASS_PROTO_BBB, - .quirks = NO_QUIRKS - }, - /* Freecom DVD drive */ - { .vendor = 0x07ab, .product = 0xfc01, .release = WILDCARD_ID, - .proto = UMASS_PROTO_SCSI, - .quirks = NO_QUIRKS - }, - /* Fujiphoto mass storage products */ - { .vendor = 0x04cb, .product = 0x0100, .release = WILDCARD_ID, - .proto = UMASS_PROTO_ATAPI | UMASS_PROTO_CBI_I, - .quirks = RS_NO_CLEAR_UA - }, - /* Genesys GL641USB USB-IDE Bridge */ - { .vendor = 0x05e3, .product = 0x0701, .release = WILDCARD_ID, - .proto = UMASS_PROTO_SCSI | UMASS_PROTO_BBB, - .quirks = FORCE_SHORT_INQUIRY | NO_START_STOP | IGNORE_RESIDUE - }, - /* Genesys GL641USB USB-IDE Bridge */ - { .vendor = 0x05e3, .product = 0x0702, .release = WILDCARD_ID, - .proto = UMASS_PROTO_SCSI | UMASS_PROTO_BBB, - .quirks = FORCE_SHORT_INQUIRY | NO_START_STOP | IGNORE_RESIDUE - }, - /* Genesys GL641USB CompactFlash Card */ - { .vendor = 0x05e3, .product = 0x0700, .release = WILDCARD_ID, - .proto = UMASS_PROTO_SCSI | UMASS_PROTO_BBB, - .quirks = FORCE_SHORT_INQUIRY | NO_START_STOP | IGNORE_RESIDUE - }, - /* Genesys GL641USB 6-in-1 Card */ - { .vendor = 0x05e3, .product = 0x0760, .release = WILDCARD_ID, - .proto = UMASS_PROTO_SCSI | UMASS_PROTO_BBB, - .quirks = WRONG_CSWSIG - }, - /* Hagiwara FlashGate SmartMedia Card */ - { .vendor = 0x0693, .product = 0x0002, .release = WILDCARD_ID, - .proto = UMASS_PROTO_SCSI | UMASS_PROTO_BBB, - .quirks = NO_QUIRKS - }, - /* Hitachi DVDCAM USB HS Interface */ - { .vendor = 0x04a4, .product = 0x001e, .release = WILDCARD_ID, - .proto = UMASS_PROTO_ATAPI | UMASS_PROTO_CBI_I, - .quirks = NO_INQUIRY - }, - /* Hitachi DVD-CAM DZ-MV100A Camcorder */ - { .vendor = 0x04a4, .product = 0x0004, .release = WILDCARD_ID, - .proto = UMASS_PROTO_SCSI | UMASS_PROTO_CBI, - .quirks = NO_GETMAXLUN - }, - /* Hewlett CD-Writer+ CD-4e */ - { .vendor = 0x03f0, .product = 0x0307, .release = WILDCARD_ID, - .proto = UMASS_PROTO_ATAPI, - .quirks = NO_QUIRKS - }, - /* Hewlett CD-Writer Plus 8200e */ - { .vendor = 0x03f0, .product = 0x0207, .release = WILDCARD_ID, - .proto = UMASS_PROTO_ATAPI | UMASS_PROTO_CBI_I, - .quirks = NO_TEST_UNIT_READY | NO_START_STOP - }, - /* Imagination DBX1 DSP core */ - { .vendor = 0x149a, .product = 0x2107, .release = WILDCARD_ID, - .proto = UMASS_PROTO_SCSI | UMASS_PROTO_BBB, - .quirks = WRONG_CSWSIG - }, - /* In-System ATAPI Adapter */ - { .vendor = 0x05ab, .product = 0x0031, .release = WILDCARD_ID, - .proto = UMASS_PROTO_RBC | UMASS_PROTO_CBI, - .quirks = NO_QUIRKS - }, - /* In-System USB Storage Adapter */ - { .vendor = 0x05ab, .product = 0x5701, .release = WILDCARD_ID, - .proto = UMASS_PROTO_RBC | UMASS_PROTO_CBI, - .quirks = NO_QUIRKS - }, - /* In-System USB cable */ - { .vendor = 0x05ab, .product = 0x081a, .release = WILDCARD_ID, - .proto = UMASS_PROTO_ATAPI | UMASS_PROTO_CBI, - .quirks = NO_TEST_UNIT_READY | NO_START_STOP | ALT_IFACE_1 - }, - /* I-O DVD Multi-plus unit */ - { .vendor = 0x04bb, .product = 0x0204, .release = WILDCARD_ID, - .proto = UMASS_PROTO_SCSI | UMASS_PROTO_BBB, - .quirks = NO_QUIRKS - }, - /* I-O DVD Multi-plus unit */ - { .vendor = 0x04bb, .product = 0x0206, .release = WILDCARD_ID, - .proto = UMASS_PROTO_SCSI | UMASS_PROTO_BBB, - .quirks = NO_QUIRKS - }, - /* Iomega Zip 100 */ - { .vendor = 0x059b, .product = 0x0001, .release = WILDCARD_ID, - /* XXX This is not correct as there are Zip drives that use ATAPI. */ - .proto = UMASS_PROTO_SCSI | UMASS_PROTO_BBB, - .quirks = NO_TEST_UNIT_READY - }, - /* Kyocera Finecam L3 */ - { .vendor = 0x0482, .product = 0x0105, .release = WILDCARD_ID, - .proto = UMASS_PROTO_SCSI | UMASS_PROTO_BBB, - .quirks = NO_INQUIRY - }, - /* Kyocera Finecam S3x */ - { .vendor = 0x0482, .product = 0x0100, .release = WILDCARD_ID, - .proto = UMASS_PROTO_ATAPI | UMASS_PROTO_CBI, - .quirks = NO_INQUIRY - }, - /* Kyocera Finecam S4 */ - { .vendor = 0x0482, .product = 0x0101, .release = WILDCARD_ID, - .proto = UMASS_PROTO_ATAPI | UMASS_PROTO_CBI, - .quirks = NO_INQUIRY - }, - /* Kyocera Finecam S5 */ - { .vendor = 0x0482, .product = 0x0103, .release = WILDCARD_ID, - .proto = UMASS_PROTO_SCSI | UMASS_PROTO_BBB, - .quirks = NO_INQUIRY - }, - /* LaCie Hard Disk */ - { .vendor = 0x059f, .product = 0xa601, .release = WILDCARD_ID, - .proto = UMASS_PROTO_RBC | UMASS_PROTO_CBI, - .quirks = NO_QUIRKS - }, - /* Lexar USB CF Reader */ - { .vendor = 0x05dc, .product = 0xb002, .release = WILDCARD_ID, - .proto = UMASS_PROTO_SCSI | UMASS_PROTO_BBB, - .quirks = NO_INQUIRY - }, - /* Lexar jumpSHOT CompactFlash Reader */ - { .vendor = 0x05dc, .product = 0x0001, .release = WILDCARD_ID, - .proto = UMASS_PROTO_SCSI, - .quirks = NO_QUIRKS - }, - /* Logitech DVD Multi-plus unit */ - { .vendor = 0x046d, .product = 0x0033, .release = WILDCARD_ID, - .proto = UMASS_PROTO_SCSI, - .quirks = NO_QUIRKS - }, - /* Logitech DVD Multi-plus unit LDR-H443U2 */ - { .vendor = 0x0789, .product = 0x00b3, .release = WILDCARD_ID, - .proto = UMASS_PROTO_SCSI | UMASS_PROTO_BBB, - .quirks = NO_QUIRKS - }, - /* Melco USB-IDE Bridge: DUB-PxxG */ - { .vendor = 0x0411, .product = 0x001c, .release = WILDCARD_ID, - .proto = UMASS_PROTO_SCSI | UMASS_PROTO_BBB, - .quirks = FORCE_SHORT_INQUIRY | NO_START_STOP | IGNORE_RESIDUE - }, - /* Microtech USB CameraMate */ - { .vendor = 0x07af, .product = 0x0006, .release = WILDCARD_ID, - .proto = UMASS_PROTO_SCSI | UMASS_PROTO_CBI, - .quirks = NO_TEST_UNIT_READY | NO_START_STOP - }, - /* Microtech USB-SCSI-DB25 */ - { .vendor = 0x07af, .product = 0x0004, .release = WILDCARD_ID, - .proto = UMASS_PROTO_SCSI | UMASS_PROTO_BBB, - .quirks = NO_QUIRKS - }, - /* Microtech USB-SCSI-HD50 */ - { .vendor = 0x07af, .product = 0x0005, .release = WILDCARD_ID, - .proto = UMASS_PROTO_SCSI | UMASS_PROTO_BBB, - .quirks = NO_QUIRKS - }, - /* Minolta Dimage E223 */ - { .vendor = 0x0686, .product = 0x4017, .release = WILDCARD_ID, - .proto = UMASS_PROTO_SCSI, - .quirks = NO_QUIRKS - }, - /* Minolta Dimage F300 */ - { .vendor = 0x0686, .product = 0x4011, .release = WILDCARD_ID, - .proto = UMASS_PROTO_SCSI | UMASS_PROTO_BBB, - .quirks = NO_QUIRKS - }, - /* Mitsumi CD-R/RW Drive */ - { .vendor = 0x03ee, .product = 0x0000, .release = WILDCARD_ID, - .proto = UMASS_PROTO_ATAPI | UMASS_PROTO_CBI, - .quirks = NO_QUIRKS - }, - /* Mitsumi USB FDD */ - { .vendor = 0x03ee, .product = 0x6901, .release = WILDCARD_ID, - .proto = UMASS_PROTO_SCSI | UMASS_PROTO_BBB, - .quirks = NO_GETMAXLUN - }, - /* Motorola E398 Mobile Phone */ - { .vendor = 0x22b8, .product = 0x4810, .release = WILDCARD_ID, - .proto = UMASS_PROTO_SCSI | UMASS_PROTO_BBB, - .quirks = FORCE_SHORT_INQUIRY | NO_INQUIRY_EVPD | NO_GETMAXLUN - }, - /* M-Systems DiskOnKey */ - { .vendor = 0x08ec, .product = 0x0010, .release = WILDCARD_ID, - .proto = UMASS_PROTO_SCSI | UMASS_PROTO_BBB, - .quirks = IGNORE_RESIDUE | NO_GETMAXLUN | RS_NO_CLEAR_UA - }, - /* M-Systems DiskOnKey */ - { .vendor = 0x08ec, .product = 0x0011, .release = WILDCARD_ID, - .proto = UMASS_PROTO_ATAPI | UMASS_PROTO_BBB, - .quirks = NO_QUIRKS - }, - /* Myson USB-IDE */ - { .vendor = 0x04cf, .product = 0x8818, .release = WILDCARD_ID, - .proto = UMASS_PROTO_SCSI | UMASS_PROTO_BBB, - .quirks = NO_INQUIRY | IGNORE_RESIDUE - }, - /* Neodio 8-in-1 Multi-format Flash */ - { .vendor = 0x0aec, .product = 0x3260, .release = WILDCARD_ID, - .proto = UMASS_PROTO_SCSI | UMASS_PROTO_BBB, - .quirks = FORCE_SHORT_INQUIRY - }, - /* Netac USB-CF-Card */ - { .vendor = 0x0dd8, .product = 0x1060, .release = WILDCARD_ID, - .proto = UMASS_PROTO_SCSI | UMASS_PROTO_BBB, - .quirks = NO_INQUIRY - }, - /* Netac OnlyDisk */ - { .vendor = 0x0dd8, .product = 0x0003, .release = WILDCARD_ID, - .proto = UMASS_PROTO_SCSI | UMASS_PROTO_BBB, - .quirks = IGNORE_RESIDUE - }, - /* NetChip USB Clik! 40 */ - { .vendor = 0x0525, .product = 0xa140, .release = WILDCARD_ID, - .proto = UMASS_PROTO_ATAPI, - .quirks = NO_INQUIRY - }, - /* Olympus C-1 Digital Camera */ - { .vendor = 0x07b4, .product = 0x0102, .release = WILDCARD_ID, - .proto = UMASS_PROTO_SCSI | UMASS_PROTO_BBB, - .quirks = WRONG_CSWSIG - }, - /* Olympus C-700 Ultra Zoom */ - { .vendor = 0x07b4, .product = 0x0105, .release = WILDCARD_ID, - .proto = UMASS_PROTO_SCSI, - .quirks = NO_GETMAXLUN - }, - /* OnSpec SIIG/Datafab Memory Stick+CF */ - { .vendor = 0x07c4, .product = 0xa001, .release = WILDCARD_ID, - .proto = UMASS_PROTO_SCSI, - .quirks = NO_QUIRKS - }, - /* OnSpec USB to CF */ - { .vendor = 0x07c4, .product = 0xa109, .release = WILDCARD_ID, - .proto = UMASS_PROTO_SCSI, - .quirks = NO_QUIRKS - }, - /* OnSpec PNY/Datafab CF+SM Reader */ - { .vendor = 0x07c4, .product = 0xa005, .release = WILDCARD_ID, - .proto = UMASS_PROTO_SCSI, - .quirks = NO_QUIRKS - }, - /* OnSpec Simple Tech/Datafab CF+SM */ - { .vendor = 0x07c4, .product = 0xa006, .release = WILDCARD_ID, - .proto = UMASS_PROTO_SCSI, - .quirks = NO_QUIRKS - }, - /* OnSpec MDCFE-B USB CF */ - { .vendor = 0x07c4, .product = 0xa000, .release = WILDCARD_ID, - .proto = UMASS_PROTO_SCSI, - .quirks = NO_QUIRKS - }, - /* OnSpec MDSM-B reader */ - { .vendor = 0x07c4, .product = 0xa103, .release = WILDCARD_ID, - .proto = UMASS_PROTO_SCSI, - .quirks = NO_INQUIRY - }, - /* OnSpec Datafab-based Reader */ - { .vendor = 0x07c4, .product = 0xa003, .release = WILDCARD_ID, - .proto = UMASS_PROTO_SCSI, - .quirks = NO_QUIRKS - }, - /* OnSpec FlashLink UCF-100 CompactFlash */ - { .vendor = 0x07c4, .product = 0xa400, .release = WILDCARD_ID, - .proto = UMASS_PROTO_ATAPI | UMASS_PROTO_BBB, - .quirks = NO_INQUIRY | NO_GETMAXLUN - }, - /* OnSpec ImageMate SDDR55 */ - { .vendor = 0x55aa, .product = 0xa103, .release = WILDCARD_ID, - .proto = UMASS_PROTO_SCSI, - .quirks = NO_GETMAXLUN - }, - /* Panasonic CD-R Drive KXL-840AN */ - { .vendor = 0x04da, .product = 0x0d01, .release = WILDCARD_ID, - .proto = UMASS_PROTO_ATAPI | UMASS_PROTO_BBB, - .quirks = NO_GETMAXLUN - }, - /* Panasonic CD-R Drive KXL-CB20AN */ - { .vendor = 0x04da, .product = 0x0d0a, .release = WILDCARD_ID, - .proto = UMASS_PROTO_SCSI | UMASS_PROTO_BBB, - .quirks = NO_QUIRKS - }, - /* Panasonic DVD-ROM & CD-R/RW */ - { .vendor = 0x04da, .product = 0x0d0e, .release = WILDCARD_ID, - .proto = UMASS_PROTO_SCSI | UMASS_PROTO_BBB, - .quirks = NO_QUIRKS - }, - /* Panasonic LS-120 Camera */ - { .vendor = 0x04da, .product = 0x0901, .release = WILDCARD_ID, - .proto = UMASS_PROTO_UFI, - .quirks = NO_QUIRKS - }, - /* Plextor PlexWriter 40/12/40U */ - { .vendor = 0x093b, .product = 0x0011, .release = WILDCARD_ID, - .proto = UMASS_PROTO_SCSI | UMASS_PROTO_BBB, - .quirks = NO_TEST_UNIT_READY - }, - /* PNY USB 2.0 Flash */ - { .vendor = 0x154b, .product = 0x0010, .release = WILDCARD_ID, - .proto = UMASS_PROTO_SCSI | UMASS_PROTO_BBB, - .quirks = IGNORE_RESIDUE | NO_START_STOP - }, - /* Pen USB 2.0 Flash Drive */ - { .vendor = 0x0d7d, .product = 0x1300, .release = WILDCARD_ID, - .proto = UMASS_PROTO_SCSI | UMASS_PROTO_BBB, - .quirks = IGNORE_RESIDUE - }, - /* Samsung YP-U2 MP3 Player */ - { .vendor = 0x04e8, .product = 0x5050, .release = WILDCARD_ID, - .proto = UMASS_PROTO_SCSI | UMASS_PROTO_BBB, - .quirks = SHUTTLE_INIT | NO_GETMAXLUN - }, - /* Samsung Digimax 410 */ - { .vendor = 0x0839, .product = 0x000a, .release = WILDCARD_ID, - .proto = UMASS_PROTO_SCSI | UMASS_PROTO_BBB, - .quirks = NO_INQUIRY - }, - /* SanDisk ImageMate SDDR-05a */ - { .vendor = 0x0781, .product = 0x0001, .release = WILDCARD_ID, - .proto = UMASS_PROTO_SCSI | UMASS_PROTO_CBI, - .quirks = READ_CAPACITY_OFFBY1 | NO_GETMAXLUN - }, - /* SanDisk ImageMate SDDR-09 */ - { .vendor = 0x0781, .product = 0x0200, .release = WILDCARD_ID, - .proto = UMASS_PROTO_SCSI, - .quirks = READ_CAPACITY_OFFBY1 | NO_GETMAXLUN - }, - /* SanDisk ImageMate SDDR-12 */ - { .vendor = 0x0781, .product = 0x0100, .release = WILDCARD_ID, - .proto = UMASS_PROTO_SCSI | UMASS_PROTO_CBI, - .quirks = READ_CAPACITY_OFFBY1 | NO_GETMAXLUN - }, - /* SanDisk ImageMate SDDR-31 */ - { .vendor = 0x0781, .product = 0x0002, .release = WILDCARD_ID, - .proto = UMASS_PROTO_SCSI | UMASS_PROTO_BBB, - .quirks = READ_CAPACITY_OFFBY1 - }, - /* SanDisk Cruzer Mini 256MB */ - { .vendor = 0x0781, .product = 0x7104, .release = WILDCARD_ID, - .proto = UMASS_PROTO_SCSI | UMASS_PROTO_BBB, - .quirks = IGNORE_RESIDUE - }, - /* SanDisk Cruzer Micro 128MB */ - { .vendor = 0x0781, .product = 0x7112, .release = WILDCARD_ID, - .proto = UMASS_PROTO_SCSI | UMASS_PROTO_BBB, - .quirks = IGNORE_RESIDUE - }, - /* SanDisk Cruzer Micro 256MB */ - { .vendor = 0x0781, .product = 0x7113, .release = WILDCARD_ID, - .proto = UMASS_PROTO_SCSI | UMASS_PROTO_BBB, - .quirks = IGNORE_RESIDUE - }, - /* ScanLogic SL11R IDE Adapter */ - { .vendor = 0x04ce, .product = 0x0002, .release = WILDCARD_ID, - .proto = UMASS_PROTO_ATAPI | UMASS_PROTO_CBI_I, - .quirks = NO_QUIRKS - }, - /* Shuttle CD-RW Device */ - { .vendor = 0x04e6, .product = 0x0101, .release = WILDCARD_ID, - .proto = UMASS_PROTO_ATAPI | UMASS_PROTO_CBI, - .quirks = NO_QUIRKS - }, - /* Shuttle eUSB CompactFlash Adapter */ - { .vendor = 0x04e6, .product = 0x000a, .release = WILDCARD_ID, - .proto = UMASS_PROTO_ATAPI | UMASS_PROTO_CBI, - .quirks = NO_QUIRKS - }, - /* Shuttle E-USB Bridge */ - { .vendor = 0x04e6, .product = 0x0001, .release = WILDCARD_ID, - .proto = UMASS_PROTO_ATAPI | UMASS_PROTO_CBI_I, - .quirks = NO_TEST_UNIT_READY | NO_START_STOP | SHUTTLE_INIT - }, - /* Shuttle eUSB ATA/ATAPI Adapter */ - { .vendor = 0x04e6, .product = 0x0009, .release = WILDCARD_ID, - .proto = UMASS_PROTO_ATAPI | UMASS_PROTO_CBI, - .quirks = NO_QUIRKS - }, - /* Shuttle eUSB SmartMedia / */ - { .vendor = 0x04e6, .product = 0x0005, .release = WILDCARD_ID, - .proto = UMASS_PROTO_SCSI, - .quirks = NO_QUIRKS - }, - /* Shuttle eUSCSI Bridge */ - { .vendor = 0x04e6, .product = 0x0002, .release = WILDCARD_ID, - .proto = UMASS_PROTO_SCSI | UMASS_PROTO_BBB, - .quirks = NO_QUIRKS - }, - /* Shuttle Sony Hifd */ - { .vendor = 0x04e6, .product = 0x0007, .release = WILDCARD_ID, - .proto = UMASS_PROTO_SCSI | UMASS_PROTO_CBI, - .quirks = NO_GETMAXLUN - }, - /* Shuttle ImageMate SDDR09 */ - { .vendor = 0x04e6, .product = 0x0003, .release = WILDCARD_ID, - .proto = UMASS_PROTO_SCSI, - .quirks = NO_GETMAXLUN - }, - /* Shuttle eUSB MultiMediaCard Adapter */ - { .vendor = 0x04e6, .product = 0x0006, .release = WILDCARD_ID, - .proto = UMASS_PROTO_SCSI | UMASS_PROTO_CBI, - .quirks = NO_GETMAXLUN - }, - /* Sigmatel i-Bead 100 MP3 */ - { .vendor = 0x066f, .product = 0x8008, .release = WILDCARD_ID, - .proto = UMASS_PROTO_SCSI | UMASS_PROTO_BBB, - .quirks = SHUTTLE_INIT - }, - /* SIIG WINTERREADER Reader */ - { .vendor = 0x07cc, .product = 0x0330, .release = WILDCARD_ID, - .proto = UMASS_PROTO_SCSI | UMASS_PROTO_BBB, - .quirks = IGNORE_RESIDUE - }, - /* Skanhex MD 7425 Camera */ - { .vendor = 0x0d96, .product = 0x410a, .release = WILDCARD_ID, - .proto = UMASS_PROTO_SCSI | UMASS_PROTO_BBB, - .quirks = NO_INQUIRY - }, - /* Skanhex SX 520z Camera */ - { .vendor = 0x0d96, .product = 0x5200, .release = WILDCARD_ID, - .proto = UMASS_PROTO_SCSI | UMASS_PROTO_BBB, - .quirks = NO_INQUIRY - }, - /* Sony Clie v4.0 */ - { .vendor = 0x054c, .product = 0x006d, .release = WILDCARD_ID, - .proto = UMASS_PROTO_SCSI | UMASS_PROTO_BBB, - .quirks = NO_INQUIRY - }, - /* Sony DSC cameras */ - { .vendor = 0x054c, .product = 0x0010, .release = WILDCARD_ID, - .proto = UMASS_PROTO_RBC | UMASS_PROTO_CBI, - .quirks = NO_QUIRKS - }, - { .vendor = 0x054c, .product = 0x02f7, .release = WILDCARD_ID, - .proto = UMASS_PROTO_RBC | UMASS_PROTO_CBI, - .quirks = NO_QUIRKS - }, - /* Sony Handycam */ - { .vendor = 0x054c, .product = 0x002e, .release = WILDCARD_ID, - .proto = UMASS_PROTO_RBC | UMASS_PROTO_CBI, - .quirks = NO_QUIRKS - }, - /* Sony Memorystick MSC-U03 */ - { .vendor = 0x054c, .product = 0x0069, .release = WILDCARD_ID, - .proto = UMASS_PROTO_UFI | UMASS_PROTO_CBI, - .quirks = NO_GETMAXLUN - }, - /* Sony Memorystick NW-MS7 */ - { .vendor = 0x054c, .product = 0x0025, .release = WILDCARD_ID, - .proto = UMASS_PROTO_SCSI | UMASS_PROTO_BBB, - .quirks = NO_GETMAXLUN - }, - /* Sony PEG N760c Memorystick */ - { .vendor = 0x054c, .product = 0x0058, .release = WILDCARD_ID, - .proto = UMASS_PROTO_SCSI | UMASS_PROTO_BBB, - .quirks = NO_INQUIRY - }, - /* Sony Memorystick MSAC-US1 */ - { .vendor = 0x054c, .product = 0x002d, .release = WILDCARD_ID, - .proto = UMASS_PROTO_SCSI | UMASS_PROTO_BBB, - .quirks = NO_GETMAXLUN - }, - /* Sony MSC memory stick */ - { .vendor = 0x054c, .product = 0x0032, .release = WILDCARD_ID, - .proto = UMASS_PROTO_RBC | UMASS_PROTO_CBI, - .quirks = NO_QUIRKS - }, - /* Sony Portable USB Harddrive */ - { .vendor = 0x054c, .product = 0x002b, .release = WILDCARD_ID, - .proto = UMASS_PROTO_SCSI | UMASS_PROTO_BBB, - .quirks = NO_QUIRKS - }, - /* Taugagreining CameraMate (DPCM_USB) */ - { .vendor = 0x0436, .product = 0x0005, .release = WILDCARD_ID, - .proto = UMASS_PROTO_SCSI, - .quirks = NO_QUIRKS - }, - /* TEAC FD-05PUB floppy */ - { .vendor = 0x0644, .product = 0x0000, .release = WILDCARD_ID, - .proto = UMASS_PROTO_UFI | UMASS_PROTO_CBI, - .quirks = NO_QUIRKS - }, - /* Trek IBM USB Memory */ - { .vendor = 0x0a16, .product = 0x8888, .release = WILDCARD_ID, - .proto = UMASS_PROTO_SCSI | UMASS_PROTO_BBB, - .quirks = NO_INQUIRY - }, - /* Trek ThumbDrive_8MB */ - { .vendor = 0x0a16, .product = 0x9988, .release = WILDCARD_ID, - .proto = UMASS_PROTO_ATAPI | UMASS_PROTO_BBB, - .quirks = IGNORE_RESIDUE - }, - /* Trumpion Comotron C3310 MP3 */ - { .vendor = 0x090a, .product = 0x1100, .release = WILDCARD_ID, - .proto = UMASS_PROTO_UFI | UMASS_PROTO_CBI, - .quirks = NO_QUIRKS - }, - /* Trumpion MP3 player */ - { .vendor = 0x090a, .product = 0x1200, .release = WILDCARD_ID, - .proto = UMASS_PROTO_RBC, - .quirks = NO_QUIRKS - }, - /* Trumpion T33520 USB Flash */ - { .vendor = 0x090a, .product = 0x1001, .release = WILDCARD_ID, - .proto = UMASS_PROTO_SCSI, - .quirks = NO_QUIRKS - }, - /* TwinMOS Memory Disk IV */ - { .vendor = 0x126f, .product = 0x1325, .release = WILDCARD_ID, - .proto = UMASS_PROTO_SCSI | UMASS_PROTO_BBB, - .quirks = NO_QUIRKS - }, - /* Vivitar Vivicam 35Xx */ - { .vendor = 0x0636, .product = 0x0003, .release = WILDCARD_ID, - .proto = UMASS_PROTO_SCSI | UMASS_PROTO_BBB, - .quirks = NO_INQUIRY - }, - /* Western Firewire USB Combo */ - { .vendor = 0x1058, .product = 0x0200, .release = WILDCARD_ID, - .proto = UMASS_PROTO_SCSI | UMASS_PROTO_BBB, - .quirks = FORCE_SHORT_INQUIRY | NO_START_STOP | IGNORE_RESIDUE - }, - /* Western External USB HHD My Passport */ - { .vendor = 0x1058, .product = 0x0704, .release = WILDCARD_ID, - .proto = UMASS_PROTO_SCSI | UMASS_PROTO_BBB, - .quirks = FORCE_SHORT_INQUIRY | NO_START_STOP | IGNORE_RESIDUE - }, - /* Western External HDD */ - { .vendor = 0x1058, .product = 0x0400, .release = WILDCARD_ID, - .proto = UMASS_PROTO_SCSI | UMASS_PROTO_BBB, - .quirks = FORCE_SHORT_INQUIRY | NO_START_STOP | IGNORE_RESIDUE - }, - /* Western MyBook External HDD */ - { .vendor = 0x1058, .product = 0x0901, .release = WILDCARD_ID, - .proto = UMASS_PROTO_SCSI | UMASS_PROTO_BBB, - .quirks = NO_INQUIRY_EVPD - }, - /* WinMaxGroup USB Flash Disk */ - { .vendor = 0x0ed1, .product = 0x6660, .release = WILDCARD_ID, - .proto = UMASS_PROTO_SCSI | UMASS_PROTO_BBB, - .quirks = NO_INQUIRY - }, - /* Yano METALWEAR-HDD */ - { .vendor = 0x094f, .product = 0x05fc, .release = WILDCARD_ID, - .proto = UMASS_PROTO_SCSI | UMASS_PROTO_BBB, - .quirks = FORCE_SHORT_INQUIRY | NO_START_STOP | IGNORE_RESIDUE - }, - /* Yano U640MO-03 */ - { .vendor = 0x094f, .product = 0x0101, .release = WILDCARD_ID, - .proto = UMASS_PROTO_ATAPI | UMASS_PROTO_CBI_I, - .quirks = FORCE_SHORT_INQUIRY - }, - /* Y-E Flashbuster-U */ - { .vendor = 0x057b, .product = 0x0000, .release = WILDCARD_ID, - .proto = UMASS_PROTO_SCSI | UMASS_PROTO_CBI, - .quirks = NO_GETMAXLUN - }, - /* Zoran Digital Camera EX-20 */ - { .vendor = 0x0595, .product = 0x4343, .release = WILDCARD_ID, - .proto = UMASS_PROTO_ATAPI | UMASS_PROTO_CBI, - .quirks = NO_QUIRKS - }, - { .vendor = EOT_ID, .product = EOT_ID, .release = EOT_ID, - .proto = 0, .quirks = 0 } -}; - - -/* the per device structure */ -struct umass_softc { - device_t sc_dev; /* base device */ - usbd_device_handle sc_udev; /* USB device */ - - struct cam_sim *umass_sim; /* SCSI Interface Module */ - - unsigned char flags; /* various device flags */ -# define UMASS_FLAGS_GONE 0x01 /* devices is no more */ - - u_int16_t proto; /* wire and cmd protocol */ - u_int16_t quirks; /* they got it almost right */ - - usbd_interface_handle iface; /* Mass Storage interface */ - int ifaceno; /* MS iface number */ - - u_int8_t bulkin; /* bulk-in Endpoint Address */ - u_int8_t bulkout; /* bulk-out Endpoint Address */ - u_int8_t intrin; /* intr-in Endp. (CBI) */ - usbd_pipe_handle bulkin_pipe; - usbd_pipe_handle bulkout_pipe; - usbd_pipe_handle intrin_pipe; - - /* Reset the device in a wire protocol specific way */ - wire_reset_f reset; - - /* The start of a wire transfer. It prepares the whole transfer (cmd, - * data, and status stage) and initiates it. It is up to the state - * machine (below) to handle the various stages and errors in these - */ - wire_transfer_f transfer; - - /* The state machine, handling the various states during a transfer */ - wire_state_f state; - - /* The command transform function is used to conver the SCSI commands - * into their derivatives, like UFI, ATAPI, and friends. - */ - command_transform_f transform; /* command transform */ - - /* Bulk specific variables for transfers in progress */ - umass_bbb_cbw_t cbw; /* command block wrapper */ - umass_bbb_csw_t csw; /* command status wrapper*/ - /* CBI specific variables for transfers in progress */ - umass_cbi_cbl_t cbl; /* command block */ - umass_cbi_sbl_t sbl; /* status block */ - - /* generic variables for transfers in progress */ - /* ctrl transfer requests */ - usb_device_request_t request; - - /* xfer handles - * Most of our operations are initiated from interrupt context, so - * we need to avoid using the one that is in use. We want to avoid - * allocating them in the interrupt context as well. - */ - /* indices into array below */ -# define XFER_BBB_CBW 0 /* Bulk-Only */ -# define XFER_BBB_DATA 1 -# define XFER_BBB_DCLEAR 2 -# define XFER_BBB_CSW1 3 -# define XFER_BBB_CSW2 4 -# define XFER_BBB_SCLEAR 5 -# define XFER_BBB_RESET1 6 -# define XFER_BBB_RESET2 7 -# define XFER_BBB_RESET3 8 - -# define XFER_CBI_CB 0 /* CBI */ -# define XFER_CBI_DATA 1 -# define XFER_CBI_STATUS 2 -# define XFER_CBI_DCLEAR 3 -# define XFER_CBI_SCLEAR 4 -# define XFER_CBI_RESET1 5 -# define XFER_CBI_RESET2 6 -# define XFER_CBI_RESET3 7 - -# define XFER_NR 9 /* maximum number */ - - usbd_xfer_handle transfer_xfer[XFER_NR]; /* for ctrl xfers */ - - int transfer_dir; /* data direction */ - void *transfer_data; /* data buffer */ - int transfer_datalen; /* (maximum) length */ - int transfer_actlen; /* actual length */ - transfer_cb_f transfer_cb; /* callback */ - void *transfer_priv; /* for callback */ - int transfer_status; - - int transfer_state; -# define TSTATE_ATTACH 0 /* in attach */ -# define TSTATE_IDLE 1 -# define TSTATE_BBB_COMMAND 2 /* CBW transfer */ -# define TSTATE_BBB_DATA 3 /* Data transfer */ -# define TSTATE_BBB_DCLEAR 4 /* clear endpt stall */ -# define TSTATE_BBB_STATUS1 5 /* clear endpt stall */ -# define TSTATE_BBB_SCLEAR 6 /* clear endpt stall */ -# define TSTATE_BBB_STATUS2 7 /* CSW transfer */ -# define TSTATE_BBB_RESET1 8 /* reset command */ -# define TSTATE_BBB_RESET2 9 /* in clear stall */ -# define TSTATE_BBB_RESET3 10 /* out clear stall */ -# define TSTATE_CBI_COMMAND 11 /* command transfer */ -# define TSTATE_CBI_DATA 12 /* data transfer */ -# define TSTATE_CBI_STATUS 13 /* status transfer */ -# define TSTATE_CBI_DCLEAR 14 /* clear ep stall */ -# define TSTATE_CBI_SCLEAR 15 /* clear ep stall */ -# define TSTATE_CBI_RESET1 16 /* reset command */ -# define TSTATE_CBI_RESET2 17 /* in clear stall */ -# define TSTATE_CBI_RESET3 18 /* out clear stall */ -# define TSTATE_STATES 19 /* # of states above */ - - - /* SCSI/CAM specific variables */ - unsigned char cam_scsi_command[CAM_MAX_CDBLEN]; - unsigned char cam_scsi_command2[CAM_MAX_CDBLEN]; - struct scsi_sense cam_scsi_sense; - struct scsi_sense cam_scsi_test_unit_ready; - int timeout; /* in msecs */ - - int maxlun; /* maximum LUN number */ - struct callout rescan_timeout; -}; - -#ifdef USB_DEBUG -char *states[TSTATE_STATES+1] = { - /* should be kept in sync with the list at transfer_state */ - "Attach", - "Idle", - "BBB CBW", - "BBB Data", - "BBB Data bulk-in/-out clear stall", - "BBB CSW, 1st attempt", - "BBB CSW bulk-in clear stall", - "BBB CSW, 2nd attempt", - "BBB Reset", - "BBB bulk-in clear stall", - "BBB bulk-out clear stall", - "CBI Command", - "CBI Data", - "CBI Status", - "CBI Data bulk-in/-out clear stall", - "CBI Status intr-in clear stall", - "CBI Reset", - "CBI bulk-in clear stall", - "CBI bulk-out clear stall", - NULL -}; -#endif - -/* If device cannot return valid inquiry data, fake it */ -static uint8_t fake_inq_data[SHORT_INQUIRY_LENGTH] = { - 0, /*removable*/ 0x80, SCSI_REV_2, SCSI_REV_2, - /*additional_length*/ 31, 0, 0, 0 -}; - -/* USB device probe/attach/detach functions */ -static device_probe_t umass_match; -static device_attach_t umass_attach; -static device_detach_t umass_detach; - -static devclass_t umass_devclass; - -static kobj_method_t umass_methods[] = { - DEVMETHOD(device_probe, umass_match), - DEVMETHOD(device_attach, umass_attach), - DEVMETHOD(device_detach, umass_detach), - DEVMETHOD_END -}; - -static driver_t umass_driver = { - "umass", - umass_methods, - sizeof(struct umass_softc) -}; - -MODULE_DEPEND(umass, usb, 1, 1, 1); - -static int umass_match_proto (struct umass_softc *sc, - usbd_interface_handle iface, - usbd_device_handle udev); - -/* quirk functions */ -static void umass_init_shuttle (struct umass_softc *sc); - -/* generic transfer functions */ -static usbd_status umass_setup_transfer (struct umass_softc *sc, - usbd_pipe_handle pipe, - void *buffer, int buflen, int flags, - usbd_xfer_handle xfer); -static usbd_status umass_setup_ctrl_transfer (struct umass_softc *sc, - usbd_device_handle udev, - usb_device_request_t *req, - void *buffer, int buflen, int flags, - usbd_xfer_handle xfer); -static void umass_clear_endpoint_stall (struct umass_softc *sc, - u_int8_t endpt, usbd_pipe_handle pipe, - int state, usbd_xfer_handle xfer); -static void umass_reset (struct umass_softc *sc, - transfer_cb_f cb, void *priv); - -/* Bulk-Only related functions */ -static void umass_bbb_reset (struct umass_softc *sc, int status); -static void umass_bbb_transfer (struct umass_softc *sc, int lun, - void *cmd, int cmdlen, - void *data, int datalen, int dir, u_int timeout, - transfer_cb_f cb, void *priv); -static void umass_bbb_state (usbd_xfer_handle xfer, - usbd_private_handle priv, - usbd_status err); -static int umass_bbb_get_max_lun - (struct umass_softc *sc); - -/* CBI related functions */ -static int umass_cbi_adsc (struct umass_softc *sc, - char *buffer, int buflen, - usbd_xfer_handle xfer); -static void umass_cbi_reset (struct umass_softc *sc, int status); -static void umass_cbi_transfer (struct umass_softc *sc, int lun, - void *cmd, int cmdlen, - void *data, int datalen, int dir, u_int timeout, - transfer_cb_f cb, void *priv); -static void umass_cbi_state (usbd_xfer_handle xfer, - usbd_private_handle priv, usbd_status err); - -/* CAM related functions */ -static void umass_cam_action (struct cam_sim *sim, union ccb *ccb); -static void umass_cam_poll (struct cam_sim *sim); - -static void umass_cam_cb (struct umass_softc *sc, void *priv, - int residue, int status); -static void umass_cam_sense_cb (struct umass_softc *sc, void *priv, - int residue, int status); -static void umass_cam_quirk_cb (struct umass_softc *sc, void *priv, - int residue, int status); - -static void umass_cam_rescan_callback - (struct cam_periph *periph,union ccb *ccb); -static void umass_cam_rescan (void *addr); - -static int umass_cam_attach_sim (struct umass_softc *sc); -static int umass_cam_attach (struct umass_softc *sc); -static int umass_cam_detach_sim (struct umass_softc *sc); - - -/* SCSI specific functions */ -static int umass_scsi_transform (struct umass_softc *sc, - unsigned char *cmd, int cmdlen, - unsigned char **rcmd, int *rcmdlen); - -/* UFI specific functions */ -#define UFI_COMMAND_LENGTH 12 /* UFI commands are always 12 bytes */ -static int umass_ufi_transform (struct umass_softc *sc, - unsigned char *cmd, int cmdlen, - unsigned char **rcmd, int *rcmdlen); - -/* ATAPI (8070i) specific functions */ -#define ATAPI_COMMAND_LENGTH 12 /* ATAPI commands are always 12 bytes */ -static int umass_atapi_transform (struct umass_softc *sc, - unsigned char *cmd, int cmdlen, - unsigned char **rcmd, int *rcmdlen); - -/* RBC specific functions */ -static int umass_rbc_transform (struct umass_softc *sc, - unsigned char *cmd, int cmdlen, - unsigned char **rcmd, int *rcmdlen); - -#ifdef USB_DEBUG -/* General debugging functions */ -static void umass_bbb_dump_cbw (struct umass_softc *sc, umass_bbb_cbw_t *cbw); -static void umass_bbb_dump_csw (struct umass_softc *sc, umass_bbb_csw_t *csw); -static void umass_cbi_dump_cmd (struct umass_softc *sc, void *cmd, int cmdlen); -static void umass_dump_buffer (struct umass_softc *sc, u_int8_t *buffer, - int buflen, int printlen); -#endif - -MODULE_DEPEND(umass, cam, 1,1,1); - -/* - * USB device probe/attach/detach - */ - -/* - * Match the device we are seeing with the devices supported. Fill in the - * description in the softc accordingly. This function is called from both - * probe and attach. - */ - -static int -umass_match_proto(struct umass_softc *sc, usbd_interface_handle iface, - usbd_device_handle udev) -{ - usb_device_descriptor_t *dd; - usb_interface_descriptor_t *id; - int i; - int found = 0; - - sc->sc_udev = udev; - sc->proto = 0; - sc->quirks = 0; - - dd = usbd_get_device_descriptor(udev); - - /* An entry specifically for Y-E Data devices as they don't fit in the - * device description table. - */ - if (UGETW(dd->idVendor) == 0x057b && UGETW(dd->idProduct) == 0x0000) { - - /* Revisions < 1.28 do not handle the inerrupt endpoint - * very well. - */ - if (UGETW(dd->bcdDevice) < 0x128) { - sc->proto = UMASS_PROTO_UFI | UMASS_PROTO_CBI; - } else { - sc->proto = UMASS_PROTO_UFI | UMASS_PROTO_CBI_I; - } - - /* - * Revisions < 1.28 do not have the TEST UNIT READY command - * Revisions == 1.28 have a broken TEST UNIT READY - */ - if (UGETW(dd->bcdDevice) <= 0x128) - sc->quirks |= NO_TEST_UNIT_READY; - - sc->quirks |= RS_NO_CLEAR_UA | FLOPPY_SPEED; - return(UMATCH_VENDOR_PRODUCT); - } - - /* Check the list of supported devices for a match. While looking, - * check for wildcarded and fully matched. First match wins. - */ - for (i = 0; umass_devdescrs[i].vendor != EOT_ID && !found; i++) { - if (umass_devdescrs[i].vendor == WILDCARD_ID && - umass_devdescrs[i].product == WILDCARD_ID && - umass_devdescrs[i].release == WILDCARD_ID) { - kprintf("umass: ignoring invalid wildcard quirk\n"); - continue; - } - if ((umass_devdescrs[i].vendor == UGETW(dd->idVendor) || - umass_devdescrs[i].vendor == WILDCARD_ID) - && (umass_devdescrs[i].product == UGETW(dd->idProduct) || - umass_devdescrs[i].product == WILDCARD_ID)) { - if (umass_devdescrs[i].release == WILDCARD_ID) { - sc->proto = umass_devdescrs[i].proto; - sc->quirks = umass_devdescrs[i].quirks; - return (UMATCH_VENDOR_PRODUCT); - } else if (umass_devdescrs[i].release == - UGETW(dd->bcdDevice)) { - sc->proto = umass_devdescrs[i].proto; - sc->quirks = umass_devdescrs[i].quirks; - return (UMATCH_VENDOR_PRODUCT_REV); - } /* else RID does not match */ - } - } - - /* Check for a standards compliant device */ - - id = usbd_get_interface_descriptor(iface); - if (id == NULL || id->bInterfaceClass != UICLASS_MASS) - return(UMATCH_NONE); - - switch (id->bInterfaceSubClass) { - case UISUBCLASS_SCSI: - sc->proto |= UMASS_PROTO_SCSI; - break; - case UISUBCLASS_UFI: - sc->proto |= UMASS_PROTO_UFI; - break; - case UISUBCLASS_RBC: - sc->proto |= UMASS_PROTO_RBC; - break; - case UISUBCLASS_SFF8020I: - case UISUBCLASS_SFF8070I: - sc->proto |= UMASS_PROTO_ATAPI; - break; - default: - DPRINTF(UDMASS_GEN, ("%s: Unsupported command protocol %d\n", - device_get_nameunit(sc->sc_dev), id->bInterfaceSubClass)); - return(UMATCH_NONE); - } - - switch (id->bInterfaceProtocol) { - case UIPROTO_MASS_CBI: - sc->proto |= UMASS_PROTO_CBI; - break; - case UIPROTO_MASS_CBI_I: - sc->proto |= UMASS_PROTO_CBI_I; - break; - case UIPROTO_MASS_BBB_OLD: - case UIPROTO_MASS_BBB: - sc->proto |= UMASS_PROTO_BBB; - break; - default: - DPRINTF(UDMASS_GEN, ("%s: Unsupported wire protocol %d\n", - device_get_nameunit(sc->sc_dev), id->bInterfaceProtocol)); - return(UMATCH_NONE); - } - - return(UMATCH_DEVCLASS_DEVSUBCLASS_DEVPROTO); -} - -static int -umass_match(device_t self) -{ - struct usb_attach_arg *uaa = device_get_ivars(self); - struct umass_softc *sc = device_get_softc(self); - - sc->sc_dev = self; - - if (uaa->iface == NULL) - return(UMATCH_NONE); - - return(umass_match_proto(sc, uaa->iface, uaa->device)); -} - -static int -umass_attach(device_t self) -{ - struct umass_softc *sc = device_get_softc(self); - struct usb_attach_arg *uaa = device_get_ivars(self); - usb_interface_descriptor_t *id; - usb_endpoint_descriptor_t *ed; - int i; - int err; - - /* - * the softc struct is bzero-ed in device_set_driver. We can safely - * call umass_detach without specifically initialising the struct. - */ - - sc->sc_dev = self; - - sc->iface = uaa->iface; - sc->ifaceno = uaa->ifaceno; - - /* initialise the proto and drive values in the umass_softc (again) */ - (void) umass_match_proto(sc, sc->iface, uaa->device); - - id = usbd_get_interface_descriptor(sc->iface); -#ifdef USB_DEBUG - kprintf("%s: ", device_get_nameunit(sc->sc_dev)); - switch (sc->proto&UMASS_PROTO_COMMAND) { - case UMASS_PROTO_SCSI: - kprintf("SCSI"); - break; - case UMASS_PROTO_ATAPI: - kprintf("8070i (ATAPI)"); - break; - case UMASS_PROTO_UFI: - kprintf("UFI"); - break; - case UMASS_PROTO_RBC: - kprintf("RBC"); - break; - default: - kprintf("(unknown 0x%02x)", sc->proto&UMASS_PROTO_COMMAND); - break; - } - kprintf(" over "); - switch (sc->proto&UMASS_PROTO_WIRE) { - case UMASS_PROTO_BBB: - kprintf("Bulk-Only"); - break; - case UMASS_PROTO_CBI: /* uses Comand/Bulk pipes */ - kprintf("CBI"); - break; - case UMASS_PROTO_CBI_I: /* uses Comand/Bulk/Interrupt pipes */ - kprintf("CBI with CCI"); -#ifndef CBI_I - kprintf(" (using CBI)"); -#endif - break; - default: - kprintf("(unknown 0x%02x)", sc->proto&UMASS_PROTO_WIRE); - } - kprintf("; quirks = 0x%04x\n", sc->quirks); -#endif - -#ifndef CBI_I - if (sc->proto & UMASS_PROTO_CBI_I) { - /* See beginning of file for comment on the use of CBI with CCI */ - sc->proto = (sc->proto & ~UMASS_PROTO_CBI_I) | UMASS_PROTO_CBI; - } -#endif - - if (sc->quirks & ALT_IFACE_1) { - err = usbd_set_interface(0, 1); - if (err) { - DPRINTF(UDMASS_USB, ("%s: could not switch to " - "Alt Interface %d\n", - device_get_nameunit(sc->sc_dev), 1)); - umass_detach(self); - return ENXIO; - } - } - - /* - * In addition to the Control endpoint the following endpoints - * are required: - * a) bulk-in endpoint. - * b) bulk-out endpoint. - * and for Control/Bulk/Interrupt with CCI (CBI_I) - * c) intr-in - * - * The endpoint addresses are not fixed, so we have to read them - * from the device descriptors of the current interface. - */ - for (i = 0 ; i < id->bNumEndpoints ; i++) { - ed = usbd_interface2endpoint_descriptor(sc->iface, i); - if (!ed) { - kprintf("%s: could not read endpoint descriptor\n", - device_get_nameunit(sc->sc_dev)); - return ENXIO; - } - if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN - && (ed->bmAttributes & UE_XFERTYPE) == UE_BULK) { - sc->bulkin = ed->bEndpointAddress; - } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT - && (ed->bmAttributes & UE_XFERTYPE) == UE_BULK) { - sc->bulkout = ed->bEndpointAddress; - } else if (sc->proto & UMASS_PROTO_CBI_I - && UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN - && (ed->bmAttributes & UE_XFERTYPE) == UE_INTERRUPT) { - sc->intrin = ed->bEndpointAddress; -#ifdef USB_DEBUG - if (UGETW(ed->wMaxPacketSize) > 2) { - DPRINTF(UDMASS_CBI, ("%s: intr size is %d\n", - device_get_nameunit(sc->sc_dev), - UGETW(ed->wMaxPacketSize))); - } -#endif - } - } - - /* check whether we found all the endpoints we need */ - if (!sc->bulkin || !sc->bulkout - || (sc->proto & UMASS_PROTO_CBI_I && !sc->intrin) ) { - DPRINTF(UDMASS_USB, ("%s: endpoint not found %d/%d/%d\n", - device_get_nameunit(sc->sc_dev), - sc->bulkin, sc->bulkout, sc->intrin)); - umass_detach(self); - return ENXIO; - } - - /* Open the bulk-in and -out pipe */ - err = usbd_open_pipe(sc->iface, sc->bulkout, - USBD_EXCLUSIVE_USE, &sc->bulkout_pipe); - if (err) { - DPRINTF(UDMASS_USB, ("%s: cannot open %d-out pipe (bulk)\n", - device_get_nameunit(sc->sc_dev), sc->bulkout)); - umass_detach(self); - return ENXIO; - } - err = usbd_open_pipe(sc->iface, sc->bulkin, - USBD_EXCLUSIVE_USE, &sc->bulkin_pipe); - if (err) { - DPRINTF(UDMASS_USB, ("%s: could not open %d-in pipe (bulk)\n", - device_get_nameunit(sc->sc_dev), sc->bulkin)); - umass_detach(self); - return ENXIO; - } - /* Open the intr-in pipe if the protocol is CBI with CCI. - * Note: early versions of the Zip drive do have an interrupt pipe, but - * this pipe is unused - * - * We do not open the interrupt pipe as an interrupt pipe, but as a - * normal bulk endpoint. We send an IN transfer down the wire at the - * appropriate time, because we know exactly when to expect data on - * that endpoint. This saves bandwidth, but more important, makes the - * code for handling the data on that endpoint simpler. No data - * arriving concurently. - */ - if (sc->proto & UMASS_PROTO_CBI_I) { - err = usbd_open_pipe(sc->iface, sc->intrin, - USBD_EXCLUSIVE_USE, &sc->intrin_pipe); - if (err) { - DPRINTF(UDMASS_USB, ("%s: couldn't open %d-in (intr)\n", - device_get_nameunit(sc->sc_dev), sc->intrin)); - umass_detach(self); - return ENXIO; - } - } - - /* initialisation of generic part */ - sc->transfer_state = TSTATE_ATTACH; - - /* request a sufficient number of xfer handles */ - for (i = 0; i < XFER_NR; i++) { - sc->transfer_xfer[i] = usbd_alloc_xfer(uaa->device); - if (!sc->transfer_xfer[i]) { - DPRINTF(UDMASS_USB, ("%s: Out of memory\n", - device_get_nameunit(sc->sc_dev))); - umass_detach(self); - return ENXIO; - } - } - - /* - * Preallocate buffers to avoid auto-allocation from an interrupt - * handler. - */ - usbd_alloc_buffer(sc->transfer_xfer[XFER_BBB_DATA], - MAXPHYS); - usbd_alloc_buffer(sc->transfer_xfer[XFER_BBB_CBW], - UMASS_BBB_CBW_SIZE); - usbd_alloc_buffer(sc->transfer_xfer[XFER_BBB_CSW1], - UMASS_BBB_CSW_SIZE); - usbd_alloc_buffer(sc->transfer_xfer[XFER_BBB_CSW2], - UMASS_BBB_CSW_SIZE); - usbd_alloc_buffer(sc->transfer_xfer[XFER_CBI_DATA], - MAXPHYS); - - /* Initialise the wire protocol specific methods */ - if (sc->proto & UMASS_PROTO_BBB) { - sc->reset = umass_bbb_reset; - sc->transfer = umass_bbb_transfer; - sc->state = umass_bbb_state; - } else if (sc->proto & (UMASS_PROTO_CBI|UMASS_PROTO_CBI_I)) { - sc->reset = umass_cbi_reset; - sc->transfer = umass_cbi_transfer; - sc->state = umass_cbi_state; -#ifdef USB_DEBUG - } else { - panic("%s:%d: Unknown proto 0x%02x", - __FILE__, __LINE__, sc->proto); -#endif - } - - if (sc->proto & UMASS_PROTO_SCSI) - sc->transform = umass_scsi_transform; - else if (sc->proto & UMASS_PROTO_UFI) - sc->transform = umass_ufi_transform; - else if (sc->proto & UMASS_PROTO_ATAPI) - sc->transform = umass_atapi_transform; - else if (sc->proto & UMASS_PROTO_RBC) - sc->transform = umass_rbc_transform; -#ifdef USB_DEBUG - else - panic("No transformation defined for command proto 0x%02x", - sc->proto & UMASS_PROTO_COMMAND); -#endif - - /* From here onwards the device can be used. */ - - if (sc->quirks & SHUTTLE_INIT) - umass_init_shuttle(sc); - - /* Get the maximum LUN supported by the device. - */ - if (((sc->proto & UMASS_PROTO_WIRE) == UMASS_PROTO_BBB) && - !(sc->quirks & NO_GETMAXLUN)) - sc->maxlun = umass_bbb_get_max_lun(sc); - else - sc->maxlun = 0; - - if ((sc->proto & UMASS_PROTO_SCSI) || - (sc->proto & UMASS_PROTO_ATAPI) || - (sc->proto & UMASS_PROTO_UFI) || - (sc->proto & UMASS_PROTO_RBC)) { - /* Prepare the SCSI command block */ - sc->cam_scsi_sense.opcode = REQUEST_SENSE; - sc->cam_scsi_test_unit_ready.opcode = TEST_UNIT_READY; - - /* register the SIM */ - err = umass_cam_attach_sim(sc); - if (err) { - umass_detach(self); - return ENXIO; - } - /* scan the new sim */ - err = umass_cam_attach(sc); - if (err) { - umass_cam_detach_sim(sc); - umass_detach(self); - return ENXIO; - } - } else { - panic("%s:%d: Unknown proto 0x%02x", - __FILE__, __LINE__, sc->proto); - } - - sc->transfer_state = TSTATE_IDLE; - DPRINTF(UDMASS_GEN, ("%s: Attach finished\n", device_get_nameunit(sc->sc_dev))); - - return 0; -} - -static int -umass_detach(device_t self) -{ - struct umass_softc *sc = device_get_softc(self); - int err = 0; - int i; - int to; - - DPRINTF(UDMASS_USB, ("%s: detached\n", device_get_nameunit(sc->sc_dev))); - - /* - * Set UMASS_FLAGS_GONE to prevent any new transfers from being - * queued, and abort any transfers in progress to ensure that - * pending requests (e.g. from CAM's bus scan) are terminated. - */ - sc->flags |= UMASS_FLAGS_GONE; - - if (sc->bulkout_pipe) - usbd_abort_pipe(sc->bulkout_pipe); - if (sc->bulkin_pipe) - usbd_abort_pipe(sc->bulkin_pipe); - if (sc->intrin_pipe) - usbd_abort_pipe(sc->intrin_pipe); - - /* - * Wait until we go idle to make sure that all of our xfer requests - * have finished. We could be in the middle of a BBB reset (which - * would not be effected by the pipe aborts above). - */ - to = hz; - while (sc->transfer_state != TSTATE_IDLE) { - kprintf("%s: state %d waiting for idle\n", - device_get_nameunit(sc->sc_dev), sc->transfer_state); - tsleep(sc, 0, "umassidl", to); - if (to >= hz * 10) { - kprintf("%s: state %d giving up!\n", - device_get_nameunit(sc->sc_dev), sc->transfer_state); - break; - } - to += hz; - } - - if ((sc->proto & UMASS_PROTO_SCSI) || - (sc->proto & UMASS_PROTO_ATAPI) || - (sc->proto & UMASS_PROTO_UFI) || - (sc->proto & UMASS_PROTO_RBC)) { - /* detach the SCSI host controller (SIM) */ - err = umass_cam_detach_sim(sc); - } - - for (i = 0; i < XFER_NR; i++) { - if (sc->transfer_xfer[i]) - usbd_free_xfer(sc->transfer_xfer[i]); - } - - /* remove all the pipes */ - if (sc->bulkout_pipe) - usbd_close_pipe(sc->bulkout_pipe); - if (sc->bulkin_pipe) - usbd_close_pipe(sc->bulkin_pipe); - if (sc->intrin_pipe) - usbd_close_pipe(sc->intrin_pipe); - - return(err); -} - -static void -umass_init_shuttle(struct umass_softc *sc) -{ - usb_device_request_t req; - u_char status[2]; - - /* The Linux driver does this, but no one can tell us what the - * command does. - */ - req.bmRequestType = UT_READ_VENDOR_DEVICE; - req.bRequest = 1; /* XXX unknown command */ - USETW(req.wValue, 0); - USETW(req.wIndex, sc->ifaceno); - USETW(req.wLength, sizeof status); - (void) usbd_do_request(sc->sc_udev, &req, &status); - - DPRINTF(UDMASS_GEN, ("%s: Shuttle init returned 0x%02x%02x\n", - device_get_nameunit(sc->sc_dev), status[0], status[1])); -} - - /* - * Generic functions to handle transfers - */ - -static usbd_status -umass_setup_transfer(struct umass_softc *sc, usbd_pipe_handle pipe, - void *buffer, int buflen, int flags, - usbd_xfer_handle xfer) -{ - usbd_status err; - - /* Initialiase a USB transfer and then schedule it */ - - (void) usbd_setup_xfer(xfer, pipe, (void *) sc, buffer, buflen, flags, - sc->timeout, sc->state); - - err = usbd_transfer(xfer); - if (err && err != USBD_IN_PROGRESS) { - DPRINTF(UDMASS_BBB, ("%s: failed to setup transfer, %s\n", - device_get_nameunit(sc->sc_dev), usbd_errstr(err))); - return(err); - } - - return (USBD_NORMAL_COMPLETION); -} - - -static usbd_status -umass_setup_ctrl_transfer(struct umass_softc *sc, usbd_device_handle udev, - usb_device_request_t *req, - void *buffer, int buflen, int flags, - usbd_xfer_handle xfer) -{ - usbd_status err; - - /* Initialiase a USB control transfer and then schedule it */ - - (void) usbd_setup_default_xfer(xfer, udev, (void *) sc, - UMASS_TIMEOUT, req, buffer, buflen, flags, sc->state); - - err = usbd_transfer(xfer); - if (err && err != USBD_IN_PROGRESS) { - DPRINTF(UDMASS_BBB, ("%s: failed to setup ctrl transfer, %s\n", - device_get_nameunit(sc->sc_dev), usbd_errstr(err))); - - /* do not reset, as this would make us loop */ - return(err); - } - - return (USBD_NORMAL_COMPLETION); -} - -static void -umass_clear_endpoint_stall(struct umass_softc *sc, - u_int8_t endpt, usbd_pipe_handle pipe, - int state, usbd_xfer_handle xfer) -{ - usbd_device_handle udev; - - DPRINTF(UDMASS_BBB, ("%s: Clear endpoint 0x%02x stall\n", - device_get_nameunit(sc->sc_dev), endpt)); - - usbd_interface2device_handle(sc->iface, &udev); - - sc->transfer_state = state; - - usbd_clear_endpoint_toggle(pipe); - - sc->request.bmRequestType = UT_WRITE_ENDPOINT; - sc->request.bRequest = UR_CLEAR_FEATURE; - USETW(sc->request.wValue, UF_ENDPOINT_HALT); - USETW(sc->request.wIndex, endpt); - USETW(sc->request.wLength, 0); - umass_setup_ctrl_transfer(sc, udev, &sc->request, NULL, 0, 0, xfer); -} - -static void -umass_reset(struct umass_softc *sc, transfer_cb_f cb, void *priv) -{ - sc->transfer_cb = cb; - sc->transfer_priv = priv; - - /* The reset is a forced reset, so no error (yet) */ - sc->reset(sc, STATUS_CMD_OK); -} - -/* - * Bulk protocol specific functions - */ - -static void -umass_bbb_reset(struct umass_softc *sc, int status) -{ - usbd_device_handle udev; - - KASSERT(sc->proto & UMASS_PROTO_BBB, - ("%s: umass_bbb_reset: wrong sc->proto 0x%02x", - device_get_nameunit(sc->sc_dev), sc->proto)); - - /* - * Reset recovery (5.3.4 in Universal Serial Bus Mass Storage Class) - * - * For Reset Recovery the host shall issue in the following order: - * a) a Bulk-Only Mass Storage Reset - * b) a Clear Feature HALT to the Bulk-In endpoint - * c) a Clear Feature HALT to the Bulk-Out endpoint - * - * This is done in 3 steps, states: - * TSTATE_BBB_RESET1 - * TSTATE_BBB_RESET2 - * TSTATE_BBB_RESET3 - * - * If the reset doesn't succeed, the device should be port reset. - */ - - DPRINTF(UDMASS_BBB, ("%s: Bulk Reset\n", - device_get_nameunit(sc->sc_dev))); - - sc->transfer_state = TSTATE_BBB_RESET1; - sc->transfer_status = status; - - usbd_interface2device_handle(sc->iface, &udev); - - /* reset is a class specific interface write */ - sc->request.bmRequestType = UT_WRITE_CLASS_INTERFACE; - sc->request.bRequest = UR_BBB_RESET; - USETW(sc->request.wValue, 0); - USETW(sc->request.wIndex, sc->ifaceno); - USETW(sc->request.wLength, 0); - umass_setup_ctrl_transfer(sc, udev, &sc->request, NULL, 0, 0, - sc->transfer_xfer[XFER_BBB_RESET1]); -} - -static void -umass_bbb_transfer(struct umass_softc *sc, int lun, void *cmd, int cmdlen, - void *data, int datalen, int dir, u_int timeout, - transfer_cb_f cb, void *priv) -{ - KASSERT(sc->proto & UMASS_PROTO_BBB, - ("%s: umass_bbb_transfer: wrong sc->proto 0x%02x", - device_get_nameunit(sc->sc_dev), sc->proto)); - /* Be a little generous. */ - sc->timeout = timeout + UMASS_TIMEOUT; - - /* - * Do a Bulk-Only transfer with cmdlen bytes from cmd, possibly - * a data phase of datalen bytes from/to the device and finally a - * csw read phase. - * If the data direction was inbound a maximum of datalen bytes - * is stored in the buffer pointed to by data. - * - * umass_bbb_transfer initialises the transfer and lets the state - * machine in umass_bbb_state handle the completion. It uses the - * following states: - * TSTATE_BBB_COMMAND - * -> TSTATE_BBB_DATA - * -> TSTATE_BBB_STATUS - * -> TSTATE_BBB_STATUS2 - * -> TSTATE_BBB_IDLE - * - * An error in any of those states will invoke - * umass_bbb_reset. - */ - - /* check the given arguments */ - KASSERT(datalen == 0 || data != NULL, - ("%s: datalen > 0, but no buffer",device_get_nameunit(sc->sc_dev))); - KASSERT(cmdlen <= CBWCDBLENGTH, - ("%s: cmdlen exceeds CDB length in CBW (%d > %d)", - device_get_nameunit(sc->sc_dev), cmdlen, CBWCDBLENGTH)); - KASSERT(dir == DIR_NONE || datalen > 0, - ("%s: datalen == 0 while direction is not NONE", - device_get_nameunit(sc->sc_dev))); - KASSERT(datalen == 0 || dir != DIR_NONE, - ("%s: direction is NONE while datalen is not zero", - device_get_nameunit(sc->sc_dev))); - KASSERT(sizeof(umass_bbb_cbw_t) == UMASS_BBB_CBW_SIZE, - ("%s: CBW struct does not have the right size (%ld vs. %d)", - device_get_nameunit(sc->sc_dev), - (long)sizeof(umass_bbb_cbw_t), UMASS_BBB_CBW_SIZE)); - KASSERT(sizeof(umass_bbb_csw_t) == UMASS_BBB_CSW_SIZE, - ("%s: CSW struct does not have the right size (%ld vs. %d)", - device_get_nameunit(sc->sc_dev), - (long)sizeof(umass_bbb_csw_t), UMASS_BBB_CSW_SIZE)); - - /* - * Determine the direction of the data transfer and the length. - * - * dCBWDataTransferLength (datalen) : - * This field indicates the number of bytes of data that the host - * intends to transfer on the IN or OUT Bulk endpoint(as indicated by - * the Direction bit) during the execution of this command. If this - * field is set to 0, the device will expect that no data will be - * transferred IN or OUT during this command, regardless of the value - * of the Direction bit defined in dCBWFlags. - * - * dCBWFlags (dir) : - * The bits of the Flags field are defined as follows: - * Bits 0-6 reserved - * Bit 7 Direction - this bit shall be ignored if the - * dCBWDataTransferLength field is zero. - * 0 = data Out from host to device - * 1 = data In from device to host - */ - - /* Fill in the Command Block Wrapper - * We fill in all the fields, so there is no need to bzero it first. - */ - USETDW(sc->cbw.dCBWSignature, CBWSIGNATURE); - /* We don't care about the initial value, as long as the values are unique */ - USETDW(sc->cbw.dCBWTag, UGETDW(sc->cbw.dCBWTag) + 1); - USETDW(sc->cbw.dCBWDataTransferLength, datalen); - /* DIR_NONE is treated as DIR_OUT (0x00) */ - sc->cbw.bCBWFlags = (dir == DIR_IN? CBWFLAGS_IN:CBWFLAGS_OUT); - sc->cbw.bCBWLUN = lun; - sc->cbw.bCDBLength = cmdlen; - bcopy(cmd, sc->cbw.CBWCDB, cmdlen); - - DIF(UDMASS_BBB, umass_bbb_dump_cbw(sc, &sc->cbw)); - - /* store the details for the data transfer phase */ - sc->transfer_dir = dir; - sc->transfer_data = data; - sc->transfer_datalen = datalen; - sc->transfer_actlen = 0; - sc->transfer_cb = cb; - sc->transfer_priv = priv; - sc->transfer_status = STATUS_CMD_OK; - - /* move from idle to the command state */ - sc->transfer_state = TSTATE_BBB_COMMAND; - - /* Send the CBW from host to device via bulk-out endpoint. */ - if (umass_setup_transfer(sc, sc->bulkout_pipe, - &sc->cbw, UMASS_BBB_CBW_SIZE, 0, - sc->transfer_xfer[XFER_BBB_CBW])) { - umass_bbb_reset(sc, STATUS_WIRE_FAILED); - } -} - - -static void -umass_bbb_state(usbd_xfer_handle xfer, usbd_private_handle priv, - usbd_status err) -{ - struct umass_softc *sc = (struct umass_softc *) priv; - usbd_xfer_handle next_xfer; - - KASSERT(sc->proto & UMASS_PROTO_BBB, - ("%s: umass_bbb_state: wrong sc->proto 0x%02x", - device_get_nameunit(sc->sc_dev), sc->proto)); - - /* - * State handling for BBB transfers. - * - * The subroutine is rather long. It steps through the states given in - * Annex A of the Bulk-Only specification. - * Each state first does the error handling of the previous transfer - * and then prepares the next transfer. - * Each transfer is done asynchroneously so after the request/transfer - * has been submitted you will find a 'return;'. - */ - - DPRINTF(UDMASS_BBB, ("%s: Handling BBB state %d (%s), xfer=%p, %s\n", - device_get_nameunit(sc->sc_dev), sc->transfer_state, - states[sc->transfer_state], xfer, usbd_errstr(err))); - - switch (sc->transfer_state) { - - /***** Bulk Transfer *****/ - case TSTATE_BBB_COMMAND: - /* Command transport phase, error handling */ - if (err) { - DPRINTF(UDMASS_BBB, ("%s: failed to send CBW\n", - device_get_nameunit(sc->sc_dev))); - /* If the device detects that the CBW is invalid, then - * the device may STALL both bulk endpoints and require - * a Bulk-Reset - */ - umass_bbb_reset(sc, STATUS_WIRE_FAILED); - return; - } - - /* Data transport phase, setup transfer */ - sc->transfer_state = TSTATE_BBB_DATA; - if (sc->transfer_dir == DIR_IN) { - if (umass_setup_transfer(sc, sc->bulkin_pipe, - sc->transfer_data, sc->transfer_datalen, - USBD_SHORT_XFER_OK, - sc->transfer_xfer[XFER_BBB_DATA])) - umass_bbb_reset(sc, STATUS_WIRE_FAILED); - - return; - } else if (sc->transfer_dir == DIR_OUT) { - if (umass_setup_transfer(sc, sc->bulkout_pipe, - sc->transfer_data, sc->transfer_datalen, - 0, /* fixed length transfer */ - sc->transfer_xfer[XFER_BBB_DATA])) - umass_bbb_reset(sc, STATUS_WIRE_FAILED); - - return; - } else { - DPRINTF(UDMASS_BBB, ("%s: no data phase\n", - device_get_nameunit(sc->sc_dev))); - } - - /* FALLTHROUGH if no data phase, err == 0 */ - case TSTATE_BBB_DATA: - /* Command transport phase, error handling (ignored if no data - * phase (fallthrough from previous state)) */ - if (sc->transfer_dir != DIR_NONE) { - /* retrieve the length of the transfer that was done */ - usbd_get_xfer_status(xfer, NULL, NULL, - &sc->transfer_actlen, NULL); - - if (err) { - DPRINTF(UDMASS_BBB, ("%s: Data-%s %db failed, " - "%s\n", device_get_nameunit(sc->sc_dev), - (sc->transfer_dir == DIR_IN?"in":"out"), - sc->transfer_datalen,usbd_errstr(err))); - - if (err == USBD_STALLED) { - umass_clear_endpoint_stall(sc, - (sc->transfer_dir == DIR_IN? - sc->bulkin:sc->bulkout), - (sc->transfer_dir == DIR_IN? - sc->bulkin_pipe:sc->bulkout_pipe), - TSTATE_BBB_DCLEAR, - sc->transfer_xfer[XFER_BBB_DCLEAR]); - return; - } else { - /* Unless the error is a pipe stall the - * error is fatal. - */ - umass_bbb_reset(sc,STATUS_WIRE_FAILED); - return; - } - } - } - - DIF(UDMASS_BBB, if (sc->transfer_dir == DIR_IN) - umass_dump_buffer(sc, sc->transfer_data, - sc->transfer_datalen, 48)); - - - - /* FALLTHROUGH, err == 0 (no data phase or successfull) */ - case TSTATE_BBB_DCLEAR: /* stall clear after data phase */ - case TSTATE_BBB_SCLEAR: /* stall clear after status phase */ - /* Reading of CSW after bulk stall condition in data phase - * (TSTATE_BBB_DATA2) or bulk-in stall condition after - * reading CSW (TSTATE_BBB_SCLEAR). - * In the case of no data phase or successfull data phase, - * err == 0 and the following if block is passed. - */ - if (err) { /* should not occur */ - /* try the transfer below, even if clear stall failed */ - DPRINTF(UDMASS_BBB, ("%s: bulk-%s stall clear failed" - ", %s\n", device_get_nameunit(sc->sc_dev), - (sc->transfer_dir == DIR_IN? "in":"out"), - usbd_errstr(err))); - umass_bbb_reset(sc, STATUS_WIRE_FAILED); - return; - } - - /* Status transport phase, setup transfer */ - if (sc->transfer_state == TSTATE_BBB_COMMAND || - sc->transfer_state == TSTATE_BBB_DATA || - sc->transfer_state == TSTATE_BBB_DCLEAR) { - /* After no data phase, successfull data phase and - * after clearing bulk-in/-out stall condition - */ - sc->transfer_state = TSTATE_BBB_STATUS1; - next_xfer = sc->transfer_xfer[XFER_BBB_CSW1]; - } else { - /* After first attempt of fetching CSW */ - sc->transfer_state = TSTATE_BBB_STATUS2; - next_xfer = sc->transfer_xfer[XFER_BBB_CSW2]; - } - - /* Read the Command Status Wrapper via bulk-in endpoint. */ - if (umass_setup_transfer(sc, sc->bulkin_pipe, - &sc->csw, UMASS_BBB_CSW_SIZE, 0, - next_xfer)) { - umass_bbb_reset(sc, STATUS_WIRE_FAILED); - return; - } - - return; - case TSTATE_BBB_STATUS1: /* first attempt */ - case TSTATE_BBB_STATUS2: /* second attempt */ - /* Status transfer, error handling */ - { - int Residue; - if (err) { - DPRINTF(UDMASS_BBB, ("%s: Failed to read CSW, %s%s\n", - device_get_nameunit(sc->sc_dev), usbd_errstr(err), - (sc->transfer_state == TSTATE_BBB_STATUS1? - ", retrying":""))); - - /* If this was the first attempt at fetching the CSW - * retry it, otherwise fail. - */ - if (sc->transfer_state == TSTATE_BBB_STATUS1) { - umass_clear_endpoint_stall(sc, - sc->bulkin, sc->bulkin_pipe, - TSTATE_BBB_SCLEAR, - sc->transfer_xfer[XFER_BBB_SCLEAR]); - return; - } else { - umass_bbb_reset(sc, STATUS_WIRE_FAILED); - return; - } - } - - DIF(UDMASS_BBB, umass_bbb_dump_csw(sc, &sc->csw)); - - /* Translate weird command-status signatures. */ - if ((sc->quirks & WRONG_CSWSIG) && - UGETDW(sc->csw.dCSWSignature) == CSWSIGNATURE_OLYMPUS_C1) - USETDW(sc->csw.dCSWSignature, CSWSIGNATURE); - - Residue = UGETDW(sc->csw.dCSWDataResidue); - if (Residue == 0 && - sc->transfer_datalen - sc->transfer_actlen != 0) - Residue = sc->transfer_datalen - sc->transfer_actlen; - - /* Check CSW and handle any error */ - if (UGETDW(sc->csw.dCSWSignature) != CSWSIGNATURE) { - /* Invalid CSW: Wrong signature or wrong tag might - * indicate that the device is confused -> reset it. - */ - kprintf("%s: Invalid CSW: sig 0x%08x should be 0x%08x\n", - device_get_nameunit(sc->sc_dev), - UGETDW(sc->csw.dCSWSignature), - CSWSIGNATURE); - - umass_bbb_reset(sc, STATUS_WIRE_FAILED); - return; - } else if (UGETDW(sc->csw.dCSWTag) - != UGETDW(sc->cbw.dCBWTag)) { - kprintf("%s: Invalid CSW: tag %d should be %d\n", - device_get_nameunit(sc->sc_dev), - UGETDW(sc->csw.dCSWTag), - UGETDW(sc->cbw.dCBWTag)); - - umass_bbb_reset(sc, STATUS_WIRE_FAILED); - return; - - /* CSW is valid here */ - } else if (sc->csw.bCSWStatus > CSWSTATUS_PHASE) { - kprintf("%s: Invalid CSW: status %d > %d\n", - device_get_nameunit(sc->sc_dev), - sc->csw.bCSWStatus, - CSWSTATUS_PHASE); - - umass_bbb_reset(sc, STATUS_WIRE_FAILED); - return; - } else if (sc->csw.bCSWStatus == CSWSTATUS_PHASE) { - kprintf("%s: Phase Error, residue = %d\n", - device_get_nameunit(sc->sc_dev), Residue); - - umass_bbb_reset(sc, STATUS_WIRE_FAILED); - return; - - } else if (sc->transfer_actlen > sc->transfer_datalen) { - /* Buffer overrun! Don't let this go by unnoticed */ - panic("%s: transferred %db instead of %db", - device_get_nameunit(sc->sc_dev), - sc->transfer_actlen, sc->transfer_datalen); - - } else if (sc->csw.bCSWStatus == CSWSTATUS_FAILED) { - DPRINTF(UDMASS_BBB, ("%s: Command Failed, res = %d\n", - device_get_nameunit(sc->sc_dev), Residue)); - - /* SCSI command failed but transfer was succesful */ - sc->transfer_state = TSTATE_IDLE; - sc->transfer_cb(sc, sc->transfer_priv, Residue, - STATUS_CMD_FAILED); - return; - - } else { /* success */ - sc->transfer_state = TSTATE_IDLE; - sc->transfer_cb(sc, sc->transfer_priv, Residue, - STATUS_CMD_OK); - - return; - } - } - - /***** Bulk Reset *****/ - case TSTATE_BBB_RESET1: - if (err) - kprintf("%s: BBB reset failed, %s\n", - device_get_nameunit(sc->sc_dev), usbd_errstr(err)); - - umass_clear_endpoint_stall(sc, - sc->bulkin, sc->bulkin_pipe, TSTATE_BBB_RESET2, - sc->transfer_xfer[XFER_BBB_RESET2]); - - return; - case TSTATE_BBB_RESET2: - if (err) /* should not occur */ - kprintf("%s: BBB bulk-in clear stall failed, %s\n", - device_get_nameunit(sc->sc_dev), usbd_errstr(err)); - /* no error recovery, otherwise we end up in a loop */ - - umass_clear_endpoint_stall(sc, - sc->bulkout, sc->bulkout_pipe, TSTATE_BBB_RESET3, - sc->transfer_xfer[XFER_BBB_RESET3]); - - return; - case TSTATE_BBB_RESET3: - if (err) /* should not occur */ - kprintf("%s: BBB bulk-out clear stall failed, %s\n", - device_get_nameunit(sc->sc_dev), usbd_errstr(err)); - /* no error recovery, otherwise we end up in a loop */ - - sc->transfer_state = TSTATE_IDLE; - if (sc->transfer_priv) { - sc->transfer_cb(sc, sc->transfer_priv, - sc->transfer_datalen, - sc->transfer_status); - } - - return; - - /***** Default *****/ - default: - panic("%s: Unknown state %d", - device_get_nameunit(sc->sc_dev), sc->transfer_state); - } -} - -static int -umass_bbb_get_max_lun(struct umass_softc *sc) -{ - usbd_device_handle udev; - usb_device_request_t req; - usbd_status err; - usb_interface_descriptor_t *id; - int maxlun = 0; - u_int8_t buf = 0; - - usbd_interface2device_handle(sc->iface, &udev); - id = usbd_get_interface_descriptor(sc->iface); - - /* The Get Max Lun command is a class-specific request. */ - req.bmRequestType = UT_READ_CLASS_INTERFACE; - req.bRequest = UR_BBB_GET_MAX_LUN; - USETW(req.wValue, 0); - USETW(req.wIndex, id->bInterfaceNumber); - USETW(req.wLength, 1); - - err = usbd_do_request(udev, &req, &buf); - switch (err) { - case USBD_NORMAL_COMPLETION: - maxlun = buf; - DPRINTF(UDMASS_BBB, ("%s: Max Lun is %d\n", - device_get_nameunit(sc->sc_dev), maxlun)); - break; - case USBD_STALLED: - case USBD_SHORT_XFER: - default: - /* Device doesn't support Get Max Lun request. */ - kprintf("%s: Get Max Lun not supported (%s)\n", - device_get_nameunit(sc->sc_dev), usbd_errstr(err)); - /* XXX Should we port_reset the device? */ - break; - } - - return(maxlun); -} - -/* - * Command/Bulk/Interrupt (CBI) specific functions - */ - -static int -umass_cbi_adsc(struct umass_softc *sc, char *buffer, int buflen, - usbd_xfer_handle xfer) -{ - usbd_device_handle udev; - - KASSERT(sc->proto & (UMASS_PROTO_CBI|UMASS_PROTO_CBI_I), - ("%s: umass_cbi_adsc: wrong sc->proto 0x%02x", - device_get_nameunit(sc->sc_dev), sc->proto)); - - usbd_interface2device_handle(sc->iface, &udev); - - sc->request.bmRequestType = UT_WRITE_CLASS_INTERFACE; - sc->request.bRequest = UR_CBI_ADSC; - USETW(sc->request.wValue, 0); - USETW(sc->request.wIndex, sc->ifaceno); - USETW(sc->request.wLength, buflen); - return umass_setup_ctrl_transfer(sc, udev, &sc->request, buffer, - buflen, 0, xfer); -} - - -static void -umass_cbi_reset(struct umass_softc *sc, int status) -{ - int i; -# define SEND_DIAGNOSTIC_CMDLEN 12 - - KASSERT(sc->proto & (UMASS_PROTO_CBI|UMASS_PROTO_CBI_I), - ("%s: umass_cbi_reset: wrong sc->proto 0x%02x", - device_get_nameunit(sc->sc_dev), sc->proto)); - - /* - * Command Block Reset Protocol - * - * First send a reset request to the device. Then clear - * any possibly stalled bulk endpoints. - - * This is done in 3 steps, states: - * TSTATE_CBI_RESET1 - * TSTATE_CBI_RESET2 - * TSTATE_CBI_RESET3 - * - * If the reset doesn't succeed, the device should be port reset. - */ - - DPRINTF(UDMASS_CBI, ("%s: CBI Reset\n", - device_get_nameunit(sc->sc_dev))); - - KASSERT(sizeof(sc->cbl) >= SEND_DIAGNOSTIC_CMDLEN, - ("%s: CBL struct is too small (%ld < %d)", - device_get_nameunit(sc->sc_dev), - (long)sizeof(sc->cbl), SEND_DIAGNOSTIC_CMDLEN)); - - sc->transfer_state = TSTATE_CBI_RESET1; - sc->transfer_status = status; - - /* The 0x1d code is the SEND DIAGNOSTIC command. To distingiush between - * the two the last 10 bytes of the cbl is filled with 0xff (section - * 2.2 of the CBI spec). - */ - sc->cbl[0] = 0x1d; /* Command Block Reset */ - sc->cbl[1] = 0x04; - for (i = 2; i < SEND_DIAGNOSTIC_CMDLEN; i++) - sc->cbl[i] = 0xff; - - umass_cbi_adsc(sc, sc->cbl, SEND_DIAGNOSTIC_CMDLEN, - sc->transfer_xfer[XFER_CBI_RESET1]); - /* XXX if the command fails we should reset the port on the bub */ -} - -static void -umass_cbi_transfer(struct umass_softc *sc, int lun, - void *cmd, int cmdlen, void *data, int datalen, int dir, - u_int timeout, transfer_cb_f cb, void *priv) -{ - KASSERT(sc->proto & (UMASS_PROTO_CBI|UMASS_PROTO_CBI_I), - ("%s: umass_cbi_transfer: wrong sc->proto 0x%02x", - device_get_nameunit(sc->sc_dev), sc->proto)); - /* Be a little generous. */ - sc->timeout = timeout + UMASS_TIMEOUT; - - /* - * Do a CBI transfer with cmdlen bytes from cmd, possibly - * a data phase of datalen bytes from/to the device and finally a - * csw read phase. - * If the data direction was inbound a maximum of datalen bytes - * is stored in the buffer pointed to by data. - * - * umass_cbi_transfer initialises the transfer and lets the state - * machine in umass_cbi_state handle the completion. It uses the - * following states: - * TSTATE_CBI_COMMAND - * -> XXX fill in - * - * An error in any of those states will invoke - * umass_cbi_reset. - */ - - /* check the given arguments */ - KASSERT(datalen == 0 || data != NULL, - ("%s: datalen > 0, but no buffer",device_get_nameunit(sc->sc_dev))); - KASSERT(datalen == 0 || dir != DIR_NONE, - ("%s: direction is NONE while datalen is not zero", - device_get_nameunit(sc->sc_dev))); - - /* store the details for the data transfer phase */ - sc->transfer_dir = dir; - sc->transfer_data = data; - sc->transfer_datalen = datalen; - sc->transfer_actlen = 0; - sc->transfer_cb = cb; - sc->transfer_priv = priv; - sc->transfer_status = STATUS_CMD_OK; - - /* move from idle to the command state */ - sc->transfer_state = TSTATE_CBI_COMMAND; - - DIF(UDMASS_CBI, umass_cbi_dump_cmd(sc, cmd, cmdlen)); - - /* Send the Command Block from host to device via control endpoint. */ - if (umass_cbi_adsc(sc, cmd, cmdlen, sc->transfer_xfer[XFER_CBI_CB])) - umass_cbi_reset(sc, STATUS_WIRE_FAILED); -} - -static void -umass_cbi_state(usbd_xfer_handle xfer, usbd_private_handle priv, - usbd_status err) -{ - struct umass_softc *sc = (struct umass_softc *) priv; - - KASSERT(sc->proto & (UMASS_PROTO_CBI|UMASS_PROTO_CBI_I), - ("%s: umass_cbi_state: wrong sc->proto 0x%02x", - device_get_nameunit(sc->sc_dev), sc->proto)); - - /* - * State handling for CBI transfers. - */ - - DPRINTF(UDMASS_CBI, ("%s: Handling CBI state %d (%s), xfer=%p, %s\n", - device_get_nameunit(sc->sc_dev), sc->transfer_state, - states[sc->transfer_state], xfer, usbd_errstr(err))); - - switch (sc->transfer_state) { - - /***** CBI Transfer *****/ - case TSTATE_CBI_COMMAND: - if (err == USBD_STALLED) { - DPRINTF(UDMASS_CBI, ("%s: Command Transport failed\n", - device_get_nameunit(sc->sc_dev))); - /* Status transport by control pipe (section 2.3.2.1). - * The command contained in the command block failed. - * - * The control pipe has already been unstalled by the - * USB stack. - * Section 2.4.3.1.1 states that the bulk in endpoints - * should not be stalled at this point. - */ - - sc->transfer_state = TSTATE_IDLE; - sc->transfer_cb(sc, sc->transfer_priv, - sc->transfer_datalen, - STATUS_CMD_FAILED); - - return; - } else if (err) { - DPRINTF(UDMASS_CBI, ("%s: failed to send ADSC\n", - device_get_nameunit(sc->sc_dev))); - umass_cbi_reset(sc, STATUS_WIRE_FAILED); - - return; - } - - sc->transfer_state = TSTATE_CBI_DATA; - if (sc->transfer_dir == DIR_IN) { - if (umass_setup_transfer(sc, sc->bulkin_pipe, - sc->transfer_data, sc->transfer_datalen, - USBD_SHORT_XFER_OK, - sc->transfer_xfer[XFER_CBI_DATA])) - umass_cbi_reset(sc, STATUS_WIRE_FAILED); - - } else if (sc->transfer_dir == DIR_OUT) { - if (umass_setup_transfer(sc, sc->bulkout_pipe, - sc->transfer_data, sc->transfer_datalen, - 0, /* fixed length transfer */ - sc->transfer_xfer[XFER_CBI_DATA])) - umass_cbi_reset(sc, STATUS_WIRE_FAILED); - - } else if (sc->proto & UMASS_PROTO_CBI_I) { - DPRINTF(UDMASS_CBI, ("%s: no data phase\n", - device_get_nameunit(sc->sc_dev))); - sc->transfer_state = TSTATE_CBI_STATUS; - if (umass_setup_transfer(sc, sc->intrin_pipe, - &sc->sbl, sizeof(sc->sbl), - 0, /* fixed length transfer */ - sc->transfer_xfer[XFER_CBI_STATUS])){ - umass_cbi_reset(sc, STATUS_WIRE_FAILED); - } - } else { - DPRINTF(UDMASS_CBI, ("%s: no data phase\n", - device_get_nameunit(sc->sc_dev))); - /* No command completion interrupt. Request - * sense data. - */ - sc->transfer_state = TSTATE_IDLE; - sc->transfer_cb(sc, sc->transfer_priv, - 0, STATUS_CMD_UNKNOWN); - } - - return; - - case TSTATE_CBI_DATA: - /* retrieve the length of the transfer that was done */ - usbd_get_xfer_status(xfer,NULL,NULL,&sc->transfer_actlen,NULL); - - if (err) { - DPRINTF(UDMASS_CBI, ("%s: Data-%s %db failed, " - "%s\n", device_get_nameunit(sc->sc_dev), - (sc->transfer_dir == DIR_IN?"in":"out"), - sc->transfer_datalen,usbd_errstr(err))); - - if (err == USBD_STALLED) { - umass_clear_endpoint_stall(sc, - sc->bulkin, sc->bulkin_pipe, - TSTATE_CBI_DCLEAR, - sc->transfer_xfer[XFER_CBI_DCLEAR]); - } else { - umass_cbi_reset(sc, STATUS_WIRE_FAILED); - } - return; - } - - DIF(UDMASS_CBI, if (sc->transfer_dir == DIR_IN) - umass_dump_buffer(sc, sc->transfer_data, - sc->transfer_actlen, 48)); - - if (sc->proto & UMASS_PROTO_CBI_I) { - sc->transfer_state = TSTATE_CBI_STATUS; - if (umass_setup_transfer(sc, sc->intrin_pipe, - &sc->sbl, sizeof(sc->sbl), - 0, /* fixed length transfer */ - sc->transfer_xfer[XFER_CBI_STATUS])){ - umass_cbi_reset(sc, STATUS_WIRE_FAILED); - } - } else { - /* No command completion interrupt. Request - * sense to get status of command. - */ - sc->transfer_state = TSTATE_IDLE; - sc->transfer_cb(sc, sc->transfer_priv, - sc->transfer_datalen - sc->transfer_actlen, - STATUS_CMD_UNKNOWN); - } - return; - - case TSTATE_CBI_STATUS: - if (err) { - DPRINTF(UDMASS_CBI, ("%s: Status Transport failed\n", - device_get_nameunit(sc->sc_dev))); - /* Status transport by interrupt pipe (section 2.3.2.2). - */ - - if (err == USBD_STALLED) { - umass_clear_endpoint_stall(sc, - sc->intrin, sc->intrin_pipe, - TSTATE_CBI_SCLEAR, - sc->transfer_xfer[XFER_CBI_SCLEAR]); - } else { - umass_cbi_reset(sc, STATUS_WIRE_FAILED); - } - return; - } - - /* Dissect the information in the buffer */ - - if (sc->proto & UMASS_PROTO_UFI) { - int status; - - /* Section 3.4.3.1.3 specifies that the UFI command - * protocol returns an ASC and ASCQ in the interrupt - * data block. - */ - - DPRINTF(UDMASS_CBI, ("%s: UFI CCI, ASC = 0x%02x, " - "ASCQ = 0x%02x\n", - device_get_nameunit(sc->sc_dev), - sc->sbl.ufi.asc, sc->sbl.ufi.ascq)); - - if (sc->sbl.ufi.asc == 0 && sc->sbl.ufi.ascq == 0) - status = STATUS_CMD_OK; - else - status = STATUS_CMD_FAILED; - - sc->transfer_state = TSTATE_IDLE; - sc->transfer_cb(sc, sc->transfer_priv, - sc->transfer_datalen - sc->transfer_actlen, - status); - } else { - /* Command Interrupt Data Block */ - DPRINTF(UDMASS_CBI, ("%s: type=0x%02x, value=0x%02x\n", - device_get_nameunit(sc->sc_dev), - sc->sbl.common.type, sc->sbl.common.value)); - - if (sc->sbl.common.type == IDB_TYPE_CCI) { - int err; - - if ((sc->sbl.common.value&IDB_VALUE_STATUS_MASK) - == IDB_VALUE_PASS) { - err = STATUS_CMD_OK; - } else if ((sc->sbl.common.value & IDB_VALUE_STATUS_MASK) - == IDB_VALUE_FAIL || - (sc->sbl.common.value & IDB_VALUE_STATUS_MASK) - == IDB_VALUE_PERSISTENT) { - err = STATUS_CMD_FAILED; - } else { - err = STATUS_WIRE_FAILED; - } - - sc->transfer_state = TSTATE_IDLE; - sc->transfer_cb(sc, sc->transfer_priv, - sc->transfer_datalen-sc->transfer_actlen, - err); - } - } - return; - - case TSTATE_CBI_DCLEAR: - if (err) { /* should not occur */ - kprintf("%s: CBI bulk-in/out stall clear failed, %s\n", - device_get_nameunit(sc->sc_dev), usbd_errstr(err)); - umass_cbi_reset(sc, STATUS_WIRE_FAILED); - } - - sc->transfer_state = TSTATE_IDLE; - sc->transfer_cb(sc, sc->transfer_priv, - sc->transfer_datalen, - STATUS_CMD_FAILED); - return; - - case TSTATE_CBI_SCLEAR: - if (err) /* should not occur */ - kprintf("%s: CBI intr-in stall clear failed, %s\n", - device_get_nameunit(sc->sc_dev), usbd_errstr(err)); - - /* Something really bad is going on. Reset the device */ - umass_cbi_reset(sc, STATUS_CMD_FAILED); - return; - - /***** CBI Reset *****/ - case TSTATE_CBI_RESET1: - if (err) - kprintf("%s: CBI reset failed, %s\n", - device_get_nameunit(sc->sc_dev), usbd_errstr(err)); - - umass_clear_endpoint_stall(sc, - sc->bulkin, sc->bulkin_pipe, TSTATE_CBI_RESET2, - sc->transfer_xfer[XFER_CBI_RESET2]); - - return; - case TSTATE_CBI_RESET2: - if (err) /* should not occur */ - kprintf("%s: CBI bulk-in stall clear failed, %s\n", - device_get_nameunit(sc->sc_dev), usbd_errstr(err)); - /* no error recovery, otherwise we end up in a loop */ - - umass_clear_endpoint_stall(sc, - sc->bulkout, sc->bulkout_pipe, TSTATE_CBI_RESET3, - sc->transfer_xfer[XFER_CBI_RESET3]); - - return; - case TSTATE_CBI_RESET3: - if (err) /* should not occur */ - kprintf("%s: CBI bulk-out stall clear failed, %s\n", - device_get_nameunit(sc->sc_dev), usbd_errstr(err)); - /* no error recovery, otherwise we end up in a loop */ - - sc->transfer_state = TSTATE_IDLE; - if (sc->transfer_priv) { - sc->transfer_cb(sc, sc->transfer_priv, - sc->transfer_datalen, - sc->transfer_status); - } - - return; - - - /***** Default *****/ - default: - panic("%s: Unknown state %d", - device_get_nameunit(sc->sc_dev), sc->transfer_state); - } -} - - - - -/* - * CAM specific functions (used by SCSI, UFI, 8070i (ATAPI)) - */ - -static int -umass_cam_attach_sim(struct umass_softc *sc) -{ - struct cam_devq *devq; /* Per device Queue */ - - /* A HBA is attached to the CAM layer. - * - * The CAM layer will then after a while start probing for - * devices on the bus. The number of SIMs is limited to one. - */ - - callout_init(&sc->rescan_timeout); - devq = cam_simq_alloc(1 /*maximum openings*/); - if (devq == NULL) - return(ENOMEM); - - sc->umass_sim = cam_sim_alloc(umass_cam_action, umass_cam_poll, - DEVNAME_SIM, - sc /*priv*/, - device_get_unit(sc->sc_dev) /*unit number*/, - &sim_mplock, - 1 /*maximum device openings*/, - 0 /*maximum tagged device openings*/, - devq); - cam_simq_release(devq); - if (sc->umass_sim == NULL) - return(ENOMEM); - - /* - * If we could not register the bus we must immediately free the - * sim so we do not attempt to deregister a bus later on that we - * had not registered. - */ - if (xpt_bus_register(sc->umass_sim, device_get_unit(sc->sc_dev)) != - CAM_SUCCESS) { - cam_sim_free(sc->umass_sim); - sc->umass_sim = NULL; - return(ENOMEM); - } - - return(0); -} - -static void -umass_cam_rescan_callback(struct cam_periph *periph, union ccb *ccb) -{ -#ifdef USB_DEBUG - if (ccb->ccb_h.status != CAM_REQ_CMP) { - DPRINTF(UDMASS_SCSI, ("%s:%d Rescan failed, 0x%04x\n", - periph->periph_name, periph->unit_number, - ccb->ccb_h.status)); - } else { - DPRINTF(UDMASS_SCSI, ("%s%d: Rescan succeeded\n", - periph->periph_name, periph->unit_number)); - } -#endif - - xpt_free_path(ccb->ccb_h.path); - kfree(ccb, M_USBDEV); -} - -/* - * Rescan the SCSI bus to detect newly added devices. We use - * an async rescan to avoid reentrancy issues. - */ -static void -umass_cam_rescan(void *addr) -{ - struct umass_softc *sc = (struct umass_softc *) addr; - struct cam_path *path; - union ccb *ccb; - - ccb = kmalloc(sizeof(union ccb), M_USBDEV, M_INTWAIT|M_ZERO); - - DPRINTF(UDMASS_SCSI, ("scbus%d: scanning for %s:%d:%d:%d\n", - cam_sim_path(sc->umass_sim), - device_get_nameunit(sc->sc_dev), cam_sim_path(sc->umass_sim), - device_get_unit(sc->sc_dev), CAM_LUN_WILDCARD)); - - if (xpt_create_path(&path, xpt_periph, cam_sim_path(sc->umass_sim), - CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) - != CAM_REQ_CMP) { - kfree(ccb, M_USBDEV); - return; - } - - xpt_setup_ccb(&ccb->ccb_h, path, 5/*priority (low)*/); - ccb->ccb_h.func_code = XPT_SCAN_BUS; - ccb->ccb_h.cbfcnp = umass_cam_rescan_callback; - ccb->crcn.flags = CAM_FLAG_NONE; - xpt_action_async(ccb); - - /* The scan is in progress now. */ -} - -static int -umass_cam_attach(struct umass_softc *sc) -{ -#ifndef USB_DEBUG - if (bootverbose) -#endif - kprintf("%s:%d:%d:%d: Attached to scbus%d\n", - device_get_nameunit(sc->sc_dev), cam_sim_path(sc->umass_sim), - device_get_unit(sc->sc_dev), CAM_LUN_WILDCARD, - cam_sim_path(sc->umass_sim)); - - if (!cold) { - /* - * Notify CAM of the new device after a 0.2 second delay. Any - * failure is benign, as the user can still do it by hand - * (camcontrol rescan ). Only do this if we are not - * booting, because CAM does a scan after booting has - * completed, when interrupts have been enabled. - */ - callout_reset(&sc->rescan_timeout, MS_TO_TICKS(200), - umass_cam_rescan, sc); - } - - return(0); /* always succesfull */ -} - -/* umass_cam_detach - * detach from the CAM layer - */ - -static int -umass_cam_detach_sim(struct umass_softc *sc) -{ - callout_stop(&sc->rescan_timeout); - if (sc->umass_sim) { - xpt_bus_deregister(cam_sim_path(sc->umass_sim)); - cam_sim_free(sc->umass_sim); - - sc->umass_sim = NULL; - } - - return(0); -} - -/* umass_cam_action - * CAM requests for action come through here - */ - -static void -umass_cam_action(struct cam_sim *sim, union ccb *ccb) -{ - struct umass_softc *sc = (struct umass_softc *)sim->softc; - - /* The softc is still there, but marked as going away. umass_cam_detach - * has not yet notified CAM of the lost device however. - */ - if (sc && (sc->flags & UMASS_FLAGS_GONE)) { - DPRINTF(UDMASS_SCSI, ("%s:%d:%d:%d:func_code 0x%04x: " - "Invalid target (gone)\n", - device_get_nameunit(sc->sc_dev), cam_sim_path(sc->umass_sim), - ccb->ccb_h.target_id, ccb->ccb_h.target_lun, - ccb->ccb_h.func_code)); - ccb->ccb_h.status = CAM_TID_INVALID; - xpt_done(ccb); - return; - } - - /* Verify, depending on the operation to perform, that we either got a - * valid sc, because an existing target was referenced, or otherwise - * the SIM is addressed. - * - * This avoids bombing out at a kprintf and does give the CAM layer some - * sensible feedback on errors. - */ - switch (ccb->ccb_h.func_code) { - case XPT_SCSI_IO: - case XPT_RESET_DEV: - case XPT_GET_TRAN_SETTINGS: - case XPT_SET_TRAN_SETTINGS: - case XPT_CALC_GEOMETRY: - /* the opcodes requiring a target. These should never occur. */ - if (sc == NULL) { - kprintf("%s:%d:%d:%d:func_code 0x%04x: " - "Invalid target (target needed)\n", - DEVNAME_SIM, 0, ccb->ccb_h.target_id, - ccb->ccb_h.target_lun, ccb->ccb_h.func_code); - - ccb->ccb_h.status = CAM_TID_INVALID; - xpt_done(ccb); - return; - } - break; - case XPT_PATH_INQ: - case XPT_NOOP: - /* The opcodes sometimes aimed at a target (sc is valid), - * sometimes aimed at the SIM (sc is invalid and target is - * CAM_TARGET_WILDCARD) - */ - if (sc == NULL && ccb->ccb_h.target_id != CAM_TARGET_WILDCARD) { - DPRINTF(UDMASS_SCSI, ("%s:%d:%d:%d:func_code 0x%04x: " - "Invalid target (no wildcard)\n", - DEVNAME_SIM, 0, ccb->ccb_h.target_id, - ccb->ccb_h.target_lun, ccb->ccb_h.func_code)); - - ccb->ccb_h.status = CAM_TID_INVALID; - xpt_done(ccb); - return; - } - break; - default: - /* XXX Hm, we should check the input parameters */ - break; - } - - /* Perform the requested action */ - switch (ccb->ccb_h.func_code) { - case XPT_SCSI_IO: - { - struct ccb_scsiio *csio = &ccb->csio; /* deref union */ - int dir; - unsigned char *cmd; - int cmdlen; - unsigned char *rcmd; - int rcmdlen; - - DPRINTF(UDMASS_SCSI, ("%s:%d:%d:%d:XPT_SCSI_IO: " - "cmd: 0x%02x, flags: 0x%02x, " - "%db cmd/%db data/%db sense\n", - device_get_nameunit(sc->sc_dev), cam_sim_path(sc->umass_sim), - ccb->ccb_h.target_id, ccb->ccb_h.target_lun, - csio->cdb_io.cdb_bytes[0], - ccb->ccb_h.flags & CAM_DIR_MASK, - csio->cdb_len, csio->dxfer_len, - csio->sense_len)); - - /* clear the end of the buffer to make sure we don't send out - * garbage. - */ - DIF(UDMASS_SCSI, if ((ccb->ccb_h.flags & CAM_DIR_MASK) - == CAM_DIR_OUT) - umass_dump_buffer(sc, csio->data_ptr, - csio->dxfer_len, 48)); - - if (sc->transfer_state != TSTATE_IDLE) { - DPRINTF(UDMASS_SCSI, ("%s:%d:%d:%d:XPT_SCSI_IO: " - "I/O in progress, deferring (state %d, %s)\n", - device_get_nameunit(sc->sc_dev), cam_sim_path(sc->umass_sim), - ccb->ccb_h.target_id, ccb->ccb_h.target_lun, - sc->transfer_state,states[sc->transfer_state])); - ccb->ccb_h.status = CAM_SCSI_BUSY; - xpt_done(ccb); - return; - } - - switch(ccb->ccb_h.flags&CAM_DIR_MASK) { - case CAM_DIR_IN: - dir = DIR_IN; - break; - case CAM_DIR_OUT: - dir = DIR_OUT; - break; - default: - dir = DIR_NONE; - } - - ccb->ccb_h.status = CAM_REQ_INPROG | CAM_SIM_QUEUED; - - - if (csio->ccb_h.flags & CAM_CDB_POINTER) { - cmd = (unsigned char *) csio->cdb_io.cdb_ptr; - } else { - cmd = (unsigned char *) &csio->cdb_io.cdb_bytes; - } - cmdlen = csio->cdb_len; - rcmd = (unsigned char *) &sc->cam_scsi_command; - rcmdlen = sizeof(sc->cam_scsi_command); - - /* sc->transform will convert the command to the command - * (format) needed by the specific command set and return - * the converted command in a buffer pointed to be rcmd. - * We pass in a buffer, but if the command does not - * have to be transformed it returns a ptr to the original - * buffer (see umass_scsi_transform). - */ - - if (sc->transform(sc, cmd, cmdlen, &rcmd, &rcmdlen)) { - /* - * Handle EVPD inquiry for broken devices first - * NO_INQUIRY also implies NO_INQUIRY_EVPD - */ - if ((sc->quirks & (NO_INQUIRY_EVPD | NO_INQUIRY)) && - rcmd[0] == INQUIRY && (rcmd[1] & SI_EVPD)) { - struct scsi_sense_data *sense; - - sense = &ccb->csio.sense_data; - bzero(sense, sizeof(*sense)); - sense->error_code = SSD_CURRENT_ERROR; - sense->flags = SSD_KEY_ILLEGAL_REQUEST; - sense->add_sense_code = 0x24; - sense->extra_len = 10; - ccb->csio.scsi_status = SCSI_STATUS_CHECK_COND; - ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR | - CAM_AUTOSNS_VALID; - xpt_done(ccb); - return; - } - /* Return fake inquiry data for broken devices */ - if ((sc->quirks & NO_INQUIRY) && rcmd[0] == INQUIRY) { - struct ccb_scsiio *csio = &ccb->csio; - - memcpy(csio->data_ptr, &fake_inq_data, - sizeof(fake_inq_data)); - csio->scsi_status = SCSI_STATUS_OK; - ccb->ccb_h.status = CAM_REQ_CMP; - xpt_done(ccb); - return; - } - if ((sc->quirks & FORCE_SHORT_INQUIRY) && - rcmd[0] == INQUIRY) { - csio->dxfer_len = SHORT_INQUIRY_LENGTH; - } - sc->transfer(sc, ccb->ccb_h.target_lun, rcmd, rcmdlen, - csio->data_ptr, - csio->dxfer_len, dir, ccb->ccb_h.timeout, - umass_cam_cb, (void *) ccb); - } else { - ccb->ccb_h.status = CAM_REQ_INVALID; - xpt_done(ccb); - } - - break; - } - case XPT_PATH_INQ: - { - struct ccb_pathinq *cpi = &ccb->cpi; - - DPRINTF(UDMASS_SCSI, ("%s:%d:%d:%d:XPT_PATH_INQ:.\n", - (sc == NULL ? DEVNAME_SIM : device_get_nameunit(sc->sc_dev)), - (sc == NULL ? 0 : cam_sim_path(sc->umass_sim)), - ccb->ccb_h.target_id, ccb->ccb_h.target_lun)); - - /* host specific information */ - cpi->version_num = 1; - cpi->hba_inquiry = 0; - cpi->target_sprt = 0; - cpi->hba_misc = PIM_NO_6_BYTE; - cpi->hba_eng_cnt = 0; - cpi->max_target = UMASS_SCSIID_MAX; /* one target */ - cpi->initiator_id = UMASS_SCSIID_HOST; - strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN); - strncpy(cpi->hba_vid, "USB SCSI", HBA_IDLEN); - strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN); - cpi->unit_number = cam_sim_unit(sim); - - if (sc == NULL) { - cpi->base_transfer_speed = 0; - cpi->max_lun = 0; - } else { - cpi->bus_id = device_get_unit(sc->sc_dev); - - if (sc->quirks & FLOPPY_SPEED) { - cpi->base_transfer_speed = - UMASS_FLOPPY_TRANSFER_SPEED; - } else if (usbd_get_speed(sc->sc_udev) == - USB_SPEED_HIGH) { - cpi->base_transfer_speed = - UMASS_HIGH_TRANSFER_SPEED; - } else { - cpi->base_transfer_speed = - UMASS_FULL_TRANSFER_SPEED; - } - cpi->max_lun = sc->maxlun; - } - - cpi->ccb_h.status = CAM_REQ_CMP; - xpt_done(ccb); - break; - } - case XPT_RESET_DEV: - { - DPRINTF(UDMASS_SCSI, ("%s:%d:%d:%d:XPT_RESET_DEV:.\n", - device_get_nameunit(sc->sc_dev), cam_sim_path(sc->umass_sim), - ccb->ccb_h.target_id, ccb->ccb_h.target_lun)); - - ccb->ccb_h.status = CAM_REQ_INPROG; - umass_reset(sc, umass_cam_cb, ccb); - break; - } - case XPT_GET_TRAN_SETTINGS: - { - struct ccb_trans_settings *cts = &ccb->cts; - cts->protocol = PROTO_SCSI; - cts->protocol_version = SCSI_REV_2; - cts->transport = XPORT_USB; - cts->transport_version = XPORT_VERSION_UNSPECIFIED; - cts->xport_specific.valid = 0; - - ccb->ccb_h.status = CAM_REQ_CMP; - xpt_done(ccb); - break; - } - case XPT_SET_TRAN_SETTINGS: - { - DPRINTF(UDMASS_SCSI, ("%s:%d:%d:%d:XPT_SET_TRAN_SETTINGS:.\n", - device_get_nameunit(sc->sc_dev), cam_sim_path(sc->umass_sim), - ccb->ccb_h.target_id, ccb->ccb_h.target_lun)); - - ccb->ccb_h.status = CAM_FUNC_NOTAVAIL; - xpt_done(ccb); - break; - } - case XPT_CALC_GEOMETRY: - { - cam_calc_geometry(&ccb->ccg, /*extended*/1); - xpt_done(ccb); - break; - } - case XPT_NOOP: - { - DPRINTF(UDMASS_SCSI, ("%s:%d:%d:%d:XPT_NOOP:.\n", - (sc == NULL ? DEVNAME_SIM : device_get_nameunit(sc->sc_dev)), - (sc == NULL ? 0 : cam_sim_path(sc->umass_sim)), - ccb->ccb_h.target_id, ccb->ccb_h.target_lun)); - - ccb->ccb_h.status = CAM_REQ_CMP; - xpt_done(ccb); - break; - } - default: - DPRINTF(UDMASS_SCSI, ("%s:%d:%d:%d:func_code 0x%04x: " - "Not implemented\n", - (sc == NULL ? DEVNAME_SIM : device_get_nameunit(sc->sc_dev)), - (sc == NULL ? 0 : cam_sim_path(sc->umass_sim)), - ccb->ccb_h.target_id, ccb->ccb_h.target_lun, - ccb->ccb_h.func_code)); - - ccb->ccb_h.status = CAM_FUNC_NOTAVAIL; - xpt_done(ccb); - break; - } -} - -static void -umass_cam_poll(struct cam_sim *sim) -{ - struct umass_softc *sc = (struct umass_softc *) sim->softc; - - KKASSERT(sc != NULL); - - DPRINTF(UDMASS_SCSI, ("%s: CAM poll\n", - device_get_nameunit(sc->sc_dev))); - - usbd_set_polling(sc->sc_udev, 1); - usbd_dopoll(sc->iface); - usbd_set_polling(sc->sc_udev, 0); -} - - -/* umass_cam_cb - * finalise a completed CAM command - */ - -static void -umass_cam_cb(struct umass_softc *sc, void *priv, int residue, int status) -{ - union ccb *ccb = (union ccb *) priv; - struct ccb_scsiio *csio = &ccb->csio; /* deref union */ - - csio->resid = residue; - - switch (status) { - case STATUS_CMD_OK: - ccb->ccb_h.status = CAM_REQ_CMP; - if ((sc->quirks & READ_CAPACITY_OFFBY1) && - (ccb->ccb_h.func_code == XPT_SCSI_IO) && - (csio->cdb_io.cdb_bytes[0] == READ_CAPACITY)) { - struct scsi_read_capacity_data *rcap; - uint32_t maxsector; - - rcap = (struct scsi_read_capacity_data *)csio->data_ptr; - maxsector = scsi_4btoul(rcap->addr) - 1; - scsi_ulto4b(maxsector, rcap->addr); - } - xpt_done(ccb); - break; - - case STATUS_CMD_UNKNOWN: - case STATUS_CMD_FAILED: - switch (ccb->ccb_h.func_code) { - case XPT_SCSI_IO: - { - unsigned char *rcmd; - int rcmdlen; - - /* fetch sense data */ - /* the rest of the command was filled in at attach */ - sc->cam_scsi_sense.length = csio->sense_len; - - DPRINTF(UDMASS_SCSI,("%s: Fetching %db sense data\n", - device_get_nameunit(sc->sc_dev), csio->sense_len)); - - rcmd = (unsigned char *) &sc->cam_scsi_command; - rcmdlen = sizeof(sc->cam_scsi_command); - - if (sc->transform(sc, - (unsigned char *) &sc->cam_scsi_sense, - sizeof(sc->cam_scsi_sense), - &rcmd, &rcmdlen)) { - if ((sc->quirks & FORCE_SHORT_INQUIRY) && (rcmd[0] == INQUIRY)) { - csio->sense_len = SHORT_INQUIRY_LENGTH; - } - sc->transfer(sc, ccb->ccb_h.target_lun, - rcmd, rcmdlen, - &csio->sense_data, - csio->sense_len, DIR_IN, ccb->ccb_h.timeout, - umass_cam_sense_cb, (void *) ccb); - } else { - panic("transform(REQUEST_SENSE) failed"); - } - break; - } - case XPT_RESET_DEV: /* Reset failed */ - ccb->ccb_h.status = CAM_REQ_CMP_ERR; - xpt_done(ccb); - break; - default: - panic("umass_cam_cb called for func_code %d", - ccb->ccb_h.func_code); - } - break; - - case STATUS_WIRE_FAILED: - /* the wire protocol failed and will have recovered - * (hopefully). We return an error to CAM and let CAM retry - * the command if necessary. - */ - ccb->ccb_h.status = CAM_REQ_CMP_ERR; - xpt_done(ccb); - break; - default: - panic("%s: Unknown status %d in umass_cam_cb", - device_get_nameunit(sc->sc_dev), status); - } -} - -/* Finalise a completed autosense operation - */ -static void -umass_cam_sense_cb(struct umass_softc *sc, void *priv, int residue, int status) -{ - union ccb *ccb = (union ccb *) priv; - struct ccb_scsiio *csio = &ccb->csio; /* deref union */ - unsigned char *rcmd; - int rcmdlen; - - switch (status) { - case STATUS_CMD_OK: - case STATUS_CMD_UNKNOWN: - case STATUS_CMD_FAILED: - /* Getting sense data always succeeds (apart from wire - * failures). - */ - if ((sc->quirks & RS_NO_CLEAR_UA) - && csio->cdb_io.cdb_bytes[0] == INQUIRY - && (csio->sense_data.flags & SSD_KEY) - == SSD_KEY_UNIT_ATTENTION) { - /* Ignore unit attention errors in the case where - * the Unit Attention state is not cleared on - * REQUEST SENSE. They will appear again at the next - * command. - */ - ccb->ccb_h.status = CAM_REQ_CMP; - } else if ((csio->sense_data.flags & SSD_KEY) - == SSD_KEY_NO_SENSE) { - /* No problem after all (in the case of CBI without - * CCI) - */ - ccb->ccb_h.status = CAM_REQ_CMP; - } else if ((sc->quirks & RS_NO_CLEAR_UA) && - (csio->cdb_io.cdb_bytes[0] == READ_CAPACITY) && - ((csio->sense_data.flags & SSD_KEY) - == SSD_KEY_UNIT_ATTENTION)) { - /* - * Some devices do not clear the unit attention error - * on request sense. We insert a test unit ready - * command to make sure we clear the unit attention - * condition, then allow the retry to proceed as - * usual. - */ - - ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR - | CAM_AUTOSNS_VALID; - csio->scsi_status = SCSI_STATUS_CHECK_COND; - -#if 0 - DELAY(300000); -#endif - - DPRINTF(UDMASS_SCSI,("%s: Doing a sneaky" - "TEST_UNIT_READY\n", - device_get_nameunit(sc->sc_dev))); - - /* the rest of the command was filled in at attach */ - - rcmd = (unsigned char *) &sc->cam_scsi_command2; - rcmdlen = sizeof(sc->cam_scsi_command2); - - if (sc->transform(sc, - (unsigned char *) - &sc->cam_scsi_test_unit_ready, - sizeof(sc->cam_scsi_test_unit_ready), - &rcmd, &rcmdlen)) { - sc->transfer(sc, ccb->ccb_h.target_lun, - rcmd, rcmdlen, - NULL, 0, DIR_NONE, ccb->ccb_h.timeout, - umass_cam_quirk_cb, (void *) ccb); - } else { - panic("transform(TEST_UNIT_READY) failed"); - } - break; - } else { - ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR - | CAM_AUTOSNS_VALID; - csio->scsi_status = SCSI_STATUS_CHECK_COND; - } - xpt_done(ccb); - break; - - default: - DPRINTF(UDMASS_SCSI, ("%s: Autosense failed, status %d\n", - device_get_nameunit(sc->sc_dev), status)); - ccb->ccb_h.status = CAM_AUTOSENSE_FAIL; - xpt_done(ccb); - } -} - -/* - * This completion code just handles the fact that we sent a test-unit-ready - * after having previously failed a READ CAPACITY with CHECK_COND. Even - * though this command succeeded, we have to tell CAM to retry. - */ -static void -umass_cam_quirk_cb(struct umass_softc *sc, void *priv, int residue, int status) -{ - union ccb *ccb = (union ccb *) priv; - - DPRINTF(UDMASS_SCSI, ("%s: Test unit ready returned status %d\n", - device_get_nameunit(sc->sc_dev), status)); -#if 0 - ccb->ccb_h.status = CAM_REQ_CMP; -#endif - ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR - | CAM_AUTOSNS_VALID; - ccb->csio.scsi_status = SCSI_STATUS_CHECK_COND; - xpt_done(ccb); -} - -static int -umass_driver_load(module_t mod, int what, void *arg) -{ - switch (what) { - case MOD_UNLOAD: - case MOD_LOAD: - default: - return(usbd_driver_load(mod, what, arg)); - } -} - -/* - * SCSI specific functions - */ - -static int -umass_scsi_transform(struct umass_softc *sc, unsigned char *cmd, int cmdlen, - unsigned char **rcmd, int *rcmdlen) -{ - switch (cmd[0]) { - case TEST_UNIT_READY: - if (sc->quirks & NO_TEST_UNIT_READY) { - KASSERT(*rcmdlen >= sizeof(struct scsi_start_stop_unit), - ("rcmdlen = %d < %ld, buffer too small", - *rcmdlen, - (long)sizeof(struct scsi_start_stop_unit))); - DPRINTF(UDMASS_SCSI, ("%s: Converted TEST_UNIT_READY " - "to START_UNIT\n", device_get_nameunit(sc->sc_dev))); - memset(*rcmd, 0, *rcmdlen); - (*rcmd)[0] = START_STOP_UNIT; - (*rcmd)[4] = SSS_START; - return 1; - } - /* fallthrough */ - case INQUIRY: - /* some drives wedge when asked for full inquiry information. */ - if (sc->quirks & FORCE_SHORT_INQUIRY) { - memcpy(*rcmd, cmd, cmdlen); - *rcmdlen = cmdlen; - (*rcmd)[4] = SHORT_INQUIRY_LENGTH; - return 1; - } - /* fallthrough */ - default: - *rcmd = cmd; /* We don't need to copy it */ - *rcmdlen = cmdlen; - } - - return 1; -} -/* RBC specific functions */ -static int -umass_rbc_transform(struct umass_softc *sc, unsigned char *cmd, int cmdlen, - unsigned char **rcmd, int *rcmdlen) -{ - switch (cmd[0]) { - /* these commands are defined in RBC: */ - case READ_10: - case READ_CAPACITY: - case START_STOP_UNIT: - case SYNCHRONIZE_CACHE: - case WRITE_10: - case 0x2f: /* VERIFY_10 is absent from scsi_all.h??? */ - case INQUIRY: - case MODE_SELECT_10: - case MODE_SENSE_10: - case TEST_UNIT_READY: - case WRITE_BUFFER: - /* The following commands are not listed in my copy of the RBC specs. - * CAM however seems to want those, and at least the Sony DSC device - * appears to support those as well */ - case REQUEST_SENSE: - case PREVENT_ALLOW: - *rcmd = cmd; /* We don't need to copy it */ - *rcmdlen = cmdlen; - return 1; - /* All other commands are not legal in RBC */ - default: - kprintf("%s: Unsupported RBC command 0x%02x", - device_get_nameunit(sc->sc_dev), cmd[0]); - kprintf("\n"); - return 0; /* failure */ - } -} - -/* - * UFI specific functions - */ -static int -umass_ufi_transform(struct umass_softc *sc, unsigned char *cmd, int cmdlen, - unsigned char **rcmd, int *rcmdlen) -{ - /* A UFI command is always 12 bytes in length */ - KASSERT(*rcmdlen >= UFI_COMMAND_LENGTH, - ("rcmdlen = %d < %d, buffer too small", - *rcmdlen, UFI_COMMAND_LENGTH)); - - *rcmdlen = UFI_COMMAND_LENGTH; - memset(*rcmd, 0, UFI_COMMAND_LENGTH); - - switch (cmd[0]) { - /* Commands of which the format has been verified. They should work. - * Copy the command into the (zeroed out) destination buffer. - */ - case TEST_UNIT_READY: - if (sc->quirks & NO_TEST_UNIT_READY) { - /* Some devices do not support this command. - * Start Stop Unit should give the same results - */ - DPRINTF(UDMASS_UFI, ("%s: Converted TEST_UNIT_READY " - "to START_UNIT\n", device_get_nameunit(sc->sc_dev))); - (*rcmd)[0] = START_STOP_UNIT; - (*rcmd)[4] = SSS_START; - } else { - memcpy(*rcmd, cmd, cmdlen); - } - return 1; - - case REZERO_UNIT: - case REQUEST_SENSE: - case INQUIRY: - case START_STOP_UNIT: - case SEND_DIAGNOSTIC: - case PREVENT_ALLOW: - case READ_CAPACITY: - case READ_10: - case WRITE_10: - case POSITION_TO_ELEMENT: /* SEEK_10 */ - case MODE_SELECT_10: - case MODE_SENSE_10: - case READ_12: - case WRITE_12: - memcpy(*rcmd, cmd, cmdlen); - return 1; - - /* Other UFI commands: FORMAT_UNIT, READ_FORMAT_CAPACITY, - * VERIFY, WRITE_AND_VERIFY. - * These should be checked whether they somehow can be made to fit. - */ - - default: - kprintf("%s: Unsupported UFI command 0x%02x\n", - device_get_nameunit(sc->sc_dev), cmd[0]); - return 0; /* failure */ - } -} - -/* - * 8070i (ATAPI) specific functions - */ -static int -umass_atapi_transform(struct umass_softc *sc, unsigned char *cmd, int cmdlen, - unsigned char **rcmd, int *rcmdlen) -{ - /* An ATAPI command is always 12 bytes in length. */ - KASSERT(*rcmdlen >= ATAPI_COMMAND_LENGTH, - ("rcmdlen = %d < %d, buffer too small", - *rcmdlen, ATAPI_COMMAND_LENGTH)); - - *rcmdlen = ATAPI_COMMAND_LENGTH; - memset(*rcmd, 0, ATAPI_COMMAND_LENGTH); - - switch (cmd[0]) { - /* Commands of which the format has been verified. They should work. - * Copy the command into the (zeroed out) destination buffer. - */ - case INQUIRY: - memcpy(*rcmd, cmd, cmdlen); - /* some drives wedge when asked for full inquiry information. */ - if (sc->quirks & FORCE_SHORT_INQUIRY) - (*rcmd)[4] = SHORT_INQUIRY_LENGTH; - return 1; - - case TEST_UNIT_READY: - if (sc->quirks & NO_TEST_UNIT_READY) { - KASSERT(*rcmdlen >= sizeof(struct scsi_start_stop_unit), - ("rcmdlen = %d < %ld, buffer too small", - *rcmdlen, - (long)sizeof(struct scsi_start_stop_unit))); - DPRINTF(UDMASS_SCSI, ("%s: Converted TEST_UNIT_READY " - "to START_UNIT\n", device_get_nameunit(sc->sc_dev))); - memset(*rcmd, 0, *rcmdlen); - (*rcmd)[0] = START_STOP_UNIT; - (*rcmd)[4] = SSS_START; - return 1; - } - /* fallthrough */ - default: - /* - * All commands are passed through, very likely it will just work - * regardless whether we know these commands or not. - */ - memcpy(*rcmd, cmd, cmdlen); - return 1; - } -} - - -/* (even the comment is missing) */ - -DRIVER_MODULE(umass, uhub, umass_driver, umass_devclass, umass_driver_load, NULL); - - - -#ifdef USB_DEBUG -static void -umass_bbb_dump_cbw(struct umass_softc *sc, umass_bbb_cbw_t *cbw) -{ - int clen = cbw->bCDBLength; - int dlen = UGETDW(cbw->dCBWDataTransferLength); - u_int8_t *c = cbw->CBWCDB; - int tag = UGETDW(cbw->dCBWTag); - int flags = cbw->bCBWFlags; - - DPRINTF(UDMASS_BBB, ("%s: CBW %d: cmd = %db " - "(0x%02x%02x%02x%02x%02x%02x%s), " - "data = %db, dir = %s\n", - device_get_nameunit(sc->sc_dev), tag, clen, - c[0], c[1], c[2], c[3], c[4], c[5], (clen > 6? "...":""), - dlen, (flags == CBWFLAGS_IN? "in": - (flags == CBWFLAGS_OUT? "out":"")))); -} - -static void -umass_bbb_dump_csw(struct umass_softc *sc, umass_bbb_csw_t *csw) -{ - int sig = UGETDW(csw->dCSWSignature); - int tag = UGETW(csw->dCSWTag); - int res = UGETDW(csw->dCSWDataResidue); - int status = csw->bCSWStatus; - - DPRINTF(UDMASS_BBB, ("%s: CSW %d: sig = 0x%08x (%s), tag = %d, " - "res = %d, status = 0x%02x (%s)\n", device_get_nameunit(sc->sc_dev), - tag, sig, (sig == CSWSIGNATURE? "valid":"invalid"), - tag, res, - status, (status == CSWSTATUS_GOOD? "good": - (status == CSWSTATUS_FAILED? "failed": - (status == CSWSTATUS_PHASE? "phase":""))))); -} - -static void -umass_cbi_dump_cmd(struct umass_softc *sc, void *cmd, int cmdlen) -{ - u_int8_t *c = cmd; - int dir = sc->transfer_dir; - - DPRINTF(UDMASS_BBB, ("%s: cmd = %db " - "(0x%02x%02x%02x%02x%02x%02x%s), " - "data = %db, dir = %s\n", - device_get_nameunit(sc->sc_dev), cmdlen, - c[0], c[1], c[2], c[3], c[4], c[5], (cmdlen > 6? "...":""), - sc->transfer_datalen, - (dir == DIR_IN? "in": - (dir == DIR_OUT? "out": - (dir == DIR_NONE? "no data phase": ""))))); -} - -static void -umass_dump_buffer(struct umass_softc *sc, u_int8_t *buffer, int buflen, - int printlen) -{ - int i, j; - char s1[40]; - char s2[40]; - char s3[5]; - - s1[0] = '\0'; - s3[0] = '\0'; - - ksprintf(s2, " buffer=%p, buflen=%d", buffer, buflen); - for (i = 0; i < buflen && i < printlen; i++) { - j = i % 16; - if (j == 0 && i != 0) { - DPRINTF(UDMASS_GEN, ("%s: 0x %s%s\n", - device_get_nameunit(sc->sc_dev), s1, s2)); - s2[0] = '\0'; - } - ksprintf(&s1[j*2], "%02x", buffer[i] & 0xff); - } - if (buflen > printlen) - ksprintf(s3, " ..."); - DPRINTF(UDMASS_GEN, ("%s: 0x %s%s%s\n", - device_get_nameunit(sc->sc_dev), s1, s2, s3)); -} -#endif diff --git a/sys/dev/usbmisc/umct/Makefile b/sys/dev/usbmisc/umct/Makefile deleted file mode 100644 index f49b292bca..0000000000 --- a/sys/dev/usbmisc/umct/Makefile +++ /dev/null @@ -1,9 +0,0 @@ -# $FreeBSD: src/sys/modules/umct/Makefile,v 1.1.2.2 2002/08/11 20:05:20 joe Exp $ -# $DragonFly: src/sys/dev/usbmisc/umct/Makefile,v 1.1 2006/12/13 20:19:06 dillon Exp $ - -.PATH: ${.CURDIR}/../ucom - -KMOD= umct -SRCS= umct.c ucomvar.h opt_usb.h device_if.h bus_if.h - -.include diff --git a/sys/dev/usbmisc/umct/umct.c b/sys/dev/usbmisc/umct/umct.c deleted file mode 100644 index ef76d57d12..0000000000 --- a/sys/dev/usbmisc/umct/umct.c +++ /dev/null @@ -1,501 +0,0 @@ -/*- - * Copyright (c) 2003 Scott Long - * 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: src/sys/dev/usb/umct.c,v 1.12 2006/09/07 00:06:42 imp Exp $ - */ - -/* - * Driver for the MCT (Magic Control Technology) USB-RS232 Converter. - * Based on the superb documentation from the linux mct_u232 driver by - * Wolfgang Grandeggar . - * This device smells a lot like the Belkin F5U103, except that it has - * suffered some mild brain-damage. This driver is based off of the ubsa.c - * driver from Alexander Kabaev . Merging the two together - * might be useful, though the subtle differences might lead to lots of - * #ifdef's. - */ - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include "../ucom/ucomvar.h" - -/* The UMCT advertises the standard 8250 UART registers */ -#define UMCT_GET_MSR 2 /* Get Modem Status Register */ -#define UMCT_GET_MSR_SIZE 1 -#define UMCT_GET_LCR 6 /* Get Line Control Register */ -#define UMCT_GET_LCR_SIZE 1 -#define UMCT_SET_BAUD 5 /* Set the Baud Rate Divisor */ -#define UMCT_SET_BAUD_SIZE 4 -#define UMCT_SET_LCR 7 /* Set Line Control Register */ -#define UMCT_SET_LCR_SIZE 1 -#define UMCT_SET_MCR 10 /* Set Modem Control Register */ -#define UMCT_SET_MCR_SIZE 1 -#define UMCT_SET_UNKNOWN1 11 -#define UMCT_SET_UNKNOWN1_SIZE 1 -#define UMCT_SET_UNKNOWN2 12 -#define UMCT_SET_UNKNOWN2_SIZE 1 - - -#define UMCT_INTR_INTERVAL 100 -#define UMCT_IFACE_INDEX 0 -#define UMCT_CONFIG_INDEX 1 - -struct umct_softc { - struct ucom_softc sc_ucom; - int sc_iface_number; - usbd_interface_handle sc_intr_iface; - int sc_intr_number; - usbd_pipe_handle sc_intr_pipe; - u_char *sc_intr_buf; - int sc_isize; - uint8_t sc_lsr; - uint8_t sc_msr; - uint8_t sc_lcr; - uint8_t sc_mcr; - struct task sc_task; -}; - -static void umct_intr(usbd_xfer_handle, usbd_private_handle, usbd_status); -static void umct_get_status(void *, int, u_char *, u_char *); -static void umct_set(void *, int, int, int); -static int umct_param(void *, int, struct termios *); -static int umct_open(void *, int); -static void umct_close(void *, int); -static void umct_notify(void *, int); - -static struct ucom_callback umct_callback = { - umct_get_status, /* ucom_get_status */ - umct_set, /* ucom_set */ - umct_param, /* ucom_param */ - NULL, /* ucom_ioctl */ - umct_open, /* ucom_open */ - umct_close, /* ucom_close */ - NULL, /* ucom_read */ - NULL /* ucom_write */ -}; - -static const struct usb_devno umct_products[] = { - { USB_DEVICE(0x050d, 0x0109) }, /* Belkin F5U109 */ - { USB_DEVICE(0x050d, 0x0409) }, /* Belkin F5U409 */ - { USB_DEVICE(0x0711, 0x0200) }, /* D-Link DU-H3SP USB BAY Hub */ - { USB_DEVICE(0x0711, 0x0210) }, /* MCT USB-232 */ - { USB_DEVICE(0x0711, 0x0230) }, /* Sitecom USB-232 */ -}; - -static device_probe_t umct_match; -static device_attach_t umct_attach; -static device_detach_t umct_detach; - -static device_method_t umct_methods[] = { - DEVMETHOD(device_probe, umct_match), - DEVMETHOD(device_attach, umct_attach), - DEVMETHOD(device_detach, umct_detach), - DEVMETHOD_END -}; - -static driver_t umct_driver = { - "ucom", - umct_methods, - sizeof(struct umct_softc) -}; - -DRIVER_MODULE(umct, uhub, umct_driver, ucom_devclass, usbd_driver_load, NULL); -MODULE_DEPEND(umct, usb, 1, 1, 1); -MODULE_DEPEND(umct, ucom, UCOM_MINVER, UCOM_PREFVER, UCOM_MAXVER); -MODULE_VERSION(umct, 1); - -static int -umct_match(device_t self) -{ - struct usb_attach_arg *uaa = device_get_ivars(self); - - if (uaa->iface != NULL) - return (UMATCH_NONE); - - return (usb_lookup(umct_products, uaa->vendor, uaa->product) != NULL) ? - UMATCH_VENDOR_PRODUCT : UMATCH_NONE; -} - -static int -umct_attach(device_t self) -{ - struct umct_softc *sc = device_get_softc(self); - struct usb_attach_arg *uaa = device_get_ivars(self); - usbd_device_handle dev; - struct ucom_softc *ucom; - usb_config_descriptor_t *cdesc; - usb_interface_descriptor_t *id; - usb_endpoint_descriptor_t *ed; - usbd_status err; - int i; - - dev = uaa->device; - bzero(sc, sizeof(struct umct_softc)); - ucom = &sc->sc_ucom; - ucom->sc_dev = self; - ucom->sc_udev = dev; - ucom->sc_iface = uaa->iface; - - ucom->sc_bulkout_no = -1; - ucom->sc_bulkin_no = -1; - sc->sc_intr_number = -1; - sc->sc_intr_pipe = NULL; - - err = usbd_set_config_index(dev, UMCT_CONFIG_INDEX, 1); - if (err) { - device_printf(ucom->sc_dev, "failed to set configuration: %s\n", - usbd_errstr(err)); - ucom->sc_dying = 1; - goto error; - } - - cdesc = usbd_get_config_descriptor(ucom->sc_udev); - if (cdesc == NULL) { - device_printf(ucom->sc_dev, "failed to get configuration " - "descriptor\n"); - ucom->sc_dying = 1; - goto error; - } - - err = usbd_device2interface_handle(dev, UMCT_IFACE_INDEX, - &ucom->sc_iface); - if (err) { - device_printf(ucom->sc_dev, "failed to get interface: %s\n", - usbd_errstr(err)); - ucom->sc_dying = 1; - goto error; - } - - id = usbd_get_interface_descriptor(ucom->sc_iface); - sc->sc_iface_number = id->bInterfaceNumber; - - for (i = 0; i < id->bNumEndpoints; i++) { - ed = usbd_interface2endpoint_descriptor(ucom->sc_iface, i); - if (ed == NULL) { - device_printf(ucom->sc_dev, "no endpoint descriptor " - "for %d\n", i); - ucom->sc_dying = 1; - goto error; - } - - /* - * The real bulk-in endpoint is also marked as an interrupt. - * The only way to differentiate it from the real interrupt - * endpoint is to look at the wMaxPacketSize field. - */ - if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN) { - if (UGETW(ed->wMaxPacketSize) == 0x2) { - sc->sc_intr_number = ed->bEndpointAddress; - sc->sc_isize = UGETW(ed->wMaxPacketSize); - } else { - ucom->sc_bulkin_no = ed->bEndpointAddress; - ucom->sc_ibufsize = UGETW(ed->wMaxPacketSize); - } - continue; - } - - if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT) { - ucom->sc_bulkout_no = ed->bEndpointAddress; - /* MCT Sitecom USB-232 device is broken. The bulk out - * endpoint descriptor reports 32 bytes, but data will - * get dropped if this value is used. */ - if (uaa->vendor == 0x0711 && uaa->product == 0x0230) - ucom->sc_obufsize = 16; - else - ucom->sc_obufsize = UGETW(ed->wMaxPacketSize); - continue; - } - - device_printf(ucom->sc_dev, "warning - unsupported endpoint " - "0x%x\n", ed->bEndpointAddress); - } - - if (sc->sc_intr_number == -1) { - device_printf(ucom->sc_dev, "could not find interrupt in\n"); - ucom->sc_dying = 1; - goto error; - } - - sc->sc_intr_iface = ucom->sc_iface; - - if (ucom->sc_bulkout_no == -1) { - device_printf(ucom->sc_dev, "rould not find data bulk out\n"); - ucom->sc_dying = 1; - goto error; - } - - ucom->sc_parent = sc; - ucom->sc_portno = UCOM_UNK_PORTNO; - ucom->sc_opkthdrlen = 0; - ucom->sc_callback = &umct_callback; - TASK_INIT(&sc->sc_task, 0, umct_notify, sc); - ucom_attach(ucom); - - return 0; - -error: - return ENXIO; -} - -static int -umct_detach(device_t self) -{ - struct umct_softc *sc = device_get_softc(self); - int rv; - - if (sc->sc_intr_pipe != NULL) { - usbd_abort_pipe(sc->sc_intr_pipe); - usbd_close_pipe(sc->sc_intr_pipe); - kfree(sc->sc_intr_buf, M_USBDEV); - sc->sc_intr_pipe = NULL; - } - - sc->sc_ucom.sc_dying = 1; - rv = ucom_detach(&sc->sc_ucom); - return (rv); -} - -static int -umct_request(struct umct_softc *sc, uint8_t request, int len, uint32_t value) -{ - usb_device_request_t req; - usbd_status err; - uint8_t oval[4]; - - req.bmRequestType = UT_WRITE_VENDOR_DEVICE; - req.bRequest = request; - USETW(req.wValue, 0); - USETW(req.wIndex, sc->sc_iface_number); - USETW(req.wLength, len); - USETDW(oval, value); - - err = usbd_do_request(sc->sc_ucom.sc_udev, &req, oval); - if (err) - device_printf(sc->sc_ucom.sc_dev, "ubsa_request: %s\n", - usbd_errstr(err)); - return (err); -} - -static void -umct_intr(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status) -{ - struct umct_softc *sc; - u_char *buf; - - sc = (struct umct_softc *)priv; - buf = sc->sc_intr_buf; - if (sc->sc_ucom.sc_dying) - return; - - if (status != USBD_NORMAL_COMPLETION) { - if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) - return; - - usbd_clear_endpoint_stall_async(sc->sc_intr_pipe); - return; - } - - sc->sc_msr = buf[0]; - sc->sc_lsr = buf[1]; - - /* - * Defer notifying the ucom layer as it doesn't like to be bothered - * from an interrupt context. - */ - taskqueue_enqueue(taskqueue_swi, &sc->sc_task); -} - -static void -umct_notify(void *arg, int count) -{ - struct umct_softc *sc; - - sc = (struct umct_softc *)arg; - if (sc->sc_ucom.sc_dying == 0) - ucom_status_change(&sc->sc_ucom); -} - -static void -umct_get_status(void *addr, int portno, u_char *lsr, u_char *msr) -{ - struct umct_softc *sc; - - sc = addr; - if (lsr != NULL) - *lsr = sc->sc_lsr; - if (msr != NULL) - *msr = sc->sc_msr; - - return; -} - -static void -umct_set(void *addr, int portno, int reg, int onoff) -{ - struct umct_softc *sc; - - sc = addr; - switch (reg) { - case UCOM_SET_BREAK: - sc->sc_lcr &= ~0x40; - sc->sc_lcr |= (onoff) ? 0x40 : 0; - umct_request(sc, UMCT_SET_LCR, UMCT_SET_LCR_SIZE, sc->sc_lcr); - break; - case UCOM_SET_DTR: - sc->sc_mcr &= ~0x01; - sc->sc_mcr |= (onoff) ? 0x01 : 0; - umct_request(sc, UMCT_SET_MCR, UMCT_SET_MCR_SIZE, sc->sc_mcr); - break; - case UCOM_SET_RTS: - sc->sc_mcr &= ~0x2; - sc->sc_mcr |= (onoff) ? 0x02 : 0; - umct_request(sc, UMCT_SET_MCR, UMCT_SET_MCR_SIZE, sc->sc_mcr); - break; - default: - break; - } -} - -static int -umct_calc_baud(u_int baud) -{ - switch(baud) { - case B300: return (0x1); - case B600: return (0x2); - case B1200: return (0x3); - case B2400: return (0x4); - case B4800: return (0x6); - case B9600: return (0x8); - case B19200: return (0x9); - case B38400: return (0xa); - case B57600: return (0xb); - case B115200: return (0xc); - case B0: - default: - break; - } - - return (0x0); -} - -static int -umct_param(void *addr, int portno, struct termios *ti) -{ - struct umct_softc *sc; - uint32_t value; - - sc = addr; - value = umct_calc_baud(ti->c_ospeed); - umct_request(sc, UMCT_SET_BAUD, UMCT_SET_BAUD_SIZE, value); - umct_request(sc, UMCT_SET_UNKNOWN1, UMCT_SET_UNKNOWN1_SIZE, 0); - umct_request(sc, UMCT_SET_UNKNOWN2, UMCT_SET_UNKNOWN2_SIZE, 0); - - value = sc->sc_lcr & 0x40; - - switch (ti->c_cflag & CSIZE) { - case CS5: value |= 0x0; break; - case CS6: value |= 0x1; break; - case CS7: value |= 0x2; break; - case CS8: value |= 0x3; break; - default: value |= 0x0; break; - } - - value |= (ti->c_cflag & CSTOPB) ? 0x4 : 0; - if (ti->c_cflag & PARENB) { - value |= 0x8; - value |= (ti->c_cflag & PARODD) ? 0x0 : 0x10; - } - - /* - * XXX There doesn't seem to be a way to tell the device to use flow - * control. - */ - - sc->sc_lcr = value; - umct_request(sc, UMCT_SET_LCR, UMCT_SET_LCR_SIZE, value); - - return (0); -} - -static int -umct_open(void *addr, int portno) -{ - struct umct_softc *sc; - int err; - - sc = addr; - if (sc->sc_ucom.sc_dying) { - return (ENXIO); - } - - if (sc->sc_intr_number != -1 && sc->sc_intr_pipe == NULL) { - sc->sc_intr_buf = kmalloc(sc->sc_isize, M_USBDEV, M_WAITOK); - err = usbd_open_pipe_intr(sc->sc_intr_iface, sc->sc_intr_number, - USBD_SHORT_XFER_OK, &sc->sc_intr_pipe, sc, sc->sc_intr_buf, - sc->sc_isize, umct_intr, UMCT_INTR_INTERVAL); - if (err) { - device_printf(sc->sc_ucom.sc_dev, "cannot open " - "interrupt pipe (addr %d)\n", - sc->sc_intr_number); - kfree(sc->sc_intr_buf, M_USBDEV); - return (EIO); - } - } - - return (0); -} - -static void -umct_close(void *addr, int portno) -{ - struct umct_softc *sc; - int err; - - sc = addr; - if (sc->sc_ucom.sc_dying) - return; - - if (sc->sc_intr_pipe != NULL) { - err = usbd_abort_pipe(sc->sc_intr_pipe); - if (err) - device_printf(sc->sc_ucom.sc_dev, "abort interrupt " - "pipe failed: %s\n", usbd_errstr(err)); - err = usbd_close_pipe(sc->sc_intr_pipe); - if (err) - device_printf(sc->sc_ucom.sc_dev, "close interrupt " - "pipe failed: %s\n", usbd_errstr(err)); - kfree(sc->sc_intr_buf, M_USBDEV); - sc->sc_intr_pipe = NULL; - } -} diff --git a/sys/dev/usbmisc/umodem/Makefile b/sys/dev/usbmisc/umodem/Makefile deleted file mode 100644 index 5a245ebf81..0000000000 --- a/sys/dev/usbmisc/umodem/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -# $FreeBSD: src/sys/modules/umodem/Makefile,v 1.7 1999/11/28 18:53:35 bde Exp $ -# $DragonFly: src/sys/dev/usbmisc/umodem/Makefile,v 1.4 2004/08/13 17:51:07 dillon Exp $ - -.PATH: ${.CURDIR}/../../dev/usb -KMOD = umodem -SRCS = bus_if.h device_if.h opt_usb.h umodem.c - -.include diff --git a/sys/dev/usbmisc/umodem/umodem.c b/sys/dev/usbmisc/umodem/umodem.c deleted file mode 100644 index 6568d65db2..0000000000 --- a/sys/dev/usbmisc/umodem/umodem.c +++ /dev/null @@ -1,774 +0,0 @@ -/* - * $NetBSD: umodem.c,v 1.45 2002/09/23 05:51:23 simonb Exp $ - * $FreeBSD: src/sys/dev/usb/umodem.c,v 1.48 2003/08/24 17:55:55 obrien Exp $ - */ - -/*- - * Copyright (c) 2003, M. Warner Losh . - * 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. - */ - -/* - * Copyright (c) 1998 The NetBSD Foundation, Inc. - * All rights reserved. - * - * This code is derived from software contributed to The NetBSD Foundation - * by Lennart Augustsson (lennart@augustsson.net) at - * Carlstedt Research & Technology. - * - * 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. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the NetBSD - * Foundation, Inc. and its contributors. - * 4. Neither the name of The NetBSD Foundation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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. - */ - -/* - * Comm Class spec: http://www.usb.org/developers/devclass_docs/usbccs10.pdf - * http://www.usb.org/developers/devclass_docs/usbcdc11.pdf - */ - -/* - * TODO: - * - Add error recovery in various places; the big problem is what - * to do in a callback if there is an error. - * - Implement a Call Device for modems without multiplexed commands. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include -#include -#include - -#ifdef USB_DEBUG -int umodemdebug = 0; -SYSCTL_NODE(_hw_usb, OID_AUTO, umodem, CTLFLAG_RW, 0, "USB umodem"); -SYSCTL_INT(_hw_usb_umodem, OID_AUTO, debug, CTLFLAG_RW, - &umodemdebug, 0, "umodem debug level"); -#define DPRINTFN(n, x) do { if (umodemdebug > (n)) kprintf x; } while (0) -#else -#define DPRINTFN(n, x) -#endif -#define DPRINTF(x) DPRINTFN(0, x) - -/* - * These are the maximum number of bytes transferred per frame. These - * values were increased from 64/256 used in older versions of the driver - * to better support EVDO wireless PPP. Old values were good enough for - * normal modems, but not for really high speed devices. - * - * The sizes should not be increased further, or there will be problems - * with contiguous storage allocation. - */ -#define UMODEMIBUFSIZE 4096 -#define UMODEMOBUFSIZE 4096 - -#define UMODEM_MODVER 1 /* module version */ - -struct umodem_softc { - struct ucom_softc sc_ucom; - - device_t sc_dev; /* base device */ - - usbd_device_handle sc_udev; /* USB device */ - - int sc_ctl_iface_no; - usbd_interface_handle sc_ctl_iface; /* control interface */ - int sc_data_iface_no; - usbd_interface_handle sc_data_iface; /* data interface */ - - int sc_cm_cap; /* CM capabilities */ - int sc_acm_cap; /* ACM capabilities */ - - int sc_cm_over_data; - - usb_cdc_line_state_t sc_line_state; /* current line state */ - u_char sc_dtr; /* current DTR state */ - u_char sc_rts; /* current RTS state */ - - u_char sc_opening; /* lock during open */ - - int sc_ctl_notify; /* Notification endpoint */ - usbd_pipe_handle sc_notify_pipe; /* Notification pipe */ - usb_cdc_notification_t sc_notify_buf; /* Notification structure */ - u_char sc_lsr; /* Local status register */ - u_char sc_msr; /* Modem status register */ -}; - -static usbd_status umodem_set_comm_feature(struct umodem_softc *sc, - int feature, int state); -static usbd_status umodem_set_line_coding(struct umodem_softc *sc, - usb_cdc_line_state_t *state); - -static int umodem_get_caps(usbd_device_handle, int *, int *, - usb_interface_descriptor_t *); - -static void umodem_get_status(void *, int portno, u_char *lsr, u_char *msr); -static void umodem_set(void *, int, int, int); -static void umodem_dtr(struct umodem_softc *, int); -static void umodem_rts(struct umodem_softc *, int); -static void umodem_break(struct umodem_softc *, int); -static void umodem_set_line_state(struct umodem_softc *); -static int umodem_param(void *, int, struct termios *); -static int umodem_ioctl(void *, int, u_long, caddr_t, int, struct thread * ); -static int umodem_open(void *, int portno); -static void umodem_close(void *, int portno); -static void umodem_intr(usbd_xfer_handle, usbd_private_handle, usbd_status); - -static struct ucom_callback umodem_callback = { - umodem_get_status, - umodem_set, - umodem_param, - umodem_ioctl, - umodem_open, - umodem_close, - NULL, - NULL, -}; - -static device_probe_t umodem_match; -static device_attach_t umodem_attach; -static device_detach_t umodem_detach; - -static device_method_t umodem_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, umodem_match), - DEVMETHOD(device_attach, umodem_attach), - DEVMETHOD(device_detach, umodem_detach), - DEVMETHOD_END -}; - -static driver_t umodem_driver = { - "ucom", - umodem_methods, - sizeof (struct umodem_softc) -}; - -DRIVER_MODULE(umodem, uhub, umodem_driver, ucom_devclass, usbd_driver_load, NULL); -MODULE_DEPEND(umodem, usb, 1, 1, 1); -MODULE_DEPEND(umodem, ucom, UCOM_MINVER, UCOM_PREFVER, UCOM_MAXVER); -MODULE_VERSION(umodem, UMODEM_MODVER); - -static int -umodem_match(device_t self) -{ - struct usb_attach_arg *uaa = device_get_ivars(self); - usb_interface_descriptor_t *id; - int cm, acm; - - if (uaa->iface == NULL) - return (UMATCH_NONE); - - id = usbd_get_interface_descriptor(uaa->iface); - if (id == NULL || - id->bInterfaceClass != UICLASS_CDC || - id->bInterfaceSubClass != UISUBCLASS_ABSTRACT_CONTROL_MODEL || - id->bInterfaceProtocol != UIPROTO_CDC_AT) - return (UMATCH_NONE); - - if (umodem_get_caps(uaa->device, &cm, &acm, id) == -1) - return (UMATCH_NONE); - - return (UMATCH_IFACECLASS_IFACESUBCLASS_IFACEPROTO); -} - -static int -umodem_attach(device_t self) -{ - struct umodem_softc *sc = device_get_softc(self); - struct usb_attach_arg *uaa = device_get_ivars(self); - usbd_device_handle dev = uaa->device; - usb_interface_descriptor_t *id; - usb_endpoint_descriptor_t *ed; - const char *devname; - usbd_status err; - int data_ifcno; - int i; - struct ucom_softc *ucom; - - ucom = &sc->sc_ucom; - ucom->sc_dev = self; - sc->sc_dev = self; - ucom->sc_udev = dev; - ucom->sc_iface = uaa->iface; - - sc->sc_udev = dev; - sc->sc_ctl_iface = uaa->iface; - - devname = device_get_nameunit(sc->sc_dev); - /* XXX ? use something else ? XXX */ - id = usbd_get_interface_descriptor(sc->sc_ctl_iface); - sc->sc_ctl_iface_no = id->bInterfaceNumber; - - sc->sc_data_iface_no = data_ifcno = - umodem_get_caps(dev, &sc->sc_cm_cap, &sc->sc_acm_cap, id); - - if (data_ifcno == -1) { - kprintf("%s: no pointer to data interface\n", devname); - goto bad; - } - - kprintf("%s: data interface %d, has %sCM over data, has %sbreak\n", - devname, data_ifcno, - sc->sc_cm_cap & USB_CDC_CM_OVER_DATA ? "" : "no ", - sc->sc_acm_cap & USB_CDC_ACM_HAS_BREAK ? "" : "no "); - - /* Get the data interface too. */ - for (i = 0; i < uaa->nifaces; i++) { - if (uaa->ifaces[i] != NULL) { - id = usbd_get_interface_descriptor(uaa->ifaces[i]); - if (id != NULL && id->bInterfaceNumber == data_ifcno) { - sc->sc_data_iface = uaa->ifaces[i]; - uaa->ifaces[i] = NULL; - } - } - } - if (sc->sc_data_iface == NULL) { - kprintf("%s: no data interface\n", devname); - goto bad; - } - ucom->sc_iface = sc->sc_data_iface; - - /* - * Find the bulk endpoints. - * Iterate over all endpoints in the data interface and take note. - */ - ucom->sc_bulkin_no = ucom->sc_bulkout_no = -1; - - id = usbd_get_interface_descriptor(sc->sc_data_iface); - for (i = 0; i < id->bNumEndpoints; i++) { - ed = usbd_interface2endpoint_descriptor(sc->sc_data_iface, i); - if (ed == NULL) { - kprintf("%s: no endpoint descriptor for %d\n", devname, - i); - goto bad; - } - if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && - UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) { - ucom->sc_bulkin_no = ed->bEndpointAddress; - } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT && - UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) { - ucom->sc_bulkout_no = ed->bEndpointAddress; - } - } - - if (ucom->sc_bulkin_no == -1) { - kprintf("%s: Could not find data bulk in\n", devname); - goto bad; - } - if (ucom->sc_bulkout_no == -1) { - kprintf("%s: Could not find data bulk out\n", devname); - goto bad; - } - - if (usbd_get_quirks(sc->sc_udev)->uq_flags & UQ_ASSUME_CM_OVER_DATA) { - DPRINTF(("Quirk says to assume CM over data\n")); - sc->sc_cm_over_data = 1; - } else { - if (sc->sc_cm_cap & USB_CDC_CM_OVER_DATA) { - if (sc->sc_acm_cap & USB_CDC_ACM_HAS_FEATURE) - err = umodem_set_comm_feature(sc, - UCDC_ABSTRACT_STATE, UCDC_DATA_MULTIPLEXED); - else - err = 0; - if (err) { - kprintf("%s: could not set data multiplex mode\n", - devname); - goto bad; - } - sc->sc_cm_over_data = 1; - } - } - - /* - * The standard allows for notification messages (to indicate things - * like a modem hangup) to come in via an interrupt endpoint - * off of the control interface. Iterate over the endpoints on - * the control interface and see if there are any interrupt - * endpoints; if there are, then register it. - */ - - sc->sc_ctl_notify = -1; - sc->sc_notify_pipe = NULL; - - for (i = 0; i < id->bNumEndpoints; i++) { - ed = usbd_interface2endpoint_descriptor(sc->sc_ctl_iface, i); - if (ed == NULL) - continue; - - if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && - (ed->bmAttributes & UE_XFERTYPE) == UE_INTERRUPT) { - kprintf("%s: status change notification available\n", - devname); - sc->sc_ctl_notify = ed->bEndpointAddress; - } - } - - sc->sc_dtr = -1; - - ucom->sc_parent = sc; - ucom->sc_portno = UCOM_UNK_PORTNO; - /* bulkin, bulkout set above */ - ucom->sc_ibufsize = UMODEMIBUFSIZE; - ucom->sc_obufsize = UMODEMOBUFSIZE; - ucom->sc_ibufsizepad = UMODEMIBUFSIZE; - ucom->sc_opkthdrlen = 0; - ucom->sc_callback = &umodem_callback; - - ucom_attach(&sc->sc_ucom); - - return 0; - - bad: - ucom->sc_dying = 1; - return ENXIO; -} - -static int -umodem_open(void *addr, int portno) -{ - struct umodem_softc *sc = addr; - int err; - - DPRINTF(("umodem_open: sc=%p\n", sc)); - - if (sc->sc_ctl_notify != -1 && sc->sc_notify_pipe == NULL) { - err = usbd_open_pipe_intr(sc->sc_ctl_iface, sc->sc_ctl_notify, - USBD_SHORT_XFER_OK, &sc->sc_notify_pipe, sc, - &sc->sc_notify_buf, sizeof(sc->sc_notify_buf), - umodem_intr, USBD_DEFAULT_INTERVAL); - - if (err) { - DPRINTF(("Failed to establish notify pipe: %s\n", - usbd_errstr(err))); - return EIO; - } - } - - return 0; -} - -static void -umodem_close(void *addr, int portno) -{ - struct umodem_softc *sc = addr; - int err; - - DPRINTF(("umodem_close: sc=%p\n", sc)); - - if (sc->sc_notify_pipe != NULL) { - err = usbd_abort_pipe(sc->sc_notify_pipe); - if (err) - kprintf("%s: abort notify pipe failed: %s\n", - device_get_nameunit(sc->sc_dev), usbd_errstr(err)); - err = usbd_close_pipe(sc->sc_notify_pipe); - if (err) - kprintf("%s: close notify pipe failed: %s\n", - device_get_nameunit(sc->sc_dev), usbd_errstr(err)); - sc->sc_notify_pipe = NULL; - } -} - -static void -umodem_intr(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status) -{ - struct umodem_softc *sc = priv; - u_char mstatus; - - if (sc->sc_ucom.sc_dying) - return; - - if (status != USBD_NORMAL_COMPLETION) { - if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) - return; - kprintf("%s: abnormal status: %s\n", device_get_nameunit(sc->sc_dev), - usbd_errstr(status)); - return; - } - - if (sc->sc_notify_buf.bmRequestType != UCDC_NOTIFICATION) { - DPRINTF(("%s: unknown message type (%02x) on notify pipe\n", - device_get_nameunit(sc->sc_dev), - sc->sc_notify_buf.bmRequestType)); - return; - } - - switch (sc->sc_notify_buf.bNotification) { - case UCDC_N_SERIAL_STATE: - /* - * Set the serial state in ucom driver based on - * the bits from the notify message - */ - if (UGETW(sc->sc_notify_buf.wLength) != 2) { - kprintf("%s: Invalid notification length! (%d)\n", - device_get_nameunit(sc->sc_dev), - UGETW(sc->sc_notify_buf.wLength)); - break; - } - DPRINTF(("%s: notify bytes = %02x%02x\n", - device_get_nameunit(sc->sc_dev), - sc->sc_notify_buf.data[0], - sc->sc_notify_buf.data[1])); - /* Currently, lsr is always zero. */ - sc->sc_lsr = sc->sc_msr = 0; - mstatus = sc->sc_notify_buf.data[0]; - - if (ISSET(mstatus, UCDC_N_SERIAL_RI)) - sc->sc_msr |= UMSR_RI; - if (ISSET(mstatus, UCDC_N_SERIAL_DSR)) - sc->sc_msr |= UMSR_DSR; - if (ISSET(mstatus, UCDC_N_SERIAL_DCD)) - sc->sc_msr |= UMSR_DCD; - ucom_status_change(&sc->sc_ucom); - break; - default: - DPRINTF(("%s: unknown notify message: %02x\n", - device_get_nameunit(sc->sc_dev), - sc->sc_notify_buf.bNotification)); - break; - } -} - -int -umodem_get_caps(usbd_device_handle dev, int *cm, int *acm, - usb_interface_descriptor_t *id) -{ - const usb_cdc_cm_descriptor_t *cmd; - const usb_cdc_acm_descriptor_t *cad; - const usb_cdc_union_descriptor_t *cud; - - *cm = *acm = 0; - - cmd = (const usb_cdc_cm_descriptor_t *)usb_find_desc_if(dev, - UDESC_CS_INTERFACE, - UDESCSUB_CDC_CM, id); - if (cmd == NULL) - DPRINTF(("umodem_get_caps: no CM desc\n")); - else - *cm = cmd->bmCapabilities; - - cad = (const usb_cdc_acm_descriptor_t *)usb_find_desc_if(dev, - UDESC_CS_INTERFACE, - UDESCSUB_CDC_ACM, id); - if (cad == NULL) - DPRINTF(("umodem_get_caps: no ACM desc\n")); - else - *acm = cad->bmCapabilities; - - cud = (const usb_cdc_union_descriptor_t *)usb_find_desc_if(dev, - UDESC_CS_INTERFACE, - UDESCSUB_CDC_UNION, id); - if (cud == NULL) - DPRINTF(("umodem_get_caps: no UNION desc\n")); - - return cmd ? cmd->bDataInterface : cud ? cud->bSlaveInterface[0] : -1; -} - -void -umodem_get_status(void *addr, int portno, u_char *lsr, u_char *msr) -{ - struct umodem_softc *sc = addr; - - DPRINTF(("umodem_get_status:\n")); - - if (lsr != NULL) - *lsr = sc->sc_lsr; - if (msr != NULL) - *msr = sc->sc_msr; -} - -int -umodem_param(void *addr, int portno, struct termios *t) -{ - struct umodem_softc *sc = addr; - usbd_status err; - usb_cdc_line_state_t ls; - - DPRINTF(("umodem_param: sc=%p\n", sc)); - - USETDW(ls.dwDTERate, t->c_ospeed); - if (ISSET(t->c_cflag, CSTOPB)) - ls.bCharFormat = UCDC_STOP_BIT_2; - else - ls.bCharFormat = UCDC_STOP_BIT_1; - if (ISSET(t->c_cflag, PARENB)) { - if (ISSET(t->c_cflag, PARODD)) - ls.bParityType = UCDC_PARITY_ODD; - else - ls.bParityType = UCDC_PARITY_EVEN; - } else - ls.bParityType = UCDC_PARITY_NONE; - switch (ISSET(t->c_cflag, CSIZE)) { - case CS5: - ls.bDataBits = 5; - break; - case CS6: - ls.bDataBits = 6; - break; - case CS7: - ls.bDataBits = 7; - break; - case CS8: - ls.bDataBits = 8; - break; - } - - err = umodem_set_line_coding(sc, &ls); - if (err) { - DPRINTF(("umodem_param: err=%s\n", usbd_errstr(err))); - return (ENOTTY); - } - return (0); -} - -int -umodem_ioctl(void *addr, int portno, u_long cmd, caddr_t data, int flag, - struct thread * p) -{ - struct umodem_softc *sc = addr; - int error = 0; - - if (sc->sc_ucom.sc_dying) - return (EIO); - - DPRINTF(("umodem_ioctl: cmd=0x%08lx\n", cmd)); - - switch (cmd) { - case USB_GET_CM_OVER_DATA: - *(int *)data = sc->sc_cm_over_data; - break; - - case USB_SET_CM_OVER_DATA: - if (*(int *)data != sc->sc_cm_over_data) { - /* XXX change it */ - } - break; - - default: - DPRINTF(("umodem_ioctl: unknown\n")); - error = ENOIOCTL; - break; - } - - return (error); -} - -void -umodem_dtr(struct umodem_softc *sc, int onoff) -{ - DPRINTF(("umodem_dtr: onoff=%d\n", onoff)); - - if (sc->sc_dtr == onoff) - return; - sc->sc_dtr = onoff; - - umodem_set_line_state(sc); -} - -void -umodem_rts(struct umodem_softc *sc, int onoff) -{ - DPRINTF(("umodem_rts: onoff=%d\n", onoff)); - - if (sc->sc_rts == onoff) - return; - sc->sc_rts = onoff; - - umodem_set_line_state(sc); -} - -void -umodem_set_line_state(struct umodem_softc *sc) -{ - usb_device_request_t req; - int ls; - - ls = (sc->sc_dtr ? UCDC_LINE_DTR : 0) | - (sc->sc_rts ? UCDC_LINE_RTS : 0); - req.bmRequestType = UT_WRITE_CLASS_INTERFACE; - req.bRequest = UCDC_SET_CONTROL_LINE_STATE; - USETW(req.wValue, ls); - USETW(req.wIndex, sc->sc_ctl_iface_no); - USETW(req.wLength, 0); - - (void)usbd_do_request(sc->sc_udev, &req, 0); - -} - -void -umodem_break(struct umodem_softc *sc, int onoff) -{ - usb_device_request_t req; - - DPRINTF(("umodem_break: onoff=%d\n", onoff)); - - if (!(sc->sc_acm_cap & USB_CDC_ACM_HAS_BREAK)) - return; - - req.bmRequestType = UT_WRITE_CLASS_INTERFACE; - req.bRequest = UCDC_SEND_BREAK; - USETW(req.wValue, onoff ? UCDC_BREAK_ON : UCDC_BREAK_OFF); - USETW(req.wIndex, sc->sc_ctl_iface_no); - USETW(req.wLength, 0); - - (void)usbd_do_request(sc->sc_udev, &req, 0); -} - -void -umodem_set(void *addr, int portno, int reg, int onoff) -{ - struct umodem_softc *sc = addr; - - switch (reg) { - case UCOM_SET_DTR: - umodem_dtr(sc, onoff); - break; - case UCOM_SET_RTS: - umodem_rts(sc, onoff); - break; - case UCOM_SET_BREAK: - umodem_break(sc, onoff); - break; - default: - break; - } -} - -usbd_status -umodem_set_line_coding(struct umodem_softc *sc, usb_cdc_line_state_t *state) -{ - usb_device_request_t req; - usbd_status err; - - DPRINTF(("umodem_set_line_coding: rate=%d fmt=%d parity=%d bits=%d\n", - UGETDW(state->dwDTERate), state->bCharFormat, - state->bParityType, state->bDataBits)); - - if (memcmp(state, &sc->sc_line_state, UCDC_LINE_STATE_LENGTH) == 0) { - DPRINTF(("umodem_set_line_coding: already set\n")); - return (USBD_NORMAL_COMPLETION); - } - - req.bmRequestType = UT_WRITE_CLASS_INTERFACE; - req.bRequest = UCDC_SET_LINE_CODING; - USETW(req.wValue, 0); - USETW(req.wIndex, sc->sc_ctl_iface_no); - USETW(req.wLength, UCDC_LINE_STATE_LENGTH); - - err = usbd_do_request(sc->sc_udev, &req, state); - if (err) { - DPRINTF(("umodem_set_line_coding: failed, err=%s\n", - usbd_errstr(err))); - return (err); - } - - sc->sc_line_state = *state; - - return (USBD_NORMAL_COMPLETION); -} - -usbd_status -umodem_set_comm_feature(struct umodem_softc *sc, int feature, int state) -{ - usb_device_request_t req; - usbd_status err; - usb_cdc_abstract_state_t ast; - - DPRINTF(("umodem_set_comm_feature: feature=%d state=%d\n", feature, - state)); - - req.bmRequestType = UT_WRITE_CLASS_INTERFACE; - req.bRequest = UCDC_SET_COMM_FEATURE; - USETW(req.wValue, feature); - USETW(req.wIndex, sc->sc_ctl_iface_no); - USETW(req.wLength, UCDC_ABSTRACT_STATE_LENGTH); - USETW(ast.wState, state); - - err = usbd_do_request(sc->sc_udev, &req, &ast); - if (err) { - DPRINTF(("umodem_set_comm_feature: feature=%d, err=%s\n", - feature, usbd_errstr(err))); - return (err); - } - - return (USBD_NORMAL_COMPLETION); -} - -static int -umodem_detach(device_t self) -{ - struct umodem_softc *sc = device_get_softc(self); - int rv = 0; - - DPRINTF(("umodem_detach: sc=%p\n", sc)); - - if (sc->sc_notify_pipe != NULL) { - usbd_abort_pipe(sc->sc_notify_pipe); - usbd_close_pipe(sc->sc_notify_pipe); - sc->sc_notify_pipe = NULL; - } - - sc->sc_ucom.sc_dying = 1; - rv = ucom_detach(&sc->sc_ucom); - - return (rv); -} diff --git a/sys/dev/usbmisc/ums/Makefile b/sys/dev/usbmisc/ums/Makefile deleted file mode 100644 index 8dddce2444..0000000000 --- a/sys/dev/usbmisc/ums/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -# $FreeBSD: src/sys/modules/ums/Makefile,v 1.7 1999/11/28 18:53:37 bde Exp $ -# $DragonFly: src/sys/dev/usbmisc/ums/Makefile,v 1.4 2004/08/13 17:51:07 dillon Exp $ - -.PATH: ${.CURDIR}/../../dev/usb -KMOD = ums -SRCS = bus_if.h device_if.h opt_usb.h ums.c - -.include diff --git a/sys/dev/usbmisc/ums/ums.c b/sys/dev/usbmisc/ums/ums.c deleted file mode 100644 index c46747777f..0000000000 --- a/sys/dev/usbmisc/ums/ums.c +++ /dev/null @@ -1,839 +0,0 @@ -/* - * $FreeBSD: src/sys/dev/usb/ums.c,v 1.64 2003/11/09 09:17:22 tanimura Exp $ - */ - -/* - * Copyright (c) 1998 The NetBSD Foundation, Inc. - * All rights reserved. - * - * This code is derived from software contributed to The NetBSD Foundation - * by Lennart Augustsson (lennart@augustsson.net) at - * Carlstedt Research & Technology. - * - * 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. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the NetBSD - * Foundation, Inc. and its contributors. - * 4. Neither the name of The NetBSD Foundation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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. - */ - -/* - * HID spec: http://www.usb.org/developers/data/devclass/hid1_1.pdf - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include -#include -#include - -#include - -#ifdef USB_DEBUG -#define DPRINTF(x) if (umsdebug) kprintf x -#define DPRINTFN(n,x) if (umsdebug>(n)) kprintf x -int umsdebug = 0; -SYSCTL_NODE(_hw_usb, OID_AUTO, ums, CTLFLAG_RW, 0, "USB ums"); -SYSCTL_INT(_hw_usb_ums, OID_AUTO, debug, CTLFLAG_RW, - &umsdebug, 0, "ums debug level"); -#else -#define DPRINTF(x) -#define DPRINTFN(n,x) -#endif - -#define UMSUNIT(s) (minor(s)&0x1f) - -#define MS_TO_TICKS(ms) ((ms) * hz / 1000) - -#define QUEUE_BUFSIZE 400 /* MUST be divisible by 5 _and_ 8 */ - -struct ums_softc { - device_t sc_dev; /* base device */ - cdev_t sc_cdev; - usbd_interface_handle sc_iface; /* interface */ - usbd_pipe_handle sc_intrpipe; /* interrupt pipe */ - int sc_ep_addr; - - u_char *sc_ibuf; - u_int8_t sc_iid; - int sc_isize; - struct hid_location sc_loc_x, sc_loc_y, sc_loc_z; - struct hid_location *sc_loc_btn; - - struct callout sc_timeout; /* for spurious button ups */ - - int sc_enabled; - int sc_disconnected; /* device is gone */ - - int flags; /* device configuration */ -#define UMS_Z 0x01 /* z direction available */ -#define UMS_SPUR_BUT_UP 0x02 /* spurious button up events */ - int nbuttons; -#define MAX_BUTTONS 31 /* must not exceed size of sc_buttons */ - - u_char qbuf[QUEUE_BUFSIZE]; /* must be divisable by 3&4 */ - u_char dummy[100]; /* XXX just for safety and for now */ - int qcount, qhead, qtail; - mousehw_t hw; - mousemode_t mode; - mousestatus_t status; - - int state; -# define UMS_ASLEEP 0x01 /* readFromDevice is waiting */ - struct kqinfo rkq; /* process waiting in select/poll/kq */ -}; - -#define MOUSE_FLAGS_MASK (HIO_CONST|HIO_RELATIVE) -#define MOUSE_FLAGS (HIO_RELATIVE) - -static void ums_intr(usbd_xfer_handle xfer, - usbd_private_handle priv, usbd_status status); - -static void ums_add_to_queue(struct ums_softc *sc, - int dx, int dy, int dz, int buttons); -static void ums_add_to_queue_timeout(void *priv); - -static int ums_enable(void *); -static void ums_disable(void *); - -static d_open_t ums_open; -static d_close_t ums_close; -static d_read_t ums_read; -static d_ioctl_t ums_ioctl; -static d_kqfilter_t ums_kqfilter; - -static void ums_filt_detach(struct knote *); -static int ums_filt(struct knote *, long); - -static struct dev_ops ums_ops = { - { "ums", 0, 0 }, - .d_open = ums_open, - .d_close = ums_close, - .d_read = ums_read, - .d_ioctl = ums_ioctl, - .d_kqfilter = ums_kqfilter -}; - -static device_probe_t ums_match; -static device_attach_t ums_attach; -static device_detach_t ums_detach; - -static devclass_t ums_devclass; - -static kobj_method_t ums_methods[] = { - DEVMETHOD(device_probe, ums_match), - DEVMETHOD(device_attach, ums_attach), - DEVMETHOD(device_detach, ums_detach), - DEVMETHOD_END -}; - -static driver_t ums_driver = { - "ums", - ums_methods, - sizeof(struct ums_softc) -}; - -MODULE_DEPEND(ums, usb, 1, 1, 1); - -static int -ums_match(device_t self) -{ - struct usb_attach_arg *uaa = device_get_ivars(self); - usb_interface_descriptor_t *id; - int size, ret; - void *desc; - usbd_status err; - - if (!uaa->iface) - return (UMATCH_NONE); - id = usbd_get_interface_descriptor(uaa->iface); - if (!id || id->bInterfaceClass != UICLASS_HID) - return (UMATCH_NONE); - - err = usbd_read_report_desc(uaa->iface, &desc, &size, M_TEMP); - if (err) - return (UMATCH_NONE); - - if (hid_is_collection(desc, size, - HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_MOUSE))) - ret = UMATCH_IFACECLASS; - else - ret = UMATCH_NONE; - - kfree(desc, M_TEMP); - return (ret); -} - -static int -ums_attach(device_t self) -{ - struct ums_softc *sc = device_get_softc(self); - struct usb_attach_arg *uaa = device_get_ivars(self); - usbd_interface_handle iface = uaa->iface; - usb_endpoint_descriptor_t *ed; - int size; - void *desc; - usbd_status err; - u_int32_t flags; - int i; - struct hid_location loc_btn; - - sc->sc_disconnected = 1; - sc->sc_iface = iface; - sc->sc_dev = self; - ed = usbd_interface2endpoint_descriptor(iface, 0); - if (!ed) { - kprintf("%s: could not read endpoint descriptor\n", - device_get_nameunit(sc->sc_dev)); - return ENXIO; - } - - DPRINTFN(10,("ums_attach: bLength=%d bDescriptorType=%d " - "bEndpointAddress=%d-%s bmAttributes=%d wMaxPacketSize=%d" - " bInterval=%d\n", - ed->bLength, ed->bDescriptorType, - UE_GET_ADDR(ed->bEndpointAddress), - UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN ? "in":"out", - UE_GET_XFERTYPE(ed->bmAttributes), - UGETW(ed->wMaxPacketSize), ed->bInterval)); - - if (UE_GET_DIR(ed->bEndpointAddress) != UE_DIR_IN || - UE_GET_XFERTYPE(ed->bmAttributes) != UE_INTERRUPT) { - kprintf("%s: unexpected endpoint\n", - device_get_nameunit(sc->sc_dev)); - return ENXIO; - } - - err = usbd_read_report_desc(uaa->iface, &desc, &size, M_TEMP); - if (err) - return ENXIO; - - if (!hid_locate(desc, size, HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_X), - hid_input, &sc->sc_loc_x, &flags)) { - kprintf("%s: mouse has no X report\n", device_get_nameunit(sc->sc_dev)); - return ENXIO; - } - if ((flags & MOUSE_FLAGS_MASK) != MOUSE_FLAGS) { - kprintf("%s: X report 0x%04x not supported\n", - device_get_nameunit(sc->sc_dev), flags); - return ENXIO; - } - - if (!hid_locate(desc, size, HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_Y), - hid_input, &sc->sc_loc_y, &flags)) { - kprintf("%s: mouse has no Y report\n", device_get_nameunit(sc->sc_dev)); - return ENXIO; - } - if ((flags & MOUSE_FLAGS_MASK) != MOUSE_FLAGS) { - kprintf("%s: Y report 0x%04x not supported\n", - device_get_nameunit(sc->sc_dev), flags); - return ENXIO; - } - - /* try to guess the Z activator: first check Z, then WHEEL */ - if (hid_locate(desc, size, HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_Z), - hid_input, &sc->sc_loc_z, &flags) || - hid_locate(desc, size, HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_WHEEL), - hid_input, &sc->sc_loc_z, &flags)) { - if ((flags & MOUSE_FLAGS_MASK) != MOUSE_FLAGS) { - sc->sc_loc_z.size = 0; /* Bad Z coord, ignore it */ - } else { - sc->flags |= UMS_Z; - } - } - - /* figure out the number of buttons */ - for (i = 1; i <= MAX_BUTTONS; i++) - if (!hid_locate(desc, size, HID_USAGE2(HUP_BUTTON, i), - hid_input, &loc_btn, 0)) - break; - sc->nbuttons = i - 1; - sc->sc_loc_btn = kmalloc(sizeof(struct hid_location)*sc->nbuttons, - M_USBDEV, M_INTWAIT); - - kprintf("%s: %d buttons%s\n", device_get_nameunit(sc->sc_dev), - sc->nbuttons, sc->flags & UMS_Z? " and Z dir." : ""); - - for (i = 1; i <= sc->nbuttons; i++) - hid_locate(desc, size, HID_USAGE2(HUP_BUTTON, i), - hid_input, &sc->sc_loc_btn[i-1], 0); - - sc->sc_isize = hid_report_size(desc, size, hid_input, &sc->sc_iid); - sc->sc_ibuf = kmalloc(sc->sc_isize, M_USB, M_INTWAIT); - sc->sc_ep_addr = ed->bEndpointAddress; - sc->sc_disconnected = 0; - kfree(desc, M_TEMP); - -#ifdef USB_DEBUG - DPRINTF(("ums_attach: sc=%p\n", sc)); - DPRINTF(("ums_attach: X\t%d/%d\n", - sc->sc_loc_x.pos, sc->sc_loc_x.size)); - DPRINTF(("ums_attach: Y\t%d/%d\n", - sc->sc_loc_y.pos, sc->sc_loc_y.size)); - if (sc->flags & UMS_Z) - DPRINTF(("ums_attach: Z\t%d/%d\n", - sc->sc_loc_z.pos, sc->sc_loc_z.size)); - for (i = 1; i <= sc->nbuttons; i++) { - DPRINTF(("ums_attach: B%d\t%d/%d\n", - i, sc->sc_loc_btn[i-1].pos,sc->sc_loc_btn[i-1].size)); - } - DPRINTF(("ums_attach: size=%d, id=%d\n", sc->sc_isize, sc->sc_iid)); -#endif - - if (sc->nbuttons > MOUSE_MSC_MAXBUTTON) - sc->hw.buttons = MOUSE_MSC_MAXBUTTON; - else - sc->hw.buttons = sc->nbuttons; - sc->hw.iftype = MOUSE_IF_USB; - sc->hw.type = MOUSE_MOUSE; - sc->hw.model = MOUSE_MODEL_GENERIC; - sc->hw.hwid = 0; - sc->mode.protocol = MOUSE_PROTO_MSC; - sc->mode.rate = -1; - sc->mode.resolution = MOUSE_RES_UNKNOWN; - sc->mode.accelfactor = 0; - sc->mode.level = 0; - sc->mode.packetsize = MOUSE_MSC_PACKETSIZE; - sc->mode.syncmask[0] = MOUSE_MSC_SYNCMASK; - sc->mode.syncmask[1] = MOUSE_MSC_SYNC; - - sc->status.flags = 0; - sc->status.button = sc->status.obutton = 0; - sc->status.dx = sc->status.dy = sc->status.dz = 0; - - sc->sc_cdev = make_dev(&ums_ops, device_get_unit(self), - UID_ROOT, GID_OPERATOR, - 0644, "ums%d", device_get_unit(self)); - reference_dev(sc->sc_cdev); - - if (usbd_get_quirks(uaa->device)->uq_flags & UQ_SPUR_BUT_UP) { - DPRINTF(("%s: Spurious button up events\n", - device_get_nameunit(sc->sc_dev))); - sc->flags |= UMS_SPUR_BUT_UP; - } - - return 0; -} - - -static int -ums_detach(device_t self) -{ - struct ums_softc *sc = device_get_softc(self); - - if (sc->sc_enabled) - ums_disable(sc); - - DPRINTF(("%s: disconnected\n", device_get_nameunit(self))); - - kfree(sc->sc_loc_btn, M_USB); - kfree(sc->sc_ibuf, M_USB); - - /* someone waiting for data */ - /* - * XXX If we wakeup the process here, the device will be gone by - * the time the process gets a chance to notice. *_close and friends - * should be fixed to handle this case. - * Or we should do a delayed detach for this. - * Does this delay now force tsleep to exit with an error? - */ - if (sc->state & UMS_ASLEEP) { - sc->state &= ~UMS_ASLEEP; - wakeup(sc); - } - - dev_ops_remove_minor(&ums_ops, /*-1, */device_get_unit(self)); - devfs_assume_knotes(sc->sc_cdev, &sc->rkq); - release_dev(sc->sc_cdev); - sc->sc_cdev = NULL; - - return 0; -} - -void -ums_intr(usbd_xfer_handle xfer, usbd_private_handle addr, - usbd_status status) -{ - struct ums_softc *sc = addr; - u_char *ibuf; - int dx, dy, dz; - u_char buttons = 0; - int i; - -#define UMS_BUT(i) ((i) < 3 ? (((i) + 2) % 3) : (i)) - - DPRINTFN(5, ("ums_intr: sc=%p status=%d\n", sc, status)); - DPRINTFN(5, ("ums_intr: data = %02x %02x %02x\n", - sc->sc_ibuf[0], sc->sc_ibuf[1], sc->sc_ibuf[2])); - - if (status == USBD_CANCELLED) - return; - - if (status != USBD_NORMAL_COMPLETION) { - DPRINTF(("ums_intr: status=%d\n", status)); - if (status == USBD_STALLED) - usbd_clear_endpoint_stall_async(sc->sc_intrpipe); - return; - } - - ibuf = sc->sc_ibuf; - if (sc->sc_iid) { - if (*ibuf++ != sc->sc_iid) - return; - } - - dx = hid_get_data(ibuf, &sc->sc_loc_x); - dy = -hid_get_data(ibuf, &sc->sc_loc_y); - dz = -hid_get_data(ibuf, &sc->sc_loc_z); - for (i = 0; i < sc->nbuttons; i++) - if (hid_get_data(ibuf, &sc->sc_loc_btn[i])) - buttons |= (1 << UMS_BUT(i)); - - if (dx || dy || dz || (sc->flags & UMS_Z) - || buttons != sc->status.button) { - DPRINTFN(5, ("ums_intr: x:%d y:%d z:%d buttons:0x%x\n", - dx, dy, dz, buttons)); - - sc->status.button = buttons; - sc->status.dx += dx; - sc->status.dy += dy; - sc->status.dz += dz; - - /* Discard data in case of full buffer */ - if (sc->qcount == sizeof(sc->qbuf)) { - DPRINTF(("Buffer full, discarded packet")); - return; - } - - /* - * The Qtronix keyboard has a built in PS/2 port for a mouse. - * The firmware once in a while posts a spurious button up - * event. This event we ignore by doing a timeout for 50 msecs. - * If we receive dx=dy=dz=buttons=0 before we add the event to - * the queue. - * In any other case we delete the timeout event. - */ - if (sc->flags & UMS_SPUR_BUT_UP && - dx == 0 && dy == 0 && dz == 0 && buttons == 0) { - callout_reset(&sc->sc_timeout, MS_TO_TICKS(50), - ums_add_to_queue_timeout, (void *) sc); - } else { - callout_stop(&sc->sc_timeout); - ums_add_to_queue(sc, dx, dy, dz, buttons); - } - } -} - -static void -ums_add_to_queue_timeout(void *priv) -{ - struct ums_softc *sc = priv; - - crit_enter(); - ums_add_to_queue(sc, 0, 0, 0, 0); - crit_exit(); -} - -static void -ums_add_to_queue(struct ums_softc *sc, int dx, int dy, int dz, int buttons) -{ - /* Discard data in case of full buffer */ - if (sc->qhead+sc->mode.packetsize > sizeof(sc->qbuf)) { - DPRINTF(("Buffer full, discarded packet")); - return; - } - - if (dx > 254) dx = 254; - if (dx < -256) dx = -256; - if (dy > 254) dy = 254; - if (dy < -256) dy = -256; - if (dz > 126) dz = 126; - if (dz < -128) dz = -128; - - sc->qbuf[sc->qhead] = sc->mode.syncmask[1]; - sc->qbuf[sc->qhead] |= ~buttons & MOUSE_MSC_BUTTONS; - sc->qbuf[sc->qhead+1] = dx >> 1; - sc->qbuf[sc->qhead+2] = dy >> 1; - sc->qbuf[sc->qhead+3] = dx - (dx >> 1); - sc->qbuf[sc->qhead+4] = dy - (dy >> 1); - - if (sc->mode.level == 1) { - sc->qbuf[sc->qhead+5] = dz >> 1; - sc->qbuf[sc->qhead+6] = dz - (dz >> 1); - sc->qbuf[sc->qhead+7] = ((~buttons >> 3) - & MOUSE_SYS_EXTBUTTONS); - } - - sc->qhead += sc->mode.packetsize; - sc->qcount += sc->mode.packetsize; - /* wrap round at end of buffer */ - if (sc->qhead >= sizeof(sc->qbuf)) - sc->qhead = 0; - - /* someone waiting for data */ - if (sc->state & UMS_ASLEEP) { - sc->state &= ~UMS_ASLEEP; - wakeup(sc); - } - KNOTE(&sc->rkq.ki_note, 0); -} - -static int -ums_enable(void *v) -{ - struct ums_softc *sc = v; - - usbd_status err; - - if (sc->sc_enabled) - return EBUSY; - - sc->sc_enabled = 1; - sc->qcount = 0; - sc->qhead = sc->qtail = 0; - sc->status.flags = 0; - sc->status.button = sc->status.obutton = 0; - sc->status.dx = sc->status.dy = sc->status.dz = 0; - - callout_init(&sc->sc_timeout); - - /* Set up interrupt pipe. */ - err = usbd_open_pipe_intr(sc->sc_iface, sc->sc_ep_addr, - USBD_SHORT_XFER_OK, &sc->sc_intrpipe, sc, - sc->sc_ibuf, sc->sc_isize, ums_intr, - USBD_DEFAULT_INTERVAL); - if (err) { - DPRINTF(("ums_enable: usbd_open_pipe_intr failed, error=%d\n", - err)); - sc->sc_enabled = 0; - return (EIO); - } - return (0); -} - -static void -ums_disable(void *priv) -{ - struct ums_softc *sc = priv; - - callout_stop(&sc->sc_timeout); - - /* Disable interrupts. */ - usbd_abort_pipe(sc->sc_intrpipe); - usbd_close_pipe(sc->sc_intrpipe); - - sc->sc_enabled = 0; - - if (sc->qcount != 0) - DPRINTF(("Discarded %d bytes in queue\n", sc->qcount)); -} - -static int -ums_open(struct dev_open_args *ap) -{ - cdev_t dev = ap->a_head.a_dev; - struct ums_softc *sc; - - sc = devclass_get_softc(ums_devclass, UMSUNIT(dev)); - if (sc == NULL) - return (ENXIO); - - return ums_enable(sc); -} - -static int -ums_close(struct dev_close_args *ap) -{ - cdev_t dev = ap->a_head.a_dev; - struct ums_softc *sc; - - sc = devclass_get_softc(ums_devclass, UMSUNIT(dev)); - - if (!sc) - return 0; - - if (sc->sc_enabled) - ums_disable(sc); - - return 0; -} - -static int -ums_read(struct dev_read_args *ap) -{ - cdev_t dev = ap->a_head.a_dev; - struct uio *uio = ap->a_uio; - struct ums_softc *sc; - char buf[sizeof(sc->qbuf)]; - int l = 0; - int error; - - sc = devclass_get_softc(ums_devclass, UMSUNIT(dev)); - - crit_enter(); - if (!sc) { - crit_exit(); - return EIO; - } - - while (sc->qcount == 0 ) { - if (ap->a_ioflag & IO_NDELAY) { /* non-blocking I/O */ - crit_exit(); - return EWOULDBLOCK; - } - - sc->state |= UMS_ASLEEP; /* blocking I/O */ - error = tsleep(sc, PCATCH, "umsrea", 0); - if (error) { - crit_exit(); - return error; - } else if (!sc->sc_enabled) { - crit_exit(); - return EINTR; - } - /* check whether the device is still there */ - - sc = devclass_get_softc(ums_devclass, UMSUNIT(dev)); - if (!sc) { - crit_exit(); - return EIO; - } - } - - /* - * The writer process only extends qcount and qtail. We could copy - * them and use the copies to do the copying out of the queue. - */ - - while ((sc->qcount > 0) && (uio->uio_resid > 0)) { - l = (sc->qcount < uio->uio_resid? sc->qcount:uio->uio_resid); - if (l > sizeof(buf)) - l = sizeof(buf); - if (l > sizeof(sc->qbuf) - sc->qtail) /* transfer till end of buf */ - l = sizeof(sc->qbuf) - sc->qtail; - - crit_exit(); - uiomove(&sc->qbuf[sc->qtail], l, uio); - crit_enter(); - - if ( sc->qcount - l < 0 ) { - DPRINTF(("qcount below 0, count=%d l=%d\n", sc->qcount, l)); - sc->qcount = l; - } - sc->qcount -= l; /* remove the bytes from the buffer */ - sc->qtail = (sc->qtail + l) % sizeof(sc->qbuf); - } - crit_exit(); - - return 0; -} - -static struct filterops ums_filtops = - { FILTEROP_ISFD, NULL, ums_filt_detach, ums_filt }; - -static int -ums_kqfilter(struct dev_kqfilter_args *ap) -{ - cdev_t dev = ap->a_head.a_dev; - struct knote *kn = ap->a_kn; - struct ums_softc *sc; - struct klist *klist; - - ap->a_result = 0; - - switch (kn->kn_filter) { - case EVFILT_READ: - sc = devclass_get_softc(ums_devclass, UMSUNIT(dev)); - kn->kn_fop = &ums_filtops; - kn->kn_hook = (caddr_t)sc; - break; - default: - ap->a_result = EOPNOTSUPP; - return (0); - } - - klist = &sc->rkq.ki_note; - knote_insert(klist, kn); - - return (0); -} - -static void -ums_filt_detach(struct knote *kn) -{ - struct ums_softc *sc = (struct ums_softc *)kn->kn_hook; - struct klist *klist; - - klist = &sc->rkq.ki_note; - knote_remove(klist, kn); -} - -static int -ums_filt(struct knote *kn, long hint) -{ - struct ums_softc *sc = (struct ums_softc *)kn->kn_hook; - int ready = 0; - - crit_enter(); - if (sc->qcount) - ready = 1; - crit_exit(); - - return (ready); -} - -int -ums_ioctl(struct dev_ioctl_args *ap) -{ - cdev_t dev = ap->a_head.a_dev; - struct ums_softc *sc; - int error = 0; - mousemode_t mode; - - sc = devclass_get_softc(ums_devclass, UMSUNIT(dev)); - - if (!sc) - return EIO; - - switch(ap->a_cmd) { - case MOUSE_GETHWINFO: - *(mousehw_t *)ap->a_data = sc->hw; - break; - case MOUSE_GETMODE: - *(mousemode_t *)ap->a_data = sc->mode; - break; - case MOUSE_SETMODE: - mode = *(mousemode_t *)ap->a_data; - - if (mode.level == -1) - /* don't change the current setting */ - ; - else if ((mode.level < 0) || (mode.level > 1)) - return (EINVAL); - - crit_enter(); - sc->mode.level = mode.level; - - if (sc->mode.level == 0) { - if (sc->nbuttons > MOUSE_MSC_MAXBUTTON) - sc->hw.buttons = MOUSE_MSC_MAXBUTTON; - else - sc->hw.buttons = sc->nbuttons; - sc->mode.protocol = MOUSE_PROTO_MSC; - sc->mode.packetsize = MOUSE_MSC_PACKETSIZE; - sc->mode.syncmask[0] = MOUSE_MSC_SYNCMASK; - sc->mode.syncmask[1] = MOUSE_MSC_SYNC; - } else if (sc->mode.level == 1) { - if (sc->nbuttons > MOUSE_SYS_MAXBUTTON) - sc->hw.buttons = MOUSE_SYS_MAXBUTTON; - else - sc->hw.buttons = sc->nbuttons; - sc->mode.protocol = MOUSE_PROTO_SYSMOUSE; - sc->mode.packetsize = MOUSE_SYS_PACKETSIZE; - sc->mode.syncmask[0] = MOUSE_SYS_SYNCMASK; - sc->mode.syncmask[1] = MOUSE_SYS_SYNC; - } - - bzero(sc->qbuf, sizeof(sc->qbuf)); - sc->qhead = sc->qtail = sc->qcount = 0; - crit_exit(); - - break; - case MOUSE_GETLEVEL: - *(int *)ap->a_data = sc->mode.level; - break; - case MOUSE_SETLEVEL: - if (*(int *)ap->a_data < 0 || *(int *)ap->a_data > 1) - return (EINVAL); - - crit_enter(); - sc->mode.level = *(int *)ap->a_data; - - if (sc->mode.level == 0) { - if (sc->nbuttons > MOUSE_MSC_MAXBUTTON) - sc->hw.buttons = MOUSE_MSC_MAXBUTTON; - else - sc->hw.buttons = sc->nbuttons; - sc->mode.protocol = MOUSE_PROTO_MSC; - sc->mode.packetsize = MOUSE_MSC_PACKETSIZE; - sc->mode.syncmask[0] = MOUSE_MSC_SYNCMASK; - sc->mode.syncmask[1] = MOUSE_MSC_SYNC; - } else if (sc->mode.level == 1) { - if (sc->nbuttons > MOUSE_SYS_MAXBUTTON) - sc->hw.buttons = MOUSE_SYS_MAXBUTTON; - else - sc->hw.buttons = sc->nbuttons; - sc->mode.protocol = MOUSE_PROTO_SYSMOUSE; - sc->mode.packetsize = MOUSE_SYS_PACKETSIZE; - sc->mode.syncmask[0] = MOUSE_SYS_SYNCMASK; - sc->mode.syncmask[1] = MOUSE_SYS_SYNC; - } - - bzero(sc->qbuf, sizeof(sc->qbuf)); - sc->qhead = sc->qtail = sc->qcount = 0; - crit_exit(); - - break; - case MOUSE_GETSTATUS: { - mousestatus_t *status = (mousestatus_t *) ap->a_data; - - crit_enter(); - *status = sc->status; - sc->status.obutton = sc->status.button; - sc->status.button = 0; - sc->status.dx = sc->status.dy = sc->status.dz = 0; - crit_exit(); - - if (status->dx || status->dy || status->dz) - status->flags |= MOUSE_POSCHANGED; - if (status->button != status->obutton) - status->flags |= MOUSE_BUTTONSCHANGED; - break; - } - default: - error = ENOTTY; - } - - return error; -} - -DRIVER_MODULE(ums, uhub, ums_driver, ums_devclass, usbd_driver_load, NULL); diff --git a/sys/dev/usbmisc/uplcom/Makefile b/sys/dev/usbmisc/uplcom/Makefile deleted file mode 100644 index d9bd987def..0000000000 --- a/sys/dev/usbmisc/uplcom/Makefile +++ /dev/null @@ -1,9 +0,0 @@ -# $FreeBSD: src/sys/modules/uplcom/Makefile,v 1.1.2.2 2002/08/11 20:05:20 joe Exp $ -# $DragonFly: src/sys/dev/usbmisc/uplcom/Makefile,v 1.4 2004/08/13 17:51:07 dillon Exp $ - -.PATH: ${.CURDIR}/../ucom - -KMOD= uplcom -SRCS= uplcom.c ucomvar.h opt_usb.h device_if.h bus_if.h - -.include diff --git a/sys/dev/usbmisc/uplcom/uplcom.c b/sys/dev/usbmisc/uplcom/uplcom.c deleted file mode 100644 index 3fb4284185..0000000000 --- a/sys/dev/usbmisc/uplcom/uplcom.c +++ /dev/null @@ -1,984 +0,0 @@ -/* - * $NetBSD: uplcom.c,v 1.21 2001/11/13 06:24:56 lukem Exp $ - * $FreeBSD: src/sys/dev/usb/uplcom.c,v 1.39 2006/09/07 00:06:42 imp Exp $ - */ - -/*- - * Copyright (c) 2001-2003, 2005 Shunsuke Akiyama . - * 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. - */ - -/* - * Copyright (c) 2001 The NetBSD Foundation, Inc. - * All rights reserved. - * - * This code is derived from software contributed to The NetBSD Foundation - * by Ichiro FUKUHARA (ichiro@ichiro.org). - * - * 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. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the NetBSD - * Foundation, Inc. and its contributors. - * 4. Neither the name of The NetBSD Foundation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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. - */ - -/* - * This driver supports several devices devices driven by Prolific PL-2303 - * (known also as PL-2303H), PL-2303X and PL-2303HX USB-to-RS232 bridge chip. - * The devices are sold under many different brand names. - * - * Datasheets are available at Prolific www site at http://www.prolific.com.tw - * The datasheets don't contain full programming information for the chip. - * - * PL-2303HX has the same features as PL-2303X (at least from the point of - * view of device driver) but is pin-to-pin compatible with PL-2303. - * - * There are several differences between PL-2303 and PL-2303(H)X. - * PL-2303(H)X can do higher bitrate in bulk mode, has _probably_ - * different command for controlling CRTSCTS and needs special - * sequence of commands for initialization which aren't also - * documented in the datasheet. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include -#include - -#include "../ucom/ucomvar.h" - -SYSCTL_NODE(_hw_usb, OID_AUTO, uplcom, CTLFLAG_RW, 0, "USB uplcom"); -#ifdef USB_DEBUG -static int uplcomdebug = 0; -SYSCTL_INT(_hw_usb_uplcom, OID_AUTO, debug, CTLFLAG_RW, - &uplcomdebug, 0, "uplcom debug level"); - -#define DPRINTFN(n, x) do { \ - if (uplcomdebug > (n)) \ - kprintf x; \ - } while (0) -#else -#define DPRINTFN(n, x) -#endif -#define DPRINTF(x) DPRINTFN(0, x) - -#define UPLCOM_MODVER 1 /* module version */ - -#define UPLCOM_CONFIG_INDEX 0 -#define UPLCOM_IFACE_INDEX 0 -#define UPLCOM_SECOND_IFACE_INDEX 1 - -#ifndef UPLCOM_INTR_INTERVAL -#define UPLCOM_INTR_INTERVAL 100 /* ms */ -#endif - -#define UPLCOM_SET_REQUEST 0x01 -#define UPLCOM_SET_CRTSCTS 0x41 -#define UPLCOM_SET_CRTSCTS_PL2303X 0x61 -#define RSAQ_STATUS_CTS 0x80 -#define RSAQ_STATUS_DSR 0x02 -#define RSAQ_STATUS_DCD 0x01 - -#define TYPE_PL2303 0 -#define TYPE_PL2303X 1 - -struct uplcom_softc { - struct ucom_softc sc_ucom; - - int sc_iface_number; /* interface number */ - - usbd_interface_handle sc_intr_iface; /* interrupt interface */ - int sc_intr_number; /* interrupt number */ - usbd_pipe_handle sc_intr_pipe; /* interrupt pipe */ - u_char *sc_intr_buf; /* interrupt buffer */ - int sc_isize; - - usb_cdc_line_state_t sc_line_state; /* current line state */ - u_char sc_dtr; /* current DTR state */ - u_char sc_rts; /* current RTS state */ - u_char sc_status; - - u_char sc_lsr; /* Local status register */ - u_char sc_msr; /* uplcom status register */ - - int sc_chiptype; /* Type of chip */ - - struct task sc_task; -}; - -/* - * These are the maximum number of bytes transferred per frame. - * The output buffer size cannot be increased due to the size encoding. - */ -#define UPLCOMIBUFSIZE 256 -#define UPLCOMOBUFSIZE 256 - -static usbd_status uplcom_reset(struct uplcom_softc *); -static usbd_status uplcom_set_line_coding(struct uplcom_softc *, - usb_cdc_line_state_t *); -static usbd_status uplcom_set_crtscts(struct uplcom_softc *); -static void uplcom_intr(usbd_xfer_handle, usbd_private_handle, usbd_status); - -static void uplcom_set(void *, int, int, int); -static void uplcom_dtr(struct uplcom_softc *, int); -static void uplcom_rts(struct uplcom_softc *, int); -static void uplcom_break(struct uplcom_softc *, int); -static void uplcom_set_line_state(struct uplcom_softc *); -static void uplcom_get_status(void *, int, u_char *, u_char *); -#if 0 /* TODO */ -static int uplcom_ioctl(void *, int, u_long, caddr_t, int, struct thread *); -#endif -static int uplcom_param(void *, int, struct termios *); -static int uplcom_open(void *, int); -static void uplcom_close(void *, int); -static void uplcom_notify(void *, int); - -struct ucom_callback uplcom_callback = { - uplcom_get_status, - uplcom_set, - uplcom_param, - NULL, /* uplcom_ioctl, TODO */ - uplcom_open, - uplcom_close, - NULL, - NULL -}; - -static const struct usb_devno uplcom_devs[] = { - { USB_DEVICE(0x0413, 0x2101) }, /* Leadtek 9531 GPS */ - { USB_DEVICE(0x0421, 0x1234) }, /* Nokia CA-42 USB data cable clones*/ - { USB_DEVICE(0x04bb, 0x0a03) }, /* I/O DATA USB-RSAQ USB to serial */ - { USB_DEVICE(0x04bb, 0x0a0e) }, /* I/O DATA USB-RSAQ5 USB to serial */ - { USB_DEVICE(0x04bf, 0x0115) }, /* TDK USB-PDC adapter UPA9664 */ - { USB_DEVICE(0x04bf, 0x0117) }, /* TDK USB-PHS adapter UHA6400 */ - { USB_DEVICE(0x04da, 0x3900) }, /* Panasonic 50" touch panel */ - { USB_DEVICE(0x04e8, 0x8001) }, /* Samsung I330 smartphone cradle */ - { USB_DEVICE(0x050d, 0x0257) }, /* Belkin F5U257 USB to serial */ - { USB_DEVICE(0x0547, 0x2008) }, /* Anchor serial */ - { USB_DEVICE(0x0557, 0x2008) }, /* Aten UC232A USB to serial */ - { USB_DEVICE(0x056e, 0x5003) }, /* ELECOM UC-SGT USB to serial */ - { USB_DEVICE(0x056e, 0x5004) }, /* ELECOM UC-SGT USB to serial */ - { USB_DEVICE(0x0584, 0xb000) }, /* RATOC REX-USB60 USB to serial */ - { USB_DEVICE(0x058f, 0x9720) }, /* Alcor AU9720 USB to serial */ - { USB_DEVICE(0x067b, 0x04bb) }, /* I/O DATA USB-RSAQ2 USB to serial */ - { USB_DEVICE(0x067b, 0x1234) }, /* Unbranded DCU-11 clone */ - { USB_DEVICE(0x067b, 0x2303) }, /* IOGEAR/ATEN UC-232A, ST Lab - USB-SERIAL-X etc */ - { USB_DEVICE(0x067b, 0xaaa0) }, /* Microsoft OEM Pharos 360 GPS */ - { USB_DEVICE(0x067b, 0xaaa2) }, /* I/O DATA USB-RSAQ3 USB to serial */ - { USB_DEVICE(0x0731, 0x0528) }, /* Sony-Ericsson DCU-10/DCU-11 */ - { USB_DEVICE(0x0731, 0x2003) }, /* Susteen Datapilot Universal-2 Phone - Cable */ - { USB_DEVICE(0x0745, 0x0001) }, /* Syntech CPT-8001C barcode scanner - USB cradle */ - { USB_DEVICE(0x079b, 0x0027) }, /* Sagem USB data cables */ - { USB_DEVICE(0x0833, 0x012e) }, /* SOURCENEXT KeikaiDenwa 8 with - charger */ - { USB_DEVICE(0x0833, 0x039f) }, /* SOURCENEXT KeikaiDenwa 8 */ - { USB_DEVICE(0x0b41, 0x0011) }, /* HAL Corporation Crossam2+USB */ - { USB_DEVICE(0x0b8c, 0x2303) }, /* Smart Technologies USB to serial */ - { USB_DEVICE(0x0df7, 0x0620) }, /* Mobile Action MA-620 IrDA */ - { USB_DEVICE(0x0e55, 0x110b) }, /* Speed Dragon MS3303H */ - { USB_DEVICE(0x0eba, 0x1080) }, /* Itegno GSM/GPRS modem */ - { USB_DEVICE(0x0eba, 0x2080) }, /* Itegno CDMA 1x card */ - { USB_DEVICE(0x10b5, 0xac70) }, /* PLX CA-42 USB data cable clone */ - { USB_DEVICE(0x11f5, 0x0001) }, /* Siemens SX1 cellphone */ - { USB_DEVICE(0x11f5, 0x0003) }, /* Siemens x65 series cellphones */ - { USB_DEVICE(0x11f5, 0x0004) }, /* Siemens x75 series cellphones */ - { USB_DEVICE(0x11f6, 0x2001) }, /* Willcom W-SIM */ - { USB_DEVICE(0x11f7, 0x02df) }, /* Alcatel One Touch 535/735 phones */ - { USB_DEVICE(0x1453, 0x4026) }, /* RADIOSHACK USB cable */ - { USB_DEVICE(0x2478, 0x2008) }, /* Tripp-Lite U209-000-R */ - { USB_DEVICE(0x6189, 0x2068) }, /* Sitecom USB to serial cable */ -}; - -static device_probe_t uplcom_match; -static device_attach_t uplcom_attach; -static device_detach_t uplcom_detach; - -static device_method_t uplcom_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, uplcom_match), - DEVMETHOD(device_attach, uplcom_attach), - DEVMETHOD(device_detach, uplcom_detach), - DEVMETHOD_END -}; - -static driver_t uplcom_driver = { - "ucom", - uplcom_methods, - sizeof (struct uplcom_softc) -}; - -DRIVER_MODULE(uplcom, uhub, uplcom_driver, ucom_devclass, usbd_driver_load, NULL); -MODULE_DEPEND(uplcom, usb, 1, 1, 1); -MODULE_DEPEND(uplcom, ucom, UCOM_MINVER, UCOM_PREFVER, UCOM_MAXVER); -MODULE_VERSION(uplcom, UPLCOM_MODVER); - -static int uplcominterval = UPLCOM_INTR_INTERVAL; - -static int -sysctl_hw_usb_uplcom_interval(SYSCTL_HANDLER_ARGS) -{ - int err, val; - - val = uplcominterval; - err = sysctl_handle_int(oidp, &val, 0, req); - if (err != 0 || req->newptr == NULL) - return (err); - if (0 < val && val <= 1000) - uplcominterval = val; - else - err = EINVAL; - - return (err); -} - -SYSCTL_PROC(_hw_usb_uplcom, OID_AUTO, interval, CTLTYPE_INT | CTLFLAG_RW, - 0, sizeof(int), sysctl_hw_usb_uplcom_interval, - "I", "uplcom interrupt pipe interval"); - -static int -uplcom_match(device_t self) -{ - struct usb_attach_arg *uaa = device_get_ivars(self); - - if (uaa->iface != NULL) - return (UMATCH_NONE); - - return (usb_lookup(uplcom_devs, uaa->vendor, uaa->product) != NULL ? - UMATCH_VENDOR_PRODUCT : UMATCH_NONE); -} - -static int -uplcom_attach(device_t self) -{ - struct uplcom_softc *sc = device_get_softc(self); - struct usb_attach_arg *uaa = device_get_ivars(self); - usbd_device_handle dev = uaa->device; - usb_device_descriptor_t *dd; - struct ucom_softc *ucom; - usb_config_descriptor_t *cdesc; - usb_interface_descriptor_t *id; - usb_endpoint_descriptor_t *ed; - usbd_status err; - int i; - - ucom = &sc->sc_ucom; - bzero(sc, sizeof (struct uplcom_softc)); - - ucom->sc_dev = self; - ucom->sc_udev = dev; - ucom->sc_iface = uaa->iface; - - DPRINTF(("uplcom attach: sc = %p\n", sc)); - - dd = usbd_get_device_descriptor(uaa->device); - - if (!dd) - goto error; - - /* - * Determine chip type with algorithm sequence taken from the - * Linux driver as I'm not aware of any better method. Device - * release number in chip could be (and in fact is in many cases) - * replaced by the contents of external EEPROM etc. - */ - else if (dd->bDeviceClass == 0x02) - sc->sc_chiptype = TYPE_PL2303; - else if (dd->bMaxPacketSize == 0x40) - sc->sc_chiptype = TYPE_PL2303X; - else - sc->sc_chiptype = TYPE_PL2303; - -#ifdef USB_DEBUG - /* print the chip type */ - if (sc->sc_chiptype == TYPE_PL2303X) { - DPRINTF(("uplcom_attach: chiptype 2303X\n")); - } else { - DPRINTF(("uplcom_attach: chiptype 2303\n")); - } -#endif - - /* initialize endpoints */ - ucom->sc_bulkin_no = ucom->sc_bulkout_no = -1; - sc->sc_intr_number = -1; - sc->sc_intr_pipe = NULL; - - /* Move the device into the configured state. */ - err = usbd_set_config_index(dev, UPLCOM_CONFIG_INDEX, 1); - if (err) { - device_printf(ucom->sc_dev, "failed to set configuration: %s\n", - usbd_errstr(err)); - ucom->sc_dying = 1; - goto error; - } - - /* get the config descriptor */ - cdesc = usbd_get_config_descriptor(ucom->sc_udev); - - if (cdesc == NULL) { - device_printf(ucom->sc_dev, "failed to get configuration " - "descriptor\n"); - ucom->sc_dying = 1; - goto error; - } - - /* get the (first/common) interface */ - err = usbd_device2interface_handle(dev, UPLCOM_IFACE_INDEX, - &ucom->sc_iface); - if (err) { - device_printf(ucom->sc_dev, "failed to get interface: %s\n", - usbd_errstr(err)); - ucom->sc_dying = 1; - goto error; - } - - /* Find the interrupt endpoints */ - - id = usbd_get_interface_descriptor(ucom->sc_iface); - sc->sc_iface_number = id->bInterfaceNumber; - - for (i = 0; i < id->bNumEndpoints; i++) { - ed = usbd_interface2endpoint_descriptor(ucom->sc_iface, i); - if (ed == NULL) { - device_printf(ucom->sc_dev, "no endpoint descriptor " - "for %d\n", i); - ucom->sc_dying = 1; - goto error; - } - - if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && - UE_GET_XFERTYPE(ed->bmAttributes) == UE_INTERRUPT) { - sc->sc_intr_number = ed->bEndpointAddress; - sc->sc_isize = UGETW(ed->wMaxPacketSize); - } - } - - if (sc->sc_intr_number == -1) { - device_printf(ucom->sc_dev, "could not find interrupt in\n"); - ucom->sc_dying = 1; - goto error; - } - - /* keep interface for interrupt */ - sc->sc_intr_iface = ucom->sc_iface; - - /* - * USB-RSAQ1 has two interface - * - * USB-RSAQ1 | USB-RSAQ2 - * -----------------+----------------- - * Interface 0 |Interface 0 - * Interrupt(0x81) | Interrupt(0x81) - * -----------------+ BulkIN(0x02) - * Interface 1 | BulkOUT(0x83) - * BulkIN(0x02) | - * BulkOUT(0x83) | - */ - if (cdesc->bNumInterface == 2) { - err = usbd_device2interface_handle(dev, - UPLCOM_SECOND_IFACE_INDEX, - &ucom->sc_iface); - if (err) { - device_printf(ucom->sc_dev, "failed to get second " - "interface: %s\n", usbd_errstr(err)); - ucom->sc_dying = 1; - goto error; - } - } - - /* Find the bulk{in,out} endpoints */ - - id = usbd_get_interface_descriptor(ucom->sc_iface); - sc->sc_iface_number = id->bInterfaceNumber; - - for (i = 0; i < id->bNumEndpoints; i++) { - ed = usbd_interface2endpoint_descriptor(ucom->sc_iface, i); - if (ed == NULL) { - device_printf(ucom->sc_dev, "no endpoint descriptor " - "for %d\n", i); - ucom->sc_dying = 1; - goto error; - } - - if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && - UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) { - ucom->sc_bulkin_no = ed->bEndpointAddress; - } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT && - UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) { - ucom->sc_bulkout_no = ed->bEndpointAddress; - } - } - - if (ucom->sc_bulkin_no == -1) { - device_printf(ucom->sc_dev, "could not find data bulk in\n"); - ucom->sc_dying = 1; - goto error; - } - - if (ucom->sc_bulkout_no == -1) { - device_printf(ucom->sc_dev, "could not find data bulk out\n"); - ucom->sc_dying = 1; - goto error; - } - - sc->sc_dtr = sc->sc_rts = -1; - ucom->sc_parent = sc; - ucom->sc_portno = UCOM_UNK_PORTNO; - /* bulkin, bulkout set above */ - ucom->sc_ibufsize = UPLCOMIBUFSIZE; - ucom->sc_obufsize = UPLCOMOBUFSIZE; - ucom->sc_ibufsizepad = UPLCOMIBUFSIZE; - ucom->sc_opkthdrlen = 0; - ucom->sc_callback = &uplcom_callback; - - err = uplcom_reset(sc); - - if (err) { - device_printf(ucom->sc_dev, "reset failed: %s\n", - usbd_errstr(err)); - ucom->sc_dying = 1; - goto error; - } - - DPRINTF(("uplcom: in = 0x%x, out = 0x%x, intr = 0x%x\n", - ucom->sc_bulkin_no, ucom->sc_bulkout_no, sc->sc_intr_number)); - - TASK_INIT(&sc->sc_task, 0, uplcom_notify, sc); - ucom_attach(&sc->sc_ucom); - - return 0; - -error: - return ENXIO; -} - -static int -uplcom_detach(device_t self) -{ - struct uplcom_softc *sc = device_get_softc(self); - int rv = 0; - - DPRINTF(("uplcom_detach: sc = %p\n", sc)); - - if (sc->sc_intr_pipe != NULL) { - usbd_abort_pipe(sc->sc_intr_pipe); - usbd_close_pipe(sc->sc_intr_pipe); - kfree(sc->sc_intr_buf, M_USBDEV); - sc->sc_intr_pipe = NULL; - } - - sc->sc_ucom.sc_dying = 1; - - rv = ucom_detach(&sc->sc_ucom); - - return (rv); -} - -static usbd_status -uplcom_reset(struct uplcom_softc *sc) -{ - usb_device_request_t req; - usbd_status err; - - req.bmRequestType = UT_WRITE_VENDOR_DEVICE; - req.bRequest = UPLCOM_SET_REQUEST; - USETW(req.wValue, 0); - USETW(req.wIndex, sc->sc_iface_number); - USETW(req.wLength, 0); - - err = usbd_do_request(sc->sc_ucom.sc_udev, &req, 0); - if (err) { - device_printf(sc->sc_ucom.sc_dev, "uplcom_reset: %s\n", - usbd_errstr(err)); - return (EIO); - } - - return (0); -} - -struct pl2303x_init { - uint8_t req_type; - uint8_t request; - uint16_t value; - uint16_t index; - uint16_t length; -}; - -static const struct pl2303x_init pl2303x[] = { - { UT_READ_VENDOR_DEVICE, UPLCOM_SET_REQUEST, 0x8484, 0, 0 }, - { UT_WRITE_VENDOR_DEVICE, UPLCOM_SET_REQUEST, 0x0404, 0, 0 }, - { UT_READ_VENDOR_DEVICE, UPLCOM_SET_REQUEST, 0x8484, 0, 0 }, - { UT_READ_VENDOR_DEVICE, UPLCOM_SET_REQUEST, 0x8383, 0, 0 }, - { UT_READ_VENDOR_DEVICE, UPLCOM_SET_REQUEST, 0x8484, 0, 0 }, - { UT_WRITE_VENDOR_DEVICE, UPLCOM_SET_REQUEST, 0x0404, 1, 0 }, - { UT_READ_VENDOR_DEVICE, UPLCOM_SET_REQUEST, 0x8484, 0, 0 }, - { UT_READ_VENDOR_DEVICE, UPLCOM_SET_REQUEST, 0x8383, 0, 0 }, - { UT_WRITE_VENDOR_DEVICE, UPLCOM_SET_REQUEST, 0, 1, 0 }, - { UT_WRITE_VENDOR_DEVICE, UPLCOM_SET_REQUEST, 1, 0, 0 }, - { UT_WRITE_VENDOR_DEVICE, UPLCOM_SET_REQUEST, 2, 0x44, 0 } -}; -#define N_PL2302X_INIT NELEM(pl2303x) - -static usbd_status -uplcom_pl2303x_init(struct uplcom_softc *sc) -{ - usb_device_request_t req; - usbd_status err; - int i; - - for (i = 0; i < N_PL2302X_INIT; i++) { - req.bmRequestType = pl2303x[i].req_type; - req.bRequest = pl2303x[i].request; - USETW(req.wValue, pl2303x[i].value); - USETW(req.wIndex, pl2303x[i].index); - USETW(req.wLength, pl2303x[i].length); - - err = usbd_do_request(sc->sc_ucom.sc_udev, &req, 0); - if (err) { - device_printf(sc->sc_ucom.sc_dev, - "uplcom_pl2303x_init: %d: %s\n", i, - usbd_errstr(err)); - return (EIO); - } - } - - return (0); -} - -static void -uplcom_set_line_state(struct uplcom_softc *sc) -{ - usb_device_request_t req; - int ls; - usbd_status err; - - ls = (sc->sc_dtr ? UCDC_LINE_DTR : 0) | - (sc->sc_rts ? UCDC_LINE_RTS : 0); - req.bmRequestType = UT_WRITE_CLASS_INTERFACE; - req.bRequest = UCDC_SET_CONTROL_LINE_STATE; - USETW(req.wValue, ls); - USETW(req.wIndex, sc->sc_iface_number); - USETW(req.wLength, 0); - - err = usbd_do_request(sc->sc_ucom.sc_udev, &req, 0); - if (err) - device_printf(sc->sc_ucom.sc_dev, "uplcom_set_line_status: " - "%s\n", usbd_errstr(err)); -} - -static void -uplcom_set(void *addr, int portno, int reg, int onoff) -{ - struct uplcom_softc *sc = addr; - - switch (reg) { - case UCOM_SET_DTR: - uplcom_dtr(sc, onoff); - break; - case UCOM_SET_RTS: - uplcom_rts(sc, onoff); - break; - case UCOM_SET_BREAK: - uplcom_break(sc, onoff); - break; - default: - break; - } -} - -static void -uplcom_dtr(struct uplcom_softc *sc, int onoff) -{ - DPRINTF(("uplcom_dtr: onoff = %d\n", onoff)); - - if (sc->sc_dtr == onoff) - return; - sc->sc_dtr = onoff; - - uplcom_set_line_state(sc); -} - -static void -uplcom_rts(struct uplcom_softc *sc, int onoff) -{ - DPRINTF(("uplcom_rts: onoff = %d\n", onoff)); - - if (sc->sc_rts == onoff) - return; - sc->sc_rts = onoff; - - uplcom_set_line_state(sc); -} - -static void -uplcom_break(struct uplcom_softc *sc, int onoff) -{ - usb_device_request_t req; - usbd_status err; - - DPRINTF(("uplcom_break: onoff = %d\n", onoff)); - - req.bmRequestType = UT_WRITE_CLASS_INTERFACE; - req.bRequest = UCDC_SEND_BREAK; - USETW(req.wValue, onoff ? UCDC_BREAK_ON : UCDC_BREAK_OFF); - USETW(req.wIndex, sc->sc_iface_number); - USETW(req.wLength, 0); - - err = usbd_do_request(sc->sc_ucom.sc_udev, &req, 0); - if (err) - device_printf(sc->sc_ucom.sc_dev, "uplcom_break: %s\n", - usbd_errstr(err)); -} - -static usbd_status -uplcom_set_crtscts(struct uplcom_softc *sc) -{ - usb_device_request_t req; - usbd_status err; - - DPRINTF(("uplcom_set_crtscts: on\n")); - - req.bmRequestType = UT_WRITE_VENDOR_DEVICE; - req.bRequest = UPLCOM_SET_REQUEST; - USETW(req.wValue, 0); - if (sc->sc_chiptype == TYPE_PL2303X) - USETW(req.wIndex, UPLCOM_SET_CRTSCTS_PL2303X); - else - USETW(req.wIndex, UPLCOM_SET_CRTSCTS); - USETW(req.wLength, 0); - - err = usbd_do_request(sc->sc_ucom.sc_udev, &req, 0); - if (err) { - device_printf(sc->sc_ucom.sc_dev, "uplcom_set_crtscts: %s\n", - usbd_errstr(err)); - return (err); - } - - return (USBD_NORMAL_COMPLETION); -} - -static usbd_status -uplcom_set_line_coding(struct uplcom_softc *sc, usb_cdc_line_state_t *state) -{ - usb_device_request_t req; - usbd_status err; - - DPRINTF(( -"uplcom_set_line_coding: rate = %d, fmt = %d, parity = %d bits = %d\n", - UGETDW(state->dwDTERate), state->bCharFormat, - state->bParityType, state->bDataBits)); - - if (memcmp(state, &sc->sc_line_state, UCDC_LINE_STATE_LENGTH) == 0) { - DPRINTF(("uplcom_set_line_coding: already set\n")); - return (USBD_NORMAL_COMPLETION); - } - - req.bmRequestType = UT_WRITE_CLASS_INTERFACE; - req.bRequest = UCDC_SET_LINE_CODING; - USETW(req.wValue, 0); - USETW(req.wIndex, sc->sc_iface_number); - USETW(req.wLength, UCDC_LINE_STATE_LENGTH); - - err = usbd_do_request(sc->sc_ucom.sc_udev, &req, state); - if (err) { - device_printf(sc->sc_ucom.sc_dev, "uplcom_set_line_coding: " - "%s\n", usbd_errstr(err)); - return (err); - } - - sc->sc_line_state = *state; - - return (USBD_NORMAL_COMPLETION); -} - -static const int uplcom_rates[] = { - 75, 150, 300, 600, 1200, 1800, 2400, 3600, 4800, 7200, 9600, 14400, - 19200, 28800, 38400, 57600, 115200, - /* - * Higher speeds are probably possible. PL2303X supports up to - * 6Mb and can set any rate - */ - 230400, 460800, 614400, 921600, 1228800 -}; -#define N_UPLCOM_RATES NELEM(uplcom_rates) - -static int -uplcom_param(void *addr, int portno, struct termios *t) -{ - struct uplcom_softc *sc = addr; - usbd_status err; - usb_cdc_line_state_t ls; - int i; - - DPRINTF(("uplcom_param: sc = %p\n", sc)); - - /* Check requested baud rate */ - for (i = 0; i < N_UPLCOM_RATES; i++) - if (uplcom_rates[i] == t->c_ospeed) - break; - if (i == N_UPLCOM_RATES) { - DPRINTF(("uplcom_param: bad baud rate (%d)\n", t->c_ospeed)); - return (EIO); - } - - USETDW(ls.dwDTERate, t->c_ospeed); - if (ISSET(t->c_cflag, CSTOPB)) - ls.bCharFormat = UCDC_STOP_BIT_2; - else - ls.bCharFormat = UCDC_STOP_BIT_1; - if (ISSET(t->c_cflag, PARENB)) { - if (ISSET(t->c_cflag, PARODD)) - ls.bParityType = UCDC_PARITY_ODD; - else - ls.bParityType = UCDC_PARITY_EVEN; - } else - ls.bParityType = UCDC_PARITY_NONE; - switch (ISSET(t->c_cflag, CSIZE)) { - case CS5: - ls.bDataBits = 5; - break; - case CS6: - ls.bDataBits = 6; - break; - case CS7: - ls.bDataBits = 7; - break; - case CS8: - ls.bDataBits = 8; - break; - } - - err = uplcom_set_line_coding(sc, &ls); - if (err) - return (EIO); - - if (ISSET(t->c_cflag, CRTSCTS)) { - err = uplcom_set_crtscts(sc); - if (err) - return (EIO); - } - - return (0); -} - -static int -uplcom_open(void *addr, int portno) -{ - struct uplcom_softc *sc = addr; - int err; - - if (sc->sc_ucom.sc_dying) - return (ENXIO); - - DPRINTF(("uplcom_open: sc = %p\n", sc)); - - if (sc->sc_intr_number != -1 && sc->sc_intr_pipe == NULL) { - sc->sc_status = 0; /* clear status bit */ - sc->sc_intr_buf = kmalloc(sc->sc_isize, M_USBDEV, M_WAITOK); - err = usbd_open_pipe_intr(sc->sc_intr_iface, - sc->sc_intr_number, - USBD_SHORT_XFER_OK, - &sc->sc_intr_pipe, - sc, - sc->sc_intr_buf, - sc->sc_isize, - uplcom_intr, - uplcominterval); - if (err) { - device_printf(sc->sc_ucom.sc_dev, "cannot open " - "interrupt pipe (addr %d)\n", - sc->sc_intr_number); - return (EIO); - } - } - - if (sc->sc_chiptype == TYPE_PL2303X) - return (uplcom_pl2303x_init(sc)); - - return (0); -} - -static void -uplcom_close(void *addr, int portno) -{ - struct uplcom_softc *sc = addr; - int err; - - if (sc->sc_ucom.sc_dying) - return; - - DPRINTF(("uplcom_close: close\n")); - - if (sc->sc_intr_pipe != NULL) { - err = usbd_abort_pipe(sc->sc_intr_pipe); - if (err) - device_printf(sc->sc_ucom.sc_dev, "abort interrupt " - "pipe failed: %s\n", usbd_errstr(err)); - err = usbd_close_pipe(sc->sc_intr_pipe); - if (err) - device_printf(sc->sc_ucom.sc_dev, "close interrupt " - "pipe failed: %s\n", usbd_errstr(err)); - kfree(sc->sc_intr_buf, M_USBDEV); - sc->sc_intr_pipe = NULL; - } -} - -static void -uplcom_intr(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status) -{ - struct uplcom_softc *sc = priv; - u_char *buf = sc->sc_intr_buf; - u_char pstatus; - - if (sc->sc_ucom.sc_dying) - return; - - if (status != USBD_NORMAL_COMPLETION) { - if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) - return; - - DPRINTF(("%s: uplcom_intr: abnormal status: %s\n", - device_get_nameunit(sc->sc_ucom.sc_dev), - usbd_errstr(status))); - usbd_clear_endpoint_stall_async(sc->sc_intr_pipe); - return; - } - - DPRINTF(("%s: uplcom status = %02x\n", - device_get_nameunit(sc->sc_ucom.sc_dev), buf[8])); - - sc->sc_lsr = sc->sc_msr = 0; - pstatus = buf[8]; - if (ISSET(pstatus, RSAQ_STATUS_CTS)) - sc->sc_msr |= UMSR_CTS; - else - sc->sc_msr &= ~UMSR_CTS; - if (ISSET(pstatus, RSAQ_STATUS_DSR)) - sc->sc_msr |= UMSR_DSR; - else - sc->sc_msr &= ~UMSR_DSR; - if (ISSET(pstatus, RSAQ_STATUS_DCD)) - sc->sc_msr |= UMSR_DCD; - else - sc->sc_msr &= ~UMSR_DCD; - - /* Deferred notifying to the ucom layer */ - taskqueue_enqueue(taskqueue_swi, &sc->sc_task); -} - -static void -uplcom_notify(void *arg, int count) -{ - struct uplcom_softc *sc; - - sc = (struct uplcom_softc *)arg; - if (sc->sc_ucom.sc_dying) - return; - ucom_status_change(&sc->sc_ucom); -} - -static void -uplcom_get_status(void *addr, int portno, u_char *lsr, u_char *msr) -{ - struct uplcom_softc *sc = addr; - - DPRINTF(("uplcom_get_status:\n")); - - if (lsr != NULL) - *lsr = sc->sc_lsr; - if (msr != NULL) - *msr = sc->sc_msr; -} - -#if 0 /* TODO */ -static int -uplcom_ioctl(void *addr, int portno, u_long cmd, caddr_t data, int flag, - struct thread *p) -{ - struct uplcom_softc *sc = addr; - int error = 0; - - if (sc->sc_ucom.sc_dying) - return (EIO); - - DPRINTF(("uplcom_ioctl: cmd = 0x%08lx\n", cmd)); - - switch (cmd) { - case TIOCNOTTY: - case TIOCMGET: - case TIOCMSET: - case USB_GET_CM_OVER_DATA: - case USB_SET_CM_OVER_DATA: - break; - - default: - DPRINTF(("uplcom_ioctl: unknown\n")); - error = ENOTTY; - break; - } - - return (error); -} -#endif diff --git a/sys/dev/usbmisc/urio/urio.c b/sys/dev/usbmisc/urio/urio.c deleted file mode 100644 index 616572a426..0000000000 --- a/sys/dev/usbmisc/urio/urio.c +++ /dev/null @@ -1,560 +0,0 @@ -/* - * Copyright (c) 2000 Iwasa Kazmi - * 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. - * - * This code is based on ugen.c and ulpt.c developed by Lennart Augustsson. - * This code includes software developed by the NetBSD Foundation, Inc. and - * its contributors. - */ - -/* - * $FreeBSD: src/sys/dev/usb/urio.c,v 1.28 2003/08/25 22:01:06 joe Exp $ - */ - -/* - * 2000/3/24 added NetBSD/OpenBSD support (from Alex Nemirovsky) - * 2000/3/07 use two bulk-pipe handles for read and write (Dirk) - * 2000/3/06 change major number(143), and copyright header - * some fix for 4.0 (Dirk) - * 2000/3/05 codes for FreeBSD 4.x - CURRENT (Thanks to Dirk-Willem van Gulik) - * 2000/3/01 remove retry code from urioioctl() - * change method of bulk transfer (no interrupt) - * 2000/2/28 small fixes for new rio_usb.h - * 2000/2/24 first version. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include - -#ifdef USB_DEBUG -#define DPRINTF(x) if (uriodebug) kprintf x -#define DPRINTFN(n,x) if (uriodebug>(n)) kprintf x -int uriodebug = 0; -SYSCTL_NODE(_hw_usb, OID_AUTO, urio, CTLFLAG_RW, 0, "USB urio"); -SYSCTL_INT(_hw_usb_urio, OID_AUTO, debug, CTLFLAG_RW, - &uriodebug, 0, "urio debug level"); -#else -#define DPRINTF(x) -#define DPRINTFN(n,x) -#endif - -/* difference of usbd interface */ -#define USBDI 1 - -#define RIO_OUT 0 -#define RIO_IN 1 -#define RIO_NODIR 2 - -d_open_t urioopen; -d_close_t urioclose; -d_read_t urioread; -d_write_t uriowrite; -d_ioctl_t urioioctl; - -static struct dev_ops urio_ops = { - { "urio", 0, 0 }, - .d_open = urioopen, - .d_close = urioclose, - .d_read = urioread, - .d_write = uriowrite, - .d_ioctl = urioioctl, -}; -#define RIO_UE_GET_DIR(p) ((UE_GET_DIR(p) == UE_DIR_IN) ? RIO_IN :\ - ((UE_GET_DIR(p) == UE_DIR_OUT) ? RIO_OUT :\ - RIO_NODIR)) - -#define URIO_BBSIZE 1024 - -struct urio_softc { - device_t sc_dev; - usbd_device_handle sc_udev; - usbd_interface_handle sc_iface; - - int sc_opened; - usbd_pipe_handle sc_pipeh_in; - usbd_pipe_handle sc_pipeh_out; - int sc_epaddr[2]; - - int sc_refcnt; -}; - -#define URIOUNIT(n) (minor(n)) - -#define RIO_RW_TIMEOUT 4000 /* ms */ - -static device_probe_t urio_match; -static device_attach_t urio_attach; -static device_detach_t urio_detach; - -static devclass_t urio_devclass; - -static kobj_method_t urio_methods[] = { - DEVMETHOD(device_probe, urio_match), - DEVMETHOD(device_attach, urio_attach), - DEVMETHOD(device_detach, urio_detach), - DEVMETHOD_END -}; - -static driver_t urio_driver = { - "urio", - urio_methods, - sizeof(struct urio_softc) -}; - -static const struct usb_devno urio_devs[] = { - { USB_DEVICE(0x045a, 0x5001) }, /* Diamond Multimedia Rio 600 */ - { USB_DEVICE(0x045a, 0x5002) }, /* Diamond Multimedia Rio 800 */ - { USB_DEVICE(0x0841, 0x0001) }, /* Diamond Multimedia Rio 500 */ -}; - -MODULE_DEPEND(urio, usb, 1, 1, 1); - -static int -urio_match(device_t self) -{ - struct usb_attach_arg *uaa = device_get_ivars(self); - - DPRINTFN(10,("urio_match\n")); - if (uaa->iface == NULL) - return (UMATCH_NONE); - - return (usb_lookup(urio_devs, uaa->vendor, uaa->product) != NULL ? - UMATCH_VENDOR_PRODUCT : UMATCH_NONE); -} - -static int -urio_attach(device_t self) -{ - struct urio_softc *sc = device_get_softc(self); - struct usb_attach_arg *uaa = device_get_ivars(self); - usbd_interface_handle iface; - u_int8_t epcount; - usbd_status r; - char * ermsg = ""; - int i; - - DPRINTFN(10,("urio_attach: sc=%p\n", sc)); - sc->sc_dev = self; - sc->sc_udev = uaa->device; - - if ((!uaa->device) || (!uaa->iface)) { - ermsg = "device or iface"; - goto nobulk; - } - sc->sc_iface = iface = uaa->iface; - sc->sc_opened = 0; - sc->sc_pipeh_in = 0; - sc->sc_pipeh_out = 0; - sc->sc_refcnt = 0; - - r = usbd_endpoint_count(iface, &epcount); - if (r != USBD_NORMAL_COMPLETION) { - ermsg = "endpoints"; - goto nobulk; - } - - sc->sc_epaddr[RIO_OUT] = 0xff; - sc->sc_epaddr[RIO_IN] = 0x00; - - for (i = 0; i < epcount; i++) { - usb_endpoint_descriptor_t *edesc = - usbd_interface2endpoint_descriptor(iface, i); - int d; - - if (!edesc) { - ermsg = "interface endpoint"; - goto nobulk; - } - - d = RIO_UE_GET_DIR(edesc->bEndpointAddress); - if (d != RIO_NODIR) - sc->sc_epaddr[d] = edesc->bEndpointAddress; - } - if ( sc->sc_epaddr[RIO_OUT] == 0xff || - sc->sc_epaddr[RIO_IN] == 0x00) { - ermsg = "Rio I&O"; - goto nobulk; - } - - make_dev(&urio_ops, device_get_unit(self), - UID_ROOT, GID_OPERATOR, - 0644, "urio%d", device_get_unit(self)); - - DPRINTFN(10, ("urio_attach: %p\n", sc->sc_udev)); - - return 0; - - nobulk: - kprintf("%s: could not find %s\n", device_get_nameunit(sc->sc_dev),ermsg); - return ENXIO; -} - - -int -urioopen(struct dev_open_args *ap) -{ - cdev_t dev = ap->a_head.a_dev; -#if (USBDI >= 1) - struct urio_softc * sc; -#endif - int unit = URIOUNIT(dev); - sc = devclass_get_softc(urio_devclass, unit); - if (sc == NULL) - return (ENXIO); - - DPRINTFN(5, ("urioopen: flag=%d, mode=%d, unit=%d\n", - ap->a_oflags, ap->a_devtype, unit)); - - if (sc->sc_opened) - return EBUSY; - - if ((ap->a_oflags & (FWRITE|FREAD)) != (FWRITE|FREAD)) - return EACCES; - - sc->sc_opened = 1; - sc->sc_pipeh_in = 0; - sc->sc_pipeh_out = 0; - if (usbd_open_pipe(sc->sc_iface, - sc->sc_epaddr[RIO_IN], 0, &sc->sc_pipeh_in) - != USBD_NORMAL_COMPLETION) - { - sc->sc_pipeh_in = 0; - return EIO; - } - if (usbd_open_pipe(sc->sc_iface, - sc->sc_epaddr[RIO_OUT], 0, &sc->sc_pipeh_out) - != USBD_NORMAL_COMPLETION) - { - usbd_close_pipe(sc->sc_pipeh_in); - sc->sc_pipeh_in = 0; - sc->sc_pipeh_out = 0; - return EIO; - } - return 0; -} - -int -urioclose(struct dev_close_args *ap) -{ - cdev_t dev = ap->a_head.a_dev; -#if (USBDI >= 1) - struct urio_softc * sc; -#endif - int unit = URIOUNIT(dev); - sc = devclass_get_softc(urio_devclass, unit); - - DPRINTFN(5, ("urioclose: flag=%d, mode=%d, unit=%d\n", - ap->a_fflag, ap->a_devtype, unit)); - if (sc->sc_pipeh_in) - usbd_close_pipe(sc->sc_pipeh_in); - - if (sc->sc_pipeh_out) - usbd_close_pipe(sc->sc_pipeh_out); - - sc->sc_pipeh_in = 0; - sc->sc_pipeh_out = 0; - sc->sc_opened = 0; - sc->sc_refcnt = 0; - return 0; -} - -int -urioread(struct dev_read_args *ap) -{ - cdev_t dev = ap->a_head.a_dev; - struct uio *uio = ap->a_uio; -#if (USBDI >= 1) - struct urio_softc * sc; - usbd_xfer_handle reqh; -#else - usbd_request_handle reqh; - usbd_private_handle r_priv; - void *r_buff; - usbd_status r_status; -#endif - int unit = URIOUNIT(dev); - usbd_status r; - char buf[URIO_BBSIZE]; - u_int32_t n, tn; - int error = 0; - - sc = devclass_get_softc(urio_devclass, unit); - - DPRINTFN(5, ("urioread: %d\n", unit)); - if (!sc->sc_opened) - return EIO; - -#if (USBDI >= 1) - sc->sc_refcnt++; - reqh = usbd_alloc_xfer(sc->sc_udev); -#else - reqh = usbd_alloc_request(); -#endif - if (reqh == 0) - return ENOMEM; - while ((n = szmin(URIO_BBSIZE, uio->uio_resid)) != 0) { - DPRINTFN(1, ("urioread: start transfer %d bytes\n", n)); - tn = n; -#if (USBDI >= 1) - usbd_setup_xfer(reqh, sc->sc_pipeh_in, 0, buf, tn, - 0, RIO_RW_TIMEOUT, 0); -#else - r = usbd_setup_request(reqh, sc->sc_pipeh_in, 0, buf, tn, - 0, RIO_RW_TIMEOUT, 0); - if (r != USBD_NORMAL_COMPLETION) { - error = EIO; - break; - } -#endif - r = usbd_sync_transfer(reqh); - if (r != USBD_NORMAL_COMPLETION) { - DPRINTFN(1, ("urioread: error=%d\n", r)); - usbd_clear_endpoint_stall(sc->sc_pipeh_in); - tn = 0; - error = EIO; - break; - } -#if (USBDI >= 1) - usbd_get_xfer_status(reqh, 0, 0, &tn, 0); -#else - usbd_get_request_status(reqh, &r_priv, &r_buff, &tn, &r_status); -#endif - - DPRINTFN(1, ("urioread: got %d bytes\n", tn)); - error = uiomove(buf, tn, uio); - if (error || tn < n) - break; - } -#if (USBDI >= 1) - usbd_free_xfer(reqh); -#else - usbd_free_request(reqh); -#endif - - return error; -} - -int -uriowrite(struct dev_write_args *ap) -{ - cdev_t dev = ap->a_head.a_dev; - struct uio *uio = ap->a_uio; -#if (USBDI >= 1) - struct urio_softc * sc; - usbd_xfer_handle reqh; -#else - usbd_request_handle reqh; -#endif - int unit = URIOUNIT(dev); - usbd_status r; - char buf[URIO_BBSIZE]; - u_int32_t n; - int error = 0; - - sc = devclass_get_softc(urio_devclass, unit); - - DPRINTFN(5, ("uriowrite: %d\n", unit)); - if (!sc->sc_opened) - return EIO; - -#if (USBDI >= 1) - sc->sc_refcnt++; - reqh = usbd_alloc_xfer(sc->sc_udev); -#else - reqh = usbd_alloc_request(); -#endif - if (reqh == 0) - return EIO; - while ((n = szmin(URIO_BBSIZE, uio->uio_resid)) != 0) { - error = uiomove(buf, n, uio); - if (error) - break; - DPRINTFN(1, ("uriowrite: transfer %d bytes\n", n)); -#if (USBDI >= 1) - usbd_setup_xfer(reqh, sc->sc_pipeh_out, 0, buf, n, - 0, RIO_RW_TIMEOUT, 0); -#else - r = usbd_setup_request(reqh, sc->sc_pipeh_out, 0, buf, n, - 0, RIO_RW_TIMEOUT, 0); - if (r != USBD_NORMAL_COMPLETION) { - error = EIO; - break; - } -#endif - r = usbd_sync_transfer(reqh); - if (r != USBD_NORMAL_COMPLETION) { - DPRINTFN(1, ("uriowrite: error=%d\n", r)); - usbd_clear_endpoint_stall(sc->sc_pipeh_out); - error = EIO; - break; - } -#if (USBDI >= 1) - usbd_get_xfer_status(reqh, 0, 0, 0, 0); -#endif - } - -#if (USBDI >= 1) - usbd_free_xfer(reqh); -#else - usbd_free_request(reqh); -#endif - - return error; -} - - -int -urioioctl(struct dev_ioctl_args *ap) -{ - cdev_t dev = ap->a_head.a_dev; -#if (USBDI >= 1) - struct urio_softc * sc; -#endif - int unit = URIOUNIT(dev); - struct RioCommand *rio_cmd; - int requesttype, len; - struct iovec iov; - struct uio uio; - usb_device_request_t req; - int req_flags = 0, req_actlen = 0; - void *ptr = NULL; - int error = 0; - usbd_status r; - - sc = devclass_get_softc(urio_devclass, unit); - - switch (ap->a_cmd) { - case RIO_RECV_COMMAND: - if (!(ap->a_fflag & FWRITE)) - return EPERM; - rio_cmd = (struct RioCommand *)ap->a_data; - if (rio_cmd == NULL) - return EINVAL; - len = rio_cmd->length; - - requesttype = rio_cmd->requesttype | UT_READ_VENDOR_DEVICE; - DPRINTFN(1,("sending command:reqtype=%0x req=%0x value=%0x index=%0x len=%0x\n", - requesttype, rio_cmd->request, rio_cmd->value, rio_cmd->index, len)); - break; - - case RIO_SEND_COMMAND: - if (!(ap->a_fflag & FWRITE)) - return EPERM; - rio_cmd = (struct RioCommand *)ap->a_data; - if (rio_cmd == NULL) - return EINVAL; - len = rio_cmd->length; - - requesttype = rio_cmd->requesttype | UT_WRITE_VENDOR_DEVICE; - DPRINTFN(1,("sending command:reqtype=%0x req=%0x value=%0x index=%0x len=%0x\n", - requesttype, rio_cmd->request, rio_cmd->value, rio_cmd->index, len)); - break; - - default: - return EINVAL; - break; - } - - /* Send rio control message */ - req.bmRequestType = requesttype; - req.bRequest = rio_cmd->request; - USETW(req.wValue, rio_cmd->value); - USETW(req.wIndex, rio_cmd->index); - USETW(req.wLength, len); - - if (len < 0 || len > 32767) - return EINVAL; - if (len != 0) { - iov.iov_base = (caddr_t)rio_cmd->buffer; - iov.iov_len = len; - uio.uio_iov = &iov; - uio.uio_iovcnt = 1; - uio.uio_resid = len; - uio.uio_offset = 0; - uio.uio_segflg = UIO_USERSPACE; - uio.uio_rw = - req.bmRequestType & UT_READ ? - UIO_READ : UIO_WRITE; - uio.uio_td = curthread; - ptr = kmalloc(len, M_TEMP, M_WAITOK); - if (uio.uio_rw == UIO_WRITE) { - error = uiomove(ptr, len, &uio); - if (error) - goto ret; - } - } - - r = usbd_do_request_flags(sc->sc_udev, &req, - ptr, req_flags, &req_actlen, - USBD_DEFAULT_TIMEOUT); - if (r == USBD_NORMAL_COMPLETION) { - error = 0; - if (len != 0) { - if (uio.uio_rw == UIO_READ) { - error = uiomove(ptr, len, &uio); - } - } - } else { - error = EIO; - } - -ret: - if (ptr) - kfree(ptr, M_TEMP); - return error; -} - -static int -urio_detach(device_t self) -{ - DPRINTF(("%s: disconnected\n", device_get_nameunit(self))); - dev_ops_remove_minor(&urio_ops, /*-1, */device_get_unit(self)); - /* XXX not implemented yet */ - device_set_desc(self, NULL); - return 0; -} - -DRIVER_MODULE(urio, uhub, urio_driver, urio_devclass, usbd_driver_load, NULL); - diff --git a/sys/dev/usbmisc/uscanner/Makefile b/sys/dev/usbmisc/uscanner/Makefile deleted file mode 100644 index d7d759ea05..0000000000 --- a/sys/dev/usbmisc/uscanner/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -# $FreeBSD: src/sys/modules/uscanner/Makefile,v 1.1.2.1 2000/10/31 23:16:08 n_hibma Exp $ -# $DragonFly: src/sys/dev/usbmisc/uscanner/Makefile,v 1.4 2004/08/13 17:51:07 dillon Exp $ - -.PATH: ${.CURDIR}/../../dev/usb -KMOD = uscanner -SRCS = bus_if.h device_if.h opt_usb.h uscanner.c - -.include diff --git a/sys/dev/usbmisc/uscanner/uscanner.c b/sys/dev/usbmisc/uscanner/uscanner.c deleted file mode 100644 index 653ea392ee..0000000000 --- a/sys/dev/usbmisc/uscanner/uscanner.c +++ /dev/null @@ -1,678 +0,0 @@ -/* - * $NetBSD: uscanner.c,v 1.30 2002/07/11 21:14:36 augustss Exp $ - * $FreeBSD: src/sys/dev/usb/uscanner.c,v 1.48 2003/12/22 19:58:27 sanpei Exp $ - */ - -/* Also already merged from NetBSD: - * $NetBSD: uscanner.c,v 1.33 2002/09/23 05:51:24 simonb Exp $ - */ - -/* - * Copyright (c) 2000 The NetBSD Foundation, Inc. - * All rights reserved. - * - * This code is derived from software contributed to The NetBSD Foundation - * by Lennart Augustsson (lennart@augustsson.net) at - * Carlstedt Research & Technology - * and Nick Hibma (n_hibma@qubesoft.com). - * - * 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. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the NetBSD - * Foundation, Inc. and its contributors. - * 4. Neither the name of The NetBSD Foundation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#ifdef USB_DEBUG -#define DPRINTF(x) if (uscannerdebug) kprintf x -#define DPRINTFN(n,x) if (uscannerdebug>(n)) kprintf x -int uscannerdebug = 0; -SYSCTL_NODE(_hw_usb, OID_AUTO, uscanner, CTLFLAG_RW, 0, "USB uscanner"); -SYSCTL_INT(_hw_usb_uscanner, OID_AUTO, debug, CTLFLAG_RW, - &uscannerdebug, 0, "uscanner debug level"); -#else -#define DPRINTF(x) -#define DPRINTFN(n,x) -#endif - -struct uscan_info { - struct usb_devno devno; - u_int flags; -#define USC_KEEP_OPEN 1 -}; - -/* Table of scanners that may work with this driver. */ -static const struct uscan_info uscanner_devs[] = { - /* Acer Peripherals */ - {{ USB_DEVICE(0x04a5, 0x2022) }, 0 }, /* Acerscan 320U */ - {{ USB_DEVICE(0x04a5, 0x20b0) }, 0 }, /* Benq 3300U/4300U */ - {{ USB_DEVICE(0x04a5, 0x2040) }, 0 }, /* Acerscan 640U */ - {{ USB_DEVICE(0x04a5, 0x20be) }, 0 }, /* Acerscan 640BT */ - {{ USB_DEVICE(0x04a5, 0x2060) }, 0 }, /* Acerscan 620U */ - {{ USB_DEVICE(0x04a5, 0x20c0) }, 0 }, /* Acerscan 1240U */ - {{ USB_DEVICE(0x04a5, 0x12a6) }, 0 }, /* Acerscan C310U */ - /* AGFA */ - {{ USB_DEVICE(0x06bd, 0x0002) }, 0 }, /* SnapScan 1236U */ - {{ USB_DEVICE(0x06bd, 0x0001) }, 0 }, /* SnapScan 1212U */ - {{ USB_DEVICE(0x06bd, 0x2061) }, 0 }, /* SnapScan 1212U */ - {{ USB_DEVICE(0x06bd, 0x0100) }, 0 }, /* SnapScan Touch */ - {{ USB_DEVICE(0x06bd, 0x208d) }, 0 }, /* SnapScan e40 */ - {{ USB_DEVICE(0x06bd, 0x208f) }, 0 }, /* SnapScan e50 */ - {{ USB_DEVICE(0x06bd, 0x2091) }, 0 }, /* SnapScan e20 */ - {{ USB_DEVICE(0x06bd, 0x2095) }, 0 }, /* SnapScan e25 */ - {{ USB_DEVICE(0x06bd, 0x2097) }, 0 }, /* SnapScan e26 */ - {{ USB_DEVICE(0x06bd, 0x20fd) }, 0 }, /* SnapScan e52 */ - /* Avision */ - {{ USB_DEVICE(0x0638, 0x0268) }, 0 }, /* Avision 1200U */ - /* Canon */ - {{ USB_DEVICE(0x04a9, 0x2206) }, 0 }, /* CanoScan N656U */ - {{ USB_DEVICE(0x04a9, 0x220d) }, 0 }, /* CanoScan N676U */ - {{ USB_DEVICE(0x04a9, 0x2207) }, 0 }, /* CanoScan N1220U */ - {{ USB_DEVICE(0x04a9, 0x2208) }, 0 }, /* CanoScan D660U */ - {{ USB_DEVICE(0x04a9, 0x220e) }, 0 }, /* CanoScan N1240U */ - {{ USB_DEVICE(0x04a9, 0x2220) }, 0 }, /* CanoScan LIDE 25 */ - /* Kye */ - {{ USB_DEVICE(0x0458, 0x2001) }, 0 }, /* ColorPage Vivid-Pro */ - /* HP */ - {{ USB_DEVICE(0x03f0, 0x0605) }, 0 }, /* ScanJet 2200C */ - {{ USB_DEVICE(0x03f0, 0x0205) }, 0 }, /* ScanJet 3300C */ - {{ USB_DEVICE(0x03f0, 0x0405) }, 0 }, /* ScanJet 3400cse */ - {{ USB_DEVICE(0x03f0, 0x0101) }, 0 }, /* Scanjet 4100C */ - {{ USB_DEVICE(0x03f0, 0x0105) }, 0 }, /* ScanJet 4200C */ - {{ USB_DEVICE(0x03f0, 0x0305) }, 0 }, /* Scanjet 4300C */ - {{ USB_DEVICE(0x03f0, 0x3005) }, 0 }, /* ScanJet 4670v */ - {{ USB_DEVICE(0x03f0, 0x0102) }, 0 }, /* Photosmart S20 */ - {{ USB_DEVICE(0x03f0, 0x0401) }, 0 }, /* Scanjet 5200C */ - {{ USB_DEVICE(0x03f0, 0x0701) }, 0 }, /* Scanjet 5300C */ - {{ USB_DEVICE(0x03f0, 0x1005) }, 0 }, /* Scanjet 5400C */ - {{ USB_DEVICE(0x03f0, 0x0201) }, 0 }, /* ScanJet 6200C */ - {{ USB_DEVICE(0x03f0, 0x0601) }, 0 }, /* Scanjet 6300C */ - {{ USB_DEVICE(0x03f0, 0x0b01) }, 0 }, /* Scanjet 82x0C */ - /* Scanlogic */ - {{ USB_DEVICE(0x04ce, 0x0300) }, 0 }, /* Phantom 336CX - C3 */ - /* Microtek */ - {{ USB_DEVICE(0x05da, 0x0099) }, 0 }, /* Phantom 336CX - C3 */ - {{ USB_DEVICE(0x05da, 0x0094) }, 0 }, /* ScanMaker X6 - X6U */ - {{ USB_DEVICE(0x05da, 0x00a0) }, 0 }, /* Phantom 336CX - C3 */ - {{ USB_DEVICE(0x05da, 0x009a) }, 0 }, /* Phantom C6 */ - {{ USB_DEVICE(0x05da, 0x00a3) }, 0 }, /* ScanMaker V6USL */ - {{ USB_DEVICE(0x05da, 0x80a3) }, 0 }, /* ScanMaker V6USL */ - {{ USB_DEVICE(0x05da, 0x80ac) }, 0 }, /* ScanMaker V6UL */ - /* Minolta */ - {{ USB_DEVICE(0x0686, 0x400e) }, 0 }, /* Dimage 5400 */ - /* Mustek */ - {{ USB_DEVICE(0x055f, 0x0001) }, 0 }, /* 1200 CU */ - {{ USB_DEVICE(0x055f, 0x0010) }, 0 }, /* BearPaw 1200F */ - {{ USB_DEVICE(0x055f, 0x021e) }, 0 }, /* BearPaw 1200TA */ - {{ USB_DEVICE(0x055f, 0x0873) }, 0 }, /* 600 USB */ - {{ USB_DEVICE(0x055f, 0x0002) }, 0 }, /* 600 CU */ - {{ USB_DEVICE(0x055f, 0x0003) }, 0 }, /* 1200 USB */ - {{ USB_DEVICE(0x055f, 0x0006) }, 0 }, /* 1200 UB */ - {{ USB_DEVICE(0x055f, 0x0007) }, 0 }, /* 1200 USB */ - {{ USB_DEVICE(0x055f, 0x0008) }, 0 }, /* 1200 CU */ - /* National */ - {{ USB_DEVICE(0x0400, 0x1000) }, 0 }, /* BearPaw 1200 */ - {{ USB_DEVICE(0x0400, 0x1001) }, 0 }, /* BearPaw 2400 */ - /* Nikon */ - {{ USB_DEVICE(0x04b0, 0x4000) }, 0 }, /* CoolScan LS40 ED */ - /* Primax */ - {{ USB_DEVICE(0x0461, 0x0300) }, 0 }, /* G2-200 */ - {{ USB_DEVICE(0x0461, 0x0301) }, 0 }, /* G2E-300 */ - {{ USB_DEVICE(0x0461, 0x0302) }, 0 }, /* G2-300 */ - {{ USB_DEVICE(0x0461, 0x0303) }, 0 }, /* G2E-300 */ - {{ USB_DEVICE(0x0461, 0x0340) }, 0 }, /* Colorado USB 9600 */ - {{ USB_DEVICE(0x0461, 0x0341) }, 0 }, /* Colorado 600u */ - {{ USB_DEVICE(0x0461, 0x0345) }, 0 }, /* Visioneer 6200 */ - {{ USB_DEVICE(0x0461, 0x0360) }, 0 }, /* Colorado USB 19200 */ - {{ USB_DEVICE(0x0461, 0x0361) }, 0 }, /* Colorado 1200u */ - {{ USB_DEVICE(0x0461, 0x0380) }, 0 }, /* G2-600 */ - {{ USB_DEVICE(0x0461, 0x0381) }, 0 }, /* ReadyScan 636i */ - {{ USB_DEVICE(0x0461, 0x0382) }, 0 }, /* G2-600 */ - {{ USB_DEVICE(0x0461, 0x0383) }, 0 }, /* G2E-600 */ - /* Epson */ - {{ USB_DEVICE(0x04b8, 0x0101) }, 0 }, /* Perfection 636U/636Photo */ - {{ USB_DEVICE(0x04b8, 0x0103) }, 0 }, /* Perfection 610 */ - {{ USB_DEVICE(0x04b8, 0x0104) }, 0 }, /* Perfection 1200U/1200Photo */ - {{ USB_DEVICE(0x04b8, 0x010b) }, 0 }, /* Perfection 1240U/1240Photo */ - {{ USB_DEVICE(0x04b8, 0x010f) }, 0 }, /* Perfection 1250U/1250Photo */ - {{ USB_DEVICE(0x04b8, 0x0107) }, 0 }, /* Expression 1600 */ - {{ USB_DEVICE(0x04b8, 0x010a) }, 0 }, /* Perfection 1640SU */ - {{ USB_DEVICE(0x04b8, 0x010c) }, 0 }, /* Perfection 640U */ - {{ USB_DEVICE(0x04b8, 0x0110) }, 0 }, /* Perfection 1650 */ - {{ USB_DEVICE(0x04b8, 0x011e) }, 0 }, /* Perfection 1660 */ - {{ USB_DEVICE(0x04b8, 0x011d) }, 0 }, /* Perfection 1260 */ - {{ USB_DEVICE(0x04b8, 0x011f) }, 0 }, /* Perfection 1670 */ - {{ USB_DEVICE(0x04b8, 0x0120) }, 0 }, /* Perfection 1270 */ - {{ USB_DEVICE(0x04b8, 0x080f) }, 0 }, /* Stylus Photo RX425 */ - {{ USB_DEVICE(0x04b8, 0x011c) }, USC_KEEP_OPEN }, /* Perfection 3200 */ - {{ USB_DEVICE(0x04b8, 0x0112) }, USC_KEEP_OPEN }, /* GT-9700F */ - {{ USB_DEVICE(0x04b8, 0x011b) }, 0 }, /* GT-9300UF */ - {{ USB_DEVICE(0x04b8, 0x0121) }, 0 }, /* Perfection 2480 */ - {{ USB_DEVICE(0x04b8, 0x080e) }, USC_KEEP_OPEN }, /* CX-3500/3600/3650 MFP */ - {{ USB_DEVICE(0x04b8, 0x0122) }, 0 }, /* Perfection 3590 */ - {{ USB_DEVICE(0x04b8, 0x0820) }, 0 }, /* CX4200 MP */ - {{ USB_DEVICE(0x04b8, 0x012a) }, 0 }, /* Perfection 4990 Photo */ - {{ USB_DEVICE(0x04b8, 0x082b) }, 0 }, /* DX-50x0 MFP */ - {{ USB_DEVICE(0x04b8, 0x082e) }, 0 }, /* DX-60x0 MFP */ - /* UMAX */ - {{ USB_DEVICE(0x1606, 0x0010) }, 0 }, /* Astra 1220U */ - {{ USB_DEVICE(0x1606, 0x0002) }, 0 }, /* Astra 1236U */ - {{ USB_DEVICE(0x1606, 0x0030) }, 0 }, /* Astra 2000U */ - {{ USB_DEVICE(0x1606, 0x0130) }, 0 }, /* Astra 2100U */ - {{ USB_DEVICE(0x1606, 0x0230) }, 0 }, /* Astra 2200U */ - {{ USB_DEVICE(0x1606, 0x0060) }, 0 }, /* Astra 3400 */ - /* Visioneer */ - {{ USB_DEVICE(0x04a7, 0x0224) }, 0 }, /* Scanport 3000 */ - {{ USB_DEVICE(0x04a7, 0x0221) }, 0 }, /* OneTouch 5300 */ - {{ USB_DEVICE(0x04a7, 0x0211) }, 0 }, /* OneTouch 7600 */ - {{ USB_DEVICE(0x04a7, 0x0231) }, 0 }, /* OneTouch 6100 */ - {{ USB_DEVICE(0x04a7, 0x0311) }, 0 }, /* OneTouch 6200 */ - {{ USB_DEVICE(0x04a7, 0x0321) }, 0 }, /* OneTouch 8100 */ - {{ USB_DEVICE(0x04a7, 0x0331) }, 0 }, /* OneTouch 8600 */ - /* Ultima */ - {{ USB_DEVICE(0x05d8, 0x4002) }, 0 }, /* 1200 UB Plus */ -}; -#define uscanner_lookup(v, p) ((const struct uscan_info *)usb_lookup(uscanner_devs, v, p)) - -#define USCANNER_BUFFERSIZE 1024 - -struct uscanner_softc { - device_t sc_dev; /* base device */ - usbd_device_handle sc_udev; - usbd_interface_handle sc_iface; - - u_int sc_dev_flags; - - usbd_pipe_handle sc_bulkin_pipe; - int sc_bulkin; - usbd_xfer_handle sc_bulkin_xfer; - void *sc_bulkin_buffer; - int sc_bulkin_bufferlen; - int sc_bulkin_datalen; - - usbd_pipe_handle sc_bulkout_pipe; - int sc_bulkout; - usbd_xfer_handle sc_bulkout_xfer; - void *sc_bulkout_buffer; - int sc_bulkout_bufferlen; - int sc_bulkout_datalen; - - u_char sc_state; -#define USCANNER_OPEN 0x01 /* opened */ - - int sc_refcnt; - u_char sc_dying; -}; - -d_open_t uscanneropen; -d_close_t uscannerclose; -d_read_t uscannerread; -d_write_t uscannerwrite; -d_kqfilter_t uscannerkqfilter; - -static struct dev_ops uscanner_ops = { - { "uscanner", 0, 0 }, - .d_open = uscanneropen, - .d_close = uscannerclose, - .d_read = uscannerread, - .d_write = uscannerwrite, - .d_kqfilter = uscannerkqfilter -}; - -static int uscanner_do_read(struct uscanner_softc *, struct uio *, int); -static int uscanner_do_write(struct uscanner_softc *, struct uio *, int); -static void uscanner_do_close(struct uscanner_softc *); - -#define USCANNERUNIT(n) (minor(n)) - -static device_probe_t uscanner_match; -static device_attach_t uscanner_attach; -static device_detach_t uscanner_detach; - -static devclass_t uscanner_devclass; - -static kobj_method_t uscanner_methods[] = { - DEVMETHOD(device_probe, uscanner_match), - DEVMETHOD(device_attach, uscanner_attach), - DEVMETHOD(device_detach, uscanner_detach), - DEVMETHOD_END -}; - -static driver_t uscanner_driver = { - "uscanner", - uscanner_methods, - sizeof(struct uscanner_softc) -}; - -MODULE_DEPEND(uscanner, usb, 1, 1, 1); - -static int -uscanner_match(device_t self) -{ - struct usb_attach_arg *uaa = device_get_ivars(self); - - if (uaa->iface != NULL) - return UMATCH_NONE; - - return (uscanner_lookup(uaa->vendor, uaa->product) != NULL ? - UMATCH_VENDOR_PRODUCT : UMATCH_NONE); -} - -static int -uscanner_attach(device_t self) -{ - struct uscanner_softc *sc = device_get_softc(self); - struct usb_attach_arg *uaa = device_get_ivars(self); - usb_interface_descriptor_t *id = NULL; - usb_endpoint_descriptor_t *ed, *ed_bulkin = NULL, *ed_bulkout = NULL; - int i; - usbd_status err; - - sc->sc_dev = self; - - sc->sc_dev_flags = uscanner_lookup(uaa->vendor, uaa->product)->flags; - - sc->sc_udev = uaa->device; - - err = usbd_set_config_no(uaa->device, 1, 1); /* XXX */ - if (err) { - kprintf("%s: setting config no failed\n", - device_get_nameunit(sc->sc_dev)); - return ENXIO; - } - - /* XXX We only check the first interface */ - err = usbd_device2interface_handle(sc->sc_udev, 0, &sc->sc_iface); - if (!err && sc->sc_iface) - id = usbd_get_interface_descriptor(sc->sc_iface); - if (err || id == NULL) { - kprintf("%s: could not get interface descriptor, err=%d,id=%p\n", - device_get_nameunit(sc->sc_dev), err, id); - return ENXIO; - } - - /* Find the two first bulk endpoints */ - for (i = 0 ; i < id->bNumEndpoints; i++) { - ed = usbd_interface2endpoint_descriptor(sc->sc_iface, i); - if (ed == NULL) { - kprintf("%s: could not read endpoint descriptor\n", - device_get_nameunit(sc->sc_dev)); - return ENXIO; - } - - if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN - && (ed->bmAttributes & UE_XFERTYPE) == UE_BULK) { - ed_bulkin = ed; - } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT - && (ed->bmAttributes & UE_XFERTYPE) == UE_BULK) { - ed_bulkout = ed; - } - - if (ed_bulkin && ed_bulkout) /* found all we need */ - break; - } - - /* Verify that we goething sensible */ - if (ed_bulkin == NULL || ed_bulkout == NULL) { - kprintf("%s: bulk-in and/or bulk-out endpoint not found\n", - device_get_nameunit(sc->sc_dev)); - return ENXIO; - } - - sc->sc_bulkin = ed_bulkin->bEndpointAddress; - sc->sc_bulkout = ed_bulkout->bEndpointAddress; - - /* the main device, ctrl endpoint */ - make_dev(&uscanner_ops, device_get_unit(sc->sc_dev), - UID_ROOT, GID_OPERATOR, 0644, - "%s", device_get_nameunit(sc->sc_dev)); - - usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev, - sc->sc_dev); - - return 0; -} - -int -uscanneropen(struct dev_open_args *ap) -{ - cdev_t dev = ap->a_head.a_dev; - struct uscanner_softc *sc; - int unit = USCANNERUNIT(dev); - usbd_status err; - - sc = devclass_get_softc(uscanner_devclass, unit); - if (sc == NULL) - return (ENXIO); - - DPRINTFN(5, ("uscanneropen: flag=%d, mode=%d, unit=%d\n", - ap->a_oflags, ap->a_devtype, unit)); - - if (sc->sc_dying) - return (ENXIO); - - if (sc->sc_state & USCANNER_OPEN) - return (EBUSY); - - sc->sc_state |= USCANNER_OPEN; - - sc->sc_bulkin_buffer = kmalloc(USCANNER_BUFFERSIZE, M_USBDEV, M_WAITOK); - sc->sc_bulkout_buffer = kmalloc(USCANNER_BUFFERSIZE, M_USBDEV, M_WAITOK); - /* No need to check buffers for NULL since we have WAITOK */ - - sc->sc_bulkin_bufferlen = USCANNER_BUFFERSIZE; - sc->sc_bulkout_bufferlen = USCANNER_BUFFERSIZE; - - /* We have decided on which endpoints to use, now open the pipes */ - if (sc->sc_bulkin_pipe == NULL) { - err = usbd_open_pipe(sc->sc_iface, sc->sc_bulkin, - USBD_EXCLUSIVE_USE, &sc->sc_bulkin_pipe); - if (err) { - kprintf("%s: cannot open bulk-in pipe (addr %d)\n", - device_get_nameunit(sc->sc_dev), sc->sc_bulkin); - uscanner_do_close(sc); - return (EIO); - } - } - if (sc->sc_bulkout_pipe == NULL) { - err = usbd_open_pipe(sc->sc_iface, sc->sc_bulkout, - USBD_EXCLUSIVE_USE, &sc->sc_bulkout_pipe); - if (err) { - kprintf("%s: cannot open bulk-out pipe (addr %d)\n", - device_get_nameunit(sc->sc_dev), sc->sc_bulkout); - uscanner_do_close(sc); - return (EIO); - } - } - - sc->sc_bulkin_xfer = usbd_alloc_xfer(sc->sc_udev); - if (sc->sc_bulkin_xfer == NULL) { - uscanner_do_close(sc); - return (ENOMEM); - } - sc->sc_bulkout_xfer = usbd_alloc_xfer(sc->sc_udev); - if (sc->sc_bulkout_xfer == NULL) { - uscanner_do_close(sc); - return (ENOMEM); - } - - return (0); /* success */ -} - -int -uscannerclose(struct dev_close_args *ap) -{ - cdev_t dev = ap->a_head.a_dev; - struct uscanner_softc *sc; - - sc = devclass_get_softc(uscanner_devclass, USCANNERUNIT(dev)); - - DPRINTFN(5, ("uscannerclose: flag=%d, mode=%d, unit=%d\n", - ap->a_fflag, ap->a_devtype, USCANNERUNIT(dev))); - -#ifdef DIAGNOSTIC - if (!(sc->sc_state & USCANNER_OPEN)) { - kprintf("uscannerclose: not open\n"); - return (EINVAL); - } -#endif - - uscanner_do_close(sc); - - return (0); -} - -void -uscanner_do_close(struct uscanner_softc *sc) -{ - if (sc->sc_bulkin_xfer) { - usbd_free_xfer(sc->sc_bulkin_xfer); - sc->sc_bulkin_xfer = NULL; - } - if (sc->sc_bulkout_xfer) { - usbd_free_xfer(sc->sc_bulkout_xfer); - sc->sc_bulkout_xfer = NULL; - } - - if (!(sc->sc_dev_flags & USC_KEEP_OPEN)) { - if (sc->sc_bulkin_pipe != NULL) { - usbd_abort_pipe(sc->sc_bulkin_pipe); - usbd_close_pipe(sc->sc_bulkin_pipe); - sc->sc_bulkin_pipe = NULL; - } - if (sc->sc_bulkout_pipe != NULL) { - usbd_abort_pipe(sc->sc_bulkout_pipe); - usbd_close_pipe(sc->sc_bulkout_pipe); - sc->sc_bulkout_pipe = NULL; - } - } - - if (sc->sc_bulkin_buffer) { - kfree(sc->sc_bulkin_buffer, M_USBDEV); - sc->sc_bulkin_buffer = NULL; - } - if (sc->sc_bulkout_buffer) { - kfree(sc->sc_bulkout_buffer, M_USBDEV); - sc->sc_bulkout_buffer = NULL; - } - - sc->sc_state &= ~USCANNER_OPEN; -} - -static int -uscanner_do_read(struct uscanner_softc *sc, struct uio *uio, int flag) -{ - u_int32_t n, tn; - usbd_status err; - int error = 0; - - DPRINTFN(5, ("%s: uscannerread\n", device_get_nameunit(sc->sc_dev))); - - if (sc->sc_dying) - return (EIO); - - while ((n = szmin(sc->sc_bulkin_bufferlen, uio->uio_resid)) != 0) { - DPRINTFN(1, ("uscannerread: start transfer %d bytes\n",n)); - tn = n; - - err = usbd_bulk_transfer( - sc->sc_bulkin_xfer, sc->sc_bulkin_pipe, - USBD_SHORT_XFER_OK, USBD_NO_TIMEOUT, - sc->sc_bulkin_buffer, &tn, - "uscnrb"); - if (err) { - if (err == USBD_INTERRUPTED) - error = EINTR; - else if (err == USBD_TIMEOUT) - error = ETIMEDOUT; - else - error = EIO; - break; - } - DPRINTFN(1, ("uscannerread: got %d bytes\n", tn)); - error = uiomove(sc->sc_bulkin_buffer, tn, uio); - if (error || tn < n) - break; - } - - return (error); -} - -int -uscannerread(struct dev_read_args *ap) -{ - cdev_t dev = ap->a_head.a_dev; - struct uscanner_softc *sc; - int error; - - sc = devclass_get_softc(uscanner_devclass, USCANNERUNIT(dev)); - - sc->sc_refcnt++; - error = uscanner_do_read(sc, ap->a_uio, ap->a_ioflag); - if (--sc->sc_refcnt < 0) - usb_detach_wakeup(sc->sc_dev); - - return (error); -} - -static int -uscanner_do_write(struct uscanner_softc *sc, struct uio *uio, int flag) -{ - u_int32_t n; - int error = 0; - usbd_status err; - - DPRINTFN(5, ("%s: uscanner_do_write\n", device_get_nameunit(sc->sc_dev))); - - if (sc->sc_dying) - return (EIO); - - while ((n = szmin(sc->sc_bulkout_bufferlen, uio->uio_resid)) != 0) { - error = uiomove(sc->sc_bulkout_buffer, n, uio); - if (error) - break; - DPRINTFN(1, ("uscanner_do_write: transfer %d bytes\n", n)); - err = usbd_bulk_transfer( - sc->sc_bulkout_xfer, sc->sc_bulkout_pipe, - 0, USBD_NO_TIMEOUT, - sc->sc_bulkout_buffer, &n, - "uscnwb"); - if (err) { - if (err == USBD_INTERRUPTED) - error = EINTR; - else - error = EIO; - break; - } - } - - return (error); -} - -int -uscannerwrite(struct dev_write_args *ap) -{ - cdev_t dev = ap->a_head.a_dev; - struct uscanner_softc *sc; - int error; - - sc = devclass_get_softc(uscanner_devclass, USCANNERUNIT(dev)); - - sc->sc_refcnt++; - error = uscanner_do_write(sc, ap->a_uio, ap->a_ioflag); - if (--sc->sc_refcnt < 0) - usb_detach_wakeup(sc->sc_dev); - return (error); -} - -static int -uscanner_detach(device_t self) -{ - struct uscanner_softc *sc = device_get_softc(self); - - DPRINTF(("uscanner_detach: sc=%p\n", sc)); - - sc->sc_dying = 1; - sc->sc_dev_flags = 0; /* make close really close device */ - - /* Abort all pipes. Causes processes waiting for transfer to wake. */ - if (sc->sc_bulkin_pipe != NULL) - usbd_abort_pipe(sc->sc_bulkin_pipe); - if (sc->sc_bulkout_pipe != NULL) - usbd_abort_pipe(sc->sc_bulkout_pipe); - - crit_enter(); - if (--sc->sc_refcnt >= 0) { - /* Wait for processes to go away. */ - usb_detach_wait(sc->sc_dev); - } - crit_exit(); - - /* destroy the device for the control endpoint */ - dev_ops_remove_minor(&uscanner_ops, /*-1, */device_get_unit(sc->sc_dev)); - - usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev, - sc->sc_dev); - - return (0); -} - -static void -uscannerfilt_detach(struct knote *kn) {} - -static int -uscannerfilt(struct knote *kn, long hint) -{ - /* - * We have no easy way of determining if a read will - * yield any data or a write will happen. - * Pretend they will. - */ - return (1); -} - -static struct filterops uscannerfiltops = - { FILTEROP_ISFD, NULL, uscannerfilt_detach, uscannerfilt }; - -int -uscannerkqfilter(struct dev_kqfilter_args *ap) -{ -/* XXX - cdev_t dev = ap->a_head.a_dev; - struct uscanner_softc *sc = devclass_get_softc(uscanner_devclass, USCANNERUNIT(dev)); - - if (sc->sc_dying) - return (EIO); -*/ - - ap->a_result = 0; - ap->a_kn->kn_fop = &uscannerfiltops; - return (0); -} - -DRIVER_MODULE(uscanner, uhub, uscanner_driver, uscanner_devclass, usbd_driver_load, NULL); - diff --git a/sys/dev/usbmisc/uslcom/Makefile b/sys/dev/usbmisc/uslcom/Makefile deleted file mode 100644 index f4381f6bc2..0000000000 --- a/sys/dev/usbmisc/uslcom/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -# $DragonFly: src/sys/dev/usbmisc/uslcom/Makefile,v 1.2 2007/09/29 21:13:09 swildner Exp $ - -.PATH: ${.CURDIR}/../ucom - -KMOD= uslcom -SRCS= uslcom.c opt_usb.h device_if.h bus_if.h - -.include diff --git a/sys/dev/usbmisc/uslcom/uslcom.c b/sys/dev/usbmisc/uslcom/uslcom.c deleted file mode 100644 index 13c3c4fae8..0000000000 --- a/sys/dev/usbmisc/uslcom/uslcom.c +++ /dev/null @@ -1,480 +0,0 @@ -/* $OpenBSD: uslcom.c,v 1.17 2007/11/24 10:52:12 jsg Exp $ */ - -/* - * Copyright (c) 2006 Jonathan Gray - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include - -#ifdef USLCOM_DEBUG -#define DPRINTFN(n, x) do { if (uslcomdebug > (n)) kprintf x; } while (0) -int uslcomdebug = 0; -#else -#define DPRINTFN(n, x) -#endif -#define DPRINTF(x) DPRINTFN(0, x) - -#define USLCOMBUFSZ 256 -#define USLCOM_CONFIG_NO 0 -#define USLCOM_IFACE_NO 0 - -#define USLCOM_SET_DATA_BITS(x) (x << 8) - -#define USLCOM_WRITE 0x41 -#define USLCOM_READ 0xc1 - -#define USLCOM_UART 0x00 -#define USLCOM_BAUD_RATE 0x01 -#define USLCOM_DATA 0x03 -#define USLCOM_BREAK 0x05 -#define USLCOM_CTRL 0x07 -#define USLCOM_MODEM 0x13 - -#define USLCOM_UART_DISABLE 0x00 -#define USLCOM_UART_ENABLE 0x01 - -#define USLCOM_CTRL_DTR_ON 0x0001 -#define USLCOM_CTRL_DTR_SET 0x0100 -#define USLCOM_CTRL_RTS_ON 0x0002 -#define USLCOM_CTRL_RTS_SET 0x0200 -#define USLCOM_CTRL_CTS 0x0010 -#define USLCOM_CTRL_DSR 0x0020 -#define USLCOM_CTRL_DCD 0x0080 - - -#define USLCOM_BAUD_REF 0x384000 - -#define USLCOM_STOP_BITS_1 0x00 -#define USLCOM_STOP_BITS_2 0x02 - -#define USLCOM_PARITY_NONE 0x00 -#define USLCOM_PARITY_ODD 0x10 -#define USLCOM_PARITY_EVEN 0x20 - -#define USLCOM_BREAK_OFF 0x00 -#define USLCOM_BREAK_ON 0x01 - - -struct uslcom_softc { - struct ucom_softc sc_ucom; - u_char sc_msr; - u_char sc_lsr; -}; - -static void uslcom_get_status(void *, int portno, u_char *lsr, - u_char *msr); -static void uslcom_set(void *, int, int, int); -static int uslcom_param(void *, int, struct termios *); -static int uslcom_open(void *sc, int portno); -static void uslcom_close(void *, int); -static void uslcom_break(void *sc, int portno, int onoff); -static void uslcom_set_flow_ctrl(struct uslcom_softc *sc, tcflag_t cflag, - tcflag_t iflag); - -struct ucom_callback uslcom_callback = { - uslcom_get_status, - uslcom_set, - uslcom_param, - NULL, - uslcom_open, - uslcom_close, - NULL, - NULL, -}; - -static const struct usb_devno uslcom_devs[] = { - { USB_DEVICE(0x0fcf, 0x1003) }, /* ANT development board */ - { USB_DEVICE(0x10a6, 0xaa26) }, /* Noname DCU-11 clone */ - { USB_DEVICE(0x10ab, 0x10c5) }, /* USI MC60 */ - { USB_DEVICE(0x10b5, 0xac70) }, /* PLX CA-42 */ - { USB_DEVICE(0x10c4, 0x803b) }, /* Pololu Serial */ - { USB_DEVICE(0x10c4, 0x8053) }, /* Enfora EDG1228 */ - { USB_DEVICE(0x10c4, 0x8066) }, /* Argussoft In-System Programmer */ - { USB_DEVICE(0x10c4, 0x807a) }, /* Crumb128 board */ - { USB_DEVICE(0x10c4, 0x80ca) }, /* Degree Controls */ - { USB_DEVICE(0x10c4, 0x80dd) }, /* Tracient RFID */ - { USB_DEVICE(0x10c4, 0x80ed) }, /* Track Systems Traqmate */ - { USB_DEVICE(0x10c4, 0x80f6) }, /* Suunto sports */ - { USB_DEVICE(0x10c4, 0x813d) }, /* Burnside Desktop mobile */ - { USB_DEVICE(0x10c4, 0x814a) }, /* West Mountain Radio RIGblaster */ - { USB_DEVICE(0x10c4, 0x814b) }, /* West Mountain Radio RIGtalk */ - { USB_DEVICE(0x10c4, 0x815e) }, /* IP-Link 1220 */ - { USB_DEVICE(0x10c4, 0x81c8) }, /* Lipowsky Baby-JTAG */ - { USB_DEVICE(0x10c4, 0x81e2) }, /* Lipowsky Baby-LIN */ - { USB_DEVICE(0x10c4, 0x8218) }, /* Lipowsky HARP-1 */ - { USB_DEVICE(0x10c4, 0xea60) }, /* Silicon Labs CP210x */ - { USB_DEVICE(0x10c4, 0xea61) }, /* Silicon Labs CP210x */ - { USB_DEVICE(0x13ad, 0x9999) }, /* Baltech card reader */ - { USB_DEVICE(0x16d6, 0x0001) }, /* Jablotron PC-60B */ -}; - -static device_probe_t uslcom_match; -static device_attach_t uslcom_attach; -static device_detach_t uslcom_detach; - -static device_method_t uslcom_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, uslcom_match), - DEVMETHOD(device_attach, uslcom_attach), - DEVMETHOD(device_detach, uslcom_detach), - DEVMETHOD_END -}; - -static driver_t uslcom_driver = { - "ucom", - uslcom_methods, - sizeof (struct uslcom_softc) -}; - -DRIVER_MODULE(uslcom, uhub, uslcom_driver, ucom_devclass, usbd_driver_load, NULL); -MODULE_DEPEND(uslcom, usb, 1, 1, 1); -MODULE_DEPEND(uslcom, ucom, UCOM_MINVER, UCOM_PREFVER, UCOM_MAXVER); -MODULE_VERSION(uslcom, 1); - -static int -uslcom_match(device_t self) -{ - struct usb_attach_arg *uaa = device_get_ivars(self); - - if (uaa->iface != NULL) - return UMATCH_NONE; - - return (usb_lookup(uslcom_devs, uaa->vendor, uaa->product) != NULL) ? - UMATCH_VENDOR_PRODUCT : UMATCH_NONE; -} - -static int -uslcom_attach(device_t self) -{ - struct uslcom_softc *sc = device_get_softc(self); - struct usb_attach_arg *uaa = device_get_ivars(self); - struct ucom_softc *ucom; - usb_interface_descriptor_t *id; - usb_endpoint_descriptor_t *ed; - usbd_status error; - int i; - - ucom = &sc->sc_ucom; - - bzero(sc, sizeof (struct uslcom_softc)); - - ucom->sc_dev = self; - ucom->sc_udev = uaa->device; - ucom->sc_iface = uaa->iface; - - if (usbd_set_config_index(ucom->sc_udev, USLCOM_CONFIG_NO, 1) != 0) { - device_printf(ucom->sc_dev, "could not set configuration no\n"); - goto error; - } - - /* get the first interface handle */ - error = usbd_device2interface_handle(ucom->sc_udev, USLCOM_IFACE_NO, - &ucom->sc_iface); - if (error != 0) { - device_printf(ucom->sc_dev, "could not get interface handle\n"); - goto error; - } - - id = usbd_get_interface_descriptor(ucom->sc_iface); - - ucom->sc_bulkin_no = ucom->sc_bulkout_no = -1; - for (i = 0; i < id->bNumEndpoints; i++) { - ed = usbd_interface2endpoint_descriptor(ucom->sc_iface, i); - if (ed == NULL) { - device_printf(ucom->sc_dev, "no endpoint descriptor " - "found for %d\n", i); - goto error; - } - - if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && - UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) - ucom->sc_bulkin_no = ed->bEndpointAddress; - else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT && - UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) - ucom->sc_bulkout_no = ed->bEndpointAddress; - } - - if (ucom->sc_bulkin_no == -1 || ucom->sc_bulkout_no == -1) { - device_printf(ucom->sc_dev, "missing endpoint\n"); - goto error; - } - - ucom->sc_parent = sc; - ucom->sc_portno = UCOM_UNK_PORTNO; - ucom->sc_ibufsize = USLCOMBUFSZ; - ucom->sc_obufsize = USLCOMBUFSZ; - ucom->sc_ibufsizepad = USLCOMBUFSZ; - ucom->sc_opkthdrlen = 0; - ucom->sc_callback = &uslcom_callback; - - usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, ucom->sc_udev, - ucom->sc_dev); - - DPRINTF(("uslcom: in = 0x%x, out = 0x%x, intr = 0x%x\n", - ucom->sc_bulkin_no, ucom->sc_bulkout_no, sc->sc_intr_number)); - - ucom_attach(&sc->sc_ucom); - return 0; - -error: - ucom->sc_dying = 1; - return ENXIO; -} - -static int -uslcom_detach(device_t self) -{ - struct uslcom_softc *sc = device_get_softc(self); - int rv = 0; - - DPRINTF(("uslcom_detach: sc=%p\n", sc)); - sc->sc_ucom.sc_dying = 1; - rv = ucom_detach(&sc->sc_ucom); - usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_ucom.sc_udev, - sc->sc_ucom.sc_dev); - - return (rv); -} - -#if 0 /* not yet */ -int -uslcom_activate(struct device *self, enum devact act) -{ - struct uslcom_softc *sc = (struct uslcom_softc *)self; - int rv = 0; - - switch (act) { - case DVACT_ACTIVATE: - break; - - case DVACT_DEACTIVATE: - if (sc->sc_subdev != NULL) - rv = config_deactivate(sc->sc_subdev); - sc->sc_dying = 1; - break; - } - return (rv); -} -#endif - -static int -uslcom_open(void *vsc, int portno) -{ - struct uslcom_softc *sc = vsc; - usb_device_request_t req; - usbd_status err; - - if (sc->sc_ucom.sc_dying) - return (EIO); - - req.bmRequestType = USLCOM_WRITE; - req.bRequest = USLCOM_UART; - USETW(req.wValue, USLCOM_UART_ENABLE); - USETW(req.wIndex, portno); - USETW(req.wLength, 0); - err = usbd_do_request(sc->sc_ucom.sc_udev, &req, NULL); - if (err) - return (EIO); - - return (0); -} - -static void -uslcom_close(void *vsc, int portno) -{ - struct uslcom_softc *sc = vsc; - usb_device_request_t req; - - if (sc->sc_ucom.sc_dying) - return; - - req.bmRequestType = USLCOM_WRITE; - req.bRequest = USLCOM_UART; - USETW(req.wValue, USLCOM_UART_DISABLE); - USETW(req.wIndex, portno); - USETW(req.wLength, 0); - usbd_do_request(sc->sc_ucom.sc_udev, &req, NULL); -} - -static void -uslcom_set(void *vsc, int portno, int reg, int onoff) -{ - struct uslcom_softc *sc = vsc; - usb_device_request_t req; - int ctl; - - switch (reg) { - case UCOM_SET_DTR: - ctl = onoff ? USLCOM_CTRL_DTR_ON : 0; - ctl |= USLCOM_CTRL_DTR_SET; - break; - case UCOM_SET_RTS: - ctl = onoff ? USLCOM_CTRL_RTS_ON : 0; - ctl |= USLCOM_CTRL_RTS_SET; - break; - case UCOM_SET_BREAK: - uslcom_break(sc, portno, onoff); - return; - default: - return; - } - req.bmRequestType = USLCOM_WRITE; - req.bRequest = USLCOM_CTRL; - USETW(req.wValue, ctl); - USETW(req.wIndex, portno); - USETW(req.wLength, 0); - usbd_do_request(sc->sc_ucom.sc_udev, &req, NULL); -} - -static int -uslcom_param(void *vsc, int portno, struct termios *t) -{ - struct uslcom_softc *sc = (struct uslcom_softc *)vsc; - usbd_status err; - usb_device_request_t req; - int data; - - if (t->c_ospeed <= 0 || t->c_ospeed > 921600) - return (EINVAL); - - req.bmRequestType = USLCOM_WRITE; - req.bRequest = USLCOM_BAUD_RATE; - USETW(req.wValue, USLCOM_BAUD_REF / t->c_ospeed); - USETW(req.wIndex, portno); - USETW(req.wLength, 0); - err = usbd_do_request(sc->sc_ucom.sc_udev, &req, NULL); - if (err) - return (EIO); - - if (ISSET(t->c_cflag, CSTOPB)) - data = USLCOM_STOP_BITS_2; - else - data = USLCOM_STOP_BITS_1; - if (ISSET(t->c_cflag, PARENB)) { - if (ISSET(t->c_cflag, PARODD)) - data |= USLCOM_PARITY_ODD; - else - data |= USLCOM_PARITY_EVEN; - } else - data |= USLCOM_PARITY_NONE; - switch (ISSET(t->c_cflag, CSIZE)) { - case CS5: - data |= USLCOM_SET_DATA_BITS(5); - break; - case CS6: - data |= USLCOM_SET_DATA_BITS(6); - break; - case CS7: - data |= USLCOM_SET_DATA_BITS(7); - break; - case CS8: - data |= USLCOM_SET_DATA_BITS(8); - break; - } - - req.bmRequestType = USLCOM_WRITE; - req.bRequest = USLCOM_DATA; - USETW(req.wValue, data); - USETW(req.wIndex, portno); - USETW(req.wLength, 0); - err = usbd_do_request(sc->sc_ucom.sc_udev, &req, NULL); - if (err) - return (EIO); - - uslcom_set_flow_ctrl(sc, t->c_cflag, t->c_iflag); - - return (0); -} - -static void -uslcom_get_status(void *vsc, int portno, u_char *lsr, u_char *msr) -{ - struct uslcom_softc *sc = vsc; - - if (msr != NULL) - *msr = sc->sc_msr; - if (lsr != NULL) - *lsr = sc->sc_lsr; -} - -static void -uslcom_break(void *vsc, int portno, int onoff) -{ - struct uslcom_softc *sc = vsc; - usb_device_request_t req; - int brk = onoff ? USLCOM_BREAK_ON : USLCOM_BREAK_OFF; - - req.bmRequestType = USLCOM_WRITE; - req.bRequest = USLCOM_BREAK; - USETW(req.wValue, brk); - USETW(req.wIndex, portno); - USETW(req.wLength, 0); - usbd_do_request(sc->sc_ucom.sc_udev, &req, NULL); -} - -static void -uslcom_set_flow_ctrl(struct uslcom_softc *sc, tcflag_t cflag, tcflag_t iflag) -{ - uint8_t modemdata[16]; - usb_device_request_t req; - usbd_status err; - - req.bmRequestType = USLCOM_READ; - req.bRequest = USLCOM_MODEM; - USETW(req.wValue, 0); - USETW(req.wIndex, 0); - USETW(req.wLength, 16); - - err = usbd_do_request(sc->sc_ucom.sc_udev, &req, modemdata); - if (err) - device_printf(sc->sc_ucom.sc_dev, "uslcom_set_flow: %s\n", - usbd_errstr(err)); - - if (ISSET(cflag, CRTSCTS)) { - modemdata[0] &= ~0x7b; - modemdata[0] |= 0x09; - modemdata[4] = 0x80; - } else { - modemdata[0] &= ~0x7b; - modemdata[0] |= 0x01; - modemdata[4] = 0x40; - } - - req.bmRequestType = USLCOM_WRITE; - req.bRequest = USLCOM_MODEM; - USETW(req.wValue, 0); - USETW(req.wIndex, 0); - USETW(req.wLength, 16); - - err = usbd_do_request(sc->sc_ucom.sc_udev, &req, modemdata); - if (err) - device_printf(sc->sc_ucom.sc_dev, "uslcom_set_flow: %s\n", - usbd_errstr(err)); -} - diff --git a/sys/dev/usbmisc/uticom/Makefile b/sys/dev/usbmisc/uticom/Makefile deleted file mode 100644 index 12953cab25..0000000000 --- a/sys/dev/usbmisc/uticom/Makefile +++ /dev/null @@ -1,10 +0,0 @@ -# $DragonFly: src/sys/dev/usbmisc/uticom/Makefile,v 1.1 2007/11/07 08:31:08 hasso Exp $ - -.PATH: ${.CURDIR}/../ucom - -KMOD= uticom -SRCS= uticom.c uticom_fw3410.h -SRCS+= ucomvar.h opt_usb.h bus_if.h device_if.h - -.include - diff --git a/sys/dev/usbmisc/uticom/uticom.c b/sys/dev/usbmisc/uticom/uticom.c deleted file mode 100644 index adfa8431f1..0000000000 --- a/sys/dev/usbmisc/uticom/uticom.c +++ /dev/null @@ -1,971 +0,0 @@ -/* - * Copyright (c) 2006-2007 Dmitry Komissaroff . - * Copyright (c) 2007 Hasso Tepper . - * - * 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include "../ucom/ucomvar.h" - -#include "uticom_fw3410.h" - -SYSCTL_NODE(_hw_usb, OID_AUTO, uticom, CTLFLAG_RW, 0, "USB uticom"); - -#ifdef USB_DEBUG -static int uticomdebug = 0; -SYSCTL_INT(_hw_usb_uticom, OID_AUTO, debug, CTLFLAG_RW, &uticomdebug, 0, - "uticom debug level"); - -#define DPRINTFN(n, x) do { if (uticomdebug > (n)) kprintf x; } while (0) -#else -#define DPRINTFN(n, x) -#endif - -#define DPRINTF(x) DPRINTFN(0, x) - -#define UTICOM_CONFIG_INDEX 1 -#define UTICOM_ACTIVE_INDEX 2 - -#define UTICOM_IFACE_INDEX 0 - -/* - * These are the maximum number of bytes transferred per frame. - * The output buffer size cannot be increased due to the size encoding. - */ -#define UTICOM_IBUFSZ 64 -#define UTICOM_OBUFSZ 64 - -#define UTICOM_FW_BUFSZ 16284 - -#define UTICOM_INTR_INTERVAL 100 /* ms */ - -#define UTICOM_RQ_LINE 0 -/* Used to sync data0/1-toggle on reopen bulk pipe. */ -#define UTICOM_RQ_SOF 1 -#define UTICOM_RQ_SON 2 - -#define UTICOM_RQ_BAUD 3 -#define UTICOM_RQ_LCR 4 -#define UTICOM_RQ_FCR 5 -#define UTICOM_RQ_RTS 6 -#define UTICOM_RQ_DTR 7 -#define UTICOM_RQ_BREAK 8 -#define UTICOM_RQ_CRTSCTS 9 - -#define UTICOM_BRATE_REF 923077 - -#define UTICOM_SET_DATA_BITS(x) (x - 5) - -#define UTICOM_STOP_BITS_1 0x00 -#define UTICOM_STOP_BITS_2 0x40 - -#define UTICOM_PARITY_NONE 0x00 -#define UTICOM_PARITY_ODD 0x08 -#define UTICOM_PARITY_EVEN 0x18 - -#define UTICOM_LCR_OVR 0x1 -#define UTICOM_LCR_PTE 0x2 -#define UTICOM_LCR_FRE 0x4 -#define UTICOM_LCR_BRK 0x8 - -#define UTICOM_MCR_CTS 0x1 -#define UTICOM_MCR_DSR 0x2 -#define UTICOM_MCR_CD 0x4 -#define UTICOM_MCR_RI 0x8 - -/* Structures */ -struct uticom_fw_header { - uint16_t length; - uint8_t checkSum; -} __attribute__((packed)); - -struct uticom_buf { - unsigned int buf_size; - char *buf_buf; - char *buf_get; - char *buf_put; -}; - -struct uticom_softc { - struct ucom_softc sc_ucom; - - int sc_iface_number; /* interface number */ - - usbd_interface_handle sc_intr_iface; /* interrupt interface */ - int sc_intr_number; /* interrupt number */ - usbd_pipe_handle sc_intr_pipe; /* interrupt pipe */ - u_char *sc_intr_buf; /* interrupt buffer */ - int sc_isize; - - u_char sc_dtr; /* current DTR state */ - u_char sc_rts; /* current RTS state */ - u_char sc_status; - - u_char sc_lsr; /* Local status register */ - u_char sc_msr; /* uticom status register */ -}; - -static usbd_status uticom_reset(struct uticom_softc *); -static usbd_status uticom_set_crtscts(struct uticom_softc *); -static void uticom_intr(usbd_xfer_handle, usbd_private_handle, usbd_status); - -static void uticom_set(void *, int, int, int); -static void uticom_dtr(struct uticom_softc *, int); -static void uticom_rts(struct uticom_softc *, int); -static void uticom_break(struct uticom_softc *, int); -static void uticom_get_status(void *, int, u_char *, u_char *); -#if 0 /* TODO */ -static int uticom_ioctl(void *, int, u_long, caddr_t, int, usb_proc_ptr); -#endif -static int uticom_param(void *, int, struct termios *); -static int uticom_open(void *, int); -static void uticom_close(void *, int); - -static int uticom_download_fw(struct uticom_softc *sc, unsigned int pipeno, - usbd_device_handle dev, unsigned char *firmware, - unsigned int firmware_size); - -struct ucom_callback uticom_callback = { - uticom_get_status, - uticom_set, - uticom_param, - NULL, /* uticom_ioctl, TODO */ - uticom_open, - uticom_close, - NULL, - NULL -}; - -static const struct usb_devno uticom_devs [] = { - { USB_DEVICE(0x0451, 0x3410) } /* TI TUSB3410 chip */ -}; - -static device_probe_t uticom_match; -static device_attach_t uticom_attach; -static device_detach_t uticom_detach; - -static device_method_t uticom_methods[] = { - DEVMETHOD(device_probe, uticom_match), - DEVMETHOD(device_attach, uticom_attach), - DEVMETHOD(device_detach, uticom_detach), - DEVMETHOD_END -}; - -static driver_t uticom_driver = { - "ucom", - uticom_methods, - sizeof (struct uticom_softc) -}; - -DRIVER_MODULE(uticom, uhub, uticom_driver, ucom_devclass, usbd_driver_load, NULL); -MODULE_DEPEND(uticom, usb, 1, 1, 1); -MODULE_DEPEND(uticom, ucom, UCOM_MINVER, UCOM_PREFVER, UCOM_MAXVER); -MODULE_VERSION(uticom, 1); - -/* Sticky DSR level sysctl handling. */ -static int uticomstickdsr = 0; -static int -sysctl_hw_usb_uticom_stickdsr(SYSCTL_HANDLER_ARGS) -{ - int err, val; - - val = uticomstickdsr; - err = sysctl_handle_int(oidp, &val, 0, req); - if (err != 0 || req->newptr == NULL) - return (err); - if (val == 0 || val == 1) - uticomstickdsr = val; - else - err = EINVAL; - - return (err); -} -SYSCTL_PROC(_hw_usb_uticom, OID_AUTO, stickdsr, CTLTYPE_INT | CTLFLAG_RW, - 0, sizeof(int), sysctl_hw_usb_uticom_stickdsr, - "I", "uticom sticky dsr level"); - -static int -uticom_match(device_t self) -{ - struct usb_attach_arg *uaa = device_get_ivars(self); - - if (uaa->iface != NULL) - return (UMATCH_NONE); - - return (usb_lookup(uticom_devs, uaa->vendor, uaa->product) != NULL ? - UMATCH_VENDOR_PRODUCT : UMATCH_NONE); -} - -static int -uticom_attach(device_t self) -{ - struct uticom_softc *sc = device_get_softc(self); - struct usb_attach_arg *uaa = device_get_ivars(self); - - usbd_device_handle dev = uaa->device; - struct ucom_softc *ucom; - usb_config_descriptor_t *cdesc; - usb_interface_descriptor_t *id; - usb_endpoint_descriptor_t *ed; - usbd_status err; - int status, i; - usb_device_descriptor_t *dd; - - ucom = &sc->sc_ucom; - bzero(sc, sizeof (struct uticom_softc)); - ucom->sc_dev = self; - ucom->sc_udev = dev; - ucom->sc_iface = uaa->iface; - - /* Initialize endpoints. */ - ucom->sc_bulkin_no = ucom->sc_bulkout_no = -1; - sc->sc_intr_number = -1; - sc->sc_intr_pipe = NULL; - - dd = usbd_get_device_descriptor(dev); - DPRINTF(("%s: uticom_attach: num of configurations %d\n", - device_get_nameunit(self), dd->bNumConfigurations)); - - /* The device without firmware has single configuration with single - * bulk out interface. */ - if (dd->bNumConfigurations > 1) - goto fwload_done; - - /* Loading firmware. */ - DPRINTF(("%s: uticom_attach: starting loading firmware\n", - device_get_nameunit(self))); - - err = usbd_set_config_index(dev, UTICOM_CONFIG_INDEX, 1); - if (err) { - device_printf(self, "failed to set configuration: %s\n", - usbd_errstr(err)); - ucom->sc_dying = 1; - return ENXIO; - } - - /* Get the config descriptor. */ - cdesc = usbd_get_config_descriptor(ucom->sc_udev); - - if (cdesc == NULL) { - device_printf(self, "failed to get configuration descriptor\n"); - ucom->sc_dying = 1; - return ENXIO; - } - - err = usbd_device2interface_handle(dev, UTICOM_IFACE_INDEX, - &ucom->sc_iface); - if (err) { - device_printf(self, "failed to get interface: %s\n", - usbd_errstr(err)); - ucom->sc_dying = 1; - return ENXIO; - } - - /* Find the bulk out interface used to upload firmware. */ - id = usbd_get_interface_descriptor(ucom->sc_iface); - sc->sc_iface_number = id->bInterfaceNumber; - - for (i = 0; i < id->bNumEndpoints; i++) { - ed = usbd_interface2endpoint_descriptor(ucom->sc_iface, i); - if (ed == NULL) { - device_printf(self, - "no endpoint descriptor for %d\n", i); - ucom->sc_dying = 1; - return ENXIO; - } - - if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT && - UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) { - ucom->sc_bulkout_no = ed->bEndpointAddress; - DPRINTF(("%s: uticom_attach: data bulk out num: %d\n", - device_get_nameunit(self), - ed->bEndpointAddress)); - } - - if (ucom->sc_bulkout_no == -1) { - device_printf(self, "could not find data bulk out\n"); - ucom->sc_dying = 1; - return ENXIO; - } - } - - status = uticom_download_fw(sc, ucom->sc_bulkout_no, dev, - uticom_fw_3410, sizeof(uticom_fw_3410)); - - if (status) { - device_printf(self, "firmware download failed\n"); - ucom->sc_dying = 1; - return ENXIO; - } else { - device_printf(self, "firmware download succeeded\n"); - } - - status = usbd_reload_device_desc(dev); - if (status) { - device_printf(self, "error reloading device descriptor\n"); - ucom->sc_dying = 1; - return ENXIO; - } - -fwload_done: - dd = usbd_get_device_descriptor(dev); - DPRINTF(("%s: uticom_attach: num of configurations %d\n", - device_get_nameunit(self), dd->bNumConfigurations)); - - err = usbd_set_config_index(dev, UTICOM_ACTIVE_INDEX, 1); - if (err) { - device_printf(self, "failed to set configuration: %s\n", - usbd_errstr(err)); - ucom->sc_dying = 1; - return ENXIO; - } - - /* Get the config descriptor. */ - cdesc = usbd_get_config_descriptor(ucom->sc_udev); - if (cdesc == NULL) { - device_printf(self, "failed to get configuration descriptor\n"); - ucom->sc_dying = 1; - return ENXIO; - } - - /* Get the interface (XXX: multiport chips are not supported yet). */ - err = usbd_device2interface_handle(dev, UTICOM_IFACE_INDEX, - &ucom->sc_iface); - if (err) { - device_printf(self, "failed to get interface: %s\n", - usbd_errstr(err)); - ucom->sc_dying = 1; - return ENXIO; - } - - /* Find the interrupt endpoints. */ - id = usbd_get_interface_descriptor(ucom->sc_iface); - sc->sc_iface_number = id->bInterfaceNumber; - - for (i = 0; i < id->bNumEndpoints; i++) { - ed = usbd_interface2endpoint_descriptor(ucom->sc_iface, i); - if (ed == NULL) { - device_printf(self, - "no endpoint descriptor for %d\n", i); - ucom->sc_dying = 1; - return ENXIO; - } - - if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && - UE_GET_XFERTYPE(ed->bmAttributes) == UE_INTERRUPT) { - sc->sc_intr_number = ed->bEndpointAddress; - sc->sc_isize = UGETW(ed->wMaxPacketSize); - } - } - - if (sc->sc_intr_number == -1) { - device_printf(self, "could not find interrupt in\n"); - ucom->sc_dying = 1; - return ENXIO; - } - - /* Keep interface for interrupt. */ - sc->sc_intr_iface = ucom->sc_iface; - - /* Find the bulk{in,out} endpoints. */ - id = usbd_get_interface_descriptor(ucom->sc_iface); - sc->sc_iface_number = id->bInterfaceNumber; - - for (i = 0; i < id->bNumEndpoints; i++) { - ed = usbd_interface2endpoint_descriptor(ucom->sc_iface, i); - if (ed == NULL) { - device_printf(self, - "no endpoint descriptor for %d\n", i); - ucom->sc_dying = 1; - return ENXIO; - } - - if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && - UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) { - ucom->sc_bulkin_no = ed->bEndpointAddress; - } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT && - UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) { - ucom->sc_bulkout_no = ed->bEndpointAddress; - } - } - - if (ucom->sc_bulkin_no == -1) { - device_printf(self, "could not find data bulk in\n"); - ucom->sc_dying = 1; - return ENXIO; - } - - if (ucom->sc_bulkout_no == -1) { - device_printf(self, "could not find data bulk out\n"); - ucom->sc_dying = 1; - return ENXIO; - } - - sc->sc_dtr = sc->sc_rts = -1; - ucom->sc_parent = sc; - ucom->sc_portno = UCOM_UNK_PORTNO; - ucom->sc_ibufsize = UTICOM_IBUFSZ; - ucom->sc_obufsize = UTICOM_OBUFSZ; - ucom->sc_ibufsizepad = UTICOM_IBUFSZ; - ucom->sc_opkthdrlen = 0; - ucom->sc_callback = &uticom_callback; - - err = uticom_reset(sc); - if (err) { - device_printf(self, "reset failed: %s\n", usbd_errstr(err)); - ucom->sc_dying = 1; - return ENXIO; - } - - DPRINTF(("%s: uticom_attach: in = 0x%x, out = 0x%x, intr = 0x%x\n", - device_get_nameunit(self), ucom->sc_bulkin_no, - ucom->sc_bulkout_no, sc->sc_intr_number)); - - ucom_attach(&sc->sc_ucom); - return 0; -} - -static int -uticom_detach(device_t self) -{ - struct uticom_softc *sc = device_get_softc(self); - - DPRINTF(("%s: uticom_detach: sc = %p\n", - device_get_nameunit(self), sc)); - - if (sc->sc_intr_pipe != NULL) { - usbd_abort_pipe(sc->sc_intr_pipe); - usbd_close_pipe(sc->sc_intr_pipe); - kfree(sc->sc_intr_buf, M_USBDEV); - sc->sc_intr_pipe = NULL; - } - - sc->sc_ucom.sc_dying = 1; - return (ucom_detach(&sc->sc_ucom)); -} - -static usbd_status -uticom_reset(struct uticom_softc *sc) -{ - usb_device_request_t req; - usbd_status err; - device_t dev = sc->sc_ucom.sc_dev; - - req.bmRequestType = UT_WRITE_VENDOR_DEVICE; - req.bRequest = UTICOM_RQ_SON; - USETW(req.wValue, 0); - USETW(req.wIndex, 0); - USETW(req.wLength, 0); - - err = usbd_do_request(sc->sc_ucom.sc_udev, &req, NULL); - if (err){ - device_printf(dev, "uticom_reset: %s\n", usbd_errstr(err)); - return (EIO); - } - - DPRINTF(("%s: uticom_reset: done\n", device_get_nameunit(dev))); - return (0); -} - -static void -uticom_set(void *addr, int portno, int reg, int onoff) -{ - struct uticom_softc *sc = addr; - - switch (reg) { - case UCOM_SET_DTR: - uticom_dtr(sc, onoff); - break; - case UCOM_SET_RTS: - uticom_rts(sc, onoff); - break; - case UCOM_SET_BREAK: - uticom_break(sc, onoff); - break; - default: - break; - } -} - -static void -uticom_dtr(struct uticom_softc *sc, int onoff) -{ - usb_device_request_t req; - usbd_status err; - device_t dev = sc->sc_ucom.sc_dev; - - DPRINTF(("%s: uticom_dtr: onoff = %d\n", device_get_nameunit(dev), - onoff)); - - if (sc->sc_dtr == onoff) - return; - sc->sc_dtr = onoff; - - req.bmRequestType = UT_WRITE_VENDOR_DEVICE; - req.bRequest = UTICOM_RQ_DTR; - USETW(req.wValue, sc->sc_dtr ? UCDC_LINE_DTR : 0); - USETW(req.wIndex, 0); - USETW(req.wLength, 0); - - err = usbd_do_request(sc->sc_ucom.sc_udev, &req, NULL); - if (err) - device_printf(dev, "uticom_dtr: %s\n", usbd_errstr(err)); -} - -static void -uticom_rts(struct uticom_softc *sc, int onoff) -{ - usb_device_request_t req; - usbd_status err; - device_t dev = sc->sc_ucom.sc_dev; - - DPRINTF(("%s: uticom_rts: onoff = %d\n", device_get_nameunit(dev), - onoff)); - - if (sc->sc_rts == onoff) - return; - sc->sc_rts = onoff; - req.bmRequestType = UT_WRITE_VENDOR_DEVICE; - req.bRequest = UTICOM_RQ_RTS; - USETW(req.wValue, sc->sc_rts ? UCDC_LINE_RTS : 0); - USETW(req.wIndex, 0); - USETW(req.wLength, 0); - - err = usbd_do_request(sc->sc_ucom.sc_udev, &req, NULL); - if (err) - device_printf(dev, "uticom_rts: %s\n", usbd_errstr(err)); -} - -static void -uticom_break(struct uticom_softc *sc, int onoff) -{ - usb_device_request_t req; - usbd_status err; - device_t dev = sc->sc_ucom.sc_dev; - - DPRINTF(("%s: uticom_break: onoff = %d\n", device_get_nameunit(dev), - onoff)); - - req.bmRequestType = UT_WRITE_VENDOR_DEVICE; - req.bRequest = UTICOM_RQ_BREAK; - USETW(req.wValue, onoff ? 1 : 0); - USETW(req.wIndex, 0); - USETW(req.wLength, 0); - - err = usbd_do_request(sc->sc_ucom.sc_udev, &req, NULL); - if (err) - device_printf(dev, "uticom_break: %s\n", usbd_errstr(err)); -} - -static usbd_status -uticom_set_crtscts(struct uticom_softc *sc) -{ - usb_device_request_t req; - usbd_status err; - device_t dev = sc->sc_ucom.sc_dev; - - DPRINTF(("%s: uticom_set_crtscts: on\n", device_get_nameunit(dev))); - - req.bmRequestType = UT_WRITE_VENDOR_DEVICE; - req.bRequest = UTICOM_RQ_CRTSCTS; - USETW(req.wValue, 1); - USETW(req.wIndex, 0); - USETW(req.wLength, 0); - - err = usbd_do_request(sc->sc_ucom.sc_udev, &req, NULL); - if (err) { - device_printf(dev, "uticom_set_crtscts: %s\n", - usbd_errstr(err)); - return (err); - } - - return (USBD_NORMAL_COMPLETION); -} - -static int -uticom_param(void *vsc, int portno, struct termios *t) -{ - struct uticom_softc *sc = (struct uticom_softc *)vsc; - device_t dev = sc->sc_ucom.sc_dev; - usb_device_request_t req; - usbd_status err; - uint8_t data; - - DPRINTF(("%s: uticom_param\n", device_get_nameunit(dev))); - - switch (t->c_ospeed) { - case 1200: - case 2400: - case 4800: - case 7200: - case 9600: - case 14400: - case 19200: - case 38400: - case 57600: - case 115200: - case 230400: - case 460800: - case 921600: - req.bmRequestType = UT_WRITE_VENDOR_DEVICE; - req.bRequest = UTICOM_RQ_BAUD; - USETW(req.wValue, (UTICOM_BRATE_REF / t->c_ospeed)); - USETW(req.wIndex, 0); - USETW(req.wLength, 0); - - err = usbd_do_request(sc->sc_ucom.sc_udev, &req, 0); - if (err) { - device_printf(dev, "uticom_param: %s\n", - usbd_errstr(err)); - return (EIO); - } - break; - default: - device_printf(dev, "uticom_param: unsupported baud rate %d\n", - t->c_ospeed); - return (EINVAL); - } - - switch (ISSET(t->c_cflag, CSIZE)) { - case CS5: - data = UTICOM_SET_DATA_BITS(5); - break; - case CS6: - data = UTICOM_SET_DATA_BITS(6); - break; - case CS7: - data = UTICOM_SET_DATA_BITS(7); - break; - case CS8: - data = UTICOM_SET_DATA_BITS(8); - break; - default: - return (EIO); - } - - if (ISSET(t->c_cflag, CSTOPB)) - data |= UTICOM_STOP_BITS_2; - else - data |= UTICOM_STOP_BITS_1; - - if (ISSET(t->c_cflag, PARENB)) { - if (ISSET(t->c_cflag, PARODD)) - data |= UTICOM_PARITY_ODD; - else - data |= UTICOM_PARITY_EVEN; - } else - data |= UTICOM_PARITY_NONE; - - req.bmRequestType = UT_WRITE_VENDOR_DEVICE; - req.bRequest = UTICOM_RQ_LCR; - USETW(req.wIndex, 0); - USETW(req.wLength, 0); - USETW(req.wValue, data); - - err = usbd_do_request(sc->sc_ucom.sc_udev, &req, NULL); - if (err) { - device_printf(dev, "uticom_param: %s\n", usbd_errstr(err)); - return (err); - } - - if (ISSET(t->c_cflag, CRTSCTS)) { - err = uticom_set_crtscts(sc); - if (err) - return (EIO); - } - - return (0); -} - -static int -uticom_open(void *addr, int portno) -{ - struct uticom_softc *sc = addr; - device_t dev = sc->sc_ucom.sc_dev; - usbd_status err; - - if (sc->sc_ucom.sc_dying) - return (ENXIO); - - DPRINTF(("%s: uticom_open\n", device_get_nameunit(dev))); - - sc->sc_status = 0; /* clear status bit */ - - if (sc->sc_intr_number != -1 && sc->sc_intr_pipe == NULL) { - sc->sc_intr_buf = kmalloc(sc->sc_isize, M_USBDEV, M_WAITOK); - err = usbd_open_pipe_intr(sc->sc_intr_iface, sc->sc_intr_number, - USBD_SHORT_XFER_OK, &sc->sc_intr_pipe, - sc, sc->sc_intr_buf, sc->sc_isize, - uticom_intr, UTICOM_INTR_INTERVAL); - if (err) { - device_printf(dev, "cannot open interrupt pipe " - "(addr %d)\n", sc->sc_intr_number); - return (EIO); - } - } - - DPRINTF(("%s: uticom_open: port opened\n", device_get_nameunit(dev))); - return (0); -} - -static void -uticom_close(void *addr, int portno) -{ - struct uticom_softc *sc = addr; - device_t dev = sc->sc_ucom.sc_dev; - usb_device_request_t req; - usbd_status err; - - if (sc->sc_ucom.sc_dying) - return; - - req.bmRequestType = UT_WRITE_VENDOR_DEVICE; - req.bRequest = UTICOM_RQ_SON; - USETW(req.wValue, 0); - USETW(req.wIndex, 0); - USETW(req.wLength, 0); - - /* Try to reset UART part of chip. */ - err = usbd_do_request(sc->sc_ucom.sc_udev, &req, NULL); - if (err) { - device_printf(dev, "uticom_close: %s\n", usbd_errstr(err)); - return; - } - - DPRINTF(("%s: uticom_close: close\n", - device_get_nameunit(sc->sc_ucom.sc_dev))); - - if (sc->sc_intr_pipe != NULL) { - err = usbd_abort_pipe(sc->sc_intr_pipe); - if (err) - device_printf(dev, "abort interrupt pipe failed: %s\n", - usbd_errstr(err)); - err = usbd_close_pipe(sc->sc_intr_pipe); - if (err) - device_printf(dev, "close interrupt pipe failed: %s\n", - usbd_errstr(err)); - kfree(sc->sc_intr_buf, M_USBDEV); - sc->sc_intr_pipe = NULL; - } -} - -static void -uticom_intr(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status) -{ - struct uticom_softc *sc = priv; - u_char *buf = sc->sc_intr_buf; - - if (sc->sc_ucom.sc_dying) - return; - - if (status != USBD_NORMAL_COMPLETION) { - if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) { - DPRINTF(("%s: uticom_intr: int status: %s\n", - device_get_nameunit(sc->sc_ucom.sc_dev), - usbd_errstr(status))); - return; - } - - DPRINTF(("%s: uticom_intr: abnormal status: %s\n", - device_get_nameunit(sc->sc_ucom.sc_dev), - usbd_errstr(status))); - usbd_clear_endpoint_stall_async(sc->sc_intr_pipe); - return; - } - - if (!xfer->actlen) - return; - - DPRINTF(("%s: xfer_length = %d\n", - device_get_nameunit(sc->sc_ucom.sc_dev), xfer->actlen)); - - sc->sc_lsr = sc->sc_msr = 0; - - if (buf[0] == 0) { - /* msr registers */ - if (buf[1] & UTICOM_MCR_CTS) - sc->sc_msr |= UMSR_CTS; - if (buf[1] & UTICOM_MCR_DSR) - sc->sc_msr |= UMSR_DSR; - if (buf[1] & UTICOM_MCR_CD) - sc->sc_msr |= UMSR_DCD; - if (buf[1] & UTICOM_MCR_RI) - sc->sc_msr |= UMSR_RI; - } else { - /* lsr registers */ - if (buf[0] & UTICOM_LCR_OVR) - sc->sc_lsr |= ULSR_OE; - if (buf[0] & UTICOM_LCR_PTE) - sc->sc_lsr |= ULSR_PE; - if (buf[0] & UTICOM_LCR_FRE) - sc->sc_lsr |= ULSR_FE; - if (buf[0] & UTICOM_LCR_BRK) - sc->sc_lsr |= ULSR_BI; - } - - if (uticomstickdsr) - sc->sc_msr |= UMSR_DSR; - - ucom_status_change(&sc->sc_ucom); -} - -static void -uticom_get_status(void *addr, int portno, u_char *lsr, u_char *msr) -{ -#if 0 /* TODO */ - struct uticom_softc *sc = addr; - - DPRINTF(("uticom_get_status:\n")); - - if (lsr != NULL) - *lsr = sc->sc_lsr; - if (msr != NULL) - *msr = sc->sc_msr; -#endif - return; -} - -#if 0 /* TODO */ -static int -uticom_ioctl(void *addr, int portno, u_long cmd, caddr_t data, int flag, - usb_proc_ptr p) -{ - struct uticom_softc *sc = addr; - int error = 0; - - if (sc->sc_ucom.sc_dying) - return (EIO); - - DPRINTF(("uticom_ioctl: cmd = 0x%08lx\n", cmd)); - - switch (cmd) { - case TIOCNOTTY: - case TIOCMGET: - case TIOCMSET: - case USB_GET_CM_OVER_DATA: - case USB_SET_CM_OVER_DATA: - break; - - default: - DPRINTF(("uticom_ioctl: unknown\n")); - error = ENOTTY; - break; - } - - return (error); -} -#endif - -static int uticom_download_fw(struct uticom_softc *sc, unsigned int pipeno, - usbd_device_handle dev, unsigned char *firmware, - unsigned int firmware_size) -{ - int buffer_size; - int pos; - uint8_t cs = 0; - uint8_t *buffer; - usbd_status err = 0; - usbd_xfer_handle oxfer = 0; - u_char *obuf; - usbd_pipe_handle pipe; - struct uticom_fw_header *header; - - buffer_size = UTICOM_FW_BUFSZ + sizeof(struct uticom_fw_header); - buffer = kmalloc(buffer_size, M_USBDEV, M_WAITOK); - - memcpy(buffer, firmware, firmware_size); - memset(buffer + firmware_size, 0xff, buffer_size - firmware_size); - - for (pos = sizeof(struct uticom_fw_header); pos < buffer_size; pos++) - cs = (uint8_t)(cs + buffer[pos]); - - header = (struct uticom_fw_header*)buffer; - header->length = (uint16_t)(buffer_size - - sizeof(struct uticom_fw_header)); - header->checkSum = cs; - - DPRINTF(("%s: downloading firmware ...\n", - device_get_nameunit(sc->sc_ucom.sc_dev))); - - err = usbd_open_pipe(sc->sc_ucom.sc_iface, pipeno, USBD_EXCLUSIVE_USE, - &pipe); - if (err) { - device_printf(sc->sc_ucom.sc_dev, "open bulk out error " - "(addr %d): %s\n", pipeno, usbd_errstr(err)); - err = EIO; - goto finish; - } - - oxfer = usbd_alloc_xfer(dev); - if (oxfer == NULL) { - err = ENOMEM; - goto finish; - } - - obuf = usbd_alloc_buffer(oxfer, buffer_size); - if (obuf == NULL) { - err = ENOMEM; - goto finish; - } - - memcpy(obuf, buffer, buffer_size); - - usbd_setup_xfer(oxfer, pipe, (usbd_private_handle)sc, obuf, buffer_size, - USBD_NO_COPY | USBD_SYNCHRONOUS, USBD_NO_TIMEOUT, 0); - err = usbd_sync_transfer(oxfer); - - if (err != USBD_NORMAL_COMPLETION) - device_printf(sc->sc_ucom.sc_dev, "uticom_download_fw: " - "error: %s\n", usbd_errstr(err)); - -finish: - usbd_free_buffer(oxfer); - usbd_free_xfer(oxfer); - oxfer = NULL; - usbd_abort_pipe(pipe); - usbd_close_pipe(pipe); - kfree(buffer, M_USBDEV); - - return err; -} diff --git a/sys/dev/usbmisc/uticom/uticom_fw3410.h b/sys/dev/usbmisc/uticom/uticom_fw3410.h deleted file mode 100644 index cd7d966955..0000000000 --- a/sys/dev/usbmisc/uticom/uticom_fw3410.h +++ /dev/null @@ -1,303 +0,0 @@ -/* - * TI 3410 USB Serial Driver Firmware Header - * - * Copyright (c) 2005 Dmitry Komissaroff . - * - * 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. - * - * $DragonFly: src/sys/dev/usbmisc/uticom/uticom_fw3410.h,v 1.1 2007/11/07 08:31:08 hasso Exp $ - */ - -#ifndef _UTICOM_FW3410_H_ -#define _UTICOM_FW3410_H_ - -static unsigned char uticom_fw_3410[] = { -0x0d, 0xce, /* firmware image length excluding header, little endian */ -0x00, -0x02,0x10,0x1c,0x02,0x00,0x99,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x5e,0x12,0x01, -0x6b,0x80,0xfe,0x90,0xff,0x4a,0xe4,0xf0,0x22,0x90,0xff,0x52,0xe0,0xfa,0x43,0x02, -0x80,0x90,0xff,0x52,0xea,0xf0,0x30,0x00,0x03,0x02,0x01,0xb7,0x22,0x90,0xff,0x5a, -0xe4,0xf0,0x22,0x90,0xff,0x0a,0xe4,0xf0,0x22,0x90,0xff,0x12,0xe4,0xf0,0x22,0x90, -0xff,0x1a,0xe4,0xf0,0x22,0x90,0xff,0xfe,0x74,0x20,0xf0,0x22,0x90,0xff,0xfe,0x74, -0x40,0xf0,0x22,0x12,0x08,0xa1,0x90,0xff,0xfe,0x74,0x80,0xf0,0x22,0x22,0xc0,0xe0, -0xc0,0xf0,0xc0,0x82,0xc0,0x83,0xc0,0x02,0xc0,0x03,0xc0,0x04,0xc0,0x05,0xc0,0x06, -0xc0,0x07,0xc0,0x00,0xc0,0x01,0xc0,0xd0,0x75,0xd0,0x00,0x12,0x0a,0x13,0xd0,0xd0, -0xd0,0x01,0xd0,0x00,0xd0,0x07,0xd0,0x06,0xd0,0x05,0xd0,0x04,0xd0,0x03,0xd0,0x02, -0xd0,0x83,0xd0,0x82,0xd0,0xf0,0xd0,0xe0,0x32,0xc0,0xe0,0xc0,0xf0,0xc0,0x82,0xc0, -0x83,0xc0,0xd0,0xc0,0x00,0xc0,0x01,0xc0,0x02,0xc0,0x03,0xc0,0x04,0xc0,0x05,0xc0, -0x06,0xc0,0x07,0x90,0xff,0x92,0xe0,0xf0,0x90,0x00,0xd0,0xc0,0x82,0xc0,0x83,0x90, -0x00,0xeb,0x54,0x7e,0xf5,0xf0,0x04,0x93,0xc0,0xe0,0xe5,0xf0,0x93,0xc0,0xe0,0x22, -0xd0,0x07,0xd0,0x06,0xd0,0x05,0xd0,0x04,0xd0,0x03,0xd0,0x02,0xd0,0x01,0xd0,0x00, -0xd0,0xd0,0xd0,0x83,0xd0,0x82,0xd0,0xf0,0xd0,0xe0,0x32,0x00,0x5d,0x00,0x5d,0x00, -0x5d,0x00,0x5d,0x00,0x5d,0x00,0x5d,0x00,0x5d,0x00,0x5d,0x00,0x5d,0x00,0x33,0x00, -0x39,0x00,0x3f,0x00,0x5d,0x00,0x5d,0x00,0x5d,0x00,0x5d,0x00,0x5d,0x00,0x13,0x00, -0x19,0x00,0x2d,0x00,0x5d,0x00,0x5d,0x00,0x5d,0x00,0x5d,0x00,0x5d,0x07,0xe4,0x00, -0x5d,0x00,0x5d,0x00,0x45,0x00,0x4c,0x00,0x53,0x00,0x5d,0x00,0x5d,0x00,0x5d,0x08, -0x65,0x08,0x83,0x00,0x5d,0x00,0x5d,0x00,0x5d,0x00,0x5d,0x0f,0x11,0x0f,0x7f,0x00, -0x5d,0x00,0x5d,0x00,0x5d,0x00,0x5d,0x00,0x5d,0x00,0x5d,0x00,0x5d,0x00,0x5d,0x00, -0x5d,0x00,0x5d,0x00,0x5d,0x00,0x5d,0x00,0x5d,0x00,0x5d,0x00,0x5d,0x00,0x5d,0x00, -0x5d,0x00,0x5d,0x00,0x5d,0x00,0x5d,0x00,0x5d,0x00,0x5d,0x90,0xff,0x93,0x74,0x2a, -0xf0,0x7a,0x93,0x7b,0xff,0x90,0xff,0x93,0xe0,0xfc,0x43,0x04,0x01,0x8a,0x82,0x8b, -0x83,0xec,0xf0,0x90,0xff,0xe0,0xe4,0xf0,0x90,0xff,0xe4,0xf0,0x90,0xff,0xfd,0xf0, -0x90,0xff,0xab,0xf0,0x12,0x0b,0xee,0x12,0x0a,0x13,0x90,0xff,0xfc,0x74,0x80,0xf0, -0xd2,0xaf,0x7a,0x93,0x7b,0xff,0x90,0xff,0x93,0xe0,0xfc,0x43,0x04,0x01,0x8a,0x82, -0x8b,0x83,0xec,0xf0,0x80,0xec,0x22,0x75,0x1b,0x00,0xc2,0x00,0x7b,0x00,0xbb,0x41, -0x00,0x50,0x0a,0x8b,0x82,0x75,0x83,0xfe,0xe4,0xf0,0x0b,0x80,0xf1,0x78,0x21,0xe6, -0x08,0x46,0x60,0x53,0x78,0x21,0xc3,0x74,0x40,0x96,0xe4,0x08,0x96,0x50,0x12,0x75, -0x1b,0x40,0x78,0x21,0xe6,0x24,0xc0,0xf6,0x08,0xe6,0x34,0xff,0xf6,0xd2,0x00,0x80, -0x0a,0x78,0x21,0x86,0x1b,0x78,0x21,0xe4,0xf6,0x08,0xf6,0x7b,0x00,0xc3,0xeb,0x95, -0x1b,0x50,0x24,0x8b,0x04,0x7d,0xfe,0x78,0x23,0x86,0x06,0x08,0x86,0x07,0x8e,0x82, -0x8f,0x83,0xe0,0xfa,0x78,0x23,0x74,0x01,0x2e,0xf6,0xe4,0x3f,0x08,0xf6,0x8c,0x82, -0x8d,0x83,0xea,0xf0,0x0b,0x80,0xd6,0x90,0xff,0x52,0xe5,0x1b,0xf0,0x22,0xaa,0x82, -0xab,0x83,0xac,0xf0,0x7d,0x40,0x7e,0x00,0x78,0x23,0xa6,0x02,0x08,0xa6,0x03,0xc3, -0xe5,0x08,0x94,0x40,0xe5,0x09,0x64,0x80,0x94,0x80,0x50,0x04,0xad,0x08,0xae,0x09, -0x78,0x21,0xa6,0x05,0x08,0xa6,0x06,0x90,0xff,0x52,0xe4,0xf0,0x02,0x01,0xb7,0x7a, -0x80,0x7b,0xff,0x90,0xff,0x80,0xe0,0xfc,0x43,0x04,0x08,0x8a,0x82,0x8b,0x83,0xec, -0xf0,0x7a,0x82,0x7b,0xff,0x90,0xff,0x82,0xe0,0xfc,0x43,0x04,0x08,0x8a,0x82,0x8b, -0x83,0xec,0xf0,0x22,0x75,0x1b,0x00,0xc2,0x01,0x78,0x27,0xe6,0x08,0x46,0x60,0x57, -0x78,0x27,0xc3,0x74,0x08,0x96,0xe4,0x08,0x96,0x50,0x12,0x75,0x1b,0x08,0x78,0x27, -0xe6,0x24,0xf8,0xf6,0x08,0xe6,0x34,0xff,0xf6,0xd2,0x01,0x80,0x0a,0x78,0x27,0x86, -0x1b,0x78,0x27,0xe4,0xf6,0x08,0xf6,0x7b,0x00,0xc3,0xeb,0x95,0x1b,0x50,0x28,0xeb, -0x24,0xf8,0xfc,0xe4,0x34,0xfe,0xfd,0x78,0x2b,0x86,0x06,0x08,0x86,0x07,0x8e,0x82, -0x8f,0x83,0xe0,0xfa,0x78,0x2b,0x74,0x01,0x2e,0xf6,0xe4,0x3f,0x08,0xf6,0x8c,0x82, -0x8d,0x83,0xea,0xf0,0x0b,0x80,0xd2,0x90,0xff,0x81,0xe5,0x1b,0xf0,0x22,0x85,0x82, -0x0c,0x85,0x83,0x0d,0x85,0xf0,0x0e,0x90,0xff,0x07,0xe0,0xfd,0x8d,0x06,0x7d,0x00, -0x90,0xff,0x06,0xe0,0xff,0x7a,0x00,0x4d,0xfb,0xea,0x4e,0xfa,0x78,0x2b,0xa6,0x0c, -0x08,0xa6,0x0d,0xc3,0xe5,0x0a,0x9b,0xe5,0x0b,0x64,0x80,0x8a,0xf0,0x63,0xf0,0x80, -0x95,0xf0,0x50,0x04,0xab,0x0a,0xaa,0x0b,0x78,0x27,0xa6,0x03,0x08,0xa6,0x02,0x90, -0xff,0x83,0xe4,0xf0,0x02,0x02,0x84,0xc2,0x01,0x78,0x27,0xe4,0xf6,0x08,0xf6,0x90, -0xff,0x81,0xe4,0xf0,0x22,0x7a,0x82,0x7b,0xff,0x90,0xff,0x82,0xe0,0xfc,0x43,0x04, -0x08,0x8a,0x82,0x8b,0x83,0xec,0xf0,0x22,0x90,0xff,0x04,0xe0,0xfa,0x53,0x02,0x0f, -0xba,0x00,0x03,0x02,0x03,0x37,0x1a,0xba,0x03,0x00,0x50,0x5a,0x90,0xff,0x04,0xe0, -0xfb,0x53,0x03,0x80,0xbb,0x80,0x27,0xea,0x75,0xf0,0x08,0xa4,0xfb,0xac,0xf0,0xeb, -0x24,0x48,0xfd,0xec,0x34,0xff,0xfe,0xeb,0x24,0x48,0xf5,0x82,0xec,0x34,0xff,0xf5, -0x83,0xe0,0xfb,0x53,0x03,0xd7,0x8d,0x82,0x8e,0x83,0xeb,0xf0,0x80,0x25,0xea,0x75, -0xf0,0x08,0xa4,0xfa,0xab,0xf0,0xea,0x24,0x08,0xfc,0xeb,0x34,0xff,0xfd,0xea,0x24, -0x08,0xf5,0x82,0xeb,0x34,0xff,0xf5,0x83,0xe0,0xfa,0x53,0x02,0xd7,0x8c,0x82,0x8d, -0x83,0xea,0xf0,0x12,0x03,0x37,0x7a,0x93,0x7b,0xff,0x90,0xff,0x93,0xe0,0xfc,0x43, -0x04,0x01,0x8a,0x82,0x8b,0x83,0xec,0xf0,0x22,0x75,0x0a,0x01,0xe4,0xf5,0x0b,0x90, -0x00,0x25,0x75,0xf0,0x00,0x02,0x02,0xee,0x75,0x0a,0x12,0xe4,0xf5,0x0b,0x90,0xf8, -0x00,0x75,0xf0,0x01,0x02,0x02,0xee,0x75,0x0a,0x27,0xe4,0xf5,0x0b,0x90,0xf8,0x12, -0x75,0xf0,0x01,0x02,0x02,0xee,0x7a,0x00,0x7b,0x00,0x90,0xff,0x02,0xe0,0xfc,0x14, -0xfd,0x90,0xff,0x02,0xf0,0xec,0x24,0xff,0x50,0x16,0xea,0x24,0x39,0xf5,0x82,0xeb, -0x34,0xf8,0xf5,0x83,0xe0,0xfc,0x7d,0x00,0xec,0x2a,0xfa,0xed,0x3b,0xfb,0x80,0xda, -0xea,0x24,0x39,0xfa,0xeb,0x34,0xf8,0xfb,0x8a,0x04,0x8b,0x05,0x7e,0x01,0x8a,0x82, -0x8b,0x83,0xe0,0xfa,0x8a,0x0a,0x75,0x0b,0x00,0x8c,0x82,0x8d,0x83,0x8e,0xf0,0x02, -0x02,0xee,0x90,0xf8,0xab,0x78,0x26,0xe6,0xf0,0x75,0x0a,0x01,0xe4,0xf5,0x0b,0x90, -0xf8,0xab,0x75,0xf0,0x01,0x02,0x02,0xee,0x90,0xf8,0x19,0xe0,0xfa,0x74,0x40,0x5a, -0xfb,0xbb,0x40,0x06,0x90,0xf8,0xab,0x74,0x01,0xf0,0x53,0x02,0x20,0xba,0x20,0x0d, -0x90,0xf8,0xab,0xe0,0xfa,0x43,0x02,0x02,0x90,0xf8,0xab,0xea,0xf0,0x75,0x0a,0x02, -0xe4,0xf5,0x0b,0x90,0xf8,0xab,0x75,0xf0,0x01,0x02,0x02,0xee,0x75,0x0a,0x02,0xe4, -0xf5,0x0b,0x90,0xf8,0xab,0x75,0xf0,0x01,0x02,0x02,0xee,0x90,0xff,0x04,0xe0,0xfa, -0x53,0x02,0x0f,0xba,0x00,0x49,0x90,0xff,0x04,0xe0,0xfb,0x53,0x03,0x80,0xbb,0x80, -0x0f,0x90,0xff,0x80,0xe0,0xfb,0x53,0x03,0x08,0x90,0xf8,0xab,0xeb,0xf0,0x80,0x0d, -0x90,0xff,0x82,0xe0,0xfb,0x53,0x03,0x08,0x90,0xf8,0xab,0xeb,0xf0,0x90,0xf8,0xab, -0xe0,0xfb,0xc4,0x23,0x54,0x1f,0xfb,0x90,0xf8,0xab,0xf0,0x90,0xff,0x83,0xe4,0xf0, -0x75,0x0a,0x02,0xe4,0xf5,0x0b,0x90,0xf8,0xab,0x75,0xf0,0x01,0x02,0x02,0xee,0x1a, -0xba,0x03,0x00,0x50,0x3c,0x90,0xff,0x04,0xe0,0xfb,0x30,0xe7,0x1b,0xea,0x75,0xf0, -0x08,0xa4,0x24,0x48,0xf5,0x82,0x74,0xff,0x35,0xf0,0xf5,0x83,0xe0,0xfb,0x53,0x03, -0x08,0x90,0xf8,0xab,0xeb,0xf0,0x80,0x19,0xea,0x75,0xf0,0x08,0xa4,0x24,0x08,0xf5, -0x82,0x74,0xff,0x35,0xf0,0xf5,0x83,0xe0,0xfa,0x53,0x02,0x08,0x90,0xf8,0xab,0xea, -0xf0,0x90,0xf8,0xab,0xe0,0xfa,0xc4,0x23,0x54,0x1f,0xfa,0x90,0xf8,0xab,0xf0,0x90, -0xff,0x83,0xe4,0xf0,0x75,0x0a,0x02,0xe4,0xf5,0x0b,0x90,0xf8,0xab,0x75,0xf0,0x01, -0x02,0x02,0xee,0x22,0x7a,0x82,0x7b,0xff,0x90,0xff,0x82,0xe0,0xfc,0x43,0x04,0x08, -0x8a,0x82,0x8b,0x83,0xec,0xf0,0x90,0xff,0x02,0xe0,0xfa,0xba,0x80,0x00,0x50,0x11, -0x7a,0xff,0x7b,0xff,0x90,0xff,0x02,0xe0,0xfc,0x8a,0x82,0x8b,0x83,0xf0,0x02,0x03, -0x37,0x02,0x02,0x5f,0x7a,0x82,0x7b,0xff,0x90,0xff,0x82,0xe0,0xfc,0x43,0x04,0x08, -0x8a,0x82,0x8b,0x83,0xec,0xf0,0x90,0xff,0x02,0xe0,0xfa,0x78,0x25,0xa6,0x02,0x02, -0x03,0x37,0x02,0x02,0x5f,0x7a,0x82,0x7b,0xff,0x90,0xff,0x82,0xe0,0xfc,0x43,0x04, -0x08,0x8a,0x82,0x8b,0x83,0xec,0xf0,0x90,0xff,0x02,0xe0,0xfa,0x60,0x03,0x02,0x06, -0x3c,0x90,0xff,0x04,0xe0,0xfa,0x53,0x02,0x0f,0xba,0x00,0x03,0x02,0x03,0x37,0x1a, -0xba,0x03,0x00,0x50,0x5a,0x90,0xff,0x04,0xe0,0xfb,0x30,0xe7,0x27,0xea,0x75,0xf0, -0x08,0xa4,0xfb,0xac,0xf0,0xeb,0x24,0x48,0xfd,0xec,0x34,0xff,0xfe,0xeb,0x24,0x48, -0xf5,0x82,0xec,0x34,0xff,0xf5,0x83,0xe0,0xfb,0x43,0x03,0x08,0x8d,0x82,0x8e,0x83, -0xeb,0xf0,0x80,0x25,0xea,0x75,0xf0,0x08,0xa4,0xfa,0xab,0xf0,0xea,0x24,0x08,0xfc, -0xeb,0x34,0xff,0xfd,0xea,0x24,0x08,0xf5,0x82,0xeb,0x34,0xff,0xf5,0x83,0xe0,0xfa, -0x43,0x02,0x08,0x8c,0x82,0x8d,0x83,0xea,0xf0,0x02,0x03,0x37,0x02,0x02,0x5f,0x22, -0x7a,0x82,0x7b,0xff,0x90,0xff,0x82,0xe0,0xfc,0x43,0x04,0x08,0x8a,0x82,0x8b,0x83, -0xec,0xf0,0x90,0xff,0x04,0xe0,0xfa,0x78,0x26,0xa6,0x02,0x02,0x03,0x37,0x90,0xff, -0xfe,0xe0,0xfa,0x53,0x02,0x01,0xba,0x00,0x03,0x02,0x02,0x5f,0x22,0x7a,0x82,0x7b, -0xff,0x90,0xff,0x82,0xe0,0xfc,0x43,0x04,0x08,0x8a,0x82,0x8b,0x83,0xec,0xf0,0x90, -0xff,0x00,0x12,0x0d,0x87,0xaa,0x82,0xab,0x83,0xba,0x00,0x05,0xbb,0x00,0x02,0x80, -0x03,0x02,0x02,0x5f,0x02,0x03,0x37,0x90,0xff,0x00,0x12,0x0c,0x3e,0xaa,0x82,0xab, -0x83,0x8a,0x04,0x8b,0x05,0xea,0x4b,0x60,0x1b,0x8c,0x82,0x8d,0x83,0xe0,0xfa,0x8a, -0x0a,0x75,0x0b,0x00,0x0c,0xbc,0x00,0x01,0x0d,0x7a,0x01,0x8c,0x82,0x8d,0x83,0x8a, -0xf0,0x02,0x02,0xee,0x02,0x02,0x5f,0x90,0xff,0x00,0xe0,0xfa,0x30,0xe7,0x03,0x02, -0x06,0x97,0x02,0x06,0x6d,0x7a,0x00,0xba,0x08,0x00,0x50,0x12,0xea,0x24,0x10,0xf8, -0x8a,0x82,0x74,0xff,0x24,0x00,0xf5,0x83,0xe0,0xfb,0xf6,0x0a,0x80,0xe9,0x7a,0x33, -0x7b,0x0b,0x7c,0x02,0x8a,0x82,0x8b,0x83,0x8c,0xf0,0x12,0x0f,0xf0,0xfd,0xa3,0xaa, -0x82,0xab,0x83,0x8c,0xf0,0x12,0x0f,0xf0,0xfe,0xa3,0xaa,0x82,0xab,0x83,0xbd,0xff, -0x05,0xbe,0xff,0x02,0x80,0x0a,0xaf,0x10,0xbf,0xc0,0x02,0x80,0x03,0xbf,0x40,0x0b, -0xea,0x24,0xfe,0xfa,0xeb,0x34,0xff,0xfb,0x02,0x07,0xad,0xed,0xb5,0x07,0x74,0xee, -0xb5,0x11,0x02,0x80,0x02,0x80,0x6c,0x7f,0xc0,0x75,0x0f,0x20,0x8a,0x18,0x8b,0x19, -0x8c,0x1a,0x7a,0x02,0xba,0x08,0x00,0x50,0x2b,0xea,0x24,0x10,0xf8,0x86,0x05,0x85, -0x18,0x82,0x85,0x19,0x83,0x85,0x1a,0xf0,0x12,0x0f,0xf0,0xfe,0xa3,0x85,0x82,0x18, -0x85,0x83,0x19,0xed,0xb5,0x06,0x04,0xe5,0x0f,0x42,0x07,0xe5,0x0f,0xc3,0x13,0xf5, -0x0f,0x0a,0x80,0xd0,0x85,0x18,0x82,0x85,0x19,0x83,0x85,0x1a,0xf0,0x12,0x0f,0xf0, -0xfd,0xef,0x5d,0xfe,0xb5,0x05,0x0e,0xe5,0x18,0x24,0xf8,0xfa,0xe5,0x19,0x34,0xff, -0xfb,0xac,0x1a,0x80,0x18,0x74,0x03,0x25,0x18,0xfa,0xe4,0x35,0x19,0xfb,0xac,0x1a, -0x02,0x06,0xf4,0x74,0x09,0x2a,0xfa,0xe4,0x3b,0xfb,0x02,0x06,0xf4,0x90,0xff,0xfe, -0xe0,0xfd,0x53,0x05,0x01,0xbd,0x00,0x2b,0x74,0x09,0x2a,0xfa,0xe4,0x3b,0xfb,0x8a, -0x82,0x8b,0x83,0x8c,0xf0,0x12,0x0f,0xf0,0xfa,0xa3,0x12,0x0f,0xf0,0xfb,0xc0,0x02, -0xc0,0x03,0x74,0xdf,0xc0,0xe0,0x74,0x07,0xc0,0xe0,0xc0,0x02,0xc0,0x03,0x22,0xd0, -0x03,0xd0,0x02,0x22,0x7a,0xfc,0x7b,0xff,0x90,0xff,0xfc,0xe0,0xfc,0x43,0x04,0x02, -0x8a,0x82,0x8b,0x83,0xec,0xf0,0x90,0xff,0x00,0xe0,0xfa,0x53,0x02,0x80,0xba,0x80, -0x14,0x7a,0xfc,0x7b,0xff,0x90,0xff,0xfc,0xe0,0xfc,0x43,0x04,0x01,0x8a,0x82,0x8b, -0x83,0xec,0xf0,0x80,0x12,0x7a,0xfc,0x7b,0xff,0x90,0xff,0xfc,0xe0,0xfc,0x53,0x04, -0xfe,0x8a,0x82,0x8b,0x83,0xec,0xf0,0xc2,0x01,0xc2,0x02,0x7a,0x00,0xba,0x04,0x00, -0x50,0x0f,0xea,0x24,0xab,0xf5,0x82,0xe4,0x34,0xf8,0xf5,0x83,0xe4,0xf0,0x0a,0x80, -0xec,0x12,0x06,0xd5,0x90,0xff,0xfe,0xe0,0xfa,0x20,0xe0,0xaa,0x7a,0xfc,0x7b,0xff, -0x90,0xff,0xfc,0xe0,0xfc,0x53,0x04,0xfd,0x8a,0x82,0x8b,0x83,0xec,0xf0,0x90,0xff, -0xfe,0x74,0x04,0xf0,0x22,0x90,0xff,0x83,0xe4,0xf0,0x30,0x01,0x03,0x02,0x02,0x84, -0x7a,0x80,0x7b,0xff,0x90,0xff,0x80,0xe0,0xfc,0x43,0x04,0x08,0x8a,0x82,0x8b,0x83, -0xec,0xf0,0x22,0x90,0xff,0x81,0xe4,0xf0,0x30,0x02,0x03,0x02,0x03,0x45,0x7a,0x82, -0x7b,0xff,0x90,0xff,0x82,0xe0,0xfc,0x43,0x04,0x08,0x8a,0x82,0x8b,0x83,0xec,0xf0, -0x22,0x78,0x27,0xe4,0xf6,0x08,0xf6,0x78,0x29,0xe4,0xf6,0x08,0xf6,0xc2,0x01,0xc2, -0x02,0x90,0xff,0xe0,0xe4,0xf0,0x90,0xff,0xe4,0xf0,0x7a,0x00,0x74,0xfb,0xfb,0xc4, -0x23,0xca,0xc4,0x23,0x54,0x1f,0x6a,0xca,0x54,0x1f,0xca,0x6a,0xca,0x7b,0x00,0x8a, -0x1b,0x7b,0x00,0xbb,0x03,0x00,0x40,0x03,0x02,0x09,0xc2,0x90,0xff,0x08,0xe4,0xf0, -0x90,0xff,0x48,0xf0,0xeb,0x75,0xf0,0x08,0xa4,0xfc,0xad,0xf0,0xec,0x24,0x08,0xfe, -0xed,0x34,0xff,0xff,0x74,0x07,0x2e,0xf5,0x82,0xe4,0x3f,0xf5,0x83,0x74,0x40,0xf0, -0xec,0x24,0x48,0xfe,0xed,0x34,0xff,0xff,0x74,0x07,0x2e,0xf5,0x82,0xe4,0x3f,0xf5, -0x83,0x74,0x40,0xf0,0xec,0x24,0x08,0xfe,0xed,0x34,0xff,0xff,0x74,0x02,0x2e,0xf5, -0x82,0xe4,0x3f,0xf5,0x83,0xe4,0xf0,0xec,0x24,0x08,0xfe,0xed,0x34,0xff,0xff,0x74, -0x06,0x2e,0xf5,0x82,0xe4,0x3f,0xf5,0x83,0xe4,0xf0,0xec,0x24,0x48,0xfe,0xed,0x34, -0xff,0xff,0x74,0x02,0x2e,0xf5,0x82,0xe4,0x3f,0xf5,0x83,0x74,0x80,0xf0,0xec,0x24, -0x48,0xfe,0xed,0x34,0xff,0xff,0x74,0x06,0x2e,0xf5,0x82,0xe4,0x3f,0xf5,0x83,0x74, -0x80,0xf0,0xec,0x24,0x08,0xfe,0xed,0x34,0xff,0xff,0x74,0x01,0x2e,0xf5,0x82,0xe4, -0x3f,0xf5,0x83,0xeb,0xc4,0x23,0x54,0xe0,0x25,0x1b,0xfe,0xf0,0xec,0x24,0x08,0xff, -0xed,0x34,0xff,0xfa,0x74,0x05,0x2f,0xf5,0x82,0xe4,0x3a,0xf5,0x83,0x74,0x08,0x2e, -0xfa,0xf0,0xec,0x24,0x48,0xfa,0xed,0x34,0xff,0xff,0x74,0x01,0x2a,0xf5,0x82,0xe4, -0x3f,0xf5,0x83,0x74,0x10,0x2e,0xfa,0xf0,0xec,0x24,0x48,0xfc,0xed,0x34,0xff,0xfd, -0x74,0x05,0x2c,0xf5,0x82,0xe4,0x3d,0xf5,0x83,0x74,0x18,0x2e,0xfe,0xf0,0x0b,0x02, -0x08,0xd3,0x90,0xff,0x80,0x74,0x8c,0xf0,0x90,0xff,0x82,0x74,0x8c,0xf0,0x90,0xff, -0x08,0x74,0x90,0xf0,0x90,0xff,0x48,0x74,0x90,0xf0,0x7a,0x00,0x74,0xfe,0xfb,0xc4, -0x23,0xca,0xc4,0x23,0x54,0x1f,0x6a,0xca,0x54,0x1f,0xca,0x6a,0xca,0x7b,0x00,0x90, -0xff,0x51,0xea,0xf0,0x90,0xff,0x50,0x74,0x84,0xf0,0x90,0xff,0xe1,0x74,0x94,0xf0, -0x90,0xff,0xe5,0x74,0x94,0xf0,0x90,0xff,0xe0,0x74,0xa1,0xf0,0x90,0xff,0xe4,0x74, -0xa1,0xf0,0x22,0x90,0xf8,0x80,0x78,0x25,0xe0,0xf6,0x90,0xf8,0x81,0x78,0x26,0xe0, -0xf6,0x7a,0x00,0xba,0x12,0x00,0x50,0x16,0xea,0x24,0x00,0xfb,0xe4,0x34,0xf8,0xfc, -0xea,0x90,0x0a,0x88,0x93,0xfd,0x8b,0x82,0x8c,0x83,0xf0,0x0a,0x80,0xe5,0x7a,0x00, -0xba,0x27,0x00,0x50,0x16,0xea,0x24,0x12,0xfb,0xe4,0x34,0xf8,0xfc,0xea,0x90,0x0a, -0x9a,0x93,0xfd,0x8b,0x82,0x8c,0x83,0xf0,0x0a,0x80,0xe5,0x90,0xf8,0x14,0x74,0x27, -0xf0,0x7a,0x00,0xba,0x72,0x00,0x50,0x16,0xea,0x24,0x39,0xfb,0xe4,0x34,0xf8,0xfc, -0xea,0x90,0x0a,0xc1,0x93,0xfd,0x8b,0x82,0x8c,0x83,0xf0,0x0a,0x80,0xe5,0x12,0x08, -0xa1,0x90,0xff,0xfd,0x74,0xe4,0xf0,0x22,0x12,0x01,0x10,0x01,0xff,0x00,0x00,0x08, -0x51,0x04,0x10,0x34,0x01,0x00,0x01,0x02,0x03,0x02,0x09,0x02,0xff,0x00,0x01,0x02, -0x00,0x80,0x32,0x09,0x04,0x00,0x00,0x03,0xff,0x00,0x00,0x00,0x07,0x05,0x01,0x02, -0x40,0x00,0x00,0x07,0x05,0x81,0x02,0x40,0x00,0x00,0x07,0x05,0x82,0x03,0x40,0x00, -0x00,0x04,0x03,0x09,0x04,0x22,0x03,0x55,0x00,0x41,0x00,0x52,0x00,0x54,0x00,0x32, -0x00,0x55,0x00,0x53,0x00,0x42,0x00,0x20,0x00,0x61,0x00,0x64,0x00,0x61,0x00,0x70, -0x00,0x74,0x00,0x65,0x00,0x72,0x00,0x2a,0x03,0x54,0x00,0x55,0x00,0x53,0x00,0x42, -0x00,0x33,0x00,0x34,0x00,0x31,0x00,0x30,0x00,0x20,0x00,0x42,0x00,0x6f,0x00,0x6f, -0x00,0x74,0x00,0x20,0x00,0x44,0x00,0x65,0x00,0x76,0x00,0x69,0x00,0x63,0x00,0x65, -0x00,0x22,0x03,0x42,0x00,0x4d,0x00,0x4c,0x00,0x53,0x00,0x30,0x00,0x30,0x00,0x30, -0x00,0x30,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20, -0x00,0x20,0x00,0xc0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x80,0xc7,0x06,0x40,0xff, -0xff,0xff,0xff,0xff,0xff,0xff,0x80,0xc7,0x06,0x02,0x01,0x00,0x00,0xff,0x00,0x00, -0x00,0xf7,0x58,0x03,0x80,0x08,0x00,0x00,0x00,0x00,0x01,0x00,0xff,0xd9,0x03,0x80, -0x06,0xff,0x01,0xff,0xff,0xff,0xff,0xd0,0xe8,0x03,0x80,0x06,0xff,0x02,0xff,0xff, -0xff,0xff,0xd0,0xf7,0x03,0x80,0x06,0xff,0x03,0xff,0xff,0xff,0xff,0xd0,0x06,0x04, -0x81,0x0a,0x00,0x00,0xff,0xff,0x01,0x00,0xf3,0x52,0x04,0x80,0x00,0x00,0x00,0x00, -0x00,0x02,0x00,0xff,0x68,0x04,0x81,0x00,0x00,0x00,0xff,0x00,0x02,0x00,0xf7,0x9c, -0x04,0x82,0x00,0x00,0x00,0xff,0x00,0x02,0x00,0xf7,0xab,0x04,0x00,0x05,0xff,0x00, -0x00,0x00,0x00,0x00,0xdf,0x64,0x05,0x00,0x09,0xff,0x00,0x00,0x00,0x00,0x00,0xdf, -0x94,0x05,0x00,0x03,0xff,0x00,0x00,0x00,0x00,0x00,0xdf,0xb2,0x05,0x02,0x03,0xff, -0x00,0xff,0x00,0x00,0x00,0xd7,0xb5,0x05,0x01,0x0b,0xff,0x00,0xff,0x00,0x00,0x00, -0xd7,0x40,0x06,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x5e,0x06,0x90,0xf8, -0xaf,0xe4,0xf0,0x90,0xff,0xab,0xf0,0x90,0xff,0xa4,0x74,0x01,0xf0,0x90,0xff,0xa9, -0x74,0x11,0xf0,0x90,0xff,0xaa,0x74,0x13,0xf0,0x90,0xff,0xa7,0x74,0x60,0xf0,0x90, -0xff,0xa8,0xe4,0xf0,0x90,0xff,0xa2,0x74,0x83,0xf0,0x90,0xff,0xa3,0xe4,0xf0,0x90, -0xff,0xa4,0xf0,0x7a,0xab,0x7b,0xff,0x90,0xff,0xab,0xe0,0xfc,0x74,0x01,0x4c,0xfd, -0x8a,0x82,0x8b,0x83,0xf0,0x90,0xff,0xab,0x43,0x04,0x02,0xec,0xf0,0x22,0xaa,0x82, -0xab,0x83,0x74,0x01,0x2a,0xf5,0x82,0xe4,0x3b,0xf5,0x83,0xe0,0xfa,0x60,0x02,0x80, -0x4d,0x90,0xff,0xa7,0xe0,0xfa,0x90,0xf8,0xb1,0xf0,0x90,0xff,0xa8,0xe0,0xfa,0x90, -0xf8,0xb2,0xf0,0x90,0xff,0xa2,0xe0,0xfa,0x90,0xf8,0xb3,0xf0,0x90,0xff,0xa4,0xe0, -0xfa,0x63,0x02,0x20,0x90,0xf8,0xb4,0xea,0xf0,0x90,0xff,0xa3,0xe0,0xfa,0x90,0xf8, -0xb5,0xf0,0x90,0xff,0xa5,0xe0,0xfa,0x90,0xf8,0xb6,0xf0,0x90,0xff,0xa6,0xe0,0xfa, -0x90,0xf8,0xb7,0xf0,0x90,0xf8,0xb0,0x74,0x07,0xf0,0x90,0xf8,0xb0,0x22,0x90,0x00, -0x00,0x22,0xe5,0x82,0xfa,0x24,0xf2,0x50,0x03,0x02,0x0d,0x7b,0xea,0x2a,0x2a,0x90, -0x0c,0xb3,0x73,0x02,0x0d,0x7b,0x02,0x0c,0xdd,0x02,0x0c,0xea,0x02,0x0c,0xf7,0x02, -0x0d,0x03,0x02,0x0d,0x0f,0x02,0x0d,0x1b,0x02,0x0d,0x27,0x02,0x0d,0x33,0x02,0x0d, -0x3f,0x02,0x0d,0x4b,0x02,0x0d,0x57,0x02,0x0d,0x63,0x02,0x0d,0x6f,0x90,0xff,0xa8, -0x74,0x03,0xf0,0x90,0xff,0xa7,0x74,0x01,0xf0,0x22,0x90,0xff,0xa8,0x74,0x01,0xf0, -0x90,0xff,0xa7,0x74,0x81,0xf0,0x22,0x90,0xff,0xa8,0xe4,0xf0,0x90,0xff,0xa7,0x74, -0xc0,0xf0,0x22,0x90,0xff,0xa8,0xe4,0xf0,0x90,0xff,0xa7,0x74,0x80,0xf0,0x22,0x90, -0xff,0xa8,0xe4,0xf0,0x90,0xff,0xa7,0x74,0x60,0xf0,0x22,0x90,0xff,0xa8,0xe4,0xf0, -0x90,0xff,0xa7,0x74,0x40,0xf0,0x22,0x90,0xff,0xa8,0xe4,0xf0,0x90,0xff,0xa7,0x74, -0x30,0xf0,0x22,0x90,0xff,0xa8,0xe4,0xf0,0x90,0xff,0xa7,0x74,0x18,0xf0,0x22,0x90, -0xff,0xa8,0xe4,0xf0,0x90,0xff,0xa7,0x74,0x10,0xf0,0x22,0x90,0xff,0xa8,0xe4,0xf0, -0x90,0xff,0xa7,0x74,0x08,0xf0,0x22,0x90,0xff,0xa8,0xe4,0xf0,0x90,0xff,0xa7,0x74, -0x04,0xf0,0x22,0x90,0xff,0xa8,0xe4,0xf0,0x90,0xff,0xa7,0x74,0x02,0xf0,0x22,0x90, -0xff,0xa8,0xe4,0xf0,0x90,0xff,0xa7,0x74,0x01,0xf0,0x22,0x90,0xff,0xa8,0xe4,0xf0, -0x90,0xff,0xa7,0x74,0x60,0xf0,0x22,0xaa,0x82,0xab,0x83,0x74,0x01,0x2a,0xf5,0x82, -0xe4,0x3b,0xf5,0x83,0xe0,0xfc,0x24,0xf6,0x50,0x03,0x02,0x0f,0x06,0xec,0x2c,0x2c, -0x90,0x0d,0xa4,0x73,0x02,0x0f,0x06,0x02,0x0d,0xc2,0x02,0x0d,0xc5,0x02,0x0d,0xcb, -0x02,0x0d,0xfe,0x02,0x0d,0xf6,0x02,0x0e,0x19,0x02,0x0e,0x51,0x02,0x0e,0x89,0x02, -0x0e,0xc0,0x02,0x0f,0x0d,0x12,0x0b,0xee,0x02,0x0f,0x0d,0x7c,0xa8,0x7d,0xff,0x74, -0x03,0x2a,0xf5,0x82,0xe4,0x3b,0xf5,0x83,0xe0,0xfe,0x8c,0x82,0x8d,0x83,0xf0,0x7c, -0xa7,0x7d,0xff,0x74,0x02,0x2a,0xf5,0x82,0xe4,0x3b,0xf5,0x83,0xe0,0xfe,0x8c,0x82, -0x8d,0x83,0xf0,0x02,0x0f,0x0d,0x90,0xff,0xa3,0xe4,0xf0,0x02,0x0f,0x0d,0x7c,0xa2, -0x7d,0xff,0x74,0x02,0x2a,0xf5,0x82,0xe4,0x3b,0xf5,0x83,0xe0,0xfe,0x43,0x06,0x80, -0x8c,0x82,0x8d,0x83,0xee,0xf0,0x02,0x0f,0x0d,0x74,0x02,0x2a,0xfc,0xe4,0x3b,0xfd, -0x8c,0x82,0x8d,0x83,0xe0,0x70,0x15,0x7c,0xa4,0x7d,0xff,0x90,0xff,0xa4,0xe0,0xfe, -0x43,0x06,0x20,0x8c,0x82,0x8d,0x83,0xee,0xf0,0x02,0x0f,0x0d,0x7c,0xa4,0x7d,0xff, -0x90,0xff,0xa4,0xe0,0xfe,0x53,0x06,0xdf,0x8c,0x82,0x8d,0x83,0xee,0xf0,0x02,0x0f, -0x0d,0x74,0x02,0x2a,0xfc,0xe4,0x3b,0xfd,0x8c,0x82,0x8d,0x83,0xe0,0x60,0x15,0x7c, -0xa4,0x7d,0xff,0x90,0xff,0xa4,0xe0,0xfe,0x43,0x06,0x10,0x8c,0x82,0x8d,0x83,0xee, -0xf0,0x02,0x0f,0x0d,0x7c,0xa4,0x7d,0xff,0x90,0xff,0xa4,0xe0,0xfe,0x53,0x06,0xef, -0x8c,0x82,0x8d,0x83,0xee,0xf0,0x02,0x0f,0x0d,0x74,0x02,0x2a,0xfc,0xe4,0x3b,0xfd, -0x8c,0x82,0x8d,0x83,0xe0,0x60,0x15,0x7c,0xa2,0x7d,0xff,0x90,0xff,0xa2,0xe0,0xfe, -0x43,0x06,0x08,0x8c,0x82,0x8d,0x83,0xee,0xf0,0x02,0x0f,0x0d,0x7c,0xa2,0x7d,0xff, -0x90,0xff,0xa2,0xe0,0xfe,0x53,0x06,0xf7,0x8c,0x82,0x8d,0x83,0xee,0xf0,0x80,0x4d, -0x74,0x02,0x2a,0xfa,0xe4,0x3b,0xfb,0x8a,0x82,0x8b,0x83,0xe0,0x60,0x1c,0x7a,0xa3, -0x7b,0xff,0x90,0xff,0xa3,0xe0,0xfc,0x74,0x04,0x4c,0xfd,0x8a,0x82,0x8b,0x83,0xf0, -0x90,0xff,0xa3,0x43,0x04,0x20,0xec,0xf0,0x80,0x23,0x7a,0xa3,0x7b,0xff,0x90,0xff, -0xa3,0xe0,0xfc,0x74,0xfb,0x5c,0xfd,0x8a,0x82,0x8b,0x83,0xf0,0x90,0xff,0xa3,0x53, -0x04,0xdf,0xec,0xf0,0x80,0x07,0x12,0x0f,0x7f,0x90,0x00,0x01,0x22,0x90,0x00,0x00, -0x22,0x90,0xf8,0xb9,0xe4,0xf0,0x90,0xff,0xa5,0xe0,0xfa,0x30,0xe0,0x0d,0x90,0xf8, -0xb8,0xe0,0xfb,0x43,0x03,0x01,0x90,0xf8,0xb8,0xeb,0xf0,0xea,0x30,0xe1,0x0d,0x90, -0xf8,0xb8,0xe0,0xfb,0x43,0x03,0x02,0x90,0xf8,0xb8,0xeb,0xf0,0xea,0x30,0xe2,0x0d, -0x90,0xf8,0xb8,0xe0,0xfb,0x43,0x03,0x04,0x90,0xf8,0xb8,0xeb,0xf0,0xea,0x30,0xe3, -0x0d,0x90,0xf8,0xb8,0xe0,0xfa,0x43,0x02,0x08,0x90,0xf8,0xb8,0xea,0xf0,0x75,0x08, -0x02,0xe4,0xf5,0x09,0x90,0xf8,0xb8,0x75,0xf0,0x01,0x12,0x02,0x2e,0x90,0xff,0xa5, -0xe0,0xfa,0x54,0x0f,0x60,0x08,0x90,0xff,0xa5,0x43,0x02,0x0f,0xea,0xf0,0x22,0x90, -0xff,0xa6,0xe0,0xfa,0x30,0xe0,0x10,0x90,0xf8,0xaf,0xe0,0xfb,0x64,0x01,0xf0,0x90, -0xff,0xa6,0x74,0x01,0x4a,0xfb,0xf0,0xea,0x30,0xe1,0x10,0x90,0xf8,0xaf,0xe0,0xfb, -0x64,0x02,0xf0,0x90,0xff,0xa6,0x74,0x02,0x4a,0xfb,0xf0,0xea,0x30,0xe2,0x10,0x90, -0xf8,0xaf,0xe0,0xfb,0x64,0x08,0xf0,0x90,0xff,0xa6,0x74,0x04,0x4a,0xfb,0xf0,0xea, -0x30,0xe3,0x10,0x90,0xf8,0xaf,0xe0,0xfb,0x64,0x04,0xf0,0x90,0xff,0xa6,0x43,0x02, -0x08,0xea,0xf0,0x90,0xf8,0xba,0xe4,0xf0,0x90,0xf8,0xaf,0xe0,0xfa,0x90,0xf8,0xbb, -0xf0,0x75,0x08,0x02,0xe4,0xf5,0x09,0x90,0xf8,0xba,0x75,0xf0,0x01,0x02,0x02,0x2e, -0xe5,0xf0,0x60,0x10,0x14,0x60,0x15,0x14,0x60,0x14,0x14,0x60,0x13,0x14,0x14,0x60, -0x03,0x74,0xff,0x22,0xc0,0x00,0xa8,0x82,0xe6,0xd0,0x00,0x22,0xe0,0x22,0x93,0x22, -0xc0,0x00,0xa8,0x82,0xe2,0xd0,0x00,0x22,0x75,0x82,0x00,0x22,0x75,0x81,0x2e,0x12, -0x10,0x18,0xe5,0x82,0x60,0x03,0x02,0x00,0x0e,0x79,0x00,0xe9,0x44,0x00,0x60,0x1b, -0x7a,0x00,0x90,0x10,0x81,0x78,0xbc,0x75,0xa0,0xf8,0xe4,0x93,0xf2,0xa3,0x08,0xb8, -0x00,0x02,0x05,0xa0,0xd9,0xf4,0xda,0xf2,0x75,0xa0,0xff,0xe4,0x78,0xff,0xf6,0xd8, -0xfd,0x78,0x00,0xe8,0x44,0x00,0x60,0x0a,0x79,0x00,0x75,0xa0,0x00,0xe4,0xf3,0x09, -0xd8,0xfc,0x78,0xbc,0xe8,0x44,0x00,0x60,0x0c,0x79,0x01,0x90,0xf8,0x00,0xe4,0xf0, -0xa3,0xd8,0xfc,0xd9,0xfa,0x75,0x00,0x87,0x75,0x01,0x87,0x75,0x02,0x87,0x02,0x00, -0x0e -}; - -#endif /* _UTICOM_FW3410_H_ */ diff --git a/sys/dev/usbmisc/uvisor/Makefile b/sys/dev/usbmisc/uvisor/Makefile deleted file mode 100644 index 725914672b..0000000000 --- a/sys/dev/usbmisc/uvisor/Makefile +++ /dev/null @@ -1,9 +0,0 @@ -# $FreeBSD: src/sys/modules/uvisor/Makefile,v 1.1.2.2 2002/08/11 20:05:20 joe Exp $ -# $DragonFly: src/sys/dev/usbmisc/uvisor/Makefile,v 1.4 2004/08/13 17:51:07 dillon Exp $ - -.PATH: ${.CURDIR}/../ucom - -KMOD= uvisor -SRCS= uvisor.c ucomvar.h opt_usb.h device_if.h bus_if.h - -.include diff --git a/sys/dev/usbmisc/uvisor/uvisor.c b/sys/dev/usbmisc/uvisor/uvisor.c deleted file mode 100644 index f31fd9a881..0000000000 --- a/sys/dev/usbmisc/uvisor/uvisor.c +++ /dev/null @@ -1,532 +0,0 @@ -/* - * $NetBSD: uvisor.c,v 1.9 2001/01/23 14:04:14 augustss Exp $ - * $FreeBSD: src/sys/dev/usb/uvisor.c,v 1.16 2003/11/08 11:23:07 joe Exp $ - */ - -/* - * Also already merged from NetBSD: - * $NetBSD: uvisor.c,v 1.12 2001/11/13 06:24:57 lukem Exp $ - * $NetBSD: uvisor.c,v 1.13 2002/02/11 15:11:49 augustss Exp $ - * $NetBSD: uvisor.c,v 1.14 2002/02/27 23:00:03 augustss Exp $ - * $NetBSD: uvisor.c,v 1.15 2002/06/16 15:01:31 augustss Exp $ - * $NetBSD: uvisor.c,v 1.16 2002/07/11 21:14:36 augustss Exp $ - * $NetBSD: uvisor.c,v 1.17 2002/08/13 11:38:15 augustss Exp $ - * $NetBSD: uvisor.c,v 1.18 2003/02/05 00:50:14 augustss Exp $ - * $NetBSD: uvisor.c,v 1.19 2003/02/07 18:12:37 augustss Exp $ - * $NetBSD: uvisor.c,v 1.20 2003/04/11 01:30:10 simonb Exp $ - */ - -/* - * Copyright (c) 2000 The NetBSD Foundation, Inc. - * All rights reserved. - * - * This code is derived from software contributed to The NetBSD Foundation - * by Lennart Augustsson (lennart@augustsson.net) at - * Carlstedt Research & Technology. - * - * 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. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the NetBSD - * Foundation, Inc. and its contributors. - * 4. Neither the name of The NetBSD Foundation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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. - */ - -/* - * Handspring Visor (Palmpilot compatible PDA) driver - */ - -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include - -#include "../ucom/ucomvar.h" - -#ifdef USB_DEBUG -#define DPRINTF(x) if (uvisordebug) kprintf x -#define DPRINTFN(n,x) if (uvisordebug>(n)) kprintf x -int uvisordebug = 0; -SYSCTL_NODE(_hw_usb, OID_AUTO, uvisor, CTLFLAG_RW, 0, "USB uvisor"); -SYSCTL_INT(_hw_usb_uvisor, OID_AUTO, debug, CTLFLAG_RW, - &uvisordebug, 0, "uvisor debug level"); -#else -#define DPRINTF(x) -#define DPRINTFN(n,x) -#endif - -#define UVISOR_CONFIG_INDEX 0 -#define UVISOR_IFACE_INDEX 0 -#define UVISOR_MODVER 1 - -/* From the Linux driver */ -/* - * UVISOR_REQUEST_BYTES_AVAILABLE asks the visor for the number of bytes that - * are available to be transfered to the host for the specified endpoint. - * Currently this is not used, and always returns 0x0001 - */ -#define UVISOR_REQUEST_BYTES_AVAILABLE 0x01 - -/* - * UVISOR_CLOSE_NOTIFICATION is set to the device to notify it that the host - * is now closing the pipe. An empty packet is sent in response. - */ -#define UVISOR_CLOSE_NOTIFICATION 0x02 - -/* - * UVISOR_GET_CONNECTION_INFORMATION is sent by the host during enumeration to - * get the endpoints used by the connection. - */ -#define UVISOR_GET_CONNECTION_INFORMATION 0x03 - - -/* - * UVISOR_GET_CONNECTION_INFORMATION returns data in the following format - */ -#define UVISOR_MAX_CONN 8 -struct uvisor_connection_info { - uWord num_ports; - struct { - uByte port_function_id; - uByte port; - } connections[UVISOR_MAX_CONN]; -}; -#define UVISOR_CONNECTION_INFO_SIZE 18 - -/* struct uvisor_connection_info.connection[x].port defines: */ -#define UVISOR_ENDPOINT_1 0x01 -#define UVISOR_ENDPOINT_2 0x02 - -/* struct uvisor_connection_info.connection[x].port_function_id defines: */ -#define UVISOR_FUNCTION_GENERIC 0x00 -#define UVISOR_FUNCTION_DEBUGGER 0x01 -#define UVISOR_FUNCTION_HOTSYNC 0x02 -#define UVISOR_FUNCTION_CONSOLE 0x03 -#define UVISOR_FUNCTION_REMOTE_FILE_SYS 0x04 - -/* - * Unknown PalmOS stuff. - */ -#define UVISOR_GET_PALM_INFORMATION 0x04 -#define UVISOR_GET_PALM_INFORMATION_LEN 0x14 - - -/* - * Crank down UVISORBUFSIZE from 1024 to 64 to avoid a problem where - * the Palm device and the USB host controller deadlock. The USB host - * controller is expecting an early-end-of-transmission packet with 0 - * data, and the Palm doesn't send one because it's already - * communicated the amount of data it's going to send in a header - * (which ucom/uvisor are oblivious to). This is the problem that has - * been known on the pilot-link lists as the "[Free]BSD USB problem", - * but not understood. - */ -#define UVISORIBUFSIZE 64 -#define UVISOROBUFSIZE 1024 - -struct uvisor_softc { - struct ucom_softc sc_ucom; - u_int16_t sc_flags; -}; - -static usbd_status uvisor_init(struct uvisor_softc *); - -static void uvisor_close(void *, int); - -struct ucom_callback uvisor_callback = { - NULL, - NULL, - NULL, - NULL, - NULL, - uvisor_close, - NULL, - NULL, -}; - -static device_probe_t uvisor_match; -static device_attach_t uvisor_attach; -static device_detach_t uvisor_detach; -static device_method_t uvisor_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, uvisor_match), - DEVMETHOD(device_attach, uvisor_attach), - DEVMETHOD(device_detach, uvisor_detach), - DEVMETHOD_END - }; - - -static driver_t uvisor_driver = { - "ucom", - uvisor_methods, - sizeof (struct uvisor_softc) -}; - -DRIVER_MODULE(uvisor, uhub, uvisor_driver, ucom_devclass, usbd_driver_load, NULL); -MODULE_DEPEND(uvisor, usb, 1, 1, 1); -MODULE_DEPEND(uvisor, ucom, UCOM_MINVER, UCOM_PREFVER, UCOM_MAXVER); -MODULE_VERSION(uvisor, UVISOR_MODVER); - -struct uvisor_type { - struct usb_devno uv_dev; - u_int16_t uv_flags; -#define PALM4 0x0001 -#define VISOR 0x0002 -#define PALM35 0x0004 -}; -static const struct uvisor_type uvisor_devs[] = { - {{ USB_DEVICE(0x054c, 0x0066) }, 0 }, /* Sony Clie v4.0 */ - {{ USB_DEVICE(0x054c, 0x0095) }, PALM4 }, /* Sony Clie s360 */ - {{ USB_DEVICE(0x054c, 0x009a) }, 0 }, /* Sony Clie v4.1 */ - {{ USB_DEVICE(0x054c, 0x00da) }, PALM4 }, /* Sony Clie nx60 */ - {{ USB_DEVICE(0x082d, 0x0100) }, 0 }, /* Handspring Visor */ - {{ USB_DEVICE(0x082d, 0x0200) }, PALM4 }, /* Handspring Treo */ - {{ USB_DEVICE(0x0830, 0x0001) }, PALM4 }, /* Palm m500 */ - {{ USB_DEVICE(0x0830, 0x0002) }, PALM4 }, /* Palm m505 */ - {{ USB_DEVICE(0x0830, 0x0003) }, PALM4 }, /* Palm m515 */ - {{ USB_DEVICE(0x0830, 0x0020) }, PALM4 }, /* Palm i705 */ - {{ USB_DEVICE(0x0830, 0x0031) }, PALM4 }, /* Palm Tungsten Z */ - {{ USB_DEVICE(0x0830, 0x0040) }, PALM4 }, /* Palm m125 */ - {{ USB_DEVICE(0x0830, 0x0050) }, PALM4 }, /* Palm m130 */ - {{ USB_DEVICE(0x0830, 0x0060) }, PALM4 }, /* Palm Tungsten T */ - {{ USB_DEVICE(0x0830, 0x0070) }, PALM4 }, /* Palm Palm Zire */ - {{ USB_DEVICE(0x4766, 0x0001) }, PALM4 }, /* Aceeca MEZ1000 RDA */ - {{ USB_DEVICE(0x091e, 0x0004) }, PALM4 }, /* Garmin iQue 3600 */ - {{ USB_DEVICE(0x0e67, 0x0002) }, PALM4 }, /* Fossil, Wrist PDA */ - {{ USB_DEVICE(0x082d, 0x0300) }, PALM4 }, /* Handspring Treo 600 */ - {{ USB_DEVICE(0x0830, 0x0060) }, PALM4 }, /* Palm Tungsten T */ - {{ USB_DEVICE(0x0830, 0x0061) }, PALM4 }, /* Palm Zire 31 */ - {{ USB_DEVICE(0x04e8, 0x6601) }, PALM4 }, /* Samsung I500 Palm USB */ - {{ USB_DEVICE(0x054c, 0x0038) }, PALM35 }, /* Sony Clie v3.5 */ - {{ USB_DEVICE(0x054c, 0x0169) }, PALM4 }, /* Sony Clie tj37 */ - {{ USB_DEVICE(0x12ef, 0x0100) }, PALM4 }, /* Tapwave Zodiac */ -}; -#define uvisor_lookup(v, p) ((const struct uvisor_type *)usb_lookup(uvisor_devs, v, p)) - -static int -uvisor_match(device_t self) -{ - struct usb_attach_arg *uaa = device_get_ivars(self); - - if (uaa->iface != NULL) - return (UMATCH_NONE); - - DPRINTFN(20,("uvisor: vendor=0x%x, product=0x%x\n", - uaa->vendor, uaa->product)); - - return (uvisor_lookup(uaa->vendor, uaa->product) != NULL ? - UMATCH_VENDOR_PRODUCT : UMATCH_NONE); -} - -static int -uvisor_attach(device_t self) -{ - struct uvisor_softc *sc = device_get_softc(self); - struct usb_attach_arg *uaa = device_get_ivars(self); - usbd_device_handle dev = uaa->device; - usbd_interface_handle iface; - usb_interface_descriptor_t *id; - usb_endpoint_descriptor_t *ed; - const char *devname; - int i; - usbd_status err; - struct ucom_softc *ucom; - - ucom = &sc->sc_ucom; - - bzero(sc, sizeof (struct uvisor_softc)); - - ucom->sc_dev = self; - ucom->sc_udev = dev; - ucom->sc_iface = uaa->iface; - - devname = device_get_nameunit(ucom->sc_dev); - - DPRINTFN(10,("\nuvisor_attach: sc=%p\n", sc)); - - /* Move the device into the configured state. */ - err = usbd_set_config_index(dev, UVISOR_CONFIG_INDEX, 1); - if (err) { - kprintf("\n%s: failed to set configuration, err=%s\n", - devname, usbd_errstr(err)); - goto bad; - } - - err = usbd_device2interface_handle(dev, UVISOR_IFACE_INDEX, &iface); - if (err) { - kprintf("\n%s: failed to get interface, err=%s\n", - devname, usbd_errstr(err)); - goto bad; - } - - sc->sc_flags = uvisor_lookup(uaa->vendor, uaa->product)->uv_flags; - - id = usbd_get_interface_descriptor(iface); - - ucom->sc_udev = dev; - ucom->sc_iface = iface; - - ucom->sc_bulkin_no = ucom->sc_bulkout_no = -1; - for (i = 0; i < id->bNumEndpoints; i++) { - int addr, dir, attr; - ed = usbd_interface2endpoint_descriptor(iface, i); - if (ed == NULL) { - kprintf("%s: could not read endpoint descriptor" - ": %s\n", devname, usbd_errstr(err)); - goto bad; - } - - addr = ed->bEndpointAddress; - dir = UE_GET_DIR(ed->bEndpointAddress); - attr = ed->bmAttributes & UE_XFERTYPE; - if (dir == UE_DIR_IN && attr == UE_BULK) - ucom->sc_bulkin_no = addr; - else if (dir == UE_DIR_OUT && attr == UE_BULK) - ucom->sc_bulkout_no = addr; - else { - kprintf("%s: unexpected endpoint\n", devname); - goto bad; - } - } - if (ucom->sc_bulkin_no == -1) { - kprintf("%s: Could not find data bulk in\n", - device_get_nameunit(ucom->sc_dev)); - goto bad; - } - if (ucom->sc_bulkout_no == -1) { - kprintf("%s: Could not find data bulk out\n", - device_get_nameunit(ucom->sc_dev)); - goto bad; - } - - ucom->sc_parent = sc; - ucom->sc_portno = UCOM_UNK_PORTNO; - /* bulkin, bulkout set above */ - ucom->sc_ibufsize = UVISORIBUFSIZE; - ucom->sc_obufsize = UVISOROBUFSIZE; - ucom->sc_ibufsizepad = UVISORIBUFSIZE; - ucom->sc_opkthdrlen = 0; - ucom->sc_callback = &uvisor_callback; - - err = uvisor_init(sc); - if (err) { - kprintf("%s: init failed, %s\n", device_get_nameunit(ucom->sc_dev), - usbd_errstr(err)); - goto bad; - } - - usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, ucom->sc_udev, - ucom->sc_dev); - - DPRINTF(("uvisor: in=0x%x out=0x%x\n", ucom->sc_bulkin_no, ucom->sc_bulkout_no)); - ucom_attach(&sc->sc_ucom); - - return 0; - -bad: - DPRINTF(("uvisor_attach: ATTACH ERROR\n")); - ucom->sc_dying = 1; - return ENXIO; -} - -#if 0 - -int -uvisor_activate(device_t self, enum devact act) -{ - struct uvisor_softc *sc = (struct uvisor_softc *)self; - int rv = 0; - - switch (act) { - case DVACT_ACTIVATE: - return (EOPNOTSUPP); - break; - - case DVACT_DEACTIVATE: - if (sc->sc_subdev != NULL) - rv = config_deactivate(sc->sc_subdev); - sc->sc_dying = 1; - break; - } - return (rv); -} - -#endif - -static int -uvisor_detach(device_t self) -{ - struct uvisor_softc *sc = device_get_softc(self); - int rv = 0; - - DPRINTF(("uvisor_detach: sc=%p\n", sc)); - sc->sc_ucom.sc_dying = 1; - rv = ucom_detach(&sc->sc_ucom); - - usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_ucom.sc_udev, - sc->sc_ucom.sc_dev); - - return (rv); -} - -usbd_status -uvisor_init(struct uvisor_softc *sc) -{ - usbd_status err; - usb_device_request_t req; - struct uvisor_connection_info coninfo; - int actlen; - uWord avail; - char buffer[256]; - - DPRINTF(("uvisor_init: getting connection info\n")); - req.bmRequestType = UT_READ_VENDOR_ENDPOINT; - req.bRequest = UVISOR_GET_CONNECTION_INFORMATION; - USETW(req.wValue, 0); - USETW(req.wIndex, 0); - USETW(req.wLength, UVISOR_CONNECTION_INFO_SIZE); - err = usbd_do_request_flags(sc->sc_ucom.sc_udev, &req, &coninfo, - USBD_SHORT_XFER_OK, &actlen, - USBD_DEFAULT_TIMEOUT); - if (err) - return (err); - -#ifdef USB_DEBUG - { - int i, np; - char *string; - - np = UGETW(coninfo.num_ports); - kprintf("%s: Number of ports: %d\n", device_get_nameunit(sc->sc_ucom.sc_dev), np); - for (i = 0; i < np; ++i) { - switch (coninfo.connections[i].port_function_id) { - case UVISOR_FUNCTION_GENERIC: - string = "Generic"; - break; - case UVISOR_FUNCTION_DEBUGGER: - string = "Debugger"; - break; - case UVISOR_FUNCTION_HOTSYNC: - string = "HotSync"; - break; - case UVISOR_FUNCTION_REMOTE_FILE_SYS: - string = "Remote File System"; - break; - default: - string = "unknown"; - break; - } - kprintf("%s: port %d, is for %s\n", - device_get_nameunit(sc->sc_ucom.sc_dev), coninfo.connections[i].port, - string); - } - } -#endif - - if (sc->sc_flags & PALM4) { - /* Palm OS 4.0 Hack */ - req.bmRequestType = UT_READ_VENDOR_ENDPOINT; - req.bRequest = UVISOR_GET_PALM_INFORMATION; - USETW(req.wValue, 0); - USETW(req.wIndex, 0); - USETW(req.wLength, UVISOR_GET_PALM_INFORMATION_LEN); - err = usbd_do_request(sc->sc_ucom.sc_udev, &req, buffer); - if (err) - return (err); - req.bmRequestType = UT_READ_VENDOR_ENDPOINT; - req.bRequest = UVISOR_GET_PALM_INFORMATION; - USETW(req.wValue, 0); - USETW(req.wIndex, 0); - USETW(req.wLength, UVISOR_GET_PALM_INFORMATION_LEN); - err = usbd_do_request(sc->sc_ucom.sc_udev, &req, buffer); - if (err) - return (err); - } - - if (sc->sc_flags & PALM35) { - /* get the config number */ - req.bmRequestType = UT_READ; - req.bRequest = UR_GET_CONFIG; - USETW(req.wValue, 0); - USETW(req.wIndex, 0); - USETW(req.wLength, 1); - err = usbd_do_request(sc->sc_ucom.sc_udev, &req, buffer); - if (err) - return (err); - - /* get the interface number */ - req.bmRequestType = UT_READ_DEVICE; - req.bRequest = UR_GET_INTERFACE; - USETW(req.wValue, 0); - USETW(req.wIndex, 0); - USETW(req.wLength, 1); - err = usbd_do_request(sc->sc_ucom.sc_udev, &req, buffer); - if (err) - return (err); - } - - DPRINTF(("uvisor_init: getting available bytes\n")); - req.bmRequestType = UT_READ_VENDOR_ENDPOINT; - req.bRequest = UVISOR_REQUEST_BYTES_AVAILABLE; - USETW(req.wValue, 0); - USETW(req.wIndex, 5); - USETW(req.wLength, sizeof avail); - err = usbd_do_request(sc->sc_ucom.sc_udev, &req, &avail); - if (err) - return (err); - DPRINTF(("uvisor_init: avail=%d\n", UGETW(avail))); - - DPRINTF(("uvisor_init: done\n")); - return (err); -} - -void -uvisor_close(void *addr, int portno) -{ - struct uvisor_softc *sc = addr; - usb_device_request_t req; - struct uvisor_connection_info coninfo; /* XXX ? */ - int actlen; - - if (sc->sc_ucom.sc_dying) - return; - - req.bmRequestType = UT_READ_VENDOR_ENDPOINT; /* XXX read? */ - req.bRequest = UVISOR_CLOSE_NOTIFICATION; - USETW(req.wValue, 0); - USETW(req.wIndex, 0); - USETW(req.wLength, UVISOR_CONNECTION_INFO_SIZE); - (void)usbd_do_request_flags(sc->sc_ucom.sc_udev, &req, &coninfo, - USBD_SHORT_XFER_OK, &actlen, - USBD_DEFAULT_TIMEOUT); -} diff --git a/sys/dev/usbmisc/uvscom/Makefile b/sys/dev/usbmisc/uvscom/Makefile deleted file mode 100644 index e93e2b8d01..0000000000 --- a/sys/dev/usbmisc/uvscom/Makefile +++ /dev/null @@ -1,9 +0,0 @@ -# $FreeBSD: src/sys/modules/uvscom/Makefile,v 1.1.2.2 2002/08/11 20:05:20 joe Exp $ -# $DragonFly: src/sys/dev/usbmisc/uvscom/Makefile,v 1.4 2004/08/13 17:51:08 dillon Exp $ - -.PATH: ${.CURDIR}/../ucom - -KMOD= uvscom -SRCS= uvscom.c ucomvar.h opt_usb.h device_if.h bus_if.h - -.include diff --git a/sys/dev/usbmisc/uvscom/uvscom.c b/sys/dev/usbmisc/uvscom/uvscom.c deleted file mode 100644 index a05c0471bf..0000000000 --- a/sys/dev/usbmisc/uvscom/uvscom.c +++ /dev/null @@ -1,865 +0,0 @@ -/*- - * Copyright (c) 2001-2002, Shunsuke Akiyama . - * 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. - * - * $NetBSD: usb/uvscom.c,v 1.1 2002/03/19 15:08:42 augustss Exp $ - * $FreeBSD: src/sys/dev/usb/uvscom.c,v 1.19 2003/11/16 12:26:10 akiyama Exp $ - */ - -/* - * uvscom: SUNTAC Slipper U VS-10U driver. - * Slipper U is a PC card to USB converter for data communication card - * adapter. It supports DDI Pocket's Air H" C@rd, C@rd H" 64, NTT's P-in, - * P-in m@ater and various data communication card adapters. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include -#include - -#include "../ucom/ucomvar.h" - -#ifdef USB_DEBUG -static int uvscomdebug = 0; -SYSCTL_NODE(_hw_usb, OID_AUTO, uvscom, CTLFLAG_RW, 0, "USB uvscom"); -SYSCTL_INT(_hw_usb_uvscom, OID_AUTO, debug, CTLFLAG_RW, - &uvscomdebug, 0, "uvscom debug level"); - -#define DPRINTFN(n, x) do { \ - if (uvscomdebug > (n)) \ - kprintf x; \ - } while (0) -#else -#define DPRINTFN(n, x) -#endif -#define DPRINTF(x) DPRINTFN(0, x) - -#define UVSCOM_MODVER 1 /* module version */ - -#define UVSCOM_CONFIG_INDEX 0 -#define UVSCOM_IFACE_INDEX 0 - -#define UVSCOM_INTR_INTERVAL 100 /* mS */ - -#define UVSCOM_UNIT_WAIT 5 - -/* Request */ -#define UVSCOM_SET_SPEED 0x10 -#define UVSCOM_LINE_CTL 0x11 -#define UVSCOM_SET_PARAM 0x12 -#define UVSCOM_READ_STATUS 0xd0 -#define UVSCOM_SHUTDOWN 0xe0 - -/* UVSCOM_SET_SPEED parameters */ -#define UVSCOM_SPEED_150BPS 0x00 -#define UVSCOM_SPEED_300BPS 0x01 -#define UVSCOM_SPEED_600BPS 0x02 -#define UVSCOM_SPEED_1200BPS 0x03 -#define UVSCOM_SPEED_2400BPS 0x04 -#define UVSCOM_SPEED_4800BPS 0x05 -#define UVSCOM_SPEED_9600BPS 0x06 -#define UVSCOM_SPEED_19200BPS 0x07 -#define UVSCOM_SPEED_38400BPS 0x08 -#define UVSCOM_SPEED_57600BPS 0x09 -#define UVSCOM_SPEED_115200BPS 0x0a - -/* UVSCOM_LINE_CTL parameters */ -#define UVSCOM_BREAK 0x40 -#define UVSCOM_RTS 0x02 -#define UVSCOM_DTR 0x01 -#define UVSCOM_LINE_INIT 0x08 - -/* UVSCOM_SET_PARAM parameters */ -#define UVSCOM_DATA_MASK 0x03 -#define UVSCOM_DATA_BIT_8 0x03 -#define UVSCOM_DATA_BIT_7 0x02 -#define UVSCOM_DATA_BIT_6 0x01 -#define UVSCOM_DATA_BIT_5 0x00 - -#define UVSCOM_STOP_MASK 0x04 -#define UVSCOM_STOP_BIT_2 0x04 -#define UVSCOM_STOP_BIT_1 0x00 - -#define UVSCOM_PARITY_MASK 0x18 -#define UVSCOM_PARITY_EVEN 0x18 -#if 0 -#define UVSCOM_PARITY_UNK 0x10 -#endif -#define UVSCOM_PARITY_ODD 0x08 -#define UVSCOM_PARITY_NONE 0x00 - -/* Status bits */ -#define UVSCOM_TXRDY 0x04 -#define UVSCOM_RXRDY 0x01 - -#define UVSCOM_DCD 0x08 -#define UVSCOM_NOCARD 0x04 -#define UVSCOM_DSR 0x02 -#define UVSCOM_CTS 0x01 -#define UVSCOM_USTAT_MASK (UVSCOM_NOCARD | UVSCOM_DSR | UVSCOM_CTS) - -struct uvscom_softc { - struct ucom_softc sc_ucom; - - int sc_iface_number;/* interface number */ - - usbd_interface_handle sc_intr_iface; /* interrupt interface */ - int sc_intr_number; /* interrupt number */ - usbd_pipe_handle sc_intr_pipe; /* interrupt pipe */ - u_char *sc_intr_buf; /* interrupt buffer */ - int sc_isize; - - u_char sc_dtr; /* current DTR state */ - u_char sc_rts; /* current RTS state */ - - u_char sc_lsr; /* Local status register */ - u_char sc_msr; /* uvscom status register */ - - uint16_t sc_lcr; /* Line control */ - u_char sc_usr; /* unit status */ -}; - -/* - * These are the maximum number of bytes transferred per frame. - * The output buffer size cannot be increased due to the size encoding. - */ -#define UVSCOMIBUFSIZE 512 -#define UVSCOMOBUFSIZE 64 - -static usbd_status uvscom_shutdown(struct uvscom_softc *); -static usbd_status uvscom_reset(struct uvscom_softc *); -static usbd_status uvscom_set_line_coding(struct uvscom_softc *, - uint16_t, uint16_t); -static usbd_status uvscom_set_line(struct uvscom_softc *, uint16_t); -static usbd_status uvscom_set_crtscts(struct uvscom_softc *); -static void uvscom_get_status(void *, int, u_char *, u_char *); -static void uvscom_dtr(struct uvscom_softc *, int); -static void uvscom_rts(struct uvscom_softc *, int); -static void uvscom_break(struct uvscom_softc *, int); - -static void uvscom_set(void *, int, int, int); -static void uvscom_intr(usbd_xfer_handle, usbd_private_handle, usbd_status); -#if 0 /* TODO */ -static int uvscom_ioctl(void *, int, u_long, caddr_t, int, struct thread *); -#endif -static int uvscom_param(void *, int, struct termios *); -static int uvscom_open(void *, int); -static void uvscom_close(void *, int); - -struct ucom_callback uvscom_callback = { - uvscom_get_status, - uvscom_set, - uvscom_param, - NULL, /* uvscom_ioctl, TODO */ - uvscom_open, - uvscom_close, - NULL, - NULL -}; - -static const struct usb_devno uvscom_devs [] = { - { USB_DEVICE(0x05db, 0x0003) }, /* SUNTAC U-Cable type D2 */ - { USB_DEVICE(0x05db, 0x0005) }, /* SUNTAC U-Cable type P1 */ - { USB_DEVICE(0x05db, 0x0009) }, /* SUNTAC Slipper U */ - { USB_DEVICE(0x05db, 0x000a) }, /* SUNTAC Ir-Trinity */ - { USB_DEVICE(0x05db, 0x0011) }, /* SUNTAC U-Cable type */ -}; - -static device_probe_t uvscom_match; -static device_attach_t uvscom_attach; -static device_detach_t uvscom_detach; - -static device_method_t uvscom_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, uvscom_match), - DEVMETHOD(device_attach, uvscom_attach), - DEVMETHOD(device_detach, uvscom_detach), - DEVMETHOD_END -}; - -static driver_t uvscom_driver = { - "ucom", - uvscom_methods, - sizeof (struct uvscom_softc) -}; - -DRIVER_MODULE(uvscom, uhub, uvscom_driver, ucom_devclass, usbd_driver_load, NULL); -MODULE_DEPEND(uvscom, ucom, UCOM_MINVER, UCOM_PREFVER, UCOM_MAXVER); -MODULE_VERSION(uvscom, UVSCOM_MODVER); - -static int -uvscom_match(device_t self) -{ - struct usb_attach_arg *uaa = device_get_ivars(self); - - if (uaa->iface != NULL) - return (UMATCH_NONE); - - return (usb_lookup(uvscom_devs, uaa->vendor, uaa->product) != NULL ? - UMATCH_VENDOR_PRODUCT : UMATCH_NONE); -} - -static int -uvscom_attach(device_t self) -{ - struct uvscom_softc *sc = device_get_softc(self); - struct usb_attach_arg *uaa = device_get_ivars(self); - usbd_device_handle dev = uaa->device; - struct ucom_softc *ucom; - usb_config_descriptor_t *cdesc; - usb_interface_descriptor_t *id; - usb_endpoint_descriptor_t *ed; - const char *devname; - usbd_status err; - int i; - - ucom = &sc->sc_ucom; - - bzero(sc, sizeof (struct uvscom_softc)); - - ucom->sc_dev = self; - ucom->sc_udev = dev; - ucom->sc_iface = uaa->iface; - - devname = device_get_nameunit(ucom->sc_dev); - - DPRINTF(("uvscom attach: sc = %p\n", sc)); - - /* initialize endpoints */ - ucom->sc_bulkin_no = ucom->sc_bulkout_no = -1; - sc->sc_intr_number = -1; - sc->sc_intr_pipe = NULL; - - /* Move the device into the configured state. */ - err = usbd_set_config_index(dev, UVSCOM_CONFIG_INDEX, 1); - if (err) { - kprintf("%s: failed to set configuration, err=%s\n", - devname, usbd_errstr(err)); - goto error; - } - - /* get the config descriptor */ - cdesc = usbd_get_config_descriptor(ucom->sc_udev); - - if (cdesc == NULL) { - kprintf("%s: failed to get configuration descriptor\n", - device_get_nameunit(ucom->sc_dev)); - goto error; - } - - /* get the common interface */ - err = usbd_device2interface_handle(dev, UVSCOM_IFACE_INDEX, - &ucom->sc_iface); - if (err) { - kprintf("%s: failed to get interface, err=%s\n", - devname, usbd_errstr(err)); - goto error; - } - - id = usbd_get_interface_descriptor(ucom->sc_iface); - sc->sc_iface_number = id->bInterfaceNumber; - - /* Find endpoints */ - for (i = 0; i < id->bNumEndpoints; i++) { - ed = usbd_interface2endpoint_descriptor(ucom->sc_iface, i); - if (ed == NULL) { - kprintf("%s: no endpoint descriptor for %d\n", - device_get_nameunit(ucom->sc_dev), i); - goto error; - } - - if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && - UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) { - ucom->sc_bulkin_no = ed->bEndpointAddress; - } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT && - UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) { - ucom->sc_bulkout_no = ed->bEndpointAddress; - } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && - UE_GET_XFERTYPE(ed->bmAttributes) == UE_INTERRUPT) { - sc->sc_intr_number = ed->bEndpointAddress; - sc->sc_isize = UGETW(ed->wMaxPacketSize); - } - } - - if (ucom->sc_bulkin_no == -1) { - kprintf("%s: Could not find data bulk in\n", - device_get_nameunit(ucom->sc_dev)); - goto error; - } - if (ucom->sc_bulkout_no == -1) { - kprintf("%s: Could not find data bulk out\n", - device_get_nameunit(ucom->sc_dev)); - goto error; - } - if (sc->sc_intr_number == -1) { - kprintf("%s: Could not find interrupt in\n", - device_get_nameunit(ucom->sc_dev)); - goto error; - } - - sc->sc_dtr = sc->sc_rts = 0; - sc->sc_lcr = UVSCOM_LINE_INIT; - - ucom->sc_parent = sc; - ucom->sc_portno = UCOM_UNK_PORTNO; - /* bulkin, bulkout set above */ - ucom->sc_ibufsize = UVSCOMIBUFSIZE; - ucom->sc_obufsize = UVSCOMOBUFSIZE; - ucom->sc_ibufsizepad = UVSCOMIBUFSIZE; - ucom->sc_opkthdrlen = 0; - ucom->sc_callback = &uvscom_callback; - - err = uvscom_reset(sc); - - if (err) { - kprintf("%s: reset failed, %s\n", device_get_nameunit(ucom->sc_dev), - usbd_errstr(err)); - goto error; - } - - DPRINTF(("uvscom: in = 0x%x out = 0x%x intr = 0x%x\n", - ucom->sc_bulkin_no, ucom->sc_bulkout_no, sc->sc_intr_number)); - - ucom_attach(&sc->sc_ucom); - - return 0; - -error: - ucom->sc_dying = 1; - return ENXIO; -} - -static int -uvscom_detach(device_t self) -{ - struct uvscom_softc *sc = device_get_softc(self); - int rv = 0; - - DPRINTF(("uvscom_detach: sc = %p\n", sc)); - - sc->sc_ucom.sc_dying = 1; - - if (sc->sc_intr_pipe != NULL) { - usbd_abort_pipe(sc->sc_intr_pipe); - usbd_close_pipe(sc->sc_intr_pipe); - kfree(sc->sc_intr_buf, M_USBDEV); - sc->sc_intr_pipe = NULL; - } - - rv = ucom_detach(&sc->sc_ucom); - - return (rv); -} - -static usbd_status -uvscom_readstat(struct uvscom_softc *sc) -{ - usb_device_request_t req; - usbd_status err; - uint16_t r; - - DPRINTF(("%s: send readstat\n", device_get_nameunit(sc->sc_ucom.sc_dev))); - - req.bmRequestType = UT_READ_VENDOR_DEVICE; - req.bRequest = UVSCOM_READ_STATUS; - USETW(req.wValue, 0); - USETW(req.wIndex, 0); - USETW(req.wLength, 2); - - err = usbd_do_request(sc->sc_ucom.sc_udev, &req, &r); - if (err) { - kprintf("%s: uvscom_readstat: %s\n", - device_get_nameunit(sc->sc_ucom.sc_dev), usbd_errstr(err)); - return (err); - } - - DPRINTF(("%s: uvscom_readstat: r = %d\n", - device_get_nameunit(sc->sc_ucom.sc_dev), r)); - - return (USBD_NORMAL_COMPLETION); -} - -static usbd_status -uvscom_shutdown(struct uvscom_softc *sc) -{ - usb_device_request_t req; - usbd_status err; - - DPRINTF(("%s: send shutdown\n", device_get_nameunit(sc->sc_ucom.sc_dev))); - - req.bmRequestType = UT_WRITE_VENDOR_DEVICE; - req.bRequest = UVSCOM_SHUTDOWN; - USETW(req.wValue, 0); - USETW(req.wIndex, 0); - USETW(req.wLength, 0); - - err = usbd_do_request(sc->sc_ucom.sc_udev, &req, NULL); - if (err) { - kprintf("%s: uvscom_shutdown: %s\n", - device_get_nameunit(sc->sc_ucom.sc_dev), usbd_errstr(err)); - return (err); - } - - return (USBD_NORMAL_COMPLETION); -} - -static usbd_status -uvscom_reset(struct uvscom_softc *sc) -{ - DPRINTF(("%s: uvscom_reset\n", device_get_nameunit(sc->sc_ucom.sc_dev))); - - return (USBD_NORMAL_COMPLETION); -} - -static usbd_status -uvscom_set_crtscts(struct uvscom_softc *sc) -{ - DPRINTF(("%s: uvscom_set_crtscts\n", device_get_nameunit(sc->sc_ucom.sc_dev))); - - return (USBD_NORMAL_COMPLETION); -} - -static usbd_status -uvscom_set_line(struct uvscom_softc *sc, uint16_t line) -{ - usb_device_request_t req; - usbd_status err; - - DPRINTF(("%s: uvscom_set_line: %04x\n", - device_get_nameunit(sc->sc_ucom.sc_dev), line)); - - req.bmRequestType = UT_WRITE_VENDOR_DEVICE; - req.bRequest = UVSCOM_LINE_CTL; - USETW(req.wValue, line); - USETW(req.wIndex, 0); - USETW(req.wLength, 0); - - err = usbd_do_request(sc->sc_ucom.sc_udev, &req, NULL); - if (err) { - kprintf("%s: uvscom_set_line: %s\n", - device_get_nameunit(sc->sc_ucom.sc_dev), usbd_errstr(err)); - return (err); - } - - return (USBD_NORMAL_COMPLETION); -} - -static usbd_status -uvscom_set_line_coding(struct uvscom_softc *sc, uint16_t lsp, uint16_t ls) -{ - usb_device_request_t req; - usbd_status err; - - DPRINTF(("%s: uvscom_set_line_coding: %02x %02x\n", - device_get_nameunit(sc->sc_ucom.sc_dev), lsp, ls)); - - req.bmRequestType = UT_WRITE_VENDOR_DEVICE; - req.bRequest = UVSCOM_SET_SPEED; - USETW(req.wValue, lsp); - USETW(req.wIndex, 0); - USETW(req.wLength, 0); - - err = usbd_do_request(sc->sc_ucom.sc_udev, &req, NULL); - if (err) { - kprintf("%s: uvscom_set_line_coding: %s\n", - device_get_nameunit(sc->sc_ucom.sc_dev), usbd_errstr(err)); - return (err); - } - - req.bmRequestType = UT_WRITE_VENDOR_DEVICE; - req.bRequest = UVSCOM_SET_PARAM; - USETW(req.wValue, ls); - USETW(req.wIndex, 0); - USETW(req.wLength, 0); - - err = usbd_do_request(sc->sc_ucom.sc_udev, &req, NULL); - if (err) { - kprintf("%s: uvscom_set_line_coding: %s\n", - device_get_nameunit(sc->sc_ucom.sc_dev), usbd_errstr(err)); - return (err); - } - - return (USBD_NORMAL_COMPLETION); -} - -static void -uvscom_dtr(struct uvscom_softc *sc, int onoff) -{ - DPRINTF(("%s: uvscom_dtr: onoff = %d\n", - device_get_nameunit(sc->sc_ucom.sc_dev), onoff)); - - if (sc->sc_dtr == onoff) - return; /* no change */ - - sc->sc_dtr = onoff; - - if (onoff) - SET(sc->sc_lcr, UVSCOM_DTR); - else - CLR(sc->sc_lcr, UVSCOM_DTR); - - uvscom_set_line(sc, sc->sc_lcr); -} - -static void -uvscom_rts(struct uvscom_softc *sc, int onoff) -{ - DPRINTF(("%s: uvscom_rts: onoff = %d\n", - device_get_nameunit(sc->sc_ucom.sc_dev), onoff)); - - if (sc->sc_rts == onoff) - return; /* no change */ - - sc->sc_rts = onoff; - - if (onoff) - SET(sc->sc_lcr, UVSCOM_RTS); - else - CLR(sc->sc_lcr, UVSCOM_RTS); - - uvscom_set_line(sc, sc->sc_lcr); -} - -static void -uvscom_break(struct uvscom_softc *sc, int onoff) -{ - DPRINTF(("%s: uvscom_break: onoff = %d\n", - device_get_nameunit(sc->sc_ucom.sc_dev), onoff)); - - if (onoff) - uvscom_set_line(sc, SET(sc->sc_lcr, UVSCOM_BREAK)); -} - -static void -uvscom_set(void *addr, int portno, int reg, int onoff) -{ - struct uvscom_softc *sc = addr; - - switch (reg) { - case UCOM_SET_DTR: - uvscom_dtr(sc, onoff); - break; - case UCOM_SET_RTS: - uvscom_rts(sc, onoff); - break; - case UCOM_SET_BREAK: - uvscom_break(sc, onoff); - break; - default: - break; - } -} - -static int -uvscom_param(void *addr, int portno, struct termios *t) -{ - struct uvscom_softc *sc = addr; - usbd_status err; - uint16_t lsp; - uint16_t ls; - - DPRINTF(("%s: uvscom_param: sc = %p\n", - device_get_nameunit(sc->sc_ucom.sc_dev), sc)); - - ls = 0; - - switch (t->c_ospeed) { - case B150: - lsp = UVSCOM_SPEED_150BPS; - break; - case B300: - lsp = UVSCOM_SPEED_300BPS; - break; - case B600: - lsp = UVSCOM_SPEED_600BPS; - break; - case B1200: - lsp = UVSCOM_SPEED_1200BPS; - break; - case B2400: - lsp = UVSCOM_SPEED_2400BPS; - break; - case B4800: - lsp = UVSCOM_SPEED_4800BPS; - break; - case B9600: - lsp = UVSCOM_SPEED_9600BPS; - break; - case B19200: - lsp = UVSCOM_SPEED_19200BPS; - break; - case B38400: - lsp = UVSCOM_SPEED_38400BPS; - break; - case B57600: - lsp = UVSCOM_SPEED_57600BPS; - break; - case B115200: - lsp = UVSCOM_SPEED_115200BPS; - break; - default: - return (EIO); - } - - if (ISSET(t->c_cflag, CSTOPB)) - SET(ls, UVSCOM_STOP_BIT_2); - else - SET(ls, UVSCOM_STOP_BIT_1); - - if (ISSET(t->c_cflag, PARENB)) { - if (ISSET(t->c_cflag, PARODD)) - SET(ls, UVSCOM_PARITY_ODD); - else - SET(ls, UVSCOM_PARITY_EVEN); - } else - SET(ls, UVSCOM_PARITY_NONE); - - switch (ISSET(t->c_cflag, CSIZE)) { - case CS5: - SET(ls, UVSCOM_DATA_BIT_5); - break; - case CS6: - SET(ls, UVSCOM_DATA_BIT_6); - break; - case CS7: - SET(ls, UVSCOM_DATA_BIT_7); - break; - case CS8: - SET(ls, UVSCOM_DATA_BIT_8); - break; - default: - return (EIO); - } - - err = uvscom_set_line_coding(sc, lsp, ls); - if (err) - return (EIO); - - if (ISSET(t->c_cflag, CRTSCTS)) { - err = uvscom_set_crtscts(sc); - if (err) - return (EIO); - } - - return (0); -} - -static int -uvscom_open(void *addr, int portno) -{ - struct uvscom_softc *sc = addr; - int err; - int i; - - if (sc->sc_ucom.sc_dying) - return (ENXIO); - - DPRINTF(("uvscom_open: sc = %p\n", sc)); - - if (sc->sc_intr_number != -1 && sc->sc_intr_pipe == NULL) { - DPRINTF(("uvscom_open: open interrupt pipe.\n")); - - sc->sc_usr = 0; /* clear unit status */ - - err = uvscom_readstat(sc); - if (err) { - DPRINTF(("%s: uvscom_open: readstat faild\n", - device_get_nameunit(sc->sc_ucom.sc_dev))); - return (ENXIO); - } - - sc->sc_intr_buf = kmalloc(sc->sc_isize, M_USBDEV, M_WAITOK); - err = usbd_open_pipe_intr(sc->sc_ucom.sc_iface, - sc->sc_intr_number, - USBD_SHORT_XFER_OK, - &sc->sc_intr_pipe, - sc, - sc->sc_intr_buf, - sc->sc_isize, - uvscom_intr, - UVSCOM_INTR_INTERVAL); - if (err) { - kprintf("%s: cannot open interrupt pipe (addr %d)\n", - device_get_nameunit(sc->sc_ucom.sc_dev), - sc->sc_intr_number); - return (ENXIO); - } - } else { - DPRINTF(("uvscom_open: did not open interrupt pipe.\n")); - } - - if ((sc->sc_usr & UVSCOM_USTAT_MASK) == 0) { - /* unit is not ready */ - - for (i = UVSCOM_UNIT_WAIT; i > 0; --i) { - tsleep(&err, 0, "uvsop", hz); /* XXX */ - if (ISSET(sc->sc_usr, UVSCOM_USTAT_MASK)) - break; - } - if (i == 0) { - DPRINTF(("%s: unit is not ready\n", - device_get_nameunit(sc->sc_ucom.sc_dev))); - return (ENXIO); - } - - /* check PC card was inserted */ - if (ISSET(sc->sc_usr, UVSCOM_NOCARD)) { - DPRINTF(("%s: no card\n", - device_get_nameunit(sc->sc_ucom.sc_dev))); - return (ENXIO); - } - } - - return (0); -} - -static void -uvscom_close(void *addr, int portno) -{ - struct uvscom_softc *sc = addr; - int err; - - if (sc->sc_ucom.sc_dying) - return; - - DPRINTF(("uvscom_close: close\n")); - - uvscom_shutdown(sc); - - if (sc->sc_intr_pipe != NULL) { - err = usbd_abort_pipe(sc->sc_intr_pipe); - if (err) - kprintf("%s: abort interrupt pipe failed: %s\n", - device_get_nameunit(sc->sc_ucom.sc_dev), - usbd_errstr(err)); - err = usbd_close_pipe(sc->sc_intr_pipe); - if (err) - kprintf("%s: close interrupt pipe failed: %s\n", - device_get_nameunit(sc->sc_ucom.sc_dev), - usbd_errstr(err)); - kfree(sc->sc_intr_buf, M_USBDEV); - sc->sc_intr_pipe = NULL; - } -} - -static void -uvscom_intr(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status) -{ - struct uvscom_softc *sc = priv; - u_char *buf = sc->sc_intr_buf; - u_char pstatus; - - if (sc->sc_ucom.sc_dying) - return; - - if (status != USBD_NORMAL_COMPLETION) { - if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) - return; - - kprintf("%s: uvscom_intr: abnormal status: %s\n", - device_get_nameunit(sc->sc_ucom.sc_dev), - usbd_errstr(status)); - usbd_clear_endpoint_stall_async(sc->sc_intr_pipe); - return; - } - - DPRINTFN(2, ("%s: uvscom status = %02x %02x\n", - device_get_nameunit(sc->sc_ucom.sc_dev), buf[0], buf[1])); - - sc->sc_lsr = sc->sc_msr = 0; - sc->sc_usr = buf[1]; - - pstatus = buf[0]; - if (ISSET(pstatus, UVSCOM_TXRDY)) - SET(sc->sc_lsr, ULSR_TXRDY); - if (ISSET(pstatus, UVSCOM_RXRDY)) - SET(sc->sc_lsr, ULSR_RXRDY); - - pstatus = buf[1]; - if (ISSET(pstatus, UVSCOM_CTS)) - SET(sc->sc_msr, UMSR_CTS); - if (ISSET(pstatus, UVSCOM_DSR)) - SET(sc->sc_msr, UMSR_DSR); - if (ISSET(pstatus, UVSCOM_DCD)) - SET(sc->sc_msr, UMSR_DCD); - - ucom_status_change(&sc->sc_ucom); -} - -static void -uvscom_get_status(void *addr, int portno, u_char *lsr, u_char *msr) -{ - struct uvscom_softc *sc = addr; - - if (lsr != NULL) - *lsr = sc->sc_lsr; - if (msr != NULL) - *msr = sc->sc_msr; -} - -#if 0 /* TODO */ -static int -uvscom_ioctl(void *addr, int portno, u_long cmd, caddr_t data, int flag, - struct thread *p) -{ - struct uvscom_softc *sc = addr; - int error = 0; - - if (sc->sc_ucom.sc_dying) - return (EIO); - - DPRINTF(("uvscom_ioctl: cmd = 0x%08lx\n", cmd)); - - switch (cmd) { - case TIOCNOTTY: - case TIOCMGET: - case TIOCMSET: - break; - - default: - DPRINTF(("uvscom_ioctl: unknown\n")); - error = ENOTTY; - break; - } - - return (error); -} -#endif diff --git a/sys/emulation/ndis/Makefile b/sys/emulation/ndis/Makefile index f1c867a6e8..da0bc43857 100644 --- a/sys/emulation/ndis/Makefile +++ b/sys/emulation/ndis/Makefile @@ -2,9 +2,9 @@ KMOD= ndis SRCS= subr_pe.c subr_ndis.c subr_hal.c subr_ntoskrnl.c kern_ndis.c -SRCS+= kern_windrv.c +SRCS+= kern_windrv.c subr_u4bd.c SRCS+= device_if.h bus_if.h pci_if.h -SRCS+= opt_usb.h use_oldusb.h +SRCS+= opt_usb.h .if ${MACHINE_ARCH} == "x86_64" SRCS+= winx64_wrap.S @@ -14,10 +14,4 @@ SRCS+= winx64_wrap.S SRCS+= winx32_wrap.S .endif -.if !defined(WANT_OLDUSB) -SRCS+= subr_u4bd.c -.else -SRCS+= subr_usbd.c -.endif - .include diff --git a/sys/emulation/ndis/kern_ndis.c b/sys/emulation/ndis/kern_ndis.c index a57a763c5e..f5c72a2482 100644 --- a/sys/emulation/ndis/kern_ndis.c +++ b/sys/emulation/ndis/kern_ndis.c @@ -32,8 +32,6 @@ * $FreeBSD: src/sys/compat/ndis/kern_ndis.c,v 1.111 2011/02/23 21:45:28 brucec Exp $ */ -#include "use_oldusb.h" - #include #include #include @@ -65,13 +63,8 @@ #include #include -#if NOLDUSB == 0 #include #include -#else -#include -#include -#endif #include #include @@ -79,11 +72,7 @@ #include #include #include -#if NOLDUSB == 0 #include -#else -#include -#endif #include #define NDIS_DUMMY_PATH "\\\\some\\bogus\\path" diff --git a/sys/emulation/ndis/kern_windrv.c b/sys/emulation/ndis/kern_windrv.c index 4caeb1b1ee..6ef6421ea0 100644 --- a/sys/emulation/ndis/kern_windrv.c +++ b/sys/emulation/ndis/kern_windrv.c @@ -32,8 +32,6 @@ * $FreeBSD: src/sys/compat/ndis/kern_windrv.c,v 1.21 2010/11/22 20:46:38 bschmidt Exp $ */ -#include "use_oldusb.h" - #include #include #include @@ -56,13 +54,8 @@ #include #endif -#if NOLDUSB == 0 #include #include -#else -#include -#include -#endif #include #include @@ -70,11 +63,7 @@ #include #include #include -#if NOLDUSB == 0 #include -#else -#include -#endif static struct lock drvdb_lock; static STAILQ_HEAD(drvdb, drvdb_ent) drvdb_head; diff --git a/sys/emulation/ndis/ntoskrnl_var.h b/sys/emulation/ndis/ntoskrnl_var.h index 6801f173ed..7b96261e7b 100644 --- a/sys/emulation/ndis/ntoskrnl_var.h +++ b/sys/emulation/ndis/ntoskrnl_var.h @@ -35,8 +35,6 @@ #ifndef _NTOSKRNL_VAR_H_ #define _NTOSKRNL_VAR_H_ -#include "use_oldusb.h" - #define MTX_NTOSKRNL_SPIN_LOCK "NDIS thread lock" /* @@ -1068,11 +1066,7 @@ struct irp { union { kapc irp_apc; struct { -#if NOLDUSB == 0 void *irp_ep; -#else - void *irp_xfer; -#endif void *irp_dev; } irp_usb; } irp_misc; @@ -1084,11 +1078,7 @@ struct irp { #define irp_pkttype s2.u2.irp_pkttype #define IRP_NDIS_DEV(irp) (irp)->irp_tail.irp_misc.irp_usb.irp_dev -#if NOLDUSB == 0 #define IRP_NDISUSB_EP(irp) (irp)->irp_tail.irp_misc.irp_usb.irp_ep -#else -#define IRP_NDISUSB_XFER(irp) (irp)->irp_tail.irp_misc.irp_usb.irp_xfer -#endif typedef struct irp irp; diff --git a/sys/emulation/ndis/subr_ndis.c b/sys/emulation/ndis/subr_ndis.c index 0dd8a7b1ac..abbeafc63c 100644 --- a/sys/emulation/ndis/subr_ndis.c +++ b/sys/emulation/ndis/subr_ndis.c @@ -47,8 +47,6 @@ * expects. */ -#include "use_oldusb.h" - #include #include #include @@ -91,13 +89,8 @@ #include #include -#if NOLDUSB == 0 #include #include -#else -#include -#include -#endif #include #include diff --git a/sys/emulation/ndis/subr_usbd.c b/sys/emulation/ndis/subr_usbd.c deleted file mode 100644 index bf1c8b784f..0000000000 --- a/sys/emulation/ndis/subr_usbd.c +++ /dev/null @@ -1,1207 +0,0 @@ -/*- - * Copyright (c) 2005 - * Bill Paul . 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. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Bill Paul. - * 4. Neither the name of the author nor the names of any co-contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY Bill Paul 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 Bill Paul OR THE VOICES IN HIS HEAD - * 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: src/sys/compat/ndis/subr_usbd.c,v 1.6 2009/02/24 18:09:31 rdivacky Exp $ - */ - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -static driver_object usbd_driver; - -static int32_t usbd_func_bulkintr(irp *); -static int32_t usbd_func_vendorclass(irp *); -static int32_t usbd_func_selconf(irp *); -static int32_t usbd_func_abort_pipe(irp *); -static int32_t usbd_func_getdesc(irp *); -static usbd_status usbd_get_desc_ndis(usbd_device_handle, int, int, int, - void *, int *); -static union usbd_urb *usbd_geturb(irp *); -static usbd_status usbd_init_ndispipe(irp *, usb_endpoint_descriptor_t *); -static usbd_xfer_handle usbd_init_ndisxfer(irp *, usb_endpoint_descriptor_t *, - void *, uint32_t); -static int32_t usbd_iodispatch(device_object *, irp *); -static int32_t usbd_ioinvalid(device_object *, irp *); -static int32_t usbd_pnp(device_object *, irp *); -static int32_t usbd_power(device_object *, irp *); -static void usbd_irpcancel(device_object *, irp *); -static void usbd_irpcancel_cb(void *); -static int32_t usbd_submit_urb(irp *); -static int32_t usbd_urb2nt(int32_t); -static void usbd_xfereof(usbd_xfer_handle, usbd_private_handle, - usbd_status); -static void usbd_xferadd(usbd_xfer_handle, usbd_private_handle, - usbd_status); -static void usbd_xfertask(device_object *, void *); -static void dummy(void); - -static union usbd_urb *USBD_CreateConfigurationRequestEx( - usb_config_descriptor_t *, - struct usbd_interface_list_entry *); -static union usbd_urb *USBD_CreateConfigurationRequest( - usb_config_descriptor_t *, - uint16_t *); -static void USBD_GetUSBDIVersion(usbd_version_info *); -static usb_interface_descriptor_t *USBD_ParseConfigurationDescriptorEx( - usb_config_descriptor_t *, void *, int32_t, int32_t, - int32_t, int32_t, int32_t); -static usb_interface_descriptor_t *USBD_ParseConfigurationDescriptor( - usb_config_descriptor_t *, uint8_t, uint8_t); - -/* - * We need to wrap these functions because these need `context switch' from - * Windows to UNIX before it's called. - */ -static funcptr usbd_iodispatch_wrap; -static funcptr usbd_ioinvalid_wrap; -static funcptr usbd_pnp_wrap; -static funcptr usbd_power_wrap; -static funcptr usbd_irpcancel_wrap; -static funcptr usbd_xfertask_wrap; - -int -usbd_libinit(void) -{ - image_patch_table *patch; - int i; - - patch = usbd_functbl; - while (patch->ipt_func != NULL) { - windrv_wrap((funcptr)patch->ipt_func, - (funcptr *)&patch->ipt_wrap, - patch->ipt_argcnt, patch->ipt_ftype); - patch++; - } - - windrv_wrap((funcptr)usbd_ioinvalid, - &usbd_ioinvalid_wrap, 2, WINDRV_WRAP_STDCALL); - windrv_wrap((funcptr)usbd_iodispatch, - &usbd_iodispatch_wrap, 2, WINDRV_WRAP_STDCALL); - windrv_wrap((funcptr)usbd_pnp, - &usbd_pnp_wrap, 2, WINDRV_WRAP_STDCALL); - windrv_wrap((funcptr)usbd_power, - &usbd_power_wrap, 2, WINDRV_WRAP_STDCALL); - windrv_wrap((funcptr)usbd_irpcancel, - &usbd_irpcancel_wrap, 2, WINDRV_WRAP_STDCALL); - windrv_wrap((funcptr)usbd_xfertask, - &usbd_xfertask_wrap, 2, WINDRV_WRAP_STDCALL); - - /* Create a fake USB driver instance. */ - - windrv_bus_attach(&usbd_driver, "USB Bus"); - - /* Set up our dipatch routine. */ - for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++) - usbd_driver.dro_dispatch[i] = - (driver_dispatch)usbd_ioinvalid_wrap; - - usbd_driver.dro_dispatch[IRP_MJ_INTERNAL_DEVICE_CONTROL] = - (driver_dispatch)usbd_iodispatch_wrap; - usbd_driver.dro_dispatch[IRP_MJ_DEVICE_CONTROL] = - (driver_dispatch)usbd_iodispatch_wrap; - usbd_driver.dro_dispatch[IRP_MJ_POWER] = - (driver_dispatch)usbd_power_wrap; - usbd_driver.dro_dispatch[IRP_MJ_PNP] = - (driver_dispatch)usbd_pnp_wrap; - - return(0); -} - -int -usbd_libfini(void) -{ - image_patch_table *patch; - - patch = usbd_functbl; - while (patch->ipt_func != NULL) { - windrv_unwrap(patch->ipt_wrap); - patch++; - } - - windrv_unwrap(usbd_ioinvalid_wrap); - windrv_unwrap(usbd_iodispatch_wrap); - windrv_unwrap(usbd_pnp_wrap); - windrv_unwrap(usbd_power_wrap); - windrv_unwrap(usbd_irpcancel_wrap); - windrv_unwrap(usbd_xfertask_wrap); - - kfree(usbd_driver.dro_drivername.us_buf, M_DEVBUF); - - return (0); -} - -static int32_t -usbd_iodispatch(device_object *dobj, irp *ip) -{ - device_t dev = dobj->do_devext; - int32_t status; - struct io_stack_location *irp_sl; - - irp_sl = IoGetCurrentIrpStackLocation(ip); - switch (irp_sl->isl_parameters.isl_ioctl.isl_iocode) { - case IOCTL_INTERNAL_USB_SUBMIT_URB: - IRP_NDIS_DEV(ip) = dev; - - status = usbd_submit_urb(ip); - break; - default: - device_printf(dev, "ioctl 0x%x isn't supported\n", - irp_sl->isl_parameters.isl_ioctl.isl_iocode); - status = USBD_STATUS_NOT_SUPPORTED; - break; - } - - if (status == USBD_STATUS_PENDING) - return (STATUS_PENDING); - - ip->irp_iostat.isb_status = usbd_urb2nt(status); - if (status != USBD_STATUS_SUCCESS) - ip->irp_iostat.isb_info = 0; - return (ip->irp_iostat.isb_status); -} - -static int32_t -usbd_ioinvalid(device_object *dobj, irp *ip) -{ - device_t dev = dobj->do_devext; - struct io_stack_location *irp_sl; - - irp_sl = IoGetCurrentIrpStackLocation(ip); - device_printf(dev, "invalid I/O dispatch %d:%d\n", irp_sl->isl_major, - irp_sl->isl_minor); - - ip->irp_iostat.isb_status = STATUS_FAILURE; - ip->irp_iostat.isb_info = 0; - - IoCompleteRequest(ip, IO_NO_INCREMENT); - - return (STATUS_FAILURE); -} - -static int32_t -usbd_pnp(device_object *dobj, irp *ip) -{ - device_t dev = dobj->do_devext; - struct io_stack_location *irp_sl; - - irp_sl = IoGetCurrentIrpStackLocation(ip); - device_printf(dev, "%s: unsupported I/O dispatch %d:%d\n", - __func__, irp_sl->isl_major, irp_sl->isl_minor); - - ip->irp_iostat.isb_status = STATUS_FAILURE; - ip->irp_iostat.isb_info = 0; - - IoCompleteRequest(ip, IO_NO_INCREMENT); - - return (STATUS_FAILURE); -} - -static int32_t -usbd_power(device_object *dobj, irp *ip) -{ - device_t dev = dobj->do_devext; - struct io_stack_location *irp_sl; - - irp_sl = IoGetCurrentIrpStackLocation(ip); - device_printf(dev, "%s: unsupported I/O dispatch %d:%d\n", - __func__, irp_sl->isl_major, irp_sl->isl_minor); - - ip->irp_iostat.isb_status = STATUS_FAILURE; - ip->irp_iostat.isb_info = 0; - - IoCompleteRequest(ip, IO_NO_INCREMENT); - - return (STATUS_FAILURE); -} - -/* Convert USBD_STATUS to NTSTATUS */ -static int32_t -usbd_urb2nt(int32_t status) -{ - - switch (status) { - case USBD_STATUS_SUCCESS: - return (STATUS_SUCCESS); - case USBD_STATUS_DEVICE_GONE: - return (STATUS_DEVICE_NOT_CONNECTED); - case USBD_STATUS_PENDING: - return (STATUS_PENDING); - case USBD_STATUS_NOT_SUPPORTED: - return (STATUS_NOT_IMPLEMENTED); - case USBD_STATUS_NO_MEMORY: - return (STATUS_NO_MEMORY); - case USBD_STATUS_REQUEST_FAILED: - return (STATUS_NOT_SUPPORTED); - case USBD_STATUS_CANCELED: - return (STATUS_CANCELLED); - default: - break; - } - - return (STATUS_FAILURE); -} - -/* Convert FreeBSD's usbd_status to USBD_STATUS */ -static int32_t -usbd_usb2urb(int status) -{ - - switch (status) { - case USBD_NORMAL_COMPLETION: - return (USBD_STATUS_SUCCESS); - case USBD_IN_PROGRESS: - return (USBD_STATUS_PENDING); - case USBD_TIMEOUT: - return (USBD_STATUS_TIMEOUT); - case USBD_SHORT_XFER: - return (USBD_STATUS_ERROR_SHORT_TRANSFER); - case USBD_IOERROR: - return (USBD_STATUS_XACT_ERROR); - case USBD_NOMEM: - return (USBD_STATUS_NO_MEMORY); - case USBD_INVAL: - return (USBD_STATUS_REQUEST_FAILED); - case USBD_NOT_STARTED: - case USBD_TOO_DEEP: - case USBD_NO_POWER: - return (USBD_STATUS_DEVICE_GONE); - case USBD_CANCELLED: - return (USBD_STATUS_CANCELED); - default: - break; - } - - return (USBD_STATUS_NOT_SUPPORTED); -} - -static union usbd_urb * -usbd_geturb(irp *ip) -{ - struct io_stack_location *irp_sl; - - irp_sl = IoGetCurrentIrpStackLocation(ip); - - return (irp_sl->isl_parameters.isl_others.isl_arg1); -} - -static int32_t -usbd_submit_urb(irp *ip) -{ - device_t dev = IRP_NDIS_DEV(ip); - int32_t status; - union usbd_urb *urb; - - urb = usbd_geturb(ip); - /* - * In a case of URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER, - * USBD_URB_STATUS(urb) would be set at callback functions like - * usbd_intr() or usbd_xfereof(). - */ - switch (urb->uu_hdr.uuh_func) { - case URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER: - status = usbd_func_bulkintr(ip); - if (status != USBD_STATUS_SUCCESS && - status != USBD_STATUS_PENDING) - USBD_URB_STATUS(urb) = status; - break; - case URB_FUNCTION_VENDOR_DEVICE: - case URB_FUNCTION_VENDOR_INTERFACE: - case URB_FUNCTION_VENDOR_ENDPOINT: - case URB_FUNCTION_VENDOR_OTHER: - case URB_FUNCTION_CLASS_DEVICE: - case URB_FUNCTION_CLASS_INTERFACE: - case URB_FUNCTION_CLASS_ENDPOINT: - case URB_FUNCTION_CLASS_OTHER: - status = usbd_func_vendorclass(ip); - USBD_URB_STATUS(urb) = status; - break; - case URB_FUNCTION_SELECT_CONFIGURATION: - status = usbd_func_selconf(ip); - USBD_URB_STATUS(urb) = status; - break; - case URB_FUNCTION_ABORT_PIPE: - status = usbd_func_abort_pipe(ip); - USBD_URB_STATUS(urb) = status; - break; - case URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE: - status = usbd_func_getdesc(ip); - USBD_URB_STATUS(urb) = status; - break; - default: - device_printf(dev, "func 0x%x isn't supported\n", - urb->uu_hdr.uuh_func); - USBD_URB_STATUS(urb) = status = USBD_STATUS_NOT_SUPPORTED; - break; - } - - return (status); -} - -static int32_t -usbd_func_getdesc(irp *ip) -{ - device_t dev = IRP_NDIS_DEV(ip); - int actlen, i; - struct usb_attach_arg *uaa = device_get_ivars(dev); - struct usbd_urb_control_descriptor_request *ctldesc; - uint32_t len; - union usbd_urb *urb; - usb_config_descriptor_t cd, *cdp; - usbd_status status; - - get_mplock(); - - urb = usbd_geturb(ip); - ctldesc = &urb->uu_ctldesc; - if (ctldesc->ucd_desctype == UDESC_CONFIG) { - /* Get the short config descriptor. */ - status = usbd_get_config_desc(uaa->device, ctldesc->ucd_idx, - &cd); - if (status != USBD_NORMAL_COMPLETION) { - ctldesc->ucd_trans_buflen = 0; - rel_mplock(); - return usbd_usb2urb(status); - } - /* Get the full descriptor. Try a few times for slow devices. */ - len = MIN(ctldesc->ucd_trans_buflen, UGETW(cd.wTotalLength)); - for (i = 0; i < 3; i++) { - status = usbd_get_desc_ndis(uaa->device, - ctldesc->ucd_desctype, ctldesc->ucd_idx, - len, ctldesc->ucd_trans_buf, &actlen); - if (status == USBD_NORMAL_COMPLETION) - break; - usbd_delay_ms(uaa->device, 200); - } - if (status != USBD_NORMAL_COMPLETION) { - ctldesc->ucd_trans_buflen = 0; - rel_mplock(); - return usbd_usb2urb(status); - } - - cdp = (usb_config_descriptor_t *)ctldesc->ucd_trans_buf; - if (cdp->bDescriptorType != UDESC_CONFIG) { - device_printf(dev, "bad desc %d\n", - cdp->bDescriptorType); - status = USBD_INVAL; - } - } else if (ctldesc->ucd_desctype == UDESC_STRING) { - /* Try a few times for slow devices. */ - for (i = 0; i < 3; i++) { - status = usbd_get_string_desc(uaa->device, - (UDESC_STRING << 8) + ctldesc->ucd_idx, - ctldesc->ucd_langid, ctldesc->ucd_trans_buf, - &actlen); - if (actlen > ctldesc->ucd_trans_buflen) - panic("small string buffer for UDESC_STRING"); - if (status == USBD_NORMAL_COMPLETION) - break; - usbd_delay_ms(uaa->device, 200); - } - } else - status = usbd_get_desc_ndis(uaa->device, ctldesc->ucd_desctype, - ctldesc->ucd_idx, ctldesc->ucd_trans_buflen, - ctldesc->ucd_trans_buf, &actlen); - - if (status != USBD_NORMAL_COMPLETION) { - ctldesc->ucd_trans_buflen = 0; - rel_mplock(); - return usbd_usb2urb(status); - } - - ctldesc->ucd_trans_buflen = actlen; - ip->irp_iostat.isb_info = actlen; - - rel_mplock(); - - return (USBD_STATUS_SUCCESS); -} - -/* - * FIXME: at USB1, not USB2, framework, there's no a interface to get `actlen'. - * However, we need it!!! - */ -static usbd_status -usbd_get_desc_ndis(usbd_device_handle dev, int type, int index, int len, - void *desc, int *actlen) -{ - usb_device_request_t req; - - req.bmRequestType = UT_READ_DEVICE; - req.bRequest = UR_GET_DESCRIPTOR; - USETW2(req.wValue, type, index); - USETW(req.wIndex, 0); - USETW(req.wLength, len); - return usbd_do_request_flags_pipe(dev, dev->default_pipe, &req, desc, - 0, actlen, USBD_DEFAULT_TIMEOUT); -} - -static int32_t -usbd_func_selconf(irp *ip) -{ - device_t dev = IRP_NDIS_DEV(ip); - int i, j; - struct usb_attach_arg *uaa = device_get_ivars(dev); - struct usbd_interface_information *intf; - struct usbd_pipe_information *pipe; - struct usbd_urb_select_configuration *selconf; - union usbd_urb *urb; - usb_config_descriptor_t *conf; - usb_endpoint_descriptor_t *edesc; - usbd_device_handle udev = uaa->device; - usbd_interface_handle iface; - usbd_status ret; - - urb = usbd_geturb(ip); - - selconf = &urb->uu_selconf; - conf = selconf->usc_conf; - if (conf == NULL) { - device_printf(dev, "select configuration is NULL\n"); - return usbd_usb2urb(USBD_NORMAL_COMPLETION); - } - - if (conf->bConfigurationValue > NDISUSB_CONFIG_NO) - device_printf(dev, "warning: config_no is larger than default"); - - intf = &selconf->usc_intf; - for (i = 0; i < conf->bNumInterface && intf->uii_len > 0; i++) { - ret = usbd_device2interface_handle(uaa->device, - intf->uii_intfnum, &iface); - if (ret != USBD_NORMAL_COMPLETION) { - device_printf(dev, - "getting interface handle failed: %s\n", - usbd_errstr(ret)); - return usbd_usb2urb(ret); - } - - ret = usbd_set_interface(iface, intf->uii_altset); - if (ret != USBD_NORMAL_COMPLETION && ret != USBD_IN_USE) { - device_printf(dev, - "setting alternate interface failed: %s\n", - usbd_errstr(ret)); - return usbd_usb2urb(ret); - } - - for (j = 0; j < iface->idesc->bNumEndpoints; j++) { - if (j >= intf->uii_numeps) { - device_printf(dev, - "endpoint %d and above are ignored", - intf->uii_numeps); - break; - } - edesc = iface->endpoints[j].edesc; - pipe = &intf->uii_pipes[j]; - pipe->upi_handle = edesc; - pipe->upi_epaddr = edesc->bEndpointAddress; - pipe->upi_maxpktsize = UGETW(edesc->wMaxPacketSize); - pipe->upi_type = UE_GET_XFERTYPE(edesc->bmAttributes); - if (pipe->upi_type != UE_INTERRUPT) - continue; - - /* XXX we're following linux USB's interval policy. */ - if (udev->speed == USB_SPEED_LOW) - pipe->upi_interval = edesc->bInterval + 5; - else if (udev->speed == USB_SPEED_FULL) - pipe->upi_interval = edesc->bInterval; - else { - int k0 = 0, k1 = 1; - do { - k1 = k1 * 2; - k0 = k0 + 1; - } while (k1 < edesc->bInterval); - pipe->upi_interval = k0; - } - } - - intf = (struct usbd_interface_information *)(((char *)intf) + - intf->uii_len); - } - - return (USBD_STATUS_SUCCESS); -} - -static int32_t -usbd_func_abort_pipe(irp *ip) -{ - device_t dev = IRP_NDIS_DEV(ip); - struct ndis_softc *sc = device_get_softc(dev); - union usbd_urb *urb; - struct usbd_urb_bulk_or_intr_transfer *ubi; - usb_endpoint_descriptor_t *ep; - uint8_t irql; - usbd_status status; - - urb = usbd_geturb(ip); - ubi = &urb->uu_bulkintr; - ep = ubi->ubi_epdesc; - if (ep == NULL) - return (USBD_STATUS_INVALID_PIPE_HANDLE); - - KeRaiseIrql(DISPATCH_LEVEL, &irql); - status = usbd_abort_pipe(sc->ndisusb_ep[NDISUSB_ENDPT_BIN]); - if (status != USBD_NORMAL_COMPLETION) - device_printf(dev, "can't be canceld"); - KeLowerIrql(irql); - - return (USBD_STATUS_SUCCESS); -} - -static int32_t -usbd_func_vendorclass(irp *ip) -{ - device_t dev = IRP_NDIS_DEV(ip); - struct usb_attach_arg *uaa = device_get_ivars(dev); - struct usbd_urb_vendor_or_class_request *vcreq; - uint8_t type = 0; - union usbd_urb *urb; - usb_device_request_t req; - usbd_status status; - - urb = usbd_geturb(ip); - vcreq = &urb->uu_vcreq; - - switch (urb->uu_hdr.uuh_func) { - case URB_FUNCTION_CLASS_DEVICE: - type = UT_CLASS | UT_DEVICE; - break; - case URB_FUNCTION_CLASS_INTERFACE: - type = UT_CLASS | UT_INTERFACE; - break; - case URB_FUNCTION_CLASS_OTHER: - type = UT_CLASS | UT_OTHER; - break; - case URB_FUNCTION_CLASS_ENDPOINT: - type = UT_CLASS | UT_ENDPOINT; - break; - case URB_FUNCTION_VENDOR_DEVICE: - type = UT_VENDOR | UT_DEVICE; - break; - case URB_FUNCTION_VENDOR_INTERFACE: - type = UT_VENDOR | UT_INTERFACE; - break; - case URB_FUNCTION_VENDOR_OTHER: - type = UT_VENDOR | UT_OTHER; - break; - case URB_FUNCTION_VENDOR_ENDPOINT: - type = UT_VENDOR | UT_ENDPOINT; - break; - default: - /* never reach. */ - break; - } - - type |= (vcreq->uvc_trans_flags & USBD_TRANSFER_DIRECTION_IN) ? - UT_READ : UT_WRITE; - type |= vcreq->uvc_reserved1; - - req.bmRequestType = type; - req.bRequest = vcreq->uvc_req; - USETW(req.wIndex, vcreq->uvc_idx); - USETW(req.wValue, vcreq->uvc_value); - USETW(req.wLength, vcreq->uvc_trans_buflen); - - if (vcreq->uvc_trans_flags & USBD_TRANSFER_DIRECTION_IN) { - get_mplock(); - status = usbd_do_request(uaa->device, &req, - vcreq->uvc_trans_buf); - rel_mplock(); - } else - status = usbd_do_request_async(uaa->device, &req, - vcreq->uvc_trans_buf); - - return usbd_usb2urb(status); -} - -static usbd_status -usbd_init_ndispipe(irp *ip, usb_endpoint_descriptor_t *ep) -{ - device_t dev = IRP_NDIS_DEV(ip); - struct ndis_softc *sc = device_get_softc(dev); - struct usb_attach_arg *uaa = device_get_ivars(dev); - usbd_interface_handle iface; - usbd_status status; - - status = usbd_device2interface_handle(uaa->device, NDISUSB_IFACE_INDEX, - &iface); - if (status != USBD_NORMAL_COMPLETION) { - device_printf(dev, "could not get interface handle\n"); - return (status); - } - - switch (UE_GET_XFERTYPE(ep->bmAttributes)) { - case UE_BULK: - if (UE_GET_DIR(ep->bEndpointAddress) == UE_DIR_IN) { - /* RX (bulk IN) */ - if (sc->ndisusb_ep[NDISUSB_ENDPT_BIN] != NULL) - return (USBD_NORMAL_COMPLETION); - - status = usbd_open_pipe(iface, ep->bEndpointAddress, - USBD_EXCLUSIVE_USE, - &sc->ndisusb_ep[NDISUSB_ENDPT_BIN]); - break; - } - - /* TX (bulk OUT) */ - if (sc->ndisusb_ep[NDISUSB_ENDPT_BOUT] != NULL) - return (USBD_NORMAL_COMPLETION); - - status = usbd_open_pipe(iface, ep->bEndpointAddress, - USBD_EXCLUSIVE_USE, &sc->ndisusb_ep[NDISUSB_ENDPT_BOUT]); - break; - case UE_INTERRUPT: - if (UE_GET_DIR(ep->bEndpointAddress) == UE_DIR_IN) { - /* Interrupt IN. */ - if (sc->ndisusb_ep[NDISUSB_ENDPT_IIN] != NULL) - return (USBD_NORMAL_COMPLETION); - - status = usbd_open_pipe(iface, ep->bEndpointAddress, - USBD_EXCLUSIVE_USE, - &sc->ndisusb_ep[NDISUSB_ENDPT_IIN]); - break; - } - - /* Interrupt OUT. */ - if (sc->ndisusb_ep[NDISUSB_ENDPT_IOUT] != NULL) - return (USBD_NORMAL_COMPLETION); - - status = usbd_open_pipe(iface, ep->bEndpointAddress, - USBD_EXCLUSIVE_USE, &sc->ndisusb_ep[NDISUSB_ENDPT_IOUT]); - break; - default: - device_printf(dev, "can't handle xfertype 0x%x\n", - UE_GET_XFERTYPE(ep->bmAttributes)); - return (USBD_INVAL); - } - - if (status != USBD_NORMAL_COMPLETION) - device_printf(dev, "open pipe failed: (0x%x) %s\n", - ep->bEndpointAddress, usbd_errstr(status)); - - return (status); -} - -static void -usbd_irpcancel_cb(void *priv) -{ - struct ndisusb_cancel *nc = priv; - struct ndis_softc *sc = device_get_softc(nc->dev); - usbd_status status; - usbd_xfer_handle xfer = nc->xfer; - - if (sc->ndisusb_status & NDISUSB_STATUS_DETACH) - goto exit; - - status = usbd_abort_pipe(xfer->pipe); - if (status != USBD_NORMAL_COMPLETION) - device_printf(nc->dev, "can't be canceld"); -exit: - kfree(nc, M_USBDEV); -} - -static void -usbd_irpcancel(device_object *dobj, irp *ip) -{ - device_t dev = IRP_NDIS_DEV(ip); - struct ndisusb_cancel *nc; - struct usb_attach_arg *uaa = device_get_ivars(dev); - - if (IRP_NDISUSB_XFER(ip) == NULL) { - ip->irp_cancel = TRUE; - IoReleaseCancelSpinLock(ip->irp_cancelirql); - return; - } - - /* - * XXX Since we're under DISPATCH_LEVEL during calling usbd_irpcancel(), - * we can't sleep at all. However, currently FreeBSD's USB stack - * requires a sleep to abort a transfer. It's inevitable! so it causes - * serveral fatal problems (e.g. kernel hangups or crashes). I think - * that there are no ways to make this reliable. In this implementation, - * I used usb_add_task() but it's not a perfect method to solve this - * because of as follows: NDIS drivers would expect that IRP's - * completely canceld when usbd_irpcancel() is returned but we need - * a sleep to do it. During canceling XFERs, usbd_intr() would be - * called with a status, USBD_CANCELLED. - */ - nc = kmalloc(sizeof(struct ndisusb_cancel), M_USBDEV, M_NOWAIT | M_ZERO); - if (nc == NULL) { - ip->irp_cancel = FALSE; - IoReleaseCancelSpinLock(ip->irp_cancelirql); - return; - } - - nc->dev = dev; - nc->xfer = IRP_NDISUSB_XFER(ip); - usb_init_task(&nc->task, usbd_irpcancel_cb, nc); - - IRP_NDISUSB_XFER(ip) = NULL; - usb_add_task(uaa->device, &nc->task, USB_TASKQ_DRIVER); - - ip->irp_cancel = TRUE; - IoReleaseCancelSpinLock(ip->irp_cancelirql); -} - -static usbd_xfer_handle -usbd_init_ndisxfer(irp *ip, usb_endpoint_descriptor_t *ep, void *buf, - uint32_t buflen) -{ - device_t dev = IRP_NDIS_DEV(ip); - struct usb_attach_arg *uaa = device_get_ivars(dev); - usbd_xfer_handle xfer; - - xfer = usbd_alloc_xfer(uaa->device); - if (xfer == NULL) - return (NULL); - - if (buf != NULL && MmIsAddressValid(buf) == FALSE && buflen > 0) { - xfer->buffer = usbd_alloc_buffer(xfer, buflen); - if (xfer->buffer == NULL) - return (NULL); - - if (UE_GET_DIR(ep->bEndpointAddress) == UE_DIR_OUT) - memcpy(xfer->buffer, buf, buflen); - } else - xfer->buffer = buf; - - xfer->length = buflen; - - IoAcquireCancelSpinLock(&ip->irp_cancelirql); - IRP_NDISUSB_XFER(ip) = xfer; - ip->irp_cancelfunc = (cancel_func)usbd_irpcancel_wrap; - IoReleaseCancelSpinLock(ip->irp_cancelirql); - - return (xfer); -} - -static void -usbd_xferadd(usbd_xfer_handle xfer, usbd_private_handle priv, - usbd_status status) -{ - irp *ip = priv; - device_t dev = IRP_NDIS_DEV(ip); - struct ndis_softc *sc = device_get_softc(dev); - struct ndisusb_xfer *nx; - uint8_t irql; - - nx = kmalloc(sizeof(struct ndisusb_xfer), M_USBDEV, M_NOWAIT | M_ZERO); - if (nx == NULL) { - device_printf(dev, "out of memory"); - return; - } - nx->nx_xfer = xfer; - nx->nx_priv = priv; - nx->nx_status = status; - - KeAcquireSpinLock(&sc->ndisusb_xferlock, &irql); - InsertTailList((&sc->ndisusb_xferlist), (&nx->nx_xferlist)); - KeReleaseSpinLock(&sc->ndisusb_xferlock, irql); - - IoQueueWorkItem(sc->ndisusb_xferitem, - (io_workitem_func)usbd_xfertask_wrap, WORKQUEUE_CRITICAL, sc); -} - -static void -usbd_xfereof(usbd_xfer_handle xfer, usbd_private_handle priv, - usbd_status status) -{ - - usbd_xferadd(xfer, priv, status); -} - -static void -usbd_xfertask(device_object *dobj, void *arg) -{ - int error; - irp *ip; - device_t dev; - list_entry *l; - struct ndis_softc *sc = arg; - struct ndisusb_xfer *nx; - struct usbd_urb_bulk_or_intr_transfer *ubi; - uint8_t irql; - union usbd_urb *urb; - usbd_private_handle priv; - usbd_status status; - usbd_xfer_handle xfer; - - dev = sc->ndis_dev; - - if (IsListEmpty(&sc->ndisusb_xferlist)) - return; - - KeAcquireSpinLock(&sc->ndisusb_xferlock, &irql); - l = sc->ndisusb_xferlist.nle_flink; - while (l != &sc->ndisusb_xferlist) { - nx = CONTAINING_RECORD(l, struct ndisusb_xfer, nx_xferlist); - xfer = nx->nx_xfer; - priv = nx->nx_priv; - status = nx->nx_status; - error = 0; - ip = priv; - - if (status != USBD_NORMAL_COMPLETION) { - if (status == USBD_NOT_STARTED) { - error = 1; - goto next; - } - if (status == USBD_STALLED) - usbd_clear_endpoint_stall_async(xfer->pipe); - /* - * NB: just for notice. We must handle error cases also - * because if we just return without notifying to the - * NDIS driver the driver never knows about that there - * was a error. This can cause a lot of problems like - * system hangs. - */ - device_printf(dev, "usb xfer warning (%s)\n", - usbd_errstr(status)); - } - - urb = usbd_geturb(ip); - - KASSERT(urb->uu_hdr.uuh_func == - URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER, - ("function(%d) isn't for bulk or interrupt", - urb->uu_hdr.uuh_func)); - - IoAcquireCancelSpinLock(&ip->irp_cancelirql); - - ip->irp_cancelfunc = NULL; - IRP_NDISUSB_XFER(ip) = NULL; - - switch (status) { - case USBD_NORMAL_COMPLETION: - ubi = &urb->uu_bulkintr; - ubi->ubi_trans_buflen = xfer->actlen; - if (ubi->ubi_trans_flags & USBD_TRANSFER_DIRECTION_IN) - memcpy(ubi->ubi_trans_buf, xfer->buffer, - xfer->actlen); - - ip->irp_iostat.isb_info = xfer->actlen; - ip->irp_iostat.isb_status = STATUS_SUCCESS; - USBD_URB_STATUS(urb) = USBD_STATUS_SUCCESS; - break; - case USBD_CANCELLED: - ip->irp_iostat.isb_info = 0; - ip->irp_iostat.isb_status = STATUS_CANCELLED; - USBD_URB_STATUS(urb) = USBD_STATUS_CANCELED; - break; - default: - ip->irp_iostat.isb_info = 0; - USBD_URB_STATUS(urb) = usbd_usb2urb(status); - ip->irp_iostat.isb_status = - usbd_urb2nt(USBD_URB_STATUS(urb)); - break; - } - - IoReleaseCancelSpinLock(ip->irp_cancelirql); -next: - l = l->nle_flink; - RemoveEntryList(&nx->nx_xferlist); - usbd_free_xfer(nx->nx_xfer); - kfree(nx, M_USBDEV); - if (error) - continue; - /* NB: call after cleaning */ - IoCompleteRequest(ip, IO_NO_INCREMENT); - } - KeReleaseSpinLock(&sc->ndisusb_xferlock, irql); -} - -static int32_t -usbd_func_bulkintr(irp *ip) -{ - device_t dev = IRP_NDIS_DEV(ip); - struct ndis_softc *sc = device_get_softc(dev); - struct usbd_urb_bulk_or_intr_transfer *ubi; - union usbd_urb *urb; - usb_endpoint_descriptor_t *ep; - usbd_status status; - usbd_xfer_handle xfer; - - urb = usbd_geturb(ip); - ubi = &urb->uu_bulkintr; - ep = ubi->ubi_epdesc; - if (ep == NULL) - return (USBD_STATUS_INVALID_PIPE_HANDLE); - - status = usbd_init_ndispipe(ip, ep); - if (status != USBD_NORMAL_COMPLETION) - return usbd_usb2urb(status); - - xfer = usbd_init_ndisxfer(ip, ep, ubi->ubi_trans_buf, - ubi->ubi_trans_buflen); - if (xfer == NULL) { - device_printf(IRP_NDIS_DEV(ip), "can't allocate xfer\n"); - return (USBD_STATUS_NO_MEMORY); - } - - if (UE_GET_DIR(ep->bEndpointAddress) == UE_DIR_IN) { - xfer->flags |= USBD_SHORT_XFER_OK; - if (!(ubi->ubi_trans_flags & USBD_SHORT_TRANSFER_OK)) - xfer->flags &= ~USBD_SHORT_XFER_OK; - } - - if (UE_GET_XFERTYPE(ep->bmAttributes) == UE_BULK) { - if (UE_GET_DIR(ep->bEndpointAddress) == UE_DIR_IN) - /* RX (bulk IN) */ - usbd_setup_xfer(xfer, sc->ndisusb_ep[NDISUSB_ENDPT_BIN], - ip, xfer->buffer, xfer->length, xfer->flags, - USBD_NO_TIMEOUT, usbd_xfereof); - else { - /* TX (bulk OUT) */ - xfer->flags |= USBD_NO_COPY; - - usbd_setup_xfer(xfer, sc->ndisusb_ep[NDISUSB_ENDPT_BOUT], - ip, xfer->buffer, xfer->length, xfer->flags, - NDISUSB_TX_TIMEOUT, usbd_xfereof); - } - } else { - if (UE_GET_DIR(ep->bEndpointAddress) == UE_DIR_IN) - /* Interrupt IN */ - usbd_setup_xfer(xfer, sc->ndisusb_ep[NDISUSB_ENDPT_IIN], - ip, xfer->buffer, xfer->length, xfer->flags, - USBD_NO_TIMEOUT, usbd_xfereof); - else - /* Interrupt OUT */ - usbd_setup_xfer(xfer, sc->ndisusb_ep[NDISUSB_ENDPT_IOUT], - ip, xfer->buffer, xfer->length, xfer->flags, - NDISUSB_INTR_TIMEOUT, usbd_xfereof); - } - - /* we've done to setup xfer. Let's transfer it. */ - ip->irp_iostat.isb_status = STATUS_PENDING; - ip->irp_iostat.isb_info = 0; - USBD_URB_STATUS(urb) = USBD_STATUS_PENDING; - IoMarkIrpPending(ip); - - status = usbd_transfer(xfer); - if (status == USBD_IN_PROGRESS) - return (USBD_STATUS_PENDING); - - usbd_free_xfer(xfer); - IRP_NDISUSB_XFER(ip) = NULL; - IoUnmarkIrpPending(ip); - USBD_URB_STATUS(urb) = usbd_usb2urb(status); - - return USBD_URB_STATUS(urb); -} - -static union usbd_urb * -USBD_CreateConfigurationRequest(usb_config_descriptor_t *conf, uint16_t *len) -{ - struct usbd_interface_list_entry list[2]; - union usbd_urb *urb; - - bzero(list, sizeof(struct usbd_interface_list_entry) * 2); - list[0].uil_intfdesc = USBD_ParseConfigurationDescriptorEx(conf, conf, - -1, -1, -1, -1, -1); - urb = USBD_CreateConfigurationRequestEx(conf, list); - if (urb == NULL) - return (NULL); - - *len = urb->uu_selconf.usc_hdr.uuh_len; - return (urb); -} - -static union usbd_urb * -USBD_CreateConfigurationRequestEx(usb_config_descriptor_t *conf, - struct usbd_interface_list_entry *list) -{ - int i, j, size; - struct usbd_interface_information *intf; - struct usbd_pipe_information *pipe; - struct usbd_urb_select_configuration *selconf; - usb_interface_descriptor_t *desc; - - for (i = 0, size = 0; i < conf->bNumInterface; i++) { - j = list[i].uil_intfdesc->bNumEndpoints; - size = size + sizeof(struct usbd_interface_information) + - sizeof(struct usbd_pipe_information) * (j - 1); - } - size += sizeof(struct usbd_urb_select_configuration) - - sizeof(struct usbd_interface_information); - - selconf = ExAllocatePoolWithTag(NonPagedPool, size, 0); - if (selconf == NULL) - return (NULL); - selconf->usc_hdr.uuh_func = URB_FUNCTION_SELECT_CONFIGURATION; - selconf->usc_hdr.uuh_len = size; - selconf->usc_handle = conf; - selconf->usc_conf = conf; - - intf = &selconf->usc_intf; - for (i = 0; i < conf->bNumInterface; i++) { - if (list[i].uil_intfdesc == NULL) - break; - - list[i].uil_intf = intf; - desc = list[i].uil_intfdesc; - - intf->uii_len = sizeof(struct usbd_interface_information) + - (desc->bNumEndpoints - 1) * - sizeof(struct usbd_pipe_information); - intf->uii_intfnum = desc->bInterfaceNumber; - intf->uii_altset = desc->bAlternateSetting; - intf->uii_intfclass = desc->bInterfaceClass; - intf->uii_intfsubclass = desc->bInterfaceSubClass; - intf->uii_intfproto = desc->bInterfaceProtocol; - intf->uii_handle = desc; - intf->uii_numeps = desc->bNumEndpoints; - - pipe = &intf->uii_pipes[0]; - for (j = 0; j < intf->uii_numeps; j++) - pipe[j].upi_maxtxsize = - USBD_DEFAULT_MAXIMUM_TRANSFER_SIZE; - - intf = (struct usbd_interface_information *)((char *)intf + - intf->uii_len); - } - - return ((union usbd_urb *)selconf); -} - -static void -USBD_GetUSBDIVersion(usbd_version_info *ui) -{ - - /* Pretend to be Windows XP. */ - - ui->uvi_usbdi_vers = USBDI_VERSION; - ui->uvi_supported_vers = USB_VER_2_0; -} - -static usb_interface_descriptor_t * -USBD_ParseConfigurationDescriptor(usb_config_descriptor_t *conf, - uint8_t intfnum, uint8_t altset) -{ - - return USBD_ParseConfigurationDescriptorEx(conf, conf, intfnum, altset, - -1, -1, -1); -} - -static usb_interface_descriptor_t * -USBD_ParseConfigurationDescriptorEx(usb_config_descriptor_t *conf, - void *start, int32_t intfnum, int32_t altset, int32_t intfclass, - int32_t intfsubclass, int32_t intfproto) -{ - char *pos; - usb_interface_descriptor_t *desc; - - for (pos = start; pos < ((char *)conf + UGETW(conf->wTotalLength)); - pos += desc->bLength) { - desc = (usb_interface_descriptor_t *)pos; - if (desc->bDescriptorType != UDESC_INTERFACE) - continue; - if (!(intfnum == -1 || desc->bInterfaceNumber == intfnum)) - continue; - if (!(altset == -1 || desc->bAlternateSetting == altset)) - continue; - if (!(intfclass == -1 || desc->bInterfaceClass == intfclass)) - continue; - if (!(intfsubclass == -1 || - desc->bInterfaceSubClass == intfsubclass)) - continue; - if (!(intfproto == -1 || desc->bInterfaceProtocol == intfproto)) - continue; - return (desc); - } - - return (NULL); -} - -static void -dummy(void) -{ - kprintf("USBD dummy called\n"); -} - -image_patch_table usbd_functbl[] = { - IMPORT_SFUNC(USBD_CreateConfigurationRequest, 2), - IMPORT_SFUNC(USBD_CreateConfigurationRequestEx, 2), - IMPORT_SFUNC_MAP(_USBD_CreateConfigurationRequestEx@8, - USBD_CreateConfigurationRequestEx, 2), - IMPORT_SFUNC(USBD_GetUSBDIVersion, 1), - IMPORT_SFUNC(USBD_ParseConfigurationDescriptor, 3), - IMPORT_SFUNC(USBD_ParseConfigurationDescriptorEx, 7), - IMPORT_SFUNC_MAP(_USBD_ParseConfigurationDescriptorEx@28, - USBD_ParseConfigurationDescriptorEx, 7), - - /* - * This last entry is a catch-all for any function we haven't - * implemented yet. The PE import list patching routine will - * use it for any function that doesn't have an explicit match - * in this table. - */ - - { NULL, (FUNC)dummy, NULL, 0, WINDRV_WRAP_STDCALL }, - - /* End of list. */ - - { NULL, NULL, NULL } -}; - -MODULE_DEPEND(ndis, usb, 1, 1, 1); diff --git a/sys/platform/pc32/conf/files b/sys/platform/pc32/conf/files index 22faa44e71..01799ff9ad 100644 --- a/sys/platform/pc32/conf/files +++ b/sys/platform/pc32/conf/files @@ -74,7 +74,6 @@ emulation/ndis/subr_hal.c optional ndisapi pci emulation/ndis/subr_ndis.c optional ndisapi pci emulation/ndis/subr_ntoskrnl.c optional ndisapi pci emulation/ndis/subr_pe.c optional ndisapi pci -emulation/ndis/subr_usbd.c optional ndisapi pci oldusb emulation/ndis/subr_u4bd.c optional ndisapi pci usb emulation/ndis/winx32_wrap.S optional ndisapi pci # @@ -134,7 +133,6 @@ dev/netif/ndis/if_ndis.c optional ndis dev/netif/ndis/if_ndis_pccard.c optional ndis pccard dev/netif/ndis/if_ndis_pci.c optional ndis cardbus dev/netif/ndis/if_ndis_pci.c optional ndis pci -dev/netif/ndis/if_ndis_usb.c optional ndis oldusb dev/netif/ndis/if_ndis_u4b.c optional ndis usb dev/netif/sr/if_sr.c optional sr dev/netif/sr/if_sr_pci.c optional sr pci diff --git a/sys/platform/pc64/conf/files b/sys/platform/pc64/conf/files index 0012fb245f..5e129456c1 100644 --- a/sys/platform/pc64/conf/files +++ b/sys/platform/pc64/conf/files @@ -37,7 +37,6 @@ emulation/ndis/subr_hal.c optional ndisapi pci emulation/ndis/subr_ndis.c optional ndisapi pci emulation/ndis/subr_ntoskrnl.c optional ndisapi pci emulation/ndis/subr_pe.c optional ndisapi pci -emulation/ndis/subr_usbd.c optional ndisapi pci oldusb emulation/ndis/subr_u4bd.c optional ndisapi pci usb emulation/ndis/winx64_wrap.S optional ndisapi pci @@ -83,7 +82,6 @@ dev/netif/ndis/if_ndis.c optional ndis dev/netif/ndis/if_ndis_pccard.c optional ndis pccard dev/netif/ndis/if_ndis_pci.c optional ndis cardbus dev/netif/ndis/if_ndis_pci.c optional ndis pci -dev/netif/ndis/if_ndis_usb.c optional ndis oldusb dev/netif/ndis/if_ndis_u4b.c optional ndis usb dev/misc/kbd/atkbd.c optional atkbd dev/misc/kbd/atkbdc.c optional atkbdc diff --git a/tools/tools/convert_usb_ids/convert_usb_ids.sh b/tools/tools/convert_usb_ids/convert_usb_ids.sh deleted file mode 100644 index d41f31068f..0000000000 --- a/tools/tools/convert_usb_ids/convert_usb_ids.sh +++ /dev/null @@ -1,155 +0,0 @@ -#!/bin/sh -# -# $DragonFly: src/tools/tools/convert_usb_ids/convert_usb_ids.sh,v 1.2 2008/01/15 12:30:44 matthias Exp $ - -ub=usbdevs - -if [ ! -f $ub ]; then - echo "Cannot find $ub. You can get the latest version from FreeBSD" - echo "http://www.freebsd.org/cgi/cvsweb.cgi/src/sys/dev/usb/usbdevs" - exit 1 -fi - -# Function for USB mass storage tables (see umass.c) -umass() -{ - i=0 - while read ip; do - # Skip over /* ... */ comments - cc=`echo "$ip" | grep "/\*"` - if [ -n "$cc" ]; then - continue - fi - - # Assume that an umass entry consists of 3 lines - if [ $i -gt 2 ]; then - i=0 - continue - fi - - # The first line - if [ -n "`echo $ip | grep '{'`" ]; then - vendor=`echo $ip | awk -F ' ' '{print $2}' | head -1 | \ - tr -d , | sed -e 's/USB_VENDOR_//g'` - product=`echo $ip | awk -F ' ' '{print $3}'| head -1 | \ - tr -d , | sed -e "s/USB_PRODUCT_${vendor}_//g"` - release=`echo $ip | awk -F ' ' '{print $4}'| head -1` - #let i=$i + 1 > /dev/null - # Second and third line - else - # Extract protocol line - if [ -n "`echo $ip | grep UMASS_PROTO`" ]; then - proto=`echo $ip | grep UMASS_PROTO` - fi - # Extract quirks - if [ $i -eq 2 ]; then - quirks=`echo $ip` - fi - #let i=$i + 1 > /dev/null - fi - if [ -n "$vendor" -a -n "$product" -a -n "$release" ] && - [ -n "$proto" -a -n "$quirks" ]; then - - # We use another define - if [ "$release" = "RID_WILDCARD," ]; then - release="WILDCARD_ID," - fi - - # Get vendor ID from usbdevs - vendor_id=`grep "vendor $vendor" $ub | head -1 | awk '{print $3}'` - - # Get vendor description from usbdevs - vendor_desc=`grep "vendor $vendor" $ub | head -1 | awk '{print $4}'` - - # Get product ID from usbdevs - product_id=`grep "product $vendor $product" $ub | \ - head -1 | awk '{print $4 }'` - - # Get full product name from usbdevs - product_name=`grep "product $vendor $product" $ub | \ - head -1 | awk '{print $5,$6,$7 }'` - - # Output our version of the device id - printf "\t" - echo "/* $vendor_desc $product_name */" - printf "\t" - echo -n "{ .vendor = $vendor_id, .product = $product_id, " - echo ".release = $release" - printf "\t" - echo " .proto = $proto" - printf "\t" - echo " .quirks = $quirks" - printf "\t" - echo "}," - release= - vendor= - product= - quirks= - i=10 - fi - let i=$i + 1 > /dev/null - done -} - -# Function for non-umass devices -nonumass() -{ - while read ip; do - # Skip lines not beginning with { - if [ -z "`echo $ip | grep '{ '`" ]; then - continue - fi - - # Get vendor - vendor=`echo $ip | awk -F ' ' '{print $2}' | head -1 | \ - tr -d , | sed -e 's/USB_VENDOR_//g'` - - # Get product - product=`echo $ip | awk -F ' ' '{print $3}'| head -1 | \ - tr -d , | sed -e "s/USB_PRODUCT_${vendor}_//g"` - - # Get possible flag (eg PALM4) - dflag=`echo $ip | awk -F ' ' '{print $5}'` - - # Get vendor ID from usbdevs - vendor_id=`grep "vendor $vendor" $ub | head -1 | awk '{print $3}'` - - # Get vendor description from usbdevs - vendor_desc=`grep "vendor $vendor" $ub | head -1 | awk '{print $4}'` - - # Get product ID from ubsdevs - product_id=`grep "product $vendor $product" $ub | \ - head -1 | awk '{print $4 }'` - - # Get full name of the product from usbdevs - product_name=`grep "product $vendor $product" $ub | \ - head -1 | awk '{print $5,$6,$7 }'` - - if [ -n "$vendor_id" -a -n "$vendor_desc" ] && - [ -n "$product_id" -a -n "$product_name" ]; then - # More complex entry with a flag - if [ "$dflag" != "" ]; then - printf "\t" - echo "{{ USB_DEVICE($vendor_id, $product_id) }, $dflag }, /* $vendor_desc $product_name */" - # Entry without a flag - elif [ "$dflag" = "" ]; then - printf "\t" - echo "{ USB_DEVICE($vendor_id, $product_id) }, /* $vendor_desc $product_name */" - fi - fi - done -} - -DFLAG=0 -case "$1" in - "-d") - DFLAG=1; break;; -esac - -if [ $DFLAG -eq 1 ]; then - umass -else - nonumass -fi - -exit $? diff --git a/usr.bin/Makefile b/usr.bin/Makefile index cc5591e4c8..d727613eb8 100644 --- a/usr.bin/Makefile +++ b/usr.bin/Makefile @@ -215,8 +215,8 @@ SUBDIR= alias \ uniq \ units \ unvis \ - ${_usbhidaction} \ - ${_usbhidctl} \ + usbhidaction \ + u4bhidctl \ users \ uudecode \ uuencode \ @@ -251,13 +251,6 @@ SUBDIR= alias \ SUBDIR+=hesinfo .endif -.if !defined(WANT_OLDUSB) -_usbhidctl= u4bhidctl -_usbhidaction= usbhidaction -.else -_usbhidctl= usbhidctl -.endif - .if !defined(NO_OPENSSL) SUBDIR+=bc \ dc diff --git a/usr.bin/usbhidctl/Makefile b/usr.bin/usbhidctl/Makefile deleted file mode 100644 index 4a82c1cca1..0000000000 --- a/usr.bin/usbhidctl/Makefile +++ /dev/null @@ -1,12 +0,0 @@ -# $NetBSD: Makefile,v 1.4 1999/05/11 21:02:25 augustss Exp $ -# $FreeBSD: src/usr.bin/usbhidctl/Makefile,v 1.2.2.1 2002/04/03 16:48:25 joe Exp $ - -.include - -PROG= usbhidctl -SRCS= usbhid.c - -LDADD+= -lusbhid -DPADD+= ${LIBUSBHID} - -.include diff --git a/usr.bin/usbhidctl/usbhid.c b/usr.bin/usbhidctl/usbhid.c deleted file mode 100644 index 19540fdd5a..0000000000 --- a/usr.bin/usbhidctl/usbhid.c +++ /dev/null @@ -1,343 +0,0 @@ -/* $NetBSD: usbhid.c,v 1.14 2000/07/03 02:51:37 matt Exp $ */ -/* $FreeBSD: src/usr.bin/usbhidctl/usbhid.c,v 1.12 2007/12/21 03:40:36 imp Exp $ */ - -/* - * Copyright (c) 1998 The NetBSD Foundation, Inc. - * All rights reserved. - * - * This code is derived from software contributed to The NetBSD Foundation - * by Lennart Augustsson (augustss@netbsd.org). - * - * 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. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the NetBSD - * Foundation, Inc. and its contributors. - * 4. Neither the name of The NetBSD Foundation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -int verbose = 0; -int all = 0; -int noname = 0; -int hexdump = 0; -static int reportid; - -char **names; -int nnames; - -void prbits(int bits, char **strs, int n); -void usage(void); -void dumpitem(const char *label, struct hid_item *h); -void dumpitems(report_desc_t r); -void rev(struct hid_item **p); -void prdata(u_char *buf, struct hid_item *h); -void dumpdata(int f, report_desc_t r, int loop); -int gotname(char *n); - -int -gotname(char *n) -{ - int i; - - for (i = 0; i < nnames; i++) - if (strcmp(names[i], n) == 0) - return 1; - return 0; -} - -void -prbits(int bits, char **strs, int n) -{ - int i; - - for(i = 0; i < n; i++, bits >>= 1) - if (strs[i*2]) - printf("%s%s", i == 0 ? "" : ", ", strs[i*2 + (bits&1)]); -} - -void -usage(void) -{ - fprintf(stderr, - "usage: %s -f device " - "[-l] [-n] [-r] [-t tablefile] [-v] [-x] name ...\n", - getprogname()); - fprintf(stderr, - " %s -f device " - "[-l] [-n] [-r] [-t tablefile] [-v] [-x] -a\n", - getprogname()); - exit(1); -} - -void -dumpitem(const char *label, struct hid_item *h) -{ - if ((h->flags & HIO_CONST) && !verbose) - return; - printf("%s size=%d count=%d page=%s usage=%s%s", label, - h->report_size, h->report_count, - hid_usage_page(HID_PAGE(h->usage)), - hid_usage_in_page(h->usage), - h->flags & HIO_CONST ? " Const" : ""); - printf(", logical range %d..%d", - h->logical_minimum, h->logical_maximum); - if (h->physical_minimum != h->physical_maximum) - printf(", physical range %d..%d", - h->physical_minimum, h->physical_maximum); - if (h->unit) - printf(", unit=0x%02x exp=%d", h->unit, h->unit_exponent); - printf("\n"); -} - -void -dumpitems(report_desc_t r) -{ - struct hid_data *d; - struct hid_item h; - int size; - - for (d = hid_start_parse(r, ~0, reportid); hid_get_item(d, &h); ) { - switch (h.kind) { - case hid_collection: - printf("Collection page=%s usage=%s\n", - hid_usage_page(HID_PAGE(h.usage)), - hid_usage_in_page(h.usage)); - break; - case hid_endcollection: - printf("End collection\n"); - break; - case hid_input: - dumpitem("Input ", &h); - break; - case hid_output: - dumpitem("Output ", &h); - break; - case hid_feature: - dumpitem("Feature", &h); - break; - } - } - hid_end_parse(d); - size = hid_report_size(r, hid_input, 0); - printf("Total input size %d bytes\n", size); - - size = hid_report_size(r, hid_output, 0); - printf("Total output size %d bytes\n", size); - - size = hid_report_size(r, hid_feature, 0); - printf("Total feature size %d bytes\n", size); -} - -void -rev(struct hid_item **p) -{ - struct hid_item *cur, *prev, *next; - - prev = NULL; - cur = *p; - while(cur != NULL) { - next = cur->next; - cur->next = prev; - prev = cur; - cur = next; - } - *p = prev; -} - -void -prdata(u_char *buf, struct hid_item *h) -{ - u_int data; - int i, pos; - - pos = h->pos; - for (i = 0; i < h->report_count; i++) { - data = hid_get_data(buf, h); - if (h->logical_minimum < 0) - printf("%d", (int)data); - else - printf("%u", data); - if (hexdump) - printf(" [0x%x]", data); - pos += h->report_size; - } -} - -void -dumpdata(int f, report_desc_t rd, int loop) -{ - struct hid_data *d; - struct hid_item h, *hids, *n; - int r, dlen; - u_char *dbuf; - static int one = 1; - u_int32_t colls[100]; - int sp = 0; - char namebuf[10000], *namep; - - hids = NULL; - for (d = hid_start_parse(rd, 1<next) { - namep = namebuf; - namep += sprintf(namep, "%s:%s.", - hid_usage_page(HID_PAGE(n->collection)), - hid_usage_in_page(n->collection)); - namep += sprintf(namep, "%s:%s", - hid_usage_page(HID_PAGE(n->usage)), - hid_usage_in_page(n->usage)); - if (all || gotname(namebuf)) { - if (!noname) - printf("%s=", namebuf); - prdata(dbuf + (reportid != 0), n); - printf("\n"); - } - } - if (loop) - printf("\n"); - } while (loop); - free(dbuf); -} - -int -main(int argc, char **argv) -{ - int f; - report_desc_t r; - char devnam[100], *dev = NULL; - int ch; - int repdump = 0; - int loop = 0; - char *table = NULL; - - while ((ch = getopt(argc, argv, "af:lnrt:vx")) != -1) { - switch(ch) { - case 'a': - all++; - break; - case 'f': - dev = optarg; - break; - case 'l': - loop ^= 1; - break; - case 'n': - noname++; - break; - case 'r': - repdump++; - break; - case 't': - table = optarg; - break; - case 'v': - verbose++; - break; - case 'x': - hexdump = 1; - break; - case '?': - default: - usage(); - } - } - argc -= optind; - argv += optind; - if (dev == NULL) - usage(); - names = argv; - nnames = argc; - - if (nnames == 0 && !all && !repdump) - usage(); - - if (dev[0] != '/') { - if (isdigit(dev[0])) - snprintf(devnam, sizeof(devnam), "/dev/uhid%s", dev); - else - snprintf(devnam, sizeof(devnam), "/dev/%s", dev); - dev = devnam; - } - - hid_init(table); - - f = open(dev, O_RDWR); - if (f < 0) - err(1, "%s", dev); - - r = hid_get_report_desc(f); - if (r == 0) - errx(1, "USB_GET_REPORT_DESC"); - - if (repdump) { - printf("Report descriptor:\n"); - dumpitems(r); - } - if (nnames != 0 || all) - dumpdata(f, r, loop); - - hid_dispose_report_desc(r); - exit(0); -} diff --git a/usr.bin/usbhidctl/usbhidctl.1 b/usr.bin/usbhidctl/usbhidctl.1 deleted file mode 100644 index f6faa04577..0000000000 --- a/usr.bin/usbhidctl/usbhidctl.1 +++ /dev/null @@ -1,98 +0,0 @@ -.\" $NetBSD: usbhidctl.1,v 1.8 1999/05/11 21:03:58 augustss Exp $ -.\" $FreeBSD: src/usr.bin/usbhidctl/usbhidctl.1,v 1.7 2006/11/23 05:08:06 grog Exp $ -.\" $DragonFly: src/usr.bin/usbhidctl/usbhidctl.1,v 1.6 2008/11/26 17:17:16 swildner Exp $ -.\" -.\" Copyright (c) 1998 The NetBSD Foundation, Inc. -.\" All rights reserved. -.\" -.\" This code is derived from software contributed to The NetBSD Foundation -.\" by Lennart Augustsson. -.\" -.\" 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. -.\" 3. All advertising materials mentioning features or use of this software -.\" must display the following acknowledgement: -.\" This product includes software developed by the NetBSD -.\" Foundation, Inc. and its contributors. -.\" 4. Neither the name of The NetBSD Foundation nor the names of its -.\" contributors may be used to endorse or promote products derived -.\" from this software without specific prior written permission. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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. -.\" -.Dd November 24, 2008 -.Dt USBHIDCTL 1 -.Os -.Sh NAME -.Nm usbhidctl -.Nd manipulate USB HID devices -.Sh SYNOPSIS -.Nm -.Op Fl a -.Fl f Ar device -.Op Fl l -.Op Fl n -.Op Fl r -.Op Fl t Ar table -.Op Fl v -.Op Fl x -.Op Ar item ... -.Sh DESCRIPTION -The -.Nm -utility can be used to dump the state of a USB HID (Human Interface Device). -Each named -.Ar item -is printed. -.Pp -The options are as follows: -.Bl -tag -width Ds -.It Fl a -Show all items. -.It Fl f Ar device -Specify a path name for the device to operate on. -.It Fl l -Loop and dump the device data every time it changes. -.It Fl n -Suppress printing of the item name. -.It Fl r -Dump the report descriptor. -.It Fl t Ar table -Specify a path name for the HID usage table file. -.It Fl v -Be verbose. -.It Fl x -Dump data in hexadecimal as well as decimal. -.El -.Sh FILES -.Pa /usr/share/misc/usb_hid_usages -The default HID usage table. -.Sh SEE ALSO -.Xr usbhid 3 , -.Xr uhid 4 , -.Xr usb 4 -.Sh HISTORY -The -.Nm -command appeared in -.Nx 1.4 . -.Sh BUGS -The -.Nm -utility cannot show nor set output and feature items. diff --git a/usr.sbin/Makefile b/usr.sbin/Makefile index 0eaadc32a3..6407508c8d 100644 --- a/usr.sbin/Makefile +++ b/usr.sbin/Makefile @@ -124,10 +124,8 @@ SUBDIR= 802_11 \ traceroute6 \ trpt \ tzsetup \ - ${_usbconfig} \ - ${_usbd} \ - ${_usbdevs} \ - ${_usbdump} \ + usbconfig \ + usbdump \ vidcontrol \ vipw \ vknetd \ @@ -143,14 +141,6 @@ SUBDIR= 802_11 \ ypset \ zic -.if defined(WANT_OLDUSB) -_usbd= usbd -_usbdevs= usbdevs -.else -_usbconfig= usbconfig -_usbdump= usbdump -.endif - .if !defined(NO_LPR) SUBDIR+=lpr .endif diff --git a/usr.sbin/usbd/Makefile b/usr.sbin/usbd/Makefile deleted file mode 100644 index 09366eab7b..0000000000 --- a/usr.sbin/usbd/Makefile +++ /dev/null @@ -1,7 +0,0 @@ -# $FreeBSD: src/usr.sbin/usbd/Makefile,v 1.4.2.1 2001/04/25 12:11:08 ru Exp $ - -PROG= usbd -MAN= usbd.conf.5 usbd.8 -CFLAGS+=-I${.CURDIR}/../../sys - -.include diff --git a/usr.sbin/usbd/usbd.8 b/usr.sbin/usbd/usbd.8 deleted file mode 100644 index 5d8f046ce1..0000000000 --- a/usr.sbin/usbd/usbd.8 +++ /dev/null @@ -1,144 +0,0 @@ -.\" Copyright (c) 1998 The NetBSD Foundation, Inc. -.\" All rights reserved. -.\" -.\" Author: Lennart Augustsson -.\" -.\" 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. -.\" 3. All advertising materials mentioning features or use of this software -.\" must display the following acknowledgement: -.\" This product includes software developed by the NetBSD -.\" Foundation, Inc. and its contributors. -.\" 4. Neither the name of The NetBSD Foundation nor the names of its -.\" contributors may be used to endorse or promote products derived -.\" from this software without specific prior written permission. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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. -.\" -.\" $NetBSD: usbd.8,v 1.2 1998/07/13 11:01:50 augustss Exp $ -.\" $FreeBSD: src/usr.sbin/usbd/usbd.8,v 1.20 2003/05/04 22:13:00 murray Exp $ -.\" -.Dd July 2, 2006 -.Dt USBD 8 -.Os -.Sh NAME -.Nm usbd -.Nd supervise USB attach/detach -.Sh SYNOPSIS -.Nm -.Op Fl c Ar configfile -.Op Fl d -.Op Fl e -.Op Fl f Ar device -.Op Fl n -.Op Fl t Ar timeout -.Op Fl v -.Sh DESCRIPTION -The -.Nm -utility handles USB device attachment and detachment. -The (multiple) -.Fl f Ar device -command line options specify which controllers it should handle. -Normally this option is not needed. -.Pp -If the -.Dq usb , -.Dq ohci -and -.Dq uhci -modules are not loaded, -.Nm -will load them automatically. -.Pp -To handle the attachment and detachment of USB devices -.Nm -opens the -.Pa /dev/usb -device and reads events from it. -Whenever a device is attached or -detached the list of actions read from -.Pa /etc/usbd.conf -is searched for a matching entry. -If found, the corresponding action is -executed. -.Pp -The command line options are as follows: -.Bl -tag -width Ds -.It Fl c Ar filename -Name of configuration file. -The default is -.Pa /etc/usbd.conf . -.It Fl d -Enable debugging to the standard output, -and do not disassociate from the controlling terminal. -.It Fl e -Do one device tree exploration, no event queue handling and then exit. -.It Fl f Ar device -Specify the pathname of a USB controller device file. -The flag may be repeated to watch more than one USB controller. -The default is -.Pa /dev/usb0 -through -.Pa /dev/usb3 . -Do not specify the device -.Pa /dev/usb -here. -It is used for events only. -.It Fl n -Do not handle the event queue on /dev/usb. -.It Fl t Ar timeout -Set the timeout interval (in seconds) before an exploration happens -without being triggered by a connect or disconnect. -A timeout of 0 means that there is no timeout. The default is 30. -.It Fl v -Be verbose. -Repeating the flag makes -.Nm -more verbose. -.El -.Sh FILES -.Bl -tag -width /etc/usbd.conf -compact -.It Pa /etc/usbd.conf -.It Pa /dev/usb -.It Pa /dev/usb0 -.It Pa /dev/usb1 -.It etc . -.El -.Sh SEE ALSO -.Xr usb 4 , -.Xr usbd.conf 5 -.Sh HISTORY -The -.Nm -utility appeared in -.Nx 1.4 . -.Sh AUTHORS -.An -nosplit -The -.Nm -driver was written by -.An Lennart Augustsson Aq Mt augustss@carlstedt.se -for the -.Nx -project. -The event queue handling in -.Nm -was added by -.An Nick Hibma Aq Mt n_hibma@FreeBSD.org . diff --git a/usr.sbin/usbd/usbd.c b/usr.sbin/usbd/usbd.c deleted file mode 100644 index 934d845def..0000000000 --- a/usr.sbin/usbd/usbd.c +++ /dev/null @@ -1,1128 +0,0 @@ -/* - * $NetBSD: usbd.c,v 1.4 1998/12/09 00:57:19 augustss Exp $ - * $FreeBSD: src/usr.sbin/usbd/usbd.c,v 1.29 2003/10/25 22:03:10 jmg Exp $ - */ - -/* - * Copyright (c) 1998 The NetBSD Foundation, Inc. - * All rights reserved. - * - * This code is derived from software contributed to The NetBSD Foundation - * by Lennart Augustsson (augustss@netbsd.org). - * - * 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. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the NetBSD - * Foundation, Inc. and its contributors. - * 4. Neither the name of The NetBSD Foundation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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. - */ - -/* USBD creates 'threads' in the kernel, used for doing discovery when a - * device has attached or detached. This functionality should be removed - * once kernel threads have been added to the kernel. - * It also handles the event queue, and executing commands based on those - * events. - * - * See usbd(8). - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -/* default name of configuration file - */ - -#define CONFIGFILE "/etc/usbd.conf" - -/* the name of the device spitting out usb attach/detach events as well as - * the prefix for the individual busses (used as a semi kernel thread). - */ -#define USBDEV "/dev/usb" - -/* Maximum number of USB busses expected to be in a system - * XXX should be replaced by dynamic allocation. - */ -#define MAXUSBDEV 4 - -/* Sometimes a device does not respond in time for interrupt - * driven explore to find it. Therefore we run an exploration - * at regular intervals to catch those. - */ -#define TIMEOUT 30 - -/* The wildcard used in actions for strings and integers - */ -#define WILDCARD_STRING NULL -#define WILDCARD_INT -1 - - -extern char *__progname; /* name of program */ - -const char *configfile = CONFIGFILE; /* name of configuration file */ - -char *devs[MAXUSBDEV]; /* device names */ -int fds[MAXUSBDEV]; /* file descriptors for USBDEV\d+ */ -int ndevs = 0; /* number of entries in fds / devs */ -int fd = -1; /* file descriptor for USBDEV */ - -int lineno; -int verbose = 0; /* print message on what it is doing */ - -typedef struct event_name_s { - int type; /* event number (from usb.h) */ - const char *name; -} event_name_t; - -event_name_t event_names[] = { - {USB_EVENT_CTRLR_ATTACH, "ctrlr-attach"}, - {USB_EVENT_CTRLR_DETACH, "ctrlr-detach"}, - {USB_EVENT_DRIVER_ATTACH, "driver-attach"}, - {USB_EVENT_DRIVER_DETACH, "driver-detach"}, - {USB_EVENT_DEVICE_ATTACH, "device-attach"}, - {USB_EVENT_DEVICE_DETACH, "device-detach"}, - {0, NULL} /* NULL indicates end of list, not 0 */ -}; - -#define DEVICE_FIELD 0 /* descriptive field */ - -#define VENDOR_FIELD 1 /* selective fields */ -#define PRODUCT_FIELD 2 -#define RELEASE_FIELD 3 -#define CLASS_FIELD 4 -#define SUBCLASS_FIELD 5 -#define PROTOCOL_FIELD 6 -#define DEVNAME_FIELD 7 - -#define ATTACH_FIELD 8 /* command fields */ -#define DETACH_FIELD 9 - - -typedef struct action_s { - char *name; /* descriptive string */ - - int vendor; /* selection criteria */ - int product; - int release; - int class; - int subclass; - int protocol; - char *devname; - regex_t devname_regex; - - char *attach; /* commands to execute */ - char *detach; - - STAILQ_ENTRY(action_s) next; -} action_t; - -STAILQ_HEAD(action_list, action_s) actions = STAILQ_HEAD_INITIALIZER(actions); - -typedef struct action_match_s { - action_t *action; - char *devname; -} action_match_t; - - -/* the function returns 0 for failure, 1 for all arguments found and 2 for - * arguments left over in trail. - */ -typedef int (*config_field_fn)(action_t *action, char *args, char **trail); - -static void execute_command(char *); -static int find_action(struct usb_device_info *, action_match_t *); -static int get_integer(char *, int *, char **); -static int get_string(char *, char **, char **); -static int match_devname(action_t *, struct usb_device_info *); -static void print_action(action_t *, int); -static void print_actions(void); -static void print_event(struct usb_event *); -static void process_event_queue(int); -static void read_configuration(void); -static int set_attach_field(action_t *, char *, char **); -static int set_class_field(action_t *, char *, char **); -static int set_detach_field(action_t *, char *, char **); -static int set_device_field(action_t *, char *, char **); -static int set_devname_field(action_t *, char *, char **); -static int set_product_field(action_t *, char *, char **); -static int set_protocol_field(action_t *, char *, char **); -static int set_release_field(action_t *, char *, char **); -static int set_subclass_field(action_t *, char *, char **); -static int set_vendor_field(action_t *, char *, char **); -static void usage(void); - - -/* the list of fields supported in an entry */ -typedef struct config_field_s { - int event; - const char *name; - config_field_fn function; -} config_field_t; - -config_field_t config_fields[] = { - {DEVICE_FIELD, "device", set_device_field}, - - {VENDOR_FIELD, "vendor", set_vendor_field}, - {PRODUCT_FIELD, "product", set_product_field}, - {RELEASE_FIELD, "release", set_release_field}, - {CLASS_FIELD, "class", set_class_field}, - {SUBCLASS_FIELD, "subclass", set_subclass_field}, - {PROTOCOL_FIELD, "protocol", set_protocol_field}, - {DEVNAME_FIELD, "devname", set_devname_field}, - - {ATTACH_FIELD, "attach", set_attach_field}, - {DETACH_FIELD, "detach", set_detach_field}, - - {0, NULL, NULL} /* NULL is EOL marker, not the 0 */ -}; - -static void -usage(void) -{ - fprintf(stderr, "usage: %s [-d] [-v] [-t timeout] [-e] [-f dev]\n" - " [-n] [-c config]\n", - __progname); - exit(1); -} - - -/* generic helper functions for the functions to set the fields of actions */ -static int -get_string(char *src, char **rdst, char **rsrc) -{ - /* Takes the first string from src, taking quoting into account. - * rsrc (if not NULL) is set to the first byte not included in the - * string returned in rdst. - * - * Input is: - * src = 'fir"st \'par"t second part'; - * Returned is: - * *dst = 'hello \'world'; - * if (rsrc != NULL) - * *rsrc = 'second part'; - * - * Notice the fact that the single quote enclosed in double quotes is - * returned. Also notice that before second part there is more than - * one space, which is removed in rsrc. - * - * The string in src is not modified. - */ - - char *dst; /* destination string */ - size_t i; /* index into src */ - int j; /* index into dst */ - int quoted = 0; /* 1 for single, 2 for double quoted */ - - dst = malloc(strlen(src)+1); /* XXX allocation is too big, realloc?*/ - if (dst == NULL) { /* should not happen, really */ - fprintf(stderr, "%s:%d: Out of memory\n", configfile, lineno); - exit(2); - } - - /* find the end of the current string. If quotes are found the search - * continues until the corresponding quote is found. - * So, - * hel'lo" "wor'ld - * represents the string - * hello" "world - * and not (hello world). - */ - for (i = 0, j = 0; i < strlen(src); i++) { - if (src[i] == '\'' && (quoted == 0 || quoted == 1)) { - quoted = (quoted? 0:1); - } else if (src[i] == '"' && (quoted == 0 || quoted == 2)) { - quoted = (quoted? 0:2); - } else if (isspace(src[i]) && !quoted) { - /* found a space outside quotes -> terminates src */ - break; - } else { - dst[j++] = src[i]; /* copy character */ - } - } - - /* quotes being left open? */ - if (quoted) { - fprintf(stderr, "%s:%d: Missing %s quote at end of '%s'\n", - configfile, lineno, - (quoted == 1? "single":"double"), src); - exit(2); - } - - /* skip whitespace for second part */ - for (/*i is set*/; i < strlen(src) && isspace(src[i]); i++) - ; /* nop */ - - dst[j] = '\0'; /* make sure it's NULL terminated */ - - *rdst = dst; /* and return the pointers */ - if (rsrc != NULL) /* if info wanted */ - *rsrc = &src[i]; - - if (*dst == '\0') { /* empty string */ - return 0; - } else if (src[i] == '\0') { /* completely used (1 argument) */ - return 1; - } else { /* 2 or more args, *rsrc is rest */ - return 2; - } -} - -static int -get_integer(char *src, int *dst, char **rsrc) -{ - char *endptr; - - /* Converts str to a number. If one argument was found in - * str, 1 is returned and *dst is set to the value of the integer. - * If 2 or more arguments were presented, 2 is returned, - * *dst is set to the converted value and rsrc, if not null, points - * at the start of the next argument (whitespace skipped). - * Else 0 is returned and nothing else is valid. - */ - - if (src == NULL || *src == '\0') /* empty src */ - return(0); - - *dst = (int) strtol(src, &endptr, 0); - - /* skip over whitespace of second argument */ - while (isspace(*endptr)) - endptr++; - - if (rsrc) - *rsrc = endptr; - - if (isspace(*endptr)) { /* partial match, 2 or more arguments */ - return(2); - } else if (*endptr == '\0') { /* full match, 1 argument */ - return(1); - } else { /* invalid src, no match */ - return(0); - } -} - -/* functions to set the fields of the actions appropriately */ -static int -set_device_field(action_t *action, char *args, char **trail) -{ - return(get_string(args, &action->name, trail)); -} - -static int -set_vendor_field(action_t *action, char *args, char **trail) -{ - return(get_integer(args, &action->vendor, trail)); -} - -static int -set_product_field(action_t *action, char *args, char **trail) -{ - return(get_integer(args, &action->product, trail)); -} - -static int -set_release_field(action_t *action, char *args, char **trail) -{ - return(get_integer(args, &action->release, trail)); -} - -static int -set_class_field(action_t *action, char *args, char **trail) -{ - return(get_integer(args, &action->class, trail)); -} - -static int -set_subclass_field(action_t *action, char *args, char **trail) -{ - return(get_integer(args, &action->subclass, trail)); -} - -static int -set_protocol_field(action_t *action, char *args, char **trail) -{ - return(get_integer(args, &action->protocol, trail)); -} - -static int -set_devname_field(action_t *action, char *args, char **trail) -{ - int match = get_string(args, &action->devname, trail); - int len; - int error; - char *string; -# define ERRSTR_SIZE 100 - char errstr[ERRSTR_SIZE]; - - if (match == 0) - return(0); - - len = strlen(action->devname); - string = malloc(len + 15); - if (string == NULL) - return(0); - - bcopy(action->devname, string+7, len); /* make some space for */ - bcopy("[[:<:]]", string, 7); /* beginning of word */ - bcopy("[[:>:]]", string+7+len, 7); /* and end of word */ - string[len + 14] = '\0'; - - error = regcomp(&action->devname_regex, string, REG_NOSUB|REG_EXTENDED); - if (error) { - errstr[0] = '\0'; - regerror(error, &action->devname_regex, errstr, ERRSTR_SIZE); - fprintf(stderr, "%s:%d: %s\n", configfile, lineno, errstr); - return(0); - } - - return(match); -} - -static int -set_attach_field(action_t *action, char *args, char **trail) -{ - return(get_string(args, &action->attach, trail)); -} - -static int -set_detach_field(action_t *action, char *args, char **trail) -{ - return(get_string(args, &action->detach, trail)); -} - -static void -read_configuration(void) -{ - FILE *file; /* file descriptor */ - char *line; /* current line */ - char *linez; /* current line, NULL terminated */ - char *field; /* first part, the field name */ - char *args; /* second part, arguments */ - char *trail; /* remaining part after parsing, should be '' */ - size_t len; /* length of current line */ - int i,j; /* loop counters */ - action_t *action = NULL; /* current action */ - - file = fopen(configfile, "r"); - if (file == NULL) { - fprintf(stderr, "%s: Could not open for reading, %s\n", - configfile, strerror(errno)); - exit(2); - } - - for (lineno = 1; /* nop */;lineno++) { - - line = fgetln(file, &len); - if (line == NULL) { - if (feof(file)) /* EOF */ - break; - if (ferror(file)) { - fprintf(stderr, "%s:%d: Could not read, %s\n", - configfile, lineno, strerror(errno)); - exit(2); - } - } - - /* skip initial spaces */ - while (len > 0 && isspace(*line)) { - line++; - len--; - } - - if (len == 0) /* empty line */ - continue; - if (line[0] == '#') /* comment line */ - continue; - - /* make a NULL terminated copy of the string */ - linez = malloc(len+1); - if (linez == NULL) { - fprintf(stderr, "%s:%d: Out of memory\n", - configfile, lineno); - exit(2); - } - strncpy(linez, line, len); - linez[len] = '\0'; - - /* find the end of the current word (is field), that's the - * start of the arguments - */ - field = linez; - args = linez; - while (*args != '\0' && !isspace(*args)) - args++; - - /* If arguments is not the empty string, NULL terminate the - * field and move the argument pointer to the first character - * of the arguments. - * If arguments is the empty string field and arguments both - * are terminated (strlen(field) >= 0, strlen(arguments) == 0). - */ - if (*args != '\0') { - *args = '\0'; - args++; - } - - /* Skip initial spaces */ - while (*args != '\0' && isspace(*args)) - args++; - - /* Cut off trailing whitespace */ - for (i = 0, j = 0; args[i] != '\0'; i++) - if (!isspace(args[i])) - j = i+1; - args[j] = '\0'; - - /* We now have the field and the argument separated into - * two strings that are NULL terminated - */ - - /* If the field is 'device' we have to start a new action. */ - if (strcmp(field, "device") == 0) { - /* Allocate a new action and set defaults */ - action = malloc(sizeof(*action)); - if (action == NULL) { - fprintf(stderr, "%s:%d: Out of memory\n", - configfile, lineno); - exit(2); - } - memset(action, 0, sizeof(*action)); - action->product = WILDCARD_INT; - action->vendor = WILDCARD_INT; - action->release = WILDCARD_INT; - action->class = WILDCARD_INT; - action->subclass = WILDCARD_INT; - action->protocol = WILDCARD_INT; - action->devname = WILDCARD_STRING; - - /* Add it to the end of the list to preserve order */ - STAILQ_INSERT_TAIL(&actions, action, next); - } - - if (action == NULL) { - line[len] = '\0'; /* XXX zero terminate */ - fprintf(stderr, "%s:%d: Doesn't start with 'device' " - "but '%s'\n", configfile, lineno, field); - exit(2); - } - - for (i = 0; config_fields[i].name ; i++) { - /* does the field name match? */ - if (strcmp(config_fields[i].name, field) == 0) { - /* execute corresponding set-field function */ - if ((config_fields[i].function)(action, args, - &trail) - != 1) { - fprintf(stderr,"%s:%d: " - "Syntax error in '%s'\n", - configfile, lineno, linez); - exit(2); - } - break; - } - } - if (config_fields[i].name == NULL) { /* Reached end of list*/ - fprintf(stderr, "%s:%d: Unknown field '%s'\n", - configfile, lineno, field); - exit(2); - } - } - - fclose(file); - - if (verbose >= 2) - print_actions(); -} - - -static void -print_event(struct usb_event *event) -{ - int i; - struct timespec *timespec = &event->ue_time; - struct usb_device_info *devinfo = &event->u.ue_device; - - printf("%s: ", __progname); - for (i = 0; event_names[i].name != NULL; i++) { - if (event->ue_type == event_names[i].type) { - printf("%s event", event_names[i].name); - break; - } - } - if (event_names[i].name == NULL) - printf("unknown event %d", event->ue_type); - - if (event->ue_type == USB_EVENT_DEVICE_ATTACH || - event->ue_type == USB_EVENT_DEVICE_DETACH) { - devinfo = &event->u.ue_device; - - printf(" at %ld.%09ld, %s, %s:\n", - timespec->tv_sec, timespec->tv_nsec, - devinfo->udi_product, devinfo->udi_vendor); - - printf(" vndr=0x%04x prdct=0x%04x rlse=0x%04x " - "clss=0x%04x subclss=0x%04x prtcl=0x%04x\n", - devinfo->udi_vendorNo, devinfo->udi_productNo, - devinfo->udi_releaseNo, - devinfo->udi_class, devinfo->udi_subclass, devinfo->udi_protocol); - - if (devinfo->udi_devnames[0][0] != '\0') { - char c = ' '; - - printf(" device names:"); - for (i = 0; i < USB_MAX_DEVNAMES; i++) { - if (devinfo->udi_devnames[i][0] == '\0') - break; - - printf("%c%s", c, devinfo->udi_devnames[i]); - c = ','; - } - } - } else if (event->ue_type == USB_EVENT_CTRLR_ATTACH || - event->ue_type == USB_EVENT_CTRLR_DETACH) { - printf(" bus=%d", event->u.ue_ctrlr.ue_bus); - } else if (event->ue_type == USB_EVENT_DRIVER_ATTACH || - event->ue_type == USB_EVENT_DRIVER_DETACH) { - printf(" cookie=%u devname=%s", - event->u.ue_driver.ue_cookie.cookie, - event->u.ue_driver.ue_devname); - } - printf("\n"); -} - -static void -print_action(action_t *action, int i) -{ - if (action == NULL) - return; - - printf("%s: action %d: %s\n", - __progname, i, - (action->name? action->name:"")); - if (action->product != WILDCARD_INT || - action->vendor != WILDCARD_INT || - action->release != WILDCARD_INT || - action->class != WILDCARD_INT || - action->subclass != WILDCARD_INT || - action->protocol != WILDCARD_INT) - printf(" "); - if (action->vendor != WILDCARD_INT) - printf(" vndr=0x%04x", action->vendor); - if (action->product != WILDCARD_INT) - printf(" prdct=0x%04x", action->product); - if (action->release != WILDCARD_INT) - printf(" rlse=0x%04x", action->release); - if (action->class != WILDCARD_INT) - printf(" clss=0x%04x", action->class); - if (action->subclass != WILDCARD_INT) - printf(" subclss=0x%04x", action->subclass); - if (action->protocol != WILDCARD_INT) - printf(" prtcl=0x%04x", action->protocol); - if (action->vendor != WILDCARD_INT || - action->product != WILDCARD_INT || - action->release != WILDCARD_INT || - action->class != WILDCARD_INT || - action->subclass != WILDCARD_INT || - action->protocol != WILDCARD_INT) - printf("\n"); - if (action->devname != WILDCARD_STRING) - printf(" devname: %s\n", action->devname); - - if (action->attach != NULL) - printf(" attach='%s'\n", - action->attach); - if (action->detach != NULL) - printf(" detach='%s'\n", - action->detach); -} - -static void -print_actions(void) -{ - int i = 0; - action_t *action; - - STAILQ_FOREACH(action, &actions, next) - print_action(action, ++i); - - printf("%s: %d action%s\n", __progname, i, (i == 1? "":"s")); -} - - -static int -match_devname(action_t *action, struct usb_device_info *devinfo) -{ - int i; - regmatch_t match; - int error; - - for (i = 0; i < USB_MAX_DEVNAMES; i++) { - if (devinfo->udi_devnames[i][0] == '\0') - break; - - error = regexec(&action->devname_regex, devinfo->udi_devnames[i], - 1, &match, 0); - if (error == 0) { - if (verbose >= 2) - printf("%s: %s matches %s\n", __progname, - devinfo->udi_devnames[i], action->devname); - return(i); - } - } - - return(-1); -} - - -static int -find_action(struct usb_device_info *devinfo, action_match_t *action_match) -{ - action_t *action; - char *_devname = NULL; - int match = -1; - - STAILQ_FOREACH(action, &actions, next) { - if ((action->vendor == WILDCARD_INT || - action->vendor == devinfo->udi_vendorNo) && - (action->product == WILDCARD_INT || - action->product == devinfo->udi_productNo) && - (action->release == WILDCARD_INT || - action->release == devinfo->udi_releaseNo) && - (action->class == WILDCARD_INT || - action->class == devinfo->udi_class) && - (action->subclass == WILDCARD_INT || - action->subclass == devinfo->udi_subclass) && - (action->protocol == WILDCARD_INT || - action->protocol == devinfo->udi_protocol) && - (action->devname == WILDCARD_STRING || - (match = match_devname(action, devinfo)) != -1)) { - /* found match !*/ - - /* Find a devname for pretty printing. Either - * the matched one or otherwise, if there is only - * one devname for that device, use that. - */ - if (match >= 0) - _devname = devinfo->udi_devnames[match]; - else if (devinfo->udi_devnames[0][0] != '\0' && - devinfo->udi_devnames[1][0] == '\0') - /* if we have exactly 1 device name */ - _devname = devinfo->udi_devnames[0]; - - if (verbose) { - printf("%s: Found action '%s' for %s, %s", - __progname, action->name, - devinfo->udi_product, devinfo->udi_vendor); - if (_devname) - printf(" at %s", _devname); - printf("\n"); - } - - action_match->action = action; - action_match->devname = _devname; - - return(1); - } - } - - return(0); -} - -static void -execute_command(char *cmd) -{ - pid_t pid; - struct sigaction ign, intact, quitact; - sigset_t newsigblock, oldsigblock; - int status; - int i; - - if (verbose) - printf("%s: Executing '%s'\n", __progname, cmd); - if (cmd == NULL) - return; - - /* The code below is directly taken from the system(3) call. - * Added to it is the closing of open file descriptors. - */ - /* - * Ignore SIGINT and SIGQUIT, block SIGCHLD. Remember to save - * existing signal dispositions. - */ - ign.sa_handler = SIG_IGN; - sigemptyset(&ign.sa_mask); - ign.sa_flags = 0; - sigaction(SIGINT, &ign, &intact); - sigaction(SIGQUIT, &ign, &quitact); - sigemptyset(&newsigblock); - sigaddset(&newsigblock, SIGCHLD); - sigprocmask(SIG_BLOCK, &newsigblock, &oldsigblock); - pid = fork(); - if (pid == -1) { - fprintf(stderr, "%s: fork failed, %s\n", - __progname, strerror(errno)); - } else if (pid == 0) { - /* child here */ - - /* close all open file handles for USBDEV\d* devices */ - for (i = 0; i < ndevs; i++) - close(fds[i]); /* USBDEV\d+ */ - close(fd); /* USBDEV */ - - /* Restore original signal dispositions and exec the command. */ - sigaction(SIGINT, &intact, NULL); - sigaction(SIGQUIT, &quitact, NULL); - sigprocmask(SIG_SETMASK, &oldsigblock, NULL); - - execl(_PATH_BSHELL, "sh", "-c", cmd, NULL); - - /* should only be reached in case of error */ - exit(127); - } else { - /* parent here */ - do { - pid = waitpid(pid, &status, 0); - } while (pid == -1 && errno == EINTR); - } - sigaction(SIGINT, &intact, NULL); - sigaction(SIGQUIT, &quitact, NULL); - sigprocmask(SIG_SETMASK, &oldsigblock, NULL); - - if (pid == -1) { - fprintf(stderr, "%s: waitpid returned: %s\n", - __progname, strerror(errno)); - } else if (pid == 0) { - fprintf(stderr, "%s: waitpid returned 0 ?!\n", - __progname); - } else { - if (status == -1) { - fprintf(stderr, "%s: Could not start '%s'\n", - __progname, cmd); - } else if (status == 127) { - fprintf(stderr, "%s: Shell failed for '%s'\n", - __progname, cmd); - } else if (WIFEXITED(status) && WEXITSTATUS(status)) { - fprintf(stderr, "%s: '%s' returned %d\n", - __progname, cmd, WEXITSTATUS(status)); - } else if (WIFSIGNALED(status)) { - fprintf(stderr, "%s: '%s' caught signal %d\n", - __progname, cmd, WTERMSIG(status)); - } else if (verbose >= 2) { - printf("%s: '%s' is ok\n", __progname, cmd); - } - } -} - -static void -process_event_queue(int fdesc) -{ - struct usb_event event; - int error; - int len; - action_match_t action_match; - - for (;;) { - len = read(fdesc, &event, sizeof(event)); - if (len == -1) { - if (errno == EWOULDBLOCK) { - /* no more events */ - break; - } else { - fprintf(stderr,"%s: Could not read event, %s\n", - __progname, strerror(errno)); - exit(1); - } - } - if (len == 0) - break; - if (len != sizeof(event)) { - fprintf(stderr, "partial read on %s\n", USBDEV); - exit(1); - } - - /* we seem to have gotten a valid event */ - - if (verbose) - print_event(&event); - - /* handle the event appropriately */ - switch (event.ue_type) { - case USB_EVENT_CTRLR_ATTACH: - if (verbose) - printf("USB_EVENT_CTRLR_ATTACH\n"); - break; - case USB_EVENT_CTRLR_DETACH: - if (verbose) - printf("USB_EVENT_CTRLR_DETACH\n"); - break; - case USB_EVENT_DEVICE_ATTACH: - case USB_EVENT_DEVICE_DETACH: - if (find_action(&event.u.ue_device, &action_match) == 0) - /* nothing found */ - break; - - if (verbose >= 2) - print_action(action_match.action, 0); - - if (action_match.devname) { - if (verbose >= 2) - printf("%s: Setting DEVNAME='%s'\n", - __progname, action_match.devname); - - error = setenv("DEVNAME", action_match.devname, 1); - if (error) - fprintf(stderr, "%s: setenv(\"DEVNAME\", \"%s\",1) failed, %s\n", - __progname, action_match.devname, strerror(errno)); - } - - if (USB_EVENT_IS_ATTACH(event.ue_type) && - action_match.action->attach) - execute_command(action_match.action->attach); - if (USB_EVENT_IS_DETACH(event.ue_type) && - action_match.action->detach) - execute_command(action_match.action->detach); - break; - case USB_EVENT_DRIVER_ATTACH: - if (verbose) - printf("USB_EVENT_DRIVER_ATTACH\n"); - break; - case USB_EVENT_DRIVER_DETACH: - if (verbose) - printf("USB_EVENT_DRIVER_DETACH\n"); - break; - default: - printf("Unknown USB event %d\n", event.ue_type); - } - } -} - - -int -main(int argc, char **argv) -{ - int error, i; - int ch; /* getopt option */ - int debug = 0; /* print debugging output */ - int explore_once = 0; /* don't do only explore */ - int handle_events = 1; /* do handle the event queue */ - int maxfd; /* maximum fd in use */ - char buf[50]; /* for creation of the filename */ - fd_set r,w; - int itimeout = TIMEOUT; /* timeout for select */ - struct timeval tv; - - if (modfind(USB_UHUB) < 0) { - if (kldload(USB_KLD) < 0 || modfind(USB_UHUB) < 0) { - perror(USB_KLD ": Kernel module not available"); - return 1; - } - } - - while ((ch = getopt(argc, argv, "c:def:nt:v")) != -1) { - switch(ch) { - case 'c': - configfile = strdup(optarg); - if (configfile == NULL) { - fprintf(stderr, "strdup returned NULL\n"); - return 1; - } - break; - case 'd': - debug++; - break; - case 'e': - explore_once = 1; - break; - case 'f': - if (ndevs < MAXUSBDEV) - devs[ndevs++] = optarg; - break; - case 'n': - handle_events = 0; - break; - case 't': - itimeout = atoi(optarg); - break; - case 'v': - verbose++; - break; - case '?': - default: - usage(); - } - } - argc -= optind; - argv += optind; - - maxfd = 0; - if (ndevs == 0) { - /* open all the USBDEVS\d+ devices */ - for (i = 0; i < MAXUSBDEV; i++) { - sprintf(buf, "%s%d", USBDEV, i); - fds[ndevs] = open(buf, O_RDWR); - if (fds[ndevs] >= 0) { - devs[ndevs] = strdup(buf); - if (devs[ndevs] == NULL) { - fprintf(stderr, "strdup returned NULL\n"); - return 1; - } - if (verbose) - printf("%s: opened %s\n", - __progname, devs[ndevs]); - if (fds[ndevs] > maxfd) - maxfd = fds[ndevs]; - ndevs++; - } else if (errno != ENXIO && errno != ENOENT) { - /* there was an error, on a device that does - * exist (device is configured) - */ - fprintf(stderr, "%s: Could not open %s, %s\n", - __progname, buf, strerror(errno)); - exit(1); - } - } - } else { - /* open all the files specified with -f */ - for (i = 0; i < ndevs; i++) { - fds[i] = open(devs[i], O_RDWR); - if (fds[i] < 0) { - fprintf(stderr, "%s: Could not open %s, %s\n", - __progname, devs[i], strerror(errno)); - exit(1); - } else { - if (verbose) - printf("%s: opened %s\n", - __progname, devs[i]); - if (fds[i] > maxfd) - maxfd = fds[i]; - } - } - } - - if (ndevs == 0) { - fprintf(stderr, "No USB host controllers found\n"); - exit(1); - } - - - /* Do the explore once and exit */ - if (explore_once) { - for (i = 0; i < ndevs; i++) { - error = ioctl(fds[i], USB_DISCOVER); - if (error < 0) { - fprintf(stderr, "%s: ioctl(%s, USB_DISCOVER) " - "failed, %s\n", - __progname, devs[i], strerror(errno)); - exit(1); - } - } - exit(0); - } - - if (handle_events) { - if (verbose) - printf("%s: reading configuration file %s\n", - __progname, configfile); - read_configuration(); - - fd = open(USBDEV, O_RDONLY | O_NONBLOCK); - if (fd < 0) { - fprintf(stderr, "%s: Could not open %s, %s\n", - __progname, USBDEV, strerror(errno)); - exit(1); - } - if (verbose) - printf("%s: opened %s\n", __progname, USBDEV); - if (fd > maxfd) - maxfd = fd; - - process_event_queue(fd); /* dequeue the initial events */ - } - - /* move to the background */ - if (!debug) - daemon(0, 0); - - /* start select on all the open file descriptors */ - for (;;) { - FD_ZERO(&r); - FD_ZERO(&w); - if (handle_events) - FD_SET(fd, &r); /* device USBDEV */ - for (i = 0; i < ndevs; i++) - FD_SET(fds[i], &w); /* device USBDEV\d+ */ - tv.tv_usec = 0; - tv.tv_sec = itimeout; - error = select(maxfd+1, &r, &w, 0, itimeout ? &tv : 0); - if (error < 0) { - fprintf(stderr, "%s: Select failed, %s\n", - __progname, strerror(errno)); - exit(1); - } - - /* USBDEV\d+ devices have signaled change, do a usb_discover */ - for (i = 0; i < ndevs; i++) { - if (error == 0 || FD_ISSET(fds[i], &w)) { - if (verbose >= 2) - printf("%s: doing %sdiscovery on %s\n", - __progname, - (error? "":"timeout "), devs[i]); - if (ioctl(fds[i], USB_DISCOVER) < 0) { - fprintf(stderr, "%s: ioctl(%s, " - "USB_DISCOVER) failed, %s\n", - __progname, devs[i], - strerror(errno)); - exit(1); - } - } - } - - /* check the event queue */ - if (handle_events && (FD_ISSET(fd, &r) || error == 0)) { - if (verbose >= 2) - printf("%s: processing event queue %son %s\n", - __progname, - (error? "":"due to timeout "), USBDEV); - process_event_queue(fd); - } - } -} diff --git a/usr.sbin/usbd/usbd.conf.5 b/usr.sbin/usbd/usbd.conf.5 deleted file mode 100644 index cc86d4f905..0000000000 --- a/usr.sbin/usbd/usbd.conf.5 +++ /dev/null @@ -1,163 +0,0 @@ -.\" -.\" Copyright (c) 1999 Nick Hibma. 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. -.\" 3. The name of the author may not be used to endorse or promote products -.\" derived from this software without specific prior written permission. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 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: src/usr.sbin/usbd/usbd.conf.5,v 1.13 2003/01/30 22:38:54 trhodes Exp $ -.\" -.\" Many parts of this manual have been snarfed from the pccard.conf (5) man -.\" page, copyright by Andrew McRae. -.\" -.Dd November 19, 1999 -.Dt USBD.CONF 5 -.Os -.Sh NAME -.Nm usbd.conf -.Nd -.Xr usbd 8 -configuration file -.Sh DESCRIPTION -The -.Nm -file is the configuration file for the -.Xr usbd 8 -daemon. -It provides information to allow execution of userland commands -on events reported by the -.Xr usb 4 -subsystem in the kernel. -Currently the only events are device attach and -detach, but could in the future be extended to include power management -functions. -.Pp -The configuration file consists of a sorted list of entries. -Each entry -describes a set of criteria commands. -When an event occurs, the criteria -are checked and if met, the commands for that event are executed through -a shell. -The list is sorted and scanned from top to bottom. -The first -matching entry is used for an event. -.Pp -Each entry contains a number of fields. -There are 3 types of fields: -descriptive fields, selection criteria and commands to execute on -events. -The field names are case sensitive and should be all lower case. -Each field can have one or more arguments. -.Pp -The following fields are available: -.Bl -tag -width devicename\ -.It device Ar string -Start a new entry. -.Ar string -is an arbitrary string used for pretty printing. -.It product Ar id -Product Id -.It vendor Ar id -Vendor Id -.It release Ar id -Release Id, also called revision Id sometimes. -.It class Ar id -Device Class -.It subclass Ar id -Device Subclass -.It protocol Ar id -Device Protocol -.It devname Ar string -Device name, for example umass2, or ums0. -These device names can contain regular expressions. -See -.Xr regex 3 -and -.Xr re_format 7 . -The device name that is matched can be used in the commands below -through adding ${DEVNAME} somewhere in that string. -.El -.Pp -String arguments may be quoted. -If a string argument contains a space or -tab character it needs to be enclosed in single or double quotes. -If an -argument contains a single or double quote, that quote needs to be -enclosed in double or single quotes respectively. -See below for -examples. -.Pp -Numeric arguments can either be specified in decimal (42), octal (052) or -hexadecimal (0x2a). -.Pp -The values for the fields -.Li product , vendor , release, class , subclass -and -.Li protocol -can be retrieved by killing the -.Nm usbd -daemon and running it with the -.Fl d -and -.Fl v -flags. -.Pp -Commands to be executed when the action is matched: -.Bl -tag -width devicename\ -.It attach Ar string -Shell command to execute when a device is attached. -.It detach Ar string -Shell command to execute when a device is detached. -.El -.Sh FILES -.Bl -tag -width /etc/usbd.conf -compact -.It Pa /etc/usbd.conf -The -.Nm usbd -configuration file. -.El -.Sh EXAMPLES -A sample entry to rescan the SCSI bus on connection of a -.Tn "Iomega USB Zip Drive" : -.Bd -literal - device "USB Zip drive" - product 0x0001 - vendor 0x059b - release 0x0100 - attach "/usr/bin/camcontrol rescan bus 0" -.Ed -.Pp -To start up moused for a newly attached mouse: -.Bd -literal - device "Mouse" - devname "ums[0-9]+" - attach "/usr/sbin/moused -p /dev/${DEVNAME} -I /var/run/moused.${DEVNAME}.pid" -.Ed -.Sh SEE ALSO -.Xr usb 4 , -.Xr usbd 8 , -.Xr usbdevs 8 -.Sh AUTHORS -This manual page was written by -.An Nick Hibma Aq Mt n_hibma@FreeBSD.org . -.Sh BUGS -It is currently not possible to use a selection criterion more than once. -For example, it is not possible to specify more than one vendor ID. diff --git a/usr.sbin/usbdevs/Makefile b/usr.sbin/usbdevs/Makefile deleted file mode 100644 index f4ae4f8d7d..0000000000 --- a/usr.sbin/usbdevs/Makefile +++ /dev/null @@ -1,9 +0,0 @@ -# $NetBSD: Makefile,v 1.2 1998/07/12 20:40:45 augustss Exp $ -# $FreeBSD: src/usr.sbin/usbdevs/Makefile,v 1.5.2.1 2001/04/25 12:11:08 ru Exp $ -# $DragonFly: src/usr.sbin/usbdevs/Makefile,v 1.4 2005/01/17 01:49:24 cpressey Exp $ - -PROG= usbdevs -MAN= usbdevs.8 -CFLAGS+=-I${.CURDIR}/../../sys - -.include diff --git a/usr.sbin/usbdevs/usbdevs.8 b/usr.sbin/usbdevs/usbdevs.8 deleted file mode 100644 index ac47ac0d2b..0000000000 --- a/usr.sbin/usbdevs/usbdevs.8 +++ /dev/null @@ -1,74 +0,0 @@ -.\" Copyright (c) 1999 The NetBSD Foundation, Inc. -.\" All rights reserved. -.\" -.\" Author: Lennart Augustsson -.\" -.\" 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. -.\" 3. All advertising materials mentioning features or use of this software -.\" must display the following acknowledgement: -.\" This product includes software developed by the NetBSD -.\" Foundation, Inc. and its contributors. -.\" 4. Neither the name of The NetBSD Foundation nor the names of its -.\" contributors may be used to endorse or promote products derived -.\" from this software without specific prior written permission. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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. -.\" -.\" $NetBSD: usbdevs.8,v 1.5 2000/10/15 12:44:11 bjh21 Exp $ -.\" $FreeBSD: src/usr.sbin/usbdevs/usbdevs.8,v 1.10 2002/07/14 14:46:46 charnier Exp $ -.\" $DragonFly: src/usr.sbin/usbdevs/usbdevs.8,v 1.3 2003/12/30 01:01:48 dillon Exp $ -.\" -.Dd October 15, 2000 -.Dt USBDEVS 8 -.Os -.Sh NAME -.Nm usbdevs -.Nd show USB devices connected to the system -.Sh SYNOPSIS -.Nm -.Op Fl a Ar addr -.Op Fl d -.Op Fl f Ar dev -.Op Fl v -.Sh DESCRIPTION -The -.Nm -utility prints a listing of all USB devices connected to the system -with some information about each device. -The indentation of each line indicates its distance from the root. -.Pp -The options are as follows: -.Bl -tag -width ".Fl a Ar addr" -.It Fl a Ar addr -only print information about the device at the given address. -.It Fl d -Show the device drivers associated with each device. -.It Fl f Ar dev -only print information for the given USB controller. -.It Fl v -Be verbose. -.El -.Sh SEE ALSO -.Xr usb 4 -.Sh HISTORY -The -.Nm -utility appeared in -.Nx 1.4 . diff --git a/usr.sbin/usbdevs/usbdevs.c b/usr.sbin/usbdevs/usbdevs.c deleted file mode 100644 index 5854337d9e..0000000000 --- a/usr.sbin/usbdevs/usbdevs.c +++ /dev/null @@ -1,227 +0,0 @@ -/* - * $NetBSD: usbdevs.c,v 1.17 2001/02/19 23:22:48 cgd Exp $ - * $FreeBSD: src/usr.sbin/usbdevs/usbdevs.c,v 1.8 2002/04/22 13:44:47 des Exp $ - */ - -/* - * Copyright (c) 1998 The NetBSD Foundation, Inc. - * All rights reserved. - * - * This code is derived from software contributed to The NetBSD Foundation - * by Lennart Augustsson (augustss@netbsd.org). - * - * 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. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the NetBSD - * Foundation, Inc. and its contributors. - * 4. Neither the name of The NetBSD Foundation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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 -#include -#include -#include -#include -#include -#include -#include -#include -#if defined(__DragonFly__) -#include -#endif - -#define USBDEV "/dev/usb" - -int verbose = 0; -int showdevs = 0; - -void usage(void); -void usbdev(int f, int a, int rec); -void usbdump(int f); -void dumpone(char *name, int f, int addr); - -void -usage(void) -{ - fprintf(stderr, "usage: %s [-a addr] [-d] [-f dev] [-v]\n", - getprogname()); - exit(1); -} - -char done[USB_MAX_DEVICES]; -int indent; - -void -usbdev(int f, int a, int rec) -{ - struct usb_device_info di; - int e, p, i; - - di.udi_addr = a; - e = ioctl(f, USB_DEVICEINFO, &di); - if (e) { - if (errno != ENXIO) - printf("addr %d: I/O error\n", a); - return; - } - printf("addr %d: ", a); - done[a] = 1; - if (verbose) { - switch (di.udi_speed) { - case USB_SPEED_LOW: printf("low speed, "); break; - case USB_SPEED_FULL: printf("full speed, "); break; - case USB_SPEED_HIGH: printf("high speed, "); break; - default: break; - } - if (di.udi_power) - printf("power %d mA, ", di.udi_power); - else - printf("self powered, "); - if (di.udi_config) - printf("config %d, ", di.udi_config); - else - printf("unconfigured, "); - } - if (verbose) { - printf("%s(0x%04x), %s(0x%04x), rev %s", - di.udi_product, di.udi_productNo, - di.udi_vendor, di.udi_vendorNo, di.udi_release); - } else - printf("%s, %s", di.udi_product, di.udi_vendor); - printf("\n"); - if (showdevs) { - for (i = 0; i < USB_MAX_DEVNAMES; i++) - if (di.udi_devnames[i][0]) - printf("%*s %s\n", indent, "", - di.udi_devnames[i]); - } - if (!rec) - return; - for (p = 0; p < di.udi_nports; p++) { - int s = di.udi_ports[p]; - if (s >= USB_MAX_DEVICES) { - if (verbose) { - printf("%*sport %d %s\n", indent+1, "", p+1, - s == USB_PORT_ENABLED ? "enabled" : - s == USB_PORT_SUSPENDED ? "suspended" : - s == USB_PORT_POWERED ? "powered" : - s == USB_PORT_DISABLED ? "disabled" : - "???"); - - } - continue; - } - indent++; - printf("%*s", indent, ""); - if (verbose) - printf("port %d ", p+1); - if (s == 0) - printf("addr 0 should never happen!\n"); - else - usbdev(f, s, 1); - indent--; - } -} - -void -usbdump(int f) -{ - int a; - - for (a = 1; a < USB_MAX_DEVICES; a++) { - if (!done[a]) - usbdev(f, a, 1); - } -} - -void -dumpone(char *name, int f, int addr) -{ - if (verbose) - printf("Controller %s:\n", name); - indent = 0; - memset(done, 0, sizeof done); - if (addr) - usbdev(f, addr, 0); - else - usbdump(f); -} - -int -main(int argc, char **argv) -{ - int ch, i, f; - char buf[50]; - char *dev = NULL; - int addr = 0; - int ncont; - - while ((ch = getopt(argc, argv, "a:df:v")) != -1) { - switch(ch) { - case 'a': - addr = atoi(optarg); - break; - case 'd': - showdevs++; - break; - case 'f': - dev = optarg; - break; - case 'v': - verbose = 1; - break; - default: - usage(); - } - } - argc -= optind; - argv += optind; - - if (dev == NULL) { - for (ncont = 0, i = 0; i < 10; i++) { - sprintf(buf, "%s%d", USBDEV, i); - f = open(buf, O_RDONLY); - if (f >= 0) { - dumpone(buf, f, addr); - close(f); - } else { - if (errno == ENOENT || errno == ENXIO) - continue; - warn("%s", buf); - } - ncont++; - } - if (verbose && ncont == 0) - printf("%s: no USB controllers found\n", - getprogname()); - } else { - f = open(dev, O_RDONLY); - if (f >= 0) - dumpone(dev, f, addr); - else - err(1, "%s", dev); - } - exit(0); -} -- 2.41.0